diff options
768 files changed, 31519 insertions, 81798 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 2f06d40fe07d..2e33dc6b2346 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -189,6 +189,14 @@ Description: A computed peak value based on the sum squared magnitude of the underlying value in the specified directions. +What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_raw +What: /sys/bus/iio/devices/iio:deviceX/in_pressure_raw +KernelVersion: 3.8 +Contact: linux-iio@vger.kernel.org +Description: + Raw pressure measurement from channel Y. Units after + application of scale and offset are kilopascal. + What: /sys/bus/iio/devices/iio:deviceX/in_accel_offset What: /sys/bus/iio/devices/iio:deviceX/in_accel_x_offset What: /sys/bus/iio/devices/iio:deviceX/in_accel_y_offset @@ -197,6 +205,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_offset What: /sys/bus/iio/devices/iio:deviceX/in_voltage_offset What: /sys/bus/iio/devices/iio:deviceX/in_tempY_offset What: /sys/bus/iio/devices/iio:deviceX/in_temp_offset +What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_offset +What: /sys/bus/iio/devices/iio:deviceX/in_pressure_offset KernelVersion: 2.6.35 Contact: linux-iio@vger.kernel.org Description: @@ -226,6 +236,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_magn_scale What: /sys/bus/iio/devices/iio:deviceX/in_magn_x_scale What: /sys/bus/iio/devices/iio:deviceX/in_magn_y_scale What: /sys/bus/iio/devices/iio:deviceX/in_magn_z_scale +What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_scale +What: /sys/bus/iio/devices/iio:deviceX/in_pressure_scale KernelVersion: 2.6.35 Contact: linux-iio@vger.kernel.org Description: @@ -245,6 +257,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibbias What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibbias What: /sys/bus/iio/devices/iio:deviceX/in_illuminance0_calibbias What: /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibbias +What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_calibbias +What: /sys/bus/iio/devices/iio:deviceX/in_pressure_calibbias KernelVersion: 2.6.35 Contact: linux-iio@vger.kernel.org Description: @@ -262,6 +276,8 @@ What /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibscale What /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibscale what /sys/bus/iio/devices/iio:deviceX/in_illuminance0_calibscale what /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibscale +What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_calibscale +What: /sys/bus/iio/devices/iio:deviceX/in_pressure_calibscale KernelVersion: 2.6.35 Contact: linux-iio@vger.kernel.org Description: @@ -275,6 +291,8 @@ What: /sys/.../iio:deviceX/in_voltage-voltage_scale_available What: /sys/.../iio:deviceX/out_voltageX_scale_available What: /sys/.../iio:deviceX/out_altvoltageX_scale_available What: /sys/.../iio:deviceX/in_capacitance_scale_available +What: /sys/.../iio:deviceX/in_pressure_scale_available +What: /sys/.../iio:deviceX/in_pressureY_scale_available KernelVersion: 2.6.35 Contact: linux-iio@vger.kernel.org Description: @@ -694,6 +712,8 @@ What: /sys/.../buffer/scan_elements/in_voltageY_en What: /sys/.../buffer/scan_elements/in_voltageY-voltageZ_en What: /sys/.../buffer/scan_elements/in_incli_x_en What: /sys/.../buffer/scan_elements/in_incli_y_en +What: /sys/.../buffer/scan_elements/in_pressureY_en +What: /sys/.../buffer/scan_elements/in_pressure_en KernelVersion: 2.6.37 Contact: linux-iio@vger.kernel.org Description: @@ -707,6 +727,8 @@ What: /sys/.../buffer/scan_elements/in_voltageY_type What: /sys/.../buffer/scan_elements/in_voltage_type What: /sys/.../buffer/scan_elements/in_voltageY_supply_type What: /sys/.../buffer/scan_elements/in_timestamp_type +What: /sys/.../buffer/scan_elements/in_pressureY_type +What: /sys/.../buffer/scan_elements/in_pressure_type KernelVersion: 2.6.37 Contact: linux-iio@vger.kernel.org Description: @@ -751,6 +773,8 @@ What: /sys/.../buffer/scan_elements/in_magn_z_index What: /sys/.../buffer/scan_elements/in_incli_x_index What: /sys/.../buffer/scan_elements/in_incli_y_index What: /sys/.../buffer/scan_elements/in_timestamp_index +What: /sys/.../buffer/scan_elements/in_pressureY_index +What: /sys/.../buffer/scan_elements/in_pressure_index KernelVersion: 2.6.37 Contact: linux-iio@vger.kernel.org Description: diff --git a/Documentation/telephony/00-INDEX b/Documentation/telephony/00-INDEX deleted file mode 100644 index 4ffe0ed5b6fb..000000000000 --- a/Documentation/telephony/00-INDEX +++ /dev/null @@ -1,4 +0,0 @@ -00-INDEX - - this file. -ixj.txt - - document describing the Quicknet drivers. diff --git a/Documentation/telephony/ixj.txt b/Documentation/telephony/ixj.txt deleted file mode 100644 index db94fb6c5678..000000000000 --- a/Documentation/telephony/ixj.txt +++ /dev/null @@ -1,394 +0,0 @@ -Linux Quicknet-Drivers-Howto -Quicknet Technologies, Inc. (www.quicknet.net) -Version 0.3.4 December 18, 1999 - -1.0 Introduction - -This document describes the first GPL release version of the Linux -driver for the Quicknet Internet PhoneJACK and Internet LineJACK -cards. More information about these cards is available at -www.quicknet.net. The driver version discussed in this document is -0.3.4. - -These cards offer nice telco style interfaces to use your standard -telephone/key system/PBX as the user interface for VoIP applications. -The Internet LineJACK also offers PSTN connectivity for a single line -Internet to PSTN gateway. Of course, you can add more than one card -to a system to obtain multi-line functionality. At this time, the -driver supports the POTS port on both the Internet PhoneJACK and the -Internet LineJACK, but the PSTN port on the latter card is not yet -supported. - -This document, and the drivers for the cards, are intended for a -limited audience that includes technically capable programmers who -would like to experiment with Quicknet cards. The drivers are -considered in ALPHA status and are not yet considered stable enough -for general, widespread use in an unlimited audience. - -That's worth saying again: - -THE LINUX DRIVERS FOR QUICKNET CARDS ARE PRESENTLY IN A ALPHA STATE -AND SHOULD NOT BE CONSIDERED AS READY FOR NORMAL WIDESPREAD USE. - -They are released early in the spirit of Internet development and to -make this technology available to innovators who would benefit from -early exposure. - -When we promote the device driver to "beta" level it will be -considered ready for non-programmer, non-technical users. Until then, -please be aware that these drivers may not be stable and may affect -the performance of your system. - - -1.1 Latest Additions/Improvements - -The 0.3.4 version of the driver is the first GPL release. Several -features had to be removed from the prior binary only module, mostly -for reasons of Intellectual Property rights. We can't release -information that is not ours - so certain aspects of the driver had to -be removed to protect the rights of others. - -Specifically, very old Internet PhoneJACK cards have non-standard -G.723.1 codecs (due to the early nature of the DSPs in those days). -The auto-conversion code to bring those cards into compliance with -today's standards is available as a binary only module to those people -needing it. If you bought your card after 1997 or so, you are OK - -it's only the very old cards that are affected. - -Also, the code to download G.728/G.729/G.729a codecs to the DSP is -available as a binary only module as well. This IP is not ours to -release. - -Hooks are built into the GPL driver to allow it to work with other -companion modules that are completely separate from this module. - -1.2 Copyright, Trademarks, Disclaimer, & Credits - -Copyright - -Copyright (c) 1999 Quicknet Technologies, Inc. Permission is granted -to freely copy and distribute this document provided you preserve it -in its original form. For corrections and minor changes contact the -maintainer at linux@quicknet.net. - -Trademarks - -Internet PhoneJACK and Internet LineJACK are registered trademarks of -Quicknet Technologies, Inc. - -Disclaimer - -Much of the info in this HOWTO is early information released by -Quicknet Technologies, Inc. for the express purpose of allowing early -testing and use of the Linux drivers developed for their products. -While every attempt has been made to be thorough, complete and -accurate, the information contained here may be unreliable and there -are likely a number of errors in this document. Please let the -maintainer know about them. Since this is free documentation, it -should be obvious that neither I nor previous authors can be held -legally responsible for any errors. - -Credits - -This HOWTO was written by: - - Greg Herlein <gherlein@quicknet.net> - Ed Okerson <eokerson@quicknet.net> - -1.3 Future Plans: You Can Help - -Please let the maintainer know of any errors in facts, opinions, -logic, spelling, grammar, clarity, links, etc. But first, if the date -is over a month old, check to see that you have the latest -version. Please send any info that you think belongs in this document. - -You can also contribute code and/or bug-fixes for the sample -applications. - - -1.4 Where to get things - -Info on latest versions of the driver are here: - -http://web.archive.org/web/*/http://www.quicknet.net/develop.htm - -1.5 Mailing List - -Quicknet operates a mailing list to provide a public forum on using -these drivers. - -To subscribe to the linux-sdk mailing list, send an email to: - - majordomo@linux.quicknet.net - -In the body of the email, type: - - subscribe linux-sdk <your-email-address> - -Please delete any signature block that you would normally add to the -bottom of your email - it tends to confuse majordomo. - -To send mail to the list, address your mail to - - linux-sdk@linux.quicknet.net - -Your message will go out to everyone on the list. - -To unsubscribe to the linux-sdk mailing list, send an email to: - - majordomo@linux.quicknet.net - -In the body of the email, type: - - unsubscribe linux-sdk <your-email-address> - - - -2.0 Requirements - -2.1 Quicknet Card(s) - -You will need at least one Internet PhoneJACK or Internet LineJACK -cards. These are ISA or PCI bus devices that use Plug-n-Play for -configuration, and use no IRQs. The driver will support up to 16 -cards in any one system, of any mix between the two types. - -Note that you will need two cards to do any useful testing alone, since -you will need a card on both ends of the connection. Of course, if -you are doing collaborative work, perhaps your friends or coworkers -have cards too. If not, we'll gladly sell them some! - - -2.2 ISAPNP - -Since the Quicknet cards are Plug-n-Play devices, you will need the -isapnp tools package to configure the cards, or you can use the isapnp -module to autoconfigure them. The former package probably came with -your Linux distribution. Documentation on this package is available -online at: - -http://mailer.wiwi.uni-marburg.de/linux/LDP/HOWTO/Plug-and-Play-HOWTO.html - -The isapnp autoconfiguration is available on the Quicknet website at: - - http://www.quicknet.net/develop.htm - -though it may be in the kernel by the time you read this. - - -3.0 Card Configuration - -If you did not get your drivers as part of the linux kernel, do the -following to install them: - - a. untar the distribution file. We use the following command: - tar -xvzf ixj-0.x.x.tgz - -This creates a subdirectory holding all the necessary files. Go to that -subdirectory. - - b. run the "ixj_dev_create" script to remove any stray device -files left in the /dev directory, and to create the new officially -designated device files. Note that the old devices were called -/dev/ixj, and the new method uses /dev/phone. - - c. type "make;make install" - this will compile and install the -module. - - d. type "depmod -av" to rebuild all your kernel version dependencies. - - e. if you are using the isapnp module to configure the cards - automatically, then skip to step f. Otherwise, ensure that you - have run the isapnp configuration utility to properly configure - the cards. - - e1. The Internet PhoneJACK has one configuration register that - requires 16 IO ports. The Internet LineJACK card has two - configuration registers and isapnp reports that IO 0 - requires 16 IO ports and IO 1 requires 8. The Quicknet - driver assumes that these registers are configured to be - contiguous, i.e. if IO 0 is set to 0x340 then IO 1 should - be set to 0x350. - - Make sure that none of the cards overlap if you have - multiple cards in the system. - - If you are new to the isapnp tools, you can jumpstart - yourself by doing the following: - - e2. go to the /etc directory and run pnpdump to get a blank - isapnp.conf file. - - pnpdump > /etc/isapnp.conf - - e3. edit the /etc/isapnp.conf file to set the IO warnings and - the register IO addresses. The IO warnings means that you - should find the line in the file that looks like this: - - (CONFLICT (IO FATAL)(IRQ FATAL)(DMA FATAL)(MEM FATAL)) # or WARNING - - and you should edit the line to look like this: - - (CONFLICT (IO WARNING)(IRQ FATAL)(DMA FATAL)(MEM FATAL)) # - or WARNING - - The next step is to set the IO port addresses. The issue - here is that isapnp does not identify all of the ports out - there. Specifically any device that does not have a driver - or module loaded by Linux will not be registered. This - includes older sound cards and network cards. We have - found that the IO port 0x300 is often used even though - isapnp claims that no-one is using those ports. We - recommend that for a single card installation that port - 0x340 (and 0x350) be used. The IO port line should change - from this: - - (IO 0 (SIZE 16) (BASE 0x0300) (CHECK)) - - to this: - - (IO 0 (SIZE 16) (BASE 0x0340) ) - - e4. if you have multiple Quicknet cards, make sure that you do - not have any overlaps. Be especially careful if you are - mixing Internet PhoneJACK and Internet LineJACK cards in - the same system. In these cases we recommend moving the - IO port addresses to the 0x400 block. Please note that on - a few machines the 0x400 series are used. Feel free to - experiment with other addresses. Our cards have been - proven to work using IO addresses of up to 0xFF0. - - e5. the last step is to uncomment the activation line so the - drivers will be associated with the port. This means the - line (immediately below) the IO line should go from this: - - # (ACT Y) - - to this: - - (ACT Y) - - Once you have finished editing the isapnp.conf file you - must submit it into the pnp driverconfigure the cards. - This is done using the following command: - - isapnp isapnp.conf - - If this works you should see a line that identifies the - Quicknet device, the IO port(s) chosen, and a message - "Enabled OK". - - f. if you are loading the module by hand, use insmod. An example -of this would look like this: - - insmod phonedev - insmod ixj dspio=0x320,0x310 xio=0,0x330 - -Then verify the module loaded by running lsmod. If you are not using a -module that matches your kernel version, you may need to "force" the -load using the -f option in the insmod command. - - insmod phonedev - insmod -f ixj dspio=0x320,0x310 xio=0,0x330 - - -If you are using isapnp to autoconfigure your card, then you do NOT -need any of the above, though you need to use depmod to load the -driver, like this: - - depmod ixj - -which will result in the needed drivers getting loaded automatically. - - g. if you are planning on having the kernel automatically request -the module for you, then you need to edit /etc/conf.modules and add the -following lines: - - options ixj dspio=0x340 xio=0x330 ixjdebug=0 - -If you do this, then when you execute an application that uses the -module the kernel will request that it is loaded. - - h. if you want non-root users to be able to read and write to the -ixj devices (this is a good idea!) you should do the following: - - - decide upon a group name to use and create that group if - needed. Add the user names to that group that you wish to - have access to the device. For example, we typically will - create a group named "ixj" in /etc/group and add all users - to that group that we want to run software that can use the - ixjX devices. - - - change the permissions on the device files, like this: - - chgrp ixj /dev/ixj* - chmod 660 /dev/ixj* - -Once this is done, then non-root users should be able to use the -devices. If you have enabled autoloading of modules, then the user -should be able to open the device and have the module loaded -automatically for them. - - -4.0 Driver Installation problems. - -We have tested these drivers on the 2.2.9, 2.2.10, 2.2.12, and 2.2.13 kernels -and in all cases have eventually been able to get the drivers to load and -run. We have found four types of problems that prevent this from happening. -The problems and solutions are: - - a. A step was missed in the installation. Go back and use section 3 -as a checklist. Many people miss running the ixj_dev_create script and thus -never load the device names into the filesystem. - - b. The kernel is inconsistently linked. We have found this problem in -the Out Of the Box installation of several distributions. The symptoms -are that neither driver will load, and that the unknown symbols include "jiffy" -and "kmalloc". The solution is to recompile both the kernel and the -modules. The command string for the final compile looks like this: - - In the kernel directory: - 1. cp .config /tmp - 2. make mrproper - 3. cp /tmp/.config . - 4. make clean;make bzImage;make modules;make modules_install - -This rebuilds both the kernel and all the modules and makes sure they all -have the same linkages. This generally solves the problem once the new -kernel is installed and the system rebooted. - - c. The kernel has been patched, then unpatched. This happens when -someone decides to use an earlier kernel after they load a later kernel. -The symptoms are proceeding through all three above steps and still not -being able to load the driver. What has happened is that the generated -header files are out of sync with the kernel itself. The solution is -to recompile (again) using "make mrproper". This will remove and then -regenerate all the necessary header files. Once this is done, then you -need to install and reboot the kernel. We have not seen any problem -loading one of our drivers after this treatment. - -5.0 Known Limitations - -We cannot currently play "dial-tone" and listen for DTMF digits at the -same time using the ISA PhoneJACK. This is a bug in the 8020 DSP chip -used on that product. All other Quicknet products function normally -in this regard. We have a work-around, but it's not done yet. Until -then, if you want dial-tone, you can always play a recorded dial-tone -sound into the audio until you have gathered the DTMF digits. - - - - - - - - - - - - - - - - - diff --git a/MAINTAINERS b/MAINTAINERS index e360784991ff..1ea0eba7ee22 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3788,6 +3788,15 @@ M: Stanislaw Gruszka <stf_xl@wp.pl> S: Maintained F: drivers/usb/atm/ueagle-atm.c +INDUSTRY PACK SUBSYSTEM (IPACK) +M: Samuel Iglesias Gonsalvez <siglesias@igalia.com> +M: Jens Taprogge <jens.taprogge@taprogge.org> +M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +L: industrypack-devel@lists.sourceforge.net +W: http://industrypack.sourceforge.net +S: Maintained +F: drivers/ipack/ + INTEGRITY MEASUREMENT ARCHITECTURE (IMA) M: Mimi Zohar <zohar@us.ibm.com> S: Supported diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index b700685762b5..56277a047136 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -45,7 +45,6 @@ #include <asm/mach/flash.h> #include <asm/mach/map.h> -#include "common.h" #include <video/omapdss.h> #include <video/omap-panel-generic-dpi.h> #include <video/omap-panel-tfp410.h> diff --git a/arch/arm/mach-omap2/drm.c b/arch/arm/mach-omap2/drm.c index 72e0f01b715c..49a7ffb716a5 100644 --- a/arch/arm/mach-omap2/drm.c +++ b/arch/arm/mach-omap2/drm.c @@ -23,15 +23,20 @@ #include <linux/init.h> #include <linux/platform_device.h> #include <linux/dma-mapping.h> +#include <linux/platform_data/omap_drm.h> #include <plat/omap_device.h> #include <plat/omap_hwmod.h> +#include <plat/cpu.h> #if defined(CONFIG_DRM_OMAP) || (CONFIG_DRM_OMAP_MODULE) +static struct omap_drm_platform_data platform_data; + static struct platform_device omap_drm_device = { .dev = { .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &platform_data, }, .name = "omapdrm", .id = 0, @@ -52,6 +57,8 @@ static int __init omap_init_drm(void) oh->name); } + platform_data.omaprev = GET_OMAP_REVISION(); + return platform_device_register(&omap_drm_device); } diff --git a/drivers/Kconfig b/drivers/Kconfig index dbdefa3fe775..f5fb0722a63a 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -156,4 +156,6 @@ source "drivers/pwm/Kconfig" source "drivers/irqchip/Kconfig" +source "drivers/ipack/Kconfig" + endmenu diff --git a/drivers/Makefile b/drivers/Makefile index a16a8d001ae0..7863b9fee50b 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -145,3 +145,4 @@ obj-$(CONFIG_EXTCON) += extcon/ obj-$(CONFIG_MEMORY) += memory/ obj-$(CONFIG_IIO) += iio/ obj-$(CONFIG_VME_BUS) += vme/ +obj-$(CONFIG_IPACK_BUS) += ipack/ diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig index fc937aca71fb..b2f963be3993 100644 --- a/drivers/iio/Kconfig +++ b/drivers/iio/Kconfig @@ -20,6 +20,12 @@ config IIO_BUFFER if IIO_BUFFER +config IIO_BUFFER_CB +boolean "IIO callback buffer used for push in-kernel interfaces" + help + Should be selected by any drivers that do-inkernel push + usage. That is, those where the data is pushed to the consumer. + config IIO_KFIFO_BUF select IIO_TRIGGER tristate "Industrial I/O buffering based on kfifo" @@ -57,11 +63,12 @@ config IIO_CONSUMERS_PER_TRIGGER source "drivers/iio/accel/Kconfig" source "drivers/iio/adc/Kconfig" source "drivers/iio/amplifiers/Kconfig" -source "drivers/iio/light/Kconfig" -source "drivers/iio/frequency/Kconfig" -source "drivers/iio/dac/Kconfig" source "drivers/iio/common/Kconfig" +source "drivers/iio/dac/Kconfig" +source "drivers/iio/frequency/Kconfig" source "drivers/iio/gyro/Kconfig" +source "drivers/iio/imu/Kconfig" +source "drivers/iio/light/Kconfig" source "drivers/iio/magnetometer/Kconfig" endif # IIO diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile index 761f2b65ac52..a0e8cdd67e4d 100644 --- a/drivers/iio/Makefile +++ b/drivers/iio/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_IIO) += industrialio.o industrialio-y := industrialio-core.o industrialio-event.o inkern.o industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o +industrialio-$(CONFIG_IIO_BUFFER_CB) += buffer_cb.o obj-$(CONFIG_IIO_TRIGGERED_BUFFER) += industrialio-triggered-buffer.o obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o @@ -13,9 +14,10 @@ obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o obj-y += accel/ obj-y += adc/ obj-y += amplifiers/ -obj-y += light/ -obj-y += frequency/ -obj-y += dac/ obj-y += common/ +obj-y += dac/ obj-y += gyro/ +obj-y += frequency/ +obj-y += imu/ +obj-y += light/ obj-y += magnetometer/ diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index b2510c4d9a5a..fe4bcd7c5b12 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -8,7 +8,7 @@ config HID_SENSOR_ACCEL_3D select IIO_BUFFER select IIO_TRIGGERED_BUFFER select HID_SENSOR_IIO_COMMON - tristate "HID Acelerometers 3D" + tristate "HID Accelerometers 3D" help Say yes here to build support for the HID SENSOR accelerometers 3D. diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c index 314a4057879e..e67bb912bd19 100644 --- a/drivers/iio/accel/hid-sensor-accel-3d.c +++ b/drivers/iio/accel/hid-sensor-accel-3d.c @@ -197,21 +197,8 @@ static const struct iio_info accel_3d_info = { /* Function to push data to buffer */ static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len) { - struct iio_buffer *buffer = indio_dev->buffer; - int datum_sz; - dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n"); - if (!buffer) { - dev_err(&indio_dev->dev, "Buffer == NULL\n"); - return; - } - datum_sz = buffer->access->get_bytes_per_datum(buffer); - if (len > datum_sz) { - dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len, - datum_sz); - return; - } - iio_push_to_buffer(buffer, (u8 *)data); + iio_push_to_buffers(indio_dev, (u8 *)data); } /* Callback handler to send event after all samples are received and captured */ @@ -319,10 +306,10 @@ static int __devinit hid_accel_3d_probe(struct platform_device *pdev) goto error_free_dev; } - channels = kmemdup(accel_3d_channels, - sizeof(accel_3d_channels), - GFP_KERNEL); + channels = kmemdup(accel_3d_channels, sizeof(accel_3d_channels), + GFP_KERNEL); if (!channels) { + ret = -ENOMEM; dev_err(&pdev->dev, "failed to duplicate channels\n"); goto error_free_dev; } diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 492758120338..961b8d0a4bac 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -18,6 +18,18 @@ config AD7266 Say yes here to build support for Analog Devices AD7265 and AD7266 ADCs. +config AD7298 + tristate "Analog Devices AD7298 ADC driver" + depends on SPI + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say yes here to build support for Analog Devices AD7298 + 8 Channel ADC with temperature sensor. + + To compile this driver as a module, choose M here: the + module will be called ad7298. + config AD7791 tristate "Analog Devices AD7791 ADC driver" depends on SPI @@ -30,6 +42,18 @@ config AD7791 To compile this driver as a module, choose M here: the module will be called ad7791. +config AD7793 + tristate "Analog Devices AD7793 and similar ADCs driver" + depends on SPI + select AD_SIGMA_DELTA + help + Say yes here to build support for Analog Devices AD7785, AD7792, AD7793, + AD7794 and AD7795 SPI analog to digital converters (ADC). + If unsure, say N (but it's safe to say "Y"). + + To compile this driver as a module, choose M here: the + module will be called AD7793. + config AD7476 tristate "Analog Devices AD7476 and similar 1-channel ADCs driver" depends on SPI @@ -45,6 +69,19 @@ config AD7476 To compile this driver as a module, choose M here: the module will be called ad7476. +config AD7887 + tristate "Analog Devices AD7887 ADC driver" + depends on SPI + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say yes here to build support for Analog Devices + AD7887 SPI analog to digital converter (ADC). + If unsure, say N (but it's safe to say "Y"). + + To compile this driver as a module, choose M here: the + module will be called ad7887. + config AT91_ADC tristate "Atmel AT91 ADC" depends on ARCH_AT91 @@ -60,4 +97,32 @@ config LP8788_ADC help Say yes here to build support for TI LP8788 ADC. +config MAX1363 + tristate "Maxim max1363 ADC driver" + depends on I2C + select IIO_TRIGGER + select MAX1363_RING_BUFFER + select IIO_BUFFER + select IIO_KFIFO_BUF + help + Say yes here to build support for many Maxim i2c analog to digital + converters (ADC). (max1361, max1362, max1363, max1364, max1036, + max1037, max1038, max1039, max1136, max1136, max1137, max1138, + max1139, max1236, max1237, max11238, max1239, max11600, max11601, + max11602, max11603, max11604, max11605, max11606, max11607, + max11608, max11609, max11610, max11611, max11612, max11613, + max11614, max11615, max11616, max11617, max11644, max11645, + max11646, max11647) Provides direct access via sysfs and buffered + data via the iio dev interface. + +config TI_ADC081C + tristate "Texas Instruments ADC081C021/027" + depends on I2C + help + If you say yes here you get support for Texas Instruments ADC081C021 + and ADC081C027 ADC chips. + + This driver can also be built as a module. If so, the module will be + called ti-adc081c. + endmenu diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 900995d5e179..472fd7cd2417 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -4,7 +4,13 @@ obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o obj-$(CONFIG_AD7266) += ad7266.o +obj-$(CONFIG_AD7298) += ad7298.o obj-$(CONFIG_AD7476) += ad7476.o obj-$(CONFIG_AD7791) += ad7791.o +obj-$(CONFIG_AD7793) += ad7793.o +obj-$(CONFIG_AD7887) += ad7887.o obj-$(CONFIG_AT91_ADC) += at91_adc.o obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o +obj-$(CONFIG_MAX1363) += max1363.o +obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o + diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c index b11f214779a2..a6f4fc5f8201 100644 --- a/drivers/iio/adc/ad7266.c +++ b/drivers/iio/adc/ad7266.c @@ -91,7 +91,6 @@ static irqreturn_t ad7266_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; - struct iio_buffer *buffer = indio_dev->buffer; struct ad7266_state *st = iio_priv(indio_dev); int ret; @@ -99,7 +98,7 @@ static irqreturn_t ad7266_trigger_handler(int irq, void *p) if (ret == 0) { if (indio_dev->scan_timestamp) ((s64 *)st->data)[1] = pf->timestamp; - iio_push_to_buffer(buffer, (u8 *)st->data); + iio_push_to_buffers(indio_dev, (u8 *)st->data); } iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/staging/iio/adc/ad7298_core.c b/drivers/iio/adc/ad7298.c index 4c75114e7d7c..2364807a5d6c 100644 --- a/drivers/staging/iio/adc/ad7298_core.c +++ b/drivers/iio/adc/ad7298.c @@ -15,12 +15,48 @@ #include <linux/err.h> #include <linux/delay.h> #include <linux/module.h> +#include <linux/interrupt.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> #include <linux/iio/buffer.h> - -#include "ad7298.h" +#include <linux/iio/trigger_consumer.h> +#include <linux/iio/triggered_buffer.h> + +#include <linux/platform_data/ad7298.h> + +#define AD7298_WRITE (1 << 15) /* write to the control register */ +#define AD7298_REPEAT (1 << 14) /* repeated conversion enable */ +#define AD7298_CH(x) (1 << (13 - (x))) /* channel select */ +#define AD7298_TSENSE (1 << 5) /* temperature conversion enable */ +#define AD7298_EXTREF (1 << 2) /* external reference enable */ +#define AD7298_TAVG (1 << 1) /* temperature sensor averaging enable */ +#define AD7298_PDD (1 << 0) /* partial power down enable */ + +#define AD7298_MAX_CHAN 8 +#define AD7298_BITS 12 +#define AD7298_STORAGE_BITS 16 +#define AD7298_INTREF_mV 2500 + +#define AD7298_CH_TEMP 9 + +#define RES_MASK(bits) ((1 << (bits)) - 1) + +struct ad7298_state { + struct spi_device *spi; + struct regulator *reg; + unsigned ext_ref; + struct spi_transfer ring_xfer[10]; + struct spi_transfer scan_single_xfer[3]; + struct spi_message ring_msg; + struct spi_message scan_single_msg; + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + __be16 rx_buf[12] ____cacheline_aligned; + __be16 tx_buf[2]; +}; #define AD7298_V_CHAN(index) \ { \ @@ -35,6 +71,7 @@ .sign = 'u', \ .realbits = 12, \ .storagebits = 16, \ + .endianness = IIO_BE, \ }, \ } @@ -44,7 +81,8 @@ static const struct iio_chan_spec ad7298_channels[] = { .indexed = 1, .channel = 0, .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, + IIO_CHAN_INFO_SCALE_SEPARATE_BIT | + IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, .address = AD7298_CH_TEMP, .scan_index = -1, .scan_type = { @@ -64,6 +102,84 @@ static const struct iio_chan_spec ad7298_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(8), }; +/** + * ad7298_update_scan_mode() setup the spi transfer buffer for the new scan mask + **/ +static int ad7298_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *active_scan_mask) +{ + struct ad7298_state *st = iio_priv(indio_dev); + int i, m; + unsigned short command; + int scan_count; + + /* Now compute overall size */ + scan_count = bitmap_weight(active_scan_mask, indio_dev->masklength); + + command = AD7298_WRITE | st->ext_ref; + + for (i = 0, m = AD7298_CH(0); i < AD7298_MAX_CHAN; i++, m >>= 1) + if (test_bit(i, active_scan_mask)) + command |= m; + + st->tx_buf[0] = cpu_to_be16(command); + + /* build spi ring message */ + st->ring_xfer[0].tx_buf = &st->tx_buf[0]; + st->ring_xfer[0].len = 2; + st->ring_xfer[0].cs_change = 1; + st->ring_xfer[1].tx_buf = &st->tx_buf[1]; + st->ring_xfer[1].len = 2; + st->ring_xfer[1].cs_change = 1; + + spi_message_init(&st->ring_msg); + spi_message_add_tail(&st->ring_xfer[0], &st->ring_msg); + spi_message_add_tail(&st->ring_xfer[1], &st->ring_msg); + + for (i = 0; i < scan_count; i++) { + st->ring_xfer[i + 2].rx_buf = &st->rx_buf[i]; + st->ring_xfer[i + 2].len = 2; + st->ring_xfer[i + 2].cs_change = 1; + spi_message_add_tail(&st->ring_xfer[i + 2], &st->ring_msg); + } + /* make sure last transfer cs_change is not set */ + st->ring_xfer[i + 1].cs_change = 0; + + return 0; +} + +/** + * ad7298_trigger_handler() bh of trigger launched polling to ring buffer + * + * Currently there is no option in this driver to disable the saving of + * timestamps within the ring. + **/ +static irqreturn_t ad7298_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct ad7298_state *st = iio_priv(indio_dev); + s64 time_ns = 0; + int b_sent; + + b_sent = spi_sync(st->spi, &st->ring_msg); + if (b_sent) + goto done; + + if (indio_dev->scan_timestamp) { + time_ns = iio_get_time_ns(); + memcpy((u8 *)st->rx_buf + indio_dev->scan_bytes - sizeof(s64), + &time_ns, sizeof(time_ns)); + } + + iio_push_to_buffers(indio_dev, (u8 *)st->rx_buf); + +done: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + static int ad7298_scan_direct(struct ad7298_state *st, unsigned ch) { int ret; @@ -79,7 +195,7 @@ static int ad7298_scan_direct(struct ad7298_state *st, unsigned ch) static int ad7298_scan_temp(struct ad7298_state *st, int *val) { - int tmp, ret; + int ret; __be16 buf; buf = cpu_to_be16(AD7298_WRITE | AD7298_TSENSE | @@ -101,24 +217,24 @@ static int ad7298_scan_temp(struct ad7298_state *st, int *val) if (ret) return ret; - tmp = be16_to_cpu(buf) & RES_MASK(AD7298_BITS); + *val = sign_extend32(be16_to_cpu(buf), 11); - /* - * One LSB of the ADC corresponds to 0.25 deg C. - * The temperature reading is in 12-bit twos complement format - */ + return 0; +} - if (tmp & (1 << (AD7298_BITS - 1))) { - tmp = (4096 - tmp) * 250; - tmp -= (2 * tmp); +static int ad7298_get_ref_voltage(struct ad7298_state *st) +{ + int vref; + + if (st->ext_ref) { + vref = regulator_get_voltage(st->reg); + if (vref < 0) + return vref; + return vref / 1000; } else { - tmp *= 250; /* temperature in milli degrees Celsius */ + return AD7298_INTREF_mV; } - - *val = tmp; - - return 0; } static int ad7298_read_raw(struct iio_dev *indio_dev, @@ -129,7 +245,6 @@ static int ad7298_read_raw(struct iio_dev *indio_dev, { int ret; struct ad7298_state *st = iio_priv(indio_dev); - unsigned int scale_uv; switch (m) { case IIO_CHAN_INFO_RAW: @@ -154,17 +269,19 @@ static int ad7298_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_VOLTAGE: - scale_uv = (st->int_vref_mv * 1000) >> AD7298_BITS; - *val = scale_uv / 1000; - *val2 = (scale_uv % 1000) * 1000; - return IIO_VAL_INT_PLUS_MICRO; + *val = ad7298_get_ref_voltage(st); + *val2 = chan->scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; case IIO_TEMP: - *val = 1; - *val2 = 0; - return IIO_VAL_INT_PLUS_MICRO; + *val = ad7298_get_ref_voltage(st); + *val2 = 10; + return IIO_VAL_FRACTIONAL; default: return -EINVAL; } + case IIO_CHAN_INFO_OFFSET: + *val = 1093 - 2732500 / ad7298_get_ref_voltage(st); + return IIO_VAL_INT; } return -EINVAL; } @@ -179,16 +296,23 @@ static int __devinit ad7298_probe(struct spi_device *spi) { struct ad7298_platform_data *pdata = spi->dev.platform_data; struct ad7298_state *st; - int ret; struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st)); + int ret; if (indio_dev == NULL) return -ENOMEM; st = iio_priv(indio_dev); - st->reg = regulator_get(&spi->dev, "vcc"); - if (!IS_ERR(st->reg)) { + if (pdata && pdata->ext_ref) + st->ext_ref = AD7298_EXTREF; + + if (st->ext_ref) { + st->reg = regulator_get(&spi->dev, "vref"); + if (IS_ERR(st->reg)) { + ret = PTR_ERR(st->reg); + goto error_free; + } ret = regulator_enable(st->reg); if (ret) goto error_put_reg; @@ -221,14 +345,8 @@ static int __devinit ad7298_probe(struct spi_device *spi) spi_message_add_tail(&st->scan_single_xfer[1], &st->scan_single_msg); spi_message_add_tail(&st->scan_single_xfer[2], &st->scan_single_msg); - if (pdata && pdata->vref_mv) { - st->int_vref_mv = pdata->vref_mv; - st->ext_ref = AD7298_EXTREF; - } else { - st->int_vref_mv = AD7298_INTREF_mV; - } - - ret = ad7298_register_ring_funcs_and_init(indio_dev); + ret = iio_triggered_buffer_setup(indio_dev, NULL, + &ad7298_trigger_handler, NULL); if (ret) goto error_disable_reg; @@ -239,13 +357,14 @@ static int __devinit ad7298_probe(struct spi_device *spi) return 0; error_cleanup_ring: - ad7298_ring_cleanup(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); error_disable_reg: - if (!IS_ERR(st->reg)) + if (st->ext_ref) regulator_disable(st->reg); error_put_reg: - if (!IS_ERR(st->reg)) + if (st->ext_ref) regulator_put(st->reg); +error_free: iio_device_free(indio_dev); return ret; @@ -257,8 +376,8 @@ static int __devexit ad7298_remove(struct spi_device *spi) struct ad7298_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - ad7298_ring_cleanup(indio_dev); - if (!IS_ERR(st->reg)) { + iio_triggered_buffer_cleanup(indio_dev); + if (st->ext_ref) { regulator_disable(st->reg); regulator_put(st->reg); } diff --git a/drivers/iio/adc/ad7476.c b/drivers/iio/adc/ad7476.c index 7f2f45a0a48d..330248bfebae 100644 --- a/drivers/iio/adc/ad7476.c +++ b/drivers/iio/adc/ad7476.c @@ -76,7 +76,7 @@ static irqreturn_t ad7476_trigger_handler(int irq, void *p) if (indio_dev->scan_timestamp) ((s64 *)st->data)[1] = time_ns; - iio_push_to_buffer(indio_dev->buffer, st->data); + iio_push_to_buffers(indio_dev, st->data); done: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c index 691a7be6f5cb..334e31ff7a4e 100644 --- a/drivers/staging/iio/adc/ad7793.c +++ b/drivers/iio/adc/ad7793.c @@ -25,8 +25,106 @@ #include <linux/iio/trigger_consumer.h> #include <linux/iio/triggered_buffer.h> #include <linux/iio/adc/ad_sigma_delta.h> - -#include "ad7793.h" +#include <linux/platform_data/ad7793.h> + +/* Registers */ +#define AD7793_REG_COMM 0 /* Communications Register (WO, 8-bit) */ +#define AD7793_REG_STAT 0 /* Status Register (RO, 8-bit) */ +#define AD7793_REG_MODE 1 /* Mode Register (RW, 16-bit */ +#define AD7793_REG_CONF 2 /* Configuration Register (RW, 16-bit) */ +#define AD7793_REG_DATA 3 /* Data Register (RO, 16-/24-bit) */ +#define AD7793_REG_ID 4 /* ID Register (RO, 8-bit) */ +#define AD7793_REG_IO 5 /* IO Register (RO, 8-bit) */ +#define AD7793_REG_OFFSET 6 /* Offset Register (RW, 16-bit + * (AD7792)/24-bit (AD7793)) */ +#define AD7793_REG_FULLSALE 7 /* Full-Scale Register + * (RW, 16-bit (AD7792)/24-bit (AD7793)) */ + +/* Communications Register Bit Designations (AD7793_REG_COMM) */ +#define AD7793_COMM_WEN (1 << 7) /* Write Enable */ +#define AD7793_COMM_WRITE (0 << 6) /* Write Operation */ +#define AD7793_COMM_READ (1 << 6) /* Read Operation */ +#define AD7793_COMM_ADDR(x) (((x) & 0x7) << 3) /* Register Address */ +#define AD7793_COMM_CREAD (1 << 2) /* Continuous Read of Data Register */ + +/* Status Register Bit Designations (AD7793_REG_STAT) */ +#define AD7793_STAT_RDY (1 << 7) /* Ready */ +#define AD7793_STAT_ERR (1 << 6) /* Error (Overrange, Underrange) */ +#define AD7793_STAT_CH3 (1 << 2) /* Channel 3 */ +#define AD7793_STAT_CH2 (1 << 1) /* Channel 2 */ +#define AD7793_STAT_CH1 (1 << 0) /* Channel 1 */ + +/* Mode Register Bit Designations (AD7793_REG_MODE) */ +#define AD7793_MODE_SEL(x) (((x) & 0x7) << 13) /* Operation Mode Select */ +#define AD7793_MODE_SEL_MASK (0x7 << 13) /* Operation Mode Select mask */ +#define AD7793_MODE_CLKSRC(x) (((x) & 0x3) << 6) /* ADC Clock Source Select */ +#define AD7793_MODE_RATE(x) ((x) & 0xF) /* Filter Update Rate Select */ + +#define AD7793_MODE_CONT 0 /* Continuous Conversion Mode */ +#define AD7793_MODE_SINGLE 1 /* Single Conversion Mode */ +#define AD7793_MODE_IDLE 2 /* Idle Mode */ +#define AD7793_MODE_PWRDN 3 /* Power-Down Mode */ +#define AD7793_MODE_CAL_INT_ZERO 4 /* Internal Zero-Scale Calibration */ +#define AD7793_MODE_CAL_INT_FULL 5 /* Internal Full-Scale Calibration */ +#define AD7793_MODE_CAL_SYS_ZERO 6 /* System Zero-Scale Calibration */ +#define AD7793_MODE_CAL_SYS_FULL 7 /* System Full-Scale Calibration */ + +#define AD7793_CLK_INT 0 /* Internal 64 kHz Clock not + * available at the CLK pin */ +#define AD7793_CLK_INT_CO 1 /* Internal 64 kHz Clock available + * at the CLK pin */ +#define AD7793_CLK_EXT 2 /* External 64 kHz Clock */ +#define AD7793_CLK_EXT_DIV2 3 /* External Clock divided by 2 */ + +/* Configuration Register Bit Designations (AD7793_REG_CONF) */ +#define AD7793_CONF_VBIAS(x) (((x) & 0x3) << 14) /* Bias Voltage + * Generator Enable */ +#define AD7793_CONF_BO_EN (1 << 13) /* Burnout Current Enable */ +#define AD7793_CONF_UNIPOLAR (1 << 12) /* Unipolar/Bipolar Enable */ +#define AD7793_CONF_BOOST (1 << 11) /* Boost Enable */ +#define AD7793_CONF_GAIN(x) (((x) & 0x7) << 8) /* Gain Select */ +#define AD7793_CONF_REFSEL(x) ((x) << 6) /* INT/EXT Reference Select */ +#define AD7793_CONF_BUF (1 << 4) /* Buffered Mode Enable */ +#define AD7793_CONF_CHAN(x) ((x) & 0xf) /* Channel select */ +#define AD7793_CONF_CHAN_MASK 0xf /* Channel select mask */ + +#define AD7793_CH_AIN1P_AIN1M 0 /* AIN1(+) - AIN1(-) */ +#define AD7793_CH_AIN2P_AIN2M 1 /* AIN2(+) - AIN2(-) */ +#define AD7793_CH_AIN3P_AIN3M 2 /* AIN3(+) - AIN3(-) */ +#define AD7793_CH_AIN1M_AIN1M 3 /* AIN1(-) - AIN1(-) */ +#define AD7793_CH_TEMP 6 /* Temp Sensor */ +#define AD7793_CH_AVDD_MONITOR 7 /* AVDD Monitor */ + +#define AD7795_CH_AIN4P_AIN4M 4 /* AIN4(+) - AIN4(-) */ +#define AD7795_CH_AIN5P_AIN5M 5 /* AIN5(+) - AIN5(-) */ +#define AD7795_CH_AIN6P_AIN6M 6 /* AIN6(+) - AIN6(-) */ +#define AD7795_CH_AIN1M_AIN1M 8 /* AIN1(-) - AIN1(-) */ + +/* ID Register Bit Designations (AD7793_REG_ID) */ +#define AD7785_ID 0xB +#define AD7792_ID 0xA +#define AD7793_ID 0xB +#define AD7794_ID 0xF +#define AD7795_ID 0xF +#define AD7796_ID 0xA +#define AD7797_ID 0xB +#define AD7798_ID 0x8 +#define AD7799_ID 0x9 +#define AD7793_ID_MASK 0xF + +/* IO (Excitation Current Sources) Register Bit Designations (AD7793_REG_IO) */ +#define AD7793_IO_IEXC1_IOUT1_IEXC2_IOUT2 0 /* IEXC1 connect to IOUT1, + * IEXC2 connect to IOUT2 */ +#define AD7793_IO_IEXC1_IOUT2_IEXC2_IOUT1 1 /* IEXC1 connect to IOUT2, + * IEXC2 connect to IOUT1 */ +#define AD7793_IO_IEXC1_IEXC2_IOUT1 2 /* Both current sources + * IEXC1,2 connect to IOUT1 */ +#define AD7793_IO_IEXC1_IEXC2_IOUT2 3 /* Both current sources + * IEXC1,2 connect to IOUT2 */ + +#define AD7793_IO_IXCEN_10uA (1 << 0) /* Excitation Current 10uA */ +#define AD7793_IO_IXCEN_210uA (2 << 0) /* Excitation Current 210uA */ +#define AD7793_IO_IXCEN_1mA (3 << 0) /* Excitation Current 1mA */ /* NOTE: * The AD7792/AD7793 features a dual use data out ready DOUT/RDY output. @@ -36,9 +134,21 @@ * The DOUT/RDY output must also be wired to an interrupt capable GPIO. */ +#define AD7793_FLAG_HAS_CLKSEL BIT(0) +#define AD7793_FLAG_HAS_REFSEL BIT(1) +#define AD7793_FLAG_HAS_VBIAS BIT(2) +#define AD7793_HAS_EXITATION_CURRENT BIT(3) +#define AD7793_FLAG_HAS_GAIN BIT(4) +#define AD7793_FLAG_HAS_BUFFER BIT(5) + struct ad7793_chip_info { + unsigned int id; const struct iio_chan_spec *channels; unsigned int num_channels; + unsigned int flags; + + const struct iio_info *iio_info; + const u16 *sample_freq_avail; }; struct ad7793_state { @@ -59,6 +169,10 @@ enum ad7793_supported_device_ids { ID_AD7793, ID_AD7794, ID_AD7795, + ID_AD7796, + ID_AD7797, + ID_AD7798, + ID_AD7799, }; static struct ad7793_state *ad_sigma_delta_to_ad7793(struct ad_sigma_delta *sd) @@ -110,19 +224,52 @@ static int ad7793_calibrate_all(struct ad7793_state *st) ARRAY_SIZE(ad7793_calib_arr)); } -static int ad7793_setup(struct iio_dev *indio_dev, +static int ad7793_check_platform_data(struct ad7793_state *st, const struct ad7793_platform_data *pdata) { + if ((pdata->current_source_direction == AD7793_IEXEC1_IEXEC2_IOUT1 || + pdata->current_source_direction == AD7793_IEXEC1_IEXEC2_IOUT2) && + ((pdata->exitation_current != AD7793_IX_10uA) && + (pdata->exitation_current != AD7793_IX_210uA))) + return -EINVAL; + + if (!(st->chip_info->flags & AD7793_FLAG_HAS_CLKSEL) && + pdata->clock_src != AD7793_CLK_SRC_INT) + return -EINVAL; + + if (!(st->chip_info->flags & AD7793_FLAG_HAS_REFSEL) && + pdata->refsel != AD7793_REFSEL_REFIN1) + return -EINVAL; + + if (!(st->chip_info->flags & AD7793_FLAG_HAS_VBIAS) && + pdata->bias_voltage != AD7793_BIAS_VOLTAGE_DISABLED) + return -EINVAL; + + if (!(st->chip_info->flags & AD7793_HAS_EXITATION_CURRENT) && + pdata->exitation_current != AD7793_IX_DISABLED) + return -EINVAL; + + return 0; +} + +static int ad7793_setup(struct iio_dev *indio_dev, + const struct ad7793_platform_data *pdata, + unsigned int vref_mv) +{ struct ad7793_state *st = iio_priv(indio_dev); int i, ret = -1; unsigned long long scale_uv; u32 id; + ret = ad7793_check_platform_data(st, pdata); + if (ret) + return ret; + /* reset the serial interface */ ret = spi_write(st->sd.spi, (u8 *)&ret, sizeof(ret)); if (ret < 0) goto out; - msleep(1); /* Wait for at least 500us */ + usleep_range(500, 2000); /* Wait for at least 500us */ /* write/read test for device presence */ ret = ad_sd_read_reg(&st->sd, AD7793_REG_ID, 1, &id); @@ -131,13 +278,32 @@ static int ad7793_setup(struct iio_dev *indio_dev, id &= AD7793_ID_MASK; - if (!((id == AD7792_ID) || (id == AD7793_ID) || (id == AD7795_ID))) { + if (id != st->chip_info->id) { dev_err(&st->sd.spi->dev, "device ID query failed\n"); goto out; } - st->mode = pdata->mode; - st->conf = pdata->conf; + st->mode = AD7793_MODE_RATE(1); + st->conf = 0; + + if (st->chip_info->flags & AD7793_FLAG_HAS_CLKSEL) + st->mode |= AD7793_MODE_CLKSRC(pdata->clock_src); + if (st->chip_info->flags & AD7793_FLAG_HAS_REFSEL) + st->conf |= AD7793_CONF_REFSEL(pdata->refsel); + if (st->chip_info->flags & AD7793_FLAG_HAS_VBIAS) + st->conf |= AD7793_CONF_VBIAS(pdata->bias_voltage); + if (pdata->buffered || !(st->chip_info->flags & AD7793_FLAG_HAS_BUFFER)) + st->conf |= AD7793_CONF_BUF; + if (pdata->boost_enable && + (st->chip_info->flags & AD7793_FLAG_HAS_VBIAS)) + st->conf |= AD7793_CONF_BOOST; + if (pdata->burnout_current) + st->conf |= AD7793_CONF_BO_EN; + if (pdata->unipolar) + st->conf |= AD7793_CONF_UNIPOLAR; + + if (!(st->chip_info->flags & AD7793_FLAG_HAS_GAIN)) + st->conf |= AD7793_CONF_GAIN(7); ret = ad7793_set_mode(&st->sd, AD_SD_MODE_IDLE); if (ret) @@ -147,10 +313,13 @@ static int ad7793_setup(struct iio_dev *indio_dev, if (ret) goto out; - ret = ad_sd_write_reg(&st->sd, AD7793_REG_IO, - sizeof(pdata->io), pdata->io); - if (ret) - goto out; + if (st->chip_info->flags & AD7793_HAS_EXITATION_CURRENT) { + ret = ad_sd_write_reg(&st->sd, AD7793_REG_IO, 1, + pdata->exitation_current | + (pdata->current_source_direction << 2)); + if (ret) + goto out; + } ret = ad7793_calibrate_all(st); if (ret) @@ -158,7 +327,7 @@ static int ad7793_setup(struct iio_dev *indio_dev, /* Populate available ADC input ranges */ for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) { - scale_uv = ((u64)st->int_vref_mv * 100000000) + scale_uv = ((u64)vref_mv * 100000000) >> (st->chip_info->channels[0].scan_type.realbits - (!!(st->conf & AD7793_CONF_UNIPOLAR) ? 0 : 1)); scale_uv >>= i; @@ -173,8 +342,11 @@ out: return ret; } -static const u16 sample_freq_avail[16] = {0, 470, 242, 123, 62, 50, 39, 33, 19, - 17, 16, 12, 10, 8, 6, 4}; +static const u16 ad7793_sample_freq_avail[16] = {0, 470, 242, 123, 62, 50, 39, + 33, 19, 17, 16, 12, 10, 8, 6, 4}; + +static const u16 ad7797_sample_freq_avail[16] = {0, 0, 0, 123, 62, 50, 0, + 33, 0, 17, 16, 12, 10, 8, 6, 4}; static ssize_t ad7793_read_frequency(struct device *dev, struct device_attribute *attr, @@ -184,7 +356,7 @@ static ssize_t ad7793_read_frequency(struct device *dev, struct ad7793_state *st = iio_priv(indio_dev); return sprintf(buf, "%d\n", - sample_freq_avail[AD7793_MODE_RATE(st->mode)]); + st->chip_info->sample_freq_avail[AD7793_MODE_RATE(st->mode)]); } static ssize_t ad7793_write_frequency(struct device *dev, @@ -204,14 +376,17 @@ static ssize_t ad7793_write_frequency(struct device *dev, } mutex_unlock(&indio_dev->mlock); - ret = strict_strtol(buf, 10, &lval); + ret = kstrtol(buf, 10, &lval); if (ret) return ret; + if (lval == 0) + return -EINVAL; + ret = -EINVAL; - for (i = 0; i < ARRAY_SIZE(sample_freq_avail); i++) - if (lval == sample_freq_avail[i]) { + for (i = 0; i < 16; i++) + if (lval == st->chip_info->sample_freq_avail[i]) { mutex_lock(&indio_dev->mlock); st->mode &= ~AD7793_MODE_RATE(-1); st->mode |= AD7793_MODE_RATE(i); @@ -231,6 +406,9 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( "470 242 123 62 50 39 33 19 17 16 12 10 8 6 4"); +static IIO_CONST_ATTR_NAMED(sampling_frequency_available_ad7797, + sampling_frequency_available, "123 62 50 33 17 16 12 10 8 6 4"); + static ssize_t ad7793_show_scale_available(struct device *dev, struct device_attribute *attr, char *buf) { @@ -262,6 +440,16 @@ static const struct attribute_group ad7793_attribute_group = { .attrs = ad7793_attributes, }; +static struct attribute *ad7797_attributes[] = { + &iio_dev_attr_sampling_frequency.dev_attr.attr, + &iio_const_attr_sampling_frequency_available_ad7797.dev_attr.attr, + NULL +}; + +static const struct attribute_group ad7797_attribute_group = { + .attrs = ad7797_attributes, +}; + static int ad7793_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, @@ -292,12 +480,12 @@ static int ad7793_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT_PLUS_NANO; } else { /* 1170mV / 2^23 * 6 */ - scale_uv = (1170ULL * 100000000ULL * 6ULL); + scale_uv = (1170ULL * 1000000000ULL * 6ULL); } break; case IIO_TEMP: /* 1170mV / 0.81 mV/C / 2^23 */ - scale_uv = 1444444444444ULL; + scale_uv = 1444444444444444ULL; break; default: return -EINVAL; @@ -387,6 +575,15 @@ static const struct iio_info ad7793_info = { .driver_module = THIS_MODULE, }; +static const struct iio_info ad7797_info = { + .read_raw = &ad7793_read_raw, + .write_raw = &ad7793_write_raw, + .write_raw_get_fmt = &ad7793_write_raw_get_fmt, + .attrs = &ad7793_attribute_group, + .validate_trigger = ad_sd_validate_trigger, + .driver_module = THIS_MODULE, +}; + #define DECLARE_AD7793_CHANNELS(_name, _b, _sb, _s) \ const struct iio_chan_spec _name##_channels[] = { \ AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), (_s)), \ @@ -412,41 +609,143 @@ const struct iio_chan_spec _name##_channels[] = { \ IIO_CHAN_SOFT_TIMESTAMP(9), \ } +#define DECLARE_AD7797_CHANNELS(_name, _b, _sb) \ +const struct iio_chan_spec _name##_channels[] = { \ + AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \ + AD_SD_SHORTED_CHANNEL(1, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), 0), \ + AD_SD_TEMP_CHANNEL(2, AD7793_CH_TEMP, (_b), (_sb), 0), \ + AD_SD_SUPPLY_CHANNEL(3, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \ + IIO_CHAN_SOFT_TIMESTAMP(4), \ +} + +#define DECLARE_AD7799_CHANNELS(_name, _b, _sb) \ +const struct iio_chan_spec _name##_channels[] = { \ + AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \ + AD_SD_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), 0), \ + AD_SD_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), 0), \ + AD_SD_SHORTED_CHANNEL(3, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), 0), \ + AD_SD_SUPPLY_CHANNEL(4, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \ + IIO_CHAN_SOFT_TIMESTAMP(5), \ +} + static DECLARE_AD7793_CHANNELS(ad7785, 20, 32, 4); static DECLARE_AD7793_CHANNELS(ad7792, 16, 32, 0); static DECLARE_AD7793_CHANNELS(ad7793, 24, 32, 0); static DECLARE_AD7795_CHANNELS(ad7794, 16, 32); static DECLARE_AD7795_CHANNELS(ad7795, 24, 32); +static DECLARE_AD7797_CHANNELS(ad7796, 16, 16); +static DECLARE_AD7797_CHANNELS(ad7797, 24, 32); +static DECLARE_AD7799_CHANNELS(ad7798, 16, 16); +static DECLARE_AD7799_CHANNELS(ad7799, 24, 32); static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { [ID_AD7785] = { + .id = AD7785_ID, .channels = ad7785_channels, .num_channels = ARRAY_SIZE(ad7785_channels), + .iio_info = &ad7793_info, + .sample_freq_avail = ad7793_sample_freq_avail, + .flags = AD7793_FLAG_HAS_CLKSEL | + AD7793_FLAG_HAS_REFSEL | + AD7793_FLAG_HAS_VBIAS | + AD7793_HAS_EXITATION_CURRENT | + AD7793_FLAG_HAS_GAIN | + AD7793_FLAG_HAS_BUFFER, }, [ID_AD7792] = { + .id = AD7792_ID, .channels = ad7792_channels, .num_channels = ARRAY_SIZE(ad7792_channels), + .iio_info = &ad7793_info, + .sample_freq_avail = ad7793_sample_freq_avail, + .flags = AD7793_FLAG_HAS_CLKSEL | + AD7793_FLAG_HAS_REFSEL | + AD7793_FLAG_HAS_VBIAS | + AD7793_HAS_EXITATION_CURRENT | + AD7793_FLAG_HAS_GAIN | + AD7793_FLAG_HAS_BUFFER, }, [ID_AD7793] = { + .id = AD7793_ID, .channels = ad7793_channels, .num_channels = ARRAY_SIZE(ad7793_channels), + .iio_info = &ad7793_info, + .sample_freq_avail = ad7793_sample_freq_avail, + .flags = AD7793_FLAG_HAS_CLKSEL | + AD7793_FLAG_HAS_REFSEL | + AD7793_FLAG_HAS_VBIAS | + AD7793_HAS_EXITATION_CURRENT | + AD7793_FLAG_HAS_GAIN | + AD7793_FLAG_HAS_BUFFER, }, [ID_AD7794] = { + .id = AD7794_ID, .channels = ad7794_channels, .num_channels = ARRAY_SIZE(ad7794_channels), + .iio_info = &ad7793_info, + .sample_freq_avail = ad7793_sample_freq_avail, + .flags = AD7793_FLAG_HAS_CLKSEL | + AD7793_FLAG_HAS_REFSEL | + AD7793_FLAG_HAS_VBIAS | + AD7793_HAS_EXITATION_CURRENT | + AD7793_FLAG_HAS_GAIN | + AD7793_FLAG_HAS_BUFFER, }, [ID_AD7795] = { + .id = AD7795_ID, .channels = ad7795_channels, .num_channels = ARRAY_SIZE(ad7795_channels), + .iio_info = &ad7793_info, + .sample_freq_avail = ad7793_sample_freq_avail, + .flags = AD7793_FLAG_HAS_CLKSEL | + AD7793_FLAG_HAS_REFSEL | + AD7793_FLAG_HAS_VBIAS | + AD7793_HAS_EXITATION_CURRENT | + AD7793_FLAG_HAS_GAIN | + AD7793_FLAG_HAS_BUFFER, + }, + [ID_AD7796] = { + .id = AD7796_ID, + .channels = ad7796_channels, + .num_channels = ARRAY_SIZE(ad7796_channels), + .iio_info = &ad7797_info, + .sample_freq_avail = ad7797_sample_freq_avail, + .flags = AD7793_FLAG_HAS_CLKSEL, + }, + [ID_AD7797] = { + .id = AD7797_ID, + .channels = ad7797_channels, + .num_channels = ARRAY_SIZE(ad7797_channels), + .iio_info = &ad7797_info, + .sample_freq_avail = ad7797_sample_freq_avail, + .flags = AD7793_FLAG_HAS_CLKSEL, + }, + [ID_AD7798] = { + .id = AD7798_ID, + .channels = ad7798_channels, + .num_channels = ARRAY_SIZE(ad7798_channels), + .iio_info = &ad7793_info, + .sample_freq_avail = ad7793_sample_freq_avail, + .flags = AD7793_FLAG_HAS_GAIN | + AD7793_FLAG_HAS_BUFFER, + }, + [ID_AD7799] = { + .id = AD7799_ID, + .channels = ad7799_channels, + .num_channels = ARRAY_SIZE(ad7799_channels), + .iio_info = &ad7793_info, + .sample_freq_avail = ad7793_sample_freq_avail, + .flags = AD7793_FLAG_HAS_GAIN | + AD7793_FLAG_HAS_BUFFER, }, }; -static int __devinit ad7793_probe(struct spi_device *spi) +static int ad7793_probe(struct spi_device *spi) { const struct ad7793_platform_data *pdata = spi->dev.platform_data; struct ad7793_state *st; struct iio_dev *indio_dev; - int ret, voltage_uv = 0; + int ret, vref_mv = 0; if (!pdata) { dev_err(&spi->dev, "no platform data?\n"); @@ -466,25 +765,31 @@ static int __devinit ad7793_probe(struct spi_device *spi) ad_sd_init(&st->sd, indio_dev, spi, &ad7793_sigma_delta_info); - st->reg = regulator_get(&spi->dev, "vcc"); - if (!IS_ERR(st->reg)) { + if (pdata->refsel != AD7793_REFSEL_INTERNAL) { + st->reg = regulator_get(&spi->dev, "refin"); + if (IS_ERR(st->reg)) { + ret = PTR_ERR(st->reg); + goto error_device_free; + } + ret = regulator_enable(st->reg); if (ret) goto error_put_reg; - voltage_uv = regulator_get_voltage(st->reg); + vref_mv = regulator_get_voltage(st->reg); + if (vref_mv < 0) { + ret = vref_mv; + goto error_disable_reg; + } + + vref_mv /= 1000; + } else { + vref_mv = 1170; /* Build-in ref */ } st->chip_info = &ad7793_chip_info_tbl[spi_get_device_id(spi)->driver_data]; - if (pdata && pdata->vref_mv) - st->int_vref_mv = pdata->vref_mv; - else if (voltage_uv) - st->int_vref_mv = voltage_uv / 1000; - else - st->int_vref_mv = 1170; /* Build-in ref */ - spi_set_drvdata(spi, indio_dev); indio_dev->dev.parent = &spi->dev; @@ -492,13 +797,13 @@ static int __devinit ad7793_probe(struct spi_device *spi) indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = st->chip_info->channels; indio_dev->num_channels = st->chip_info->num_channels; - indio_dev->info = &ad7793_info; + indio_dev->info = st->chip_info->iio_info; ret = ad_sd_setup_buffer_and_trigger(indio_dev); if (ret) goto error_disable_reg; - ret = ad7793_setup(indio_dev, pdata); + ret = ad7793_setup(indio_dev, pdata, vref_mv); if (ret) goto error_remove_trigger; @@ -511,26 +816,27 @@ static int __devinit ad7793_probe(struct spi_device *spi) error_remove_trigger: ad_sd_cleanup_buffer_and_trigger(indio_dev); error_disable_reg: - if (!IS_ERR(st->reg)) + if (pdata->refsel != AD7793_REFSEL_INTERNAL) regulator_disable(st->reg); error_put_reg: - if (!IS_ERR(st->reg)) + if (pdata->refsel != AD7793_REFSEL_INTERNAL) regulator_put(st->reg); - +error_device_free: iio_device_free(indio_dev); return ret; } -static int __devexit ad7793_remove(struct spi_device *spi) +static int ad7793_remove(struct spi_device *spi) { + const struct ad7793_platform_data *pdata = spi->dev.platform_data; struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad7793_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); ad_sd_cleanup_buffer_and_trigger(indio_dev); - if (!IS_ERR(st->reg)) { + if (pdata->refsel != AD7793_REFSEL_INTERNAL) { regulator_disable(st->reg); regulator_put(st->reg); } @@ -546,6 +852,10 @@ static const struct spi_device_id ad7793_id[] = { {"ad7793", ID_AD7793}, {"ad7794", ID_AD7794}, {"ad7795", ID_AD7795}, + {"ad7796", ID_AD7796}, + {"ad7797", ID_AD7797}, + {"ad7798", ID_AD7798}, + {"ad7799", ID_AD7799}, {} }; MODULE_DEVICE_TABLE(spi, ad7793_id); @@ -556,7 +866,7 @@ static struct spi_driver ad7793_driver = { .owner = THIS_MODULE, }, .probe = ad7793_probe, - .remove = __devexit_p(ad7793_remove), + .remove = ad7793_remove, .id_table = ad7793_id, }; module_spi_driver(ad7793_driver); diff --git a/drivers/staging/iio/adc/ad7887_core.c b/drivers/iio/adc/ad7887.c index 551790584a12..81153fafac7a 100644 --- a/drivers/staging/iio/adc/ad7887_core.c +++ b/drivers/iio/adc/ad7887.c @@ -14,13 +14,139 @@ #include <linux/regulator/consumer.h> #include <linux/err.h> #include <linux/module.h> +#include <linux/interrupt.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> #include <linux/iio/buffer.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/iio/triggered_buffer.h> -#include "ad7887.h" +#include <linux/platform_data/ad7887.h> + +#define AD7887_REF_DIS (1 << 5) /* on-chip reference disable */ +#define AD7887_DUAL (1 << 4) /* dual-channel mode */ +#define AD7887_CH_AIN1 (1 << 3) /* convert on channel 1, DUAL=1 */ +#define AD7887_CH_AIN0 (0 << 3) /* convert on channel 0, DUAL=0,1 */ +#define AD7887_PM_MODE1 (0) /* CS based shutdown */ +#define AD7887_PM_MODE2 (1) /* full on */ +#define AD7887_PM_MODE3 (2) /* auto shutdown after conversion */ +#define AD7887_PM_MODE4 (3) /* standby mode */ + +enum ad7887_channels { + AD7887_CH0, + AD7887_CH0_CH1, + AD7887_CH1, +}; + +#define RES_MASK(bits) ((1 << (bits)) - 1) + +/** + * struct ad7887_chip_info - chip specifc information + * @int_vref_mv: the internal reference voltage + * @channel: channel specification + */ +struct ad7887_chip_info { + u16 int_vref_mv; + struct iio_chan_spec channel[3]; +}; + +struct ad7887_state { + struct spi_device *spi; + const struct ad7887_chip_info *chip_info; + struct regulator *reg; + struct spi_transfer xfer[4]; + struct spi_message msg[3]; + struct spi_message *ring_msg; + unsigned char tx_cmd_buf[4]; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + * Buffer needs to be large enough to hold two 16 bit samples and a + * 64 bit aligned 64 bit timestamp. + */ + unsigned char data[ALIGN(4, sizeof(s64)) + sizeof(s64)] + ____cacheline_aligned; +}; + +enum ad7887_supported_device_ids { + ID_AD7887 +}; + +static int ad7887_ring_preenable(struct iio_dev *indio_dev) +{ + struct ad7887_state *st = iio_priv(indio_dev); + int ret; + + ret = iio_sw_buffer_preenable(indio_dev); + if (ret < 0) + return ret; + + /* We know this is a single long so can 'cheat' */ + switch (*indio_dev->active_scan_mask) { + case (1 << 0): + st->ring_msg = &st->msg[AD7887_CH0]; + break; + case (1 << 1): + st->ring_msg = &st->msg[AD7887_CH1]; + /* Dummy read: push CH1 setting down to hardware */ + spi_sync(st->spi, st->ring_msg); + break; + case ((1 << 1) | (1 << 0)): + st->ring_msg = &st->msg[AD7887_CH0_CH1]; + break; + } + + return 0; +} + +static int ad7887_ring_postdisable(struct iio_dev *indio_dev) +{ + struct ad7887_state *st = iio_priv(indio_dev); + + /* dummy read: restore default CH0 settin */ + return spi_sync(st->spi, &st->msg[AD7887_CH0]); +} + +/** + * ad7887_trigger_handler() bh of trigger launched polling to ring buffer + * + * Currently there is no option in this driver to disable the saving of + * timestamps within the ring. + **/ +static irqreturn_t ad7887_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct ad7887_state *st = iio_priv(indio_dev); + s64 time_ns; + int b_sent; + + b_sent = spi_sync(st->spi, st->ring_msg); + if (b_sent) + goto done; + + time_ns = iio_get_time_ns(); + + if (indio_dev->scan_timestamp) + memcpy(st->data + indio_dev->scan_bytes - sizeof(s64), + &time_ns, sizeof(time_ns)); + + iio_push_to_buffers(indio_dev, st->data); +done: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static const struct iio_buffer_setup_ops ad7887_ring_setup_ops = { + .preenable = &ad7887_ring_preenable, + .postenable = &iio_triggered_buffer_postenable, + .predisable = &iio_triggered_buffer_predisable, + .postdisable = &ad7887_ring_postdisable, +}; static int ad7887_scan_direct(struct ad7887_state *st, unsigned ch) { @@ -39,7 +165,6 @@ static int ad7887_read_raw(struct iio_dev *indio_dev, { int ret; struct ad7887_state *st = iio_priv(indio_dev); - unsigned int scale_uv; switch (m) { case IIO_CHAN_INFO_RAW: @@ -52,15 +177,22 @@ static int ad7887_read_raw(struct iio_dev *indio_dev, if (ret < 0) return ret; - *val = (ret >> st->chip_info->channel[0].scan_type.shift) & - RES_MASK(st->chip_info->channel[0].scan_type.realbits); + *val = ret >> chan->scan_type.shift; + *val &= RES_MASK(chan->scan_type.realbits); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - scale_uv = (st->int_vref_mv * 1000) - >> st->chip_info->channel[0].scan_type.realbits; - *val = scale_uv/1000; - *val2 = (scale_uv%1000)*1000; - return IIO_VAL_INT_PLUS_MICRO; + if (st->reg) { + *val = regulator_get_voltage(st->reg); + if (*val < 0) + return *val; + *val /= 1000; + } else { + *val = st->chip_info->int_vref_mv; + } + + *val2 = chan->scan_type.realbits; + + return IIO_VAL_FRACTIONAL_LOG2; } return -EINVAL; } @@ -105,21 +237,25 @@ static int __devinit ad7887_probe(struct spi_device *spi) { struct ad7887_platform_data *pdata = spi->dev.platform_data; struct ad7887_state *st; - int ret, voltage_uv = 0; struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st)); + uint8_t mode; + int ret; if (indio_dev == NULL) return -ENOMEM; st = iio_priv(indio_dev); - st->reg = regulator_get(&spi->dev, "vcc"); - if (!IS_ERR(st->reg)) { + if (!pdata || !pdata->use_onchip_ref) { + st->reg = regulator_get(&spi->dev, "vref"); + if (IS_ERR(st->reg)) { + ret = PTR_ERR(st->reg); + goto error_free; + } + ret = regulator_enable(st->reg); if (ret) goto error_put_reg; - - voltage_uv = regulator_get_voltage(st->reg); } st->chip_info = @@ -136,9 +272,13 @@ static int __devinit ad7887_probe(struct spi_device *spi) /* Setup default message */ - st->tx_cmd_buf[0] = AD7887_CH_AIN0 | AD7887_PM_MODE4 | - ((pdata && pdata->use_onchip_ref) ? - 0 : AD7887_REF_DIS); + mode = AD7887_PM_MODE4; + if (!pdata || !pdata->use_onchip_ref) + mode |= AD7887_REF_DIS; + if (pdata && pdata->en_dual) + mode |= AD7887_DUAL; + + st->tx_cmd_buf[0] = AD7887_CH_AIN0 | mode; st->xfer[0].rx_buf = &st->data[0]; st->xfer[0].tx_buf = &st->tx_cmd_buf[0]; @@ -148,56 +288,36 @@ static int __devinit ad7887_probe(struct spi_device *spi) spi_message_add_tail(&st->xfer[0], &st->msg[AD7887_CH0]); if (pdata && pdata->en_dual) { - st->tx_cmd_buf[0] |= AD7887_DUAL | AD7887_REF_DIS; - - st->tx_cmd_buf[2] = AD7887_CH_AIN1 | AD7887_DUAL | - AD7887_REF_DIS | AD7887_PM_MODE4; - st->tx_cmd_buf[4] = AD7887_CH_AIN0 | AD7887_DUAL | - AD7887_REF_DIS | AD7887_PM_MODE4; - st->tx_cmd_buf[6] = AD7887_CH_AIN1 | AD7887_DUAL | - AD7887_REF_DIS | AD7887_PM_MODE4; + st->tx_cmd_buf[2] = AD7887_CH_AIN1 | mode; st->xfer[1].rx_buf = &st->data[0]; st->xfer[1].tx_buf = &st->tx_cmd_buf[2]; st->xfer[1].len = 2; st->xfer[2].rx_buf = &st->data[2]; - st->xfer[2].tx_buf = &st->tx_cmd_buf[4]; + st->xfer[2].tx_buf = &st->tx_cmd_buf[0]; st->xfer[2].len = 2; spi_message_init(&st->msg[AD7887_CH0_CH1]); spi_message_add_tail(&st->xfer[1], &st->msg[AD7887_CH0_CH1]); spi_message_add_tail(&st->xfer[2], &st->msg[AD7887_CH0_CH1]); - st->xfer[3].rx_buf = &st->data[0]; - st->xfer[3].tx_buf = &st->tx_cmd_buf[6]; + st->xfer[3].rx_buf = &st->data[2]; + st->xfer[3].tx_buf = &st->tx_cmd_buf[2]; st->xfer[3].len = 2; spi_message_init(&st->msg[AD7887_CH1]); spi_message_add_tail(&st->xfer[3], &st->msg[AD7887_CH1]); - if (pdata && pdata->vref_mv) - st->int_vref_mv = pdata->vref_mv; - else if (voltage_uv) - st->int_vref_mv = voltage_uv / 1000; - else - dev_warn(&spi->dev, "reference voltage unspecified\n"); - indio_dev->channels = st->chip_info->channel; indio_dev->num_channels = 3; } else { - if (pdata && pdata->vref_mv) - st->int_vref_mv = pdata->vref_mv; - else if (pdata && pdata->use_onchip_ref) - st->int_vref_mv = st->chip_info->int_vref_mv; - else - dev_warn(&spi->dev, "reference voltage unspecified\n"); - indio_dev->channels = &st->chip_info->channel[1]; indio_dev->num_channels = 2; } - ret = ad7887_register_ring_funcs_and_init(indio_dev); + ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, + &ad7887_trigger_handler, &ad7887_ring_setup_ops); if (ret) goto error_disable_reg; @@ -207,13 +327,14 @@ static int __devinit ad7887_probe(struct spi_device *spi) return 0; error_unregister_ring: - ad7887_ring_cleanup(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); error_disable_reg: - if (!IS_ERR(st->reg)) + if (st->reg) regulator_disable(st->reg); error_put_reg: - if (!IS_ERR(st->reg)) + if (st->reg) regulator_put(st->reg); +error_free: iio_device_free(indio_dev); return ret; @@ -225,8 +346,8 @@ static int __devexit ad7887_remove(struct spi_device *spi) struct ad7887_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - ad7887_ring_cleanup(indio_dev); - if (!IS_ERR(st->reg)) { + iio_triggered_buffer_cleanup(indio_dev); + if (st->reg) { regulator_disable(st->reg); regulator_put(st->reg); } diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c index 67baa1363d7a..afe6d78c8ff0 100644 --- a/drivers/iio/adc/ad_sigma_delta.c +++ b/drivers/iio/adc/ad_sigma_delta.c @@ -391,7 +391,7 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p) break; } - iio_push_to_buffer(indio_dev->buffer, (uint8_t *)data); + iio_push_to_buffers(indio_dev, (uint8_t *)data); iio_trigger_notify_done(indio_dev->trig); sigma_delta->irq_dis = false; diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 3ed94bf80596..03b85940f4ba 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -46,7 +46,6 @@ struct at91_adc_state { struct clk *clk; bool done; int irq; - bool irq_enabled; u16 last_value; struct mutex lock; u8 num_channels; @@ -66,7 +65,6 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *idev = pf->indio_dev; struct at91_adc_state *st = iio_priv(idev); - struct iio_buffer *buffer = idev->buffer; int i, j = 0; for (i = 0; i < idev->masklength; i++) { @@ -82,10 +80,9 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p) *timestamp = pf->timestamp; } - buffer->access->store_to(buffer, (u8 *)st->buffer); + iio_push_to_buffers(indio_dev, (u8 *)st->buffer); iio_trigger_notify_done(idev->trig); - st->irq_enabled = true; /* Needed to ACK the DRDY interruption */ at91_adc_readl(st, AT91_ADC_LCDR); @@ -106,7 +103,6 @@ static irqreturn_t at91_adc_eoc_trigger(int irq, void *private) if (iio_buffer_enabled(idev)) { disable_irq_nosync(irq); - st->irq_enabled = false; iio_trigger_poll(idev->trig, iio_get_time_ns()); } else { st->last_value = at91_adc_readl(st, AT91_ADC_LCDR); diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/iio/adc/max1363.c index d7b4ffcfa052..1e84b5b55093 100644 --- a/drivers/staging/iio/adc/max1363_core.c +++ b/drivers/iio/adc/max1363.c @@ -37,8 +37,151 @@ #include <linux/iio/events.h> #include <linux/iio/buffer.h> #include <linux/iio/driver.h> +#include <linux/iio/kfifo_buf.h> +#include <linux/iio/trigger_consumer.h> + +#define MAX1363_SETUP_BYTE(a) ((a) | 0x80) + +/* There is a fair bit more defined here than currently + * used, but the intention is to support everything these + * chips do in the long run */ + +/* see data sheets */ +/* max1363 and max1236, max1237, max1238, max1239 */ +#define MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_VDD 0x00 +#define MAX1363_SETUP_AIN3_IS_REF_EXT_TO_REF 0x20 +#define MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_INT 0x40 +#define MAX1363_SETUP_AIN3_IS_REF_REF_IS_INT 0x60 +#define MAX1363_SETUP_POWER_UP_INT_REF 0x10 +#define MAX1363_SETUP_POWER_DOWN_INT_REF 0x00 + +/* think about includeing max11600 etc - more settings */ +#define MAX1363_SETUP_EXT_CLOCK 0x08 +#define MAX1363_SETUP_INT_CLOCK 0x00 +#define MAX1363_SETUP_UNIPOLAR 0x00 +#define MAX1363_SETUP_BIPOLAR 0x04 +#define MAX1363_SETUP_RESET 0x00 +#define MAX1363_SETUP_NORESET 0x02 +/* max1363 only - though don't care on others. + * For now monitor modes are not implemented as the relevant + * line is not connected on my test board. + * The definitions are here as I intend to add this soon. + */ +#define MAX1363_SETUP_MONITOR_SETUP 0x01 + +/* Specific to the max1363 */ +#define MAX1363_MON_RESET_CHAN(a) (1 << ((a) + 4)) +#define MAX1363_MON_INT_ENABLE 0x01 + +/* defined for readability reasons */ +/* All chips */ +#define MAX1363_CONFIG_BYTE(a) ((a)) + +#define MAX1363_CONFIG_SE 0x01 +#define MAX1363_CONFIG_DE 0x00 +#define MAX1363_CONFIG_SCAN_TO_CS 0x00 +#define MAX1363_CONFIG_SCAN_SINGLE_8 0x20 +#define MAX1363_CONFIG_SCAN_MONITOR_MODE 0x40 +#define MAX1363_CONFIG_SCAN_SINGLE_1 0x60 +/* max123{6-9} only */ +#define MAX1236_SCAN_MID_TO_CHANNEL 0x40 + +/* max1363 only - merely part of channel selects or don't care for others*/ +#define MAX1363_CONFIG_EN_MON_MODE_READ 0x18 + +#define MAX1363_CHANNEL_SEL(a) ((a) << 1) + +/* max1363 strictly 0x06 - but doesn't matter */ +#define MAX1363_CHANNEL_SEL_MASK 0x1E +#define MAX1363_SCAN_MASK 0x60 +#define MAX1363_SE_DE_MASK 0x01 + +#define MAX1363_MAX_CHANNELS 25 +/** + * struct max1363_mode - scan mode information + * @conf: The corresponding value of the configuration register + * @modemask: Bit mask corresponding to channels enabled in this mode + */ +struct max1363_mode { + int8_t conf; + DECLARE_BITMAP(modemask, MAX1363_MAX_CHANNELS); +}; -#include "max1363.h" +/* This must be maintained along side the max1363_mode_table in max1363_core */ +enum max1363_modes { + /* Single read of a single channel */ + _s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9, _s10, _s11, + /* Differential single read */ + d0m1, d2m3, d4m5, d6m7, d8m9, d10m11, + d1m0, d3m2, d5m4, d7m6, d9m8, d11m10, + /* Scan to channel and mid to channel where overlapping */ + s0to1, s0to2, s2to3, s0to3, s0to4, s0to5, s0to6, + s6to7, s0to7, s6to8, s0to8, s6to9, + s0to9, s6to10, s0to10, s6to11, s0to11, + /* Differential scan to channel and mid to channel where overlapping */ + d0m1to2m3, d0m1to4m5, d0m1to6m7, d6m7to8m9, + d0m1to8m9, d6m7to10m11, d0m1to10m11, d1m0to3m2, + d1m0to5m4, d1m0to7m6, d7m6to9m8, d1m0to9m8, + d7m6to11m10, d1m0to11m10, +}; + +/** + * struct max1363_chip_info - chip specifc information + * @info: iio core function callbacks structure + * @channels: channel specification + * @num_channels: number of channels + * @mode_list: array of available scan modes + * @default_mode: the scan mode in which the chip starts up + * @int_vref_mv: the internal reference voltage + * @num_channels: number of channels + * @bits: accuracy of the adc in bits + */ +struct max1363_chip_info { + const struct iio_info *info; + const struct iio_chan_spec *channels; + int num_channels; + const enum max1363_modes *mode_list; + enum max1363_modes default_mode; + u16 int_vref_mv; + u8 num_modes; + u8 bits; +}; + +/** + * struct max1363_state - driver instance specific data + * @client: i2c_client + * @setupbyte: cache of current device setup byte + * @configbyte: cache of current device config byte + * @chip_info: chip model specific constants, available modes etc + * @current_mode: the scan mode of this chip + * @requestedmask: a valid requested set of channels + * @reg: supply regulator + * @monitor_on: whether monitor mode is enabled + * @monitor_speed: parameter corresponding to device monitor speed setting + * @mask_high: bitmask for enabled high thresholds + * @mask_low: bitmask for enabled low thresholds + * @thresh_high: high threshold values + * @thresh_low: low threshold values + */ +struct max1363_state { + struct i2c_client *client; + u8 setupbyte; + u8 configbyte; + const struct max1363_chip_info *chip_info; + const struct max1363_mode *current_mode; + u32 requestedmask; + struct regulator *reg; + + /* Using monitor modes and buffer at the same time is + currently not supported */ + bool monitor_on; + unsigned int monitor_speed:3; + u8 mask_high; + u8 mask_low; + /* 4x unipolar first then the fours bipolar ones */ + s16 thresh_high[8]; + s16 thresh_low[8]; +}; #define MAX1363_MODE_SINGLE(_num, _mask) { \ .conf = MAX1363_CHANNEL_SEL(_num) \ @@ -148,7 +291,7 @@ static const struct max1363_mode max1363_mode_table[] = { MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(11, 6, 0xFC0000), }; -const struct max1363_mode +static const struct max1363_mode *max1363_match_mode(const unsigned long *mask, const struct max1363_chip_info *ci) { @@ -172,7 +315,7 @@ static int max1363_write_basic_config(struct i2c_client *client, return i2c_master_send(client, tx_buf, 2); } -int max1363_set_scan_mode(struct max1363_state *st) +static int max1363_set_scan_mode(struct max1363_state *st) { st->configbyte &= ~(MAX1363_CHANNEL_SEL_MASK | MAX1363_SCAN_MASK @@ -622,9 +765,9 @@ static int max1363_read_event_config(struct iio_dev *indio_dev, u64 event_code) { struct max1363_state *st = iio_priv(indio_dev); - int val; int number = IIO_EVENT_CODE_EXTRACT_CHAN(event_code); + mutex_lock(&indio_dev->mlock); if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING) val = (1 << number) & st->mask_low; @@ -644,7 +787,7 @@ static int max1363_monitor_mode_update(struct max1363_state *st, int enabled) const long *modemask; if (!enabled) { - /* transition to ring capture is not currently supported */ + /* transition to buffered capture is not currently supported */ st->setupbyte &= ~MAX1363_SETUP_MONITOR_SETUP; st->configbyte &= ~MAX1363_SCAN_MASK; st->monitor_on = false; @@ -826,8 +969,21 @@ static struct attribute_group max1363_event_attribute_group = { .name = "events", }; -#define MAX1363_EVENT_FUNCS \ +static int max1363_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *scan_mask) +{ + struct max1363_state *st = iio_priv(indio_dev); + /* + * Need to figure out the current mode based upon the requested + * scan mask in iio_dev + */ + st->current_mode = max1363_match_mode(scan_mask, st->chip_info); + if (!st->current_mode) + return -EINVAL; + max1363_set_scan_mode(st); + return 0; +} static const struct iio_info max1238_info = { .read_raw = &max1363_read_raw, @@ -1230,8 +1386,6 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = { }, }; - - static int max1363_initial_setup(struct max1363_state *st) { st->setupbyte = MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_VDD @@ -1269,34 +1423,137 @@ static int __devinit max1363_alloc_scan_masks(struct iio_dev *indio_dev) return 0; } + +static irqreturn_t max1363_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct max1363_state *st = iio_priv(indio_dev); + s64 time_ns; + __u8 *rxbuf; + int b_sent; + size_t d_size; + unsigned long numvals = bitmap_weight(st->current_mode->modemask, + MAX1363_MAX_CHANNELS); + + /* Ensure the timestamp is 8 byte aligned */ + if (st->chip_info->bits != 8) + d_size = numvals*2; + else + d_size = numvals; + if (indio_dev->scan_timestamp) { + d_size += sizeof(s64); + if (d_size % sizeof(s64)) + d_size += sizeof(s64) - (d_size % sizeof(s64)); + } + /* Monitor mode prevents reading. Whilst not currently implemented + * might as well have this test in here in the meantime as it does + * no harm. + */ + if (numvals == 0) + goto done; + + rxbuf = kmalloc(d_size, GFP_KERNEL); + if (rxbuf == NULL) + goto done; + if (st->chip_info->bits != 8) + b_sent = i2c_master_recv(st->client, rxbuf, numvals*2); + else + b_sent = i2c_master_recv(st->client, rxbuf, numvals); + if (b_sent < 0) + goto done_free; + + time_ns = iio_get_time_ns(); + + if (indio_dev->scan_timestamp) + memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns)); + iio_push_to_buffers(indio_dev, rxbuf); + +done_free: + kfree(rxbuf); +done: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static const struct iio_buffer_setup_ops max1363_buffered_setup_ops = { + .postenable = &iio_triggered_buffer_postenable, + .preenable = &iio_sw_buffer_preenable, + .predisable = &iio_triggered_buffer_predisable, +}; + +static int max1363_register_buffered_funcs_and_init(struct iio_dev *indio_dev) +{ + struct max1363_state *st = iio_priv(indio_dev); + int ret = 0; + + indio_dev->buffer = iio_kfifo_allocate(indio_dev); + if (!indio_dev->buffer) { + ret = -ENOMEM; + goto error_ret; + } + indio_dev->pollfunc = iio_alloc_pollfunc(NULL, + &max1363_trigger_handler, + IRQF_ONESHOT, + indio_dev, + "%s_consumer%d", + st->client->name, + indio_dev->id); + if (indio_dev->pollfunc == NULL) { + ret = -ENOMEM; + goto error_deallocate_sw_rb; + } + /* Buffer functions - here trigger setup related */ + indio_dev->setup_ops = &max1363_buffered_setup_ops; + + /* Flag that polled buffering is possible */ + indio_dev->modes |= INDIO_BUFFER_TRIGGERED; + + return 0; + +error_deallocate_sw_rb: + iio_kfifo_free(indio_dev->buffer); +error_ret: + return ret; +} + +static void max1363_buffer_cleanup(struct iio_dev *indio_dev) +{ + /* ensure that the trigger has been detached */ + iio_dealloc_pollfunc(indio_dev->pollfunc); + iio_kfifo_free(indio_dev->buffer); +} + static int __devinit max1363_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret; struct max1363_state *st; struct iio_dev *indio_dev; - struct regulator *reg; - - reg = regulator_get(&client->dev, "vcc"); - if (IS_ERR(reg)) { - ret = PTR_ERR(reg); - goto error_out; - } - - ret = regulator_enable(reg); - if (ret) - goto error_put_reg; indio_dev = iio_device_alloc(sizeof(struct max1363_state)); if (indio_dev == NULL) { ret = -ENOMEM; - goto error_disable_reg; + goto error_out; } + ret = iio_map_array_register(indio_dev, client->dev.platform_data); if (ret < 0) goto error_free_device; + st = iio_priv(indio_dev); - st->reg = reg; + + st->reg = regulator_get(&client->dev, "vcc"); + if (IS_ERR(st->reg)) { + ret = PTR_ERR(st->reg); + goto error_unregister_map; + } + + ret = regulator_enable(st->reg); + if (ret) + goto error_put_reg; + /* this is only used for device removal purposes */ i2c_set_clientdata(client, indio_dev); @@ -1305,7 +1562,7 @@ static int __devinit max1363_probe(struct i2c_client *client, ret = max1363_alloc_scan_masks(indio_dev); if (ret) - goto error_unregister_map; + goto error_disable_reg; /* Estabilish that the iio_dev is a child of the i2c device */ indio_dev->dev.parent = &client->dev; @@ -1320,7 +1577,7 @@ static int __devinit max1363_probe(struct i2c_client *client, if (ret < 0) goto error_free_available_scan_masks; - ret = max1363_register_ring_funcs_and_init(indio_dev); + ret = max1363_register_buffered_funcs_and_init(indio_dev); if (ret) goto error_free_available_scan_masks; @@ -1328,7 +1585,7 @@ static int __devinit max1363_probe(struct i2c_client *client, st->chip_info->channels, st->chip_info->num_channels); if (ret) - goto error_cleanup_ring; + goto error_cleanup_buffer; if (client->irq) { ret = request_threaded_irq(st->client->irq, @@ -1339,7 +1596,7 @@ static int __devinit max1363_probe(struct i2c_client *client, indio_dev); if (ret) - goto error_uninit_ring; + goto error_uninit_buffer; } ret = iio_device_register(indio_dev); @@ -1349,20 +1606,20 @@ static int __devinit max1363_probe(struct i2c_client *client, return 0; error_free_irq: free_irq(st->client->irq, indio_dev); -error_uninit_ring: +error_uninit_buffer: iio_buffer_unregister(indio_dev); -error_cleanup_ring: - max1363_ring_cleanup(indio_dev); +error_cleanup_buffer: + max1363_buffer_cleanup(indio_dev); error_free_available_scan_masks: kfree(indio_dev->available_scan_masks); error_unregister_map: iio_map_array_unregister(indio_dev, client->dev.platform_data); -error_free_device: - iio_device_free(indio_dev); error_disable_reg: - regulator_disable(reg); + regulator_disable(st->reg); error_put_reg: - regulator_put(reg); + regulator_put(st->reg); +error_free_device: + iio_device_free(indio_dev); error_out: return ret; } @@ -1371,17 +1628,16 @@ static int __devexit max1363_remove(struct i2c_client *client) { struct iio_dev *indio_dev = i2c_get_clientdata(client); struct max1363_state *st = iio_priv(indio_dev); - struct regulator *reg = st->reg; iio_device_unregister(indio_dev); if (client->irq) free_irq(st->client->irq, indio_dev); iio_buffer_unregister(indio_dev); - max1363_ring_cleanup(indio_dev); + max1363_buffer_cleanup(indio_dev); kfree(indio_dev->available_scan_masks); - if (!IS_ERR(reg)) { - regulator_disable(reg); - regulator_put(reg); + if (!IS_ERR(st->reg)) { + regulator_disable(st->reg); + regulator_put(st->reg); } iio_map_array_unregister(indio_dev, client->dev.platform_data); iio_device_free(indio_dev); diff --git a/drivers/iio/adc/ti-adc081c.c b/drivers/iio/adc/ti-adc081c.c new file mode 100644 index 000000000000..f4a46dd8f43b --- /dev/null +++ b/drivers/iio/adc/ti-adc081c.c @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2012 Avionic Design GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/err.h> +#include <linux/i2c.h> +#include <linux/module.h> + +#include <linux/iio/iio.h> +#include <linux/regulator/consumer.h> + +struct adc081c { + struct i2c_client *i2c; + struct regulator *ref; +}; + +#define REG_CONV_RES 0x00 + +static int adc081c_read_raw(struct iio_dev *iio, + struct iio_chan_spec const *channel, int *value, + int *shift, long mask) +{ + struct adc081c *adc = iio_priv(iio); + int err; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + err = i2c_smbus_read_word_swapped(adc->i2c, REG_CONV_RES); + if (err < 0) + return err; + + *value = (err >> 4) & 0xff; + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + err = regulator_get_voltage(adc->ref); + if (err < 0) + return err; + + *value = err / 1000; + *shift = 8; + + return IIO_VAL_FRACTIONAL_LOG2; + + default: + break; + } + + return -EINVAL; +} + +static const struct iio_chan_spec adc081c_channel = { + .type = IIO_VOLTAGE, + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT | + IIO_CHAN_INFO_RAW_SEPARATE_BIT, +}; + +static const struct iio_info adc081c_info = { + .read_raw = adc081c_read_raw, + .driver_module = THIS_MODULE, +}; + +static int adc081c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct iio_dev *iio; + struct adc081c *adc; + int err; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) + return -ENODEV; + + iio = iio_device_alloc(sizeof(*adc)); + if (!iio) + return -ENOMEM; + + adc = iio_priv(iio); + adc->i2c = client; + + adc->ref = regulator_get(&client->dev, "vref"); + if (IS_ERR(adc->ref)) { + err = PTR_ERR(adc->ref); + goto iio_free; + } + + err = regulator_enable(adc->ref); + if (err < 0) + goto regulator_put; + + iio->dev.parent = &client->dev; + iio->name = dev_name(&client->dev); + iio->modes = INDIO_DIRECT_MODE; + iio->info = &adc081c_info; + + iio->channels = &adc081c_channel; + iio->num_channels = 1; + + err = iio_device_register(iio); + if (err < 0) + goto regulator_disable; + + i2c_set_clientdata(client, iio); + + return 0; + +regulator_disable: + regulator_disable(adc->ref); +regulator_put: + regulator_put(adc->ref); +iio_free: + iio_device_free(iio); + + return err; +} + +static int adc081c_remove(struct i2c_client *client) +{ + struct iio_dev *iio = i2c_get_clientdata(client); + struct adc081c *adc = iio_priv(iio); + + iio_device_unregister(iio); + regulator_disable(adc->ref); + regulator_put(adc->ref); + iio_device_free(iio); + + return 0; +} + +static const struct i2c_device_id adc081c_id[] = { + { "adc081c", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adc081c_id); + +#ifdef CONFIG_OF +static const struct of_device_id adc081c_of_match[] = { + { .compatible = "ti,adc081c" }, + { } +}; +MODULE_DEVICE_TABLE(of, adc081c_of_match); +#endif + +static struct i2c_driver adc081c_driver = { + .driver = { + .name = "adc081c", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(adc081c_of_match), + }, + .probe = adc081c_probe, + .remove = adc081c_remove, + .id_table = adc081c_id, +}; +module_i2c_driver(adc081c_driver); + +MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>"); +MODULE_DESCRIPTION("Texas Instruments ADC081C021/027 driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/buffer_cb.c b/drivers/iio/buffer_cb.c new file mode 100644 index 000000000000..4d40e24f3721 --- /dev/null +++ b/drivers/iio/buffer_cb.c @@ -0,0 +1,113 @@ +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/err.h> +#include <linux/export.h> +#include <linux/iio/buffer.h> +#include <linux/iio/consumer.h> + +struct iio_cb_buffer { + struct iio_buffer buffer; + int (*cb)(u8 *data, void *private); + void *private; + struct iio_channel *channels; +}; + +static int iio_buffer_cb_store_to(struct iio_buffer *buffer, u8 *data) +{ + struct iio_cb_buffer *cb_buff = container_of(buffer, + struct iio_cb_buffer, + buffer); + + return cb_buff->cb(data, cb_buff->private); +} + +static struct iio_buffer_access_funcs iio_cb_access = { + .store_to = &iio_buffer_cb_store_to, +}; + +struct iio_cb_buffer *iio_channel_get_all_cb(const char *name, + int (*cb)(u8 *data, + void *private), + void *private) +{ + 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); + if (cb_buff == NULL) { + ret = -ENOMEM; + goto error_ret; + } + + cb_buff->private = private; + cb_buff->cb = cb; + cb_buff->buffer.access = &iio_cb_access; + INIT_LIST_HEAD(&cb_buff->buffer.demux_list); + + cb_buff->channels = iio_channel_get_all(name); + if (IS_ERR(cb_buff->channels)) { + ret = PTR_ERR(cb_buff->channels); + goto error_free_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); + 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) { + ret = -EINVAL; + goto error_release_channels; + } + set_bit(chan->channel->scan_index, + cb_buff->buffer.scan_mask); + chan++; + } + + return cb_buff; + +error_release_channels: + iio_channel_release_all(cb_buff->channels); +error_free_cb_buff: + kfree(cb_buff); +error_ret: + return ERR_PTR(ret); +} +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, + 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); +} +EXPORT_SYMBOL_GPL(iio_channel_stop_all_cb); + +void iio_channel_release_all_cb(struct iio_cb_buffer *cb_buff) +{ + iio_channel_release_all(cb_buff->channels); + kfree(cb_buff); +} +EXPORT_SYMBOL_GPL(iio_channel_release_all_cb); + +struct iio_channel +*iio_channel_cb_get_channels(const struct iio_cb_buffer *cb_buffer) +{ + return cb_buffer->channels; +} +EXPORT_SYMBOL_GPL(iio_channel_cb_get_channels); diff --git a/drivers/iio/common/hid-sensors/Kconfig b/drivers/iio/common/hid-sensors/Kconfig index 8e63d81d652a..ae10778da7aa 100644 --- a/drivers/iio/common/hid-sensors/Kconfig +++ b/drivers/iio/common/hid-sensors/Kconfig @@ -15,7 +15,7 @@ config HID_SENSOR_IIO_COMMON attributes. config HID_SENSOR_ENUM_BASE_QUIRKS - tristate "ENUM base quirks for HID Sensor IIO drivers" + bool "ENUM base quirks for HID Sensor IIO drivers" depends on HID_SENSOR_IIO_COMMON help Say yes here to build support for sensor hub FW using diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c index d4b790d18efb..d60198a6ca29 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c @@ -36,10 +36,8 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, int state_val; state_val = state ? 1 : 0; -#if (defined CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS) || \ - (defined CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS_MODULE) - ++state_val; -#endif + if (IS_ENABLED(CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS)) + ++state_val; st->data_ready = state; sensor_hub_set_feature(st->hsdev, st->power_state.report_id, st->power_state.index, diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index b1c0ee5294ca..f4a6f0838327 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -67,6 +67,16 @@ config AD5446 To compile this driver as a module, choose M here: the module will be called ad5446. +config AD5449 + tristate "Analog Device AD5449 and similar DACs driver" + depends on SPI_MASTER + help + Say yes here to build support for Analog Devices AD5415, AD5426, AD5429, + AD5432, AD5439, AD5443, AD5449 Digital to Analog Converters. + + To compile this driver as a module, choose M here: the + module will be called ad5449. + config AD5504 tristate "Analog Devices AD5504/AD5501 DAC SPI driver" depends on SPI @@ -122,7 +132,7 @@ config AD5686 config MAX517 tristate "Maxim MAX517/518/519 DAC driver" - depends on I2C && EXPERIMENTAL + depends on I2C help If you say yes here you get support for the Maxim chips MAX517, MAX518 and MAX519 (I2C 8-Bit DACs with rail-to-rail outputs). diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile index c0d333b23ba3..5b528ebb3343 100644 --- a/drivers/iio/dac/Makefile +++ b/drivers/iio/dac/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_AD5624R_SPI) += ad5624r_spi.o obj-$(CONFIG_AD5064) += ad5064.o obj-$(CONFIG_AD5504) += ad5504.o obj-$(CONFIG_AD5446) += ad5446.o +obj-$(CONFIG_AD5449) += ad5449.o obj-$(CONFIG_AD5755) += ad5755.o obj-$(CONFIG_AD5764) += ad5764.o obj-$(CONFIG_AD5791) += ad5791.o diff --git a/drivers/iio/dac/ad5449.c b/drivers/iio/dac/ad5449.c new file mode 100644 index 000000000000..0ee6f8eeba8d --- /dev/null +++ b/drivers/iio/dac/ad5449.c @@ -0,0 +1,376 @@ +/* + * AD5415, AD5426, AD5429, AD5432, AD5439, AD5443, AD5449 Digital to Analog + * Converter driver. + * + * Copyright 2012 Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + * + * Licensed under the GPL-2. + */ + +#include <linux/device.h> +#include <linux/err.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/spi/spi.h> +#include <linux/slab.h> +#include <linux/sysfs.h> +#include <linux/regulator/consumer.h> +#include <asm/unaligned.h> + +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> + +#include <linux/platform_data/ad5449.h> + +#define AD5449_MAX_CHANNELS 2 +#define AD5449_MAX_VREFS 2 + +#define AD5449_CMD_NOOP 0x0 +#define AD5449_CMD_LOAD_AND_UPDATE(x) (0x1 + (x) * 3) +#define AD5449_CMD_READ(x) (0x2 + (x) * 3) +#define AD5449_CMD_LOAD(x) (0x3 + (x) * 3) +#define AD5449_CMD_CTRL 13 + +#define AD5449_CTRL_SDO_OFFSET 10 +#define AD5449_CTRL_DAISY_CHAIN BIT(9) +#define AD5449_CTRL_HCLR_TO_MIDSCALE BIT(8) +#define AD5449_CTRL_SAMPLE_RISING BIT(7) + +/** + * struct ad5449_chip_info - chip specific information + * @channels: Channel specification + * @num_channels: Number of channels + * @has_ctrl: Chip has a control register + */ +struct ad5449_chip_info { + const struct iio_chan_spec *channels; + unsigned int num_channels; + bool has_ctrl; +}; + +/** + * struct ad5449 - driver instance specific data + * @spi: the SPI device for this driver instance + * @chip_info: chip model specific constants, available modes etc + * @vref_reg: vref supply regulators + * @has_sdo: whether the SDO line is connected + * @dac_cache: Cache for the DAC values + * @data: spi transfer buffers + */ +struct ad5449 { + struct spi_device *spi; + const struct ad5449_chip_info *chip_info; + struct regulator_bulk_data vref_reg[AD5449_MAX_VREFS]; + + bool has_sdo; + uint16_t dac_cache[AD5449_MAX_CHANNELS]; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + __be16 data[2] ____cacheline_aligned; +}; + +enum ad5449_type { + ID_AD5426, + ID_AD5429, + ID_AD5432, + ID_AD5439, + ID_AD5443, + ID_AD5449, +}; + +static int ad5449_write(struct iio_dev *indio_dev, unsigned int addr, + unsigned int val) +{ + struct ad5449 *st = iio_priv(indio_dev); + int ret; + + mutex_lock(&indio_dev->mlock); + st->data[0] = cpu_to_be16((addr << 12) | val); + ret = spi_write(st->spi, st->data, 2); + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static int ad5449_read(struct iio_dev *indio_dev, unsigned int addr, + unsigned int *val) +{ + struct ad5449 *st = iio_priv(indio_dev); + int ret; + struct spi_message msg; + struct spi_transfer t[] = { + { + .tx_buf = &st->data[0], + .len = 2, + .cs_change = 1, + }, { + .tx_buf = &st->data[1], + .rx_buf = &st->data[1], + .len = 2, + }, + }; + + spi_message_init(&msg); + spi_message_add_tail(&t[0], &msg); + spi_message_add_tail(&t[1], &msg); + + mutex_lock(&indio_dev->mlock); + st->data[0] = cpu_to_be16(addr << 12); + st->data[1] = cpu_to_be16(AD5449_CMD_NOOP); + + ret = spi_sync(st->spi, &msg); + if (ret < 0) + goto out_unlock; + + *val = be16_to_cpu(st->data[1]); + +out_unlock: + mutex_unlock(&indio_dev->mlock); + return ret; +} + +static int ad5449_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, int *val2, long info) +{ + struct ad5449 *st = iio_priv(indio_dev); + struct regulator_bulk_data *reg; + int scale_uv; + int ret; + + switch (info) { + case IIO_CHAN_INFO_RAW: + if (st->has_sdo) { + ret = ad5449_read(indio_dev, + AD5449_CMD_READ(chan->address), val); + if (ret) + return ret; + *val &= 0xfff; + } else { + *val = st->dac_cache[chan->address]; + } + + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + reg = &st->vref_reg[chan->channel]; + scale_uv = regulator_get_voltage(reg->consumer); + if (scale_uv < 0) + return scale_uv; + + *val = scale_uv / 1000; + *val2 = chan->scan_type.realbits; + + return IIO_VAL_FRACTIONAL_LOG2; + default: + break; + } + + return -EINVAL; +} + +static int ad5449_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, int val2, long info) +{ + struct ad5449 *st = iio_priv(indio_dev); + int ret; + + switch (info) { + case IIO_CHAN_INFO_RAW: + if (val < 0 || val >= (1 << chan->scan_type.realbits)) + return -EINVAL; + + ret = ad5449_write(indio_dev, + AD5449_CMD_LOAD_AND_UPDATE(chan->address), + val << chan->scan_type.shift); + if (ret == 0) + st->dac_cache[chan->address] = val; + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static const struct iio_info ad5449_info = { + .read_raw = ad5449_read_raw, + .write_raw = ad5449_write_raw, + .driver_module = THIS_MODULE, +}; + +#define AD5449_CHANNEL(chan, bits) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .output = 1, \ + .channel = (chan), \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ + .address = (chan), \ + .scan_type = IIO_ST('u', (bits), 16, 12 - (bits)), \ +} + +#define DECLARE_AD5449_CHANNELS(name, bits) \ +const struct iio_chan_spec name[] = { \ + AD5449_CHANNEL(0, bits), \ + AD5449_CHANNEL(1, bits), \ +} + +static DECLARE_AD5449_CHANNELS(ad5429_channels, 8); +static DECLARE_AD5449_CHANNELS(ad5439_channels, 10); +static DECLARE_AD5449_CHANNELS(ad5449_channels, 12); + +static const struct ad5449_chip_info ad5449_chip_info[] = { + [ID_AD5426] = { + .channels = ad5429_channels, + .num_channels = 1, + .has_ctrl = false, + }, + [ID_AD5429] = { + .channels = ad5429_channels, + .num_channels = 2, + .has_ctrl = true, + }, + [ID_AD5432] = { + .channels = ad5439_channels, + .num_channels = 1, + .has_ctrl = false, + }, + [ID_AD5439] = { + .channels = ad5439_channels, + .num_channels = 2, + .has_ctrl = true, + }, + [ID_AD5443] = { + .channels = ad5449_channels, + .num_channels = 1, + .has_ctrl = false, + }, + [ID_AD5449] = { + .channels = ad5449_channels, + .num_channels = 2, + .has_ctrl = true, + }, +}; + +static const char *ad5449_vref_name(struct ad5449 *st, int n) +{ + if (st->chip_info->num_channels == 1) + return "VREF"; + + if (n == 0) + return "VREFA"; + else + return "VREFB"; +} + +static int __devinit ad5449_spi_probe(struct spi_device *spi) +{ + struct ad5449_platform_data *pdata = spi->dev.platform_data; + const struct spi_device_id *id = spi_get_device_id(spi); + struct iio_dev *indio_dev; + struct ad5449 *st; + unsigned int i; + int ret; + + indio_dev = iio_device_alloc(sizeof(*st)); + if (indio_dev == NULL) + return -ENOMEM; + + st = iio_priv(indio_dev); + spi_set_drvdata(spi, indio_dev); + + st->chip_info = &ad5449_chip_info[id->driver_data]; + st->spi = spi; + + for (i = 0; i < st->chip_info->num_channels; ++i) + st->vref_reg[i].supply = ad5449_vref_name(st, i); + + ret = regulator_bulk_get(&spi->dev, st->chip_info->num_channels, + st->vref_reg); + if (ret) + goto error_free; + + ret = regulator_bulk_enable(st->chip_info->num_channels, st->vref_reg); + if (ret) + goto error_free_reg; + + indio_dev->dev.parent = &spi->dev; + indio_dev->name = id->name; + indio_dev->info = &ad5449_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = st->chip_info->channels; + indio_dev->num_channels = st->chip_info->num_channels; + + if (st->chip_info->has_ctrl) { + unsigned int ctrl = 0x00; + if (pdata) { + if (pdata->hardware_clear_to_midscale) + ctrl |= AD5449_CTRL_HCLR_TO_MIDSCALE; + ctrl |= pdata->sdo_mode << AD5449_CTRL_SDO_OFFSET; + st->has_sdo = pdata->sdo_mode != AD5449_SDO_DISABLED; + } else { + st->has_sdo = true; + } + ad5449_write(indio_dev, AD5449_CMD_CTRL, ctrl); + } + + ret = iio_device_register(indio_dev); + if (ret) + goto error_disable_reg; + + return 0; + +error_disable_reg: + regulator_bulk_disable(st->chip_info->num_channels, st->vref_reg); +error_free_reg: + regulator_bulk_free(st->chip_info->num_channels, st->vref_reg); +error_free: + iio_device_free(indio_dev); + + return ret; +} + +static int __devexit ad5449_spi_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct ad5449 *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + regulator_bulk_disable(st->chip_info->num_channels, st->vref_reg); + regulator_bulk_free(st->chip_info->num_channels, st->vref_reg); + + iio_device_free(indio_dev); + + return 0; +} + +static const struct spi_device_id ad5449_spi_ids[] = { + { "ad5415", ID_AD5449 }, + { "ad5426", ID_AD5426 }, + { "ad5429", ID_AD5429 }, + { "ad5432", ID_AD5432 }, + { "ad5439", ID_AD5439 }, + { "ad5443", ID_AD5443 }, + { "ad5449", ID_AD5449 }, + {} +}; +MODULE_DEVICE_TABLE(spi, ad5449_spi_ids); + +static struct spi_driver ad5449_spi_driver = { + .driver = { + .name = "ad5449", + .owner = THIS_MODULE, + }, + .probe = ad5449_spi_probe, + .remove = __devexit_p(ad5449_spi_remove), + .id_table = ad5449_spi_ids, +}; +module_spi_driver(ad5449_spi_driver); + +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); +MODULE_DESCRIPTION("Analog Devices AD5449 and similar DACs"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c index 6948d75e1036..bc92ff9309c2 100644 --- a/drivers/iio/dac/ad5686.c +++ b/drivers/iio/dac/ad5686.c @@ -188,7 +188,7 @@ static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev, if (ret) return ret; - if (readin == true) + if (readin) st->pwr_down_mask |= (0x3 << (chan->channel * 2)); else st->pwr_down_mask &= ~(0x3 << (chan->channel * 2)); diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig index 21e27e2fc68c..48ed1483ff27 100644 --- a/drivers/iio/gyro/Kconfig +++ b/drivers/iio/gyro/Kconfig @@ -3,6 +3,15 @@ # menu "Digital gyroscope sensors" +config ADIS16136 + tristate "Analog devices ADIS16136 and similar gyroscopes driver" + depends on SPI_MASTER + select IIO_ADIS_LIB + select IIO_ADIS_LIB_BUFFER if IIO_BUFFER + help + Say yes here to build support for the Analog Devices ADIS16133, ADIS16135, + ADIS16136 gyroscope devices. + config HID_SENSOR_GYRO_3D depends on HID_SENSOR_HUB select IIO_BUFFER diff --git a/drivers/iio/gyro/Makefile b/drivers/iio/gyro/Makefile index 8a895d9fcbce..702a058907e3 100644 --- a/drivers/iio/gyro/Makefile +++ b/drivers/iio/gyro/Makefile @@ -2,4 +2,5 @@ # Makefile for industrial I/O gyroscope sensor drivers # +obj-$(CONFIG_ADIS16136) += adis16136.o obj-$(CONFIG_HID_SENSOR_GYRO_3D) += hid-sensor-gyro-3d.o diff --git a/drivers/iio/gyro/adis16136.c b/drivers/iio/gyro/adis16136.c new file mode 100644 index 000000000000..8cb0bcbfd609 --- /dev/null +++ b/drivers/iio/gyro/adis16136.c @@ -0,0 +1,580 @@ +/* + * ADIS16133/ADIS16135/ADIS16136 gyroscope driver + * + * Copyright 2012 Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + * + * Licensed under the GPL-2. + */ + +#include <linux/interrupt.h> +#include <linux/delay.h> +#include <linux/mutex.h> +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/spi/spi.h> +#include <linux/slab.h> +#include <linux/sysfs.h> +#include <linux/module.h> + +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/buffer.h> +#include <linux/iio/imu/adis.h> + +#include <linux/debugfs.h> + +#define ADIS16136_REG_FLASH_CNT 0x00 +#define ADIS16136_REG_TEMP_OUT 0x02 +#define ADIS16136_REG_GYRO_OUT2 0x04 +#define ADIS16136_REG_GYRO_OUT 0x06 +#define ADIS16136_REG_GYRO_OFF2 0x08 +#define ADIS16136_REG_GYRO_OFF 0x0A +#define ADIS16136_REG_ALM_MAG1 0x10 +#define ADIS16136_REG_ALM_MAG2 0x12 +#define ADIS16136_REG_ALM_SAMPL1 0x14 +#define ADIS16136_REG_ALM_SAMPL2 0x16 +#define ADIS16136_REG_ALM_CTRL 0x18 +#define ADIS16136_REG_GPIO_CTRL 0x1A +#define ADIS16136_REG_MSC_CTRL 0x1C +#define ADIS16136_REG_SMPL_PRD 0x1E +#define ADIS16136_REG_AVG_CNT 0x20 +#define ADIS16136_REG_DEC_RATE 0x22 +#define ADIS16136_REG_SLP_CTRL 0x24 +#define ADIS16136_REG_DIAG_STAT 0x26 +#define ADIS16136_REG_GLOB_CMD 0x28 +#define ADIS16136_REG_LOT1 0x32 +#define ADIS16136_REG_LOT2 0x34 +#define ADIS16136_REG_LOT3 0x36 +#define ADIS16136_REG_PROD_ID 0x38 +#define ADIS16136_REG_SERIAL_NUM 0x3A + +#define ADIS16136_DIAG_STAT_FLASH_UPDATE_FAIL 2 +#define ADIS16136_DIAG_STAT_SPI_FAIL 3 +#define ADIS16136_DIAG_STAT_SELF_TEST_FAIL 5 +#define ADIS16136_DIAG_STAT_FLASH_CHKSUM_FAIL 6 + +#define ADIS16136_MSC_CTRL_MEMORY_TEST BIT(11) +#define ADIS16136_MSC_CTRL_SELF_TEST BIT(10) + +struct adis16136_chip_info { + unsigned int precision; + unsigned int fullscale; +}; + +struct adis16136 { + const struct adis16136_chip_info *chip_info; + + struct adis adis; +}; + +#ifdef CONFIG_DEBUG_FS + +static ssize_t adis16136_show_serial(struct file *file, + char __user *userbuf, size_t count, loff_t *ppos) +{ + struct adis16136 *adis16136 = file->private_data; + uint16_t lot1, lot2, lot3, serial; + char buf[20]; + size_t len; + int ret; + + ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_SERIAL_NUM, + &serial); + if (ret < 0) + return ret; + + ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_LOT1, &lot1); + if (ret < 0) + return ret; + + ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_LOT2, &lot2); + if (ret < 0) + return ret; + + ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_LOT3, &lot3); + if (ret < 0) + return ret; + + len = snprintf(buf, sizeof(buf), "%.4x%.4x%.4x-%.4x\n", lot1, lot2, + lot3, serial); + + return simple_read_from_buffer(userbuf, count, ppos, buf, len); +} + +static const struct file_operations adis16136_serial_fops = { + .open = simple_open, + .read = adis16136_show_serial, + .llseek = default_llseek, + .owner = THIS_MODULE, +}; + +static int adis16136_show_product_id(void *arg, u64 *val) +{ + struct adis16136 *adis16136 = arg; + u16 prod_id; + int ret; + + ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_PROD_ID, + &prod_id); + if (ret < 0) + return ret; + + *val = prod_id; + + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(adis16136_product_id_fops, + adis16136_show_product_id, NULL, "%llu\n"); + +static int adis16136_show_flash_count(void *arg, u64 *val) +{ + struct adis16136 *adis16136 = arg; + uint16_t flash_count; + int ret; + + ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_FLASH_CNT, + &flash_count); + if (ret < 0) + return ret; + + *val = flash_count; + + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(adis16136_flash_count_fops, + adis16136_show_flash_count, NULL, "%lld\n"); + +static int adis16136_debugfs_init(struct iio_dev *indio_dev) +{ + struct adis16136 *adis16136 = iio_priv(indio_dev); + + debugfs_create_file("serial_number", 0400, indio_dev->debugfs_dentry, + adis16136, &adis16136_serial_fops); + debugfs_create_file("product_id", 0400, indio_dev->debugfs_dentry, + adis16136, &adis16136_product_id_fops); + debugfs_create_file("flash_count", 0400, indio_dev->debugfs_dentry, + adis16136, &adis16136_flash_count_fops); + + return 0; +} + +#else + +static int adis16136_debugfs_init(struct iio_dev *indio_dev) +{ + return 0; +} + +#endif + +static int adis16136_set_freq(struct adis16136 *adis16136, unsigned int freq) +{ + unsigned int t; + + t = 32768 / freq; + if (t < 0xf) + t = 0xf; + else if (t > 0xffff) + t = 0xffff; + else + t--; + + return adis_write_reg_16(&adis16136->adis, ADIS16136_REG_SMPL_PRD, t); +} + +static int adis16136_get_freq(struct adis16136 *adis16136, unsigned int *freq) +{ + uint16_t t; + int ret; + + ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_SMPL_PRD, &t); + if (ret < 0) + return ret; + + *freq = 32768 / (t + 1); + + return 0; +} + +static ssize_t adis16136_write_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 adis16136 *adis16136 = iio_priv(indio_dev); + unsigned int val; + int ret; + + ret = kstrtouint(buf, 10, &val); + if (ret) + return ret; + + if (val == 0) + return -EINVAL; + + ret = adis16136_set_freq(adis16136, val); + + return ret ? ret : len; +} + +static ssize_t adis16136_read_frequency(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct adis16136 *adis16136 = iio_priv(indio_dev); + unsigned int freq; + int ret; + + ret = adis16136_get_freq(adis16136, &freq); + if (ret < 0) + return ret; + + return sprintf(buf, "%d\n", freq); +} + +static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, + adis16136_read_frequency, + adis16136_write_frequency); + +static const unsigned adis16136_3db_divisors[] = { + [0] = 2, /* Special case */ + [1] = 6, + [2] = 12, + [3] = 25, + [4] = 50, + [5] = 100, + [6] = 200, + [7] = 200, /* Not a valid setting */ +}; + +static int adis16136_set_filter(struct iio_dev *indio_dev, int val) +{ + struct adis16136 *adis16136 = iio_priv(indio_dev); + unsigned int freq; + int i, ret; + + ret = adis16136_get_freq(adis16136, &freq); + if (ret < 0) + return ret; + + for (i = ARRAY_SIZE(adis16136_3db_divisors) - 1; i >= 1; i--) { + if (freq / adis16136_3db_divisors[i] >= val) + break; + } + + return adis_write_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, i); +} + +static int adis16136_get_filter(struct iio_dev *indio_dev, int *val) +{ + struct adis16136 *adis16136 = iio_priv(indio_dev); + unsigned int freq; + uint16_t val16; + int ret; + + mutex_lock(&indio_dev->mlock); + + ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, &val16); + if (ret < 0) + goto err_unlock; + + ret = adis16136_get_freq(adis16136, &freq); + if (ret < 0) + goto err_unlock; + + *val = freq / adis16136_3db_divisors[val16 & 0x07]; + +err_unlock: + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : IIO_VAL_INT; +} + +static int adis16136_read_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, int *val, int *val2, long info) +{ + struct adis16136 *adis16136 = iio_priv(indio_dev); + uint32_t val32; + int ret; + + switch (info) { + case IIO_CHAN_INFO_RAW: + return adis_single_conversion(indio_dev, chan, 0, val); + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ANGL_VEL: + *val = adis16136->chip_info->precision; + *val2 = (adis16136->chip_info->fullscale << 16); + return IIO_VAL_FRACTIONAL; + case IIO_TEMP: + *val = 10; + *val2 = 697000; /* 0.010697 degree Celsius */ + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_CALIBBIAS: + ret = adis_read_reg_32(&adis16136->adis, + ADIS16136_REG_GYRO_OFF2, &val32); + if (ret < 0) + return ret; + + *val = sign_extend32(val32, 31); + + return IIO_VAL_INT; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + return adis16136_get_filter(indio_dev, val); + default: + return -EINVAL; + } +} + +static int adis16136_write_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, int val, int val2, long info) +{ + struct adis16136 *adis16136 = iio_priv(indio_dev); + + switch (info) { + case IIO_CHAN_INFO_CALIBBIAS: + return adis_write_reg_32(&adis16136->adis, + ADIS16136_REG_GYRO_OFF2, val); + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + return adis16136_set_filter(indio_dev, val); + default: + break; + } + + return -EINVAL; +} + +enum { + ADIS16136_SCAN_GYRO, + ADIS16136_SCAN_TEMP, +}; + +static const struct iio_chan_spec adis16136_channels[] = { + { + .type = IIO_ANGL_VEL, + .modified = 1, + .channel2 = IIO_MOD_X, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT | + IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT, + .address = ADIS16136_REG_GYRO_OUT2, + .scan_index = ADIS16136_SCAN_GYRO, + .scan_type = { + .sign = 's', + .realbits = 32, + .storagebits = 32, + .endianness = IIO_BE, + }, + }, { + .type = IIO_TEMP, + .indexed = 1, + .channel = 0, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, + .address = ADIS16136_REG_TEMP_OUT, + .scan_index = ADIS16136_SCAN_TEMP, + .scan_type = { + .sign = 's', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_BE, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(2), +}; + +static struct attribute *adis16136_attributes[] = { + &iio_dev_attr_sampling_frequency.dev_attr.attr, + NULL +}; + +static const struct attribute_group adis16136_attribute_group = { + .attrs = adis16136_attributes, +}; + +static const struct iio_info adis16136_info = { + .driver_module = THIS_MODULE, + .attrs = &adis16136_attribute_group, + .read_raw = &adis16136_read_raw, + .write_raw = &adis16136_write_raw, + .update_scan_mode = adis_update_scan_mode, + .debugfs_reg_access = adis_debugfs_reg_access, +}; + +static int adis16136_stop_device(struct iio_dev *indio_dev) +{ + struct adis16136 *adis16136 = iio_priv(indio_dev); + int ret; + + ret = adis_write_reg_16(&adis16136->adis, ADIS16136_REG_SLP_CTRL, 0xff); + if (ret) + dev_err(&indio_dev->dev, + "Could not power down device: %d\n", ret); + + return ret; +} + +static int adis16136_initial_setup(struct iio_dev *indio_dev) +{ + struct adis16136 *adis16136 = iio_priv(indio_dev); + unsigned int device_id; + uint16_t prod_id; + int ret; + + ret = adis_initial_startup(&adis16136->adis); + if (ret) + return ret; + + ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_PROD_ID, + &prod_id); + if (ret) + return ret; + + sscanf(indio_dev->name, "adis%u\n", &device_id); + + if (prod_id != device_id) + dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.", + device_id, prod_id); + + return 0; +} + +static const char * const adis16136_status_error_msgs[] = { + [ADIS16136_DIAG_STAT_FLASH_UPDATE_FAIL] = "Flash update failed", + [ADIS16136_DIAG_STAT_SPI_FAIL] = "SPI failure", + [ADIS16136_DIAG_STAT_SELF_TEST_FAIL] = "Self test error", + [ADIS16136_DIAG_STAT_FLASH_CHKSUM_FAIL] = "Flash checksum error", +}; + +static const struct adis_data adis16136_data = { + .diag_stat_reg = ADIS16136_REG_DIAG_STAT, + .glob_cmd_reg = ADIS16136_REG_GLOB_CMD, + .msc_ctrl_reg = ADIS16136_REG_MSC_CTRL, + + .self_test_mask = ADIS16136_MSC_CTRL_SELF_TEST, + .startup_delay = 80, + + .read_delay = 10, + .write_delay = 10, + + .status_error_msgs = adis16136_status_error_msgs, + .status_error_mask = BIT(ADIS16136_DIAG_STAT_FLASH_UPDATE_FAIL) | + BIT(ADIS16136_DIAG_STAT_SPI_FAIL) | + BIT(ADIS16136_DIAG_STAT_SELF_TEST_FAIL) | + BIT(ADIS16136_DIAG_STAT_FLASH_CHKSUM_FAIL), +}; + +enum adis16136_id { + ID_ADIS16133, + ID_ADIS16135, + ID_ADIS16136, +}; + +static const struct adis16136_chip_info adis16136_chip_info[] = { + [ID_ADIS16133] = { + .precision = IIO_DEGREE_TO_RAD(1200), + .fullscale = 24000, + }, + [ID_ADIS16135] = { + .precision = IIO_DEGREE_TO_RAD(300), + .fullscale = 24000, + }, + [ID_ADIS16136] = { + .precision = IIO_DEGREE_TO_RAD(450), + .fullscale = 24623, + }, +}; + +static int adis16136_probe(struct spi_device *spi) +{ + const struct spi_device_id *id = spi_get_device_id(spi); + struct adis16136 *adis16136; + struct iio_dev *indio_dev; + int ret; + + indio_dev = iio_device_alloc(sizeof(*adis16136)); + if (indio_dev == NULL) + return -ENOMEM; + + spi_set_drvdata(spi, indio_dev); + + adis16136 = iio_priv(indio_dev); + + adis16136->chip_info = &adis16136_chip_info[id->driver_data]; + indio_dev->dev.parent = &spi->dev; + indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->channels = adis16136_channels; + indio_dev->num_channels = ARRAY_SIZE(adis16136_channels); + indio_dev->info = &adis16136_info; + indio_dev->modes = INDIO_DIRECT_MODE; + + ret = adis_init(&adis16136->adis, indio_dev, spi, &adis16136_data); + if (ret) + goto error_free_dev; + + ret = adis_setup_buffer_and_trigger(&adis16136->adis, indio_dev, NULL); + if (ret) + goto error_free_dev; + + ret = adis16136_initial_setup(indio_dev); + if (ret) + goto error_cleanup_buffer; + + ret = iio_device_register(indio_dev); + if (ret) + goto error_stop_device; + + adis16136_debugfs_init(indio_dev); + + return 0; + +error_stop_device: + adis16136_stop_device(indio_dev); +error_cleanup_buffer: + adis_cleanup_buffer_and_trigger(&adis16136->adis, indio_dev); +error_free_dev: + iio_device_free(indio_dev); + return ret; +} + +static int adis16136_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct adis16136 *adis16136 = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + adis16136_stop_device(indio_dev); + + adis_cleanup_buffer_and_trigger(&adis16136->adis, indio_dev); + + iio_device_free(indio_dev); + + return 0; +} + +static const struct spi_device_id adis16136_ids[] = { + { "adis16133", ID_ADIS16133 }, + { "adis16135", ID_ADIS16135 }, + { "adis16136", ID_ADIS16136 }, + { } +}; +MODULE_DEVICE_TABLE(spi, adis16136_ids); + +static struct spi_driver adis16136_driver = { + .driver = { + .name = "adis16136", + .owner = THIS_MODULE, + }, + .id_table = adis16136_ids, + .probe = adis16136_probe, + .remove = adis16136_remove, +}; +module_spi_driver(adis16136_driver); + +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); +MODULE_DESCRIPTION("Analog Devices ADIS16133/ADIS16135/ADIS16136 gyroscope driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c index 4c56ada51c39..4c8b158e40e1 100644 --- a/drivers/iio/gyro/hid-sensor-gyro-3d.c +++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c @@ -197,21 +197,8 @@ static const struct iio_info gyro_3d_info = { /* Function to push data to buffer */ static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len) { - struct iio_buffer *buffer = indio_dev->buffer; - int datum_sz; - dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n"); - if (!buffer) { - dev_err(&indio_dev->dev, "Buffer == NULL\n"); - return; - } - datum_sz = buffer->access->get_bytes_per_datum(buffer); - if (len > datum_sz) { - dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len, - datum_sz); - return; - } - iio_push_to_buffer(buffer, (u8 *)data); + iio_push_to_buffers(indio_dev, (u8 *)data); } /* Callback handler to send event after all samples are received and captured */ @@ -319,10 +306,10 @@ static int __devinit hid_gyro_3d_probe(struct platform_device *pdev) goto error_free_dev; } - channels = kmemdup(gyro_3d_channels, - sizeof(gyro_3d_channels), - GFP_KERNEL); + channels = kmemdup(gyro_3d_channels, sizeof(gyro_3d_channels), + GFP_KERNEL); if (!channels) { + ret = -ENOMEM; dev_err(&pdev->dev, "failed to duplicate channels\n"); goto error_free_dev; } diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig new file mode 100644 index 000000000000..3d79a40e916b --- /dev/null +++ b/drivers/iio/imu/Kconfig @@ -0,0 +1,27 @@ +# +# IIO imu drivers configuration +# +menu "Inertial measurement units" + +config ADIS16480 + tristate "Analog Devices ADIS16480 and similar IMU driver" + depends on SPI + select IIO_ADIS_LIB + select IIO_ADIS_LIB_BUFFER if IIO_BUFFER + help + Say yes here to build support for Analog Devices ADIS16375, ADIS16480, + ADIS16485, ADIS16488 inertial sensors. + +endmenu + +config IIO_ADIS_LIB + tristate + help + A set of IO helper functions for the Analog Devices ADIS* device family. + +config IIO_ADIS_LIB_BUFFER + bool + select IIO_TRIGGERED_BUFFER + help + A set of buffer helper functions for the Analog Devices ADIS* device + family. diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile new file mode 100644 index 000000000000..cfe57638f6f9 --- /dev/null +++ b/drivers/iio/imu/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for Inertial Measurement Units +# + +obj-$(CONFIG_ADIS16480) += adis16480.o + +adis_lib-y += adis.o +adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_trigger.o +adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o +obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c new file mode 100644 index 000000000000..911255d41c1a --- /dev/null +++ b/drivers/iio/imu/adis.c @@ -0,0 +1,440 @@ +/* + * Common library for ADIS16XXX devices + * + * Copyright 2012 Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + * + * Licensed under the GPL-2 or later. + */ + +#include <linux/delay.h> +#include <linux/mutex.h> +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/spi/spi.h> +#include <linux/slab.h> +#include <linux/sysfs.h> +#include <linux/module.h> +#include <asm/unaligned.h> + +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/buffer.h> +#include <linux/iio/imu/adis.h> + +#define ADIS_MSC_CTRL_DATA_RDY_EN BIT(2) +#define ADIS_MSC_CTRL_DATA_RDY_POL_HIGH BIT(1) +#define ADIS_MSC_CTRL_DATA_RDY_DIO2 BIT(0) +#define ADIS_GLOB_CMD_SW_RESET BIT(7) + +int adis_write_reg(struct adis *adis, unsigned int reg, + unsigned int value, unsigned int size) +{ + unsigned int page = reg / ADIS_PAGE_SIZE; + int ret, i; + struct spi_message msg; + struct spi_transfer xfers[] = { + { + .tx_buf = adis->tx, + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + .delay_usecs = adis->data->write_delay, + }, { + .tx_buf = adis->tx + 2, + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + .delay_usecs = adis->data->write_delay, + }, { + .tx_buf = adis->tx + 4, + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + .delay_usecs = adis->data->write_delay, + }, { + .tx_buf = adis->tx + 6, + .bits_per_word = 8, + .len = 2, + .delay_usecs = adis->data->write_delay, + }, { + .tx_buf = adis->tx + 8, + .bits_per_word = 8, + .len = 2, + .delay_usecs = adis->data->write_delay, + }, + }; + + mutex_lock(&adis->txrx_lock); + + spi_message_init(&msg); + + if (adis->current_page != page) { + adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID); + adis->tx[1] = page; + spi_message_add_tail(&xfers[0], &msg); + } + + switch (size) { + case 4: + adis->tx[8] = ADIS_WRITE_REG(reg + 3); + adis->tx[9] = (value >> 24) & 0xff; + adis->tx[6] = ADIS_WRITE_REG(reg + 2); + adis->tx[7] = (value >> 16) & 0xff; + case 2: + adis->tx[4] = ADIS_WRITE_REG(reg + 1); + adis->tx[5] = (value >> 8) & 0xff; + case 1: + adis->tx[2] = ADIS_WRITE_REG(reg); + adis->tx[3] = value & 0xff; + break; + default: + ret = -EINVAL; + goto out_unlock; + } + + xfers[size].cs_change = 0; + + for (i = 1; i <= size; i++) + spi_message_add_tail(&xfers[i], &msg); + + ret = spi_sync(adis->spi, &msg); + if (ret) { + dev_err(&adis->spi->dev, "Failed to write register 0x%02X: %d\n", + reg, ret); + } else { + adis->current_page = page; + } + +out_unlock: + mutex_unlock(&adis->txrx_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(adis_write_reg); + +/** + * adis_read_reg() - read 2 bytes from a 16-bit register + * @adis: The adis device + * @reg: The address of the lower of the two registers + * @val: The value read back from the device + */ +int adis_read_reg(struct adis *adis, unsigned int reg, + unsigned int *val, unsigned int size) +{ + unsigned int page = reg / ADIS_PAGE_SIZE; + struct spi_message msg; + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = adis->tx, + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + .delay_usecs = adis->data->write_delay, + }, { + .tx_buf = adis->tx + 2, + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + .delay_usecs = adis->data->read_delay, + }, { + .tx_buf = adis->tx + 4, + .rx_buf = adis->rx, + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + .delay_usecs = adis->data->read_delay, + }, { + .rx_buf = adis->rx + 2, + .bits_per_word = 8, + .len = 2, + .delay_usecs = adis->data->read_delay, + }, + }; + + mutex_lock(&adis->txrx_lock); + spi_message_init(&msg); + + if (adis->current_page != page) { + adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID); + adis->tx[1] = page; + spi_message_add_tail(&xfers[0], &msg); + } + + switch (size) { + case 4: + adis->tx[2] = ADIS_READ_REG(reg + 2); + adis->tx[3] = 0; + spi_message_add_tail(&xfers[1], &msg); + case 2: + adis->tx[4] = ADIS_READ_REG(reg); + adis->tx[5] = 0; + spi_message_add_tail(&xfers[2], &msg); + spi_message_add_tail(&xfers[3], &msg); + break; + default: + ret = -EINVAL; + goto out_unlock; + } + + ret = spi_sync(adis->spi, &msg); + if (ret) { + dev_err(&adis->spi->dev, "Failed to read register 0x%02X: %d\n", + reg, ret); + goto out_unlock; + } else { + adis->current_page = page; + } + + switch (size) { + case 4: + *val = get_unaligned_be32(adis->rx); + break; + case 2: + *val = get_unaligned_be16(adis->rx + 2); + break; + } + +out_unlock: + mutex_unlock(&adis->txrx_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(adis_read_reg); + +#ifdef CONFIG_DEBUG_FS + +int adis_debugfs_reg_access(struct iio_dev *indio_dev, + unsigned int reg, unsigned int writeval, unsigned int *readval) +{ + struct adis *adis = iio_device_get_drvdata(indio_dev); + + if (readval) { + uint16_t val16; + int ret; + + ret = adis_read_reg_16(adis, reg, &val16); + *readval = val16; + + return ret; + } else { + return adis_write_reg_16(adis, reg, writeval); + } +} +EXPORT_SYMBOL(adis_debugfs_reg_access); + +#endif + +/** + * adis_enable_irq() - Enable or disable data ready IRQ + * @adis: The adis device + * @enable: Whether to enable the IRQ + * + * Returns 0 on success, negative error code otherwise + */ +int adis_enable_irq(struct adis *adis, bool enable) +{ + int ret = 0; + uint16_t msc; + + if (adis->data->enable_irq) + return adis->data->enable_irq(adis, enable); + + ret = adis_read_reg_16(adis, adis->data->msc_ctrl_reg, &msc); + if (ret) + goto error_ret; + + msc |= ADIS_MSC_CTRL_DATA_RDY_POL_HIGH; + msc &= ~ADIS_MSC_CTRL_DATA_RDY_DIO2; + if (enable) + msc |= ADIS_MSC_CTRL_DATA_RDY_EN; + else + msc &= ~ADIS_MSC_CTRL_DATA_RDY_EN; + + ret = adis_write_reg_16(adis, adis->data->msc_ctrl_reg, msc); + +error_ret: + return ret; +} +EXPORT_SYMBOL(adis_enable_irq); + +/** + * adis_check_status() - Check the device for error conditions + * @adis: The adis device + * + * Returns 0 on success, a negative error code otherwise + */ +int adis_check_status(struct adis *adis) +{ + uint16_t status; + int ret; + int i; + + ret = adis_read_reg_16(adis, adis->data->diag_stat_reg, &status); + if (ret < 0) + return ret; + + status &= adis->data->status_error_mask; + + if (status == 0) + return 0; + + for (i = 0; i < 16; ++i) { + if (status & BIT(i)) { + dev_err(&adis->spi->dev, "%s.\n", + adis->data->status_error_msgs[i]); + } + } + + return -EIO; +} +EXPORT_SYMBOL_GPL(adis_check_status); + +/** + * adis_reset() - Reset the device + * @adis: The adis device + * + * Returns 0 on success, a negative error code otherwise + */ +int adis_reset(struct adis *adis) +{ + int ret; + + ret = adis_write_reg_8(adis, adis->data->glob_cmd_reg, + ADIS_GLOB_CMD_SW_RESET); + if (ret) + dev_err(&adis->spi->dev, "Failed to reset device: %d\n", ret); + + return ret; +} +EXPORT_SYMBOL_GPL(adis_reset); + +static int adis_self_test(struct adis *adis) +{ + int ret; + + ret = adis_write_reg_16(adis, adis->data->msc_ctrl_reg, + adis->data->self_test_mask); + if (ret) { + dev_err(&adis->spi->dev, "Failed to initiate self test: %d\n", + ret); + return ret; + } + + msleep(adis->data->startup_delay); + + return adis_check_status(adis); +} + +/** + * adis_inital_startup() - Performs device self-test + * @adis: The adis device + * + * Returns 0 if the device is operational, a negative error code otherwise. + * + * This function should be called early on in the device initialization sequence + * to ensure that the device is in a sane and known state and that it is usable. + */ +int adis_initial_startup(struct adis *adis) +{ + int ret; + + ret = adis_self_test(adis); + if (ret) { + dev_err(&adis->spi->dev, "Self-test failed, trying reset.\n"); + adis_reset(adis); + msleep(adis->data->startup_delay); + ret = adis_self_test(adis); + if (ret) { + dev_err(&adis->spi->dev, "Second self-test failed, giving up.\n"); + return ret; + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(adis_initial_startup); + +/** + * adis_single_conversion() - Performs a single sample conversion + * @indio_dev: The IIO device + * @chan: The IIO channel + * @error_mask: Mask for the error bit + * @val: Result of the conversion + * + * Returns IIO_VAL_INT on success, a negative error code otherwise. + * + * The function performs a single conversion on a given channel and post + * processes the value accordingly to the channel spec. If a error_mask is given + * the function will check if the mask is set in the returned raw value. If it + * is set the function will perform a self-check. If the device does not report + * a error bit in the channels raw value set error_mask to 0. + */ +int adis_single_conversion(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, unsigned int error_mask, int *val) +{ + struct adis *adis = iio_device_get_drvdata(indio_dev); + unsigned int uval; + int ret; + + mutex_lock(&indio_dev->mlock); + + ret = adis_read_reg(adis, chan->address, &uval, + chan->scan_type.storagebits / 8); + if (ret) + goto err_unlock; + + if (uval & error_mask) { + ret = adis_check_status(adis); + if (ret) + goto err_unlock; + } + + if (chan->scan_type.sign == 's') + *val = sign_extend32(uval, chan->scan_type.realbits - 1); + else + *val = uval & ((1 << chan->scan_type.realbits) - 1); + + ret = IIO_VAL_INT; +err_unlock: + mutex_unlock(&indio_dev->mlock); + return ret; +} +EXPORT_SYMBOL_GPL(adis_single_conversion); + +/** + * adis_init() - Initialize adis device structure + * @adis: The adis device + * @indio_dev: The iio device + * @spi: The spi device + * @data: Chip specific data + * + * Returns 0 on success, a negative error code otherwise. + * + * This function must be called, before any other adis helper function may be + * called. + */ +int adis_init(struct adis *adis, struct iio_dev *indio_dev, + struct spi_device *spi, const struct adis_data *data) +{ + mutex_init(&adis->txrx_lock); + adis->spi = spi; + adis->data = data; + iio_device_set_drvdata(indio_dev, adis); + + if (data->has_paging) { + /* Need to set the page before first read/write */ + adis->current_page = -1; + } else { + /* Page will always be 0 */ + adis->current_page = 0; + } + + return adis_enable_irq(adis, false); +} +EXPORT_SYMBOL_GPL(adis_init); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); +MODULE_DESCRIPTION("Common library code for ADIS16XXX devices"); diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c new file mode 100644 index 000000000000..8c26a5f7cd5d --- /dev/null +++ b/drivers/iio/imu/adis16480.c @@ -0,0 +1,924 @@ +/* + * ADIS16480 and similar IMUs driver + * + * Copyright 2012 Analog Devices Inc. + * + * 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/interrupt.h> +#include <linux/delay.h> +#include <linux/mutex.h> +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/spi/spi.h> +#include <linux/slab.h> +#include <linux/sysfs.h> +#include <linux/module.h> + +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/buffer.h> +#include <linux/iio/imu/adis.h> + +#include <linux/debugfs.h> + +#define ADIS16480_PAGE_SIZE 0x80 + +#define ADIS16480_REG(page, reg) ((page) * ADIS16480_PAGE_SIZE + (reg)) + +#define ADIS16480_REG_PAGE_ID 0x00 /* Same address on each page */ +#define ADIS16480_REG_SEQ_CNT ADIS16480_REG(0x00, 0x06) +#define ADIS16480_REG_SYS_E_FLA ADIS16480_REG(0x00, 0x08) +#define ADIS16480_REG_DIAG_STS ADIS16480_REG(0x00, 0x0A) +#define ADIS16480_REG_ALM_STS ADIS16480_REG(0x00, 0x0C) +#define ADIS16480_REG_TEMP_OUT ADIS16480_REG(0x00, 0x0E) +#define ADIS16480_REG_X_GYRO_OUT ADIS16480_REG(0x00, 0x10) +#define ADIS16480_REG_Y_GYRO_OUT ADIS16480_REG(0x00, 0x14) +#define ADIS16480_REG_Z_GYRO_OUT ADIS16480_REG(0x00, 0x18) +#define ADIS16480_REG_X_ACCEL_OUT ADIS16480_REG(0x00, 0x1C) +#define ADIS16480_REG_Y_ACCEL_OUT ADIS16480_REG(0x00, 0x20) +#define ADIS16480_REG_Z_ACCEL_OUT ADIS16480_REG(0x00, 0x24) +#define ADIS16480_REG_X_MAGN_OUT ADIS16480_REG(0x00, 0x28) +#define ADIS16480_REG_Y_MAGN_OUT ADIS16480_REG(0x00, 0x2A) +#define ADIS16480_REG_Z_MAGN_OUT ADIS16480_REG(0x00, 0x2C) +#define ADIS16480_REG_BAROM_OUT ADIS16480_REG(0x00, 0x2E) +#define ADIS16480_REG_X_DELTAANG_OUT ADIS16480_REG(0x00, 0x40) +#define ADIS16480_REG_Y_DELTAANG_OUT ADIS16480_REG(0x00, 0x44) +#define ADIS16480_REG_Z_DELTAANG_OUT ADIS16480_REG(0x00, 0x48) +#define ADIS16480_REG_X_DELTAVEL_OUT ADIS16480_REG(0x00, 0x4C) +#define ADIS16480_REG_Y_DELTAVEL_OUT ADIS16480_REG(0x00, 0x50) +#define ADIS16480_REG_Z_DELTAVEL_OUT ADIS16480_REG(0x00, 0x54) +#define ADIS16480_REG_PROD_ID ADIS16480_REG(0x00, 0x7E) + +#define ADIS16480_REG_X_GYRO_SCALE ADIS16480_REG(0x02, 0x04) +#define ADIS16480_REG_Y_GYRO_SCALE ADIS16480_REG(0x02, 0x06) +#define ADIS16480_REG_Z_GYRO_SCALE ADIS16480_REG(0x02, 0x08) +#define ADIS16480_REG_X_ACCEL_SCALE ADIS16480_REG(0x02, 0x0A) +#define ADIS16480_REG_Y_ACCEL_SCALE ADIS16480_REG(0x02, 0x0C) +#define ADIS16480_REG_Z_ACCEL_SCALE ADIS16480_REG(0x02, 0x0E) +#define ADIS16480_REG_X_GYRO_BIAS ADIS16480_REG(0x02, 0x10) +#define ADIS16480_REG_Y_GYRO_BIAS ADIS16480_REG(0x02, 0x14) +#define ADIS16480_REG_Z_GYRO_BIAS ADIS16480_REG(0x02, 0x18) +#define ADIS16480_REG_X_ACCEL_BIAS ADIS16480_REG(0x02, 0x1C) +#define ADIS16480_REG_Y_ACCEL_BIAS ADIS16480_REG(0x02, 0x20) +#define ADIS16480_REG_Z_ACCEL_BIAS ADIS16480_REG(0x02, 0x24) +#define ADIS16480_REG_X_HARD_IRON ADIS16480_REG(0x02, 0x28) +#define ADIS16480_REG_Y_HARD_IRON ADIS16480_REG(0x02, 0x2A) +#define ADIS16480_REG_Z_HARD_IRON ADIS16480_REG(0x02, 0x2C) +#define ADIS16480_REG_BAROM_BIAS ADIS16480_REG(0x02, 0x40) +#define ADIS16480_REG_FLASH_CNT ADIS16480_REG(0x02, 0x7C) + +#define ADIS16480_REG_GLOB_CMD ADIS16480_REG(0x03, 0x02) +#define ADIS16480_REG_FNCTIO_CTRL ADIS16480_REG(0x03, 0x06) +#define ADIS16480_REG_GPIO_CTRL ADIS16480_REG(0x03, 0x08) +#define ADIS16480_REG_CONFIG ADIS16480_REG(0x03, 0x0A) +#define ADIS16480_REG_DEC_RATE ADIS16480_REG(0x03, 0x0C) +#define ADIS16480_REG_SLP_CNT ADIS16480_REG(0x03, 0x10) +#define ADIS16480_REG_FILTER_BNK0 ADIS16480_REG(0x03, 0x16) +#define ADIS16480_REG_FILTER_BNK1 ADIS16480_REG(0x03, 0x18) +#define ADIS16480_REG_ALM_CNFG0 ADIS16480_REG(0x03, 0x20) +#define ADIS16480_REG_ALM_CNFG1 ADIS16480_REG(0x03, 0x22) +#define ADIS16480_REG_ALM_CNFG2 ADIS16480_REG(0x03, 0x24) +#define ADIS16480_REG_XG_ALM_MAGN ADIS16480_REG(0x03, 0x28) +#define ADIS16480_REG_YG_ALM_MAGN ADIS16480_REG(0x03, 0x2A) +#define ADIS16480_REG_ZG_ALM_MAGN ADIS16480_REG(0x03, 0x2C) +#define ADIS16480_REG_XA_ALM_MAGN ADIS16480_REG(0x03, 0x2E) +#define ADIS16480_REG_YA_ALM_MAGN ADIS16480_REG(0x03, 0x30) +#define ADIS16480_REG_ZA_ALM_MAGN ADIS16480_REG(0x03, 0x32) +#define ADIS16480_REG_XM_ALM_MAGN ADIS16480_REG(0x03, 0x34) +#define ADIS16480_REG_YM_ALM_MAGN ADIS16480_REG(0x03, 0x36) +#define ADIS16480_REG_ZM_ALM_MAGN ADIS16480_REG(0x03, 0x38) +#define ADIS16480_REG_BR_ALM_MAGN ADIS16480_REG(0x03, 0x3A) +#define ADIS16480_REG_FIRM_REV ADIS16480_REG(0x03, 0x78) +#define ADIS16480_REG_FIRM_DM ADIS16480_REG(0x03, 0x7A) +#define ADIS16480_REG_FIRM_Y ADIS16480_REG(0x03, 0x7C) + +#define ADIS16480_REG_SERIAL_NUM ADIS16480_REG(0x04, 0x20) + +/* Each filter coefficent bank spans two pages */ +#define ADIS16480_FIR_COEF(page) (x < 60 ? ADIS16480_REG(page, (x) + 8) : \ + ADIS16480_REG((page) + 1, (x) - 60 + 8)) +#define ADIS16480_FIR_COEF_A(x) ADIS16480_FIR_COEF(0x05, (x)) +#define ADIS16480_FIR_COEF_B(x) ADIS16480_FIR_COEF(0x07, (x)) +#define ADIS16480_FIR_COEF_C(x) ADIS16480_FIR_COEF(0x09, (x)) +#define ADIS16480_FIR_COEF_D(x) ADIS16480_FIR_COEF(0x0B, (x)) + +struct adis16480_chip_info { + unsigned int num_channels; + const struct iio_chan_spec *channels; +}; + +struct adis16480 { + const struct adis16480_chip_info *chip_info; + + struct adis adis; +}; + +#ifdef CONFIG_DEBUG_FS + +static ssize_t adis16480_show_firmware_revision(struct file *file, + char __user *userbuf, size_t count, loff_t *ppos) +{ + struct adis16480 *adis16480 = file->private_data; + char buf[7]; + size_t len; + u16 rev; + int ret; + + ret = adis_read_reg_16(&adis16480->adis, ADIS16480_REG_FIRM_REV, &rev); + if (ret < 0) + return ret; + + len = scnprintf(buf, sizeof(buf), "%x.%x\n", rev >> 8, rev & 0xff); + + return simple_read_from_buffer(userbuf, count, ppos, buf, len); +} + +static const struct file_operations adis16480_firmware_revision_fops = { + .open = simple_open, + .read = adis16480_show_firmware_revision, + .llseek = default_llseek, + .owner = THIS_MODULE, +}; + +static ssize_t adis16480_show_firmware_date(struct file *file, + char __user *userbuf, size_t count, loff_t *ppos) +{ + struct adis16480 *adis16480 = file->private_data; + u16 md, year; + char buf[12]; + size_t len; + int ret; + + ret = adis_read_reg_16(&adis16480->adis, ADIS16480_REG_FIRM_Y, &year); + if (ret < 0) + return ret; + + ret = adis_read_reg_16(&adis16480->adis, ADIS16480_REG_FIRM_DM, &md); + if (ret < 0) + return ret; + + len = snprintf(buf, sizeof(buf), "%.2x-%.2x-%.4x\n", + md >> 8, md & 0xff, year); + + return simple_read_from_buffer(userbuf, count, ppos, buf, len); +} + +static const struct file_operations adis16480_firmware_date_fops = { + .open = simple_open, + .read = adis16480_show_firmware_date, + .llseek = default_llseek, + .owner = THIS_MODULE, +}; + +static int adis16480_show_serial_number(void *arg, u64 *val) +{ + struct adis16480 *adis16480 = arg; + u16 serial; + int ret; + + ret = adis_read_reg_16(&adis16480->adis, ADIS16480_REG_SERIAL_NUM, + &serial); + if (ret < 0) + return ret; + + *val = serial; + + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(adis16480_serial_number_fops, + adis16480_show_serial_number, NULL, "0x%.4llx\n"); + +static int adis16480_show_product_id(void *arg, u64 *val) +{ + struct adis16480 *adis16480 = arg; + u16 prod_id; + int ret; + + ret = adis_read_reg_16(&adis16480->adis, ADIS16480_REG_PROD_ID, + &prod_id); + if (ret < 0) + return ret; + + *val = prod_id; + + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(adis16480_product_id_fops, + adis16480_show_product_id, NULL, "%llu\n"); + +static int adis16480_show_flash_count(void *arg, u64 *val) +{ + struct adis16480 *adis16480 = arg; + u32 flash_count; + int ret; + + ret = adis_read_reg_32(&adis16480->adis, ADIS16480_REG_FLASH_CNT, + &flash_count); + if (ret < 0) + return ret; + + *val = flash_count; + + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(adis16480_flash_count_fops, + adis16480_show_flash_count, NULL, "%lld\n"); + +static int adis16480_debugfs_init(struct iio_dev *indio_dev) +{ + struct adis16480 *adis16480 = iio_priv(indio_dev); + + debugfs_create_file("firmware_revision", 0400, + indio_dev->debugfs_dentry, adis16480, + &adis16480_firmware_revision_fops); + debugfs_create_file("firmware_date", 0400, indio_dev->debugfs_dentry, + adis16480, &adis16480_firmware_date_fops); + debugfs_create_file("serial_number", 0400, indio_dev->debugfs_dentry, + adis16480, &adis16480_serial_number_fops); + debugfs_create_file("product_id", 0400, indio_dev->debugfs_dentry, + adis16480, &adis16480_product_id_fops); + debugfs_create_file("flash_count", 0400, indio_dev->debugfs_dentry, + adis16480, &adis16480_flash_count_fops); + + return 0; +} + +#else + +static int adis16480_debugfs_init(struct iio_dev *indio_dev) +{ + return 0; +} + +#endif + +static int adis16480_set_freq(struct adis16480 *st, unsigned int freq) +{ + unsigned int t; + + t = 2460000 / freq; + if (t > 2048) + t = 2048; + + if (t != 0) + t--; + + return adis_write_reg_16(&st->adis, ADIS16480_REG_DEC_RATE, t); +} + +static int adis16480_get_freq(struct adis16480 *st, unsigned int *freq) +{ + uint16_t t; + int ret; + + ret = adis_read_reg_16(&st->adis, ADIS16480_REG_DEC_RATE, &t); + if (ret < 0) + return ret; + + *freq = 2460000 / (t + 1); + + return 0; +} + +static ssize_t adis16480_read_frequency(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct adis16480 *st = iio_priv(indio_dev); + unsigned int freq; + int ret; + + ret = adis16480_get_freq(st, &freq); + if (ret < 0) + return ret; + + return sprintf(buf, "%d.%.3d\n", freq / 1000, freq % 1000); +} + +static ssize_t adis16480_write_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 adis16480 *st = iio_priv(indio_dev); + int freq_int, freq_fract; + long val; + int ret; + + ret = iio_str_to_fixpoint(buf, 100, &freq_int, &freq_fract); + if (ret) + return ret; + + val = freq_int * 1000 + freq_fract; + + if (val <= 0) + return -EINVAL; + + ret = adis16480_set_freq(st, val); + + return ret ? ret : len; +} + +static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, + adis16480_read_frequency, + adis16480_write_frequency); + +enum { + ADIS16480_SCAN_GYRO_X, + ADIS16480_SCAN_GYRO_Y, + ADIS16480_SCAN_GYRO_Z, + ADIS16480_SCAN_ACCEL_X, + ADIS16480_SCAN_ACCEL_Y, + ADIS16480_SCAN_ACCEL_Z, + ADIS16480_SCAN_MAGN_X, + ADIS16480_SCAN_MAGN_Y, + ADIS16480_SCAN_MAGN_Z, + ADIS16480_SCAN_BARO, + ADIS16480_SCAN_TEMP, +}; + +static const unsigned int adis16480_calibbias_regs[] = { + [ADIS16480_SCAN_GYRO_X] = ADIS16480_REG_X_GYRO_BIAS, + [ADIS16480_SCAN_GYRO_Y] = ADIS16480_REG_Y_GYRO_BIAS, + [ADIS16480_SCAN_GYRO_Z] = ADIS16480_REG_Z_GYRO_BIAS, + [ADIS16480_SCAN_ACCEL_X] = ADIS16480_REG_X_ACCEL_BIAS, + [ADIS16480_SCAN_ACCEL_Y] = ADIS16480_REG_Y_ACCEL_BIAS, + [ADIS16480_SCAN_ACCEL_Z] = ADIS16480_REG_Z_ACCEL_BIAS, + [ADIS16480_SCAN_MAGN_X] = ADIS16480_REG_X_HARD_IRON, + [ADIS16480_SCAN_MAGN_Y] = ADIS16480_REG_Y_HARD_IRON, + [ADIS16480_SCAN_MAGN_Z] = ADIS16480_REG_Z_HARD_IRON, + [ADIS16480_SCAN_BARO] = ADIS16480_REG_BAROM_BIAS, +}; + +static const unsigned int adis16480_calibscale_regs[] = { + [ADIS16480_SCAN_GYRO_X] = ADIS16480_REG_X_GYRO_SCALE, + [ADIS16480_SCAN_GYRO_Y] = ADIS16480_REG_Y_GYRO_SCALE, + [ADIS16480_SCAN_GYRO_Z] = ADIS16480_REG_Z_GYRO_SCALE, + [ADIS16480_SCAN_ACCEL_X] = ADIS16480_REG_X_ACCEL_SCALE, + [ADIS16480_SCAN_ACCEL_Y] = ADIS16480_REG_Y_ACCEL_SCALE, + [ADIS16480_SCAN_ACCEL_Z] = ADIS16480_REG_Z_ACCEL_SCALE, +}; + +static int adis16480_set_calibbias(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, int bias) +{ + unsigned int reg = adis16480_calibbias_regs[chan->scan_index]; + struct adis16480 *st = iio_priv(indio_dev); + + switch (chan->type) { + case IIO_MAGN: + case IIO_PRESSURE: + if (bias < -0x8000 || bias >= 0x8000) + return -EINVAL; + return adis_write_reg_16(&st->adis, reg, bias); + case IIO_ANGL_VEL: + case IIO_ACCEL: + return adis_write_reg_32(&st->adis, reg, bias); + default: + break; + } + + return -EINVAL; +} + +static int adis16480_get_calibbias(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, int *bias) +{ + unsigned int reg = adis16480_calibbias_regs[chan->scan_index]; + struct adis16480 *st = iio_priv(indio_dev); + uint16_t val16; + uint32_t val32; + int ret; + + switch (chan->type) { + case IIO_MAGN: + case IIO_PRESSURE: + ret = adis_read_reg_16(&st->adis, reg, &val16); + *bias = sign_extend32(val16, 15); + break; + case IIO_ANGL_VEL: + case IIO_ACCEL: + ret = adis_read_reg_32(&st->adis, reg, &val32); + *bias = sign_extend32(val32, 31); + break; + default: + ret = -EINVAL; + } + + if (ret < 0) + return ret; + + return IIO_VAL_INT; +} + +static int adis16480_set_calibscale(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, int scale) +{ + unsigned int reg = adis16480_calibscale_regs[chan->scan_index]; + struct adis16480 *st = iio_priv(indio_dev); + + if (scale < -0x8000 || scale >= 0x8000) + return -EINVAL; + + return adis_write_reg_16(&st->adis, reg, scale); +} + +static int adis16480_get_calibscale(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, int *scale) +{ + unsigned int reg = adis16480_calibscale_regs[chan->scan_index]; + struct adis16480 *st = iio_priv(indio_dev); + uint16_t val16; + int ret; + + ret = adis_read_reg_16(&st->adis, reg, &val16); + if (ret < 0) + return ret; + + *scale = sign_extend32(val16, 15); + return IIO_VAL_INT; +} + +static const unsigned int adis16480_def_filter_freqs[] = { + 310, + 55, + 275, + 63, +}; + +static const unsigned int ad16480_filter_data[][2] = { + [ADIS16480_SCAN_GYRO_X] = { ADIS16480_REG_FILTER_BNK0, 0 }, + [ADIS16480_SCAN_GYRO_Y] = { ADIS16480_REG_FILTER_BNK0, 3 }, + [ADIS16480_SCAN_GYRO_Z] = { ADIS16480_REG_FILTER_BNK0, 6 }, + [ADIS16480_SCAN_ACCEL_X] = { ADIS16480_REG_FILTER_BNK0, 9 }, + [ADIS16480_SCAN_ACCEL_Y] = { ADIS16480_REG_FILTER_BNK0, 12 }, + [ADIS16480_SCAN_ACCEL_Z] = { ADIS16480_REG_FILTER_BNK1, 0 }, + [ADIS16480_SCAN_MAGN_X] = { ADIS16480_REG_FILTER_BNK1, 3 }, + [ADIS16480_SCAN_MAGN_Y] = { ADIS16480_REG_FILTER_BNK1, 6 }, + [ADIS16480_SCAN_MAGN_Z] = { ADIS16480_REG_FILTER_BNK1, 9 }, +}; + +static int adis16480_get_filter_freq(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, int *freq) +{ + struct adis16480 *st = iio_priv(indio_dev); + unsigned int enable_mask, offset, reg; + uint16_t val; + int ret; + + reg = ad16480_filter_data[chan->scan_index][0]; + offset = ad16480_filter_data[chan->scan_index][1]; + enable_mask = BIT(offset + 2); + + ret = adis_read_reg_16(&st->adis, reg, &val); + if (ret < 0) + return ret; + + if (!(val & enable_mask)) + *freq = 0; + else + *freq = adis16480_def_filter_freqs[(val >> offset) & 0x3]; + + return IIO_VAL_INT; +} + +static int adis16480_set_filter_freq(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, unsigned int freq) +{ + struct adis16480 *st = iio_priv(indio_dev); + unsigned int enable_mask, offset, reg; + unsigned int diff, best_diff; + unsigned int i, best_freq; + uint16_t val; + int ret; + + reg = ad16480_filter_data[chan->scan_index][0]; + offset = ad16480_filter_data[chan->scan_index][1]; + enable_mask = BIT(offset + 2); + + ret = adis_read_reg_16(&st->adis, reg, &val); + if (ret < 0) + return ret; + + if (freq == 0) { + val &= ~enable_mask; + } else { + best_freq = 0; + best_diff = 310; + for (i = 0; i < ARRAY_SIZE(adis16480_def_filter_freqs); i++) { + if (adis16480_def_filter_freqs[i] >= freq) { + diff = adis16480_def_filter_freqs[i] - freq; + if (diff < best_diff) { + best_diff = diff; + best_freq = i; + } + } + } + + val &= ~(0x3 << offset); + val |= best_freq << offset; + val |= enable_mask; + } + + return adis_write_reg_16(&st->adis, reg, val); +} + +static int adis16480_read_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, int *val, int *val2, long info) +{ + switch (info) { + case IIO_CHAN_INFO_RAW: + return adis_single_conversion(indio_dev, chan, 0, val); + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ANGL_VEL: + *val = 0; + *val2 = IIO_DEGREE_TO_RAD(20000); /* 0.02 degree/sec */ + return IIO_VAL_INT_PLUS_MICRO; + case IIO_ACCEL: + *val = 0; + *val2 = IIO_G_TO_M_S_2(800); /* 0.8 mg */ + return IIO_VAL_INT_PLUS_MICRO; + case IIO_MAGN: + *val = 0; + *val2 = 100; /* 0.0001 gauss */ + return IIO_VAL_INT_PLUS_MICRO; + case IIO_TEMP: + *val = 5; + *val2 = 650000; /* 5.65 milli degree Celsius */ + return IIO_VAL_INT_PLUS_MICRO; + case IIO_PRESSURE: + *val = 0; + *val2 = 4000; /* 40ubar = 0.004 kPa */ + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_OFFSET: + /* Only the temperature channel has a offset */ + *val = 4425; /* 25 degree Celsius = 0x0000 */ + return IIO_VAL_INT; + case IIO_CHAN_INFO_CALIBBIAS: + return adis16480_get_calibbias(indio_dev, chan, val); + case IIO_CHAN_INFO_CALIBSCALE: + return adis16480_get_calibscale(indio_dev, chan, val); + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + return adis16480_get_filter_freq(indio_dev, chan, val); + default: + return -EINVAL; + } +} + +static int adis16480_write_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, int val, int val2, long info) +{ + switch (info) { + case IIO_CHAN_INFO_CALIBBIAS: + return adis16480_set_calibbias(indio_dev, chan, val); + case IIO_CHAN_INFO_CALIBSCALE: + return adis16480_set_calibscale(indio_dev, chan, val); + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + return adis16480_set_filter_freq(indio_dev, chan, val); + default: + return -EINVAL; + } +} + +#define ADIS16480_MOD_CHANNEL(_type, _mod, _address, _si, _info, _bits) \ + { \ + .type = (_type), \ + .modified = 1, \ + .channel2 = (_mod), \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SHARED_BIT | \ + _info, \ + .address = (_address), \ + .scan_index = (_si), \ + .scan_type = { \ + .sign = 's', \ + .realbits = (_bits), \ + .storagebits = (_bits), \ + .endianness = IIO_BE, \ + }, \ + } + +#define ADIS16480_GYRO_CHANNEL(_mod) \ + ADIS16480_MOD_CHANNEL(IIO_ANGL_VEL, IIO_MOD_ ## _mod, \ + ADIS16480_REG_ ## _mod ## _GYRO_OUT, ADIS16480_SCAN_GYRO_ ## _mod, \ + IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT | \ + IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT, \ + 32) + +#define ADIS16480_ACCEL_CHANNEL(_mod) \ + ADIS16480_MOD_CHANNEL(IIO_ACCEL, IIO_MOD_ ## _mod, \ + ADIS16480_REG_ ## _mod ## _ACCEL_OUT, ADIS16480_SCAN_ACCEL_ ## _mod, \ + IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT | \ + IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT, \ + 32) + +#define ADIS16480_MAGN_CHANNEL(_mod) \ + ADIS16480_MOD_CHANNEL(IIO_MAGN, IIO_MOD_ ## _mod, \ + ADIS16480_REG_ ## _mod ## _MAGN_OUT, ADIS16480_SCAN_MAGN_ ## _mod, \ + IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT, \ + 16) + +#define ADIS16480_PRESSURE_CHANNEL() \ + { \ + .type = IIO_PRESSURE, \ + .indexed = 1, \ + .channel = 0, \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ + .address = ADIS16480_REG_BAROM_OUT, \ + .scan_index = ADIS16480_SCAN_BARO, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 32, \ + .storagebits = 32, \ + .endianness = IIO_BE, \ + }, \ + } + +#define ADIS16480_TEMP_CHANNEL() { \ + .type = IIO_TEMP, \ + .indexed = 1, \ + .channel = 0, \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \ + IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, \ + .address = ADIS16480_REG_TEMP_OUT, \ + .scan_index = ADIS16480_SCAN_TEMP, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_BE, \ + }, \ + } + +static const struct iio_chan_spec adis16480_channels[] = { + ADIS16480_GYRO_CHANNEL(X), + ADIS16480_GYRO_CHANNEL(Y), + ADIS16480_GYRO_CHANNEL(Z), + ADIS16480_ACCEL_CHANNEL(X), + ADIS16480_ACCEL_CHANNEL(Y), + ADIS16480_ACCEL_CHANNEL(Z), + ADIS16480_MAGN_CHANNEL(X), + ADIS16480_MAGN_CHANNEL(Y), + ADIS16480_MAGN_CHANNEL(Z), + ADIS16480_PRESSURE_CHANNEL(), + ADIS16480_TEMP_CHANNEL(), + IIO_CHAN_SOFT_TIMESTAMP(11) +}; + +static const struct iio_chan_spec adis16485_channels[] = { + ADIS16480_GYRO_CHANNEL(X), + ADIS16480_GYRO_CHANNEL(Y), + ADIS16480_GYRO_CHANNEL(Z), + ADIS16480_ACCEL_CHANNEL(X), + ADIS16480_ACCEL_CHANNEL(Y), + ADIS16480_ACCEL_CHANNEL(Z), + ADIS16480_TEMP_CHANNEL(), + IIO_CHAN_SOFT_TIMESTAMP(7) +}; + +enum adis16480_variant { + ADIS16375, + ADIS16480, + ADIS16485, + ADIS16488, +}; + +static const struct adis16480_chip_info adis16480_chip_info[] = { + [ADIS16375] = { + .channels = adis16485_channels, + .num_channels = ARRAY_SIZE(adis16485_channels), + }, + [ADIS16480] = { + .channels = adis16480_channels, + .num_channels = ARRAY_SIZE(adis16480_channels), + }, + [ADIS16485] = { + .channels = adis16485_channels, + .num_channels = ARRAY_SIZE(adis16485_channels), + }, + [ADIS16488] = { + .channels = adis16480_channels, + .num_channels = ARRAY_SIZE(adis16480_channels), + }, +}; + +static struct attribute *adis16480_attributes[] = { + &iio_dev_attr_sampling_frequency.dev_attr.attr, + NULL +}; + +static const struct attribute_group adis16480_attribute_group = { + .attrs = adis16480_attributes, +}; + +static const struct iio_info adis16480_info = { + .attrs = &adis16480_attribute_group, + .read_raw = &adis16480_read_raw, + .write_raw = &adis16480_write_raw, + .update_scan_mode = adis_update_scan_mode, + .driver_module = THIS_MODULE, +}; + +static int adis16480_stop_device(struct iio_dev *indio_dev) +{ + struct adis16480 *st = iio_priv(indio_dev); + int ret; + + ret = adis_write_reg_16(&st->adis, ADIS16480_REG_SLP_CNT, BIT(9)); + if (ret) + dev_err(&indio_dev->dev, + "Could not power down device: %d\n", ret); + + return ret; +} + +static int adis16480_enable_irq(struct adis *adis, bool enable) +{ + return adis_write_reg_16(adis, ADIS16480_REG_FNCTIO_CTRL, + enable ? BIT(3) : 0); +} + +static int adis16480_initial_setup(struct iio_dev *indio_dev) +{ + struct adis16480 *st = iio_priv(indio_dev); + uint16_t prod_id; + unsigned int device_id; + int ret; + + adis_reset(&st->adis); + msleep(70); + + ret = adis_write_reg_16(&st->adis, ADIS16480_REG_GLOB_CMD, BIT(1)); + if (ret) + return ret; + msleep(30); + + ret = adis_check_status(&st->adis); + if (ret) + return ret; + + ret = adis_read_reg_16(&st->adis, ADIS16480_REG_PROD_ID, &prod_id); + if (ret) + return ret; + + sscanf(indio_dev->name, "adis%u\n", &device_id); + + if (prod_id != device_id) + dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.", + device_id, prod_id); + + return 0; +} + +#define ADIS16480_DIAG_STAT_XGYRO_FAIL 0 +#define ADIS16480_DIAG_STAT_YGYRO_FAIL 1 +#define ADIS16480_DIAG_STAT_ZGYRO_FAIL 2 +#define ADIS16480_DIAG_STAT_XACCL_FAIL 3 +#define ADIS16480_DIAG_STAT_YACCL_FAIL 4 +#define ADIS16480_DIAG_STAT_ZACCL_FAIL 5 +#define ADIS16480_DIAG_STAT_XMAGN_FAIL 8 +#define ADIS16480_DIAG_STAT_YMAGN_FAIL 9 +#define ADIS16480_DIAG_STAT_ZMAGN_FAIL 10 +#define ADIS16480_DIAG_STAT_BARO_FAIL 11 + +static const char * const adis16480_status_error_msgs[] = { + [ADIS16480_DIAG_STAT_XGYRO_FAIL] = "X-axis gyroscope self-test failure", + [ADIS16480_DIAG_STAT_YGYRO_FAIL] = "Y-axis gyroscope self-test failure", + [ADIS16480_DIAG_STAT_ZGYRO_FAIL] = "Z-axis gyroscope self-test failure", + [ADIS16480_DIAG_STAT_XACCL_FAIL] = "X-axis accelerometer self-test failure", + [ADIS16480_DIAG_STAT_YACCL_FAIL] = "Y-axis accelerometer self-test failure", + [ADIS16480_DIAG_STAT_ZACCL_FAIL] = "Z-axis accelerometer self-test failure", + [ADIS16480_DIAG_STAT_XMAGN_FAIL] = "X-axis magnetometer self-test failure", + [ADIS16480_DIAG_STAT_YMAGN_FAIL] = "Y-axis magnetometer self-test failure", + [ADIS16480_DIAG_STAT_ZMAGN_FAIL] = "Z-axis magnetometer self-test failure", + [ADIS16480_DIAG_STAT_BARO_FAIL] = "Barometer self-test failure", +}; + +static const struct adis_data adis16480_data = { + .diag_stat_reg = ADIS16480_REG_DIAG_STS, + .glob_cmd_reg = ADIS16480_REG_GLOB_CMD, + .has_paging = true, + + .read_delay = 5, + .write_delay = 5, + + .status_error_msgs = adis16480_status_error_msgs, + .status_error_mask = BIT(ADIS16480_DIAG_STAT_XGYRO_FAIL) | + BIT(ADIS16480_DIAG_STAT_YGYRO_FAIL) | + BIT(ADIS16480_DIAG_STAT_ZGYRO_FAIL) | + BIT(ADIS16480_DIAG_STAT_XACCL_FAIL) | + BIT(ADIS16480_DIAG_STAT_YACCL_FAIL) | + BIT(ADIS16480_DIAG_STAT_ZACCL_FAIL) | + BIT(ADIS16480_DIAG_STAT_XMAGN_FAIL) | + BIT(ADIS16480_DIAG_STAT_YMAGN_FAIL) | + BIT(ADIS16480_DIAG_STAT_ZMAGN_FAIL) | + BIT(ADIS16480_DIAG_STAT_BARO_FAIL), + + .enable_irq = adis16480_enable_irq, +}; + +static int adis16480_probe(struct spi_device *spi) +{ + const struct spi_device_id *id = spi_get_device_id(spi); + struct iio_dev *indio_dev; + struct adis16480 *st; + int ret; + + indio_dev = iio_device_alloc(sizeof(*st)); + if (indio_dev == NULL) + return -ENOMEM; + + spi_set_drvdata(spi, indio_dev); + + st = iio_priv(indio_dev); + + st->chip_info = &adis16480_chip_info[id->driver_data]; + indio_dev->dev.parent = &spi->dev; + indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->channels = st->chip_info->channels; + indio_dev->num_channels = st->chip_info->num_channels; + indio_dev->info = &adis16480_info; + indio_dev->modes = INDIO_DIRECT_MODE; + + ret = adis_init(&st->adis, indio_dev, spi, &adis16480_data); + if (ret) + goto error_free_dev; + + ret = adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL); + if (ret) + goto error_free_dev; + + ret = adis16480_initial_setup(indio_dev); + if (ret) + goto error_cleanup_buffer; + + ret = iio_device_register(indio_dev); + if (ret) + goto error_stop_device; + + adis16480_debugfs_init(indio_dev); + + return 0; + +error_stop_device: + adis16480_stop_device(indio_dev); +error_cleanup_buffer: + adis_cleanup_buffer_and_trigger(&st->adis, indio_dev); +error_free_dev: + iio_device_free(indio_dev); + return ret; +} + +static int adis16480_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct adis16480 *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + adis16480_stop_device(indio_dev); + + adis_cleanup_buffer_and_trigger(&st->adis, indio_dev); + + iio_device_free(indio_dev); + + return 0; +} + +static const struct spi_device_id adis16480_ids[] = { + { "adis16375", ADIS16375 }, + { "adis16480", ADIS16480 }, + { "adis16485", ADIS16485 }, + { "adis16488", ADIS16488 }, + { } +}; +MODULE_DEVICE_TABLE(spi, adis16480_ids); + +static struct spi_driver adis16480_driver = { + .driver = { + .name = "adis16480", + .owner = THIS_MODULE, + }, + .id_table = adis16480_ids, + .probe = adis16480_probe, + .remove = adis16480_remove, +}; +module_spi_driver(adis16480_driver); + +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); +MODULE_DESCRIPTION("Analog Devices ADIS16480 IMU driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c new file mode 100644 index 000000000000..99d8e0b0dd34 --- /dev/null +++ b/drivers/iio/imu/adis_buffer.c @@ -0,0 +1,176 @@ +/* + * Common library for ADIS16XXX devices + * + * Copyright 2012 Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + * + * Licensed under the GPL-2 or later. + */ + +#include <linux/export.h> +#include <linux/interrupt.h> +#include <linux/mutex.h> +#include <linux/kernel.h> +#include <linux/spi/spi.h> +#include <linux/slab.h> + +#include <linux/iio/iio.h> +#include <linux/iio/buffer.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/iio/triggered_buffer.h> +#include <linux/iio/imu/adis.h> + +int adis_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *scan_mask) +{ + struct adis *adis = iio_device_get_drvdata(indio_dev); + const struct iio_chan_spec *chan; + unsigned int scan_count; + unsigned int i, j; + __be16 *tx, *rx; + + kfree(adis->xfer); + kfree(adis->buffer); + + scan_count = indio_dev->scan_bytes / 2; + + adis->xfer = kcalloc(scan_count + 1, sizeof(*adis->xfer), GFP_KERNEL); + if (!adis->xfer) + return -ENOMEM; + + adis->buffer = kzalloc(indio_dev->scan_bytes * 2, GFP_KERNEL); + if (!adis->buffer) + return -ENOMEM; + + rx = adis->buffer; + tx = rx + indio_dev->scan_bytes; + + spi_message_init(&adis->msg); + + for (j = 0; j <= scan_count; j++) { + adis->xfer[j].bits_per_word = 8; + if (j != scan_count) + adis->xfer[j].cs_change = 1; + adis->xfer[j].len = 2; + adis->xfer[j].delay_usecs = adis->data->read_delay; + if (j < scan_count) + adis->xfer[j].tx_buf = &tx[j]; + if (j >= 1) + adis->xfer[j].rx_buf = &rx[j - 1]; + spi_message_add_tail(&adis->xfer[j], &adis->msg); + } + + chan = indio_dev->channels; + for (i = 0; i < indio_dev->num_channels; i++, chan++) { + if (!test_bit(chan->scan_index, scan_mask)) + continue; + if (chan->scan_type.storagebits == 32) + *tx++ = cpu_to_be16((chan->address + 2) << 8); + *tx++ = cpu_to_be16(chan->address << 8); + } + + return 0; +} +EXPORT_SYMBOL_GPL(adis_update_scan_mode); + +static irqreturn_t adis_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct adis *adis = iio_device_get_drvdata(indio_dev); + int ret; + + if (!adis->buffer) + return -ENOMEM; + + if (adis->data->has_paging) { + mutex_lock(&adis->txrx_lock); + if (adis->current_page != 0) { + adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID); + adis->tx[1] = 0; + spi_write(adis->spi, adis->tx, 2); + } + } + + ret = spi_sync(adis->spi, &adis->msg); + if (ret) + dev_err(&adis->spi->dev, "Failed to read data: %d", ret); + + + if (adis->data->has_paging) { + adis->current_page = 0; + mutex_unlock(&adis->txrx_lock); + } + + /* Guaranteed to be aligned with 8 byte boundary */ + if (indio_dev->scan_timestamp) { + void *b = adis->buffer + indio_dev->scan_bytes - sizeof(s64); + *(s64 *)b = pf->timestamp; + } + + iio_push_to_buffers(indio_dev, adis->buffer); + + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +/** + * adis_setup_buffer_and_trigger() - Sets up buffer and trigger for the adis device + * @adis: The adis device. + * @indio_dev: The IIO device. + * @trigger_handler: Optional trigger handler, may be NULL. + * + * Returns 0 on success, a negative error code otherwise. + * + * This function sets up the buffer and trigger for a adis devices. If + * 'trigger_handler' is NULL the default trigger handler will be used. The + * default trigger handler will simply read the registers assigned to the + * currently active channels. + * + * adis_cleanup_buffer_and_trigger() should be called to free the resources + * allocated by this function. + */ +int adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev, + irqreturn_t (*trigger_handler)(int, void *)) +{ + int ret; + + if (!trigger_handler) + trigger_handler = adis_trigger_handler; + + ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, + trigger_handler, NULL); + if (ret) + return ret; + + if (adis->spi->irq) { + ret = adis_probe_trigger(adis, indio_dev); + if (ret) + goto error_buffer_cleanup; + } + return 0; + +error_buffer_cleanup: + iio_triggered_buffer_cleanup(indio_dev); + return ret; +} +EXPORT_SYMBOL_GPL(adis_setup_buffer_and_trigger); + +/** + * adis_cleanup_buffer_and_trigger() - Free buffer and trigger resources + * @adis: The adis device. + * @indio_dev: The IIO device. + * + * Frees resources allocated by adis_setup_buffer_and_trigger() + */ +void adis_cleanup_buffer_and_trigger(struct adis *adis, + struct iio_dev *indio_dev) +{ + if (adis->spi->irq) + adis_remove_trigger(adis); + kfree(adis->buffer); + kfree(adis->xfer); + iio_triggered_buffer_cleanup(indio_dev); +} +EXPORT_SYMBOL_GPL(adis_cleanup_buffer_and_trigger); diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c new file mode 100644 index 000000000000..5a24c9cac343 --- /dev/null +++ b/drivers/iio/imu/adis_trigger.c @@ -0,0 +1,89 @@ +/* + * Common library for ADIS16XXX devices + * + * Copyright 2012 Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + * + * Licensed under the GPL-2 or later. + */ + +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/spi/spi.h> +#include <linux/export.h> + +#include <linux/iio/iio.h> +#include <linux/iio/trigger.h> +#include <linux/iio/imu/adis.h> + +static int adis_data_rdy_trigger_set_state(struct iio_trigger *trig, + bool state) +{ + struct adis *adis = trig->private_data; + + return adis_enable_irq(adis, state); +} + +static const struct iio_trigger_ops adis_trigger_ops = { + .owner = THIS_MODULE, + .set_trigger_state = &adis_data_rdy_trigger_set_state, +}; + +/** + * adis_probe_trigger() - Sets up trigger for a adis device + * @adis: The adis device + * @indio_dev: The IIO device + * + * Returns 0 on success or a negative error code + * + * adis_remove_trigger() should be used to free the trigger. + */ +int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev) +{ + int ret; + + adis->trig = iio_trigger_alloc("%s-dev%d", indio_dev->name, + indio_dev->id); + if (adis->trig == NULL) + return -ENOMEM; + + ret = request_irq(adis->spi->irq, + &iio_trigger_generic_data_rdy_poll, + IRQF_TRIGGER_RISING, + indio_dev->name, + adis->trig); + if (ret) + goto error_free_trig; + + adis->trig->dev.parent = &adis->spi->dev; + adis->trig->ops = &adis_trigger_ops; + adis->trig->private_data = adis; + ret = iio_trigger_register(adis->trig); + + indio_dev->trig = adis->trig; + if (ret) + goto error_free_irq; + + return 0; + +error_free_irq: + free_irq(adis->spi->irq, adis->trig); +error_free_trig: + iio_trigger_free(adis->trig); + return ret; +} +EXPORT_SYMBOL_GPL(adis_probe_trigger); + +/** + * adis_remove_trigger() - Remove trigger for a adis devices + * @adis: The adis device + * + * Removes the trigger previously registered with adis_probe_trigger(). + */ +void adis_remove_trigger(struct adis *adis) +{ + iio_trigger_unregister(adis->trig); + free_irq(adis->spi->irq, adis->trig); + iio_trigger_free(adis->trig); +} +EXPORT_SYMBOL_GPL(adis_remove_trigger); diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index d4ad37455a67..aaadd32f9f0d 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -31,6 +31,18 @@ static const char * const iio_endian_prefix[] = { [IIO_LE] = "le", }; +static bool iio_buffer_is_active(struct iio_dev *indio_dev, + struct iio_buffer *buf) +{ + struct list_head *p; + + list_for_each(p, &indio_dev->buffer_list) + if (p == &buf->buffer_list) + return true; + + return false; +} + /** * iio_buffer_read_first_n_outer() - chrdev read for buffer access * @@ -134,7 +146,7 @@ static ssize_t iio_scan_el_store(struct device *dev, if (ret < 0) return ret; mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) { + if (iio_buffer_is_active(indio_dev, indio_dev->buffer)) { ret = -EBUSY; goto error_ret; } @@ -180,12 +192,11 @@ static ssize_t iio_scan_el_ts_store(struct device *dev, return ret; mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) { + if (iio_buffer_is_active(indio_dev, indio_dev->buffer)) { ret = -EBUSY; goto error_ret; } indio_dev->buffer->scan_timestamp = state; - indio_dev->scan_timestamp = state; error_ret: mutex_unlock(&indio_dev->mlock); @@ -371,12 +382,12 @@ ssize_t iio_buffer_write_length(struct device *dev, const char *buf, size_t len) { - int ret; - ulong val; struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_buffer *buffer = indio_dev->buffer; + unsigned int val; + int ret; - ret = strict_strtoul(buf, 10, &val); + ret = kstrtouint(buf, 10, &val); if (ret) return ret; @@ -385,7 +396,7 @@ ssize_t iio_buffer_write_length(struct device *dev, return len; mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) { + if (iio_buffer_is_active(indio_dev, indio_dev->buffer)) { ret = -EBUSY; } else { if (buffer->access->set_length) @@ -398,102 +409,14 @@ ssize_t iio_buffer_write_length(struct device *dev, } EXPORT_SYMBOL(iio_buffer_write_length); -ssize_t iio_buffer_store_enable(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - int ret; - bool requested_state, current_state; - int previous_mode; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct iio_buffer *buffer = indio_dev->buffer; - - mutex_lock(&indio_dev->mlock); - previous_mode = indio_dev->currentmode; - requested_state = !(buf[0] == '0'); - current_state = iio_buffer_enabled(indio_dev); - if (current_state == requested_state) { - printk(KERN_INFO "iio-buffer, current state requested again\n"); - goto done; - } - if (requested_state) { - if (indio_dev->setup_ops->preenable) { - ret = indio_dev->setup_ops->preenable(indio_dev); - if (ret) { - printk(KERN_ERR - "Buffer not started: " - "buffer preenable failed\n"); - goto error_ret; - } - } - if (buffer->access->request_update) { - ret = buffer->access->request_update(buffer); - if (ret) { - printk(KERN_INFO - "Buffer not started: " - "buffer parameter update failed\n"); - goto error_ret; - } - } - /* Definitely possible for devices to support both of these. */ - if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) { - if (!indio_dev->trig) { - printk(KERN_INFO - "Buffer not started: no trigger\n"); - ret = -EINVAL; - goto error_ret; - } - indio_dev->currentmode = INDIO_BUFFER_TRIGGERED; - } else if (indio_dev->modes & INDIO_BUFFER_HARDWARE) - indio_dev->currentmode = INDIO_BUFFER_HARDWARE; - else { /* should never be reached */ - ret = -EINVAL; - goto error_ret; - } - - if (indio_dev->setup_ops->postenable) { - ret = indio_dev->setup_ops->postenable(indio_dev); - if (ret) { - printk(KERN_INFO - "Buffer not started: " - "postenable failed\n"); - indio_dev->currentmode = previous_mode; - if (indio_dev->setup_ops->postdisable) - indio_dev->setup_ops-> - postdisable(indio_dev); - goto error_ret; - } - } - } else { - if (indio_dev->setup_ops->predisable) { - ret = indio_dev->setup_ops->predisable(indio_dev); - if (ret) - goto error_ret; - } - indio_dev->currentmode = INDIO_DIRECT_MODE; - if (indio_dev->setup_ops->postdisable) { - ret = indio_dev->setup_ops->postdisable(indio_dev); - if (ret) - goto error_ret; - } - } -done: - mutex_unlock(&indio_dev->mlock); - return len; - -error_ret: - mutex_unlock(&indio_dev->mlock); - return ret; -} -EXPORT_SYMBOL(iio_buffer_store_enable); - ssize_t iio_buffer_show_enable(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); - return sprintf(buf, "%d\n", iio_buffer_enabled(indio_dev)); + return sprintf(buf, "%d\n", + iio_buffer_is_active(indio_dev, + indio_dev->buffer)); } EXPORT_SYMBOL(iio_buffer_show_enable); @@ -537,35 +460,220 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev, const long *mask, return bytes; } -int iio_sw_buffer_preenable(struct iio_dev *indio_dev) +int iio_update_buffers(struct iio_dev *indio_dev, + struct iio_buffer *insert_buffer, + struct iio_buffer *remove_buffer) { - struct iio_buffer *buffer = indio_dev->buffer; - dev_dbg(&indio_dev->dev, "%s\n", __func__); + int ret; + int success = 0; + struct iio_buffer *buffer; + unsigned long *compound_mask; + const unsigned long *old_mask; - /* How much space will the demuxed element take? */ - indio_dev->scan_bytes = - iio_compute_scan_bytes(indio_dev, buffer->scan_mask, - buffer->scan_timestamp); - buffer->access->set_bytes_per_datum(buffer, indio_dev->scan_bytes); + /* Wind down existing buffers - iff there are any */ + if (!list_empty(&indio_dev->buffer_list)) { + if (indio_dev->setup_ops->predisable) { + ret = indio_dev->setup_ops->predisable(indio_dev); + if (ret) + goto error_ret; + } + indio_dev->currentmode = INDIO_DIRECT_MODE; + if (indio_dev->setup_ops->postdisable) { + ret = indio_dev->setup_ops->postdisable(indio_dev); + if (ret) + goto error_ret; + } + } + /* Keep a copy of current setup to allow roll back */ + old_mask = indio_dev->active_scan_mask; + if (!indio_dev->available_scan_masks) + indio_dev->active_scan_mask = NULL; + + if (remove_buffer) + list_del(&remove_buffer->buffer_list); + if (insert_buffer) + list_add(&insert_buffer->buffer_list, &indio_dev->buffer_list); + + /* If no buffers in list, we are done */ + if (list_empty(&indio_dev->buffer_list)) { + indio_dev->currentmode = INDIO_DIRECT_MODE; + if (indio_dev->available_scan_masks == NULL) + kfree(old_mask); + return 0; + } /* What scan mask do we actually have ?*/ - if (indio_dev->available_scan_masks) + compound_mask = kcalloc(BITS_TO_LONGS(indio_dev->masklength), + sizeof(long), GFP_KERNEL); + if (compound_mask == NULL) { + if (indio_dev->available_scan_masks == NULL) + kfree(old_mask); + return -ENOMEM; + } + indio_dev->scan_timestamp = 0; + + list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) { + bitmap_or(compound_mask, compound_mask, buffer->scan_mask, + indio_dev->masklength); + indio_dev->scan_timestamp |= buffer->scan_timestamp; + } + if (indio_dev->available_scan_masks) { indio_dev->active_scan_mask = iio_scan_mask_match(indio_dev->available_scan_masks, indio_dev->masklength, - buffer->scan_mask); - else - indio_dev->active_scan_mask = buffer->scan_mask; - - if (indio_dev->active_scan_mask == NULL) - return -EINVAL; + compound_mask); + if (indio_dev->active_scan_mask == NULL) { + /* + * Roll back. + * Note can only occur when adding a buffer. + */ + list_del(&insert_buffer->buffer_list); + indio_dev->active_scan_mask = old_mask; + success = -EINVAL; + } + } else { + indio_dev->active_scan_mask = compound_mask; + } iio_update_demux(indio_dev); - if (indio_dev->info->update_scan_mode) - return indio_dev->info + /* Wind up again */ + if (indio_dev->setup_ops->preenable) { + ret = indio_dev->setup_ops->preenable(indio_dev); + if (ret) { + printk(KERN_ERR + "Buffer not started:" + "buffer preenable failed\n"); + goto error_remove_inserted; + } + } + indio_dev->scan_bytes = + iio_compute_scan_bytes(indio_dev, + indio_dev->active_scan_mask, + indio_dev->scan_timestamp); + list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) + if (buffer->access->request_update) { + ret = buffer->access->request_update(buffer); + if (ret) { + printk(KERN_INFO + "Buffer not started:" + "buffer parameter update failed\n"); + goto error_run_postdisable; + } + } + if (indio_dev->info->update_scan_mode) { + ret = indio_dev->info ->update_scan_mode(indio_dev, indio_dev->active_scan_mask); + if (ret < 0) { + printk(KERN_INFO "update scan mode failed\n"); + goto error_run_postdisable; + } + } + /* Definitely possible for devices to support both of these.*/ + if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) { + if (!indio_dev->trig) { + printk(KERN_INFO "Buffer not started: no trigger\n"); + ret = -EINVAL; + /* Can only occur on first buffer */ + goto error_run_postdisable; + } + indio_dev->currentmode = INDIO_BUFFER_TRIGGERED; + } else if (indio_dev->modes & INDIO_BUFFER_HARDWARE) { + indio_dev->currentmode = INDIO_BUFFER_HARDWARE; + } else { /* should never be reached */ + ret = -EINVAL; + goto error_run_postdisable; + } + + if (indio_dev->setup_ops->postenable) { + ret = indio_dev->setup_ops->postenable(indio_dev); + if (ret) { + printk(KERN_INFO + "Buffer not started: postenable failed\n"); + indio_dev->currentmode = INDIO_DIRECT_MODE; + if (indio_dev->setup_ops->postdisable) + indio_dev->setup_ops->postdisable(indio_dev); + goto error_disable_all_buffers; + } + } + + if (indio_dev->available_scan_masks) + kfree(compound_mask); + else + kfree(old_mask); + + return success; + +error_disable_all_buffers: + indio_dev->currentmode = INDIO_DIRECT_MODE; +error_run_postdisable: + if (indio_dev->setup_ops->postdisable) + indio_dev->setup_ops->postdisable(indio_dev); +error_remove_inserted: + + if (insert_buffer) + list_del(&insert_buffer->buffer_list); + indio_dev->active_scan_mask = old_mask; + kfree(compound_mask); +error_ret: + + return ret; +} +EXPORT_SYMBOL_GPL(iio_update_buffers); + +ssize_t iio_buffer_store_enable(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + int ret; + bool requested_state; + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct iio_buffer *pbuf = indio_dev->buffer; + bool inlist; + + ret = strtobool(buf, &requested_state); + if (ret < 0) + return ret; + + mutex_lock(&indio_dev->mlock); + + /* Find out if it is in the list */ + inlist = iio_buffer_is_active(indio_dev, pbuf); + /* Already in desired state */ + if (inlist == requested_state) + goto done; + + if (requested_state) + ret = iio_update_buffers(indio_dev, + indio_dev->buffer, NULL); + else + ret = iio_update_buffers(indio_dev, + NULL, indio_dev->buffer); + + if (ret < 0) + goto done; +done: + mutex_unlock(&indio_dev->mlock); + return (ret < 0) ? ret : len; +} +EXPORT_SYMBOL(iio_buffer_store_enable); + +int iio_sw_buffer_preenable(struct iio_dev *indio_dev) +{ + struct iio_buffer *buffer; + unsigned bytes; + dev_dbg(&indio_dev->dev, "%s\n", __func__); + + list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) + if (buffer->access->set_bytes_per_datum) { + bytes = iio_compute_scan_bytes(indio_dev, + buffer->scan_mask, + buffer->scan_timestamp); + + buffer->access->set_bytes_per_datum(buffer, bytes); + } return 0; } EXPORT_SYMBOL(iio_sw_buffer_preenable); @@ -599,7 +707,11 @@ static bool iio_validate_scan_mask(struct iio_dev *indio_dev, * iio_scan_mask_set() - set particular bit in the scan mask * @buffer: the buffer whose scan mask we are interested in * @bit: the bit to be set. - **/ + * + * Note that at this point we have no way of knowing what other + * buffers might request, hence this code only verifies that the + * individual buffers request is plausible. + */ int iio_scan_mask_set(struct iio_dev *indio_dev, struct iio_buffer *buffer, int bit) { @@ -682,13 +794,12 @@ static unsigned char *iio_demux(struct iio_buffer *buffer, return buffer->demux_bounce; } -int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data) +static int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data) { unsigned char *dataout = iio_demux(buffer, data); return buffer->access->store_to(buffer, dataout); } -EXPORT_SYMBOL_GPL(iio_push_to_buffer); static void iio_buffer_demux_free(struct iio_buffer *buffer) { @@ -699,10 +810,26 @@ static void iio_buffer_demux_free(struct iio_buffer *buffer) } } -int iio_update_demux(struct iio_dev *indio_dev) + +int iio_push_to_buffers(struct iio_dev *indio_dev, unsigned char *data) +{ + int ret; + struct iio_buffer *buf; + + list_for_each_entry(buf, &indio_dev->buffer_list, buffer_list) { + ret = iio_push_to_buffer(buf, data); + if (ret < 0) + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(iio_push_to_buffers); + +static int iio_buffer_update_demux(struct iio_dev *indio_dev, + struct iio_buffer *buffer) { const struct iio_chan_spec *ch; - struct iio_buffer *buffer = indio_dev->buffer; int ret, in_ind = -1, out_ind, length; unsigned in_loc = 0, out_loc = 0; struct iio_demux_table *p; @@ -787,4 +914,23 @@ error_clear_mux_table: return ret; } + +int iio_update_demux(struct iio_dev *indio_dev) +{ + struct iio_buffer *buffer; + int ret; + + list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) { + ret = iio_buffer_update_demux(indio_dev, buffer); + if (ret < 0) + goto error_clear_mux_table; + } + return 0; + +error_clear_mux_table: + list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) + iio_buffer_demux_free(buffer); + + return ret; +} EXPORT_SYMBOL_GPL(iio_update_demux); diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 6eb24dbc081e..8848f16c547b 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -65,6 +65,7 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_CAPACITANCE] = "capacitance", [IIO_ALTVOLTAGE] = "altvoltage", [IIO_CCT] = "cct", + [IIO_PRESSURE] = "pressure", }; static const char * const iio_modifier_names[] = { @@ -397,11 +398,74 @@ static ssize_t iio_read_channel_info(struct device *dev, val2 = do_div(tmp, 1000000000LL); val = tmp; return sprintf(buf, "%d.%09u\n", val, val2); + case IIO_VAL_FRACTIONAL_LOG2: + tmp = (s64)val * 1000000000LL >> val2; + val2 = do_div(tmp, 1000000000LL); + val = tmp; + return sprintf(buf, "%d.%09u\n", val, val2); default: return 0; } } +/** + * iio_str_to_fixpoint() - Parse a fixed-point number from a string + * @str: The string to parse + * @fract_mult: Multiplier for the first decimal place, should be a power of 10 + * @integer: The integer part of the number + * @fract: The fractional part of the number + * + * Returns 0 on success, or a negative error code if the string could not be + * parsed. + */ +int iio_str_to_fixpoint(const char *str, int fract_mult, + int *integer, int *fract) +{ + int i = 0, f = 0; + bool integer_part = true, negative = false; + + if (str[0] == '-') { + negative = true; + str++; + } else if (str[0] == '+') { + str++; + } + + while (*str) { + if ('0' <= *str && *str <= '9') { + if (integer_part) { + i = i * 10 + *str - '0'; + } else { + f += fract_mult * (*str - '0'); + fract_mult /= 10; + } + } else if (*str == '\n') { + if (*(str + 1) == '\0') + break; + else + return -EINVAL; + } else if (*str == '.' && integer_part) { + integer_part = false; + } else { + return -EINVAL; + } + str++; + } + + if (negative) { + if (i) + i = -i; + else + f = -f; + } + + *integer = i; + *fract = f; + + return 0; +} +EXPORT_SYMBOL_GPL(iio_str_to_fixpoint); + static ssize_t iio_write_channel_info(struct device *dev, struct device_attribute *attr, const char *buf, @@ -409,8 +473,8 @@ static ssize_t iio_write_channel_info(struct device *dev, { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int ret, integer = 0, fract = 0, fract_mult = 100000; - bool integer_part = true, negative = false; + int ret, fract_mult = 100000; + int integer, fract; /* Assumes decimal - precision based on number of digits */ if (!indio_dev->info->write_raw) @@ -429,39 +493,9 @@ static ssize_t iio_write_channel_info(struct device *dev, return -EINVAL; } - if (buf[0] == '-') { - negative = true; - buf++; - } - - while (*buf) { - if ('0' <= *buf && *buf <= '9') { - if (integer_part) - integer = integer*10 + *buf - '0'; - else { - fract += fract_mult*(*buf - '0'); - if (fract_mult == 1) - break; - fract_mult /= 10; - } - } else if (*buf == '\n') { - if (*(buf + 1) == '\0') - break; - else - return -EINVAL; - } else if (*buf == '.') { - integer_part = false; - } else { - return -EINVAL; - } - buf++; - } - if (negative) { - if (integer) - integer = -integer; - else - fract = -fract; - } + ret = iio_str_to_fixpoint(buf, fract_mult, &integer, &fract); + if (ret) + return ret; ret = indio_dev->info->write_raw(indio_dev, this_attr->c, integer, fract, this_attr->address); @@ -851,6 +885,7 @@ struct iio_dev *iio_device_alloc(int sizeof_priv) return NULL; } dev_set_name(&dev->dev, "iio:device%d", dev->id); + INIT_LIST_HEAD(&dev->buffer_list); } return dev; diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index fa6543bf6731..261cae00557e 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -239,13 +239,13 @@ static ssize_t iio_ev_value_store(struct device *dev, { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - unsigned long val; + int val; int ret; if (!indio_dev->info->write_event_value) return -EINVAL; - ret = strict_strtoul(buf, 10, &val); + ret = kstrtoint(buf, 10, &val); if (ret) return ret; @@ -350,15 +350,10 @@ static inline int __iio_add_event_config_attrs(struct iio_dev *indio_dev) ret = iio_device_add_event_sysfs(indio_dev, &indio_dev->channels[j]); if (ret < 0) - goto error_clear_attrs; + return ret; attrcount += ret; } return attrcount; - -error_clear_attrs: - __iio_remove_event_config_attrs(indio_dev); - - return ret; } static bool iio_check_for_dynamic_events(struct iio_dev *indio_dev) diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index f2b78d4fe457..d55e98fb300e 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -78,7 +78,7 @@ int iio_map_array_unregister(struct iio_dev *indio_dev, found_it = true; break; } - if (found_it == false) { + if (!found_it) { ret = -ENODEV; goto error_ret; } @@ -203,6 +203,7 @@ struct iio_channel *iio_channel_get_all(const char *name) if (name && strcmp(name, c->map->consumer_dev_name) != 0) continue; chans[mapind].indio_dev = c->indio_dev; + chans[mapind].data = c->map->consumer_data; chans[mapind].channel = iio_chan_spec_from_name(chans[mapind].indio_dev, c->map->adc_channel_label); @@ -314,6 +315,9 @@ static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan, *processed = div_s64(raw64 * (s64)scale_val * scale, scale_val2); break; + case IIO_VAL_FRACTIONAL_LOG2: + *processed = (raw64 * (s64)scale_val * scale) >> scale_val2; + break; default: return -EINVAL; } diff --git a/drivers/iio/light/adjd_s311.c b/drivers/iio/light/adjd_s311.c index 164b62b91a4b..36d210a06b28 100644 --- a/drivers/iio/light/adjd_s311.c +++ b/drivers/iio/light/adjd_s311.c @@ -164,7 +164,6 @@ static irqreturn_t adjd_s311_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct adjd_s311_data *data = iio_priv(indio_dev); - struct iio_buffer *buffer = indio_dev->buffer; s64 time_ns = iio_get_time_ns(); int len = 0; int i, j = 0; @@ -187,7 +186,7 @@ static irqreturn_t adjd_s311_trigger_handler(int irq, void *p) if (indio_dev->scan_timestamp) *(s64 *)((u8 *)data->buffer + ALIGN(len, sizeof(s64))) = time_ns; - iio_push_to_buffer(buffer, (u8 *)data->buffer); + iio_push_to_buffers(indio_dev, (u8 *)data->buffer); done: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c index 96e3691e42c4..23eeeef64e84 100644 --- a/drivers/iio/light/hid-sensor-als.c +++ b/drivers/iio/light/hid-sensor-als.c @@ -176,21 +176,8 @@ static const struct iio_info als_info = { /* Function to push data to buffer */ static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len) { - struct iio_buffer *buffer = indio_dev->buffer; - int datum_sz; - dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n"); - if (!buffer) { - dev_err(&indio_dev->dev, "Buffer == NULL\n"); - return; - } - datum_sz = buffer->access->get_bytes_per_datum(buffer); - if (len > datum_sz) { - dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len, - datum_sz); - return; - } - iio_push_to_buffer(buffer, (u8 *)data); + iio_push_to_buffers(indio_dev, (u8 *)data); } /* Callback handler to send event after all samples are received and captured */ @@ -285,10 +272,9 @@ static int __devinit hid_als_probe(struct platform_device *pdev) goto error_free_dev; } - channels = kmemdup(als_channels, - sizeof(als_channels), - GFP_KERNEL); + channels = kmemdup(als_channels, sizeof(als_channels), GFP_KERNEL); if (!channels) { + ret = -ENOMEM; dev_err(&pdev->dev, "failed to duplicate channels\n"); goto error_free_dev; } diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c index c4f0d274f577..8e75eb76ccd9 100644 --- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c +++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c @@ -198,21 +198,8 @@ static const struct iio_info magn_3d_info = { /* Function to push data to buffer */ static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len) { - struct iio_buffer *buffer = indio_dev->buffer; - int datum_sz; - dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n"); - if (!buffer) { - dev_err(&indio_dev->dev, "Buffer == NULL\n"); - return; - } - datum_sz = buffer->access->get_bytes_per_datum(buffer); - if (len > datum_sz) { - dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len, - datum_sz); - return; - } - iio_push_to_buffer(buffer, (u8 *)data); + iio_push_to_buffers(indio_dev, (u8 *)data); } /* Callback handler to send event after all samples are received and captured */ @@ -320,10 +307,10 @@ static int __devinit hid_magn_3d_probe(struct platform_device *pdev) goto error_free_dev; } - channels = kmemdup(magn_3d_channels, - sizeof(magn_3d_channels), - GFP_KERNEL); + channels = kmemdup(magn_3d_channels, sizeof(magn_3d_channels), + GFP_KERNEL); if (!channels) { + ret = -ENOMEM; dev_err(&pdev->dev, "failed to duplicate channels\n"); goto error_free_dev; } diff --git a/drivers/ipack/Kconfig b/drivers/ipack/Kconfig new file mode 100644 index 000000000000..3949e5589560 --- /dev/null +++ b/drivers/ipack/Kconfig @@ -0,0 +1,24 @@ +# +# IPACK configuration. +# + +menuconfig IPACK_BUS + tristate "IndustryPack bus support" + depends on HAS_IOMEM + ---help--- + This option provides support for the IndustryPack framework. There + are IndustryPack carrier boards, which interface another bus (such as + PCI) to an IndustryPack bus, and IndustryPack modules, that are + hosted on these buses. While IndustryPack modules can provide a + large variety of functionality, they are most often found in + industrial control applications. + + Say N if unsure. + +if IPACK_BUS + +source "drivers/ipack/carriers/Kconfig" + +source "drivers/ipack/devices/Kconfig" + +endif # IPACK diff --git a/drivers/staging/ipack/Makefile b/drivers/ipack/Makefile index 85ff223616fd..6f14ade0f8f3 100644 --- a/drivers/staging/ipack/Makefile +++ b/drivers/ipack/Makefile @@ -3,4 +3,4 @@ # obj-$(CONFIG_IPACK_BUS) += ipack.o obj-y += devices/ -obj-y += bridges/ +obj-y += carriers/ diff --git a/drivers/ipack/carriers/Kconfig b/drivers/ipack/carriers/Kconfig new file mode 100644 index 000000000000..922ff5c35acc --- /dev/null +++ b/drivers/ipack/carriers/Kconfig @@ -0,0 +1,7 @@ +config BOARD_TPCI200 + tristate "Support for the TEWS TPCI-200 IndustryPack carrier board" + depends on IPACK_BUS + depends on PCI + help + This driver adds support for the TEWS TPCI200 IndustryPack carrier board. + default n diff --git a/drivers/staging/ipack/bridges/Makefile b/drivers/ipack/carriers/Makefile index d8b76459300f..d8b76459300f 100644 --- a/drivers/staging/ipack/bridges/Makefile +++ b/drivers/ipack/carriers/Makefile diff --git a/drivers/staging/ipack/bridges/tpci200.c b/drivers/ipack/carriers/tpci200.c index 46d6657280b8..0246b1fddffe 100644 --- a/drivers/staging/ipack/bridges/tpci200.c +++ b/drivers/ipack/carriers/tpci200.c @@ -2,9 +2,10 @@ * tpci200.c * * driver for the TEWS TPCI-200 device - * Copyright (c) 2009 Nicolas Serafini, EIC2 SA - * Copyright (c) 2010,2011 Samuel Iglesias Gonsalvez <siglesia@cern.ch>, CERN - * Copyright (c) 2012 Samuel Iglesias Gonsalvez <siglesias@igalia.com>, Igalia + * + * Copyright (C) 2009-2012 CERN (www.cern.ch) + * Author: Nicolas Serafini, EIC2 SA + * Author: Samuel Iglesias Gonsalvez <siglesias@igalia.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 @@ -15,20 +16,36 @@ #include <linux/slab.h> #include "tpci200.h" -static u16 tpci200_status_timeout[] = { +static const u16 tpci200_status_timeout[] = { TPCI200_A_TIMEOUT, TPCI200_B_TIMEOUT, TPCI200_C_TIMEOUT, TPCI200_D_TIMEOUT, }; -static u16 tpci200_status_error[] = { +static const u16 tpci200_status_error[] = { TPCI200_A_ERROR, TPCI200_B_ERROR, TPCI200_C_ERROR, TPCI200_D_ERROR, }; +static const size_t tpci200_space_size[IPACK_SPACE_COUNT] = { + [IPACK_IO_SPACE] = TPCI200_IO_SPACE_SIZE, + [IPACK_ID_SPACE] = TPCI200_ID_SPACE_SIZE, + [IPACK_INT_SPACE] = TPCI200_INT_SPACE_SIZE, + [IPACK_MEM8_SPACE] = TPCI200_MEM8_SPACE_SIZE, + [IPACK_MEM16_SPACE] = TPCI200_MEM16_SPACE_SIZE, +}; + +static const size_t tpci200_space_interval[IPACK_SPACE_COUNT] = { + [IPACK_IO_SPACE] = TPCI200_IO_SPACE_INTERVAL, + [IPACK_ID_SPACE] = TPCI200_ID_SPACE_INTERVAL, + [IPACK_INT_SPACE] = TPCI200_INT_SPACE_INTERVAL, + [IPACK_MEM8_SPACE] = TPCI200_MEM8_SPACE_INTERVAL, + [IPACK_MEM16_SPACE] = TPCI200_MEM16_SPACE_INTERVAL, +}; + static struct tpci200_board *check_slot(struct ipack_device *dev) { struct tpci200_board *tpci200; @@ -47,7 +64,7 @@ static struct tpci200_board *check_slot(struct ipack_device *dev) if (dev->slot >= TPCI200_NB_SLOT) { dev_info(&dev->dev, "Slot [%d:%d] doesn't exist! Last tpci200 slot is %d.\n", - dev->bus_nr, dev->slot, TPCI200_NB_SLOT-1); + dev->bus->bus_nr, dev->slot, TPCI200_NB_SLOT-1); return NULL; } @@ -74,33 +91,19 @@ static void tpci200_set_mask(struct tpci200_board *tpci200, static void tpci200_unregister(struct tpci200_board *tpci200) { - int i; - free_irq(tpci200->info->pdev->irq, (void *) tpci200); pci_iounmap(tpci200->info->pdev, tpci200->info->interface_regs); - pci_iounmap(tpci200->info->pdev, tpci200->info->ioidint_space); - pci_iounmap(tpci200->info->pdev, tpci200->info->mem8_space); pci_iounmap(tpci200->info->pdev, tpci200->info->cfg_regs); pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR); pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR); + pci_release_region(tpci200->info->pdev, TPCI200_MEM16_SPACE_BAR); pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR); pci_release_region(tpci200->info->pdev, TPCI200_CFG_MEM_BAR); pci_disable_device(tpci200->info->pdev); pci_dev_put(tpci200->info->pdev); - - for (i = 0; i < TPCI200_NB_SLOT; i++) { - tpci200->slots[i].io_phys.address = NULL; - tpci200->slots[i].io_phys.size = 0; - tpci200->slots[i].id_phys.address = NULL; - tpci200->slots[i].id_phys.size = 0; - tpci200->slots[i].int_phys.address = NULL; - tpci200->slots[i].int_phys.size = 0; - tpci200->slots[i].mem_phys.address = NULL; - tpci200->slots[i].mem_phys.size = 0; - } } static void tpci200_enable_irq(struct tpci200_board *tpci200, @@ -207,7 +210,8 @@ static int tpci200_request_irq(struct ipack_device *dev, if (tpci200->slots[dev->slot].irq != NULL) { dev_err(&dev->dev, - "Slot [%d:%d] IRQ already registered !\n", dev->bus_nr, + "Slot [%d:%d] IRQ already registered !\n", + dev->bus->bus_nr, dev->slot); res = -EINVAL; goto out_unlock; @@ -217,7 +221,7 @@ static int tpci200_request_irq(struct ipack_device *dev, if (slot_irq == NULL) { dev_err(&dev->dev, "Slot [%d:%d] unable to allocate memory for IRQ !\n", - dev->bus_nr, dev->slot); + dev->bus->bus_nr, dev->slot); res = -ENOMEM; goto out_unlock; } @@ -244,8 +248,7 @@ static int tpci200_register(struct tpci200_board *tpci200) { int i; int res; - unsigned long ioidint_base; - unsigned long mem_base; + phys_addr_t ioidint_base; unsigned short slot_ctrl; if (pci_enable_device(tpci200->info->pdev) < 0) @@ -274,38 +277,49 @@ static int tpci200_register(struct tpci200_board *tpci200) goto out_release_ip_space; } - /* Request MEM space (Bar 4) */ + /* Request MEM8 space (Bar 5) */ res = pci_request_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR, - "Carrier MEM space"); + "Carrier MEM8 space"); if (res) { dev_err(&tpci200->info->pdev->dev, - "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 4!", + "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 5!", tpci200->info->pdev->bus->number, tpci200->info->pdev->devfn); goto out_release_ioid_int_space; } + /* Request MEM16 space (Bar 4) */ + res = pci_request_region(tpci200->info->pdev, TPCI200_MEM16_SPACE_BAR, + "Carrier MEM16 space"); + if (res) { + dev_err(&tpci200->info->pdev->dev, + "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 4!", + tpci200->info->pdev->bus->number, + tpci200->info->pdev->devfn); + goto out_release_mem8_space; + } + /* Map internal tpci200 driver user space */ tpci200->info->interface_regs = ioremap_nocache(pci_resource_start(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR), TPCI200_IFACE_SIZE); - tpci200->info->ioidint_space = - ioremap_nocache(pci_resource_start(tpci200->info->pdev, - TPCI200_IO_ID_INT_SPACES_BAR), - TPCI200_IOIDINT_SIZE); - tpci200->info->mem8_space = - ioremap_nocache(pci_resource_start(tpci200->info->pdev, - TPCI200_MEM8_SPACE_BAR), - TPCI200_MEM8_SIZE); /* Initialize lock that protects interface_regs */ spin_lock_init(&tpci200->regs_lock); ioidint_base = pci_resource_start(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR); - mem_base = pci_resource_start(tpci200->info->pdev, - TPCI200_MEM8_SPACE_BAR); + tpci200->mod_mem[IPACK_IO_SPACE] = ioidint_base + TPCI200_IO_SPACE_OFF; + tpci200->mod_mem[IPACK_ID_SPACE] = ioidint_base + TPCI200_ID_SPACE_OFF; + tpci200->mod_mem[IPACK_INT_SPACE] = + ioidint_base + TPCI200_INT_SPACE_OFF; + tpci200->mod_mem[IPACK_MEM8_SPACE] = + pci_resource_start(tpci200->info->pdev, + TPCI200_MEM8_SPACE_BAR); + tpci200->mod_mem[IPACK_MEM16_SPACE] = + pci_resource_start(tpci200->info->pdev, + TPCI200_MEM16_SPACE_BAR); /* Set the default parameters of the slot * INT0 disabled, level sensitive @@ -316,30 +330,8 @@ static int tpci200_register(struct tpci200_board *tpci200) * clock rate 8 MHz */ slot_ctrl = 0; - - /* Set all slot physical address space */ - for (i = 0; i < TPCI200_NB_SLOT; i++) { - tpci200->slots[i].io_phys.address = - (void __iomem *)ioidint_base + - TPCI200_IO_SPACE_OFF + TPCI200_IO_SPACE_GAP*i; - tpci200->slots[i].io_phys.size = TPCI200_IO_SPACE_SIZE; - - tpci200->slots[i].id_phys.address = - (void __iomem *)ioidint_base + - TPCI200_ID_SPACE_OFF + TPCI200_ID_SPACE_GAP*i; - tpci200->slots[i].id_phys.size = TPCI200_ID_SPACE_SIZE; - - tpci200->slots[i].int_phys.address = - (void __iomem *)ioidint_base + - TPCI200_INT_SPACE_OFF + TPCI200_INT_SPACE_GAP * i; - tpci200->slots[i].int_phys.size = TPCI200_INT_SPACE_SIZE; - - tpci200->slots[i].mem_phys.address = - (void __iomem *)mem_base + TPCI200_MEM8_GAP*i; - tpci200->slots[i].mem_phys.size = TPCI200_MEM8_SIZE; - + for (i = 0; i < TPCI200_NB_SLOT; i++) writew(slot_ctrl, &tpci200->info->interface_regs->control[i]); - } res = request_irq(tpci200->info->pdev->irq, tpci200_interrupt, IRQF_SHARED, @@ -354,6 +346,8 @@ static int tpci200_register(struct tpci200_board *tpci200) return 0; +out_release_mem8_space: + pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR); out_release_ioid_int_space: pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR); out_release_ip_space: @@ -363,166 +357,6 @@ out_disable_pci: return res; } -static int tpci200_slot_unmap_space(struct ipack_device *dev, int space) -{ - struct ipack_addr_space *virt_addr_space; - struct tpci200_board *tpci200; - - tpci200 = check_slot(dev); - if (tpci200 == NULL) - return -EINVAL; - - if (mutex_lock_interruptible(&tpci200->mutex)) - return -ERESTARTSYS; - - switch (space) { - case IPACK_IO_SPACE: - if (dev->io_space.address == NULL) { - dev_info(&dev->dev, - "Slot [%d:%d] IO space not mapped !\n", - dev->bus_nr, dev->slot); - goto out_unlock; - } - virt_addr_space = &dev->io_space; - break; - case IPACK_ID_SPACE: - if (dev->id_space.address == NULL) { - dev_info(&dev->dev, - "Slot [%d:%d] ID space not mapped !\n", - dev->bus_nr, dev->slot); - goto out_unlock; - } - virt_addr_space = &dev->id_space; - break; - case IPACK_INT_SPACE: - if (dev->int_space.address == NULL) { - dev_info(&dev->dev, - "Slot [%d:%d] INT space not mapped !\n", - dev->bus_nr, dev->slot); - goto out_unlock; - } - virt_addr_space = &dev->int_space; - break; - case IPACK_MEM_SPACE: - if (dev->mem_space.address == NULL) { - dev_info(&dev->dev, - "Slot [%d:%d] MEM space not mapped !\n", - dev->bus_nr, dev->slot); - goto out_unlock; - } - virt_addr_space = &dev->mem_space; - break; - default: - dev_err(&dev->dev, - "Slot [%d:%d] space number %d doesn't exist !\n", - dev->bus_nr, dev->slot, space); - mutex_unlock(&tpci200->mutex); - return -EINVAL; - } - - iounmap(virt_addr_space->address); - - virt_addr_space->address = NULL; - virt_addr_space->size = 0; -out_unlock: - mutex_unlock(&tpci200->mutex); - return 0; -} - -static int tpci200_slot_map_space(struct ipack_device *dev, - unsigned int memory_size, int space) -{ - int res = 0; - unsigned int size_to_map; - void __iomem *phys_address; - struct ipack_addr_space *virt_addr_space; - struct tpci200_board *tpci200; - - tpci200 = check_slot(dev); - if (tpci200 == NULL) - return -EINVAL; - - if (mutex_lock_interruptible(&tpci200->mutex)) - return -ERESTARTSYS; - - switch (space) { - case IPACK_IO_SPACE: - if (dev->io_space.address != NULL) { - dev_err(&dev->dev, - "Slot [%d:%d] IO space already mapped !\n", - tpci200->number, dev->slot); - res = -EINVAL; - goto out_unlock; - } - virt_addr_space = &dev->io_space; - - phys_address = tpci200->slots[dev->slot].io_phys.address; - size_to_map = tpci200->slots[dev->slot].io_phys.size; - break; - case IPACK_ID_SPACE: - if (dev->id_space.address != NULL) { - dev_err(&dev->dev, - "Slot [%d:%d] ID space already mapped !\n", - tpci200->number, dev->slot); - res = -EINVAL; - goto out_unlock; - } - virt_addr_space = &dev->id_space; - - phys_address = tpci200->slots[dev->slot].id_phys.address; - size_to_map = tpci200->slots[dev->slot].id_phys.size; - break; - case IPACK_INT_SPACE: - if (dev->int_space.address != NULL) { - dev_err(&dev->dev, - "Slot [%d:%d] INT space already mapped !\n", - tpci200->number, dev->slot); - res = -EINVAL; - goto out_unlock; - } - virt_addr_space = &dev->int_space; - - phys_address = tpci200->slots[dev->slot].int_phys.address; - size_to_map = tpci200->slots[dev->slot].int_phys.size; - break; - case IPACK_MEM_SPACE: - if (dev->mem_space.address != NULL) { - dev_err(&dev->dev, - "Slot [%d:%d] MEM space already mapped !\n", - tpci200->number, dev->slot); - res = -EINVAL; - goto out_unlock; - } - virt_addr_space = &dev->mem_space; - - if (memory_size > tpci200->slots[dev->slot].mem_phys.size) { - dev_err(&dev->dev, - "Slot [%d:%d] request is 0x%X memory, only 0x%X available !\n", - dev->bus_nr, dev->slot, memory_size, - tpci200->slots[dev->slot].mem_phys.size); - res = -EINVAL; - goto out_unlock; - } - - phys_address = tpci200->slots[dev->slot].mem_phys.address; - size_to_map = memory_size; - break; - default: - dev_err(&dev->dev, "Slot [%d:%d] space %d doesn't exist !\n", - tpci200->number, dev->slot, space); - res = -EINVAL; - goto out_unlock; - } - - virt_addr_space->size = size_to_map; - virt_addr_space->address = - ioremap_nocache((unsigned long)phys_address, size_to_map); - -out_unlock: - mutex_unlock(&tpci200->mutex); - return res; -} - static int tpci200_get_clockrate(struct ipack_device *dev) { struct tpci200_board *tpci200 = check_slot(dev); @@ -610,8 +444,6 @@ static void tpci200_uninstall(struct tpci200_board *tpci200) } static const struct ipack_bus_ops tpci200_bus_ops = { - .map_space = tpci200_slot_map_space, - .unmap_space = tpci200_slot_unmap_space, .request_irq = tpci200_request_irq, .free_irq = tpci200_free_irq, .get_clockrate = tpci200_get_clockrate, @@ -641,6 +473,31 @@ static int tpci200_install(struct tpci200_board *tpci200) return 0; } +static void tpci200_release_device(struct ipack_device *dev) +{ + kfree(dev); +} + +static int tpci200_create_device(struct tpci200_board *tpci200, int i) +{ + enum ipack_space space; + struct ipack_device *dev = + kzalloc(sizeof(struct ipack_device), GFP_KERNEL); + if (!dev) + return -ENOMEM; + dev->slot = i; + dev->bus = tpci200->info->ipack_bus; + dev->release = tpci200_release_device; + + for (space = 0; space < IPACK_SPACE_COUNT; space++) { + dev->region[space].start = + tpci200->mod_mem[space] + + tpci200_space_interval[space] * i; + dev->region[space].size = tpci200_space_size[space]; + } + return ipack_device_register(dev); +} + static int tpci200_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -716,7 +573,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev, dev_set_drvdata(&pdev->dev, tpci200); for (i = 0; i < TPCI200_NB_SLOT; i++) - ipack_device_register(tpci200->info->ipack_bus, i); + tpci200_create_device(tpci200, i); return 0; out_err_bus_register: @@ -742,7 +599,7 @@ static void __tpci200_pci_remove(struct tpci200_board *tpci200) kfree(tpci200); } -static void __devexit tpci200_pci_remove(struct pci_dev *dev) +static void tpci200_pci_remove(struct pci_dev *dev) { struct tpci200_board *tpci200 = pci_get_drvdata(dev); @@ -761,20 +618,10 @@ static struct pci_driver tpci200_pci_drv = { .name = "tpci200", .id_table = tpci200_idtable, .probe = tpci200_pci_probe, - .remove = __devexit_p(tpci200_pci_remove), + .remove = tpci200_pci_remove, }; -static int __init tpci200_drvr_init_module(void) -{ - return pci_register_driver(&tpci200_pci_drv); -} - -static void __exit tpci200_drvr_exit_module(void) -{ - pci_unregister_driver(&tpci200_pci_drv); -} +module_pci_driver(tpci200_pci_drv); MODULE_DESCRIPTION("TEWS TPCI-200 device driver"); MODULE_LICENSE("GPL"); -module_init(tpci200_drvr_init_module); -module_exit(tpci200_drvr_exit_module); diff --git a/drivers/staging/ipack/bridges/tpci200.h b/drivers/ipack/carriers/tpci200.h index 235d1fe4f48c..a7a151dab83c 100644 --- a/drivers/staging/ipack/bridges/tpci200.h +++ b/drivers/ipack/carriers/tpci200.h @@ -2,9 +2,10 @@ * tpci200.h * * driver for the carrier TEWS TPCI-200 - * Copyright (c) 2009 Nicolas Serafini, EIC2 SA - * Copyright (c) 2010,2011 Samuel Iglesias Gonsalvez <siglesia@cern.ch>, CERN - * Copyright (c) 2012 Samuel Iglesias Gonsalvez <siglesias@igalia.com>, Igalia + * + * Copyright (C) 2009-2012 CERN (www.cern.ch) + * Author: Nicolas Serafini, EIC2 SA + * Author: Samuel Iglesias Gonsalvez <siglesias@igalia.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 @@ -19,8 +20,7 @@ #include <linux/spinlock.h> #include <linux/swab.h> #include <linux/io.h> - -#include "../ipack.h" +#include <linux/ipack.h> #define TPCI200_NB_SLOT 0x4 #define TPCI200_NB_BAR 0x6 @@ -49,20 +49,20 @@ struct tpci200_regs { #define TPCI200_IFACE_SIZE 0x100 #define TPCI200_IO_SPACE_OFF 0x0000 -#define TPCI200_IO_SPACE_GAP 0x0100 +#define TPCI200_IO_SPACE_INTERVAL 0x0100 #define TPCI200_IO_SPACE_SIZE 0x0080 #define TPCI200_ID_SPACE_OFF 0x0080 -#define TPCI200_ID_SPACE_GAP 0x0100 +#define TPCI200_ID_SPACE_INTERVAL 0x0100 #define TPCI200_ID_SPACE_SIZE 0x0040 #define TPCI200_INT_SPACE_OFF 0x00C0 -#define TPCI200_INT_SPACE_GAP 0x0100 +#define TPCI200_INT_SPACE_INTERVAL 0x0100 #define TPCI200_INT_SPACE_SIZE 0x0040 #define TPCI200_IOIDINT_SIZE 0x0400 -#define TPCI200_MEM8_GAP 0x00400000 -#define TPCI200_MEM8_SIZE 0x00400000 -#define TPCI200_MEM16_GAP 0x00800000 -#define TPCI200_MEM16_SIZE 0x00800000 +#define TPCI200_MEM8_SPACE_INTERVAL 0x00400000 +#define TPCI200_MEM8_SPACE_SIZE 0x00400000 +#define TPCI200_MEM16_SPACE_INTERVAL 0x00800000 +#define TPCI200_MEM16_SPACE_SIZE 0x00800000 /* control field in tpci200_regs */ #define TPCI200_INT0_EN 0x0040 @@ -137,11 +137,7 @@ struct slot_irq { * */ struct tpci200_slot { - struct slot_irq *irq; - struct ipack_addr_space io_phys; - struct ipack_addr_space id_phys; - struct ipack_addr_space int_phys; - struct ipack_addr_space mem_phys; + struct slot_irq *irq; }; /** @@ -156,8 +152,6 @@ struct tpci200_infos { struct pci_dev *pdev; struct pci_device_id *id_table; struct tpci200_regs __iomem *interface_regs; - void __iomem *ioidint_space; - void __iomem *mem8_space; void __iomem *cfg_regs; struct ipack_bus_device *ipack_bus; }; @@ -167,6 +161,7 @@ struct tpci200_board { spinlock_t regs_lock; struct tpci200_slot *slots; struct tpci200_infos *info; + phys_addr_t mod_mem[IPACK_SPACE_COUNT]; }; #endif /* _TPCI200_H_ */ diff --git a/drivers/staging/ipack/devices/Kconfig b/drivers/ipack/devices/Kconfig index 39f71888a584..0b82fdc198c0 100644 --- a/drivers/staging/ipack/devices/Kconfig +++ b/drivers/ipack/devices/Kconfig @@ -4,4 +4,3 @@ config SERIAL_IPOCTAL help This driver supports the IPOCTAL serial port device for the IndustryPack bus. default n - diff --git a/drivers/staging/ipack/devices/Makefile b/drivers/ipack/devices/Makefile index 6de18bda4a9a..6de18bda4a9a 100644 --- a/drivers/staging/ipack/devices/Makefile +++ b/drivers/ipack/devices/Makefile diff --git a/drivers/staging/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c index d751edfda839..c06ab396e84f 100644 --- a/drivers/staging/ipack/devices/ipoctal.c +++ b/drivers/ipack/devices/ipoctal.c @@ -2,9 +2,10 @@ * ipoctal.c * * driver for the GE IP-OCTAL boards - * Copyright (c) 2009 Nicolas Serafini, EIC2 SA - * Copyright (c) 2010,2011 Samuel Iglesias Gonsalvez <siglesia@cern.ch>, CERN - * Copyright (c) 2012 Samuel Iglesias Gonsalvez <siglesias@igalia.com>, Igalia + * + * Copyright (C) 2009-2012 CERN (www.cern.ch) + * Author: Nicolas Serafini, EIC2 SA + * Author: Samuel Iglesias Gonsalvez <siglesias@igalia.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 @@ -21,7 +22,7 @@ #include <linux/slab.h> #include <linux/atomic.h> #include <linux/io.h> -#include "../ipack.h" +#include <linux/ipack.h> #include "ipoctal.h" #include "scc2698.h" @@ -53,6 +54,8 @@ struct ipoctal { struct ipoctal_channel channel[NR_CHANNELS]; unsigned char write; struct tty_driver *tty_drv; + u8 __iomem *mem8_space; + u8 __iomem *int_space; }; static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty) @@ -252,35 +255,12 @@ static irqreturn_t ipoctal_irq_handler(void *arg) ipoctal_irq_channel(&ipoctal->channel[i]); /* Clear the IPack device interrupt */ - readw(ipoctal->dev->int_space.address + ACK_INT_REQ0); - readw(ipoctal->dev->int_space.address + ACK_INT_REQ1); + readw(ipoctal->int_space + ACK_INT_REQ0); + readw(ipoctal->int_space + ACK_INT_REQ1); return IRQ_HANDLED; } -static int ipoctal_check_model(struct ipack_device *dev, unsigned char *id) -{ - unsigned char manufacturerID; - unsigned char board_id; - - - manufacturerID = ioread8(dev->id_space.address + IPACK_IDPROM_OFFSET_MANUFACTURER_ID); - if (manufacturerID != IPACK1_VENDOR_ID_SBS) - return -ENODEV; - board_id = ioread8(dev->id_space.address + IPACK_IDPROM_OFFSET_MODEL); - switch (board_id) { - case IPACK1_DEVICE_ID_SBS_OCTAL_232: - case IPACK1_DEVICE_ID_SBS_OCTAL_422: - case IPACK1_DEVICE_ID_SBS_OCTAL_485: - *id = board_id; - break; - default: - return -ENODEV; - } - - return 0; -} - static const struct tty_port_operations ipoctal_tty_port_ops = { .dtr_rts = NULL, .activate = ipoctal_port_activate, @@ -289,64 +269,55 @@ static const struct tty_port_operations ipoctal_tty_port_ops = { static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, unsigned int slot) { - int res = 0; + int res; int i; struct tty_driver *tty; char name[20]; - unsigned char board_id; struct ipoctal_channel *channel; + struct ipack_region *region; + void __iomem *addr; union scc2698_channel __iomem *chan_regs; union scc2698_block __iomem *block_regs; - res = ipoctal->dev->bus->ops->map_space(ipoctal->dev, 0, - IPACK_ID_SPACE); - if (res) { - dev_err(&ipoctal->dev->dev, - "Unable to map slot [%d:%d] ID space!\n", - bus_nr, slot); - return res; - } - - res = ipoctal_check_model(ipoctal->dev, &board_id); - if (res) { - ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, - IPACK_ID_SPACE); - goto out_unregister_id_space; - } - ipoctal->board_id = board_id; + ipoctal->board_id = ipoctal->dev->id_device; - res = ipoctal->dev->bus->ops->map_space(ipoctal->dev, 0, - IPACK_IO_SPACE); - if (res) { + region = &ipoctal->dev->region[IPACK_IO_SPACE]; + addr = devm_ioremap_nocache(&ipoctal->dev->dev, + region->start, region->size); + if (!addr) { dev_err(&ipoctal->dev->dev, "Unable to map slot [%d:%d] IO space!\n", bus_nr, slot); - goto out_unregister_id_space; + return -EADDRNOTAVAIL; } + /* Save the virtual address to access the registers easily */ + chan_regs = + (union scc2698_channel __iomem *) addr; + block_regs = + (union scc2698_block __iomem *) addr; - res = ipoctal->dev->bus->ops->map_space(ipoctal->dev, 0, - IPACK_INT_SPACE); - if (res) { + region = &ipoctal->dev->region[IPACK_INT_SPACE]; + ipoctal->int_space = + devm_ioremap_nocache(&ipoctal->dev->dev, + region->start, region->size); + if (!ipoctal->int_space) { dev_err(&ipoctal->dev->dev, "Unable to map slot [%d:%d] INT space!\n", bus_nr, slot); - goto out_unregister_io_space; + return -EADDRNOTAVAIL; } - res = ipoctal->dev->bus->ops->map_space(ipoctal->dev, - 0x8000, IPACK_MEM_SPACE); - if (res) { + region = &ipoctal->dev->region[IPACK_MEM8_SPACE]; + ipoctal->mem8_space = + devm_ioremap_nocache(&ipoctal->dev->dev, + region->start, 0x8000); + if (!addr) { dev_err(&ipoctal->dev->dev, - "Unable to map slot [%d:%d] MEM space!\n", + "Unable to map slot [%d:%d] MEM8 space!\n", bus_nr, slot); - goto out_unregister_int_space; + return -EADDRNOTAVAIL; } - /* Save the virtual address to access the registers easily */ - chan_regs = - (union scc2698_channel __iomem *) ipoctal->dev->io_space.address; - block_regs = - (union scc2698_block __iomem *) ipoctal->dev->io_space.address; /* Disable RX and TX before touching anything */ for (i = 0; i < NR_CHANNELS ; i++) { @@ -389,17 +360,15 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, ipoctal->dev->bus->ops->request_irq(ipoctal->dev, ipoctal_irq_handler, ipoctal); /* Dummy write */ - iowrite8(1, ipoctal->dev->mem_space.address + 1); + iowrite8(1, ipoctal->mem8_space + 1); /* Register the TTY device */ /* Each IP-OCTAL channel is a TTY port */ tty = alloc_tty_driver(NR_CHANNELS); - if (!tty) { - res = -ENOMEM; - goto out_unregister_slot_unmap; - } + if (!tty) + return -ENOMEM; /* Fill struct tty_driver with ipoctal data */ tty->owner = THIS_MODULE; @@ -422,7 +391,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, if (res) { dev_err(&ipoctal->dev->dev, "Can't register tty driver.\n"); put_tty_driver(tty); - goto out_unregister_slot_unmap; + return res; } /* Save struct tty_driver for use it when uninstalling the device */ @@ -458,16 +427,6 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, } return 0; - -out_unregister_slot_unmap: - ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_ID_SPACE); -out_unregister_int_space: - ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_INT_SPACE); -out_unregister_io_space: - ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_IO_SPACE); -out_unregister_id_space: - ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_MEM_SPACE); - return res; } static inline int ipoctal_copy_write_buffer(struct ipoctal_channel *channel, @@ -719,7 +678,7 @@ static int ipoctal_probe(struct ipack_device *dev) return -ENOMEM; ipoctal->dev = dev; - res = ipoctal_inst_slot(ipoctal, dev->bus_nr, dev->slot); + res = ipoctal_inst_slot(ipoctal, dev->bus->bus_nr, dev->slot); if (res) goto out_uninst; @@ -745,10 +704,6 @@ static void __ipoctal_remove(struct ipoctal *ipoctal) tty_unregister_driver(ipoctal->tty_drv); put_tty_driver(ipoctal->tty_drv); - ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_MEM_SPACE); - ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_INT_SPACE); - ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_IO_SPACE); - ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_ID_SPACE); kfree(ipoctal); } diff --git a/drivers/staging/ipack/devices/ipoctal.h b/drivers/ipack/devices/ipoctal.h index c5b4ed46516f..28f1c4233154 100644 --- a/drivers/staging/ipack/devices/ipoctal.h +++ b/drivers/ipack/devices/ipoctal.h @@ -2,9 +2,10 @@ * ipoctal.h * * driver for the IPOCTAL boards - * Copyright (c) 2009 Nicolas Serafini, EIC2 SA - * Copyright (c) 2010,2011 Samuel Iglesias Gonsalvez <siglesia@cern.ch>, CERN - * Copyright (c) 2012 Samuel Iglesias Gonsalvez <siglesias@igalia.com>, Igalia + + * Copyright (C) 2009-2012 CERN (www.cern.ch) + * Author: Nicolas Serafini, EIC2 SA + * Author: Samuel Iglesias Gonsalvez <siglesias@igalia.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 diff --git a/drivers/staging/ipack/devices/scc2698.h b/drivers/ipack/devices/scc2698.h index 96e8d8c30e14..2ad6acd513fa 100644 --- a/drivers/staging/ipack/devices/scc2698.h +++ b/drivers/ipack/devices/scc2698.h @@ -2,9 +2,10 @@ * scc2698.h * * driver for the IPOCTAL boards - * Copyright (c) 2009 Nicolas Serafini, EIC2 SA - * Copyright (c) 2010,2011 Samuel Iglesias Gonsalvez <siglesia@cern.ch>, CERN - * Copyright (c) 2012 Samuel Iglesias Gonsalvez <siglesias@igalia.com>, Igalia + * + * Copyright (C) 2009-2012 CERN (www.cern.ch) + * Author: Nicolas Serafini, EIC2 SA + * Author: Samuel Iglesias Gonsalvez <siglesias@igalia.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 diff --git a/drivers/staging/ipack/ipack.c b/drivers/ipack/ipack.c index d1e0651592a2..7ec6b208b1cb 100644 --- a/drivers/staging/ipack/ipack.c +++ b/drivers/ipack/ipack.c @@ -1,8 +1,8 @@ /* * Industry-pack bus support functions. * - * (C) 2011 Samuel Iglesias Gonsalvez <siglesia@cern.ch>, CERN - * (C) 2012 Samuel Iglesias Gonsalvez <siglesias@igalia.com>, Igalia + * Copyright (C) 2011-2012 CERN (www.cern.ch) + * Author: Samuel Iglesias Gonsalvez <siglesias@igalia.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 @@ -12,8 +12,8 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/idr.h> -#include <asm/io.h> -#include "ipack.h" +#include <linux/io.h> +#include <linux/ipack.h> #define to_ipack_dev(device) container_of(device, struct ipack_device, dev) #define to_ipack_driver(drv) container_of(drv, struct ipack_driver, driver) @@ -24,7 +24,7 @@ static void ipack_device_release(struct device *dev) { struct ipack_device *device = to_ipack_dev(dev); kfree(device->id); - kfree(device); + device->release(device); } static inline const struct ipack_device_id * @@ -85,8 +85,6 @@ static int ipack_bus_remove(struct device *device) return 0; } -#ifdef CONFIG_HOTPLUG - static int ipack_uevent(struct device *dev, struct kobj_uevent_env *env) { struct ipack_device *idev; @@ -104,12 +102,6 @@ static int ipack_uevent(struct device *dev, struct kobj_uevent_env *env) return 0; } -#else /* !CONFIG_HOTPLUG */ - -#define ipack_uevent NULL - -#endif /* !CONFIG_HOTPLUG */ - #define ipack_device_attr(field, format_string) \ static ssize_t \ field##_show(struct device *dev, struct device_attribute *attr, \ @@ -234,7 +226,7 @@ static int ipack_unregister_bus_member(struct device *dev, void *data) struct ipack_device *idev = to_ipack_dev(dev); struct ipack_bus_device *bus = data; - if (idev->bus_nr == bus->bus_nr) + if (idev->bus == bus) ipack_device_unregister(idev); return 1; @@ -242,7 +234,8 @@ static int ipack_unregister_bus_member(struct device *dev, void *data) int ipack_bus_unregister(struct ipack_bus_device *bus) { - bus_for_each_dev(&ipack_bus_type, NULL, bus, ipack_unregister_bus_member); + bus_for_each_dev(&ipack_bus_type, NULL, bus, + ipack_unregister_bus_member); ida_simple_remove(&ipack_ida, bus->bus_nr); kfree(bus); return 0; @@ -351,12 +344,12 @@ static int ipack_device_read_id(struct ipack_device *dev) int i; int ret = 0; - ret = dev->bus->ops->map_space(dev, 0, IPACK_ID_SPACE); - if (ret) { + idmem = ioremap(dev->region[IPACK_ID_SPACE].start, + dev->region[IPACK_ID_SPACE].size); + if (!idmem) { dev_err(&dev->dev, "error mapping memory\n"); - return ret; + return -ENOMEM; } - idmem = dev->id_space.address; /* Determine ID PROM Data Format. If we find the ids "IPAC" or "IPAH" * we are dealing with a IndustryPack format 1 device. If we detect @@ -421,57 +414,44 @@ static int ipack_device_read_id(struct ipack_device *dev) } out: - dev->bus->ops->unmap_space(dev, IPACK_ID_SPACE); + iounmap(idmem); return ret; } -struct ipack_device *ipack_device_register(struct ipack_bus_device *bus, - int slot) +int ipack_device_register(struct ipack_device *dev) { int ret; - struct ipack_device *dev; - - dev = kzalloc(sizeof(struct ipack_device), GFP_KERNEL); - if (!dev) - return NULL; dev->dev.bus = &ipack_bus_type; dev->dev.release = ipack_device_release; - dev->dev.parent = bus->parent; - dev->slot = slot; - dev->bus_nr = bus->bus_nr; - dev->bus = bus; + dev->dev.parent = dev->bus->parent; dev_set_name(&dev->dev, - "ipack-dev.%u.%u", dev->bus_nr, dev->slot); + "ipack-dev.%u.%u", dev->bus->bus_nr, dev->slot); - if (bus->ops->set_clockrate(dev, 8)) + if (dev->bus->ops->set_clockrate(dev, 8)) dev_warn(&dev->dev, "failed to switch to 8 MHz operation for reading of device ID.\n"); - if (bus->ops->reset_timeout(dev)) + if (dev->bus->ops->reset_timeout(dev)) dev_warn(&dev->dev, "failed to reset potential timeout."); ret = ipack_device_read_id(dev); if (ret < 0) { dev_err(&dev->dev, "error reading device id section.\n"); - kfree(dev); - return NULL; + return ret; } /* if the device supports 32 MHz operation, use it. */ if (dev->speed_32mhz) { - ret = bus->ops->set_clockrate(dev, 32); + ret = dev->bus->ops->set_clockrate(dev, 32); if (ret < 0) dev_err(&dev->dev, "failed to switch to 32 MHz operation.\n"); } ret = device_register(&dev->dev); - if (ret < 0) { + if (ret < 0) kfree(dev->id); - kfree(dev); - return NULL; - } - return dev; + return ret; } EXPORT_SYMBOL_GPL(ipack_device_register); diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index d805eef11915..943ca607200c 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -52,8 +52,6 @@ source "drivers/staging/rtl8192e/Kconfig" source "drivers/staging/rtl8712/Kconfig" -source "drivers/staging/rts_pstor/Kconfig" - source "drivers/staging/rts5139/Kconfig" source "drivers/staging/frontier/Kconfig" @@ -120,14 +118,10 @@ source "drivers/staging/omapdrm/Kconfig" source "drivers/staging/android/Kconfig" -source "drivers/staging/telephony/Kconfig" - source "drivers/staging/ozwpan/Kconfig" source "drivers/staging/ccg/Kconfig" -source "drivers/staging/ipack/Kconfig" - source "drivers/staging/gdm72xx/Kconfig" source "drivers/staging/csr/Kconfig" @@ -144,4 +138,6 @@ source "drivers/staging/imx-drm/Kconfig" source "drivers/staging/dgrp/Kconfig" +source "drivers/staging/fwserial/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 76e2ebd596ff..20c764d7ab33 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -19,7 +19,6 @@ obj-$(CONFIG_R8187SE) += rtl8187se/ obj-$(CONFIG_RTL8192U) += rtl8192u/ obj-$(CONFIG_RTL8192E) += rtl8192e/ obj-$(CONFIG_R8712U) += rtl8712/ -obj-$(CONFIG_RTS_PSTOR) += rts_pstor/ obj-$(CONFIG_RTS5139) += rts5139/ obj-$(CONFIG_TRANZPORT) += frontier/ obj-$(CONFIG_IDE_PHISON) += phison/ @@ -29,7 +28,6 @@ obj-$(CONFIG_OCTEON_ETHERNET) += octeon/ obj-$(CONFIG_VT6655) += vt6655/ obj-$(CONFIG_VT6656) += vt6656/ obj-$(CONFIG_VME_BUS) += vme/ -obj-$(CONFIG_IPACK_BUS) += ipack/ obj-$(CONFIG_DX_SEP) += sep/ obj-$(CONFIG_IIO) += iio/ obj-$(CONFIG_ZRAM) += zram/ @@ -53,7 +51,6 @@ obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += ste_rmi4/ obj-$(CONFIG_MFD_NVEC) += nvec/ obj-$(CONFIG_DRM_OMAP) += omapdrm/ obj-$(CONFIG_ANDROID) += android/ -obj-$(CONFIG_PHONE) += telephony/ obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/ obj-$(CONFIG_USB_G_CCG) += ccg/ obj-$(CONFIG_WIMAX_GDM72XX) += gdm72xx/ @@ -64,3 +61,4 @@ obj-$(CONFIG_NET_VENDOR_SILICOM) += silicom/ obj-$(CONFIG_CED1401) += ced1401/ obj-$(CONFIG_DRM_IMX) += imx-drm/ obj-$(CONFIG_DGRP) += dgrp/ +obj-$(CONFIG_FIREWIRE_SERIAL) += fwserial/ diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile index e16fcd51716e..b35a631734d6 100644 --- a/drivers/staging/android/Makefile +++ b/drivers/staging/android/Makefile @@ -1,3 +1,5 @@ +ccflags-y += -I$(src) # needed for trace events + obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o obj-$(CONFIG_ASHMEM) += ashmem.o obj-$(CONFIG_ANDROID_LOGGER) += logger.o diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 5d4610babd8a..4a36e9ab8cf7 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -15,6 +15,8 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <asm/cacheflush.h> #include <linux/fdtable.h> #include <linux/file.h> @@ -35,8 +37,9 @@ #include <linux/slab.h> #include "binder.h" +#include "binder_trace.h" -static DEFINE_MUTEX(binder_lock); +static DEFINE_MUTEX(binder_main_lock); static DEFINE_MUTEX(binder_deferred_lock); static DEFINE_MUTEX(binder_mmap_lock); @@ -411,6 +414,19 @@ static long task_close_fd(struct binder_proc *proc, unsigned int fd) return retval; } +static inline void binder_lock(const char *tag) +{ + trace_binder_lock(tag); + mutex_lock(&binder_main_lock); + trace_binder_locked(tag); +} + +static inline void binder_unlock(const char *tag) +{ + trace_binder_unlock(tag); + mutex_unlock(&binder_main_lock); +} + static void binder_set_nice(long nice) { long min_nice; @@ -420,12 +436,12 @@ static void binder_set_nice(long nice) } min_nice = 20 - current->signal->rlim[RLIMIT_NICE].rlim_cur; binder_debug(BINDER_DEBUG_PRIORITY_CAP, - "binder: %d: nice value %ld not allowed use " - "%ld instead\n", current->pid, nice, min_nice); + "%d: nice value %ld not allowed use %ld instead\n", + current->pid, nice, min_nice); set_user_nice(current, min_nice); if (min_nice < 20) return; - binder_user_error("binder: %d RLIMIT_NICE not set\n", current->pid); + binder_user_error("%d RLIMIT_NICE not set\n", current->pid); } static size_t binder_buffer_size(struct binder_proc *proc, @@ -452,8 +468,8 @@ static void binder_insert_free_buffer(struct binder_proc *proc, new_buffer_size = binder_buffer_size(proc, new_buffer); binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "binder: %d: add free buffer, size %zd, " - "at %p\n", proc->pid, new_buffer_size, new_buffer); + "%d: add free buffer, size %zd, at %p\n", + proc->pid, new_buffer_size, new_buffer); while (*p) { parent = *p; @@ -531,12 +547,14 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, struct mm_struct *mm; binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "binder: %d: %s pages %p-%p\n", proc->pid, + "%d: %s pages %p-%p\n", proc->pid, allocate ? "allocate" : "free", start, end); if (end <= start) return 0; + trace_binder_update_page_range(proc, allocate, start, end); + if (vma) mm = NULL; else @@ -546,7 +564,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, down_write(&mm->mmap_sem); vma = proc->vma; if (vma && mm != proc->vma_vm_mm) { - pr_err("binder: %d: vma mm and task mm mismatch\n", + pr_err("%d: vma mm and task mm mismatch\n", proc->pid); vma = NULL; } @@ -556,8 +574,8 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, goto free_range; if (vma == NULL) { - pr_err("binder: %d: binder_alloc_buf failed to " - "map pages in userspace, no vma\n", proc->pid); + pr_err("%d: binder_alloc_buf failed to map pages in userspace, no vma\n", + proc->pid); goto err_no_vma; } @@ -569,8 +587,8 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, BUG_ON(*page); *page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO); if (*page == NULL) { - pr_err("binder: %d: binder_alloc_buf failed " - "for page at %p\n", proc->pid, page_addr); + pr_err("%d: binder_alloc_buf failed for page at %p\n", + proc->pid, page_addr); goto err_alloc_page_failed; } tmp_area.addr = page_addr; @@ -578,8 +596,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, page_array_ptr = page; ret = map_vm_area(&tmp_area, PAGE_KERNEL, &page_array_ptr); if (ret) { - pr_err("binder: %d: binder_alloc_buf failed " - "to map page at %p in kernel\n", + pr_err("%d: binder_alloc_buf failed to map page at %p in kernel\n", proc->pid, page_addr); goto err_map_kernel_failed; } @@ -587,8 +604,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, (uintptr_t)page_addr + proc->user_buffer_offset; ret = vm_insert_page(vma, user_page_addr, page[0]); if (ret) { - pr_err("binder: %d: binder_alloc_buf failed " - "to map page at %lx in userspace\n", + pr_err("%d: binder_alloc_buf failed to map page at %lx in userspace\n", proc->pid, user_page_addr); goto err_vm_insert_page_failed; } @@ -636,7 +652,7 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, size_t size; if (proc->vma == NULL) { - pr_err("binder: %d: binder_alloc_buf, no vma\n", + pr_err("%d: binder_alloc_buf, no vma\n", proc->pid); return NULL; } @@ -645,16 +661,16 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, ALIGN(offsets_size, sizeof(void *)); if (size < data_size || size < offsets_size) { - binder_user_error("binder: %d: got transaction with invalid " - "size %zd-%zd\n", proc->pid, data_size, offsets_size); + binder_user_error("%d: got transaction with invalid size %zd-%zd\n", + proc->pid, data_size, offsets_size); return NULL; } if (is_async && proc->free_async_space < size + sizeof(struct binder_buffer)) { binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "binder: %d: binder_alloc_buf size %zd" - "failed, no async space left\n", proc->pid, size); + "%d: binder_alloc_buf size %zd failed, no async space left\n", + proc->pid, size); return NULL; } @@ -674,8 +690,8 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, } } if (best_fit == NULL) { - pr_err("binder: %d: binder_alloc_buf size %zd failed, " - "no address space\n", proc->pid, size); + pr_err("%d: binder_alloc_buf size %zd failed, no address space\n", + proc->pid, size); return NULL; } if (n == NULL) { @@ -684,8 +700,8 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, } binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "binder: %d: binder_alloc_buf size %zd got buff" - "er %p size %zd\n", proc->pid, size, buffer, buffer_size); + "%d: binder_alloc_buf size %zd got buffer %p size %zd\n", + proc->pid, size, buffer, buffer_size); has_page_addr = (void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK); @@ -713,17 +729,16 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, binder_insert_free_buffer(proc, new_buffer); } binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "binder: %d: binder_alloc_buf size %zd got " - "%p\n", proc->pid, size, buffer); + "%d: binder_alloc_buf size %zd got %p\n", + proc->pid, size, buffer); buffer->data_size = data_size; buffer->offsets_size = offsets_size; buffer->async_transaction = is_async; if (is_async) { proc->free_async_space -= size + sizeof(struct binder_buffer); binder_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC, - "binder: %d: binder_alloc_buf size %zd " - "async free %zd\n", proc->pid, size, - proc->free_async_space); + "%d: binder_alloc_buf size %zd async free %zd\n", + proc->pid, size, proc->free_async_space); } return buffer; @@ -754,8 +769,8 @@ static void binder_delete_free_buffer(struct binder_proc *proc, if (buffer_end_page(prev) == buffer_end_page(buffer)) free_page_end = 0; binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "binder: %d: merge free, buffer %p " - "share page with %p\n", proc->pid, buffer, prev); + "%d: merge free, buffer %p share page with %p\n", + proc->pid, buffer, prev); } if (!list_is_last(&buffer->entry, &proc->buffers)) { @@ -767,16 +782,14 @@ static void binder_delete_free_buffer(struct binder_proc *proc, buffer_start_page(buffer)) free_page_start = 0; binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "binder: %d: merge free, buffer" - " %p share page with %p\n", proc->pid, - buffer, prev); + "%d: merge free, buffer %p share page with %p\n", + proc->pid, buffer, prev); } } list_del(&buffer->entry); if (free_page_start || free_page_end) { binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "binder: %d: merge free, buffer %p do " - "not share page%s%s with with %p or %p\n", + "%d: merge free, buffer %p do not share page%s%s with with %p or %p\n", proc->pid, buffer, free_page_start ? "" : " end", free_page_end ? "" : " start", prev, next); binder_update_page_range(proc, 0, free_page_start ? @@ -797,8 +810,8 @@ static void binder_free_buf(struct binder_proc *proc, ALIGN(buffer->offsets_size, sizeof(void *)); binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "binder: %d: binder_free_buf %p size %zd buffer" - "_size %zd\n", proc->pid, buffer, size, buffer_size); + "%d: binder_free_buf %p size %zd buffer_size %zd\n", + proc->pid, buffer, size, buffer_size); BUG_ON(buffer->free); BUG_ON(size > buffer_size); @@ -810,9 +823,8 @@ static void binder_free_buf(struct binder_proc *proc, proc->free_async_space += size + sizeof(struct binder_buffer); binder_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC, - "binder: %d: binder_free_buf size %zd " - "async free %zd\n", proc->pid, size, - proc->free_async_space); + "%d: binder_free_buf size %zd async free %zd\n", + proc->pid, size, proc->free_async_space); } binder_update_page_range(proc, 0, @@ -894,7 +906,7 @@ static struct binder_node *binder_new_node(struct binder_proc *proc, INIT_LIST_HEAD(&node->work.entry); INIT_LIST_HEAD(&node->async_todo); binder_debug(BINDER_DEBUG_INTERNAL_REFS, - "binder: %d:%d node %d u%p c%p created\n", + "%d:%d node %d u%p c%p created\n", proc->pid, current->pid, node->debug_id, node->ptr, node->cookie); return node; @@ -909,8 +921,8 @@ static int binder_inc_node(struct binder_node *node, int strong, int internal, node->internal_strong_refs == 0 && !(node == binder_context_mgr_node && node->has_strong_ref)) { - pr_err("binder: invalid inc strong " - "node for %d\n", node->debug_id); + pr_err("invalid inc strong node for %d\n", + node->debug_id); return -EINVAL; } node->internal_strong_refs++; @@ -925,8 +937,8 @@ static int binder_inc_node(struct binder_node *node, int strong, int internal, node->local_weak_refs++; if (!node->has_weak_ref && list_empty(&node->work.entry)) { if (target_list == NULL) { - pr_err("binder: invalid inc weak node " - "for %d\n", node->debug_id); + pr_err("invalid inc weak node for %d\n", + node->debug_id); return -EINVAL; } list_add_tail(&node->work.entry, target_list); @@ -962,12 +974,12 @@ static int binder_dec_node(struct binder_node *node, int strong, int internal) if (node->proc) { rb_erase(&node->rb_node, &node->proc->nodes); binder_debug(BINDER_DEBUG_INTERNAL_REFS, - "binder: refless node %d deleted\n", + "refless node %d deleted\n", node->debug_id); } else { hlist_del(&node->dead_node); binder_debug(BINDER_DEBUG_INTERNAL_REFS, - "binder: dead node %d deleted\n", + "dead node %d deleted\n", node->debug_id); } kfree(node); @@ -1053,14 +1065,13 @@ static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc, hlist_add_head(&new_ref->node_entry, &node->refs); binder_debug(BINDER_DEBUG_INTERNAL_REFS, - "binder: %d new ref %d desc %d for " - "node %d\n", proc->pid, new_ref->debug_id, - new_ref->desc, node->debug_id); + "%d new ref %d desc %d for node %d\n", + proc->pid, new_ref->debug_id, new_ref->desc, + node->debug_id); } else { binder_debug(BINDER_DEBUG_INTERNAL_REFS, - "binder: %d new ref %d desc %d for " - "dead node\n", proc->pid, new_ref->debug_id, - new_ref->desc); + "%d new ref %d desc %d for dead node\n", + proc->pid, new_ref->debug_id, new_ref->desc); } return new_ref; } @@ -1068,9 +1079,9 @@ static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc, static void binder_delete_ref(struct binder_ref *ref) { binder_debug(BINDER_DEBUG_INTERNAL_REFS, - "binder: %d delete ref %d desc %d for " - "node %d\n", ref->proc->pid, ref->debug_id, - ref->desc, ref->node->debug_id); + "%d delete ref %d desc %d for node %d\n", + ref->proc->pid, ref->debug_id, ref->desc, + ref->node->debug_id); rb_erase(&ref->rb_node_desc, &ref->proc->refs_by_desc); rb_erase(&ref->rb_node_node, &ref->proc->refs_by_node); @@ -1080,9 +1091,8 @@ static void binder_delete_ref(struct binder_ref *ref) binder_dec_node(ref->node, 0, 1); if (ref->death) { binder_debug(BINDER_DEBUG_DEAD_BINDER, - "binder: %d delete ref %d desc %d " - "has death notification\n", ref->proc->pid, - ref->debug_id, ref->desc); + "%d delete ref %d desc %d has death notification\n", + ref->proc->pid, ref->debug_id, ref->desc); list_del(&ref->death->work.entry); kfree(ref->death); binder_stats_deleted(BINDER_STAT_DEATH); @@ -1118,8 +1128,7 @@ static int binder_dec_ref(struct binder_ref *ref, int strong) { if (strong) { if (ref->strong == 0) { - binder_user_error("binder: %d invalid dec strong, " - "ref %d desc %d s %d w %d\n", + binder_user_error("%d invalid dec strong, ref %d desc %d s %d w %d\n", ref->proc->pid, ref->debug_id, ref->desc, ref->strong, ref->weak); return -EINVAL; @@ -1133,8 +1142,7 @@ static int binder_dec_ref(struct binder_ref *ref, int strong) } } else { if (ref->weak == 0) { - binder_user_error("binder: %d invalid dec weak, " - "ref %d desc %d s %d w %d\n", + binder_user_error("%d invalid dec weak, ref %d desc %d s %d w %d\n", ref->proc->pid, ref->debug_id, ref->desc, ref->strong, ref->weak); return -EINVAL; @@ -1179,8 +1187,7 @@ static void binder_send_failed_reply(struct binder_transaction *t, } if (target_thread->return_error == BR_OK) { binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, - "binder: send failed reply for " - "transaction %d to %d:%d\n", + "send failed reply for transaction %d to %d:%d\n", t->debug_id, target_thread->proc->pid, target_thread->pid); @@ -1188,9 +1195,8 @@ static void binder_send_failed_reply(struct binder_transaction *t, target_thread->return_error = error_code; wake_up_interruptible(&target_thread->wait); } else { - pr_err("binder: reply failed, target " - "thread, %d:%d, has error code %d " - "already\n", target_thread->proc->pid, + pr_err("reply failed, target thread, %d:%d, has error code %d already\n", + target_thread->proc->pid, target_thread->pid, target_thread->return_error); } @@ -1199,21 +1205,19 @@ static void binder_send_failed_reply(struct binder_transaction *t, struct binder_transaction *next = t->from_parent; binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, - "binder: send failed reply " - "for transaction %d, target dead\n", + "send failed reply for transaction %d, target dead\n", t->debug_id); binder_pop_transaction(target_thread, t); if (next == NULL) { binder_debug(BINDER_DEBUG_DEAD_BINDER, - "binder: reply failed," - " no target thread at root\n"); + "reply failed, no target thread at root\n"); return; } t = next; binder_debug(BINDER_DEBUG_DEAD_BINDER, - "binder: reply failed, no target " - "thread -- retry %d\n", t->debug_id); + "reply failed, no target thread -- retry %d\n", + t->debug_id); } } } @@ -1226,7 +1230,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, int debug_id = buffer->debug_id; binder_debug(BINDER_DEBUG_TRANSACTION, - "binder: %d buffer release %d, size %zd-%zd, failed at %p\n", + "%d buffer release %d, size %zd-%zd, failed at %p\n", proc->pid, buffer->debug_id, buffer->data_size, buffer->offsets_size, failed_at); @@ -1243,9 +1247,8 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, if (*offp > buffer->data_size - sizeof(*fp) || buffer->data_size < sizeof(*fp) || !IS_ALIGNED(*offp, sizeof(void *))) { - pr_err("binder: transaction release %d bad" - "offset %zd, size %zd\n", debug_id, - *offp, buffer->data_size); + pr_err("transaction release %d bad offset %zd, size %zd\n", + debug_id, *offp, buffer->data_size); continue; } fp = (struct flat_binder_object *)(buffer->data + *offp); @@ -1254,8 +1257,8 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, case BINDER_TYPE_WEAK_BINDER: { struct binder_node *node = binder_get_node(proc, fp->binder); if (node == NULL) { - pr_err("binder: transaction release %d" - " bad node %p\n", debug_id, fp->binder); + pr_err("transaction release %d bad node %p\n", + debug_id, fp->binder); break; } binder_debug(BINDER_DEBUG_TRANSACTION, @@ -1267,9 +1270,8 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, case BINDER_TYPE_WEAK_HANDLE: { struct binder_ref *ref = binder_get_ref(proc, fp->handle); if (ref == NULL) { - pr_err("binder: transaction release %d" - " bad handle %ld\n", debug_id, - fp->handle); + pr_err("transaction release %d bad handle %ld\n", + debug_id, fp->handle); break; } binder_debug(BINDER_DEBUG_TRANSACTION, @@ -1286,8 +1288,8 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, break; default: - pr_err("binder: transaction release %d bad " - "object type %lx\n", debug_id, fp->type); + pr_err("transaction release %d bad object type %lx\n", + debug_id, fp->type); break; } } @@ -1320,17 +1322,14 @@ static void binder_transaction(struct binder_proc *proc, if (reply) { in_reply_to = thread->transaction_stack; if (in_reply_to == NULL) { - binder_user_error("binder: %d:%d got reply transaction " - "with no transaction stack\n", + binder_user_error("%d:%d got reply transaction with no transaction stack\n", proc->pid, thread->pid); return_error = BR_FAILED_REPLY; goto err_empty_call_stack; } binder_set_nice(in_reply_to->saved_priority); if (in_reply_to->to_thread != thread) { - binder_user_error("binder: %d:%d got reply transaction " - "with bad transaction stack," - " transaction %d has target %d:%d\n", + binder_user_error("%d:%d got reply transaction with bad transaction stack, transaction %d has target %d:%d\n", proc->pid, thread->pid, in_reply_to->debug_id, in_reply_to->to_proc ? in_reply_to->to_proc->pid : 0, @@ -1347,9 +1346,7 @@ static void binder_transaction(struct binder_proc *proc, goto err_dead_binder; } if (target_thread->transaction_stack != in_reply_to) { - binder_user_error("binder: %d:%d got reply transaction " - "with bad target transaction stack %d, " - "expected %d\n", + binder_user_error("%d:%d got reply transaction with bad target transaction stack %d, expected %d\n", proc->pid, thread->pid, target_thread->transaction_stack ? target_thread->transaction_stack->debug_id : 0, @@ -1365,8 +1362,7 @@ static void binder_transaction(struct binder_proc *proc, struct binder_ref *ref; ref = binder_get_ref(proc, tr->target.handle); if (ref == NULL) { - binder_user_error("binder: %d:%d got " - "transaction to invalid handle\n", + binder_user_error("%d:%d got transaction to invalid handle\n", proc->pid, thread->pid); return_error = BR_FAILED_REPLY; goto err_invalid_target_handle; @@ -1389,9 +1385,7 @@ static void binder_transaction(struct binder_proc *proc, struct binder_transaction *tmp; tmp = thread->transaction_stack; if (tmp->to_thread != thread) { - binder_user_error("binder: %d:%d got new " - "transaction with bad transaction stack" - ", transaction %d has target %d:%d\n", + binder_user_error("%d:%d got new transaction with bad transaction stack, transaction %d has target %d:%d\n", proc->pid, thread->pid, tmp->debug_id, tmp->to_proc ? tmp->to_proc->pid : 0, tmp->to_thread ? @@ -1436,16 +1430,14 @@ static void binder_transaction(struct binder_proc *proc, if (reply) binder_debug(BINDER_DEBUG_TRANSACTION, - "binder: %d:%d BC_REPLY %d -> %d:%d, " - "data %p-%p size %zd-%zd\n", + "%d:%d BC_REPLY %d -> %d:%d, data %p-%p size %zd-%zd\n", proc->pid, thread->pid, t->debug_id, target_proc->pid, target_thread->pid, tr->data.ptr.buffer, tr->data.ptr.offsets, tr->data_size, tr->offsets_size); else binder_debug(BINDER_DEBUG_TRANSACTION, - "binder: %d:%d BC_TRANSACTION %d -> " - "%d - node %d, data %p-%p size %zd-%zd\n", + "%d:%d BC_TRANSACTION %d -> %d - node %d, data %p-%p size %zd-%zd\n", proc->pid, thread->pid, t->debug_id, target_proc->pid, target_node->debug_id, tr->data.ptr.buffer, tr->data.ptr.offsets, @@ -1461,6 +1453,9 @@ static void binder_transaction(struct binder_proc *proc, t->code = tr->code; t->flags = tr->flags; t->priority = task_nice(current); + + trace_binder_transaction(reply, t, target_node); + t->buffer = binder_alloc_buf(target_proc, tr->data_size, tr->offsets_size, !reply && (t->flags & TF_ONE_WAY)); if (t->buffer == NULL) { @@ -1471,27 +1466,27 @@ static void binder_transaction(struct binder_proc *proc, t->buffer->debug_id = t->debug_id; t->buffer->transaction = t; t->buffer->target_node = target_node; + trace_binder_transaction_alloc_buf(t->buffer); if (target_node) binder_inc_node(target_node, 1, 0, NULL); offp = (size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *))); if (copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) { - binder_user_error("binder: %d:%d got transaction with invalid " - "data ptr\n", proc->pid, thread->pid); + binder_user_error("%d:%d got transaction with invalid data ptr\n", + proc->pid, thread->pid); return_error = BR_FAILED_REPLY; goto err_copy_data_failed; } if (copy_from_user(offp, tr->data.ptr.offsets, tr->offsets_size)) { - binder_user_error("binder: %d:%d got transaction with invalid " - "offsets ptr\n", proc->pid, thread->pid); + binder_user_error("%d:%d got transaction with invalid offsets ptr\n", + proc->pid, thread->pid); return_error = BR_FAILED_REPLY; goto err_copy_data_failed; } if (!IS_ALIGNED(tr->offsets_size, sizeof(size_t))) { - binder_user_error("binder: %d:%d got transaction with " - "invalid offsets size, %zd\n", - proc->pid, thread->pid, tr->offsets_size); + binder_user_error("%d:%d got transaction with invalid offsets size, %zd\n", + proc->pid, thread->pid, tr->offsets_size); return_error = BR_FAILED_REPLY; goto err_bad_offset; } @@ -1501,9 +1496,8 @@ static void binder_transaction(struct binder_proc *proc, if (*offp > t->buffer->data_size - sizeof(*fp) || t->buffer->data_size < sizeof(*fp) || !IS_ALIGNED(*offp, sizeof(void *))) { - binder_user_error("binder: %d:%d got transaction with " - "invalid offset, %zd\n", - proc->pid, thread->pid, *offp); + binder_user_error("%d:%d got transaction with invalid offset, %zd\n", + proc->pid, thread->pid, *offp); return_error = BR_FAILED_REPLY; goto err_bad_offset; } @@ -1523,8 +1517,7 @@ static void binder_transaction(struct binder_proc *proc, node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS); } if (fp->cookie != node->cookie) { - binder_user_error("binder: %d:%d sending u%p " - "node %d, cookie mismatch %p != %p\n", + binder_user_error("%d:%d sending u%p node %d, cookie mismatch %p != %p\n", proc->pid, thread->pid, fp->binder, node->debug_id, fp->cookie, node->cookie); @@ -1543,6 +1536,7 @@ static void binder_transaction(struct binder_proc *proc, binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE, &thread->todo); + trace_binder_transaction_node_to_ref(t, node, ref); binder_debug(BINDER_DEBUG_TRANSACTION, " node %d u%p -> ref %d desc %d\n", node->debug_id, node->ptr, ref->debug_id, @@ -1552,10 +1546,9 @@ static void binder_transaction(struct binder_proc *proc, case BINDER_TYPE_WEAK_HANDLE: { struct binder_ref *ref = binder_get_ref(proc, fp->handle); if (ref == NULL) { - binder_user_error("binder: %d:%d got " - "transaction with invalid " - "handle, %ld\n", proc->pid, - thread->pid, fp->handle); + binder_user_error("%d:%d got transaction with invalid handle, %ld\n", + proc->pid, + thread->pid, fp->handle); return_error = BR_FAILED_REPLY; goto err_binder_get_ref_failed; } @@ -1567,6 +1560,7 @@ static void binder_transaction(struct binder_proc *proc, fp->binder = ref->node->ptr; fp->cookie = ref->node->cookie; binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL); + trace_binder_transaction_ref_to_node(t, ref); binder_debug(BINDER_DEBUG_TRANSACTION, " ref %d desc %d -> node %d u%p\n", ref->debug_id, ref->desc, ref->node->debug_id, @@ -1580,6 +1574,8 @@ static void binder_transaction(struct binder_proc *proc, } fp->handle = new_ref->desc; binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL); + trace_binder_transaction_ref_to_ref(t, ref, + new_ref); binder_debug(BINDER_DEBUG_TRANSACTION, " ref %d desc %d -> ref %d desc %d (node %d)\n", ref->debug_id, ref->desc, new_ref->debug_id, @@ -1593,13 +1589,13 @@ static void binder_transaction(struct binder_proc *proc, if (reply) { if (!(in_reply_to->flags & TF_ACCEPT_FDS)) { - binder_user_error("binder: %d:%d got reply with fd, %ld, but target does not allow fds\n", + binder_user_error("%d:%d got reply with fd, %ld, but target does not allow fds\n", proc->pid, thread->pid, fp->handle); return_error = BR_FAILED_REPLY; goto err_fd_not_allowed; } } else if (!target_node->accept_fds) { - binder_user_error("binder: %d:%d got transaction with fd, %ld, but target does not allow fds\n", + binder_user_error("%d:%d got transaction with fd, %ld, but target does not allow fds\n", proc->pid, thread->pid, fp->handle); return_error = BR_FAILED_REPLY; goto err_fd_not_allowed; @@ -1607,7 +1603,7 @@ static void binder_transaction(struct binder_proc *proc, file = fget(fp->handle); if (file == NULL) { - binder_user_error("binder: %d:%d got transaction with invalid fd, %ld\n", + binder_user_error("%d:%d got transaction with invalid fd, %ld\n", proc->pid, thread->pid, fp->handle); return_error = BR_FAILED_REPLY; goto err_fget_failed; @@ -1619,6 +1615,7 @@ static void binder_transaction(struct binder_proc *proc, goto err_get_unused_fd_failed; } task_fd_install(target_proc, target_fd, file); + trace_binder_transaction_fd(t, fp->handle, target_fd); binder_debug(BINDER_DEBUG_TRANSACTION, " fd %ld -> %d\n", fp->handle, target_fd); /* TODO: fput? */ @@ -1626,8 +1623,7 @@ static void binder_transaction(struct binder_proc *proc, } break; default: - binder_user_error("binder: %d:%d got transactio" - "n with invalid object type, %lx\n", + binder_user_error("%d:%d got transaction with invalid object type, %lx\n", proc->pid, thread->pid, fp->type); return_error = BR_FAILED_REPLY; goto err_bad_object_type; @@ -1667,6 +1663,7 @@ err_binder_new_node_failed: err_bad_object_type: err_bad_offset: err_copy_data_failed: + trace_binder_transaction_failed_buffer_release(t->buffer); binder_transaction_buffer_release(target_proc, t->buffer, offp); t->buffer->transaction = NULL; binder_free_buf(target_proc, t->buffer); @@ -1683,7 +1680,7 @@ err_dead_binder: err_invalid_target_handle: err_no_context_mgr_node: binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, - "binder: %d:%d transaction failed %d, size %zd-%zd\n", + "%d:%d transaction failed %d, size %zd-%zd\n", proc->pid, thread->pid, return_error, tr->data_size, tr->offsets_size); @@ -1712,6 +1709,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, if (get_user(cmd, (uint32_t __user *)ptr)) return -EFAULT; ptr += sizeof(uint32_t); + trace_binder_command(cmd); if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.bc)) { binder_stats.bc[_IOC_NR(cmd)]++; proc->stats.bc[_IOC_NR(cmd)]++; @@ -1734,18 +1732,14 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, ref = binder_get_ref_for_node(proc, binder_context_mgr_node); if (ref->desc != target) { - binder_user_error("binder: %d:" - "%d tried to acquire " - "reference to desc 0, " - "got %d instead\n", + binder_user_error("%d:%d tried to acquire reference to desc 0, got %d instead\n", proc->pid, thread->pid, ref->desc); } } else ref = binder_get_ref(proc, target); if (ref == NULL) { - binder_user_error("binder: %d:%d refcou" - "nt change on invalid ref %d\n", + binder_user_error("%d:%d refcount change on invalid ref %d\n", proc->pid, thread->pid, target); break; } @@ -1769,7 +1763,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, break; } binder_debug(BINDER_DEBUG_USER_REFS, - "binder: %d:%d %s ref %d desc %d s %d w %d for node %d\n", + "%d:%d %s ref %d desc %d s %d w %d for node %d\n", proc->pid, thread->pid, debug_string, ref->debug_id, ref->desc, ref->strong, ref->weak, ref->node->debug_id); break; @@ -1788,8 +1782,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, ptr += sizeof(void *); node = binder_get_node(proc, node_ptr); if (node == NULL) { - binder_user_error("binder: %d:%d " - "%s u%p no match\n", + binder_user_error("%d:%d %s u%p no match\n", proc->pid, thread->pid, cmd == BC_INCREFS_DONE ? "BC_INCREFS_DONE" : @@ -1798,8 +1791,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, break; } if (cookie != node->cookie) { - binder_user_error("binder: %d:%d %s u%p node %d" - " cookie mismatch %p != %p\n", + binder_user_error("%d:%d %s u%p node %d cookie mismatch %p != %p\n", proc->pid, thread->pid, cmd == BC_INCREFS_DONE ? "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE", @@ -1809,9 +1801,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, } if (cmd == BC_ACQUIRE_DONE) { if (node->pending_strong_ref == 0) { - binder_user_error("binder: %d:%d " - "BC_ACQUIRE_DONE node %d has " - "no pending acquire request\n", + binder_user_error("%d:%d BC_ACQUIRE_DONE node %d has no pending acquire request\n", proc->pid, thread->pid, node->debug_id); break; @@ -1819,9 +1809,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, node->pending_strong_ref = 0; } else { if (node->pending_weak_ref == 0) { - binder_user_error("binder: %d:%d " - "BC_INCREFS_DONE node %d has " - "no pending increfs request\n", + binder_user_error("%d:%d BC_INCREFS_DONE node %d has no pending increfs request\n", proc->pid, thread->pid, node->debug_id); break; @@ -1830,17 +1818,17 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, } binder_dec_node(node, cmd == BC_ACQUIRE_DONE, 0); binder_debug(BINDER_DEBUG_USER_REFS, - "binder: %d:%d %s node %d ls %d lw %d\n", + "%d:%d %s node %d ls %d lw %d\n", proc->pid, thread->pid, cmd == BC_INCREFS_DONE ? "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE", node->debug_id, node->local_strong_refs, node->local_weak_refs); break; } case BC_ATTEMPT_ACQUIRE: - pr_err("binder: BC_ATTEMPT_ACQUIRE not supported\n"); + pr_err("BC_ATTEMPT_ACQUIRE not supported\n"); return -EINVAL; case BC_ACQUIRE_RESULT: - pr_err("binder: BC_ACQUIRE_RESULT not supported\n"); + pr_err("BC_ACQUIRE_RESULT not supported\n"); return -EINVAL; case BC_FREE_BUFFER: { @@ -1853,20 +1841,17 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, buffer = binder_buffer_lookup(proc, data_ptr); if (buffer == NULL) { - binder_user_error("binder: %d:%d " - "BC_FREE_BUFFER u%p no match\n", + binder_user_error("%d:%d BC_FREE_BUFFER u%p no match\n", proc->pid, thread->pid, data_ptr); break; } if (!buffer->allow_user_free) { - binder_user_error("binder: %d:%d " - "BC_FREE_BUFFER u%p matched " - "unreturned buffer\n", + binder_user_error("%d:%d BC_FREE_BUFFER u%p matched unreturned buffer\n", proc->pid, thread->pid, data_ptr); break; } binder_debug(BINDER_DEBUG_FREE_BUFFER, - "binder: %d:%d BC_FREE_BUFFER u%p found buffer %d for %s transaction\n", + "%d:%d BC_FREE_BUFFER u%p found buffer %d for %s transaction\n", proc->pid, thread->pid, data_ptr, buffer->debug_id, buffer->transaction ? "active" : "finished"); @@ -1881,6 +1866,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, else list_move_tail(buffer->target_node->async_todo.next, &thread->todo); } + trace_binder_transaction_buffer_release(buffer); binder_transaction_buffer_release(proc, buffer, NULL); binder_free_buf(proc, buffer); break; @@ -1899,19 +1885,15 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, case BC_REGISTER_LOOPER: binder_debug(BINDER_DEBUG_THREADS, - "binder: %d:%d BC_REGISTER_LOOPER\n", + "%d:%d BC_REGISTER_LOOPER\n", proc->pid, thread->pid); if (thread->looper & BINDER_LOOPER_STATE_ENTERED) { thread->looper |= BINDER_LOOPER_STATE_INVALID; - binder_user_error("binder: %d:%d ERROR:" - " BC_REGISTER_LOOPER called " - "after BC_ENTER_LOOPER\n", + binder_user_error("%d:%d ERROR: BC_REGISTER_LOOPER called after BC_ENTER_LOOPER\n", proc->pid, thread->pid); } else if (proc->requested_threads == 0) { thread->looper |= BINDER_LOOPER_STATE_INVALID; - binder_user_error("binder: %d:%d ERROR:" - " BC_REGISTER_LOOPER called " - "without request\n", + binder_user_error("%d:%d ERROR: BC_REGISTER_LOOPER called without request\n", proc->pid, thread->pid); } else { proc->requested_threads--; @@ -1921,20 +1903,18 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, break; case BC_ENTER_LOOPER: binder_debug(BINDER_DEBUG_THREADS, - "binder: %d:%d BC_ENTER_LOOPER\n", + "%d:%d BC_ENTER_LOOPER\n", proc->pid, thread->pid); if (thread->looper & BINDER_LOOPER_STATE_REGISTERED) { thread->looper |= BINDER_LOOPER_STATE_INVALID; - binder_user_error("binder: %d:%d ERROR:" - " BC_ENTER_LOOPER called after " - "BC_REGISTER_LOOPER\n", + binder_user_error("%d:%d ERROR: BC_ENTER_LOOPER called after BC_REGISTER_LOOPER\n", proc->pid, thread->pid); } thread->looper |= BINDER_LOOPER_STATE_ENTERED; break; case BC_EXIT_LOOPER: binder_debug(BINDER_DEBUG_THREADS, - "binder: %d:%d BC_EXIT_LOOPER\n", + "%d:%d BC_EXIT_LOOPER\n", proc->pid, thread->pid); thread->looper |= BINDER_LOOPER_STATE_EXITED; break; @@ -1954,8 +1934,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, ptr += sizeof(void *); ref = binder_get_ref(proc, target); if (ref == NULL) { - binder_user_error("binder: %d:%d %s " - "invalid ref %d\n", + binder_user_error("%d:%d %s invalid ref %d\n", proc->pid, thread->pid, cmd == BC_REQUEST_DEATH_NOTIFICATION ? "BC_REQUEST_DEATH_NOTIFICATION" : @@ -1965,7 +1944,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, } binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION, - "binder: %d:%d %s %p ref %d desc %d s %d w %d for node %d\n", + "%d:%d %s %p ref %d desc %d s %d w %d for node %d\n", proc->pid, thread->pid, cmd == BC_REQUEST_DEATH_NOTIFICATION ? "BC_REQUEST_DEATH_NOTIFICATION" : @@ -1975,10 +1954,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, if (cmd == BC_REQUEST_DEATH_NOTIFICATION) { if (ref->death) { - binder_user_error("binder: %d:%" - "d BC_REQUEST_DEATH_NOTI" - "FICATION death notific" - "ation already set\n", + binder_user_error("%d:%d BC_REQUEST_DEATH_NOTIFICATION death notification already set\n", proc->pid, thread->pid); break; } @@ -1986,8 +1962,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, if (death == NULL) { thread->return_error = BR_ERROR; binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, - "binder: %d:%d " - "BC_REQUEST_DEATH_NOTIFICATION failed\n", + "%d:%d BC_REQUEST_DEATH_NOTIFICATION failed\n", proc->pid, thread->pid); break; } @@ -2006,20 +1981,13 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, } } else { if (ref->death == NULL) { - binder_user_error("binder: %d:%" - "d BC_CLEAR_DEATH_NOTIFI" - "CATION death notificat" - "ion not active\n", + binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification not active\n", proc->pid, thread->pid); break; } death = ref->death; if (death->cookie != cookie) { - binder_user_error("binder: %d:%" - "d BC_CLEAR_DEATH_NOTIFI" - "CATION death notificat" - "ion cookie mismatch " - "%p != %p\n", + binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification cookie mismatch %p != %p\n", proc->pid, thread->pid, death->cookie, cookie); break; @@ -2055,11 +2023,10 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, } } binder_debug(BINDER_DEBUG_DEAD_BINDER, - "binder: %d:%d BC_DEAD_BINDER_DONE %p found %p\n", + "%d:%d BC_DEAD_BINDER_DONE %p found %p\n", proc->pid, thread->pid, cookie, death); if (death == NULL) { - binder_user_error("binder: %d:%d BC_DEAD" - "_BINDER_DONE %p not found\n", + binder_user_error("%d:%d BC_DEAD_BINDER_DONE %p not found\n", proc->pid, thread->pid, cookie); break; } @@ -2077,7 +2044,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, } break; default: - pr_err("binder: %d:%d unknown command %d\n", + pr_err("%d:%d unknown command %d\n", proc->pid, thread->pid, cmd); return -EINVAL; } @@ -2089,6 +2056,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, void binder_stat_br(struct binder_proc *proc, struct binder_thread *thread, uint32_t cmd) { + trace_binder_return(cmd); if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.br)) { binder_stats.br[_IOC_NR(cmd)]++; proc->stats.br[_IOC_NR(cmd)]++; @@ -2135,6 +2103,7 @@ retry: if (put_user(thread->return_error2, (uint32_t __user *)ptr)) return -EFAULT; ptr += sizeof(uint32_t); + binder_stat_br(proc, thread, thread->return_error2); if (ptr == end) goto done; thread->return_error2 = BR_OK; @@ -2142,6 +2111,7 @@ retry: if (put_user(thread->return_error, (uint32_t __user *)ptr)) return -EFAULT; ptr += sizeof(uint32_t); + binder_stat_br(proc, thread, thread->return_error); thread->return_error = BR_OK; goto done; } @@ -2150,13 +2120,16 @@ retry: thread->looper |= BINDER_LOOPER_STATE_WAITING; if (wait_for_proc_work) proc->ready_threads++; - mutex_unlock(&binder_lock); + + binder_unlock(__func__); + + trace_binder_wait_for_work(wait_for_proc_work, + !!thread->transaction_stack, + !list_empty(&thread->todo)); if (wait_for_proc_work) { if (!(thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED))) { - binder_user_error("binder: %d:%d ERROR: Thread waiting " - "for process work before calling BC_REGISTER_" - "LOOPER or BC_ENTER_LOOPER (state %x)\n", + binder_user_error("%d:%d ERROR: Thread waiting for process work before calling BC_REGISTER_LOOPER or BC_ENTER_LOOPER (state %x)\n", proc->pid, thread->pid, thread->looper); wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2); @@ -2174,7 +2147,9 @@ retry: } else ret = wait_event_interruptible(thread->wait, binder_has_thread_work(thread)); } - mutex_lock(&binder_lock); + + binder_lock(__func__); + if (wait_for_proc_work) proc->ready_threads--; thread->looper &= ~BINDER_LOOPER_STATE_WAITING; @@ -2213,7 +2188,7 @@ retry: binder_stat_br(proc, thread, cmd); binder_debug(BINDER_DEBUG_TRANSACTION_COMPLETE, - "binder: %d:%d BR_TRANSACTION_COMPLETE\n", + "%d:%d BR_TRANSACTION_COMPLETE\n", proc->pid, thread->pid); list_del(&w->entry); @@ -2260,13 +2235,13 @@ retry: binder_stat_br(proc, thread, cmd); binder_debug(BINDER_DEBUG_USER_REFS, - "binder: %d:%d %s %d u%p c%p\n", + "%d:%d %s %d u%p c%p\n", proc->pid, thread->pid, cmd_name, node->debug_id, node->ptr, node->cookie); } else { list_del_init(&w->entry); if (!weak && !strong) { binder_debug(BINDER_DEBUG_INTERNAL_REFS, - "binder: %d:%d node %d u%p c%p deleted\n", + "%d:%d node %d u%p c%p deleted\n", proc->pid, thread->pid, node->debug_id, node->ptr, node->cookie); rb_erase(&node->rb_node, &proc->nodes); @@ -2274,7 +2249,7 @@ retry: binder_stats_deleted(BINDER_STAT_NODE); } else { binder_debug(BINDER_DEBUG_INTERNAL_REFS, - "binder: %d:%d node %d u%p c%p state unchanged\n", + "%d:%d node %d u%p c%p state unchanged\n", proc->pid, thread->pid, node->debug_id, node->ptr, node->cookie); } @@ -2297,8 +2272,9 @@ retry: if (put_user(death->cookie, (void * __user *)ptr)) return -EFAULT; ptr += sizeof(void *); + binder_stat_br(proc, thread, cmd); binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION, - "binder: %d:%d %s %p\n", + "%d:%d %s %p\n", proc->pid, thread->pid, cmd == BR_DEAD_BINDER ? "BR_DEAD_BINDER" : @@ -2364,10 +2340,10 @@ retry: return -EFAULT; ptr += sizeof(tr); + trace_binder_transaction_received(t); binder_stat_br(proc, thread, cmd); binder_debug(BINDER_DEBUG_TRANSACTION, - "binder: %d:%d %s %d %d:%d, cmd %d" - "size %zd-%zd ptr %p-%p\n", + "%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %p-%p\n", proc->pid, thread->pid, (cmd == BR_TRANSACTION) ? "BR_TRANSACTION" : "BR_REPLY", @@ -2400,10 +2376,11 @@ done: /*spawn a new thread if we leave this out */) { proc->requested_threads++; binder_debug(BINDER_DEBUG_THREADS, - "binder: %d:%d BR_SPAWN_LOOPER\n", + "%d:%d BR_SPAWN_LOOPER\n", proc->pid, thread->pid); if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer)) return -EFAULT; + binder_stat_br(proc, thread, BR_SPAWN_LOOPER); } return 0; } @@ -2424,7 +2401,7 @@ static void binder_release_work(struct list_head *list) binder_send_failed_reply(t, BR_DEAD_REPLY); } else { binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, - "binder: undelivered transaction %d\n", + "undelivered transaction %d\n", t->debug_id); t->buffer->transaction = NULL; kfree(t); @@ -2433,7 +2410,7 @@ static void binder_release_work(struct list_head *list) } break; case BINDER_WORK_TRANSACTION_COMPLETE: { binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, - "binder: undelivered TRANSACTION_COMPLETE\n"); + "undelivered TRANSACTION_COMPLETE\n"); kfree(w); binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE); } break; @@ -2443,13 +2420,13 @@ static void binder_release_work(struct list_head *list) death = container_of(w, struct binder_ref_death, work); binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, - "binder: undelivered death notification, %p\n", + "undelivered death notification, %p\n", death->cookie); kfree(death); binder_stats_deleted(BINDER_STAT_DEATH); } break; default: - pr_err("binder: unexpected work type, %d, not freed\n", + pr_err("unexpected work type, %d, not freed\n", w->type); break; } @@ -2506,8 +2483,8 @@ static int binder_free_thread(struct binder_proc *proc, while (t) { active_transactions++; binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, - "binder: release %d:%d transaction %d " - "%s, still active\n", proc->pid, thread->pid, + "release %d:%d transaction %d %s, still active\n", + proc->pid, thread->pid, t->debug_id, (t->to_thread == thread) ? "in" : "out"); @@ -2540,12 +2517,14 @@ static unsigned int binder_poll(struct file *filp, struct binder_thread *thread = NULL; int wait_for_proc_work; - mutex_lock(&binder_lock); + binder_lock(__func__); + thread = binder_get_thread(proc); wait_for_proc_work = thread->transaction_stack == NULL && list_empty(&thread->todo) && thread->return_error == BR_OK; - mutex_unlock(&binder_lock); + + binder_unlock(__func__); if (wait_for_proc_work) { if (binder_has_proc_work(proc, thread)) @@ -2573,11 +2552,13 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /*pr_info("binder_ioctl: %d:%d %x %lx\n", proc->pid, current->pid, cmd, arg);*/ + trace_binder_ioctl(cmd, arg); + ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2); if (ret) - return ret; + goto err_unlocked; - mutex_lock(&binder_lock); + binder_lock(__func__); thread = binder_get_thread(proc); if (thread == NULL) { ret = -ENOMEM; @@ -2596,12 +2577,13 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) goto err; } binder_debug(BINDER_DEBUG_READ_WRITE, - "binder: %d:%d write %ld at %08lx, read %ld at %08lx\n", - proc->pid, thread->pid, bwr.write_size, bwr.write_buffer, - bwr.read_size, bwr.read_buffer); + "%d:%d write %ld at %08lx, read %ld at %08lx\n", + proc->pid, thread->pid, bwr.write_size, + bwr.write_buffer, bwr.read_size, bwr.read_buffer); if (bwr.write_size > 0) { ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed); + trace_binder_write_done(ret); if (ret < 0) { bwr.read_consumed = 0; if (copy_to_user(ubuf, &bwr, sizeof(bwr))) @@ -2611,6 +2593,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } if (bwr.read_size > 0) { ret = binder_thread_read(proc, thread, (void __user *)bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK); + trace_binder_read_done(ret); if (!list_empty(&proc->todo)) wake_up_interruptible(&proc->wait); if (ret < 0) { @@ -2620,7 +2603,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } } binder_debug(BINDER_DEBUG_READ_WRITE, - "binder: %d:%d wrote %ld of %ld, read return %ld of %ld\n", + "%d:%d wrote %ld of %ld, read return %ld of %ld\n", proc->pid, thread->pid, bwr.write_consumed, bwr.write_size, bwr.read_consumed, bwr.read_size); if (copy_to_user(ubuf, &bwr, sizeof(bwr))) { @@ -2637,14 +2620,13 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) break; case BINDER_SET_CONTEXT_MGR: if (binder_context_mgr_node != NULL) { - pr_err("binder: BINDER_SET_CONTEXT_MGR already set\n"); + pr_err("BINDER_SET_CONTEXT_MGR already set\n"); ret = -EBUSY; goto err; } if (uid_valid(binder_context_mgr_uid)) { if (!uid_eq(binder_context_mgr_uid, current->cred->euid)) { - pr_err("binder: BINDER_SET_" - "CONTEXT_MGR bad uid %d != %d\n", + pr_err("BINDER_SET_CONTEXT_MGR bad uid %d != %d\n", from_kuid(&init_user_ns, current->cred->euid), from_kuid(&init_user_ns, binder_context_mgr_uid)); ret = -EPERM; @@ -2663,7 +2645,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) binder_context_mgr_node->has_weak_ref = 1; break; case BINDER_THREAD_EXIT: - binder_debug(BINDER_DEBUG_THREADS, "binder: %d:%d exit\n", + binder_debug(BINDER_DEBUG_THREADS, "%d:%d exit\n", proc->pid, thread->pid); binder_free_thread(proc, thread); thread = NULL; @@ -2686,10 +2668,12 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) err: if (thread) thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN; - mutex_unlock(&binder_lock); + binder_unlock(__func__); wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2); if (ret && ret != -ERESTARTSYS) - pr_info("binder: %d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret); + pr_info("%d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret); +err_unlocked: + trace_binder_ioctl_done(ret); return ret; } @@ -2697,7 +2681,7 @@ static void binder_vma_open(struct vm_area_struct *vma) { struct binder_proc *proc = vma->vm_private_data; binder_debug(BINDER_DEBUG_OPEN_CLOSE, - "binder: %d open vm area %lx-%lx (%ld K) vma %lx pagep %lx\n", + "%d open vm area %lx-%lx (%ld K) vma %lx pagep %lx\n", proc->pid, vma->vm_start, vma->vm_end, (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, (unsigned long)pgprot_val(vma->vm_page_prot)); @@ -2707,7 +2691,7 @@ static void binder_vma_close(struct vm_area_struct *vma) { struct binder_proc *proc = vma->vm_private_data; binder_debug(BINDER_DEBUG_OPEN_CLOSE, - "binder: %d close vm area %lx-%lx (%ld K) vma %lx pagep %lx\n", + "%d close vm area %lx-%lx (%ld K) vma %lx pagep %lx\n", proc->pid, vma->vm_start, vma->vm_end, (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, (unsigned long)pgprot_val(vma->vm_page_prot)); @@ -2835,13 +2819,16 @@ static int binder_open(struct inode *nodp, struct file *filp) INIT_LIST_HEAD(&proc->todo); init_waitqueue_head(&proc->wait); proc->default_priority = task_nice(current); - mutex_lock(&binder_lock); + + binder_lock(__func__); + binder_stats_created(BINDER_STAT_PROC); hlist_add_head(&proc->proc_node, &binder_procs); proc->pid = current->group_leader->pid; INIT_LIST_HEAD(&proc->delivered_death); filp->private_data = proc; - mutex_unlock(&binder_lock); + + binder_unlock(__func__); if (binder_debugfs_dir_entry_proc) { char strbuf[11]; @@ -2949,9 +2936,8 @@ static void binder_deferred_release(struct binder_proc *proc) } } binder_debug(BINDER_DEBUG_DEAD_BINDER, - "binder: node %d now dead, " - "refs %d, death %d\n", node->debug_id, - incoming_refs, death); + "node %d now dead, refs %d, death %d\n", + node->debug_id, incoming_refs, death); } } outgoing_refs = 0; @@ -2972,8 +2958,7 @@ static void binder_deferred_release(struct binder_proc *proc) if (t) { t->buffer = NULL; buffer->transaction = NULL; - pr_err("binder: release proc %d, " - "transaction %d, not freed\n", + pr_err("release proc %d, transaction %d, not freed\n", proc->pid, t->debug_id); /*BUG();*/ } @@ -2990,8 +2975,7 @@ static void binder_deferred_release(struct binder_proc *proc) if (proc->pages[i]) { void *page_addr = proc->buffer + i * PAGE_SIZE; binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "binder_release: %d: " - "page %d at %p not freed\n", + "binder_release: %d: page %d at %p not freed\n", proc->pid, i, page_addr); unmap_kernel_range((unsigned long)page_addr, @@ -3007,9 +2991,7 @@ static void binder_deferred_release(struct binder_proc *proc) put_task_struct(proc->tsk); binder_debug(BINDER_DEBUG_OPEN_CLOSE, - "binder_release: %d threads %d, nodes %d (ref %d), " - "refs %d, active transactions %d, buffers %d, " - "pages %d\n", + "binder_release: %d threads %d, nodes %d (ref %d), refs %d, active transactions %d, buffers %d, pages %d\n", proc->pid, threads, nodes, incoming_refs, outgoing_refs, active_transactions, buffers, page_count); @@ -3023,7 +3005,7 @@ static void binder_deferred_func(struct work_struct *work) int defer; do { - mutex_lock(&binder_lock); + binder_lock(__func__); mutex_lock(&binder_deferred_lock); if (!hlist_empty(&binder_deferred_list)) { proc = hlist_entry(binder_deferred_list.first, @@ -3050,7 +3032,7 @@ static void binder_deferred_func(struct work_struct *work) if (defer & BINDER_DEFERRED_RELEASE) binder_deferred_release(proc); /* frees proc */ - mutex_unlock(&binder_lock); + binder_unlock(__func__); if (files) put_files_struct(files); } while (proc); @@ -3391,7 +3373,7 @@ static int binder_state_show(struct seq_file *m, void *unused) int do_lock = !binder_debug_no_lock; if (do_lock) - mutex_lock(&binder_lock); + binder_lock(__func__); seq_puts(m, "binder state:\n"); @@ -3403,7 +3385,7 @@ static int binder_state_show(struct seq_file *m, void *unused) hlist_for_each_entry(proc, pos, &binder_procs, proc_node) print_binder_proc(m, proc, 1); if (do_lock) - mutex_unlock(&binder_lock); + binder_unlock(__func__); return 0; } @@ -3414,7 +3396,7 @@ static int binder_stats_show(struct seq_file *m, void *unused) int do_lock = !binder_debug_no_lock; if (do_lock) - mutex_lock(&binder_lock); + binder_lock(__func__); seq_puts(m, "binder stats:\n"); @@ -3423,7 +3405,7 @@ static int binder_stats_show(struct seq_file *m, void *unused) hlist_for_each_entry(proc, pos, &binder_procs, proc_node) print_binder_proc_stats(m, proc); if (do_lock) - mutex_unlock(&binder_lock); + binder_unlock(__func__); return 0; } @@ -3434,13 +3416,13 @@ static int binder_transactions_show(struct seq_file *m, void *unused) int do_lock = !binder_debug_no_lock; if (do_lock) - mutex_lock(&binder_lock); + binder_lock(__func__); seq_puts(m, "binder transactions:\n"); hlist_for_each_entry(proc, pos, &binder_procs, proc_node) print_binder_proc(m, proc, 0); if (do_lock) - mutex_unlock(&binder_lock); + binder_unlock(__func__); return 0; } @@ -3450,11 +3432,11 @@ static int binder_proc_show(struct seq_file *m, void *unused) int do_lock = !binder_debug_no_lock; if (do_lock) - mutex_lock(&binder_lock); + binder_lock(__func__); seq_puts(m, "binder proc state:\n"); print_binder_proc(m, proc, 1); if (do_lock) - mutex_unlock(&binder_lock); + binder_unlock(__func__); return 0; } @@ -3549,4 +3531,7 @@ static int __init binder_init(void) device_initcall(binder_init); +#define CREATE_TRACE_POINTS +#include "binder_trace.h" + MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/android/binder_trace.h b/drivers/staging/android/binder_trace.h new file mode 100644 index 000000000000..82a567c2af67 --- /dev/null +++ b/drivers/staging/android/binder_trace.h @@ -0,0 +1,327 @@ +/* + * 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. + * + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM binder + +#if !defined(_BINDER_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define _BINDER_TRACE_H + +#include <linux/tracepoint.h> + +struct binder_buffer; +struct binder_node; +struct binder_proc; +struct binder_ref; +struct binder_thread; +struct binder_transaction; + +TRACE_EVENT(binder_ioctl, + TP_PROTO(unsigned int cmd, unsigned long arg), + TP_ARGS(cmd, arg), + + TP_STRUCT__entry( + __field(unsigned int, cmd) + __field(unsigned long, arg) + ), + TP_fast_assign( + __entry->cmd = cmd; + __entry->arg = arg; + ), + TP_printk("cmd=0x%x arg=0x%lx", __entry->cmd, __entry->arg) +); + +DECLARE_EVENT_CLASS(binder_lock_class, + TP_PROTO(const char *tag), + TP_ARGS(tag), + TP_STRUCT__entry( + __field(const char *, tag) + ), + TP_fast_assign( + __entry->tag = tag; + ), + TP_printk("tag=%s", __entry->tag) +); + +#define DEFINE_BINDER_LOCK_EVENT(name) \ +DEFINE_EVENT(binder_lock_class, name, \ + TP_PROTO(const char *func), \ + TP_ARGS(func)) + +DEFINE_BINDER_LOCK_EVENT(binder_lock); +DEFINE_BINDER_LOCK_EVENT(binder_locked); +DEFINE_BINDER_LOCK_EVENT(binder_unlock); + +DECLARE_EVENT_CLASS(binder_function_return_class, + TP_PROTO(int ret), + TP_ARGS(ret), + TP_STRUCT__entry( + __field(int, ret) + ), + TP_fast_assign( + __entry->ret = ret; + ), + TP_printk("ret=%d", __entry->ret) +); + +#define DEFINE_BINDER_FUNCTION_RETURN_EVENT(name) \ +DEFINE_EVENT(binder_function_return_class, name, \ + TP_PROTO(int ret), \ + TP_ARGS(ret)) + +DEFINE_BINDER_FUNCTION_RETURN_EVENT(binder_ioctl_done); +DEFINE_BINDER_FUNCTION_RETURN_EVENT(binder_write_done); +DEFINE_BINDER_FUNCTION_RETURN_EVENT(binder_read_done); + +TRACE_EVENT(binder_wait_for_work, + TP_PROTO(bool proc_work, bool transaction_stack, bool thread_todo), + TP_ARGS(proc_work, transaction_stack, thread_todo), + + TP_STRUCT__entry( + __field(bool, proc_work) + __field(bool, transaction_stack) + __field(bool, thread_todo) + ), + TP_fast_assign( + __entry->proc_work = proc_work; + __entry->transaction_stack = transaction_stack; + __entry->thread_todo = thread_todo; + ), + TP_printk("proc_work=%d transaction_stack=%d thread_todo=%d", + __entry->proc_work, __entry->transaction_stack, + __entry->thread_todo) +); + +TRACE_EVENT(binder_transaction, + TP_PROTO(bool reply, struct binder_transaction *t, + struct binder_node *target_node), + TP_ARGS(reply, t, target_node), + TP_STRUCT__entry( + __field(int, debug_id) + __field(int, target_node) + __field(int, to_proc) + __field(int, to_thread) + __field(int, reply) + __field(unsigned int, code) + __field(unsigned int, flags) + ), + TP_fast_assign( + __entry->debug_id = t->debug_id; + __entry->target_node = target_node ? target_node->debug_id : 0; + __entry->to_proc = t->to_proc->pid; + __entry->to_thread = t->to_thread ? t->to_thread->pid : 0; + __entry->reply = reply; + __entry->code = t->code; + __entry->flags = t->flags; + ), + TP_printk("transaction=%d dest_node=%d dest_proc=%d dest_thread=%d reply=%d flags=0x%x code=0x%x", + __entry->debug_id, __entry->target_node, + __entry->to_proc, __entry->to_thread, + __entry->reply, __entry->flags, __entry->code) +); + +TRACE_EVENT(binder_transaction_received, + TP_PROTO(struct binder_transaction *t), + TP_ARGS(t), + + TP_STRUCT__entry( + __field(int, debug_id) + ), + TP_fast_assign( + __entry->debug_id = t->debug_id; + ), + TP_printk("transaction=%d", __entry->debug_id) +); + +TRACE_EVENT(binder_transaction_node_to_ref, + TP_PROTO(struct binder_transaction *t, struct binder_node *node, + struct binder_ref *ref), + TP_ARGS(t, node, ref), + + TP_STRUCT__entry( + __field(int, debug_id) + __field(int, node_debug_id) + __field(void __user *, node_ptr) + __field(int, ref_debug_id) + __field(uint32_t, ref_desc) + ), + TP_fast_assign( + __entry->debug_id = t->debug_id; + __entry->node_debug_id = node->debug_id; + __entry->node_ptr = node->ptr; + __entry->ref_debug_id = ref->debug_id; + __entry->ref_desc = ref->desc; + ), + TP_printk("transaction=%d node=%d src_ptr=0x%p ==> dest_ref=%d dest_desc=%d", + __entry->debug_id, __entry->node_debug_id, __entry->node_ptr, + __entry->ref_debug_id, __entry->ref_desc) +); + +TRACE_EVENT(binder_transaction_ref_to_node, + TP_PROTO(struct binder_transaction *t, struct binder_ref *ref), + TP_ARGS(t, ref), + + TP_STRUCT__entry( + __field(int, debug_id) + __field(int, ref_debug_id) + __field(uint32_t, ref_desc) + __field(int, node_debug_id) + __field(void __user *, node_ptr) + ), + TP_fast_assign( + __entry->debug_id = t->debug_id; + __entry->ref_debug_id = ref->debug_id; + __entry->ref_desc = ref->desc; + __entry->node_debug_id = ref->node->debug_id; + __entry->node_ptr = ref->node->ptr; + ), + TP_printk("transaction=%d node=%d src_ref=%d src_desc=%d ==> dest_ptr=0x%p", + __entry->debug_id, __entry->node_debug_id, + __entry->ref_debug_id, __entry->ref_desc, __entry->node_ptr) +); + +TRACE_EVENT(binder_transaction_ref_to_ref, + TP_PROTO(struct binder_transaction *t, struct binder_ref *src_ref, + struct binder_ref *dest_ref), + TP_ARGS(t, src_ref, dest_ref), + + TP_STRUCT__entry( + __field(int, debug_id) + __field(int, node_debug_id) + __field(int, src_ref_debug_id) + __field(uint32_t, src_ref_desc) + __field(int, dest_ref_debug_id) + __field(uint32_t, dest_ref_desc) + ), + TP_fast_assign( + __entry->debug_id = t->debug_id; + __entry->node_debug_id = src_ref->node->debug_id; + __entry->src_ref_debug_id = src_ref->debug_id; + __entry->src_ref_desc = src_ref->desc; + __entry->dest_ref_debug_id = dest_ref->debug_id; + __entry->dest_ref_desc = dest_ref->desc; + ), + TP_printk("transaction=%d node=%d src_ref=%d src_desc=%d ==> dest_ref=%d dest_desc=%d", + __entry->debug_id, __entry->node_debug_id, + __entry->src_ref_debug_id, __entry->src_ref_desc, + __entry->dest_ref_debug_id, __entry->dest_ref_desc) +); + +TRACE_EVENT(binder_transaction_fd, + TP_PROTO(struct binder_transaction *t, int src_fd, int dest_fd), + TP_ARGS(t, src_fd, dest_fd), + + TP_STRUCT__entry( + __field(int, debug_id) + __field(int, src_fd) + __field(int, dest_fd) + ), + TP_fast_assign( + __entry->debug_id = t->debug_id; + __entry->src_fd = src_fd; + __entry->dest_fd = dest_fd; + ), + TP_printk("transaction=%d src_fd=%d ==> dest_fd=%d", + __entry->debug_id, __entry->src_fd, __entry->dest_fd) +); + +DECLARE_EVENT_CLASS(binder_buffer_class, + TP_PROTO(struct binder_buffer *buf), + TP_ARGS(buf), + TP_STRUCT__entry( + __field(int, debug_id) + __field(size_t, data_size) + __field(size_t, offsets_size) + ), + TP_fast_assign( + __entry->debug_id = buf->debug_id; + __entry->data_size = buf->data_size; + __entry->offsets_size = buf->offsets_size; + ), + TP_printk("transaction=%d data_size=%zd offsets_size=%zd", + __entry->debug_id, __entry->data_size, __entry->offsets_size) +); + +DEFINE_EVENT(binder_buffer_class, binder_transaction_alloc_buf, + TP_PROTO(struct binder_buffer *buffer), + TP_ARGS(buffer)); + +DEFINE_EVENT(binder_buffer_class, binder_transaction_buffer_release, + TP_PROTO(struct binder_buffer *buffer), + TP_ARGS(buffer)); + +DEFINE_EVENT(binder_buffer_class, binder_transaction_failed_buffer_release, + TP_PROTO(struct binder_buffer *buffer), + TP_ARGS(buffer)); + +TRACE_EVENT(binder_update_page_range, + TP_PROTO(struct binder_proc *proc, bool allocate, + void *start, void *end), + TP_ARGS(proc, allocate, start, end), + TP_STRUCT__entry( + __field(int, proc) + __field(bool, allocate) + __field(size_t, offset) + __field(size_t, size) + ), + TP_fast_assign( + __entry->proc = proc->pid; + __entry->allocate = allocate; + __entry->offset = start - proc->buffer; + __entry->size = end - start; + ), + TP_printk("proc=%d allocate=%d offset=%zu size=%zu", + __entry->proc, __entry->allocate, + __entry->offset, __entry->size) +); + +TRACE_EVENT(binder_command, + TP_PROTO(uint32_t cmd), + TP_ARGS(cmd), + TP_STRUCT__entry( + __field(uint32_t, cmd) + ), + TP_fast_assign( + __entry->cmd = cmd; + ), + TP_printk("cmd=0x%x %s", + __entry->cmd, + _IOC_NR(__entry->cmd) < ARRAY_SIZE(binder_command_strings) ? + binder_command_strings[_IOC_NR(__entry->cmd)] : + "unknown") +); + +TRACE_EVENT(binder_return, + TP_PROTO(uint32_t cmd), + TP_ARGS(cmd), + TP_STRUCT__entry( + __field(uint32_t, cmd) + ), + TP_fast_assign( + __entry->cmd = cmd; + ), + TP_printk("cmd=0x%x %s", + __entry->cmd, + _IOC_NR(__entry->cmd) < ARRAY_SIZE(binder_return_strings) ? + binder_return_strings[_IOC_NR(__entry->cmd)] : + "unknown") +); + +#endif /* _BINDER_TRACE_H */ + +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_PATH . +#define TRACE_INCLUDE_FILE binder_trace +#include <trace/define_trace.h> diff --git a/drivers/staging/android/logger.c b/drivers/staging/android/logger.c index 1d5ed475364b..dbc63cbb4d3a 100644 --- a/drivers/staging/android/logger.c +++ b/drivers/staging/android/logger.c @@ -676,4 +676,25 @@ static int __init logger_init(void) out: return ret; } + +static void __exit logger_exit(void) +{ + struct logger_log *current_log, *next_log; + + list_for_each_entry_safe(current_log, next_log, &log_list, logs) { + /* we have to delete all the entry inside log_list */ + misc_deregister(¤t_log->misc); + vfree(current_log->buffer); + kfree(current_log->misc.name); + list_del(¤t_log->logs); + kfree(current_log); + } +} + + device_initcall(logger_init); +module_exit(logger_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Robert Love, <rlove@google.com>"); +MODULE_DESCRIPTION("Android Logger"); diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h index 4d490a99110c..f57794827f73 100644 --- a/drivers/staging/bcm/Adapter.h +++ b/drivers/staging/bcm/Adapter.h @@ -151,7 +151,7 @@ struct bcm_packet_info { UINT NumOfPacketsSent; UCHAR ucDirection; USHORT usCID; - S_MIBS_EXTSERVICEFLOW_PARAMETERS stMibsExtServiceFlowTable; + struct bcm_mibs_parameters stMibsExtServiceFlowTable; UINT uiCurrentRxRate; UINT uiThisPeriodRxBytes; UINT uiTotalRxBytes; @@ -198,7 +198,7 @@ struct bcm_tarang_data { int AppCtrlQueueLen; BOOLEAN MacTracingEnabled; BOOLEAN bApplicationToExit; - S_MIBS_DROPPED_APP_CNTRL_MESSAGES stDroppedAppCntrlMsgs; + struct bcm_mibs_dropped_cntrl_msg stDroppedAppCntrlMsgs; ULONG RxCntrlMsgBitMask; }; @@ -371,8 +371,8 @@ struct bcm_mini_adapter { PFLASH2X_VENDORSPECIFIC_INFO psFlash2xVendorInfo; UINT uiFlashBaseAdd; /* Flash start address */ UINT uiActiveISOOffset; /* Active ISO offset chosen before f/w download */ - FLASH2X_SECTION_VAL eActiveISO; /* Active ISO section val */ - FLASH2X_SECTION_VAL eActiveDSD; /* Active DSD val chosen before f/w download */ + enum bcm_flash2x_section_val eActiveISO; /* Active ISO section val */ + enum bcm_flash2x_section_val eActiveDSD; /* Active DSD val chosen before f/w download */ UINT uiActiveDSDOffsetAtFwDld; /* For accessing Active DSD chosen before f/w download */ UINT uiFlashLayoutMajorVersion; UINT uiFlashLayoutMinorVersion; diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c index 3d02c2ebfb8d..efad33e3ba73 100644 --- a/drivers/staging/bcm/Bcmchar.c +++ b/drivers/staging/bcm/Bcmchar.c @@ -160,7 +160,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) struct bcm_mini_adapter *Adapter = pTarang->Adapter; INT Status = STATUS_FAILURE; int timeout = 0; - IOCTL_BUFFER IoBuffer; + struct bcm_ioctl_buffer IoBuffer; int bytes; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Parameters Passed to control IOCTL cmd=0x%X arg=0x%lX", cmd, arg); @@ -203,13 +203,13 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) switch (cmd) { /* Rdms for Swin Idle... */ case IOCTL_BCM_REGISTER_READ_PRIVATE: { - RDM_BUFFER sRdmBuffer = {0}; + struct bcm_rdm_buffer sRdmBuffer = {0}; PCHAR temp_buff; UINT Bufflen; u16 temp_value; /* Copy Ioctl Buffer structure */ - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) return -EFAULT; if (IoBuffer.InputLength > sizeof(sRdmBuffer)) @@ -248,11 +248,11 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) } case IOCTL_BCM_REGISTER_WRITE_PRIVATE: { - WRM_BUFFER sWrmBuffer = {0}; + struct bcm_wrm_buffer sWrmBuffer = {0}; UINT uiTempVar = 0; /* Copy Ioctl Buffer structure */ - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) return -EFAULT; if (IoBuffer.InputLength > sizeof(sWrmBuffer)) @@ -287,7 +287,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) case IOCTL_BCM_REGISTER_READ: case IOCTL_BCM_EEPROM_REGISTER_READ: { - RDM_BUFFER sRdmBuffer = {0}; + struct bcm_rdm_buffer sRdmBuffer = {0}; PCHAR temp_buff = NULL; UINT uiTempVar = 0; if ((Adapter->IdleMode == TRUE) || @@ -299,7 +299,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) } /* Copy Ioctl Buffer structure */ - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) return -EFAULT; if (IoBuffer.InputLength > sizeof(sRdmBuffer)) @@ -345,8 +345,9 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) } case IOCTL_BCM_REGISTER_WRITE: case IOCTL_BCM_EEPROM_REGISTER_WRITE: { - WRM_BUFFER sWrmBuffer = {0}; + struct bcm_wrm_buffer sWrmBuffer = {0}; UINT uiTempVar = 0; + if ((Adapter->IdleMode == TRUE) || (Adapter->bShutStatus == TRUE) || (Adapter->bPreparingForLowPowerMode == TRUE)) { @@ -356,7 +357,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) } /* Copy Ioctl Buffer structure */ - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) return -EFAULT; if (IoBuffer.InputLength > sizeof(sWrmBuffer)) @@ -401,8 +402,8 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) UINT value = 0; UINT uiBit = 0; UINT uiOperation = 0; + struct bcm_gpio_info gpio_info = {0}; - GPIO_INFO gpio_info = {0}; if ((Adapter->IdleMode == TRUE) || (Adapter->bShutStatus == TRUE) || (Adapter->bPreparingForLowPowerMode == TRUE)) { @@ -411,7 +412,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) return -EACCES; } - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) return -EFAULT; if (IoBuffer.InputLength > sizeof(gpio_info)) @@ -478,7 +479,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) break; case BCM_LED_THREAD_STATE_CHANGE_REQ: { - USER_THREAD_REQ threadReq = {0}; + struct bcm_user_thread_req threadReq = {0}; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "User made LED thread InActive"); if ((Adapter->IdleMode == TRUE) || @@ -490,7 +491,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) break; } - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) return -EFAULT; if (IoBuffer.InputLength > sizeof(threadReq)) @@ -518,14 +519,14 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) case IOCTL_BCM_GPIO_STATUS_REQUEST: { ULONG uiBit = 0; UCHAR ucRead[4]; - GPIO_INFO gpio_info = {0}; + struct bcm_gpio_info gpio_info = {0}; if ((Adapter->IdleMode == TRUE) || (Adapter->bShutStatus == TRUE) || (Adapter->bPreparingForLowPowerMode == TRUE)) return -EACCES; - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) return -EFAULT; if (IoBuffer.InputLength > sizeof(gpio_info)) @@ -552,17 +553,17 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) case IOCTL_BCM_GPIO_MULTI_REQUEST: { UCHAR ucResetValue[4]; - GPIO_MULTI_INFO gpio_multi_info[MAX_IDX]; - PGPIO_MULTI_INFO pgpio_multi_info = (PGPIO_MULTI_INFO)gpio_multi_info; + struct bcm_gpio_multi_info gpio_multi_info[MAX_IDX]; + struct bcm_gpio_multi_info *pgpio_multi_info = (struct bcm_gpio_multi_info *)gpio_multi_info; - memset(pgpio_multi_info, 0, MAX_IDX * sizeof(GPIO_MULTI_INFO)); + memset(pgpio_multi_info, 0, MAX_IDX * sizeof(struct bcm_gpio_multi_info)); if ((Adapter->IdleMode == TRUE) || (Adapter->bShutStatus == TRUE) || (Adapter->bPreparingForLowPowerMode == TRUE)) return -EINVAL; - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) return -EFAULT; if (IoBuffer.InputLength > sizeof(gpio_multi_info)) @@ -636,15 +637,15 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) case IOCTL_BCM_GPIO_MODE_REQUEST: { UCHAR ucResetValue[4]; - GPIO_MULTI_MODE gpio_multi_mode[MAX_IDX]; - PGPIO_MULTI_MODE pgpio_multi_mode = (PGPIO_MULTI_MODE)gpio_multi_mode; + struct bcm_gpio_multi_mode gpio_multi_mode[MAX_IDX]; + struct bcm_gpio_multi_mode *pgpio_multi_mode = (struct bcm_gpio_multi_mode *)gpio_multi_mode; if ((Adapter->IdleMode == TRUE) || (Adapter->bShutStatus == TRUE) || (Adapter->bPreparingForLowPowerMode == TRUE)) return -EINVAL; - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) return -EFAULT; if (IoBuffer.InputLength > sizeof(gpio_multi_mode)) @@ -719,7 +720,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) PVOID pvBuffer = NULL; /* Copy Ioctl Buffer structure */ - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) return -EFAULT; if (IoBuffer.InputLength < sizeof(struct bcm_link_request)) @@ -799,7 +800,7 @@ cntrlEnd: } /* Copy Ioctl Buffer structure */ - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) { + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) { up(&Adapter->fw_download_sema); return -EFAULT; } @@ -895,7 +896,7 @@ cntrlEnd: mdelay(10); /* Wait for MailBox Interrupt */ - if (StartInterruptUrb((PS_INTERFACE_ADAPTER)Adapter->pvInterfaceAdapter)) + if (StartInterruptUrb((struct bcm_interface_adapter *)Adapter->pvInterfaceAdapter)) BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Unable to send interrupt...\n"); timeout = 5*HZ; @@ -1000,7 +1001,7 @@ cntrlEnd: ulong len; /* Copy Ioctl Buffer structure */ - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) return -EFAULT; len = min_t(ulong, IoBuffer.OutputLength, strlen(VER_FILEVERSION_STR) + 1); @@ -1015,7 +1016,7 @@ cntrlEnd: LINK_STATE link_state; /* Copy Ioctl Buffer structure */ - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) { + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "copy_from_user failed..\n"); return -EFAULT; } @@ -1042,7 +1043,7 @@ cntrlEnd: UINT tracing_flag; /* copy ioctl Buffer structure */ - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) return -EFAULT; if (copy_from_user(&tracing_flag, IoBuffer.InputBuffer, sizeof(UINT))) @@ -1057,13 +1058,13 @@ cntrlEnd: case IOCTL_BCM_GET_DSX_INDICATION: { ULONG ulSFId = 0; - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) return -EFAULT; - if (IoBuffer.OutputLength < sizeof(stLocalSFAddIndicationAlt)) { + if (IoBuffer.OutputLength < sizeof(struct bcm_add_indication_alt)) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Mismatch req: %lx needed is =0x%zx!!!", - IoBuffer.OutputLength, sizeof(stLocalSFAddIndicationAlt)); + IoBuffer.OutputLength, sizeof(struct bcm_add_indication_alt)); return -EINVAL; } @@ -1079,18 +1080,18 @@ cntrlEnd: case IOCTL_BCM_GET_HOST_MIBS: { PVOID temp_buff; - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) return -EFAULT; - if (IoBuffer.OutputLength != sizeof(S_MIBS_HOST_STATS_MIBS)) { + if (IoBuffer.OutputLength != sizeof(struct bcm_host_stats_mibs)) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Length Check failed %lu %zd\n", - IoBuffer.OutputLength, sizeof(S_MIBS_HOST_STATS_MIBS)); + IoBuffer.OutputLength, sizeof(struct bcm_host_stats_mibs)); return -EINVAL; } /* FIXME: HOST_STATS are too big for kmalloc (122048)! */ - temp_buff = kzalloc(sizeof(S_MIBS_HOST_STATS_MIBS), GFP_KERNEL); + temp_buff = kzalloc(sizeof(struct bcm_host_stats_mibs), GFP_KERNEL); if (!temp_buff) return STATUS_FAILURE; @@ -1098,7 +1099,7 @@ cntrlEnd: GetDroppedAppCntrlPktMibs(temp_buff, pTarang); if (Status != STATUS_FAILURE) - if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, sizeof(S_MIBS_HOST_STATS_MIBS))) { + if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, sizeof(struct bcm_host_stats_mibs))) { kfree(temp_buff); return -EFAULT; } @@ -1118,7 +1119,7 @@ cntrlEnd: break; case IOCTL_BCM_BULK_WRM: { - PBULKWRM_BUFFER pBulkBuffer; + struct bcm_bulk_wrm_buffer *pBulkBuffer; UINT uiTempVar = 0; PCHAR pvBuffer = NULL; @@ -1132,7 +1133,7 @@ cntrlEnd: } /* Copy Ioctl Buffer structure */ - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) return -EFAULT; if (IoBuffer.InputLength < sizeof(ULONG) * 2) @@ -1143,7 +1144,7 @@ cntrlEnd: if (IS_ERR(pvBuffer)) return PTR_ERR(pvBuffer); - pBulkBuffer = (PBULKWRM_BUFFER)pvBuffer; + pBulkBuffer = (struct bcm_bulk_wrm_buffer *)pvBuffer; if (((ULONG)pBulkBuffer->Register & 0x0F000000) != 0x0F000000 || ((ULONG)pBulkBuffer->Register & 0x3)) { @@ -1180,7 +1181,7 @@ cntrlEnd: } case IOCTL_BCM_GET_NVM_SIZE: - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) return -EFAULT; if (Adapter->eNVMType == NVM_EEPROM || Adapter->eNVMType == NVM_FLASH) { @@ -1194,7 +1195,7 @@ cntrlEnd: case IOCTL_BCM_CAL_INIT: { UINT uiSectorSize = 0 ; if (Adapter->eNVMType == NVM_FLASH) { - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) return -EFAULT; if (copy_from_user(&uiSectorSize, IoBuffer.InputBuffer, sizeof(UINT))) @@ -1231,7 +1232,7 @@ cntrlEnd: USER_BCM_DBG_STATE sUserDebugState; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "In SET_DEBUG ioctl\n"); - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) return -EFAULT; if (copy_from_user(&sUserDebugState, IoBuffer.InputBuffer, sizeof(USER_BCM_DBG_STATE))) @@ -1262,7 +1263,7 @@ cntrlEnd: case IOCTL_BCM_NVM_READ: case IOCTL_BCM_NVM_WRITE: { - NVM_READWRITE stNVMReadWrite; + struct bcm_nvm_readwrite stNVMReadWrite; PUCHAR pReadData = NULL; ULONG ulDSDMagicNumInUsrBuff = 0; struct timeval tv0, tv1; @@ -1284,12 +1285,12 @@ cntrlEnd: } /* Copy Ioctl Buffer structure */ - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) return -EFAULT; if (copy_from_user(&stNVMReadWrite, (IOCTL_BCM_NVM_READ == cmd) ? IoBuffer.OutputBuffer : IoBuffer.InputBuffer, - sizeof(NVM_READWRITE))) + sizeof(struct bcm_nvm_readwrite))) return -EFAULT; /* @@ -1404,7 +1405,7 @@ cntrlEnd: } case IOCTL_BCM_FLASH2X_SECTION_READ: { - FLASH2X_READWRITE sFlash2xRead = {0}; + struct bcm_flash2x_readwrite sFlash2xRead = {0}; PUCHAR pReadBuff = NULL ; UINT NOB = 0; UINT BuffSize = 0; @@ -1418,11 +1419,11 @@ cntrlEnd: } BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_READ Called"); - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) return -EFAULT; /* Reading FLASH 2.x READ structure */ - if (copy_from_user(&sFlash2xRead, IoBuffer.InputBuffer, sizeof(FLASH2X_READWRITE))) + if (copy_from_user(&sFlash2xRead, IoBuffer.InputBuffer, sizeof(struct bcm_flash2x_readwrite))) return -EFAULT; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.Section :%x", sFlash2xRead.Section); @@ -1495,7 +1496,7 @@ cntrlEnd: break; case IOCTL_BCM_FLASH2X_SECTION_WRITE: { - FLASH2X_READWRITE sFlash2xWrite = {0}; + struct bcm_flash2x_readwrite sFlash2xWrite = {0}; PUCHAR pWriteBuff; void __user *InputAddr; UINT NOB = 0; @@ -1513,11 +1514,11 @@ cntrlEnd: BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_WRITE Called"); - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) return -EFAULT; /* Reading FLASH 2.x READ structure */ - if (copy_from_user(&sFlash2xWrite, IoBuffer.InputBuffer, sizeof(FLASH2X_READWRITE))) + if (copy_from_user(&sFlash2xWrite, IoBuffer.InputBuffer, sizeof(struct bcm_flash2x_readwrite))) return -EFAULT; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.Section :%x", sFlash2xWrite.Section); @@ -1604,16 +1605,16 @@ cntrlEnd: break; case IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP: { - PFLASH2X_BITMAP psFlash2xBitMap; + struct bcm_flash2x_bitmap *psFlash2xBitMap; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP Called"); - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) return -EFAULT; - if (IoBuffer.OutputLength != sizeof(FLASH2X_BITMAP)) + if (IoBuffer.OutputLength != sizeof(struct bcm_flash2x_bitmap)) return -EINVAL; - psFlash2xBitMap = kzalloc(sizeof(FLASH2X_BITMAP), GFP_KERNEL); + psFlash2xBitMap = kzalloc(sizeof(struct bcm_flash2x_bitmap), GFP_KERNEL); if (psFlash2xBitMap == NULL) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory is not available"); return -ENOMEM; @@ -1634,7 +1635,7 @@ cntrlEnd: BcmGetFlash2xSectionalBitMap(Adapter, psFlash2xBitMap); up(&Adapter->NVMRdmWrmLock); - if (copy_to_user(IoBuffer.OutputBuffer, psFlash2xBitMap, sizeof(FLASH2X_BITMAP))) { + if (copy_to_user(IoBuffer.OutputBuffer, psFlash2xBitMap, sizeof(struct bcm_flash2x_bitmap))) { kfree(psFlash2xBitMap); return -EFAULT; } @@ -1644,7 +1645,7 @@ cntrlEnd: break; case IOCTL_BCM_SET_ACTIVE_SECTION: { - FLASH2X_SECTION_VAL eFlash2xSectionVal = 0; + enum bcm_flash2x_section_val eFlash2xSectionVal = 0; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SET_ACTIVE_SECTION Called"); if (IsFlash2x(Adapter) != TRUE) { @@ -1652,7 +1653,7 @@ cntrlEnd: return -EINVAL; } - Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); + Status = copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)); if (Status) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); return -EFAULT; @@ -1692,7 +1693,7 @@ cntrlEnd: break; case IOCTL_BCM_COPY_SECTION: { - FLASH2X_COPY_SECTION sCopySectStrut = {0}; + struct bcm_flash2x_copy_section sCopySectStrut = {0}; Status = STATUS_SUCCESS; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_COPY_SECTION Called"); @@ -1702,13 +1703,13 @@ cntrlEnd: return -EINVAL; } - Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); + Status = copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)); if (Status) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed Status :%d", Status); return -EFAULT; } - Status = copy_from_user(&sCopySectStrut, IoBuffer.InputBuffer, sizeof(FLASH2X_COPY_SECTION)); + Status = copy_from_user(&sCopySectStrut, IoBuffer.InputBuffer, sizeof(struct bcm_flash2x_copy_section)); if (Status) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of Copy_Section_Struct failed with Status :%d", Status); return -EFAULT; @@ -1769,7 +1770,7 @@ cntrlEnd: Status = STATUS_SUCCESS; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_GET_FLASH_CS_INFO Called"); - Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); + Status = copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)); if (Status) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); return -EFAULT; @@ -1799,7 +1800,7 @@ cntrlEnd: case IOCTL_BCM_SELECT_DSD: { UINT SectOfset = 0; - FLASH2X_SECTION_VAL eFlash2xSectionVal; + enum bcm_flash2x_section_val eFlash2xSectionVal; eFlash2xSectionVal = NO_SECTION_VAL; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SELECT_DSD Called"); @@ -1808,7 +1809,7 @@ cntrlEnd: return -EINVAL; } - Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); + Status = copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)); if (Status) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); return -EFAULT; @@ -1842,7 +1843,7 @@ cntrlEnd: break; case IOCTL_BCM_NVM_RAW_READ: { - NVM_READWRITE stNVMRead; + struct bcm_nvm_readwrite stNVMRead; INT NOB ; INT BuffSize ; INT ReadOffset = 0; @@ -1856,12 +1857,12 @@ cntrlEnd: } /* Copy Ioctl Buffer structure */ - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) { + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "copy_from_user 1 failed\n"); return -EFAULT; } - if (copy_from_user(&stNVMRead, IoBuffer.OutputBuffer, sizeof(NVM_READWRITE))) + if (copy_from_user(&stNVMRead, IoBuffer.OutputBuffer, sizeof(struct bcm_nvm_readwrite))) return -EFAULT; NOB = stNVMRead.uiNumBytes; @@ -1933,7 +1934,7 @@ cntrlEnd: ULONG RxCntrlMsgBitMask = 0; /* Copy Ioctl Buffer structure */ - Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); + Status = copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)); if (Status) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "copy of Ioctl buffer is failed from user space"); return -EFAULT; @@ -1955,7 +1956,7 @@ cntrlEnd: break; case IOCTL_BCM_GET_DEVICE_DRIVER_INFO: { - DEVICE_DRIVER_INFO DevInfo; + struct bcm_driver_info DevInfo; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Called IOCTL_BCM_GET_DEVICE_DRIVER_INFO\n"); @@ -1965,7 +1966,7 @@ cntrlEnd: DevInfo.u32NVMType = Adapter->eNVMType; DevInfo.u32InterfaceType = BCM_USB; - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) return -EFAULT; if (IoBuffer.OutputLength < sizeof(DevInfo)) @@ -1977,19 +1978,19 @@ cntrlEnd: break; case IOCTL_BCM_TIME_SINCE_NET_ENTRY: { - ST_TIME_ELAPSED stTimeElapsedSinceNetEntry = {0}; + struct bcm_time_elapsed stTimeElapsedSinceNetEntry = {0}; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_TIME_SINCE_NET_ENTRY called"); - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) return -EFAULT; - if (IoBuffer.OutputLength < sizeof(ST_TIME_ELAPSED)) + if (IoBuffer.OutputLength < sizeof(struct bcm_time_elapsed)) return -EINVAL; stTimeElapsedSinceNetEntry.ul64TimeElapsedSinceNetEntry = get_seconds() - Adapter->liTimeSinceLastNetEntry; - if (copy_to_user(IoBuffer.OutputBuffer, &stTimeElapsedSinceNetEntry, sizeof(ST_TIME_ELAPSED))) + if (copy_to_user(IoBuffer.OutputBuffer, &stTimeElapsedSinceNetEntry, sizeof(struct bcm_time_elapsed))) return -EFAULT; } break; diff --git a/drivers/staging/bcm/Bcmnet.c b/drivers/staging/bcm/Bcmnet.c index 6e8c7f523214..a3b91c7ee8ff 100644 --- a/drivers/staging/bcm/Bcmnet.c +++ b/drivers/staging/bcm/Bcmnet.c @@ -142,7 +142,7 @@ static void bcm_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev); - PS_INTERFACE_ADAPTER psIntfAdapter = Adapter->pvInterfaceAdapter; + struct bcm_interface_adapter *psIntfAdapter = Adapter->pvInterfaceAdapter; struct usb_device *udev = interface_to_usbdev(psIntfAdapter->interface); strcpy(info->driver, DRV_NAME); @@ -186,7 +186,7 @@ static const struct ethtool_ops bcm_ethtool_ops = { int register_networkdev(struct bcm_mini_adapter *Adapter) { struct net_device *net = Adapter->dev; - PS_INTERFACE_ADAPTER IntfAdapter = Adapter->pvInterfaceAdapter; + struct bcm_interface_adapter *IntfAdapter = Adapter->pvInterfaceAdapter; struct usb_interface *udev = IntfAdapter->interface; struct usb_device *xdev = IntfAdapter->udev; @@ -227,7 +227,7 @@ int register_networkdev(struct bcm_mini_adapter *Adapter) void unregister_networkdev(struct bcm_mini_adapter *Adapter) { struct net_device *net = Adapter->dev; - PS_INTERFACE_ADAPTER IntfAdapter = Adapter->pvInterfaceAdapter; + struct bcm_interface_adapter *IntfAdapter = Adapter->pvInterfaceAdapter; struct usb_interface *udev = IntfAdapter->interface; struct usb_device *xdev = IntfAdapter->udev; diff --git a/drivers/staging/bcm/CmHost.c b/drivers/staging/bcm/CmHost.c index 325b592fd41f..23ddc3d7c9ea 100644 --- a/drivers/staging/bcm/CmHost.c +++ b/drivers/staging/bcm/CmHost.c @@ -107,7 +107,7 @@ static VOID deleteSFBySfid(struct bcm_mini_adapter *Adapter, UINT uiSearchRuleIn DeleteAllClassifiersForSF(Adapter, uiSearchRuleIndex); /* Resetting only MIBS related entries in the SF */ - memset((PVOID)&Adapter->PackInfo[uiSearchRuleIndex], 0, sizeof(S_MIBS_SERVICEFLOW_TABLE)); + memset((PVOID)&Adapter->PackInfo[uiSearchRuleIndex], 0, sizeof(struct bcm_mibs_table)); } static inline VOID @@ -431,7 +431,7 @@ static VOID CopyToAdapter(register struct bcm_mini_adapter *Adapter, /* <Pointer register struct bcm_connect_mgr_params *psfLocalSet, /* Pointer to the connection manager parameters structure */ register UINT uiSearchRuleIndex, /* <Index of Queue, to which this data belongs */ register UCHAR ucDsxType, - stLocalSFAddIndicationAlt *pstAddIndication) { + struct bcm_add_indication_alt *pstAddIndication) { /* UCHAR ucProtocolLength = 0; */ ULONG ulSFID; @@ -833,11 +833,11 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) { int uiLoopIndex; int nIndex; - stLocalSFAddIndicationAlt *pstAddIndication; + struct bcm_add_indication_alt *pstAddIndication; UINT nCurClassifierCnt; struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); - pstAddIndication = (stLocalSFAddIndicationAlt *)pvBuffer; + pstAddIndication = (struct bcm_add_indication_alt *)pvBuffer; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "======>"); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Type: 0x%X", pstAddIndication->u8Type); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Direction: 0x%X", pstAddIndication->u8Direction); @@ -1333,13 +1333,13 @@ static ULONG StoreSFParam(struct bcm_mini_adapter *Adapter, PUCHAR pucSrcBuffer, ULONG StoreCmControlResponseMessage(struct bcm_mini_adapter *Adapter, PVOID pvBuffer, UINT *puBufferLength) { - stLocalSFAddIndicationAlt *pstAddIndicationAlt = NULL; + struct bcm_add_indication_alt *pstAddIndicationAlt = NULL; struct bcm_add_indication *pstAddIndication = NULL; struct bcm_del_request *pstDeletionRequest; UINT uiSearchRuleIndex; ULONG ulSFID; - pstAddIndicationAlt = (stLocalSFAddIndicationAlt *)(pvBuffer); + pstAddIndicationAlt = (struct bcm_add_indication_alt *)(pvBuffer); /* * In case of DSD Req By MS, we should immediately delete this SF so that @@ -1445,29 +1445,29 @@ ULONG StoreCmControlResponseMessage(struct bcm_mini_adapter *Adapter, PVOID pvBu return 1; } -static inline stLocalSFAddIndicationAlt +static inline struct bcm_add_indication_alt *RestoreCmControlResponseMessage(register struct bcm_mini_adapter *Adapter, register PVOID pvBuffer) { ULONG ulStatus = 0; struct bcm_add_indication *pstAddIndication = NULL; - stLocalSFAddIndicationAlt *pstAddIndicationDest = NULL; + struct bcm_add_indication_alt *pstAddIndicationDest = NULL; pstAddIndication = (struct bcm_add_indication *)(pvBuffer); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "=====>"); if ((pstAddIndication->u8Type == DSD_REQ) || (pstAddIndication->u8Type == DSD_RSP) || (pstAddIndication->u8Type == DSD_ACK)) - return (stLocalSFAddIndicationAlt *)pvBuffer; + return (struct bcm_add_indication_alt *)pvBuffer; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Inside RestoreCmControlResponseMessage "); /* * Need to Allocate memory to contain the SUPER Large structures * Our driver can't create these structures on Stack :( */ - pstAddIndicationDest = kmalloc(sizeof(stLocalSFAddIndicationAlt), GFP_KERNEL); + pstAddIndicationDest = kmalloc(sizeof(struct bcm_add_indication_alt), GFP_KERNEL); if (pstAddIndicationDest) { - memset(pstAddIndicationDest, 0, sizeof(stLocalSFAddIndicationAlt)); + memset(pstAddIndicationDest, 0, sizeof(struct bcm_add_indication_alt)); } else { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Failed to allocate memory for SF Add Indication Structure "); return NULL; @@ -1573,36 +1573,36 @@ ULONG SetUpTargetDsxBuffers(struct bcm_mini_adapter *Adapter) static ULONG GetNextTargetBufferLocation(struct bcm_mini_adapter *Adapter, B_UINT16 tid) { - ULONG ulTargetDSXBufferAddress; - ULONG ulTargetDsxBufferIndexToUse, ulMaxTry; + ULONG dsx_buf; + ULONG idx, max_try; if ((Adapter->ulTotalTargetBuffersAvailable == 0) || (Adapter->ulFreeTargetBufferCnt == 0)) { ClearTargetDSXBuffer(Adapter, tid, FALSE); return 0; } - ulTargetDsxBufferIndexToUse = Adapter->ulCurrentTargetBuffer; - ulMaxTry = Adapter->ulTotalTargetBuffersAvailable; - while ((ulMaxTry) && (Adapter->astTargetDsxBuffer[ulTargetDsxBufferIndexToUse].valid != 1)) { - ulTargetDsxBufferIndexToUse = (ulTargetDsxBufferIndexToUse+1) % Adapter->ulTotalTargetBuffersAvailable; - ulMaxTry--; + idx = Adapter->ulCurrentTargetBuffer; + max_try = Adapter->ulTotalTargetBuffersAvailable; + while ((max_try) && (Adapter->astTargetDsxBuffer[idx].valid != 1)) { + idx = (idx+1) % Adapter->ulTotalTargetBuffersAvailable; + max_try--; } - if (ulMaxTry == 0) { + if (max_try == 0) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "\n GetNextTargetBufferLocation : Error No Free Target DSX Buffers FreeCnt : %lx ", Adapter->ulFreeTargetBufferCnt); ClearTargetDSXBuffer(Adapter, tid, FALSE); return 0; } - ulTargetDSXBufferAddress = Adapter->astTargetDsxBuffer[ulTargetDsxBufferIndexToUse].ulTargetDsxBuffer; - Adapter->astTargetDsxBuffer[ulTargetDsxBufferIndexToUse].valid = 0; - Adapter->astTargetDsxBuffer[ulTargetDsxBufferIndexToUse].tid = tid; + dsx_buf = Adapter->astTargetDsxBuffer[idx].ulTargetDsxBuffer; + Adapter->astTargetDsxBuffer[idx].valid = 0; + Adapter->astTargetDsxBuffer[idx].tid = tid; Adapter->ulFreeTargetBufferCnt--; - ulTargetDsxBufferIndexToUse = (ulTargetDsxBufferIndexToUse+1)%Adapter->ulTotalTargetBuffersAvailable; - Adapter->ulCurrentTargetBuffer = ulTargetDsxBufferIndexToUse; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "GetNextTargetBufferLocation :Returning address %lx tid %d\n", ulTargetDSXBufferAddress, tid); + idx = (idx+1)%Adapter->ulTotalTargetBuffersAvailable; + Adapter->ulCurrentTargetBuffer = idx; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "GetNextTargetBufferLocation :Returning address %lx tid %d\n", dsx_buf, tid); - return ulTargetDSXBufferAddress; + return dsx_buf; } int AllocAdapterDsxBuffer(struct bcm_mini_adapter *Adapter) @@ -1611,7 +1611,7 @@ int AllocAdapterDsxBuffer(struct bcm_mini_adapter *Adapter) * Need to Allocate memory to contain the SUPER Large structures * Our driver can't create these structures on Stack */ - Adapter->caDsxReqResp = kmalloc(sizeof(stLocalSFAddIndicationAlt)+LEADER_SIZE, GFP_KERNEL); + Adapter->caDsxReqResp = kmalloc(sizeof(struct bcm_add_indication_alt)+LEADER_SIZE, GFP_KERNEL); if (!Adapter->caDsxReqResp) return -ENOMEM; @@ -1634,8 +1634,8 @@ BOOLEAN CmControlResponseMessage(struct bcm_mini_adapter *Adapter, /* <Pointer PVOID pvBuffer /* Starting Address of the Buffer, that contains the AddIndication Data */) { struct bcm_connect_mgr_params *psfLocalSet = NULL; - stLocalSFAddIndicationAlt *pstAddIndication = NULL; - stLocalSFChangeIndicationAlt *pstChangeIndication = NULL; + struct bcm_add_indication_alt *pstAddIndication = NULL; + struct bcm_change_indication *pstChangeIndication = NULL; struct bcm_leader *pLeader = NULL; /* @@ -1661,12 +1661,12 @@ BOOLEAN CmControlResponseMessage(struct bcm_mini_adapter *Adapter, /* <Pointer switch (pstAddIndication->u8Type) { case DSA_REQ: { - pLeader->PLength = sizeof(stLocalSFAddIndicationAlt); + pLeader->PLength = sizeof(struct bcm_add_indication_alt); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Sending DSA Response....\n"); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSA RESPONSE TO MAC %d", pLeader->PLength); - *((stLocalSFAddIndicationAlt *)&(Adapter->caDsxReqResp[LEADER_SIZE])) + *((struct bcm_add_indication_alt *)&(Adapter->caDsxReqResp[LEADER_SIZE])) = *pstAddIndication; - ((stLocalSFAddIndicationAlt *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSA_RSP; + ((struct bcm_add_indication_alt *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSA_RSP; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, " VCID = %x", ntohs(pstAddIndication->u16VCID)); CopyBufferToControlPacket(Adapter, (PVOID)Adapter->caDsxReqResp); @@ -1675,12 +1675,12 @@ BOOLEAN CmControlResponseMessage(struct bcm_mini_adapter *Adapter, /* <Pointer break; case DSA_RSP: { - pLeader->PLength = sizeof(stLocalSFAddIndicationAlt); + pLeader->PLength = sizeof(struct bcm_add_indication_alt); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSA ACK TO MAC %d", pLeader->PLength); - *((stLocalSFAddIndicationAlt *)&(Adapter->caDsxReqResp[LEADER_SIZE])) + *((struct bcm_add_indication_alt *)&(Adapter->caDsxReqResp[LEADER_SIZE])) = *pstAddIndication; - ((stLocalSFAddIndicationAlt *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSA_ACK; + ((struct bcm_add_indication_alt *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSA_ACK; } /* no break here..we should go down. */ case DSA_ACK: @@ -1773,12 +1773,12 @@ BOOLEAN CmControlResponseMessage(struct bcm_mini_adapter *Adapter, /* <Pointer break; case DSC_REQ: { - pLeader->PLength = sizeof(stLocalSFChangeIndicationAlt); - pstChangeIndication = (stLocalSFChangeIndicationAlt *)pstAddIndication; + pLeader->PLength = sizeof(struct bcm_change_indication); + pstChangeIndication = (struct bcm_change_indication *)pstAddIndication; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSC RESPONSE TO MAC %d", pLeader->PLength); - *((stLocalSFChangeIndicationAlt *)&(Adapter->caDsxReqResp[LEADER_SIZE])) = *pstChangeIndication; - ((stLocalSFChangeIndicationAlt *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSC_RSP; + *((struct bcm_change_indication *)&(Adapter->caDsxReqResp[LEADER_SIZE])) = *pstChangeIndication; + ((struct bcm_change_indication *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSC_RSP; CopyBufferToControlPacket(Adapter, (PVOID)Adapter->caDsxReqResp); kfree(pstAddIndication); @@ -1786,17 +1786,17 @@ BOOLEAN CmControlResponseMessage(struct bcm_mini_adapter *Adapter, /* <Pointer break; case DSC_RSP: { - pLeader->PLength = sizeof(stLocalSFChangeIndicationAlt); - pstChangeIndication = (stLocalSFChangeIndicationAlt *)pstAddIndication; + pLeader->PLength = sizeof(struct bcm_change_indication); + pstChangeIndication = (struct bcm_change_indication *)pstAddIndication; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSC ACK TO MAC %d", pLeader->PLength); - *((stLocalSFChangeIndicationAlt *)&(Adapter->caDsxReqResp[LEADER_SIZE])) = *pstChangeIndication; - ((stLocalSFChangeIndicationAlt *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSC_ACK; + *((struct bcm_change_indication *)&(Adapter->caDsxReqResp[LEADER_SIZE])) = *pstChangeIndication; + ((struct bcm_change_indication *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSC_ACK; } case DSC_ACK: { UINT uiSearchRuleIndex = 0; - pstChangeIndication = (stLocalSFChangeIndicationAlt *)pstAddIndication; + pstChangeIndication = (struct bcm_change_indication *)pstAddIndication; uiSearchRuleIndex = SearchSfid(Adapter, ntohl(pstChangeIndication->sfActiveSet.u32SFID)); if (uiSearchRuleIndex > NO_OF_QUEUES-1) BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "SF doesn't exist for which DSC_ACK is received"); @@ -1902,7 +1902,7 @@ int get_dsx_sf_data_to_application(struct bcm_mini_adapter *Adapter, UINT uiSFId BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "status =%d", status); psSfInfo = &Adapter->PackInfo[status]; if (psSfInfo->pstSFIndication && copy_to_user(user_buffer, - psSfInfo->pstSFIndication, sizeof(stLocalSFAddIndicationAlt))) { + psSfInfo->pstSFIndication, sizeof(struct bcm_add_indication_alt))) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "copy to user failed SFID %d, present in queue !!!", uiSFId); status = -EFAULT; return status; diff --git a/drivers/staging/bcm/CmHost.h b/drivers/staging/bcm/CmHost.h index 1c5a07c7bbe2..eecad8d90aea 100644 --- a/drivers/staging/bcm/CmHost.h +++ b/drivers/staging/bcm/CmHost.h @@ -1,147 +1,66 @@ -/// ************************************************************************** -/// (c) Beceem Communications Inc. -/// All Rights Reserved -/// -/// \file : CmHost.h -/// \author : Rajeev Tirumala -/// \date : September 8 , 2006 -/// \brief : Definitions for Connection Management Requests structure -/// which we will use to setup our connection structures.Its high -/// time we had a header file for CmHost.cpp to isolate the way -/// f/w sends DSx messages and the way we interpret them in code. -/// Revision History -/// -/// Date Author Version Description -/// 08-Sep-06 Rajeev 0.1 Created -/// ************************************************************************** +/*************************************************************************** + * (c) Beceem Communications Inc. + * All Rights Reserved + * + * file : CmHost.h + * author: Rajeev Tirumala + * date : September 8 , 2006 + * brief : Definitions for Connection Management Requests structure + * which we will use to setup our connection structures.Its high + * time we had a header file for CmHost.cpp to isolate the way + * f/w sends DSx messages and the way we interpret them in code. + * Revision History + * + * Date Author Version Description + * 08-Sep-06 Rajeev 0.1 Created + ***************************************************************************/ #ifndef _CM_HOST_H #define _CM_HOST_H #pragma once -#pragma pack (push,4) - -#define DSX_MESSAGE_EXCHANGE_BUFFER 0xBF60AC84 // This contains the pointer -#define DSX_MESSAGE_EXCHANGE_BUFFER_SIZE 72000 // 24 K Bytes - -/// \brief structure stLocalSFAddRequest -typedef struct stLocalSFAddRequestAlt{ - B_UINT8 u8Type; - B_UINT8 u8Direction; - - B_UINT16 u16TID; - /// \brief 16bitCID - B_UINT16 u16CID; - /// \brief 16bitVCID - B_UINT16 u16VCID; - - - struct bcm_connect_mgr_params sfParameterSet; - - //USE_MEMORY_MANAGER(); -}stLocalSFAddRequestAlt; - -/// \brief structure stLocalSFAddIndication -typedef struct stLocalSFAddIndicationAlt{ - B_UINT8 u8Type; - B_UINT8 u8Direction; - B_UINT16 u16TID; - /// \brief 16bitCID - B_UINT16 u16CID; - /// \brief 16bitVCID - B_UINT16 u16VCID; +#pragma pack(push, 4) + +#define DSX_MESSAGE_EXCHANGE_BUFFER 0xBF60AC84 /* This contains the pointer */ +#define DSX_MESSAGE_EXCHANGE_BUFFER_SIZE 72000 /* 24 K Bytes */ + +struct bcm_add_indication_alt { + u8 u8Type; + u8 u8Direction; + u16 u16TID; + /* brief 16bitCID */ + u16 u16CID; + /* brief 16bitVCID */ + u16 u16VCID; struct bcm_connect_mgr_params sfAuthorizedSet; struct bcm_connect_mgr_params sfAdmittedSet; struct bcm_connect_mgr_params sfActiveSet; - - B_UINT8 u8CC; /**< Confirmation Code*/ - B_UINT8 u8Padd; /**< 8-bit Padding */ - B_UINT16 u16Padd; /**< 16 bit Padding */ -// USE_MEMORY_MANAGER(); -}stLocalSFAddIndicationAlt; - -/// \brief structure stLocalSFAddConfirmation -typedef struct stLocalSFAddConfirmationAlt{ - B_UINT8 u8Type; - B_UINT8 u8Direction; - B_UINT16 u16TID; - /// \brief 16bitCID - B_UINT16 u16CID; - /// \brief 16bitVCID - B_UINT16 u16VCID; + u8 u8CC; /* < Confirmation Code */ + u8 u8Padd; /* < 8-bit Padding */ + u16 u16Padd; /* < 16 bit Padding */ +}; + +struct bcm_change_indication { + u8 u8Type; + u8 u8Direction; + u16 u16TID; + /* brief 16bitCID */ + u16 u16CID; + /* brief 16bitVCID */ + u16 u16VCID; struct bcm_connect_mgr_params sfAuthorizedSet; struct bcm_connect_mgr_params sfAdmittedSet; struct bcm_connect_mgr_params sfActiveSet; -}stLocalSFAddConfirmationAlt; - - -/// \brief structure stLocalSFChangeRequest -typedef struct stLocalSFChangeRequestAlt{ - B_UINT8 u8Type; - B_UINT8 u8Direction; - B_UINT16 u16TID; - /// \brief 16bitCID - B_UINT16 u16CID; - /// \brief 16bitVCID - B_UINT16 u16VCID; - /* - //Pointer location at which following connection manager param Structure can be read - //from the target. We only get the address location and we need to read out the - //entire connection manager param structure at the given location on target - */ - struct bcm_connect_mgr_params sfAuthorizedSet; - struct bcm_connect_mgr_params sfAdmittedSet; - struct bcm_connect_mgr_params sfActiveSet; - - B_UINT8 u8CC; /**< Confirmation Code*/ - B_UINT8 u8Padd; /**< 8-bit Padding */ - B_UINT16 u16Padd; /**< 16 bit */ - -}stLocalSFChangeRequestAlt; - -/// \brief structure stLocalSFChangeConfirmation -typedef struct stLocalSFChangeConfirmationAlt{ - B_UINT8 u8Type; - B_UINT8 u8Direction; - B_UINT16 u16TID; - /// \brief 16bitCID - B_UINT16 u16CID; - /// \brief 16bitVCID - B_UINT16 u16VCID; - struct bcm_connect_mgr_params sfAuthorizedSet; - struct bcm_connect_mgr_params sfAdmittedSet; - struct bcm_connect_mgr_params sfActiveSet; - -}stLocalSFChangeConfirmationAlt; - -/// \brief structure stLocalSFChangeIndication -typedef struct stLocalSFChangeIndicationAlt{ - B_UINT8 u8Type; - B_UINT8 u8Direction; - B_UINT16 u16TID; - /// \brief 16bitCID - B_UINT16 u16CID; - /// \brief 16bitVCID - B_UINT16 u16VCID; - struct bcm_connect_mgr_params sfAuthorizedSet; - struct bcm_connect_mgr_params sfAdmittedSet; - struct bcm_connect_mgr_params sfActiveSet; - - B_UINT8 u8CC; /**< Confirmation Code*/ - B_UINT8 u8Padd; /**< 8-bit Padding */ - B_UINT16 u16Padd; /**< 16 bit */ - -}stLocalSFChangeIndicationAlt; - -ULONG StoreCmControlResponseMessage(struct bcm_mini_adapter *Adapter, PVOID pvBuffer,UINT *puBufferLength); - -INT AllocAdapterDsxBuffer(struct bcm_mini_adapter *Adapter); - -INT FreeAdapterDsxBuffer(struct bcm_mini_adapter *Adapter); -ULONG SetUpTargetDsxBuffers(struct bcm_mini_adapter *Adapter); - -BOOLEAN CmControlResponseMessage(struct bcm_mini_adapter *Adapter, PVOID pvBuffer); - - -#pragma pack (pop) + u8 u8CC; /* < Confirmation Code */ + u8 u8Padd; /* < 8-bit Padding */ + u16 u16Padd; /* < 16 bit */ +}; + +unsigned long StoreCmControlResponseMessage(struct bcm_mini_adapter *Adapter, void *pvBuffer, unsigned int *puBufferLength); +int AllocAdapterDsxBuffer(struct bcm_mini_adapter *Adapter); +int FreeAdapterDsxBuffer(struct bcm_mini_adapter *Adapter); +unsigned long SetUpTargetDsxBuffers(struct bcm_mini_adapter *Adapter); +BOOLEAN CmControlResponseMessage(struct bcm_mini_adapter *Adapter, void *pvBuffer); + +#pragma pack(pop) #endif diff --git a/drivers/staging/bcm/HandleControlPacket.c b/drivers/staging/bcm/HandleControlPacket.c index 25e5c68bfe85..1bb53e247a62 100644 --- a/drivers/staging/bcm/HandleControlPacket.c +++ b/drivers/staging/bcm/HandleControlPacket.c @@ -226,7 +226,7 @@ INT flushAllAppQ(void) pTarang->AppCtrlQueueLen = 0; /* dropped contrl packet statistics also should be reset. */ memset((PVOID)&pTarang->stDroppedAppCntrlMsgs, 0, - sizeof(S_MIBS_DROPPED_APP_CNTRL_MESSAGES)); + sizeof(struct bcm_mibs_dropped_cntrl_msg)); } return STATUS_SUCCESS; diff --git a/drivers/staging/bcm/HostMIBSInterface.h b/drivers/staging/bcm/HostMIBSInterface.h index e34531b638e8..f922ac49b70e 100644 --- a/drivers/staging/bcm/HostMIBSInterface.h +++ b/drivers/staging/bcm/HostMIBSInterface.h @@ -1,5 +1,3 @@ - - #ifndef _HOST_MIBSINTERFACE_H #define _HOST_MIBSINTERFACE_H @@ -10,221 +8,185 @@ * statistics used for the MIBS. */ -#define MIBS_MAX_CLASSIFIERS 100 -#define MIBS_MAX_PHSRULES 100 -#define MIBS_MAX_SERVICEFLOWS 17 -#define MIBS_MAX_IP_RANGE_LENGTH 4 -#define MIBS_MAX_PORT_RANGE 4 -#define MIBS_MAX_PROTOCOL_LENGTH 32 -#define MIBS_MAX_PHS_LENGTHS 255 -#define MIBS_IPV6_ADDRESS_SIZEINBYTES 0x10 +#define MIBS_MAX_CLASSIFIERS 100 +#define MIBS_MAX_PHSRULES 100 +#define MIBS_MAX_SERVICEFLOWS 17 +#define MIBS_MAX_IP_RANGE_LENGTH 4 +#define MIBS_MAX_PORT_RANGE 4 +#define MIBS_MAX_PROTOCOL_LENGTH 32 +#define MIBS_MAX_PHS_LENGTHS 255 +#define MIBS_IPV6_ADDRESS_SIZEINBYTES 0x10 #define MIBS_IP_LENGTH_OF_ADDRESS 4 -#define MIBS_MAX_HIST_ENTRIES 12 -#define MIBS_PKTSIZEHIST_RANGE 128 - -typedef union _U_MIBS_IP_ADDRESS -{ - struct - { - //Source Ip Address Range - ULONG ulIpv4Addr[MIBS_MAX_IP_RANGE_LENGTH]; - //Source Ip Mask Address Range - ULONG ulIpv4Mask[MIBS_MAX_IP_RANGE_LENGTH]; +#define MIBS_MAX_HIST_ENTRIES 12 +#define MIBS_PKTSIZEHIST_RANGE 128 + +union bcm_mibs_ip_addr { + struct { + /* Source Ip Address Range */ + unsigned long ulIpv4Addr[MIBS_MAX_IP_RANGE_LENGTH]; + /* Source Ip Mask Address Range */ + unsigned long ulIpv4Mask[MIBS_MAX_IP_RANGE_LENGTH]; }; - struct - { - //Source Ip Address Range - ULONG ulIpv6Addr[MIBS_MAX_IP_RANGE_LENGTH * 4]; - //Source Ip Mask Address Range - ULONG ulIpv6Mask[MIBS_MAX_IP_RANGE_LENGTH * 4]; - + struct { + /* Source Ip Address Range */ + unsigned long ulIpv6Addr[MIBS_MAX_IP_RANGE_LENGTH * 4]; + /* Source Ip Mask Address Range */ + unsigned long ulIpv6Mask[MIBS_MAX_IP_RANGE_LENGTH * 4]; }; - struct - { - UCHAR ucIpv4Address[MIBS_MAX_IP_RANGE_LENGTH * - MIBS_IP_LENGTH_OF_ADDRESS]; - UCHAR ucIpv4Mask[MIBS_MAX_IP_RANGE_LENGTH * - MIBS_IP_LENGTH_OF_ADDRESS]; + struct { + unsigned char ucIpv4Address[MIBS_MAX_IP_RANGE_LENGTH * MIBS_IP_LENGTH_OF_ADDRESS]; + unsigned char ucIpv4Mask[MIBS_MAX_IP_RANGE_LENGTH * MIBS_IP_LENGTH_OF_ADDRESS]; }; - struct - { - UCHAR ucIpv6Address[MIBS_MAX_IP_RANGE_LENGTH * MIBS_IPV6_ADDRESS_SIZEINBYTES]; - UCHAR ucIpv6Mask[MIBS_MAX_IP_RANGE_LENGTH * MIBS_IPV6_ADDRESS_SIZEINBYTES]; + struct { + unsigned char ucIpv6Address[MIBS_MAX_IP_RANGE_LENGTH * MIBS_IPV6_ADDRESS_SIZEINBYTES]; + unsigned char ucIpv6Mask[MIBS_MAX_IP_RANGE_LENGTH * MIBS_IPV6_ADDRESS_SIZEINBYTES]; }; -}U_MIBS_IP_ADDRESS; - - -typedef struct _S_MIBS_HOST_INFO -{ - ULONG64 GoodTransmits; - ULONG64 GoodReceives; - // this to keep track of the Tx and Rx MailBox Registers. - ULONG NumDesUsed; - ULONG CurrNumFreeDesc; - ULONG PrevNumFreeDesc; - // to keep track the no of byte received - ULONG PrevNumRcevBytes; - ULONG CurrNumRcevBytes; - +}; + +struct bcm_mibs_host_info { + u64 GoodTransmits; + u64 GoodReceives; + /* this to keep track of the Tx and Rx MailBox Registers. */ + unsigned long NumDesUsed; + unsigned long CurrNumFreeDesc; + unsigned long PrevNumFreeDesc; + /* to keep track the no of byte received */ + unsigned long PrevNumRcevBytes; + unsigned long CurrNumRcevBytes; /* QOS Related */ - ULONG BEBucketSize; - ULONG rtPSBucketSize; - ULONG LastTxQueueIndex; - BOOLEAN TxOutofDescriptors; - BOOLEAN TimerActive; - UINT32 u32TotalDSD; - UINT32 aTxPktSizeHist[MIBS_MAX_HIST_ENTRIES]; - UINT32 aRxPktSizeHist[MIBS_MAX_HIST_ENTRIES]; -}S_MIBS_HOST_INFO; - -typedef struct _S_MIBS_CLASSIFIER_RULE -{ - ULONG ulSFID; - UCHAR ucReserved[2]; - B_UINT16 uiClassifierRuleIndex; - BOOLEAN bUsed; - USHORT usVCID_Value; - // This field detemines the Classifier Priority - B_UINT8 u8ClassifierRulePriority; - U_MIBS_IP_ADDRESS stSrcIpAddress; - /*IP Source Address Length*/ - UCHAR ucIPSourceAddressLength; - - U_MIBS_IP_ADDRESS stDestIpAddress; + unsigned long BEBucketSize; + unsigned long rtPSBucketSize; + unsigned long LastTxQueueIndex; + bool TxOutofDescriptors; + bool TimerActive; + u32 u32TotalDSD; + u32 aTxPktSizeHist[MIBS_MAX_HIST_ENTRIES]; + u32 aRxPktSizeHist[MIBS_MAX_HIST_ENTRIES]; +}; + +struct bcm_mibs_classifier_rule { + unsigned long ulSFID; + unsigned char ucReserved[2]; + u16 uiClassifierRuleIndex; + bool bUsed; + unsigned short usVCID_Value; + u8 u8ClassifierRulePriority; + union bcm_mibs_ip_addr stSrcIpAddress; + /* IP Source Address Length */ + unsigned char ucIPSourceAddressLength; + union bcm_mibs_ip_addr stDestIpAddress; /* IP Destination Address Length */ - UCHAR ucIPDestinationAddressLength; - UCHAR ucIPTypeOfServiceLength;//Type of service Length - UCHAR ucTosLow;//Tos Low - UCHAR ucTosHigh;//Tos High - UCHAR ucTosMask;//Tos Mask - UCHAR ucProtocolLength;//protocol Length - UCHAR ucProtocol[MIBS_MAX_PROTOCOL_LENGTH];//protocol Length - USHORT usSrcPortRangeLo[MIBS_MAX_PORT_RANGE]; - USHORT usSrcPortRangeHi[MIBS_MAX_PORT_RANGE]; - UCHAR ucSrcPortRangeLength; - USHORT usDestPortRangeLo[MIBS_MAX_PORT_RANGE]; - USHORT usDestPortRangeHi[MIBS_MAX_PORT_RANGE]; - UCHAR ucDestPortRangeLength; - BOOLEAN bProtocolValid; - BOOLEAN bTOSValid; - BOOLEAN bDestIpValid; - BOOLEAN bSrcIpValid; - UCHAR ucDirection; - BOOLEAN bIpv6Protocol; - UINT32 u32PHSRuleID; -}S_MIBS_CLASSIFIER_RULE; - - -typedef struct _S_MIBS_PHS_RULE -{ - ULONG ulSFID; - /// brief 8bit PHSI Of The Service Flow - B_UINT8 u8PHSI; - /// brief PHSF Of The Service Flow - B_UINT8 u8PHSFLength; - B_UINT8 u8PHSF[MIBS_MAX_PHS_LENGTHS]; - /// brief PHSM Of The Service Flow - B_UINT8 u8PHSMLength; - B_UINT8 u8PHSM[MIBS_MAX_PHS_LENGTHS]; - /// brief 8bit PHSS Of The Service Flow - B_UINT8 u8PHSS; - /// brief 8bit PHSV Of The Service Flow - B_UINT8 u8PHSV; - // Reserved bytes are 5, so that it is similar to S_PHS_RULE structure. - B_UINT8 reserved[5]; + unsigned char ucIPDestinationAddressLength; + unsigned char ucIPTypeOfServiceLength; + unsigned char ucTosLow; + unsigned char ucTosHigh; + unsigned char ucTosMask; + unsigned char ucProtocolLength; + unsigned char ucProtocol[MIBS_MAX_PROTOCOL_LENGTH]; + unsigned short usSrcPortRangeLo[MIBS_MAX_PORT_RANGE]; + unsigned short usSrcPortRangeHi[MIBS_MAX_PORT_RANGE]; + unsigned char ucSrcPortRangeLength; + unsigned short usDestPortRangeLo[MIBS_MAX_PORT_RANGE]; + unsigned short usDestPortRangeHi[MIBS_MAX_PORT_RANGE]; + unsigned char ucDestPortRangeLength; + bool bProtocolValid; + bool bTOSValid; + bool bDestIpValid; + bool bSrcIpValid; + unsigned char ucDirection; + bool bIpv6Protocol; + u32 u32PHSRuleID; +}; + +struct bcm_mibs_phs_rule { + unsigned long ulSFID; + u8 u8PHSI; + u8 u8PHSFLength; + u8 u8PHSF[MIBS_MAX_PHS_LENGTHS]; + u8 u8PHSMLength; + u8 u8PHSM[MIBS_MAX_PHS_LENGTHS]; + u8 u8PHSS; + u8 u8PHSV; + u8 reserved[5]; + long PHSModifiedBytes; + unsigned long PHSModifiedNumPackets; + unsigned long PHSErrorNumPackets; +}; + +struct bcm_mibs_parameters { + u32 wmanIfSfid; + u32 wmanIfCmnCpsSfState; + u32 wmanIfCmnCpsMaxSustainedRate; + u32 wmanIfCmnCpsMaxTrafficBurst; + u32 wmanIfCmnCpsMinReservedRate; + u32 wmanIfCmnCpsToleratedJitter; + u32 wmanIfCmnCpsMaxLatency; + u32 wmanIfCmnCpsFixedVsVariableSduInd; + u32 wmanIfCmnCpsSduSize; + u32 wmanIfCmnCpsSfSchedulingType; + u32 wmanIfCmnCpsArqEnable; + u32 wmanIfCmnCpsArqWindowSize; + u32 wmanIfCmnCpsArqBlockLifetime; + u32 wmanIfCmnCpsArqSyncLossTimeout; + u32 wmanIfCmnCpsArqDeliverInOrder; + u32 wmanIfCmnCpsArqRxPurgeTimeout; + u32 wmanIfCmnCpsArqBlockSize; + u32 wmanIfCmnCpsMinRsvdTolerableRate; + u32 wmanIfCmnCpsReqTxPolicy; + u32 wmanIfCmnSfCsSpecification; + u32 wmanIfCmnCpsTargetSaid; +}; + +struct bcm_mibs_table { + unsigned long ulSFID; + unsigned short usVCID_Value; + unsigned int uiThreshold; + u8 u8TrafficPriority; + bool bValid; + bool bActive; + bool bActivateRequestSent; + u8 u8QueueType; + unsigned int uiMaxBucketSize; + unsigned int uiCurrentQueueDepthOnTarget; + unsigned int uiCurrentBytesOnHost; + unsigned int uiCurrentPacketsOnHost; + unsigned int uiDroppedCountBytes; + unsigned int uiDroppedCountPackets; + unsigned int uiSentBytes; + unsigned int uiSentPackets; + unsigned int uiCurrentDrainRate; + unsigned int uiThisPeriodSentBytes; + u64 liDrainCalculated; + unsigned int uiCurrentTokenCount; + u64 liLastUpdateTokenAt; + unsigned int uiMaxAllowedRate; + unsigned int NumOfPacketsSent; + unsigned char ucDirection; + unsigned short usCID; + struct bcm_mibs_parameters stMibsExtServiceFlowTable; + unsigned int uiCurrentRxRate; + unsigned int uiThisPeriodRxBytes; + unsigned int uiTotalRxBytes; + unsigned int uiTotalTxBytes; +}; + +struct bcm_mibs_dropped_cntrl_msg { + unsigned long cm_responses; + unsigned long cm_control_newdsx_multiclassifier_resp; + unsigned long link_control_resp; + unsigned long status_rsp; + unsigned long stats_pointer_resp; + unsigned long idle_mode_status; + unsigned long auth_ss_host_msg; + unsigned long low_priority_message; +}; + +struct bcm_host_stats_mibs { + struct bcm_mibs_host_info stHostInfo; + struct bcm_mibs_classifier_rule astClassifierTable[MIBS_MAX_CLASSIFIERS]; + struct bcm_mibs_table astSFtable[MIBS_MAX_SERVICEFLOWS]; + struct bcm_mibs_phs_rule astPhsRulesTable[MIBS_MAX_PHSRULES]; + struct bcm_mibs_dropped_cntrl_msg stDroppedAppCntrlMsgs; +}; - LONG PHSModifiedBytes; - ULONG PHSModifiedNumPackets; - ULONG PHSErrorNumPackets; -}S_MIBS_PHS_RULE; - -typedef struct _S_MIBS_EXTSERVICEFLOW_PARAMETERS -{ - UINT32 wmanIfSfid; - UINT32 wmanIfCmnCpsSfState; - UINT32 wmanIfCmnCpsMaxSustainedRate; - UINT32 wmanIfCmnCpsMaxTrafficBurst; - UINT32 wmanIfCmnCpsMinReservedRate; - UINT32 wmanIfCmnCpsToleratedJitter; - UINT32 wmanIfCmnCpsMaxLatency; - UINT32 wmanIfCmnCpsFixedVsVariableSduInd; - UINT32 wmanIfCmnCpsSduSize; - UINT32 wmanIfCmnCpsSfSchedulingType; - UINT32 wmanIfCmnCpsArqEnable; - UINT32 wmanIfCmnCpsArqWindowSize; - UINT32 wmanIfCmnCpsArqBlockLifetime; - UINT32 wmanIfCmnCpsArqSyncLossTimeout; - UINT32 wmanIfCmnCpsArqDeliverInOrder; - UINT32 wmanIfCmnCpsArqRxPurgeTimeout; - UINT32 wmanIfCmnCpsArqBlockSize; - UINT32 wmanIfCmnCpsMinRsvdTolerableRate; - UINT32 wmanIfCmnCpsReqTxPolicy; - UINT32 wmanIfCmnSfCsSpecification; - UINT32 wmanIfCmnCpsTargetSaid; - -}S_MIBS_EXTSERVICEFLOW_PARAMETERS; - - -typedef struct _S_MIBS_SERVICEFLOW_TABLE -{ - //classification extension Rule - ULONG ulSFID; - USHORT usVCID_Value; - UINT uiThreshold; - // This field determines the priority of the SF Queues - B_UINT8 u8TrafficPriority; - - BOOLEAN bValid; - BOOLEAN bActive; - BOOLEAN bActivateRequestSent; - //BE or rtPS - B_UINT8 u8QueueType; - //maximum size of the bucket for the queue - UINT uiMaxBucketSize; - UINT uiCurrentQueueDepthOnTarget; - UINT uiCurrentBytesOnHost; - UINT uiCurrentPacketsOnHost; - UINT uiDroppedCountBytes; - UINT uiDroppedCountPackets; - UINT uiSentBytes; - UINT uiSentPackets; - UINT uiCurrentDrainRate; - UINT uiThisPeriodSentBytes; - LARGE_INTEGER liDrainCalculated; - UINT uiCurrentTokenCount; - LARGE_INTEGER liLastUpdateTokenAt; - UINT uiMaxAllowedRate; - UINT NumOfPacketsSent; - UCHAR ucDirection; - USHORT usCID; - S_MIBS_EXTSERVICEFLOW_PARAMETERS stMibsExtServiceFlowTable; - UINT uiCurrentRxRate; - UINT uiThisPeriodRxBytes; - UINT uiTotalRxBytes; - UINT uiTotalTxBytes; -}S_MIBS_SERVICEFLOW_TABLE; - -typedef struct _S_MIBS_DROPPED_APP_CNTRL_MESSAGES -{ - ULONG cm_responses; - ULONG cm_control_newdsx_multiclassifier_resp; - ULONG link_control_resp; - ULONG status_rsp; - ULONG stats_pointer_resp; - ULONG idle_mode_status; - ULONG auth_ss_host_msg; - ULONG low_priority_message; - -}S_MIBS_DROPPED_APP_CNTRL_MESSAGES; - -typedef struct _S_MIBS_HOST_STATS_MIBS -{ - S_MIBS_HOST_INFO stHostInfo; - S_MIBS_CLASSIFIER_RULE astClassifierTable[MIBS_MAX_CLASSIFIERS]; - S_MIBS_SERVICEFLOW_TABLE astSFtable[MIBS_MAX_SERVICEFLOWS]; - S_MIBS_PHS_RULE astPhsRulesTable[MIBS_MAX_PHSRULES]; - S_MIBS_DROPPED_APP_CNTRL_MESSAGES stDroppedAppCntrlMsgs; -}S_MIBS_HOST_STATS_MIBS; #endif - - diff --git a/drivers/staging/bcm/InterfaceAdapter.h b/drivers/staging/bcm/InterfaceAdapter.h index 4607c265d981..06a6b18bca48 100644 --- a/drivers/staging/bcm/InterfaceAdapter.h +++ b/drivers/staging/bcm/InterfaceAdapter.h @@ -1,97 +1,79 @@ #ifndef _INTERFACE_ADAPTER_H #define _INTERFACE_ADAPTER_H -typedef struct _BULK_ENDP_IN -{ - PCHAR bulk_in_buffer; - size_t bulk_in_size; - UCHAR bulk_in_endpointAddr; - UINT bulk_in_pipe; -}BULK_ENDP_IN, *PBULK_ENDP_IN; - - -typedef struct _BULK_ENDP_OUT -{ - UCHAR bulk_out_buffer; - size_t bulk_out_size; - UCHAR bulk_out_endpointAddr; - UINT bulk_out_pipe; - //this is used when int out endpoint is used as bulk out end point - UCHAR int_out_interval; -}BULK_ENDP_OUT, *PBULK_ENDP_OUT; - -typedef struct _INTR_ENDP_IN -{ - PCHAR int_in_buffer; - size_t int_in_size; - UCHAR int_in_endpointAddr; - UCHAR int_in_interval; - UINT int_in_pipe; -}INTR_ENDP_IN, *PINTR_ENDP_IN; - -typedef struct _INTR_ENDP_OUT -{ - PCHAR int_out_buffer; - size_t int_out_size; - UCHAR int_out_endpointAddr; - UCHAR int_out_interval; - UINT int_out_pipe; -}INTR_ENDP_OUT, *PINTR_ENDP_OUT; - - -typedef struct _USB_TCB -{ +struct bcm_bulk_endpoint_in { + char *bulk_in_buffer; + size_t bulk_in_size; + unsigned char bulk_in_endpointAddr; + unsigned int bulk_in_pipe; +}; + +struct bcm_bulk_endpoint_out { + unsigned char bulk_out_buffer; + size_t bulk_out_size; + unsigned char bulk_out_endpointAddr; + unsigned int bulk_out_pipe; + /* this is used when int out endpoint is used as bulk out end point */ + unsigned char int_out_interval; +}; + +struct bcm_intr_endpoint_in { + char *int_in_buffer; + size_t int_in_size; + unsigned char int_in_endpointAddr; + unsigned char int_in_interval; + unsigned int int_in_pipe; +}; + +struct bcm_intr_endpoint_out { + char *int_out_buffer; + size_t int_out_size; + unsigned char int_out_endpointAddr; + unsigned char int_out_interval; + unsigned int int_out_pipe; +}; + +struct bcm_usb_tcb { struct urb *urb; - PVOID psIntfAdapter; - BOOLEAN bUsed; -}USB_TCB, *PUSB_TCB; + void *psIntfAdapter; + bool bUsed; +}; - -typedef struct _USB_RCB -{ +struct bcm_usb_rcb { struct urb *urb; - PVOID psIntfAdapter; - BOOLEAN bUsed; -}USB_RCB, *PUSB_RCB; + void *psIntfAdapter; + bool bUsed; +}; /* -//This is the interface specific Sub-Adapter -//Structure. -*/ -typedef struct _S_INTERFACE_ADAPTER -{ - struct usb_device * udev; - struct usb_interface * interface; - + * This is the interface specific Sub-Adapter + * Structure. + */ +struct bcm_interface_adapter { + struct usb_device *udev; + struct usb_interface *interface; /* Bulk endpoint in info */ - BULK_ENDP_IN sBulkIn; + struct bcm_bulk_endpoint_in sBulkIn; /* Bulk endpoint out info */ - BULK_ENDP_OUT sBulkOut; + struct bcm_bulk_endpoint_out sBulkOut; /* Interrupt endpoint in info */ - INTR_ENDP_IN sIntrIn; + struct bcm_intr_endpoint_in sIntrIn; /* Interrupt endpoint out info */ - INTR_ENDP_OUT sIntrOut; - - - - ULONG ulInterruptData[2]; - + struct bcm_intr_endpoint_out sIntrOut; + unsigned long ulInterruptData[2]; struct urb *psInterruptUrb; - - USB_TCB asUsbTcb[MAXIMUM_USB_TCB]; - USB_RCB asUsbRcb[MAXIMUM_USB_RCB]; - atomic_t uNumTcbUsed; - atomic_t uCurrTcb; - atomic_t uNumRcbUsed; - atomic_t uCurrRcb; - + struct bcm_usb_tcb asUsbTcb[MAXIMUM_USB_TCB]; + struct bcm_usb_rcb asUsbRcb[MAXIMUM_USB_RCB]; + atomic_t uNumTcbUsed; + atomic_t uCurrTcb; + atomic_t uNumRcbUsed; + atomic_t uCurrRcb; struct bcm_mini_adapter *psAdapter; - BOOLEAN bFlashBoot; - BOOLEAN bHighSpeedDevice ; - - BOOLEAN bSuspended; - BOOLEAN bPreparingForBusSuspend; + bool bFlashBoot; + bool bHighSpeedDevice; + bool bSuspended; + bool bPreparingForBusSuspend; struct work_struct usbSuspendWork; -}S_INTERFACE_ADAPTER,*PS_INTERFACE_ADAPTER; +}; #endif diff --git a/drivers/staging/bcm/InterfaceDld.c b/drivers/staging/bcm/InterfaceDld.c index 3a89e33733ee..87117a797d5b 100644 --- a/drivers/staging/bcm/InterfaceDld.c +++ b/drivers/staging/bcm/InterfaceDld.c @@ -6,7 +6,7 @@ int InterfaceFileDownload(PVOID arg, struct file *flp, unsigned int on_chip_loc) mm_segment_t oldfs = {0}; int errno = 0, len = 0; /* ,is_config_file = 0 */ loff_t pos = 0; - PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)arg; + struct bcm_interface_adapter *psIntfAdapter = (struct bcm_interface_adapter *)arg; /* struct bcm_mini_adapter *Adapter = psIntfAdapter->psAdapter; */ char *buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL); @@ -61,7 +61,7 @@ int InterfaceFileReadbackFromChip(PVOID arg, struct file *flp, unsigned int on_c loff_t pos = 0; static int fw_down; INT Status = STATUS_SUCCESS; - PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)arg; + struct bcm_interface_adapter *psIntfAdapter = (struct bcm_interface_adapter *)arg; int bytes; buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_DMA); diff --git a/drivers/staging/bcm/InterfaceIdleMode.c b/drivers/staging/bcm/InterfaceIdleMode.c index 4f2f490921e1..a1bf21579d3f 100644 --- a/drivers/staging/bcm/InterfaceIdleMode.c +++ b/drivers/staging/bcm/InterfaceIdleMode.c @@ -156,7 +156,7 @@ static int InterfaceAbortIdlemode(struct bcm_mini_adapter *Adapter, unsigned int int lenwritten = 0; unsigned char aucAbortPattern[8]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; - PS_INTERFACE_ADAPTER psInterfaceAdapter = Adapter->pvInterfaceAdapter; + struct bcm_interface_adapter *psInterfaceAdapter = Adapter->pvInterfaceAdapter; //Abort Bus suspend if its already suspended if((TRUE == psInterfaceAdapter->bSuspended) && (TRUE == Adapter->bDoSuspend)) diff --git a/drivers/staging/bcm/InterfaceIdleMode.h b/drivers/staging/bcm/InterfaceIdleMode.h index c3338c8a1dc8..2ef64003aa89 100644 --- a/drivers/staging/bcm/InterfaceIdleMode.h +++ b/drivers/staging/bcm/InterfaceIdleMode.h @@ -3,11 +3,12 @@ INT InterfaceIdleModeWakeup(struct bcm_mini_adapter *Adapter); -INT InterfaceIdleModeRespond(struct bcm_mini_adapter *Adapter, unsigned int *puiBuffer); +INT InterfaceIdleModeRespond(struct bcm_mini_adapter *Adapter, + unsigned int *puiBuffer); VOID InterfaceWriteIdleModeWakePattern(struct bcm_mini_adapter *Adapter); -INT InterfaceWakeUp(struct bcm_mini_adapter * Adapter); +INT InterfaceWakeUp(struct bcm_mini_adapter *Adapter); VOID InterfaceHandleShutdownModeWakeup(struct bcm_mini_adapter *Adapter); #endif diff --git a/drivers/staging/bcm/InterfaceInit.c b/drivers/staging/bcm/InterfaceInit.c index b05f5f73548c..eb246430b320 100644 --- a/drivers/staging/bcm/InterfaceInit.c +++ b/drivers/staging/bcm/InterfaceInit.c @@ -4,11 +4,12 @@ static struct usb_device_id InterfaceUsbtable[] = { { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3) }, { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3B) }, { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3L) }, - { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_SM250) }, + { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_SYM) }, { USB_DEVICE(BCM_USB_VENDOR_ID_ZTE, BCM_USB_PRODUCT_ID_226) }, { USB_DEVICE(BCM_USB_VENDOR_ID_FOXCONN, BCM_USB_PRODUCT_ID_1901) }, { USB_DEVICE(BCM_USB_VENDOR_ID_ZTE, BCM_USB_PRODUCT_ID_ZTE_TU25) }, { USB_DEVICE(BCM_USB_VENDOR_ID_ZTE, BCM_USB_PRODUCT_ID_ZTE_226) }, + { USB_DEVICE(BCM_USB_VENDOR_ID_ZTE, BCM_USB_PRODUCT_ID_ZTE_326) }, { } }; MODULE_DEVICE_TABLE(usb, InterfaceUsbtable); @@ -22,9 +23,9 @@ static const u32 default_msg = | NETIF_MSG_TIMER | NETIF_MSG_TX_ERR | NETIF_MSG_RX_ERR | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN; -static int InterfaceAdapterInit(PS_INTERFACE_ADAPTER Adapter); +static int InterfaceAdapterInit(struct bcm_interface_adapter *Adapter); -static void InterfaceAdapterFree(PS_INTERFACE_ADAPTER psIntfAdapter) +static void InterfaceAdapterFree(struct bcm_interface_adapter *psIntfAdapter) { int i = 0; @@ -79,7 +80,7 @@ static void ConfigureEndPointTypesThroughEEPROM(struct bcm_mini_adapter *Adapter ulReg = ntohl(EP2_CFG_REG); BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x132, 4, TRUE); - if (((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter))->bHighSpeedDevice == TRUE) { + if (((struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter))->bHighSpeedDevice == TRUE) { ulReg = ntohl(EP2_CFG_INT); BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x136, 4, TRUE); } else { @@ -145,7 +146,7 @@ static int usbbcm_device_probe(struct usb_interface *intf, const struct usb_devi struct usb_device *udev = interface_to_usbdev(intf); int retval; struct bcm_mini_adapter *psAdapter; - PS_INTERFACE_ADAPTER psIntfAdapter; + struct bcm_interface_adapter *psIntfAdapter; struct net_device *ndev; /* Reserve one extra queue for the bit-bucket */ @@ -189,7 +190,7 @@ static int usbbcm_device_probe(struct usb_interface *intf, const struct usb_devi } /* Allocate interface adapter structure */ - psIntfAdapter = kzalloc(sizeof(S_INTERFACE_ADAPTER), GFP_KERNEL); + psIntfAdapter = kzalloc(sizeof(struct bcm_interface_adapter), GFP_KERNEL); if (psIntfAdapter == NULL) { dev_err(&udev->dev, DRV_NAME ": no memory for Interface adapter\n"); AdapterFree(psAdapter); @@ -257,7 +258,7 @@ static int usbbcm_device_probe(struct usb_interface *intf, const struct usb_devi static void usbbcm_disconnect(struct usb_interface *intf) { - PS_INTERFACE_ADAPTER psIntfAdapter = usb_get_intfdata(intf); + struct bcm_interface_adapter *psIntfAdapter = usb_get_intfdata(intf); struct bcm_mini_adapter *psAdapter; struct usb_device *udev = interface_to_usbdev(intf); @@ -276,7 +277,7 @@ static void usbbcm_disconnect(struct usb_interface *intf) usb_put_dev(udev); } -static int AllocUsbCb(PS_INTERFACE_ADAPTER psIntfAdapter) +static int AllocUsbCb(struct bcm_interface_adapter *psIntfAdapter) { int i = 0; @@ -311,7 +312,7 @@ static int AllocUsbCb(PS_INTERFACE_ADAPTER psIntfAdapter) return 0; } -static int device_run(PS_INTERFACE_ADAPTER psIntfAdapter) +static int device_run(struct bcm_interface_adapter *psIntfAdapter) { int value = 0; UINT status = STATUS_SUCCESS; @@ -421,7 +422,7 @@ static inline int bcm_usb_endpoint_is_isoc_out(const struct usb_endpoint_descrip return bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_out(epd); } -static int InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter) +static int InterfaceAdapterInit(struct bcm_interface_adapter *psIntfAdapter) { struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; @@ -619,7 +620,7 @@ static int InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter) static int InterfaceSuspend(struct usb_interface *intf, pm_message_t message) { - PS_INTERFACE_ADAPTER psIntfAdapter = usb_get_intfdata(intf); + struct bcm_interface_adapter *psIntfAdapter = usb_get_intfdata(intf); psIntfAdapter->bSuspended = TRUE; @@ -646,7 +647,7 @@ static int InterfaceSuspend(struct usb_interface *intf, pm_message_t message) static int InterfaceResume(struct usb_interface *intf) { - PS_INTERFACE_ADAPTER psIntfAdapter = usb_get_intfdata(intf); + struct bcm_interface_adapter *psIntfAdapter = usb_get_intfdata(intf); mdelay(100); psIntfAdapter->bSuspended = FALSE; diff --git a/drivers/staging/bcm/InterfaceInit.h b/drivers/staging/bcm/InterfaceInit.h index 866924e35f9c..ffa6e9667ec4 100644 --- a/drivers/staging/bcm/InterfaceInit.h +++ b/drivers/staging/bcm/InterfaceInit.h @@ -8,11 +8,11 @@ #define BCM_USB_PRODUCT_ID_T3 0x0300 #define BCM_USB_PRODUCT_ID_T3B 0x0210 #define BCM_USB_PRODUCT_ID_T3L 0x0220 -#define BCM_USB_PRODUCT_ID_SM250 0xbccd #define BCM_USB_PRODUCT_ID_SYM 0x15E #define BCM_USB_PRODUCT_ID_1901 0xe017 #define BCM_USB_PRODUCT_ID_226 0x0132 /* not sure if this is valid */ #define BCM_USB_PRODUCT_ID_ZTE_226 0x172 +#define BCM_USB_PRODUCT_ID_ZTE_326 0x173 /* ZTE AX326 */ #define BCM_USB_PRODUCT_ID_ZTE_TU25 0x0007 #define BCM_USB_MINOR_BASE 192 @@ -21,6 +21,6 @@ int InterfaceInitialize(void); int InterfaceExit(void); -int usbbcm_worker_thread(PS_INTERFACE_ADAPTER psIntfAdapter); +int usbbcm_worker_thread(struct bcm_interface_adapter *psIntfAdapter); #endif diff --git a/drivers/staging/bcm/InterfaceIsr.c b/drivers/staging/bcm/InterfaceIsr.c index 6ee3428daa55..8322f1b76e2a 100644 --- a/drivers/staging/bcm/InterfaceIsr.c +++ b/drivers/staging/bcm/InterfaceIsr.c @@ -4,7 +4,7 @@ static void read_int_callback(struct urb *urb/*, struct pt_regs *regs*/) { int status = urb->status; - PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)urb->context; + struct bcm_interface_adapter *psIntfAdapter = (struct bcm_interface_adapter *)urb->context; struct bcm_mini_adapter *Adapter = psIntfAdapter->psAdapter ; if (netif_msg_intr(Adapter)) @@ -114,7 +114,7 @@ static void read_int_callback(struct urb *urb/*, struct pt_regs *regs*/) } -int CreateInterruptUrb(PS_INTERFACE_ADAPTER psIntfAdapter) +int CreateInterruptUrb(struct bcm_interface_adapter *psIntfAdapter) { psIntfAdapter->psInterruptUrb = usb_alloc_urb(0, GFP_KERNEL); if (!psIntfAdapter->psInterruptUrb) @@ -143,7 +143,7 @@ int CreateInterruptUrb(PS_INTERFACE_ADAPTER psIntfAdapter) } -INT StartInterruptUrb(PS_INTERFACE_ADAPTER psIntfAdapter) +INT StartInterruptUrb(struct bcm_interface_adapter *psIntfAdapter) { INT status = 0; diff --git a/drivers/staging/bcm/InterfaceIsr.h b/drivers/staging/bcm/InterfaceIsr.h index 40399788c419..3073bd71cfeb 100644 --- a/drivers/staging/bcm/InterfaceIsr.h +++ b/drivers/staging/bcm/InterfaceIsr.h @@ -1,10 +1,10 @@ #ifndef _INTERFACE_ISR_H #define _INTERFACE_ISR_H -int CreateInterruptUrb(PS_INTERFACE_ADAPTER psIntfAdapter); +int CreateInterruptUrb(struct bcm_interface_adapter *psIntfAdapter); -INT StartInterruptUrb(PS_INTERFACE_ADAPTER psIntfAdapter); +INT StartInterruptUrb(struct bcm_interface_adapter *psIntfAdapter); VOID InterfaceEnableInterrupt(struct bcm_mini_adapter *Adapter); diff --git a/drivers/staging/bcm/InterfaceMisc.c b/drivers/staging/bcm/InterfaceMisc.c index bbe909946091..afca010f9db5 100644 --- a/drivers/staging/bcm/InterfaceMisc.c +++ b/drivers/staging/bcm/InterfaceMisc.c @@ -1,17 +1,14 @@ #include "headers.h" -INT InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter, - UINT addr, - PVOID buff, - INT len) +int InterfaceRDM(struct bcm_interface_adapter *psIntfAdapter, + unsigned int addr, + void *buff, + int len) { int bytes; - USHORT usRetries = 0; - if (psIntfAdapter == NULL) { - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Interface Adapter is NULL"); + if (!psIntfAdapter) return -EINVAL; - } if (psIntfAdapter->psAdapter->device_removed == TRUE) { BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Device got removed"); @@ -29,27 +26,21 @@ INT InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter, } psIntfAdapter->psAdapter->DeviceAccess = TRUE; - do { - bytes = usb_control_msg(psIntfAdapter->udev, - usb_rcvctrlpipe(psIntfAdapter->udev, 0), - 0x02, - 0xC2, - (addr & 0xFFFF), - ((addr >> 16) & 0xFFFF), - buff, - len, - 5000); - - usRetries++; - if (-ENODEV == bytes) { - psIntfAdapter->psAdapter->device_removed = TRUE; - break; - } + bytes = usb_control_msg(psIntfAdapter->udev, + usb_rcvctrlpipe(psIntfAdapter->udev, 0), + 0x02, + 0xC2, + (addr & 0xFFFF), + ((addr >> 16) & 0xFFFF), + buff, + len, + 5000); - } while ((bytes < 0) && (usRetries < MAX_RDM_WRM_RETIRES)); + if (-ENODEV == bytes) + psIntfAdapter->psAdapter->device_removed = TRUE; if (bytes < 0) - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d, retires :%d", bytes, usRetries); + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d", bytes); else BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM sent %d", bytes); @@ -57,18 +48,15 @@ INT InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter, return bytes; } -INT InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter, - UINT addr, - PVOID buff, - INT len) +int InterfaceWRM(struct bcm_interface_adapter *psIntfAdapter, + unsigned int addr, + void *buff, + int len) { int retval = 0; - USHORT usRetries = 0; - if (psIntfAdapter == NULL) { - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Interface Adapter is NULL"); + if (!psIntfAdapter) return -EINVAL; - } if (psIntfAdapter->psAdapter->device_removed == TRUE) { BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Device got removed"); @@ -87,27 +75,21 @@ INT InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter, psIntfAdapter->psAdapter->DeviceAccess = TRUE; - do { - retval = usb_control_msg(psIntfAdapter->udev, - usb_sndctrlpipe(psIntfAdapter->udev, 0), - 0x01, - 0x42, - (addr & 0xFFFF), - ((addr >> 16) & 0xFFFF), - buff, - len, - 5000); - - usRetries++; - if (-ENODEV == retval) { - psIntfAdapter->psAdapter->device_removed = TRUE; - break; - } + retval = usb_control_msg(psIntfAdapter->udev, + usb_sndctrlpipe(psIntfAdapter->udev, 0), + 0x01, + 0x42, + (addr & 0xFFFF), + ((addr >> 16) & 0xFFFF), + buff, + len, + 5000); - } while ((retval < 0) && (usRetries < MAX_RDM_WRM_RETIRES)); + if (-ENODEV == retval) + psIntfAdapter->psAdapter->device_removed = TRUE; if (retval < 0) { - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM failed status :%d, retires :%d", retval, usRetries); + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM failed status :%d", retval); psIntfAdapter->psAdapter->DeviceAccess = FALSE; return retval; } else { @@ -117,26 +99,26 @@ INT InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter, } } -INT BcmRDM(PVOID arg, - UINT addr, - PVOID buff, - INT len) +int BcmRDM(void *arg, + unsigned int addr, + void *buff, + int len) { - return InterfaceRDM((PS_INTERFACE_ADAPTER)arg, addr, buff, len); + return InterfaceRDM((struct bcm_interface_adapter*)arg, addr, buff, len); } -INT BcmWRM(PVOID arg, - UINT addr, - PVOID buff, - INT len) +int BcmWRM(void *arg, + unsigned int addr, + void *buff, + int len) { - return InterfaceWRM((PS_INTERFACE_ADAPTER)arg, addr, buff, len); + return InterfaceWRM((struct bcm_interface_adapter *)arg, addr, buff, len); } -INT Bcm_clear_halt_of_endpoints(struct bcm_mini_adapter *Adapter) +int Bcm_clear_halt_of_endpoints(struct bcm_mini_adapter *Adapter) { - PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter); - INT status = STATUS_SUCCESS; + struct bcm_interface_adapter *psIntfAdapter = (struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter); + int status = STATUS_SUCCESS; /* * usb_clear_halt - tells device to clear endpoint halt/stall condition @@ -172,10 +154,10 @@ INT Bcm_clear_halt_of_endpoints(struct bcm_mini_adapter *Adapter) return status; } -VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter) +void Bcm_kill_all_URBs(struct bcm_interface_adapter *psIntfAdapter) { struct urb *tempUrb = NULL; - UINT i; + unsigned int i; /* * usb_kill_urb - cancel a transfer request and wait for it to finish @@ -193,7 +175,7 @@ VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter) */ /* Cancel submitted Interrupt-URB's */ - if (psIntfAdapter->psInterruptUrb != NULL) { + if (psIntfAdapter->psInterruptUrb) { if (psIntfAdapter->psInterruptUrb->status == -EINPROGRESS) usb_kill_urb(psIntfAdapter->psInterruptUrb); } @@ -222,11 +204,11 @@ VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter) atomic_set(&psIntfAdapter->uCurrRcb, 0); } -VOID putUsbSuspend(struct work_struct *work) +void putUsbSuspend(struct work_struct *work) { - PS_INTERFACE_ADAPTER psIntfAdapter = NULL; + struct bcm_interface_adapter *psIntfAdapter = NULL; struct usb_interface *intf = NULL; - psIntfAdapter = container_of(work, S_INTERFACE_ADAPTER, usbSuspendWork); + psIntfAdapter = container_of(work, struct bcm_interface_adapter, usbSuspendWork); intf = psIntfAdapter->interface; if (psIntfAdapter->bSuspended == FALSE) diff --git a/drivers/staging/bcm/InterfaceMisc.h b/drivers/staging/bcm/InterfaceMisc.h index 1dfabdc3aadd..bce6869a7478 100644 --- a/drivers/staging/bcm/InterfaceMisc.h +++ b/drivers/staging/bcm/InterfaceMisc.h @@ -2,13 +2,13 @@ #define __INTERFACE_MISC_H INT -InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter, +InterfaceRDM(struct bcm_interface_adapter *psIntfAdapter, UINT addr, PVOID buff, INT len); INT -InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter, +InterfaceWRM(struct bcm_interface_adapter *psIntfAdapter, UINT addr, PVOID buff, INT len); @@ -35,7 +35,7 @@ int BcmWRM(PVOID arg, INT Bcm_clear_halt_of_endpoints(struct bcm_mini_adapter *Adapter); -VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter); +VOID Bcm_kill_all_URBs(struct bcm_interface_adapter *psIntfAdapter); #define DISABLE_USB_ZERO_LEN_INT 0x0F011878 diff --git a/drivers/staging/bcm/InterfaceRx.c b/drivers/staging/bcm/InterfaceRx.c index 8a9f90fbdf13..26f5bc76111c 100644 --- a/drivers/staging/bcm/InterfaceRx.c +++ b/drivers/staging/bcm/InterfaceRx.c @@ -12,10 +12,10 @@ static int SearchVcid(struct bcm_mini_adapter *Adapter,unsigned short usVcid) } -static PUSB_RCB -GetBulkInRcb(PS_INTERFACE_ADAPTER psIntfAdapter) +static struct bcm_usb_rcb * +GetBulkInRcb(struct bcm_interface_adapter *psIntfAdapter) { - PUSB_RCB pRcb = NULL; + struct bcm_usb_rcb *pRcb = NULL; UINT index = 0; if((atomic_read(&psIntfAdapter->uNumRcbUsed) < MAXIMUM_USB_RCB) && @@ -43,8 +43,8 @@ static void read_bulk_callback(struct urb *urb) UINT uiIndex=0; int process_done = 1; //int idleflag = 0 ; - PUSB_RCB pRcb = (PUSB_RCB)urb->context; - PS_INTERFACE_ADAPTER psIntfAdapter = pRcb->psIntfAdapter; + struct bcm_usb_rcb *pRcb = (struct bcm_usb_rcb *)urb->context; + struct bcm_interface_adapter *psIntfAdapter = pRcb->psIntfAdapter; struct bcm_mini_adapter *Adapter = psIntfAdapter->psAdapter; struct bcm_leader *pLeader = urb->transfer_buffer; @@ -196,7 +196,7 @@ static void read_bulk_callback(struct urb *urb) atomic_dec(&psIntfAdapter->uNumRcbUsed); } -static int ReceiveRcb(PS_INTERFACE_ADAPTER psIntfAdapter, PUSB_RCB pRcb) +static int ReceiveRcb(struct bcm_interface_adapter *psIntfAdapter, struct bcm_usb_rcb *pRcb) { struct urb *urb = pRcb->urb; int retval = 0; @@ -240,10 +240,10 @@ Return: TRUE - If Rx was successful. Other - If an error occurred. */ -BOOLEAN InterfaceRx (PS_INTERFACE_ADAPTER psIntfAdapter) +BOOLEAN InterfaceRx (struct bcm_interface_adapter *psIntfAdapter) { USHORT RxDescCount = NUM_RX_DESC - atomic_read(&psIntfAdapter->uNumRcbUsed); - PUSB_RCB pRcb = NULL; + struct bcm_usb_rcb *pRcb = NULL; // RxDescCount = psIntfAdapter->psAdapter->CurrNumRecvDescs - // psIntfAdapter->psAdapter->PrevNumRecvDescs; diff --git a/drivers/staging/bcm/InterfaceRx.h b/drivers/staging/bcm/InterfaceRx.h index 96e81a1d37b8..424645e9e476 100644 --- a/drivers/staging/bcm/InterfaceRx.h +++ b/drivers/staging/bcm/InterfaceRx.h @@ -1,7 +1,7 @@ #ifndef _INTERFACE_RX_H #define _INTERFACE_RX_H -BOOLEAN InterfaceRx(PS_INTERFACE_ADAPTER Adapter); +BOOLEAN InterfaceRx(struct bcm_interface_adapter *Adapter); #endif diff --git a/drivers/staging/bcm/InterfaceTx.c b/drivers/staging/bcm/InterfaceTx.c index 7e2b53be4d9e..b8c785556dda 100644 --- a/drivers/staging/bcm/InterfaceTx.c +++ b/drivers/staging/bcm/InterfaceTx.c @@ -3,8 +3,8 @@ /*this is transmit call-back(BULK OUT)*/ static void write_bulk_callback(struct urb *urb/*, struct pt_regs *regs*/) { - PUSB_TCB pTcb= (PUSB_TCB)urb->context; - PS_INTERFACE_ADAPTER psIntfAdapter = pTcb->psIntfAdapter; + struct bcm_usb_tcb *pTcb= (struct bcm_usb_tcb *)urb->context; + struct bcm_interface_adapter *psIntfAdapter = pTcb->psIntfAdapter; struct bcm_link_request *pControlMsg = (struct bcm_link_request *)urb->transfer_buffer; struct bcm_mini_adapter *psAdapter = psIntfAdapter->psAdapter ; BOOLEAN bpowerDownMsg = FALSE ; @@ -107,9 +107,9 @@ err_exit : } -static PUSB_TCB GetBulkOutTcb(PS_INTERFACE_ADAPTER psIntfAdapter) +static struct bcm_usb_tcb *GetBulkOutTcb(struct bcm_interface_adapter *psIntfAdapter) { - PUSB_TCB pTcb = NULL; + struct bcm_usb_tcb *pTcb = NULL; UINT index = 0; if((atomic_read(&psIntfAdapter->uNumTcbUsed) < MAXIMUM_USB_TCB) && @@ -128,7 +128,7 @@ static PUSB_TCB GetBulkOutTcb(PS_INTERFACE_ADAPTER psIntfAdapter) return pTcb; } -static int TransmitTcb(PS_INTERFACE_ADAPTER psIntfAdapter, PUSB_TCB pTcb, PVOID data, int len) +static int TransmitTcb(struct bcm_interface_adapter *psIntfAdapter, struct bcm_usb_tcb *pTcb, PVOID data, int len) { struct urb *urb = pTcb->urb; @@ -182,9 +182,9 @@ static int TransmitTcb(PS_INTERFACE_ADAPTER psIntfAdapter, PUSB_TCB pTcb, PVOID int InterfaceTransmitPacket(PVOID arg, PVOID data, UINT len) { - PUSB_TCB pTcb= NULL; + struct bcm_usb_tcb *pTcb= NULL; - PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)arg; + struct bcm_interface_adapter *psIntfAdapter = (struct bcm_interface_adapter *)arg; pTcb= GetBulkOutTcb(psIntfAdapter); if(pTcb == NULL) { diff --git a/drivers/staging/bcm/Ioctl.h b/drivers/staging/bcm/Ioctl.h index f859cf1c47b0..8c70af90969b 100644 --- a/drivers/staging/bcm/Ioctl.h +++ b/drivers/staging/bcm/Ioctl.h @@ -1,247 +1,136 @@ #ifndef _IOCTL_H_ #define _IOCTL_H_ -typedef struct rdmbuffer -{ - ULONG Register; - ULONG Length; -}__attribute__((packed)) RDM_BUFFER, *PRDM_BUFFER; - - -typedef struct wrmbuffer -{ - ULONG Register; - ULONG Length; - UCHAR Data[4]; -}__attribute__((packed)) WRM_BUFFER, *PWRM_BUFFER; - - -typedef struct ioctlbuffer -{ +struct bcm_rdm_buffer { + unsigned long Register; + unsigned long Length; +} __packed; + +struct bcm_wrm_buffer { + unsigned long Register; + unsigned long Length; + unsigned char Data[4]; +} __packed; + +struct bcm_ioctl_buffer { void __user *InputBuffer; - ULONG InputLength; + unsigned long InputLength; void __user *OutputBuffer; - ULONG OutputLength; -}__attribute__((packed)) IOCTL_BUFFER, *PIOCTL_BUFFER; - -typedef struct stGPIOInfo -{ - UINT uiGpioNumber ; /* valid numbers 0-15 */ - UINT uiGpioValue; /* 1 set ; 0 not set */ -}__attribute__((packed))GPIO_INFO,*PGPIO_INFO; -typedef struct stUserThreadReq -{ - //0->Inactivate LED thread. - //1->Activate the LED thread - UINT ThreadState; -}__attribute__((packed))USER_THREAD_REQ,*PUSER_THREAD_REQ; -#define LED_THREAD_ACTIVATION_REQ 1 - - -////********** ioctl codes ***********//// - -#define BCM_IOCTL 'k' - -//1.Control code for CONTROL MESSAGES - -#define IOCTL_SEND_CONTROL_MESSAGE _IOW(BCM_IOCTL, 0x801,int) - -//2.Control code to write a particular value to a particular register -#define IOCTL_BCM_REGISTER_WRITE _IOW(BCM_IOCTL, 0x802, int) // - -//3. -#define IOCTL_BCM_REGISTER_READ _IOR(BCM_IOCTL, 0x803, int) // + unsigned long OutputLength; +} __packed; -//4.Control code to write x number of bytes to common memory -//starting from address y -#define IOCTL_BCM_COMMON_MEMORY_WRITE _IOW(BCM_IOCTL, 0x804, int)// +struct bcm_gpio_info { + unsigned int uiGpioNumber; /* valid numbers 0-15 */ + unsigned int uiGpioValue; /* 1 set ; 0 not set */ +} __packed; -//5.Control code to write x number of bytes to common memory -//starting from address y -#define IOCTL_BCM_COMMON_MEMORY_READ _IOR(BCM_IOCTL, 0x805, int)// - -//6.Control code for CONTROL MESSAGES -#define IOCTL_GET_CONTROL_MESSAGE _IOR(BCM_IOCTL, 0x806, int)// - -//7.Control code for FIRMWARE DOWNLOAD -#define IOCTL_BCM_FIRMWARE_DOWNLOAD _IOW(BCM_IOCTL, 0x807, int)// - -#define IOCTL_BCM_SET_SEND_VCID _IOW(BCM_IOCTL, 0x808, int) - -//9.Control code for TRANSFER MODE SWITCHING -#define IOCTL_BCM_SWITCH_TRANSFER_MODE _IOW(BCM_IOCTL, 0x809, int) -//10.Control code for LINK UP -#define IOCTL_LINK_REQ _IOW(BCM_IOCTL, 0x80A, int) - -//11.Control code for RSSI Level Request -#define IOCTL_RSSI_LEVEL_REQ _IOW(BCM_IOCTL, 0x80B, int) -//12.Control code for IDLE MODE CONTROL -#define IOCTL_IDLE_REQ _IOW(BCM_IOCTL, 0x80C, int) -//13.Control code for SS/BS info -#define IOCTL_SS_INFO_REQ _IOW(BCM_IOCTL, 0x80D, int) +struct bcm_user_thread_req { + /* 0->Inactivate LED thread. */ + /* 1->Activate the LED thread */ + unsigned int ThreadState; +} __packed; +#define LED_THREAD_ACTIVATION_REQ 1 +#define BCM_IOCTL 'k' +#define IOCTL_SEND_CONTROL_MESSAGE _IOW(BCM_IOCTL, 0x801, int) +#define IOCTL_BCM_REGISTER_WRITE _IOW(BCM_IOCTL, 0x802, int) +#define IOCTL_BCM_REGISTER_READ _IOR(BCM_IOCTL, 0x803, int) +#define IOCTL_BCM_COMMON_MEMORY_WRITE _IOW(BCM_IOCTL, 0x804, int) +#define IOCTL_BCM_COMMON_MEMORY_READ _IOR(BCM_IOCTL, 0x805, int) +#define IOCTL_GET_CONTROL_MESSAGE _IOR(BCM_IOCTL, 0x806, int) +#define IOCTL_BCM_FIRMWARE_DOWNLOAD _IOW(BCM_IOCTL, 0x807, int) +#define IOCTL_BCM_SET_SEND_VCID _IOW(BCM_IOCTL, 0x808, int) +#define IOCTL_BCM_SWITCH_TRANSFER_MODE _IOW(BCM_IOCTL, 0x809, int) +#define IOCTL_LINK_REQ _IOW(BCM_IOCTL, 0x80A, int) +#define IOCTL_RSSI_LEVEL_REQ _IOW(BCM_IOCTL, 0x80B, int) +#define IOCTL_IDLE_REQ _IOW(BCM_IOCTL, 0x80C, int) +#define IOCTL_SS_INFO_REQ _IOW(BCM_IOCTL, 0x80D, int) #define IOCTL_GET_STATISTICS_POINTER _IOW(BCM_IOCTL, 0x80E, int) - -#define IOCTL_CM_REQUEST _IOW(BCM_IOCTL, 0x80F, int) - -#define IOCTL_INIT_PARAM_REQ _IOW(BCM_IOCTL, 0x810, int) - -#define IOCTL_MAC_ADDR_REQ _IOW(BCM_IOCTL, 0x811, int) - -#define IOCTL_MAC_ADDR_RESP _IOWR(BCM_IOCTL, 0x812, int) - -#define IOCTL_CLASSIFICATION_RULE _IOW(BCM_IOCTL, 0x813, char) - +#define IOCTL_CM_REQUEST _IOW(BCM_IOCTL, 0x80F, int) +#define IOCTL_INIT_PARAM_REQ _IOW(BCM_IOCTL, 0x810, int) +#define IOCTL_MAC_ADDR_REQ _IOW(BCM_IOCTL, 0x811, int) +#define IOCTL_MAC_ADDR_RESP _IOWR(BCM_IOCTL, 0x812, int) +#define IOCTL_CLASSIFICATION_RULE _IOW(BCM_IOCTL, 0x813, char) #define IOCTL_CLOSE_NOTIFICATION _IO(BCM_IOCTL, 0x814) - -#define IOCTL_LINK_UP _IO(BCM_IOCTL, 0x815) - -#define IOCTL_LINK_DOWN _IO(BCM_IOCTL, 0x816, IOCTL_BUFFER) - -#define IOCTL_CHIP_RESET _IO(BCM_IOCTL, 0x816) - +#define IOCTL_LINK_UP _IO(BCM_IOCTL, 0x815) +#define IOCTL_LINK_DOWN _IO(BCM_IOCTL, 0x816, struct bcm_ioctl_buffer) +#define IOCTL_CHIP_RESET _IO(BCM_IOCTL, 0x816) #define IOCTL_CINR_LEVEL_REQ _IOW(BCM_IOCTL, 0x817, char) - -#define IOCTL_WTM_CONTROL_REQ _IOW(BCM_IOCTL, 0x817,char) - +#define IOCTL_WTM_CONTROL_REQ _IOW(BCM_IOCTL, 0x817, char) #define IOCTL_BE_BUCKET_SIZE _IOW(BCM_IOCTL, 0x818, unsigned long) - #define IOCTL_RTPS_BUCKET_SIZE _IOW(BCM_IOCTL, 0x819, unsigned long) - -#define IOCTL_QOS_THRESHOLD _IOW(BCM_IOCTL, 0x820, unsigned long) - -#define IOCTL_DUMP_PACKET_INFO _IO(BCM_IOCTL, 0x821) - -#define IOCTL_GET_PACK_INFO _IOR(BCM_IOCTL, 0x823, int) - +#define IOCTL_QOS_THRESHOLD _IOW(BCM_IOCTL, 0x820, unsigned long) +#define IOCTL_DUMP_PACKET_INFO _IO(BCM_IOCTL, 0x821) +#define IOCTL_GET_PACK_INFO _IOR(BCM_IOCTL, 0x823, int) #define IOCTL_BCM_GET_DRIVER_VERSION _IOR(BCM_IOCTL, 0x829, int) - -#define IOCTL_BCM_GET_CURRENT_STATUS _IOW(BCM_IOCTL, 0x828, int) - -#define IOCTL_BCM_GPIO_SET_REQUEST _IOW(BCM_IOCTL, 0x82A, int) - -#define IOCTL_BCM_GPIO_STATUS_REQUEST _IOW(BCM_IOCTL, 0x82b, int) - -#define IOCTL_BCM_GET_DSX_INDICATION _IOR(BCM_IOCTL, 0x854, int) - -#define IOCTL_BCM_BUFFER_DOWNLOAD_START _IOW(BCM_IOCTL, 0x855, int) - -#define IOCTL_BCM_BUFFER_DOWNLOAD _IOW(BCM_IOCTL, 0x856, int) - -#define IOCTL_BCM_BUFFER_DOWNLOAD_STOP _IOW(BCM_IOCTL, 0x857, int) - -#define IOCTL_BCM_REGISTER_WRITE_PRIVATE _IOW(BCM_IOCTL, 0x826, char) - +#define IOCTL_BCM_GET_CURRENT_STATUS _IOW(BCM_IOCTL, 0x828, int) +#define IOCTL_BCM_GPIO_SET_REQUEST _IOW(BCM_IOCTL, 0x82A, int) +#define IOCTL_BCM_GPIO_STATUS_REQUEST _IOW(BCM_IOCTL, 0x82b, int) +#define IOCTL_BCM_GET_DSX_INDICATION _IOR(BCM_IOCTL, 0x854, int) +#define IOCTL_BCM_BUFFER_DOWNLOAD_START _IOW(BCM_IOCTL, 0x855, int) +#define IOCTL_BCM_BUFFER_DOWNLOAD _IOW(BCM_IOCTL, 0x856, int) +#define IOCTL_BCM_BUFFER_DOWNLOAD_STOP _IOW(BCM_IOCTL, 0x857, int) +#define IOCTL_BCM_REGISTER_WRITE_PRIVATE _IOW(BCM_IOCTL, 0x826, char) #define IOCTL_BCM_REGISTER_READ_PRIVATE _IOW(BCM_IOCTL, 0x827, char) - -#define IOCTL_BCM_SET_DEBUG _IOW(BCM_IOCTL, 0x824, IOCTL_BUFFER) - -#define IOCTL_BCM_EEPROM_REGISTER_WRITE _IOW(BCM_IOCTL, 0x858, int) - -#define IOCTL_BCM_EEPROM_REGISTER_READ _IOR(BCM_IOCTL, 0x859, int) - +#define IOCTL_BCM_SET_DEBUG _IOW(BCM_IOCTL, 0x824, struct bcm_ioctl_buffer) +#define IOCTL_BCM_EEPROM_REGISTER_WRITE _IOW(BCM_IOCTL, 0x858, int) +#define IOCTL_BCM_EEPROM_REGISTER_READ _IOR(BCM_IOCTL, 0x859, int) #define IOCTL_BCM_WAKE_UP_DEVICE_FROM_IDLE _IOR(BCM_IOCTL, 0x860, int) - -#define IOCTL_BCM_SET_MAC_TRACING _IOW(BCM_IOCTL, 0x82c, int) - -#define IOCTL_BCM_GET_HOST_MIBS _IOW(BCM_IOCTL, 0x853, int) - -#define IOCTL_BCM_NVM_READ _IOR(BCM_IOCTL, 0x861, int) - -#define IOCTL_BCM_NVM_WRITE _IOW(BCM_IOCTL, 0x862, int) - -#define IOCTL_BCM_GET_NVM_SIZE _IOR(BCM_IOCTL, 0x863, int) - -#define IOCTL_BCM_CAL_INIT _IOR(BCM_IOCTL, 0x864, int) - -#define IOCTL_BCM_BULK_WRM _IOW(BCM_IOCTL, 0x90B, int) - -#define IOCTL_BCM_FLASH2X_SECTION_READ _IOR(BCM_IOCTL, 0x865, int) - +#define IOCTL_BCM_SET_MAC_TRACING _IOW(BCM_IOCTL, 0x82c, int) +#define IOCTL_BCM_GET_HOST_MIBS _IOW(BCM_IOCTL, 0x853, int) +#define IOCTL_BCM_NVM_READ _IOR(BCM_IOCTL, 0x861, int) +#define IOCTL_BCM_NVM_WRITE _IOW(BCM_IOCTL, 0x862, int) +#define IOCTL_BCM_GET_NVM_SIZE _IOR(BCM_IOCTL, 0x863, int) +#define IOCTL_BCM_CAL_INIT _IOR(BCM_IOCTL, 0x864, int) +#define IOCTL_BCM_BULK_WRM _IOW(BCM_IOCTL, 0x90B, int) +#define IOCTL_BCM_FLASH2X_SECTION_READ _IOR(BCM_IOCTL, 0x865, int) #define IOCTL_BCM_FLASH2X_SECTION_WRITE _IOW(BCM_IOCTL, 0x866, int) +#define IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP _IOR(BCM_IOCTL, 0x867, int) +#define IOCTL_BCM_SET_ACTIVE_SECTION _IOW(BCM_IOCTL, 0x868, int) +#define IOCTL_BCM_IDENTIFY_ACTIVE_SECTION _IO(BCM_IOCTL, 0x869) +#define IOCTL_BCM_COPY_SECTION _IOW(BCM_IOCTL, 0x870, int) +#define IOCTL_BCM_GET_FLASH_CS_INFO _IOR(BCM_IOCTL, 0x871, int) +#define IOCTL_BCM_SELECT_DSD _IOW(BCM_IOCTL, 0x872, int) +#define IOCTL_BCM_NVM_RAW_READ _IOR(BCM_IOCTL, 0x875, int) +#define IOCTL_BCM_CNTRLMSG_MASK _IOW(BCM_IOCTL, 0x874, int) +#define IOCTL_BCM_GET_DEVICE_DRIVER_INFO _IOR(BCM_IOCTL, 0x877, int) +#define IOCTL_BCM_TIME_SINCE_NET_ENTRY _IOR(BCM_IOCTL, 0x876, int) +#define BCM_LED_THREAD_STATE_CHANGE_REQ _IOW(BCM_IOCTL, 0x878, int) +#define IOCTL_BCM_GPIO_MULTI_REQUEST _IOW(BCM_IOCTL, 0x82D, struct bcm_ioctl_buffer) +#define IOCTL_BCM_GPIO_MODE_REQUEST _IOW(BCM_IOCTL, 0x82E, struct bcm_ioctl_buffer) + +enum bcm_interface_type { + BCM_MII, + BCM_CARDBUS, + BCM_USB, + BCM_SDIO, + BCM_PCMCIA +}; -#define IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP _IOR(BCM_IOCTL,0x867, int) - -#define IOCTL_BCM_SET_ACTIVE_SECTION _IOW(BCM_IOCTL,0x868, int) - -#define IOCTL_BCM_IDENTIFY_ACTIVE_SECTION _IO(BCM_IOCTL,0x869) - -#define IOCTL_BCM_COPY_SECTION _IOW(BCM_IOCTL, 0x870,int) - -#define IOCTL_BCM_GET_FLASH_CS_INFO _IOR(BCM_IOCTL, 0x871, int) - -#define IOCTL_BCM_SELECT_DSD _IOW(BCM_IOCTL, 0x872, int) - -#define IOCTL_BCM_NVM_RAW_READ _IOR(BCM_IOCTL, 0x875, int) - -#define IOCTL_BCM_CNTRLMSG_MASK _IOW(BCM_IOCTL, 0x874, int) - -#define IOCTL_BCM_GET_DEVICE_DRIVER_INFO _IOR(BCM_IOCTL, 0x877, int) - -#define IOCTL_BCM_TIME_SINCE_NET_ENTRY _IOR(BCM_IOCTL, 0x876, int) - -#define BCM_LED_THREAD_STATE_CHANGE_REQ _IOW(BCM_IOCTL, 0x878, int) - -#define IOCTL_BCM_GPIO_MULTI_REQUEST _IOW(BCM_IOCTL, 0x82D, IOCTL_BUFFER) -#define IOCTL_BCM_GPIO_MODE_REQUEST _IOW(BCM_IOCTL, 0x82E, IOCTL_BUFFER) - - - -typedef enum _BCM_INTERFACE_TYPE -{ - BCM_MII, - BCM_CARDBUS, - BCM_USB, - BCM_SDIO, - BCM_PCMCIA -}BCM_INTERFACE_TYPE; - -typedef struct _DEVICE_DRIVER_INFO -{ - NVM_TYPE u32NVMType; - UINT MaxRDMBufferSize; - BCM_INTERFACE_TYPE u32InterfaceType; - UINT u32DSDStartOffset; - UINT u32RxAlignmentCorrection; - UINT u32Reserved[10]; -} DEVICE_DRIVER_INFO; - -typedef struct _NVM_READWRITE -{ +struct bcm_driver_info { + NVM_TYPE u32NVMType; + unsigned int MaxRDMBufferSize; + enum bcm_interface_type u32InterfaceType; + unsigned int u32DSDStartOffset; + unsigned int u32RxAlignmentCorrection; + unsigned int u32Reserved[10]; +}; +struct bcm_nvm_readwrite { void __user *pBuffer; -// Data to be written from|read to. Memory should be allocated by the caller. - uint32_t uiOffset; -// offset at which data should be written to or read from. - - uint32_t uiNumBytes; -// No. of bytes to be written or read. - - bool bVerify; -// Applicable only for write. If set verification of written data will be done. - -} NVM_READWRITE,*PNVM_READWRITE; -typedef struct bulkwrmbuffer -{ - ULONG Register; - ULONG SwapEndian; - ULONG Values[1]; - -}BULKWRM_BUFFER,*PBULKWRM_BUFFER; - - -/***********Structure used for FlashMap2.x *******************************/ + uint32_t uiNumBytes; + bool bVerify; +}; -/* -* These are Sction present inside the Flash. -* There is sectional RD/WR for flash Map 2.x. -* hence these section will be used in read/write API. -*/ +struct bcm_bulk_wrm_buffer { + unsigned long Register; + unsigned long SwapEndian; + unsigned long Values[1]; +}; -typedef enum _FLASH2X_SECTION_VAL -{ - NO_SECTION_VAL = 0, //no section is chosen when absolute offset is given for RD/WR +enum bcm_flash2x_section_val { + NO_SECTION_VAL = 0, /* no section is chosen when absolute offset is given for RD/WR */ ISO_IMAGE1, ISO_IMAGE2, DSD0, @@ -257,104 +146,81 @@ typedef enum _FLASH2X_SECTION_VAL ISO_IMAGE2_PART2, ISO_IMAGE2_PART3, TOTAL_SECTIONS -}FLASH2X_SECTION_VAL; +}; /* -* Structure used for READ/WRITE Flash Map2.x -*/ -typedef struct _FLASH2X_READWRITE -{ - - FLASH2X_SECTION_VAL Section; //which section has to be read/written - B_UINT32 offset; //Offset within Section. - B_UINT32 numOfBytes; //NOB from the offset - B_UINT32 bVerify; - void __user *pDataBuff; //Buffer for reading/writing + * Structure used for READ/WRITE Flash Map2.x + */ +struct bcm_flash2x_readwrite { + enum bcm_flash2x_section_val Section; /* which section has to be read/written */ + u32 offset; /* Offset within Section. */ + u32 numOfBytes; /* NOB from the offset */ + u32 bVerify; + void __user *pDataBuff; /* Buffer for reading/writing */ +}; -}FLASH2X_READWRITE, *PFLASH2X_READWRITE; /* -* This structure is used for coping one section to other. -* there are two ways to copy one section to other. -* it NOB =0, complete section will be copied on to other. -* if NOB !=0, only NOB will be copied from the given offset. -*/ - -typedef struct _FLASH2X_COPY_SECTION -{ - //Src Section from which Data has to be copied to DstSection - FLASH2X_SECTION_VAL SrcSection; - - //Destination Section from where Data has to be coppied. - FLASH2X_SECTION_VAL DstSection; - - //Offset within Section. if NOB =0 it will be ignored and data will be coped from offset 0. - B_UINT32 offset; - - //NOB from the offset. if NOB = 0 complete src section will be copied to Destination section. - B_UINT32 numOfBytes; -} FLASH2X_COPY_SECTION, *PFLASH2X_COPY_SECTION; - - -typedef enum _SECTION_TYPE -{ - ISO = 0, - VSA = 1, - DSD = 2 -} SECTION_TYPE, *PSECTION_TYPE; + * This structure is used for coping one section to other. + * there are two ways to copy one section to other. + * it NOB =0, complete section will be copied on to other. + * if NOB !=0, only NOB will be copied from the given offset. + */ + +struct bcm_flash2x_copy_section { + enum bcm_flash2x_section_val SrcSection; + enum bcm_flash2x_section_val DstSection; + u32 offset; + u32 numOfBytes; +}; /* -* This section provide the complete bitmap of the Flash. -* using this map lib/APP will isssue read/write command. - Fields are defined as : - Bit [0] = section is present //1:present, 0: Not present -* Bit [1] = section is valid //1: valid, 0: not valid -* Bit [2] = Section is R/W //0: RW, 1: RO -* Bit [3] = Section is Active or not 1 means Active, 0->inactive -* Bit [7...3] = Reserved -*/ - -typedef struct _FLASH2X_BITMAP -{ - UCHAR ISO_IMAGE1; - UCHAR ISO_IMAGE2; - UCHAR DSD0; - UCHAR DSD1; - UCHAR DSD2; - UCHAR VSA0; - UCHAR VSA1; - UCHAR VSA2; - UCHAR SCSI; - UCHAR CONTROL_SECTION; - //Reserved for future use - UCHAR Reserved0; - UCHAR Reserved1; - UCHAR Reserved2; -}FLASH2X_BITMAP, *PFLASH2X_BITMAP; + * This section provide the complete bitmap of the Flash. + * using this map lib/APP will isssue read/write command. + * Fields are defined as : + * Bit [0] = section is present //1:present, 0: Not present + * Bit [1] = section is valid //1: valid, 0: not valid + * Bit [2] = Section is R/W //0: RW, 1: RO + * Bit [3] = Section is Active or not 1 means Active, 0->inactive + * Bit [7...3] = Reserved + */ + +struct bcm_flash2x_bitmap { + unsigned char ISO_IMAGE1; + unsigned char ISO_IMAGE2; + unsigned char DSD0; + unsigned char DSD1; + unsigned char DSD2; + unsigned char VSA0; + unsigned char VSA1; + unsigned char VSA2; + unsigned char SCSI; + unsigned char CONTROL_SECTION; + /* Reserved for future use */ + unsigned char Reserved0; + unsigned char Reserved1; + unsigned char Reserved2; +}; -//for net entry time check -typedef struct _ST_TIME_ELAPSED_ -{ - ULONG64 ul64TimeElapsedSinceNetEntry; - UINT32 uiReserved[4]; //By chance if required for future proofing -}ST_TIME_ELAPSED,*PST_TIME_ELAPSED; +struct bcm_time_elapsed { + unsigned long long ul64TimeElapsedSinceNetEntry; + u32 uiReserved[4]; +}; enum { - WIMAX_IDX=0, /*To access WiMAX chip GPIO's for GPIO_MULTI_INFO or GPIO_MULTI_MODE*/ - HOST_IDX, /*To access Host chip GPIO's for GPIO_MULTI_INFO or GPIO_MULTI_MODE*/ - MAX_IDX + WIMAX_IDX = 0, /* To access WiMAX chip GPIO's for GPIO_MULTI_INFO or GPIO_MULTI_MODE */ + HOST_IDX, /* To access Host chip GPIO's for GPIO_MULTI_INFO or GPIO_MULTI_MODE */ + MAX_IDX }; -typedef struct stGPIOMultiInfo -{ - UINT uiGPIOCommand; /* 1 for set and 0 for get*/ - UINT uiGPIOMask; /* set the correspondig bit to 1 to access GPIO*/ - UINT uiGPIOValue; /* 0 or 1; value to be set when command is 1.*/ -}__attribute__((packed))GPIO_MULTI_INFO , *PGPIO_MULTI_INFO; -typedef struct stGPIOMultiMode -{ - UINT uiGPIOMode; /* 1 for OUT mode, 0 for IN mode*/ - UINT uiGPIOMask; /* GPIO mask to set mode*/ -}__attribute__((packed))GPIO_MULTI_MODE, *PGPIO_MULTI_MODE; +struct bcm_gpio_multi_info { + unsigned int uiGPIOCommand; /* 1 for set and 0 for get */ + unsigned int uiGPIOMask; /* set the correspondig bit to 1 to access GPIO */ + unsigned int uiGPIOValue; /* 0 or 1; value to be set when command is 1. */ +} __packed; +struct bcm_gpio_multi_mode { + unsigned int uiGPIOMode; /* 1 for OUT mode, 0 for IN mode */ + unsigned int uiGPIOMask; /* GPIO mask to set mode */ +} __packed; #endif diff --git a/drivers/staging/bcm/LeakyBucket.c b/drivers/staging/bcm/LeakyBucket.c index 6e8a3279698b..877cf0b2bee1 100644 --- a/drivers/staging/bcm/LeakyBucket.c +++ b/drivers/staging/bcm/LeakyBucket.c @@ -21,10 +21,12 @@ static VOID UpdateTokenCount(register struct bcm_mini_adapter *Adapter) INT i = 0; struct timeval tv; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "=====>\n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, + "=====>\n"); if(NULL == Adapter) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "Adapter found NULL!\n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, + DBG_LVL_ALL, "Adapter found NULL!\n"); return; } diff --git a/drivers/staging/bcm/Misc.c b/drivers/staging/bcm/Misc.c index f13a9582a82f..c92078e7fe86 100644 --- a/drivers/staging/bcm/Misc.c +++ b/drivers/staging/bcm/Misc.c @@ -1,14 +1,14 @@ #include "headers.h" static int BcmFileDownload(struct bcm_mini_adapter *Adapter, const char *path, unsigned int loc); -static VOID doPowerAutoCorrection(struct bcm_mini_adapter *psAdapter); +static void doPowerAutoCorrection(struct bcm_mini_adapter *psAdapter); static void HandleShutDownModeRequest(struct bcm_mini_adapter *Adapter, PUCHAR pucBuffer); static int bcm_parse_target_params(struct bcm_mini_adapter *Adapter); static void beceem_protocol_reset(struct bcm_mini_adapter *Adapter); -static VOID default_wimax_protocol_initialize(struct bcm_mini_adapter *Adapter) +static void default_wimax_protocol_initialize(struct bcm_mini_adapter *Adapter) { - UINT uiLoopIndex; + unsigned int uiLoopIndex; for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES-1; uiLoopIndex++) { Adapter->PackInfo[uiLoopIndex].uiThreshold = TX_PACKET_THRESHOLD; @@ -24,10 +24,10 @@ static VOID default_wimax_protocol_initialize(struct bcm_mini_adapter *Adapter) return; } -INT InitAdapter(struct bcm_mini_adapter *psAdapter) +int InitAdapter(struct bcm_mini_adapter *psAdapter) { int i = 0; - INT Status = STATUS_SUCCESS; + int Status = STATUS_SUCCESS; BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Initialising Adapter = %p", psAdapter); if (psAdapter == NULL) { @@ -93,7 +93,7 @@ INT InitAdapter(struct bcm_mini_adapter *psAdapter) return STATUS_SUCCESS; } -VOID AdapterFree(struct bcm_mini_adapter *Adapter) +void AdapterFree(struct bcm_mini_adapter *Adapter) { int count; beceem_protocol_reset(Adapter); @@ -216,12 +216,12 @@ exit_download: * Logical Adapter * Control Packet Buffer */ -INT CopyBufferToControlPacket(struct bcm_mini_adapter *Adapter, PVOID ioBuffer) +int CopyBufferToControlPacket(struct bcm_mini_adapter *Adapter, void *ioBuffer) { struct bcm_leader *pLeader = NULL; - INT Status = 0; - unsigned char *ctrl_buff = NULL; - UINT pktlen = 0; + int Status = 0; + unsigned char *ctrl_buff; + unsigned int pktlen = 0; struct bcm_link_request *pLinkReq = NULL; PUCHAR pucAddIndication = NULL; @@ -253,7 +253,7 @@ INT CopyBufferToControlPacket(struct bcm_mini_adapter *Adapter, PVOID ioBuffer) return STATUS_FAILURE; } - if (TRUE == Adapter->bShutStatus) { + if (Adapter->bShutStatus == TRUE) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "SYNC UP IN SHUTDOWN..Device WakeUp\n"); if (Adapter->bTriedToWakeUpFromlowPowerMode == FALSE) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Waking up for the First Time..\n"); @@ -275,7 +275,7 @@ INT CopyBufferToControlPacket(struct bcm_mini_adapter *Adapter, PVOID ioBuffer) } } - if (TRUE == Adapter->IdleMode) { + if (Adapter->IdleMode == TRUE) { /* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is in Idle mode ... hence\n"); */ if (pLeader->Status == LINK_UP_CONTROL_REQ || pLeader->Status == 0x80 || pLeader->Status == CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ) { @@ -325,64 +325,66 @@ INT CopyBufferToControlPacket(struct bcm_mini_adapter *Adapter, PVOID ioBuffer) pktlen = pLeader->PLength; ctrl_buff = (char *)Adapter->txctlpacket[atomic_read(&Adapter->index_wr_txcntrlpkt)%MAX_CNTRL_PKTS]; + if (!ctrl_buff) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "mem allocation Failed"); + return -ENOMEM; + } + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Control packet to be taken =%d and address is =%pincoming address is =%p and packet len=%x", atomic_read(&Adapter->index_wr_txcntrlpkt), ctrl_buff, ioBuffer, pktlen); - if (ctrl_buff) { - if (pLeader) { - if ((pLeader->Status == 0x80) || - (pLeader->Status == CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ)) { - /* - * Restructure the DSX message to handle Multiple classifier Support - * Write the Service Flow param Structures directly to the target - * and embed the pointers in the DSX messages sent to target. - */ - /* Lets store the current length of the control packet we are transmitting */ - pucAddIndication = (PUCHAR)ioBuffer + LEADER_SIZE; - pktlen = pLeader->PLength; - Status = StoreCmControlResponseMessage(Adapter, pucAddIndication, &pktlen); - if (Status != 1) { - ClearTargetDSXBuffer(Adapter, ((stLocalSFAddIndicationAlt *)pucAddIndication)->u16TID, FALSE); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, " Error Restoring The DSX Control Packet. Dsx Buffers on Target may not be Setup Properly "); - return STATUS_FAILURE; - } - /* - * update the leader to use the new length - * The length of the control packet is length of message being sent + Leader length - */ - pLeader->PLength = pktlen; + + if (pLeader) { + if ((pLeader->Status == 0x80) || + (pLeader->Status == CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ)) { + /* + * Restructure the DSX message to handle Multiple classifier Support + * Write the Service Flow param Structures directly to the target + * and embed the pointers in the DSX messages sent to target. + */ + /* Lets store the current length of the control packet we are transmitting */ + pucAddIndication = (PUCHAR)ioBuffer + LEADER_SIZE; + pktlen = pLeader->PLength; + Status = StoreCmControlResponseMessage(Adapter, pucAddIndication, &pktlen); + if (Status != 1) { + ClearTargetDSXBuffer(Adapter, ((struct bcm_add_indication_alt *)pucAddIndication)->u16TID, FALSE); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, " Error Restoring The DSX Control Packet. Dsx Buffers on Target may not be Setup Properly "); + return STATUS_FAILURE; } + /* + * update the leader to use the new length + * The length of the control packet is length of message being sent + Leader length + */ + pLeader->PLength = pktlen; } - - if (pktlen + LEADER_SIZE > MAX_CNTL_PKT_SIZE) - return -EINVAL; - - memset(ctrl_buff, 0, pktlen+LEADER_SIZE); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Copying the Control Packet Buffer with length=%d\n", pLeader->PLength); - *(struct bcm_leader *)ctrl_buff = *pLeader; - memcpy(ctrl_buff + LEADER_SIZE, ((PUCHAR)ioBuffer + LEADER_SIZE), pLeader->PLength); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Enqueuing the Control Packet"); - - /* Update the statistics counters */ - spin_lock_bh(&Adapter->PackInfo[HiPriority].SFQueueLock); - Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost += pLeader->PLength; - Adapter->PackInfo[HiPriority].uiCurrentPacketsOnHost++; - atomic_inc(&Adapter->TotalPacketCount); - spin_unlock_bh(&Adapter->PackInfo[HiPriority].SFQueueLock); - Adapter->PackInfo[HiPriority].bValid = TRUE; - - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "CurrBytesOnHost: %x bValid: %x", - Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost, - Adapter->PackInfo[HiPriority].bValid); - Status = STATUS_SUCCESS; - /*Queue the packet for transmission */ - atomic_inc(&Adapter->index_wr_txcntrlpkt); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Calling transmit_packets"); - atomic_set(&Adapter->TxPktAvail, 1); - wake_up(&Adapter->tx_packet_wait_queue); - } else { - Status = -ENOMEM; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "mem allocation Failed"); } + + if (pktlen + LEADER_SIZE > MAX_CNTL_PKT_SIZE) + return -EINVAL; + + memset(ctrl_buff, 0, pktlen+LEADER_SIZE); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Copying the Control Packet Buffer with length=%d\n", pLeader->PLength); + *(struct bcm_leader *)ctrl_buff = *pLeader; + memcpy(ctrl_buff + LEADER_SIZE, ((PUCHAR)ioBuffer + LEADER_SIZE), pLeader->PLength); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Enqueuing the Control Packet"); + + /* Update the statistics counters */ + spin_lock_bh(&Adapter->PackInfo[HiPriority].SFQueueLock); + Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost += pLeader->PLength; + Adapter->PackInfo[HiPriority].uiCurrentPacketsOnHost++; + atomic_inc(&Adapter->TotalPacketCount); + spin_unlock_bh(&Adapter->PackInfo[HiPriority].SFQueueLock); + Adapter->PackInfo[HiPriority].bValid = TRUE; + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "CurrBytesOnHost: %x bValid: %x", + Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost, + Adapter->PackInfo[HiPriority].bValid); + Status = STATUS_SUCCESS; + /*Queue the packet for transmission */ + atomic_inc(&Adapter->index_wr_txcntrlpkt); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Calling transmit_packets"); + atomic_set(&Adapter->TxPktAvail, 1); + wake_up(&Adapter->tx_packet_wait_queue); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL |