Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov: - a new driver for Rohm BU21029 touch controller - new bitmap APIs: bitmap_alloc, bitmap_zalloc and bitmap_free - updates to Atmel, eeti. pxrc and iforce drivers - assorted driver cleanups and fixes. * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (57 commits) MAINTAINERS: Add PhoenixRC Flight Controller Adapter Input: do not use WARN() in input_alloc_absinfo() Input: mark expected switch fall-throughs Input: raydium_i2c_ts - use true and false for boolean values Input: evdev - switch to bitmap API Input: gpio-keys - switch to bitmap_zalloc() Input: elan_i2c_smbus - cast sizeof to int for comparison bitmap: Add bitmap_alloc(), bitmap_zalloc() and bitmap_free() md: Avoid namespace collision with bitmap API dm: Avoid namespace collision with bitmap API Input: pm8941-pwrkey - add resin entry Input: pm8941-pwrkey - abstract register offsets and event code Input: iforce - reorganize joystick configuration lists Input: atmel_mxt_ts - move completion to after config crc is updated Input: atmel_mxt_ts - don't report zero pressure from T9 Input: atmel_mxt_ts - zero terminate config firmware file Input: atmel_mxt_ts - refactor config update code to add context struct Input: atmel_mxt_ts - config CRC may start at T71 Input: atmel_mxt_ts - remove unnecessary debug on ENOMEM Input: atmel_mxt_ts - remove duplicate setup of ABS_MT_PRESSURE ...
This commit is contained in:
commit
08b5fa8199
|
@ -0,0 +1,8 @@
|
|||
General Keys Properties:
|
||||
|
||||
Optional properties for Keys:
|
||||
- power-off-time-sec: Duration in seconds which the key should be kept
|
||||
pressed for device to power off automatically. Device with key pressed
|
||||
shutdown feature can specify this property.
|
||||
- linux,keycodes: Specifies the numeric keycode values to be used for
|
||||
reporting key presses.
|
|
@ -7,6 +7,7 @@ PROPERTIES
|
|||
Value type: <string>
|
||||
Definition: must be one of:
|
||||
"qcom,pm8941-pwrkey"
|
||||
"qcom,pm8941-resin"
|
||||
|
||||
- reg:
|
||||
Usage: required
|
||||
|
@ -32,6 +33,14 @@ PROPERTIES
|
|||
Definition: presence of this property indicates that the KPDPWR_N pin
|
||||
should be configured for pull up.
|
||||
|
||||
- linux,code:
|
||||
Usage: optional
|
||||
Value type: <u32>
|
||||
Definition: The input key-code associated with the power key.
|
||||
Use the linux event codes defined in
|
||||
include/dt-bindings/input/linux-event-codes.h
|
||||
When property is omitted KEY_POWER is assumed.
|
||||
|
||||
EXAMPLE
|
||||
|
||||
pwrkey@800 {
|
||||
|
@ -40,4 +49,5 @@ EXAMPLE
|
|||
interrupts = <0x0 0x8 0 IRQ_TYPE_EDGE_BOTH>;
|
||||
debounce = <15625>;
|
||||
bias-pull-up;
|
||||
linux,code = <KEY_POWER>;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
* Rohm BU21029 Touch Screen Controller
|
||||
|
||||
Required properties:
|
||||
- compatible : must be "rohm,bu21029"
|
||||
- reg : i2c device address of the chip (0x40 or 0x41)
|
||||
- interrupt-parent : the phandle for the gpio controller
|
||||
- interrupts : (gpio) interrupt to which the chip is connected
|
||||
- rohm,x-plate-ohms : x-plate resistance in Ohm
|
||||
|
||||
Optional properties:
|
||||
- reset-gpios : gpio pin to reset the chip (active low)
|
||||
- touchscreen-size-x : horizontal resolution of touchscreen (in pixels)
|
||||
- touchscreen-size-y : vertical resolution of touchscreen (in pixels)
|
||||
- touchscreen-max-pressure: maximum pressure value
|
||||
- vdd-supply : power supply for the controller
|
||||
|
||||
Example:
|
||||
|
||||
&i2c1 {
|
||||
/* ... */
|
||||
|
||||
bu21029: bu21029@40 {
|
||||
compatible = "rohm,bu21029";
|
||||
reg = <0x40>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
|
||||
reset-gpios = <&gpio6 16 GPIO_ACTIVE_LOW>;
|
||||
rohm,x-plate-ohms = <600>;
|
||||
touchscreen-size-x = <800>;
|
||||
touchscreen-size-y = <480>;
|
||||
touchscreen-max-pressure = <4095>;
|
||||
};
|
||||
|
||||
/* ... */
|
||||
};
|
|
@ -0,0 +1,30 @@
|
|||
Bindings for EETI touchscreen controller
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "eeti,exc3000-i2c"
|
||||
- reg: I2C address of the chip. Should be set to <0xa>
|
||||
- interrupts: interrupt to which the chip is connected
|
||||
|
||||
Optional properties:
|
||||
- attn-gpios: A handle to a GPIO to check whether interrupt is still
|
||||
latched. This is necessary for platforms that lack
|
||||
support for level-triggered IRQs.
|
||||
|
||||
The following optional properties described in touchscreen.txt are
|
||||
also supported:
|
||||
|
||||
- touchscreen-inverted-x
|
||||
- touchscreen-inverted-y
|
||||
- touchscreen-swapped-x-y
|
||||
|
||||
Example:
|
||||
|
||||
i2c-master {
|
||||
touchscreen@a {
|
||||
compatible = "eeti,exc3000-i2c";
|
||||
reg = <0xa>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <123 IRQ_TYPE_EDGE_RISING>;
|
||||
attn-gpios = <&gpio 123 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
|
@ -11340,6 +11340,13 @@ S: Maintained
|
|||
F: include/linux/personality.h
|
||||
F: include/uapi/linux/personality.h
|
||||
|
||||
PHOENIX RC FLIGHT CONTROLLER ADAPTER
|
||||
M: Marcus Folkesson <marcus.folkesson@gmail.com>
|
||||
L: linux-input@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/input/devices/pxrc.rst
|
||||
F: drivers/input/joystick/pxrc.c
|
||||
|
||||
PHONET PROTOCOL
|
||||
M: Remi Denis-Courmont <courmisch@gmail.com>
|
||||
S: Supported
|
||||
|
|
|
@ -20,10 +20,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
|
|
@ -481,7 +481,7 @@ static int evdev_release(struct inode *inode, struct file *file)
|
|||
evdev_detach_client(evdev, client);
|
||||
|
||||
for (i = 0; i < EV_CNT; ++i)
|
||||
kfree(client->evmasks[i]);
|
||||
bitmap_free(client->evmasks[i]);
|
||||
|
||||
kvfree(client);
|
||||
|
||||
|
@ -925,17 +925,15 @@ static int evdev_handle_get_val(struct evdev_client *client,
|
|||
{
|
||||
int ret;
|
||||
unsigned long *mem;
|
||||
size_t len;
|
||||
|
||||
len = BITS_TO_LONGS(maxbit) * sizeof(unsigned long);
|
||||
mem = kmalloc(len, GFP_KERNEL);
|
||||
mem = bitmap_alloc(maxbit, GFP_KERNEL);
|
||||
if (!mem)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_irq(&dev->event_lock);
|
||||
spin_lock(&client->buffer_lock);
|
||||
|
||||
memcpy(mem, bits, len);
|
||||
bitmap_copy(mem, bits, maxbit);
|
||||
|
||||
spin_unlock(&dev->event_lock);
|
||||
|
||||
|
@ -947,7 +945,7 @@ static int evdev_handle_get_val(struct evdev_client *client,
|
|||
if (ret < 0)
|
||||
evdev_queue_syn_dropped(client);
|
||||
|
||||
kfree(mem);
|
||||
bitmap_free(mem);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1003,13 +1001,13 @@ static int evdev_set_mask(struct evdev_client *client,
|
|||
if (!cnt)
|
||||
return 0;
|
||||
|
||||
mask = kcalloc(sizeof(unsigned long), BITS_TO_LONGS(cnt), GFP_KERNEL);
|
||||
mask = bitmap_zalloc(cnt, GFP_KERNEL);
|
||||
if (!mask)
|
||||
return -ENOMEM;
|
||||
|
||||
error = bits_from_user(mask, cnt - 1, codes_size, codes, compat);
|
||||
if (error < 0) {
|
||||
kfree(mask);
|
||||
bitmap_free(mask);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -1018,7 +1016,7 @@ static int evdev_set_mask(struct evdev_client *client,
|
|||
client->evmasks[type] = mask;
|
||||
spin_unlock_irqrestore(&client->buffer_lock, flags);
|
||||
|
||||
kfree(oldmask);
|
||||
bitmap_free(oldmask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -20,10 +20,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <asm/io.h>
|
||||
|
|
|
@ -20,10 +20,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <asm/io.h>
|
||||
|
|
|
@ -21,10 +21,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <asm/io.h>
|
||||
|
|
|
@ -480,11 +480,19 @@ EXPORT_SYMBOL(input_inject_event);
|
|||
*/
|
||||
void input_alloc_absinfo(struct input_dev *dev)
|
||||
{
|
||||
if (!dev->absinfo)
|
||||
dev->absinfo = kcalloc(ABS_CNT, sizeof(*dev->absinfo),
|
||||
GFP_KERNEL);
|
||||
if (dev->absinfo)
|
||||
return;
|
||||
|
||||
WARN(!dev->absinfo, "%s(): kcalloc() failed?\n", __func__);
|
||||
dev->absinfo = kcalloc(ABS_CNT, sizeof(*dev->absinfo), GFP_KERNEL);
|
||||
if (!dev->absinfo) {
|
||||
dev_err(dev->dev.parent ?: &dev->dev,
|
||||
"%s: unable to allocate memory\n", __func__);
|
||||
/*
|
||||
* We will handle this allocation failure in
|
||||
* input_register_device() when we refuse to register input
|
||||
* device with ABS bits but without absinfo.
|
||||
*/
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(input_alloc_absinfo);
|
||||
|
||||
|
|
|
@ -20,10 +20,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
|
|
@ -20,10 +20,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
|
|
|
@ -20,10 +20,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
|
|
|
@ -20,10 +20,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
|
|
|
@ -20,10 +20,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
|
|
@ -23,10 +23,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
@ -263,6 +259,7 @@ static unsigned char db9_saturn_read_packet(struct parport *port, unsigned char
|
|||
db9_saturn_write_sub(port, type, 3, powered, 0);
|
||||
return data[0] = 0xe3;
|
||||
}
|
||||
/* else: fall through */
|
||||
default:
|
||||
return data[0];
|
||||
}
|
||||
|
@ -282,11 +279,14 @@ static int db9_saturn_report(unsigned char id, unsigned char data[60], struct in
|
|||
switch (data[j]) {
|
||||
case 0x16: /* multi controller (analog 4 axis) */
|
||||
input_report_abs(dev, db9_abs[5], data[j + 6]);
|
||||
/* fall through */
|
||||
case 0x15: /* mission stick (analog 3 axis) */
|
||||
input_report_abs(dev, db9_abs[3], data[j + 4]);
|
||||
input_report_abs(dev, db9_abs[4], data[j + 5]);
|
||||
/* fall through */
|
||||
case 0x13: /* racing controller (analog 1 axis) */
|
||||
input_report_abs(dev, db9_abs[2], data[j + 3]);
|
||||
/* fall through */
|
||||
case 0x34: /* saturn keyboard (udlr ZXC ASD QE Esc) */
|
||||
case 0x02: /* digital pad (digital 2 axis + buttons) */
|
||||
input_report_abs(dev, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64));
|
||||
|
@ -380,6 +380,7 @@ static void db9_timer(struct timer_list *t)
|
|||
input_report_abs(dev2, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
|
||||
input_report_abs(dev2, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
|
||||
input_report_key(dev2, BTN_TRIGGER, ~data & DB9_FIRE1);
|
||||
/* fall through */
|
||||
|
||||
case DB9_MULTI_0802:
|
||||
|
||||
|
|
|
@ -24,10 +24,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
|
|
@ -20,10 +20,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
|
|
|
@ -20,10 +20,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
|
|
@ -20,10 +20,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
|
|
@ -19,10 +19,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include "iforce.h"
|
||||
|
@ -56,7 +52,7 @@ static int make_magnitude_modifier(struct iforce* iforce,
|
|||
|
||||
iforce_send_packet(iforce, FF_CMD_MAGNITUDE, data);
|
||||
|
||||
iforce_dump_packet("magnitude: ", FF_CMD_MAGNITUDE, data);
|
||||
iforce_dump_packet(iforce, "magnitude", FF_CMD_MAGNITUDE, data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -178,7 +174,7 @@ static int make_condition_modifier(struct iforce* iforce,
|
|||
data[9] = (100 * lsat) >> 16;
|
||||
|
||||
iforce_send_packet(iforce, FF_CMD_CONDITION, data);
|
||||
iforce_dump_packet("condition", FF_CMD_CONDITION, data);
|
||||
iforce_dump_packet(iforce, "condition", FF_CMD_CONDITION, data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -19,10 +19,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include "iforce.h"
|
||||
|
@ -33,21 +29,14 @@ MODULE_LICENSE("GPL");
|
|||
|
||||
static signed short btn_joystick[] =
|
||||
{ BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE,
|
||||
BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_BASE5, BTN_A, BTN_B, BTN_C, -1 };
|
||||
BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_BASE5, BTN_A,
|
||||
BTN_B, BTN_C, BTN_DEAD, -1 };
|
||||
|
||||
static signed short btn_avb_pegasus[] =
|
||||
{ BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE,
|
||||
BTN_BASE2, BTN_BASE3, BTN_BASE4, -1 };
|
||||
static signed short btn_joystick_avb[] =
|
||||
{ BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE,
|
||||
BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_DEAD, -1 };
|
||||
|
||||
static signed short btn_wheel[] =
|
||||
{ BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE,
|
||||
BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_BASE5, BTN_A, BTN_B, BTN_C, -1 };
|
||||
|
||||
static signed short btn_avb_tw[] =
|
||||
{ BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE,
|
||||
BTN_BASE2, BTN_BASE3, BTN_BASE4, -1 };
|
||||
|
||||
static signed short btn_avb_wheel[] =
|
||||
{ BTN_GEAR_DOWN, BTN_GEAR_UP, BTN_BASE, BTN_BASE2, BTN_BASE3,
|
||||
BTN_BASE4, BTN_BASE5, BTN_BASE6, -1 };
|
||||
|
||||
|
@ -73,9 +62,9 @@ static struct iforce_device iforce_device[] = {
|
|||
{ 0x044f, 0xa01c, "Thrustmaster Motor Sport GT", btn_wheel, abs_wheel, ff_iforce },
|
||||
{ 0x046d, 0xc281, "Logitech WingMan Force", btn_joystick, abs_joystick, ff_iforce },
|
||||
{ 0x046d, 0xc291, "Logitech WingMan Formula Force", btn_wheel, abs_wheel, ff_iforce },
|
||||
{ 0x05ef, 0x020a, "AVB Top Shot Pegasus", btn_avb_pegasus, abs_avb_pegasus, ff_iforce },
|
||||
{ 0x05ef, 0x8884, "AVB Mag Turbo Force", btn_avb_wheel, abs_wheel, ff_iforce },
|
||||
{ 0x05ef, 0x8888, "AVB Top Shot Force Feedback Racing Wheel", btn_avb_tw, abs_wheel, ff_iforce }, //?
|
||||
{ 0x05ef, 0x020a, "AVB Top Shot Pegasus", btn_joystick_avb, abs_avb_pegasus, ff_iforce },
|
||||
{ 0x05ef, 0x8884, "AVB Mag Turbo Force", btn_wheel, abs_wheel, ff_iforce },
|
||||
{ 0x05ef, 0x8888, "AVB Top Shot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //?
|
||||
{ 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //?
|
||||
{ 0x061c, 0xc084, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce },
|
||||
{ 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //?
|
||||
|
@ -360,7 +349,7 @@ int iforce_init_device(struct iforce *iforce)
|
|||
|
||||
for (i = 0; c[i]; i++)
|
||||
if (!iforce_get_id_packet(iforce, c + i))
|
||||
iforce_dump_packet("info", iforce->ecmd, iforce->edata);
|
||||
iforce_dump_packet(iforce, "info", iforce->ecmd, iforce->edata);
|
||||
|
||||
/*
|
||||
* Disable spring, enable force feedback.
|
||||
|
@ -388,7 +377,6 @@ int iforce_init_device(struct iforce *iforce)
|
|||
|
||||
for (i = 0; iforce->type->btn[i] >= 0; i++)
|
||||
set_bit(iforce->type->btn[i], input_dev->keybit);
|
||||
set_bit(BTN_DEAD, input_dev->keybit);
|
||||
|
||||
for (i = 0; iforce->type->abs[i] >= 0; i++) {
|
||||
|
||||
|
|
|
@ -19,10 +19,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include "iforce.h"
|
||||
|
@ -33,14 +29,10 @@ static struct {
|
|||
} iforce_hat_to_axis[16] = {{ 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
|
||||
|
||||
|
||||
void iforce_dump_packet(char *msg, u16 cmd, unsigned char *data)
|
||||
void iforce_dump_packet(struct iforce *iforce, char *msg, u16 cmd, unsigned char *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
printk(KERN_DEBUG __FILE__ ": %s cmd = %04x, data = ", msg, cmd);
|
||||
for (i = 0; i < LO(cmd); i++)
|
||||
printk("%02x ", data[i]);
|
||||
printk("\n");
|
||||
dev_dbg(iforce->dev->dev.parent, "%s %s cmd = %04x, data = %*ph\n",
|
||||
__func__, msg, cmd, LO(cmd), data);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -255,7 +247,7 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet)
|
|||
iforce->cr.bRequest = packet[0];
|
||||
iforce->ctrl->dev = iforce->usbdev;
|
||||
|
||||
status = usb_submit_urb(iforce->ctrl, GFP_ATOMIC);
|
||||
status = usb_submit_urb(iforce->ctrl, GFP_KERNEL);
|
||||
if (status) {
|
||||
dev_err(&iforce->intf->dev,
|
||||
"usb_submit_urb failed %d\n", status);
|
||||
|
|
|
@ -19,10 +19,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include "iforce.h"
|
||||
|
|
|
@ -19,10 +19,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include "iforce.h"
|
||||
|
|
|
@ -19,10 +19,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
@ -158,7 +154,7 @@ int iforce_init_device(struct iforce *iforce);
|
|||
int iforce_control_playback(struct iforce*, u16 id, unsigned int);
|
||||
void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data);
|
||||
int iforce_send_packet(struct iforce *iforce, u16 cmd, unsigned char* data);
|
||||
void iforce_dump_packet(char *msg, u16 cmd, unsigned char *data) ;
|
||||
void iforce_dump_packet(struct iforce *iforce, char *msg, u16 cmd, unsigned char *data);
|
||||
int iforce_get_id_packet(struct iforce *iforce, char *packet);
|
||||
|
||||
/* iforce-ff.c */
|
||||
|
|
|
@ -23,10 +23,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
|
|
@ -21,10 +21,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
|
|
@ -20,10 +20,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
* Driver for Phoenix RC Flight Controller Adapter
|
||||
*
|
||||
* Copyright (C) 2018 Marcus Folkesson <marcus.folkesson@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
@ -16,31 +15,22 @@
|
|||
#include <linux/mutex.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
#define PXRC_VENDOR_ID (0x1781)
|
||||
#define PXRC_PRODUCT_ID (0x0898)
|
||||
|
||||
static const struct usb_device_id pxrc_table[] = {
|
||||
{ USB_DEVICE(PXRC_VENDOR_ID, PXRC_PRODUCT_ID) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, pxrc_table);
|
||||
#define PXRC_VENDOR_ID 0x1781
|
||||
#define PXRC_PRODUCT_ID 0x0898
|
||||
|
||||
struct pxrc {
|
||||
struct input_dev *input;
|
||||
struct usb_device *udev;
|
||||
struct usb_interface *intf;
|
||||
struct urb *urb;
|
||||
struct mutex pm_mutex;
|
||||
bool is_open;
|
||||
__u8 epaddr;
|
||||
char phys[64];
|
||||
unsigned char *data;
|
||||
size_t bsize;
|
||||
};
|
||||
|
||||
static void pxrc_usb_irq(struct urb *urb)
|
||||
{
|
||||
struct pxrc *pxrc = urb->context;
|
||||
u8 *data = urb->transfer_buffer;
|
||||
int error;
|
||||
|
||||
switch (urb->status) {
|
||||
|
@ -68,15 +58,15 @@ static void pxrc_usb_irq(struct urb *urb)
|
|||
}
|
||||
|
||||
if (urb->actual_length == 8) {
|
||||
input_report_abs(pxrc->input, ABS_X, pxrc->data[0]);
|
||||
input_report_abs(pxrc->input, ABS_Y, pxrc->data[2]);
|
||||
input_report_abs(pxrc->input, ABS_RX, pxrc->data[3]);
|
||||
input_report_abs(pxrc->input, ABS_RY, pxrc->data[4]);
|
||||
input_report_abs(pxrc->input, ABS_RUDDER, pxrc->data[5]);
|
||||
input_report_abs(pxrc->input, ABS_THROTTLE, pxrc->data[6]);
|
||||
input_report_abs(pxrc->input, ABS_MISC, pxrc->data[7]);
|
||||
input_report_abs(pxrc->input, ABS_X, data[0]);
|
||||
input_report_abs(pxrc->input, ABS_Y, data[2]);
|
||||
input_report_abs(pxrc->input, ABS_RX, data[3]);
|
||||
input_report_abs(pxrc->input, ABS_RY, data[4]);
|
||||
input_report_abs(pxrc->input, ABS_RUDDER, data[5]);
|
||||
input_report_abs(pxrc->input, ABS_THROTTLE, data[6]);
|
||||
input_report_abs(pxrc->input, ABS_MISC, data[7]);
|
||||
|
||||
input_report_key(pxrc->input, BTN_A, pxrc->data[1]);
|
||||
input_report_key(pxrc->input, BTN_A, data[1]);
|
||||
}
|
||||
|
||||
exit:
|
||||
|
@ -120,61 +110,73 @@ static void pxrc_close(struct input_dev *input)
|
|||
mutex_unlock(&pxrc->pm_mutex);
|
||||
}
|
||||
|
||||
static int pxrc_usb_init(struct pxrc *pxrc)
|
||||
static void pxrc_free_urb(void *_pxrc)
|
||||
{
|
||||
struct usb_endpoint_descriptor *epirq;
|
||||
unsigned int pipe;
|
||||
int retval;
|
||||
|
||||
/* Set up the endpoint information */
|
||||
/* This device only has an interrupt endpoint */
|
||||
retval = usb_find_common_endpoints(pxrc->intf->cur_altsetting,
|
||||
NULL, NULL, &epirq, NULL);
|
||||
if (retval) {
|
||||
dev_err(&pxrc->intf->dev,
|
||||
"Could not find endpoint\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
pxrc->bsize = usb_endpoint_maxp(epirq);
|
||||
pxrc->epaddr = epirq->bEndpointAddress;
|
||||
pxrc->data = devm_kmalloc(&pxrc->intf->dev, pxrc->bsize, GFP_KERNEL);
|
||||
if (!pxrc->data) {
|
||||
retval = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
usb_set_intfdata(pxrc->intf, pxrc);
|
||||
usb_make_path(pxrc->udev, pxrc->phys, sizeof(pxrc->phys));
|
||||
strlcat(pxrc->phys, "/input0", sizeof(pxrc->phys));
|
||||
|
||||
pxrc->urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!pxrc->urb) {
|
||||
retval = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
pipe = usb_rcvintpipe(pxrc->udev, pxrc->epaddr),
|
||||
usb_fill_int_urb(pxrc->urb, pxrc->udev, pipe, pxrc->data, pxrc->bsize,
|
||||
pxrc_usb_irq, pxrc, 1);
|
||||
|
||||
error:
|
||||
return retval;
|
||||
|
||||
struct pxrc *pxrc = _pxrc;
|
||||
|
||||
usb_free_urb(pxrc->urb);
|
||||
}
|
||||
|
||||
static int pxrc_input_init(struct pxrc *pxrc)
|
||||
static int pxrc_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
pxrc->input = devm_input_allocate_device(&pxrc->intf->dev);
|
||||
if (pxrc->input == NULL) {
|
||||
dev_err(&pxrc->intf->dev, "couldn't allocate input device\n");
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
struct pxrc *pxrc;
|
||||
struct usb_endpoint_descriptor *epirq;
|
||||
size_t xfer_size;
|
||||
void *xfer_buf;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* Locate the endpoint information. This device only has an
|
||||
* interrupt endpoint.
|
||||
*/
|
||||
error = usb_find_common_endpoints(intf->cur_altsetting,
|
||||
NULL, NULL, &epirq, NULL);
|
||||
if (error) {
|
||||
dev_err(&intf->dev, "Could not find endpoint\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
pxrc = devm_kzalloc(&intf->dev, sizeof(*pxrc), GFP_KERNEL);
|
||||
if (!pxrc)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&pxrc->pm_mutex);
|
||||
pxrc->intf = intf;
|
||||
|
||||
usb_set_intfdata(pxrc->intf, pxrc);
|
||||
|
||||
xfer_size = usb_endpoint_maxp(epirq);
|
||||
xfer_buf = devm_kmalloc(&intf->dev, xfer_size, GFP_KERNEL);
|
||||
if (!xfer_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
pxrc->urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!pxrc->urb)
|
||||
return -ENOMEM;
|
||||
|
||||
error = devm_add_action_or_reset(&intf->dev, pxrc_free_urb, pxrc);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
usb_fill_int_urb(pxrc->urb, udev,
|
||||
usb_rcvintpipe(udev, epirq->bEndpointAddress),
|
||||
xfer_buf, xfer_size, pxrc_usb_irq, pxrc, 1);
|
||||
|
||||
pxrc->input = devm_input_allocate_device(&intf->dev);
|
||||
if (!pxrc->input) {
|
||||
dev_err(&intf->dev, "couldn't allocate input device\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pxrc->input->name = "PXRC Flight Controller Adapter";
|
||||
|
||||
usb_make_path(udev, pxrc->phys, sizeof(pxrc->phys));
|
||||
strlcat(pxrc->phys, "/input0", sizeof(pxrc->phys));
|
||||
pxrc->input->phys = pxrc->phys;
|
||||
usb_to_input_id(pxrc->udev, &pxrc->input->id);
|
||||
|
||||
usb_to_input_id(udev, &pxrc->input->id);
|
||||
|
||||
pxrc->input->open = pxrc_open;
|
||||
pxrc->input->close = pxrc_close;
|
||||
|
@ -190,46 +192,16 @@ static int pxrc_input_init(struct pxrc *pxrc)
|
|||
|
||||
input_set_drvdata(pxrc->input, pxrc);
|
||||
|
||||
return input_register_device(pxrc->input);
|
||||
}
|
||||
|
||||
static int pxrc_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
struct pxrc *pxrc;
|
||||
int retval;
|
||||
|
||||
pxrc = devm_kzalloc(&intf->dev, sizeof(*pxrc), GFP_KERNEL);
|
||||
if (!pxrc)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&pxrc->pm_mutex);
|
||||
pxrc->udev = usb_get_dev(interface_to_usbdev(intf));
|
||||
pxrc->intf = intf;
|
||||
|
||||
retval = pxrc_usb_init(pxrc);
|
||||
if (retval)
|
||||
goto error;
|
||||
|
||||
retval = pxrc_input_init(pxrc);
|
||||
if (retval)
|
||||
goto err_free_urb;
|
||||
error = input_register_device(pxrc->input);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_urb:
|
||||
usb_free_urb(pxrc->urb);
|
||||
|
||||
error:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void pxrc_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct pxrc *pxrc = usb_get_intfdata(intf);
|
||||
|
||||
usb_free_urb(pxrc->urb);
|
||||
usb_set_intfdata(intf, NULL);
|
||||
/* All driver resources are devm-managed. */
|
||||
}
|
||||
|
||||
static int pxrc_suspend(struct usb_interface *intf, pm_message_t message)
|
||||
|
@ -284,6 +256,12 @@ static int pxrc_reset_resume(struct usb_interface *intf)
|
|||
return pxrc_resume(intf);
|
||||
}
|
||||
|
||||
static const struct usb_device_id pxrc_table[] = {
|
||||
{ USB_DEVICE(PXRC_VENDOR_ID, PXRC_PRODUCT_ID) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, pxrc_table);
|
||||
|
||||
static struct usb_driver pxrc_driver = {
|
||||
.name = "pxrc",
|
||||
.probe = pxrc_probe,
|
||||
|
|
|
@ -20,10 +20,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
|
|
|
@ -24,10 +24,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
|
|
@ -23,10 +23,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
|
|
@ -21,10 +21,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
|
|
@ -23,10 +23,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
|
|
|
@ -23,10 +23,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
|
|
@ -20,10 +20,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
|
|
@ -885,6 +885,7 @@ static int adp5589_probe(struct i2c_client *client,
|
|||
switch (id->driver_data) {
|
||||
case ADP5585_02:
|
||||
kpad->support_row5 = true;
|
||||
/* fall through */
|
||||
case ADP5585_01:
|
||||
kpad->is_adp5585 = true;
|
||||
kpad->var = &const_adp5585;
|
||||
|
|
|
@ -23,10 +23,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
|
|
@ -34,10 +34,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
|
|
@ -1,25 +1,15 @@
|
|||
/*
|
||||
* ChromeOS EC keyboard driver
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This driver uses the Chrome OS EC byte-level message-based protocol for
|
||||
* communicating the keyboard state (which keys are pressed) from a keyboard EC
|
||||
* to the AP over some bus (such as i2c, lpc, spi). The EC does debouncing,
|
||||
* but everything else (including deghosting) is done here. The main
|
||||
* motivation for this is to keep the EC firmware as simple as possible, since
|
||||
* it cannot be easily upgraded and EC flash/IRAM space is relatively
|
||||
* expensive.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// ChromeOS EC keyboard driver
|
||||
//
|
||||
// Copyright (C) 2012 Google, Inc.
|
||||
//
|
||||
// This driver uses the ChromeOS EC byte-level message-based protocol for
|
||||
// communicating the keyboard state (which keys are pressed) from a keyboard EC
|
||||
// to the AP over some bus (such as i2c, lpc, spi). The EC does debouncing,
|
||||
// but everything else (including deghosting) is done here. The main
|
||||
// motivation for this is to keep the EC firmware as simple as possible, since
|
||||
// it cannot be easily upgraded and EC flash/IRAM space is relatively
|
||||
// expensive.
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/bitops.h>
|
||||
|
@ -170,9 +160,6 @@ static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev,
|
|||
int col, row;
|
||||
int new_state;
|
||||
int old_state;
|
||||
int num_cols;
|
||||
|
||||
num_cols = len;
|
||||
|
||||
if (ckdev->ghost_filter && cros_ec_keyb_has_ghosting(ckdev, kb_state)) {
|
||||
/*
|
||||
|
@ -242,19 +229,17 @@ static int cros_ec_keyb_work(struct notifier_block *nb,
|
|||
u32 val;
|
||||
unsigned int ev_type;
|
||||
|
||||
/*
|
||||
* If not wake enabled, discard key state changes during
|
||||
* suspend. Switches will be re-checked in
|
||||
* cros_ec_keyb_resume() to be sure nothing is lost.
|
||||
*/
|
||||
if (queued_during_suspend && !device_may_wakeup(ckdev->dev))
|
||||
return NOTIFY_OK;
|
||||
|
||||
switch (ckdev->ec->event_data.event_type) {
|
||||
case EC_MKBP_EVENT_KEY_MATRIX:
|
||||
if (device_may_wakeup(ckdev->dev)) {
|
||||
pm_wakeup_event(ckdev->dev, 0);
|
||||
} else {
|
||||
/*
|
||||
* If keyboard is not wake enabled, discard key state
|
||||
* changes during suspend. Switches will be re-checked
|
||||
* in cros_ec_keyb_resume() to be sure nothing is lost.
|
||||
*/
|
||||
if (queued_during_suspend)
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
pm_wakeup_event(ckdev->dev, 0);
|
||||
|
||||
if (ckdev->ec->event_size != ckdev->cols) {
|
||||
dev_err(ckdev->dev,
|
||||
|
@ -268,10 +253,7 @@ static int cros_ec_keyb_work(struct notifier_block *nb,
|
|||
break;
|
||||
|
||||
case EC_MKBP_EVENT_SYSRQ:
|
||||
if (device_may_wakeup(ckdev->dev))
|
||||
pm_wakeup_event(ckdev->dev, 0);
|
||||
else if (queued_during_suspend)
|
||||
return NOTIFY_OK;
|
||||
pm_wakeup_event(ckdev->dev, 0);
|
||||
|
||||
val = get_unaligned_le32(&ckdev->ec->event_data.data.sysrq);
|
||||
dev_dbg(ckdev->dev, "sysrq code from EC: %#x\n", val);
|
||||
|
@ -280,10 +262,7 @@ static int cros_ec_keyb_work(struct notifier_block *nb,
|
|||
|
||||
case EC_MKBP_EVENT_BUTTON:
|
||||
case EC_MKBP_EVENT_SWITCH:
|
||||
if (device_may_wakeup(ckdev->dev))
|
||||
pm_wakeup_event(ckdev->dev, 0);
|
||||
else if (queued_during_suspend)
|
||||
return NOTIFY_OK;
|
||||
pm_wakeup_event(ckdev->dev, 0);
|
||||
|
||||
if (ckdev->ec->event_data.event_type == EC_MKBP_EVENT_BUTTON) {
|
||||
val = get_unaligned_le32(
|
||||
|
@ -683,6 +662,6 @@ static struct platform_driver cros_ec_keyb_driver = {
|
|||
|
||||
module_platform_driver(cros_ec_keyb_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("ChromeOS EC keyboard driver");
|
||||
MODULE_ALIAS("platform:cros-ec-keyb");
|
||||
|
|
|
@ -196,7 +196,7 @@ static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata,
|
|||
ssize_t ret;
|
||||
int i;
|
||||
|
||||
bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL);
|
||||
bits = bitmap_zalloc(n_events, GFP_KERNEL);
|
||||
if (!bits)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -216,7 +216,7 @@ static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata,
|
|||
buf[ret++] = '\n';
|
||||
buf[ret] = '\0';
|
||||
|
||||
kfree(bits);
|
||||
bitmap_free(bits);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -240,7 +240,7 @@ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata,
|
|||
ssize_t error;
|
||||
int i;
|
||||
|
||||
bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL);
|
||||
bits = bitmap_zalloc(n_events, GFP_KERNEL);
|
||||
if (!bits)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -284,7 +284,7 @@ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata,
|
|||
mutex_unlock(&ddata->disable_lock);
|
||||
|
||||
out:
|
||||
kfree(bits);
|
||||
bitmap_free(bits);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
/*
|
||||
* Driver for the IMX keypad port.
|
||||
* Copyright (C) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// Driver for the IMX keypad port.
|
||||
// Copyright (C) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
|
|
|
@ -20,10 +20,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <j.cormack@doc.ic.ac.uk>, or by paper mail:
|
||||
* Justin Cormack, 68 Dartmouth Park Road, London NW5 1SN, UK.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
|
|
@ -1,14 +1,7 @@
|
|||
/*
|
||||
* Driver for the IMX SNVS ON/OFF Power Key
|
||||
* Copyright (C) 2015 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||
*
|
||||
* The code contained herein is licensed under the GNU General Public
|
||||
* License. You may obtain a copy of the GNU General Public License
|
||||
* Version 2 or later at the following locations:
|
||||
*
|
||||
* http://www.opensource.org/licenses/gpl-license.html
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
//
|
||||
// Driver for the IMX SNVS ON/OFF Power Key
|
||||
// Copyright (C) 2015 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
|
|
|
@ -23,10 +23,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <marek.vasut@gmail.com>, or by paper mail:
|
||||
* Marek Vasut, Liskovecka 559, Frydek-Mistek, 738 01 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
|
|
@ -20,10 +20,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
|
|
|
@ -20,10 +20,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
|
|
@ -466,7 +466,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
|
|||
remote->in_endpoint = endpoint;
|
||||
remote->toggle = -1; /* Set to -1 so we will always not match the toggle from the first remote message. */
|
||||
|
||||
remote->in_buffer = usb_alloc_coherent(udev, RECV_SIZE, GFP_ATOMIC, &remote->in_dma);
|
||||
remote->in_buffer = usb_alloc_coherent(udev, RECV_SIZE, GFP_KERNEL, &remote->in_dma);
|
||||
if (!remote->in_buffer) {
|
||||
error = -ENOMEM;
|
||||
goto fail1;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <linux/log2.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/regmap.h>
|
||||
|
@ -28,6 +29,7 @@
|
|||
|
||||
#define PON_RT_STS 0x10
|
||||
#define PON_KPDPWR_N_SET BIT(0)
|
||||
#define PON_RESIN_N_SET BIT(1)
|
||||
|
||||
#define PON_PS_HOLD_RST_CTL 0x5a
|
||||
#define PON_PS_HOLD_RST_CTL2 0x5b
|
||||
|
@ -38,10 +40,15 @@
|
|||
|
||||
#define PON_PULL_CTL 0x70
|
||||
#define PON_KPDPWR_PULL_UP BIT(1)
|
||||
#define PON_RESIN_PULL_UP BIT(0)
|
||||
|
||||
#define PON_DBC_CTL 0x71
|
||||
#define PON_DBC_DELAY_MASK 0x7
|
||||
|
||||
struct pm8941_data {
|
||||
unsigned int pull_up_bit;
|
||||
unsigned int status_bit;
|
||||
};
|
||||
|
||||
struct pm8941_pwrkey {
|
||||
struct device *dev;
|
||||
|
@ -52,6 +59,9 @@ struct pm8941_pwrkey {
|
|||
|
||||
unsigned int revision;
|
||||
struct notifier_block reboot_notifier;
|
||||
|
||||
u32 code;
|
||||
const struct pm8941_data *data;
|
||||
};
|
||||
|
||||
static int pm8941_reboot_notify(struct notifier_block *nb,
|
||||
|
@ -124,7 +134,8 @@ static irqreturn_t pm8941_pwrkey_irq(int irq, void *_data)
|
|||
if (error)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
input_report_key(pwrkey->input, KEY_POWER, !!(sts & PON_KPDPWR_N_SET));
|
||||
input_report_key(pwrkey->input, pwrkey->code,
|
||||
sts & pwrkey->data->status_bit);
|
||||
input_sync(pwrkey->input);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
@ -157,6 +168,7 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct pm8941_pwrkey *pwrkey;
|
||||
bool pull_up;
|
||||
struct device *parent;
|
||||
u32 req_delay;
|
||||
int error;
|
||||
|
||||
|
@ -175,12 +187,30 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
|
|||
return -ENOMEM;
|
||||
|
||||
pwrkey->dev = &pdev->dev;
|
||||
pwrkey->data = of_device_get_match_data(&pdev->dev);
|
||||
|
||||
pwrkey->regmap = dev_get_regmap(pdev->dev.parent, NULL);
|
||||
parent = pdev->dev.parent;
|
||||
pwrkey->regmap = dev_get_regmap(parent, NULL);
|
||||
if (!pwrkey->regmap) {
|
||||
dev_err(&pdev->dev, "failed to locate regmap\n");
|
||||
return -ENODEV;
|
||||
/*
|
||||
* We failed to get regmap for parent. Let's see if we are
|
||||
* a child of pon node and read regmap and reg from its
|
||||
* parent.
|
||||
*/
|
||||
pwrkey->regmap = dev_get_regmap(parent->parent, NULL);
|
||||
if (!pwrkey->regmap) {
|
||||
dev_err(&pdev->dev, "failed to locate regmap\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
error = of_property_read_u32(parent->of_node,
|
||||
"reg", &pwrkey->baseaddr);
|
||||
} else {
|
||||
error = of_property_read_u32(pdev->dev.of_node, "reg",
|
||||
&pwrkey->baseaddr);
|
||||
}
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
pwrkey->irq = platform_get_irq(pdev, 0);
|
||||
if (pwrkey->irq < 0) {
|
||||
|
@ -188,11 +218,6 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
|
|||
return pwrkey->irq;
|
||||
}
|
||||
|
||||
error = of_property_read_u32(pdev->dev.of_node, "reg",
|
||||
&pwrkey->baseaddr);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = regmap_read(pwrkey->regmap, pwrkey->baseaddr + PON_REV2,
|
||||
&pwrkey->revision);
|
||||
if (error) {
|
||||
|
@ -200,13 +225,21 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
|
|||
return error;
|
||||
}
|
||||
|
||||
error = of_property_read_u32(pdev->dev.of_node, "linux,code",
|
||||
&pwrkey->code);
|
||||
if (error) {
|
||||
dev_dbg(&pdev->dev,
|
||||
"no linux,code assuming power (%d)\n", error);
|
||||
pwrkey->code = KEY_POWER;
|
||||
}
|
||||
|
||||
pwrkey->input = devm_input_allocate_device(&pdev->dev);
|
||||
if (!pwrkey->input) {
|
||||
dev_dbg(&pdev->dev, "unable to allocate input device\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
input_set_capability(pwrkey->input, EV_KEY, KEY_POWER);
|
||||
input_set_capability(pwrkey->input, EV_KEY, pwrkey->code);
|
||||
|
||||
pwrkey->input->name = "pm8941_pwrkey";
|
||||
pwrkey->input->phys = "pm8941_pwrkey/input0";
|
||||
|
@ -225,8 +258,8 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
|
|||
|
||||
error = regmap_update_bits(pwrkey->regmap,
|
||||
pwrkey->baseaddr + PON_PULL_CTL,
|
||||
PON_KPDPWR_PULL_UP,
|
||||
pull_up ? PON_KPDPWR_PULL_UP : 0);
|
||||
pwrkey->data->pull_up_bit,
|
||||
pull_up ? pwrkey->data->pull_up_bit : 0);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to set pull: %d\n", error);
|
||||
return error;
|
||||
|
@ -271,8 +304,19 @@ static int pm8941_pwrkey_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct pm8941_data pwrkey_data = {
|
||||
.pull_up_bit = PON_KPDPWR_PULL_UP,
|
||||
.status_bit = PON_KPDPWR_N_SET,
|
||||
};
|
||||
|
||||
static const struct pm8941_data resin_data = {
|
||||
.pull_up_bit = PON_RESIN_PULL_UP,
|
||||
.status_bit = PON_RESIN_N_SET,
|
||||
};
|
||||
|
||||
static const struct of_device_id pm8941_pwr_key_id_table[] = {
|
||||
{ .compatible = "qcom,pm8941-pwrkey" },
|
||||
{ .compatible = "qcom,pm8941-pwrkey", .data = &pwrkey_data },
|
||||
{ .compatible = "qcom,pm8941-resin", .data = &resin_data },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, pm8941_pwr_key_id_table);
|
||||
|
|
|
@ -277,7 +277,7 @@ static int powermate_input_event(struct input_dev *dev, unsigned int type, unsig
|
|||
static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_device *pm)
|
||||
{
|
||||
pm->data = usb_alloc_coherent(udev, POWERMATE_PAYLOAD_SIZE_MAX,
|
||||
GFP_ATOMIC, &pm->data_dma);
|
||||
GFP_KERNEL, &pm->data_dma);
|
||||
if (!pm->data)
|
||||
return -1;
|
||||
|
||||
|
|
|
@ -63,6 +63,9 @@ static void xenkbd_disconnect_backend(struct xenkbd_info *);
|
|||
static void xenkbd_handle_motion_event(struct xenkbd_info *info,
|
||||
struct xenkbd_motion *motion)
|
||||
{
|
||||
if (unlikely(!info->ptr))
|
||||
return;
|
||||
|
||||
input_report_rel(info->ptr, REL_X, motion->rel_x);
|
||||
input_report_rel(info->ptr, REL_Y, motion->rel_y);
|
||||
if (motion->rel_z)
|
||||
|
@ -73,6 +76,9 @@ static void xenkbd_handle_motion_event(struct xenkbd_info *info,
|
|||
static void xenkbd_handle_position_event(struct xenkbd_info *info,
|
||||
struct xenkbd_position *pos)
|
||||
{
|
||||
if (unlikely(!info->ptr))
|
||||
return;
|
||||
|
||||
input_report_abs(info->ptr, ABS_X, pos->abs_x);
|
||||
input_report_abs(info->ptr, ABS_Y, pos->abs_y);
|
||||
if (pos->rel_z)
|
||||
|
@ -97,6 +103,9 @@ static void xenkbd_handle_key_event(struct xenkbd_info *info,
|
|||
return;
|
||||
}
|
||||
|
||||
if (unlikely(!dev))
|
||||
return;
|
||||
|
||||
input_event(dev, EV_KEY, key->keycode, value);
|
||||
input_sync(dev);
|
||||
}
|
||||
|
@ -192,7 +201,7 @@ static int xenkbd_probe(struct xenbus_device *dev,
|
|||
const struct xenbus_device_id *id)
|
||||
{
|
||||
int ret, i;
|
||||
unsigned int abs, touch;
|
||||
bool with_mtouch, with_kbd, with_ptr;
|
||||
struct xenkbd_info *info;
|
||||
struct input_dev *kbd, *ptr, *mtouch;
|
||||
|
||||
|
@ -211,106 +220,127 @@ static int xenkbd_probe(struct xenbus_device *dev,
|
|||
if (!info->page)
|
||||
goto error_nomem;
|
||||
|
||||
/* Set input abs params to match backend screen res */
|
||||
abs = xenbus_read_unsigned(dev->otherend,
|
||||
XENKBD_FIELD_FEAT_ABS_POINTER, 0);
|
||||
ptr_size[KPARAM_X] = xenbus_read_unsigned(dev->otherend,
|
||||
XENKBD_FIELD_WIDTH,
|
||||
ptr_size[KPARAM_X]);
|
||||
ptr_size[KPARAM_Y] = xenbus_read_unsigned(dev->otherend,
|
||||
XENKBD_FIELD_HEIGHT,
|
||||
ptr_size[KPARAM_Y]);
|
||||
if (abs) {
|
||||
ret = xenbus_write(XBT_NIL, dev->nodename,
|
||||
XENKBD_FIELD_REQ_ABS_POINTER, "1");
|
||||
if (ret) {
|
||||
pr_warn("xenkbd: can't request abs-pointer\n");
|
||||
abs = 0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* The below are reverse logic, e.g. if the feature is set, then
|
||||
* do not expose the corresponding virtual device.
|
||||
*/
|
||||
with_kbd = !xenbus_read_unsigned(dev->otherend,
|
||||
XENKBD_FIELD_FEAT_DSBL_KEYBRD, 0);
|
||||
|
||||
touch = xenbus_read_unsigned(dev->nodename,
|
||||
XENKBD_FIELD_FEAT_MTOUCH, 0);
|
||||
if (touch) {
|
||||
with_ptr = !xenbus_read_unsigned(dev->otherend,
|
||||
XENKBD_FIELD_FEAT_DSBL_POINTER, 0);
|
||||
|
||||
/* Direct logic: if set, then create multi-touch device. */
|
||||
with_mtouch = xenbus_read_unsigned(dev->otherend,
|
||||
XENKBD_FIELD_FEAT_MTOUCH, 0);
|
||||
if (with_mtouch) {
|
||||
ret = xenbus_write(XBT_NIL, dev->nodename,
|
||||
XENKBD_FIELD_REQ_MTOUCH, "1");
|
||||
if (ret) {
|
||||
pr_warn("xenkbd: can't request multi-touch");
|
||||
touch = 0;
|
||||
with_mtouch = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* keyboard */
|
||||
kbd = input_allocate_device();
|
||||
if (!kbd)
|
||||
goto error_nomem;
|
||||
kbd->name = "Xen Virtual Keyboard";
|
||||
kbd->phys = info->phys;
|
||||
kbd->id.bustype = BUS_PCI;
|
||||
kbd->id.vendor = 0x5853;
|
||||
kbd->id.product = 0xffff;
|
||||
if (with_kbd) {
|
||||
kbd = input_allocate_device();
|
||||
if (!kbd)
|
||||
goto error_nomem;
|
||||
kbd->name = "Xen Virtual Keyboard";
|
||||
kbd->phys = info->phys;
|
||||
kbd->id.bustype = BUS_PCI;
|
||||
kbd->id.vendor = 0x5853;
|
||||
kbd->id.product = 0xffff;
|
||||
|
||||
__set_bit(EV_KEY, kbd->evbit);
|
||||
for (i = KEY_ESC; i < KEY_UNKNOWN; i++)
|
||||
__set_bit(i, kbd->keybit);
|
||||
for (i = KEY_OK; i < KEY_MAX; i++)
|
||||
__set_bit(i, kbd->keybit);
|
||||
__set_bit(EV_KEY, kbd->evbit);
|
||||
for (i = KEY_ESC; i < KEY_UNKNOWN; i++)
|
||||
__set_bit(i, kbd->keybit);
|
||||
for (i = KEY_OK; i < KEY_MAX; i++)
|
||||
__set_bit(i, kbd->keybit);
|
||||
|
||||
ret = input_register_device(kbd);
|
||||
if (ret) {
|
||||
input_free_device(kbd);
|
||||
xenbus_dev_fatal(dev, ret, "input_register_device(kbd)");
|
||||
goto error;
|
||||
ret = input_register_device(kbd);
|
||||
if (ret) {
|
||||
input_free_device(kbd);
|
||||
xenbus_dev_fatal(dev, ret,
|
||||
"input_register_device(kbd)");
|
||||
goto error;
|
||||
}
|
||||
info->kbd = kbd;
|
||||
}
|
||||
info->kbd = kbd;
|
||||
|
||||
/* pointing device */
|
||||
ptr = input_allocate_device();
|
||||
if (!ptr)
|
||||
goto error_nomem;
|
||||
ptr->name = "Xen Virtual Pointer";
|
||||
ptr->phys = info->phys;
|
||||
ptr->id.bustype = BUS_PCI;
|
||||
ptr->id.vendor = 0x5853;
|
||||
ptr->id.product = 0xfffe;
|
||||
if (with_ptr) {
|
||||
unsigned int abs;
|
||||
|
||||
if (abs) {
|
||||
__set_bit(EV_ABS, ptr->evbit);
|
||||
input_set_abs_params(ptr, ABS_X, 0, ptr_size[KPARAM_X], 0, 0);
|
||||
input_set_abs_params(ptr, ABS_Y, 0, ptr_size[KPARAM_Y], 0, 0);
|
||||
} else {
|
||||
input_set_capability(ptr, EV_REL, REL_X);
|
||||
input_set_capability(ptr, EV_REL, REL_Y);
|
||||
/* Set input abs params to match backend screen res */
|
||||
abs = xenbus_read_unsigned(dev->otherend,
|
||||
XENKBD_FIELD_FEAT_ABS_POINTER, 0);
|
||||
ptr_size[KPARAM_X] = xenbus_read_unsigned(dev->otherend,
|
||||
XENKBD_FIELD_WIDTH,
|
||||
ptr_size[KPARAM_X]);
|
||||
ptr_size[KPARAM_Y] = xenbus_read_unsigned(dev->otherend,
|
||||
XENKBD_FIELD_HEIGHT,
|
||||
ptr_size[KPARAM_Y]);
|
||||
if (abs) {
|
||||
ret = xenbus_write(XBT_NIL, dev->nodename,
|
||||
XENKBD_FIELD_REQ_ABS_POINTER, "1");
|
||||
if (ret) {
|
||||
pr_warn("xenkbd: can't request abs-pointer\n");
|
||||
abs = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ptr = input_allocate_device();
|
||||
if (!ptr)
|
||||
goto error_nomem;
|
||||
ptr->name = "Xen Virtual Pointer";
|
||||
ptr->phys = info->phys;
|
||||
ptr->id.bustype = BUS_PCI;
|
||||
ptr->id.vendor = 0x5853;
|
||||
ptr->id.product = 0xfffe;
|
||||
|
||||
if (abs) {
|
||||
__set_bit(EV_ABS, ptr->evbit);
|
||||
input_set_abs_params(ptr, ABS_X, 0,
|
||||
ptr_size[KPARAM_X], 0, 0);
|
||||
input_set_abs_params(ptr, ABS_Y, 0,
|
||||
ptr_size[KPARAM_Y], 0, 0);
|
||||
} else {
|
||||
input_set_capability(ptr, EV_REL, REL_X);
|
||||
input_set_capability(ptr, EV_REL, REL_Y);
|
||||
}
|
||||
input_set_capability(ptr, EV_REL, REL_WHEEL);
|
||||
|
||||
__set_bit(EV_KEY, ptr->evbit);
|
||||
for (i = BTN_LEFT; i <= BTN_TASK; i++)
|
||||
__set_bit(i, ptr->keybit);
|
||||
|
||||
ret = input_register_device(ptr);
|
||||
if (ret) {
|
||||
input_free_device(ptr);
|
||||
xenbus_dev_fatal(dev, ret,
|
||||
"input_register_device(ptr)");
|
||||
goto error;
|
||||
}
|
||||
info->ptr = ptr;
|
||||
}
|
||||
input_set_capability(ptr, EV_REL, REL_WHEEL);
|
||||
|
||||
__set_bit(EV_KEY, ptr->evbit);
|
||||
for (i = BTN_LEFT; i <= BTN_TASK; i++)
|
||||
__set_bit(i, ptr->keybit);
|
||||
|
||||
ret = input_register_device(ptr);
|
||||
if (ret) {
|
||||
input_free_device(ptr);
|
||||
xenbus_dev_fatal(dev, ret, "input_register_device(ptr)");
|
||||
goto error;
|
||||
}
|
||||
info->ptr = ptr;
|
||||
|
||||
/* multi-touch device */
|
||||
if (touch) {
|
||||
if (with_mtouch) {
|
||||
int num_cont, width, height;
|
||||
|
||||
mtouch = input_allocate_device();
|
||||
if (!mtouch)
|
||||
goto error_nomem;
|
||||
|
||||
num_cont = xenbus_read_unsigned(info->xbdev->nodename,
|
||||
num_cont = xenbus_read_unsigned(info->xbdev->otherend,
|
||||
XENKBD_FIELD_MT_NUM_CONTACTS,
|
||||
1);
|
||||
width = xenbus_read_unsigned(info->xbdev->nodename,
|
||||
width = xenbus_read_unsigned(info->xbdev->otherend,
|
||||
XENKBD_FIELD_MT_WIDTH,
|
||||
XENFB_WIDTH);
|
||||
height = xenbus_read_unsigned(info->xbdev->nodename,
|
||||
height = xenbus_read_unsigned(info->xbdev->otherend,
|
||||
XENKBD_FIELD_MT_HEIGHT,
|
||||
XENFB_HEIGHT);
|
||||
|
||||
|
@ -346,6 +376,11 @@ static int xenkbd_probe(struct xenbus_device *dev,
|
|||
info->mtouch = mtouch;
|
||||
}
|
||||
|
||||
if (!(with_kbd || with_ptr || with_mtouch)) {
|
||||
ret = -ENXIO;
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = xenkbd_connect_backend(dev, info);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
|
|
@ -894,12 +894,12 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
|||
|
||||
/* allocate usb buffers */
|
||||
yld->irq_data = usb_alloc_coherent(udev, USB_PKT_LEN,
|
||||
GFP_ATOMIC, &yld->irq_dma);
|
||||
GFP_KERNEL, &yld->irq_dma);
|
||||
if (yld->irq_data == NULL)
|
||||
return usb_cleanup(yld, -ENOMEM);
|
||||
|
||||
yld->ctl_data = usb_alloc_coherent(udev, USB_PKT_LEN,
|
||||
GFP_ATOMIC, &yld->ctl_dma);
|
||||
GFP_KERNEL, &yld->ctl_dma);
|
||||
if (!yld->ctl_data)
|
||||
return usb_cleanup(yld, -ENOMEM);
|
||||
|
||||
|
|
|
@ -472,6 +472,7 @@ static int atp_status_check(struct urb *urb)
|
|||
dev->info->datalen, dev->urb->actual_length);
|
||||
dev->overflow_warned = true;
|
||||
}
|
||||
/* fall through */
|
||||
case -ECONNRESET:
|
||||
case -ENOENT:
|
||||
case -ESHUTDOWN:
|
||||
|
@ -810,7 +811,7 @@ static int atp_open(struct input_dev *input)
|
|||
{
|
||||
struct atp *dev = input_get_drvdata(input);
|
||||
|
||||
if (usb_submit_urb(dev->urb, GFP_ATOMIC))
|
||||
if (usb_submit_urb(dev->urb, GFP_KERNEL))
|
||||
return -EIO;
|
||||
|
||||
dev->open = true;
|
||||
|
@ -976,7 +977,7 @@ static int atp_recover(struct atp *dev)
|
|||
if (error)
|
||||
return error;
|
||||
|
||||
if (dev->open && usb_submit_urb(dev->urb, GFP_ATOMIC))
|
||||
if (dev->open && usb_submit_urb(dev->urb, GFP_KERNEL))
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
|
@ -994,7 +995,7 @@ static int atp_resume(struct usb_interface *iface)
|
|||
{
|
||||
struct atp *dev = usb_get_intfdata(iface);
|
||||
|
||||
if (dev->open && usb_submit_urb(dev->urb, GFP_ATOMIC))
|
||||
if (dev->open && usb_submit_urb(dev->urb, GFP_KERNEL))
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -2554,6 +2554,7 @@ static int cyapa_gen5_do_operational_check(struct cyapa *cyapa)
|
|||
}
|
||||
|
||||
cyapa->state = CYAPA_STATE_GEN5_APP;
|
||||
/* fall through */
|
||||
|
||||
case CYAPA_STATE_GEN5_APP:
|
||||
/*
|
||||
|
|
|
@ -680,6 +680,7 @@ static int cyapa_gen6_operational_check(struct cyapa *cyapa)
|
|||
}
|
||||
|
||||
cyapa->state = CYAPA_STATE_GEN6_APP;
|
||||
/* fall through */
|
||||
|
||||
case CYAPA_STATE_GEN6_APP:
|
||||
/*
|
||||
|
|
|
@ -387,7 +387,7 @@ static int elan_smbus_prepare_fw_update(struct i2c_client *client)
|
|||
len = i2c_smbus_read_block_data(client,
|
||||
ETP_SMBUS_IAP_PASSWORD_READ,
|
||||
val);
|
||||
if (len < sizeof(u16)) {
|
||||
if (len < (int)sizeof(u16)) {
|
||||
error = len < 0 ? len : -EIO;
|
||||
dev_err(dev, "failed to read iap password: %d\n",
|
||||
error);
|
||||
|
|
|
@ -340,7 +340,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
|
|||
*/
|
||||
if (packet[3] & 0x80)
|
||||
fingers = 4;
|
||||
/* pass through... */
|
||||
/* fall through */
|
||||
case 1:
|
||||
/*
|
||||
* byte 1: . . . . x11 x10 x9 x8
|
||||
|
|
|
@ -26,10 +26,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
|
|
@ -27,10 +27,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
|
|
@ -23,10 +23,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
|
|
@ -20,10 +20,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
|
@ -143,7 +139,8 @@ static void sermouse_process_ms(struct sermouse *sermouse, signed char data)
|
|||
switch (sermouse->type) {
|
||||
|
||||
case SERIO_MS:
|
||||
sermouse->type = SERIO_MP;
|
||||
sermouse->type = SERIO_MP;
|
||||
/* fall through */
|
||||
|
||||
case SERIO_MP:
|
||||
if ((data >> 2) & 3) break; /* M++ Wireless Extension packet. */
|
||||
|
@ -154,6 +151,7 @@ static void sermouse_process_ms(struct sermouse *sermouse, signed char data)
|
|||
case SERIO_MZP:
|
||||
case SERIO_MZPP:
|
||||
input_report_key(dev, BTN_SIDE, (data >> 5) & 1);
|
||||
/* fall through */
|
||||
|
||||
case SERIO_MZ:
|
||||
input_report_key(dev, BTN_MIDDLE, (data >> 4) & 1);
|
||||
|
|
|
@ -20,10 +20,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
|
|
|
@ -573,6 +573,9 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id)
|
|||
port = &i8042_ports[port_no];
|
||||
serio = port->exists ? port->serio : NULL;
|
||||
|
||||
if (irq && serio)
|
||||
pm_wakeup_event(&serio->dev, 0);
|
||||
|
||||
filter_dbg(port->driver_bound, data, "<- i8042 (interrupt, %d, %d%s%s)\n",
|
||||
port_no, irq,
|
||||
dfl & SERIO_PARITY ? ", bad parity" : "",
|
||||
|
|
|
@ -23,10 +23,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
|
|
@ -21,10 +21,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
|
|
@ -20,10 +20,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
|
|
@ -1712,7 +1712,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
|||
}
|
||||
|
||||
aiptek->data = usb_alloc_coherent(usbdev, AIPTEK_PACKET_LENGTH,
|
||||
GFP_ATOMIC, &aiptek->data_dma);
|
||||
GFP_KERNEL, &aiptek->data_dma);
|
||||
if (!aiptek->data) {
|
||||
dev_warn(&intf->dev, "cannot allocate usb buffer\n");
|
||||
goto fail1;
|
||||
|
|
|
@ -164,6 +164,18 @@ config TOUCHSCREEN_BU21013
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called bu21013_ts.
|
||||
|
||||
config TOUCHSCREEN_BU21029
|
||||
tristate "Rohm BU21029 based touch panel controllers"
|
||||
depends on I2C
|
||||
help
|
||||
Say Y here if you have a Rohm BU21029 touchscreen controller
|
||||
connected to your system.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called bu21029_ts.
|
||||
|
||||
config TOUCHSCREEN_CHIPONE_ICN8318
|
||||
tristate "chipone icn8318 touchscreen controller"
|
||||
depends on GPIOLIB || COMPILE_TEST
|
||||
|
|
|
@ -19,6 +19,7 @@ obj-$(CONFIG_TOUCHSCREEN_AR1021_I2C) += ar1021_i2c.o
|
|||
obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_BU21029) += bu21029_ts.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_CHIPONE_ICN8318) += chipone_icn8318.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_CHIPONE_ICN8505) += chipone_icn8505.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
#define MXT_SPT_DIGITIZER_T43 43
|
||||
#define MXT_SPT_MESSAGECOUNT_T44 44
|
||||
#define MXT_SPT_CTECONFIG_T46 46
|
||||
#define MXT_SPT_DYNAMICCONFIGURATIONCONTAINER_T71 71
|
||||
#define MXT_TOUCH_MULTITOUCHSCREEN_T100 100
|
||||
|
||||
/* MXT_GEN_MESSAGE_T5 object */
|
||||
|
@ -88,12 +89,12 @@
|
|||
#define MXT_COMMAND_DIAGNOSTIC 5
|
||||
|
||||
/* Define for T6 status byte */
|
||||
#define MXT_T6_STATUS_RESET (1 << 7)
|
||||
#define MXT_T6_STATUS_OFL (1 << 6)
|
||||
#define MXT_T6_STATUS_SIGERR (1 << 5)
|
||||
#define MXT_T6_STATUS_CAL (1 << 4)
|
||||
#define MXT_T6_STATUS_CFGERR (1 << 3)
|
||||
#define MXT_T6_STATUS_COMSERR (1 << 2)
|
||||
#define MXT_T6_STATUS_RESET BIT(7)
|
||||
#define MXT_T6_STATUS_OFL BIT(6)
|
||||
#define MXT_T6_STATUS_SIGERR BIT(5)
|
||||
#define MXT_T6_STATUS_CAL BIT(4)
|
||||
#define MXT_T6_STATUS_CFGERR BIT(3)
|
||||
#define MXT_T6_STATUS_COMSERR BIT(2)
|
||||
|
||||
/* MXT_GEN_POWER_T7 field */
|
||||
struct t7_config {
|
||||
|
@ -112,14 +113,14 @@ struct t7_config {
|
|||
#define MXT_T9_RANGE 18
|
||||
|
||||
/* MXT_TOUCH_MULTI_T9 status */
|
||||
#define MXT_T9_UNGRIP (1 << 0)
|
||||
#define MXT_T9_SUPPRESS (1 << 1)
|
||||
#define MXT_T9_AMP (1 << 2)
|
||||
#define MXT_T9_VECTOR (1 << 3)
|
||||
#define MXT_T9_MOVE (1 << 4)
|
||||
#define MXT_T9_RELEASE (1 << 5)
|
||||
#define MXT_T9_PRESS (1 << 6)
|
||||
#define MXT_T9_DETECT (1 << 7)
|
||||
#define MXT_T9_UNGRIP BIT(0)
|
||||
#define MXT_T9_SUPPRESS BIT(1)
|
||||
#define MXT_T9_AMP BIT(2)
|
||||
#define MXT_T9_VECTOR BIT(3)
|
||||
#define MXT_T9_MOVE BIT(4)
|
||||
#define MXT_T9_RELEASE BIT(5)
|
||||
#define MXT_T9_PRESS BIT(6)
|
||||
#define MXT_T9_DETECT BIT(7)
|
||||
|
||||
struct t9_range {
|
||||
__le16 x;
|
||||
|
@ -127,9 +128,9 @@ struct t9_range {
|
|||
} __packed;
|
||||
|
||||
/* MXT_TOUCH_MULTI_T9 orient */
|
||||
#define MXT_T9_ORIENT_SWITCH (1 << 0)
|
||||
#define MXT_T9_ORIENT_INVERTX (1 << 1)
|
||||
#define MXT_T9_ORIENT_INVERTY (1 << 2)
|
||||
#define MXT_T9_ORIENT_SWITCH BIT(0)
|
||||
#define MXT_T9_ORIENT_INVERTX BIT(1)
|
||||
#define MXT_T9_ORIENT_INVERTY BIT(2)
|
||||
|
||||
/* MXT_SPT_COMMSCONFIG_T18 */
|
||||
#define MXT_COMMS_CTRL 0
|
||||
|
@ -214,7 +215,7 @@ enum t100_type {
|
|||
#define MXT_FRAME_CRC_PASS 0x04
|
||||
#define MXT_APP_CRC_FAIL 0x40 /* valid 7 8 bit only */
|
||||
#define MXT_BOOT_STATUS_MASK 0x3f
|
||||
#define MXT_BOOT_EXTENDED_ID (1 << 5)
|
||||
#define MXT_BOOT_EXTENDED_ID BIT(5)
|
||||
#define MXT_BOOT_ID_MASK 0x1f
|
||||
|
||||
/* Touchscreen absolute values */
|
||||
|
@ -276,6 +277,19 @@ enum mxt_suspend_mode {
|
|||
MXT_SUSPEND_T9_CTRL = 1,
|
||||
};
|
||||
|
||||
/* Config update context */
|
||||
struct mxt_cfg {
|
||||
u8 *raw;
|
||||
size_t raw_size;
|
||||
off_t raw_pos;
|
||||
|
||||
u8 *mem;
|
||||
size_t mem_size;
|
||||
int start_ofs;
|
||||
|
||||
struct mxt_info info;
|
||||
};
|
||||
|
||||
/* Each client has this additional data */
|
||||
struct mxt_data {
|
||||
struct i2c_client *client;
|
||||
|
@ -317,6 +331,7 @@ struct mxt_data {
|
|||
u8 T6_reportid;
|
||||
u16 T6_address;
|
||||
u16 T7_address;
|
||||
u16 T71_address;
|
||||
u8 T9_reportid_min;
|
||||
u8 T9_reportid_max;
|
||||
u8 T19_reportid;
|
||||
|
@ -382,6 +397,7 @@ static bool mxt_object_readable(unsigned int type)
|
|||
case MXT_SPT_USERDATA_T38:
|
||||
case MXT_SPT_DIGITIZER_T43:
|
||||
case MXT_SPT_CTECONFIG_T46:
|
||||
case MXT_SPT_DYNAMICCONFIGURATIONCONTAINER_T71:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -712,13 +728,13 @@ static void mxt_proc_t6_messages(struct mxt_data *data, u8 *msg)
|
|||
u8 status = msg[1];
|
||||
u32 crc = msg[2] | (msg[3] << 8) | (msg[4] << 16);
|
||||
|
||||
complete(&data->crc_completion);
|
||||
|
||||
if (crc != data->config_crc) {
|
||||
data->config_crc = crc;
|
||||
dev_dbg(dev, "T6 Config Checksum: 0x%06X\n", crc);
|
||||
}
|
||||
|
||||
complete(&data->crc_completion);
|
||||
|
||||
/* Detect reset */
|
||||
if (status & MXT_T6_STATUS_RESET)
|
||||
complete(&data->reset_completion);
|
||||
|
@ -827,6 +843,10 @@ static void mxt_proc_t9_message(struct mxt_data *data, u8 *message)
|
|||
mxt_input_sync(data);
|
||||
}
|
||||
|
||||
/* if active, pressure must be non-zero */
|
||||
if (!amplitude)
|
||||
amplitude = MXT_PRESSURE_DEFAULT;
|
||||
|
||||
/* Touch active */
|
||||
input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 1);
|
||||
input_report_abs(input_dev, ABS_MT_POSITION_X, x);
|
||||
|
@ -1279,12 +1299,7 @@ static u32 mxt_calculate_crc(u8 *base, off_t start_off, off_t end_off)
|
|||
return crc;
|
||||
}
|
||||
|
||||
static int mxt_prepare_cfg_mem(struct mxt_data *data,
|
||||
const struct firmware *cfg,
|
||||
unsigned int data_pos,
|
||||
unsigned int cfg_start_ofs,
|
||||
u8 *config_mem,
|
||||
size_t config_mem_size)
|
||||
static int mxt_prepare_cfg_mem(struct mxt_data *data, struct mxt_cfg *cfg)
|
||||
{
|
||||
struct device *dev = &data->client->dev;
|
||||
struct mxt_object *object;
|
||||
|
@ -1295,9 +1310,9 @@ static int mxt_prepare_cfg_mem(struct mxt_data *data,
|
|||
u16 reg;
|
||||
u8 val;
|
||||
|
||||
while (data_pos < cfg->size) {
|
||||
while (cfg->raw_pos < cfg->raw_size) {
|
||||
/* Read type, instance, length */
|
||||
ret = sscanf(cfg->data + data_pos, "%x %x %x%n",
|
||||
ret = sscanf(cfg->raw + cfg->raw_pos, "%x %x %x%n",
|
||||
&type, &instance, &size, &offset);
|
||||
if (ret == 0) {
|
||||
/* EOF */
|
||||
|
@ -1306,20 +1321,20 @@ static int mxt_prepare_cfg_mem(struct mxt_data *data,
|
|||
dev_err(dev, "Bad format: failed to parse object\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
data_pos += offset;
|
||||
cfg->raw_pos += offset;
|
||||
|
||||
object = mxt_get_object(data, type);
|
||||
if (!object) {
|
||||
/* Skip object */
|
||||
for (i = 0; i < size; i++) {
|
||||
ret = sscanf(cfg->data + data_pos, "%hhx%n",
|
||||
ret = sscanf(cfg->raw + cfg->raw_pos, "%hhx%n",
|
||||
&val, &offset);
|
||||
if (ret != 1) {
|
||||
dev_err(dev, "Bad format in T%d at %d\n",
|
||||
type, i);
|
||||
return -EINVAL;
|
||||
}
|
||||
data_pos += offset;
|
||||
cfg->raw_pos += offset;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -1354,7 +1369,7 @@ static int mxt_prepare_cfg_mem(struct mxt_data *data,
|
|||
reg = object->start_address + mxt_obj_size(object) * instance;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
ret = sscanf(cfg->data + data_pos, "%hhx%n",
|
||||
ret = sscanf(cfg->raw + cfg->raw_pos, "%hhx%n",
|
||||
&val,
|
||||
&offset);
|
||||
if (ret != 1) {
|
||||
|
@ -1362,15 +1377,15 @@ static int mxt_prepare_cfg_mem(struct mxt_data *data,
|
|||
type, i);
|
||||
return -EINVAL;
|
||||
}
|
||||
data_pos += offset;
|
||||
cfg->raw_pos += offset;
|
||||
|
||||
if (i > mxt_obj_size(object))
|
||||
continue;
|
||||
|
||||
byte_offset = reg + i - cfg_start_ofs;
|
||||
byte_offset = reg + i - cfg->start_ofs;
|
||||
|
||||
if (byte_offset >= 0 && byte_offset < config_mem_size) {
|
||||
*(config_mem + byte_offset) = val;
|
||||
if (byte_offset >= 0 && byte_offset < cfg->mem_size) {
|
||||
*(cfg->mem + byte_offset) = val;
|
||||
} else {
|
||||
dev_err(dev, "Bad object: reg:%d, T%d, ofs=%d\n",
|
||||
reg, object->type, byte_offset);
|
||||
|
@ -1382,22 +1397,21 @@ static int mxt_prepare_cfg_mem(struct mxt_data *data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mxt_upload_cfg_mem(struct mxt_data *data, unsigned int cfg_start,
|
||||
u8 *config_mem, size_t config_mem_size)
|
||||
static int mxt_upload_cfg_mem(struct mxt_data *data, struct mxt_cfg *cfg)
|
||||
{
|
||||
unsigned int byte_offset = 0;
|
||||
int error;
|
||||
|
||||
/* Write configuration as blocks */
|
||||
while (byte_offset < config_mem_size) {
|
||||
unsigned int size = config_mem_size - byte_offset;
|
||||
while (byte_offset < cfg->mem_size) {
|
||||
unsigned int size = cfg->mem_size - byte_offset;
|
||||
|
||||
if (size > MXT_MAX_BLOCK_WRITE)
|
||||
size = MXT_MAX_BLOCK_WRITE;
|
||||
|
||||
error = __mxt_write_reg(data->client,
|
||||
cfg_start + byte_offset,
|
||||
size, config_mem + byte_offset);
|
||||
cfg->start_ofs + byte_offset,
|
||||
size, cfg->mem + byte_offset);
|
||||
if (error) {
|
||||
dev_err(&data->client->dev,
|
||||
"Config write error, ret=%d\n", error);
|
||||
|
@ -1431,65 +1445,75 @@ static int mxt_init_t7_power_cfg(struct mxt_data *data);
|
|||
* <SIZE> - 2-byte object size as hex
|
||||
* <CONTENTS> - array of <SIZE> 1-byte hex values
|
||||
*/
|
||||
static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg)
|
||||
static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw)
|
||||
{
|
||||
struct device *dev = &data->client->dev;
|
||||
struct mxt_info cfg_info;
|
||||
struct mxt_cfg cfg;
|
||||
int ret;
|
||||
int offset;
|
||||
int data_pos;
|
||||
int i;
|
||||
int cfg_start_ofs;
|
||||
u32 info_crc, config_crc, calculated_crc;
|
||||
u8 *config_mem;
|
||||
size_t config_mem_size;
|
||||
u16 crc_start = 0;
|
||||
|
||||
/* Make zero terminated copy of the OBP_RAW file */
|
||||
cfg.raw = kmemdup_nul(fw->data, fw->size, GFP_KERNEL);
|
||||
if (!cfg.raw)
|
||||
return -ENOMEM;
|
||||
|
||||
cfg.raw_size = fw->size;
|
||||
|
||||
mxt_update_crc(data, MXT_COMMAND_REPORTALL, 1);
|
||||
|
||||
if (strncmp(cfg->data, MXT_CFG_MAGIC, strlen(MXT_CFG_MAGIC))) {
|
||||
if (strncmp(cfg.raw, MXT_CFG_MAGIC, strlen(MXT_CFG_MAGIC))) {
|
||||
dev_err(dev, "Unrecognised config file\n");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto release_raw;
|
||||
}
|
||||
|
||||
data_pos = strlen(MXT_CFG_MAGIC);
|
||||
cfg.raw_pos = strlen(MXT_CFG_MAGIC);
|
||||
|
||||
/* Load information block and check */
|
||||
for (i = 0; i < sizeof(struct mxt_info); i++) {
|
||||
ret = sscanf(cfg->data + data_pos, "%hhx%n",
|
||||
(unsigned char *)&cfg_info + i,
|
||||
ret = sscanf(cfg.raw + cfg.raw_pos, "%hhx%n",
|
||||
(unsigned char *)&cfg.info + i,
|
||||
&offset);
|
||||
if (ret != 1) {
|
||||
dev_err(dev, "Bad format\n");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto release_raw;
|
||||
}
|
||||
|
||||
data_pos += offset;
|
||||
cfg.raw_pos += offset;
|
||||
}
|
||||
|
||||
if (cfg_info.family_id != data->info->family_id) {
|
||||
if (cfg.info.family_id != data->info->family_id) {
|
||||
dev_err(dev, "Family ID mismatch!\n");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto release_raw;
|
||||
}
|
||||
|
||||
if (cfg_info.variant_id != data->info->variant_id) {
|
||||
if (cfg.info.variant_id != data->info->variant_id) {
|
||||
dev_err(dev, "Variant ID mismatch!\n");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto release_raw;
|
||||
}
|
||||
|
||||
/* Read CRCs */
|
||||
ret = sscanf(cfg->data + data_pos, "%x%n", &info_crc, &offset);
|
||||
ret = sscanf(cfg.raw + cfg.raw_pos, "%x%n", &info_crc, &offset);
|
||||
if (ret != 1) {
|
||||
dev_err(dev, "Bad format: failed to parse Info CRC\n");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto release_raw;
|
||||
}
|
||||
data_pos += offset;
|
||||
cfg.raw_pos += offset;
|
||||
|
||||
ret = sscanf(cfg->data + data_pos, "%x%n", &config_crc, &offset);
|
||||
ret = sscanf(cfg.raw + cfg.raw_pos, "%x%n", &config_crc, &offset);
|
||||
if (ret != 1) {
|
||||
dev_err(dev, "Bad format: failed to parse Config CRC\n");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto release_raw;
|
||||
}
|
||||
data_pos += offset;
|
||||
cfg.raw_pos += offset;
|
||||
|
||||
/*
|
||||
* The Info Block CRC is calculated over mxt_info and the object
|
||||
|
@ -1515,39 +1539,39 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg)
|
|||
}
|
||||
|
||||
/* Malloc memory to store configuration */
|
||||
cfg_start_ofs = MXT_OBJECT_START +
|
||||
cfg.start_ofs = MXT_OBJECT_START +
|
||||
data->info->object_num * sizeof(struct mxt_object) +
|
||||
MXT_INFO_CHECKSUM_SIZE;
|
||||
config_mem_size = data->mem_size - cfg_start_ofs;
|
||||
config_mem = kzalloc(config_mem_size, GFP_KERNEL);
|
||||
if (!config_mem) {
|
||||
dev_err(dev, "Failed to allocate memory\n");
|
||||
return -ENOMEM;
|
||||
cfg.mem_size = data->mem_size - cfg.start_ofs;
|
||||
cfg.mem = kzalloc(cfg.mem_size, GFP_KERNEL);
|
||||
if (!cfg.mem) {
|
||||
ret = -ENOMEM;
|
||||
goto release_raw;
|
||||
}
|
||||
|
||||
ret = mxt_prepare_cfg_mem(data, cfg, data_pos, cfg_start_ofs,
|
||||
config_mem, config_mem_size);
|
||||
ret = mxt_prepare_cfg_mem(data, &cfg);
|
||||
if (ret)
|
||||
goto release_mem;
|
||||
|
||||
/* Calculate crc of the received configs (not the raw config file) */
|
||||
if (data->T7_address < cfg_start_ofs) {
|
||||
dev_err(dev, "Bad T7 address, T7addr = %x, config offset %x\n",
|
||||
data->T7_address, cfg_start_ofs);
|
||||
ret = 0;
|
||||
goto release_mem;
|
||||
if (data->T71_address)
|
||||
crc_start = data->T71_address;
|
||||
else if (data->T7_address)
|
||||
crc_start = data->T7_address;
|
||||
else
|
||||
dev_warn(dev, "Could not find CRC start\n");
|
||||
|
||||
if (crc_start > cfg.start_ofs) {
|
||||
calculated_crc = mxt_calculate_crc(cfg.mem,
|
||||
crc_start - cfg.start_ofs,
|
||||
cfg.mem_size);
|
||||
|
||||
if (config_crc > 0 && config_crc != calculated_crc)
|
||||
dev_warn(dev, "Config CRC in file inconsistent, calculated=%06X, file=%06X\n",
|
||||
calculated_crc, config_crc);
|
||||
}
|
||||
|
||||
calculated_crc = mxt_calculate_crc(config_mem,
|
||||
data->T7_address - cfg_start_ofs,
|
||||
config_mem_size);
|
||||
|
||||
if (config_crc > 0 && config_crc != calculated_crc)
|
||||
dev_warn(dev, "Config CRC error, calculated=%06X, file=%06X\n",
|
||||
calculated_crc, config_crc);
|
||||
|
||||
ret = mxt_upload_cfg_mem(data, cfg_start_ofs,
|
||||
config_mem, config_mem_size);
|
||||
ret = mxt_upload_cfg_mem(data, &cfg);
|
||||
if (ret)
|
||||
goto release_mem;
|
||||
|
||||
|
@ -1562,8 +1586,10 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg)
|
|||
/* T7 config may have changed */
|
||||
mxt_init_t7_power_cfg(data);
|
||||
|
||||
release_raw:
|
||||
kfree(cfg.raw);
|
||||
release_mem:
|
||||
kfree(config_mem);
|
||||
kfree(cfg.mem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1591,6 +1617,7 @@ static void mxt_free_object_table(struct mxt_data *data)
|
|||
data->T5_msg_size = 0;
|
||||
data->T6_reportid = 0;
|
||||
data->T7_address = 0;
|
||||
data->T71_address = 0;
|
||||
data->T9_reportid_min = 0;
|
||||
data->T9_reportid_max = 0;
|
||||
data->T19_reportid = 0;
|
||||
|
@ -1656,12 +1683,16 @@ static int mxt_parse_object_table(struct mxt_data *data,
|
|||
case MXT_GEN_POWER_T7:
|
||||
data->T7_address = object->start_address;
|
||||
break;
|
||||
case MXT_SPT_DYNAMICCONFIGURATIONCONTAINER_T71:
|
||||
data->T71_address = object->start_address;
|
||||
break;
|
||||
case MXT_TOUCH_MULTI_T9:
|
||||
data->multitouch = MXT_TOUCH_MULTI_T9;
|
||||
/* Only handle messages from first T9 instance */
|
||||
data->T9_reportid_min = min_id;
|
||||
data->T9_reportid_max = max_id;
|
||||
data->num_touchids = object->num_report_ids
|
||||
* mxt_obj_instances(object);
|
||||
data->T9_reportid_max = min_id +
|
||||
object->num_report_ids - 1;
|
||||
data->num_touchids = object->num_report_ids;
|
||||
break;
|
||||
case MXT_SPT_MESSAGECOUNT_T44:
|
||||
data->T44_address = object->start_address;
|
||||
|
@ -1981,10 +2012,8 @@ static int mxt_initialize_input_device(struct mxt_data *data)
|
|||
|
||||
/* Register input device */
|
||||
input_dev = input_allocate_device();
|
||||
if (!input_dev) {
|
||||
dev_err(dev, "Failed to allocate memory\n");
|
||||
if (!input_dev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
input_dev->name = "Atmel maXTouch Touchscreen";
|
||||
input_dev->phys = data->phys;
|
||||
|
@ -2054,12 +2083,6 @@ static int mxt_initialize_input_device(struct mxt_data *data)
|
|||
0, 255, 0, 0);
|
||||
}
|
||||
|
||||
if (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 &&
|
||||
data->t100_aux_ampl) {
|
||||
input_set_abs_params(input_dev, ABS_MT_PRESSURE,
|
||||
0, 255, 0, 0);
|
||||
}
|
||||
|
||||
if (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 &&
|
||||
data->t100_aux_vect) {
|
||||
input_set_abs_params(input_dev, ABS_MT_ORIENTATION,
|
||||
|
|
|
@ -0,0 +1,484 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Rohm BU21029 touchscreen controller driver
|
||||
*
|
||||
* Copyright (C) 2015-2018 Bosch Sicherheitssysteme 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/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/touchscreen.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/timer.h>
|
||||
|
||||
/*
|
||||
* HW_ID1 Register (PAGE=0, ADDR=0x0E, Reset value=0x02, Read only)
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
* | HW_IDH |
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
* HW_ID2 Register (PAGE=0, ADDR=0x0F, Reset value=0x29, Read only)
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
* | HW_IDL |
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
* HW_IDH: high 8bits of IC's ID
|
||||
* HW_IDL: low 8bits of IC's ID
|
||||
*/
|
||||
#define BU21029_HWID_REG (0x0E << 3)
|
||||
#define SUPPORTED_HWID 0x0229
|
||||
|
||||
/*
|
||||
* CFR0 Register (PAGE=0, ADDR=0x00, Reset value=0x20)
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
* | 0 | 0 | CALIB | INTRM | 0 | 0 | 0 | 0 |
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
* CALIB: 0 = not to use calibration result (*)
|
||||
* 1 = use calibration result
|
||||
* INTRM: 0 = INT output depend on "pen down" (*)
|
||||
* 1 = INT output always "0"
|
||||
*/
|
||||
#define BU21029_CFR0_REG (0x00 << 3)
|
||||
#define CFR0_VALUE 0x00
|
||||
|
||||
/*
|
||||
* CFR1 Register (PAGE=0, ADDR=0x01, Reset value=0xA6)
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
* | MAV | AVE[2:0] | 0 | SMPL[2:0] |
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
* MAV: 0 = median average filter off
|
||||
* 1 = median average filter on (*)
|
||||
* AVE: AVE+1 = number of average samples for MAV,
|
||||
* if AVE>SMPL, then AVE=SMPL (=3)
|
||||
* SMPL: SMPL+1 = number of conversion samples for MAV (=7)
|
||||
*/
|
||||
#define BU21029_CFR1_REG (0x01 << 3)
|
||||
#define CFR1_VALUE 0xA6
|
||||
|
||||
/*
|
||||
* CFR2 Register (PAGE=0, ADDR=0x02, Reset value=0x04)
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
* | INTVL_TIME[3:0] | TIME_ST_ADC[3:0] |
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
* INTVL_TIME: waiting time between completion of conversion
|
||||
* and start of next conversion, only usable in
|
||||
* autoscan mode (=20.480ms)
|
||||
* TIME_ST_ADC: waiting time between application of voltage
|
||||
* to panel and start of A/D conversion (=100us)
|
||||
*/
|
||||
#define BU21029_CFR2_REG (0x02 << 3)
|
||||
#define CFR2_VALUE 0xC9
|
||||
|
||||
/*
|
||||
* CFR3 Register (PAGE=0, ADDR=0x0B, Reset value=0x72)
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
* | RM8 | STRETCH| PU90K | DUAL | PIDAC_OFS[3:0] |
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
* RM8: 0 = coordinate resolution is 12bit (*)
|
||||
* 1 = coordinate resolution is 8bit
|
||||
* STRETCH: 0 = SCL_STRETCH function off
|
||||
* 1 = SCL_STRETCH function on (*)
|
||||
* PU90K: 0 = internal pull-up resistance for touch detection is ~50kohms (*)
|
||||
* 1 = internal pull-up resistance for touch detection is ~90kohms
|
||||
* DUAL: 0 = dual touch detection off (*)
|
||||
* 1 = dual touch detection on
|
||||
* PIDAC_OFS: dual touch detection circuit adjustment, it is not necessary
|
||||
* to change this from initial value
|
||||
*/
|
||||
#define BU21029_CFR3_REG (0x0B << 3)
|
||||
#define CFR3_VALUE 0x42
|
||||
|
||||
/*
|
||||
* LDO Register (PAGE=0, ADDR=0x0C, Reset value=0x00)
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
* | 0 | PVDD[2:0] | 0 | AVDD[2:0] |
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
* PVDD: output voltage of panel output regulator (=2.000V)
|
||||
* AVDD: output voltage of analog circuit regulator (=2.000V)
|
||||
*/
|
||||
#define BU21029_LDO_REG (0x0C << 3)
|
||||
#define LDO_VALUE 0x77
|
||||
|
||||
/*
|
||||
* Serial Interface Command Byte 1 (CID=1)
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
* | 1 | CF | CMSK | PDM | STP |
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
* CF: conversion function, see table 3 in datasheet p6 (=0000, automatic scan)
|
||||
* CMSK: 0 = executes convert function (*)
|
||||
* 1 = reads the convert result
|
||||
* PDM: 0 = power down after convert function stops (*)
|
||||
* 1 = keep power on after convert function stops
|
||||
* STP: 1 = abort current conversion and power down, set to "0" automatically
|
||||
*/
|
||||
#define BU21029_AUTOSCAN 0x80
|
||||
|
||||
/*
|
||||
* The timeout value needs to be larger than INTVL_TIME + tConv4 (sample and
|
||||
* conversion time), where tConv4 is calculated by formula:
|
||||
* tPON + tDLY1 + (tTIME_ST_ADC + (tADC * tSMPL) * 2 + tDLY2) * 3
|
||||
* see figure 8 in datasheet p15 for details of each field.
|
||||
*/
|
||||
#define PEN_UP_TIMEOUT_MS 50
|
||||
|
||||
#define STOP_DELAY_MIN_US 50
|
||||
#define STOP_DELAY_MAX_US 1000
|
||||
#define START_DELAY_MS 2
|
||||
#define BUF_LEN 8
|
||||
#define SCALE_12BIT (1 << 12)
|
||||
#define MAX_12BIT ((1 << 12) - 1)
|
||||
#define DRIVER_NAME "bu21029"
|
||||
|
||||
struct bu21029_ts_data {
|
||||
struct i2c_client *client;
|
||||
struct input_dev *in_dev;
|
||||
struct timer_list timer;
|
||||
struct regulator *vdd;
|
||||
struct gpio_desc *reset_gpios;
|
||||
u32 x_plate_ohms;
|
||||
struct touchscreen_properties prop;
|
||||
};
|
||||
|
||||
static void bu21029_touch_report(struct bu21029_ts_data *bu21029, const u8 *buf)
|
||||
{
|
||||
u16 x, y, z1, z2;
|
||||
u32 rz;
|
||||
s32 max_pressure = input_abs_get_max(bu21029->in_dev, ABS_PRESSURE);
|
||||
|
||||
/*
|
||||
* compose upper 8 and lower 4 bits into a 12bit value:
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
* | ByteH | ByteL |
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
* |b07|b06|b05|b04|b03|b02|b01|b00|b07|b06|b05|b04|b03|b02|b01|b00|
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
* |v11|v10|v09|v08|v07|v06|v05|v04|v03|v02|v01|v00| 0 | 0 | 0 | 0 |
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*/
|
||||
x = (buf[0] << 4) | (buf[1] >> 4);
|
||||
y = (buf[2] << 4) | (buf[3] >> 4);
|
||||
z1 = (buf[4] << 4) | (buf[5] >> 4);
|
||||
z2 = (buf[6] << 4) | (buf[7] >> 4);
|
||||
|
||||
if (z1 && z2) {
|
||||
/*
|
||||
* calculate Rz (pressure resistance value) by equation:
|
||||
* Rz = Rx * (x/Q) * ((z2/z1) - 1), where
|
||||
* Rx is x-plate resistance,
|
||||
* Q is the touch screen resolution (8bit = 256, 12bit = 4096)
|
||||
* x, z1, z2 are the measured positions.
|
||||
*/
|
||||
rz = z2 - z1;
|
||||
rz *= x;
|
||||
rz *= bu21029->x_plate_ohms;
|
||||
rz /= z1;
|
||||
rz = DIV_ROUND_CLOSEST(rz, SCALE_12BIT);
|
||||
if (rz <= max_pressure) {
|
||||
touchscreen_report_pos(bu21029->in_dev, &bu21029->prop,
|
||||
x, y, false);
|
||||
input_report_abs(bu21029->in_dev, ABS_PRESSURE,
|
||||
max_pressure - rz);
|
||||
input_report_key(bu21029->in_dev, BTN_TOUCH, 1);
|
||||
input_sync(bu21029->in_dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void bu21029_touch_release(struct timer_list *t)
|
||||
{
|
||||
struct bu21029_ts_data *bu21029 = from_timer(bu21029, t, timer);
|
||||
|
||||
input_report_abs(bu21029->in_dev, ABS_PRESSURE, 0);
|
||||
input_report_key(bu21029->in_dev, BTN_TOUCH, 0);
|
||||
input_sync(bu21029->in_dev);
|
||||
}
|
||||
|
||||
static irqreturn_t bu21029_touch_soft_irq(int irq, void *data)
|
||||
{
|
||||
struct bu21029_ts_data *bu21029 = data;
|
||||
u8 buf[BUF_LEN];
|
||||
int error;
|
||||
|
||||
/*
|
||||
* Read touch data and deassert interrupt (will assert again after
|
||||
* INTVL_TIME + tConv4 for continuous touch)
|
||||
*/
|
||||
error = i2c_smbus_read_i2c_block_data(bu21029->client, BU21029_AUTOSCAN,
|
||||
sizeof(buf), buf);
|
||||
if (error < 0)
|
||||
goto out;
|
||||
|
||||
bu21029_touch_report(bu21029, buf);
|
||||
|
||||
/* reset timer for pen up detection */
|
||||
mod_timer(&bu21029->timer,
|
||||
jiffies + msecs_to_jiffies(PEN_UP_TIMEOUT_MS));
|
||||
|
||||
out:
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void bu21029_put_chip_in_reset(struct bu21029_ts_data *bu21029)
|
||||
{
|
||||
if (bu21029->reset_gpios) {
|
||||
gpiod_set_value_cansleep(bu21029->reset_gpios, 1);
|
||||
usleep_range(STOP_DELAY_MIN_US, STOP_DELAY_MAX_US);
|
||||
}
|
||||
}
|
||||
|
||||
static int bu21029_start_chip(struct input_dev *dev)
|
||||
{
|
||||
struct bu21029_ts_data *bu21029 = input_get_drvdata(dev);
|
||||
struct i2c_client *i2c = bu21029->client;
|
||||
struct {
|
||||
u8 reg;
|
||||
u8 value;
|
||||
} init_table[] = {
|
||||
{BU21029_CFR0_REG, CFR0_VALUE},
|
||||
{BU21029_CFR1_REG, CFR1_VALUE},
|
||||
{BU21029_CFR2_REG, CFR2_VALUE},
|
||||
{BU21029_CFR3_REG, CFR3_VALUE},
|
||||
{BU21029_LDO_REG, LDO_VALUE}
|
||||
};
|
||||
int error, i;
|
||||
__be16 hwid;
|
||||
|
||||
error = regulator_enable(bu21029->vdd);
|
||||
if (error) {
|
||||
dev_err(&i2c->dev, "failed to power up chip: %d", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
/* take chip out of reset */
|
||||
if (bu21029->reset_gpios) {
|
||||
gpiod_set_value_cansleep(bu21029->reset_gpios, 0);
|
||||
msleep(START_DELAY_MS);
|
||||
}
|
||||
|
||||
error = i2c_smbus_read_i2c_block_data(i2c, BU21029_HWID_REG,
|
||||
sizeof(hwid), (u8 *)&hwid);
|
||||
if (error < 0) {
|
||||
dev_err(&i2c->dev, "failed to read HW ID\n");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (be16_to_cpu(hwid) != SUPPORTED_HWID) {
|
||||
dev_err(&i2c->dev,
|
||||
"unsupported HW ID 0x%x\n", be16_to_cpu(hwid));
|
||||
error = -ENODEV;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(init_table); ++i) {
|
||||
error = i2c_smbus_write_byte_data(i2c,
|
||||
init_table[i].reg,
|
||||
init_table[i].value);
|
||||
if (error < 0) {
|
||||
dev_err(&i2c->dev,
|
||||
"failed to write %#02x to register %#02x: %d\n",
|
||||
init_table[i].value, init_table[i].reg,
|
||||
error);
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
|
||||
error = i2c_smbus_write_byte(i2c, BU21029_AUTOSCAN);
|
||||
if (error < 0) {
|
||||
dev_err(&i2c->dev, "failed to start autoscan\n");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
enable_irq(bu21029->client->irq);
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
bu21029_put_chip_in_reset(bu21029);
|
||||
regulator_disable(bu21029->vdd);
|
||||
return error;
|
||||
}
|
||||
|
||||
static void bu21029_stop_chip(struct input_dev *dev)
|
||||
{
|
||||
struct bu21029_ts_data *bu21029 = input_get_drvdata(dev);
|
||||
|
||||
disable_irq(bu21029->client->irq);
|
||||
del_timer_sync(&bu21029->timer);
|
||||
|
||||
bu21029_put_chip_in_reset(bu21029);
|
||||
regulator_disable(bu21029->vdd);
|
||||
}
|
||||
|
||||
static int bu21029_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct bu21029_ts_data *bu21029;
|
||||
struct input_dev *in_dev;
|
||||
int error;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_WRITE_BYTE |
|
||||
I2C_FUNC_SMBUS_WRITE_BYTE_DATA |
|
||||
I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
|
||||
dev_err(&client->dev,
|
||||
"i2c functionality support is not sufficient\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
bu21029 = devm_kzalloc(&client->dev, sizeof(*bu21029), GFP_KERNEL);
|
||||
if (!bu21029)
|
||||
return -ENOMEM;
|
||||
|
||||
error = device_property_read_u32(&client->dev, "rohm,x-plate-ohms",
|
||||
&bu21029->x_plate_ohms);
|
||||
if (error) {
|
||||
dev_err(&client->dev,
|
||||
"invalid 'x-plate-ohms' supplied: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
bu21029->vdd = devm_regulator_get(&client->dev, "vdd");
|
||||
if (IS_ERR(bu21029->vdd)) {
|
||||
error = PTR_ERR(bu21029->vdd);
|
||||
if (error != -EPROBE_DEFER)
|
||||
dev_err(&client->dev,
|
||||
"failed to acquire 'vdd' supply: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
bu21029->reset_gpios = devm_gpiod_get_optional(&client->dev,
|
||||
"reset", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(bu21029->reset_gpios)) {
|
||||
error = PTR_ERR(bu21029->reset_gpios);
|
||||
if (error != -EPROBE_DEFER)
|
||||
dev_err(&client->dev,
|
||||
"failed to acquire 'reset' gpio: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
in_dev = devm_input_allocate_device(&client->dev);
|
||||
if (!in_dev) {
|
||||
dev_err(&client->dev, "unable to allocate input device\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
bu21029->client = client;
|
||||
bu21029->in_dev = in_dev;
|
||||
timer_setup(&bu21029->timer, bu21029_touch_release, 0);
|
||||
|
||||
in_dev->name = DRIVER_NAME;
|
||||
in_dev->id.bustype = BUS_I2C;
|
||||
in_dev->open = bu21029_start_chip;
|
||||
in_dev->close = bu21029_stop_chip;
|
||||
|
||||
input_set_capability(in_dev, EV_KEY, BTN_TOUCH);
|
||||
input_set_abs_params(in_dev, ABS_X, 0, MAX_12BIT, 0, 0);
|
||||
input_set_abs_params(in_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
|
||||
input_set_abs_params(in_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
|
||||
touchscreen_parse_properties(in_dev, false, &bu21029->prop);
|
||||
|
||||
input_set_drvdata(in_dev, bu21029);
|
||||
|
||||
irq_set_status_flags(client->irq, IRQ_NOAUTOEN);
|
||||
error = devm_request_threaded_irq(&client->dev, client->irq,
|
||||
NULL, bu21029_touch_soft_irq,
|
||||
IRQF_ONESHOT, DRIVER_NAME, bu21029);
|
||||
if (error) {
|
||||
dev_err(&client->dev,
|
||||
"unable to request touch irq: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
error = input_register_device(in_dev);
|
||||
if (error) {
|
||||
dev_err(&client->dev,
|
||||
"unable to register input device: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, bu21029);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused bu21029_suspend(struct device *dev)
|
||||
{
|
||||
struct i2c_client *i2c = to_i2c_client(dev);
|
||||
struct bu21029_ts_data *bu21029 = i2c_get_clientdata(i2c);
|
||||
|
||||
if (!device_may_wakeup(dev)) {
|
||||
mutex_lock(&bu21029->in_dev->mutex);
|
||||
if (bu21029->in_dev->users)
|
||||
bu21029_stop_chip(bu21029->in_dev);
|
||||
mutex_unlock(&bu21029->in_dev->mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused bu21029_resume(struct device *dev)
|
||||
{
|
||||
struct i2c_client *i2c = to_i2c_client(dev);
|
||||
struct bu21029_ts_data *bu21029 = i2c_get_clientdata(i2c);
|
||||
|
||||
if (!device_may_wakeup(dev)) {
|
||||
mutex_lock(&bu21029->in_dev->mutex);
|
||||
if (bu21029->in_dev->users)
|
||||
bu21029_start_chip(bu21029->in_dev);
|
||||
mutex_unlock(&bu21029->in_dev->mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static SIMPLE_DEV_PM_OPS(bu21029_pm_ops, bu21029_suspend, bu21029_resume);
|
||||
|
||||
static const struct i2c_device_id bu21029_ids[] = {
|
||||
{ DRIVER_NAME, 0 },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, bu21029_ids);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id bu21029_of_ids[] = {
|
||||
{ .compatible = "rohm,bu21029" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bu21029_of_ids);
|
||||
#endif
|
||||
|
||||
static struct i2c_driver bu21029_driver = {
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.of_match_table = of_match_ptr(bu21029_of_ids),
|
||||
.pm = &bu21029_pm_ops,
|
||||
},
|
||||
.id_table = bu21029_ids,
|
||||
.probe = bu21029_probe,
|
||||
};
|
||||
module_i2c_driver(bu21029_driver);
|
||||
|
||||
MODULE_AUTHOR("Zhu Yi <yi.zhu5@cn.bosch.com>");
|
||||
MODULE_DESCRIPTION("Rohm BU21029 touchscreen controller driver");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
* Touch Screen driver for EETI's I2C connected touch screen panels
|
||||
* Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
|
||||
* Copyright (c) 2009,2018 Daniel Mack <daniel@zonque.org>
|
||||
*
|
||||
* See EETI's software guide for the protocol specification:
|
||||
* http://home.eeti.com.tw/web20/eg/guide.htm
|
||||
* http://home.eeti.com.tw/documentation.html
|
||||
*
|
||||
* Based on migor_ts.c
|
||||
* Copyright (c) 2008 Magnus Damm
|
||||
|
@ -25,28 +25,22 @@
|
|||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/touchscreen.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
static bool flip_x;
|
||||
module_param(flip_x, bool, 0644);
|
||||
MODULE_PARM_DESC(flip_x, "flip x coordinate");
|
||||
|
||||
static bool flip_y;
|
||||
module_param(flip_y, bool, 0644);
|
||||
MODULE_PARM_DESC(flip_y, "flip y coordinate");
|
||||
|
||||
struct eeti_ts {
|
||||
struct i2c_client *client;
|
||||
struct input_dev *input;
|
||||
struct gpio_desc *attn_gpio;
|
||||
struct touchscreen_properties props;
|
||||
bool running;
|
||||
};
|
||||
|
||||
|
@ -73,17 +67,10 @@ static void eeti_ts_report_event(struct eeti_ts *eeti, u8 *buf)
|
|||
x >>= res - EETI_TS_BITDEPTH;
|
||||
y >>= res - EETI_TS_BITDEPTH;
|
||||
|
||||
if (flip_x)
|
||||
x = EETI_MAXVAL - x;
|
||||
|
||||
if (flip_y)
|
||||
y = EETI_MAXVAL - y;
|
||||
|
||||
if (buf[0] & REPORT_BIT_HAS_PRESSURE)
|
||||
input_report_abs(eeti->input, ABS_PRESSURE, buf[5]);
|
||||
|
||||
input_report_abs(eeti->input, ABS_X, x);
|
||||
input_report_abs(eeti->input, ABS_Y, y);
|
||||
touchscreen_report_pos(eeti->input, &eeti->props, x, y, false);
|
||||
input_report_key(eeti->input, BTN_TOUCH, buf[0] & REPORT_BIT_PRESSED);
|
||||
input_sync(eeti->input);
|
||||
}
|
||||
|
@ -178,6 +165,8 @@ static int eeti_ts_probe(struct i2c_client *client,
|
|||
input_set_abs_params(input, ABS_Y, 0, EETI_MAXVAL, 0, 0);
|
||||
input_set_abs_params(input, ABS_PRESSURE, 0, 0xff, 0, 0);
|
||||
|
||||
touchscreen_parse_properties(input, false, &eeti->props);
|
||||
|
||||
input->name = client->name;
|
||||
input->id.bustype = BUS_I2C;
|
||||
input->open = eeti_ts_open;
|
||||
|
@ -262,10 +251,18 @@ static const struct i2c_device_id eeti_ts_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, eeti_ts_id);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id of_eeti_ts_match[] = {
|
||||
{ .compatible = "eeti,exc3000-i2c", },
|
||||
{ }
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct i2c_driver eeti_ts_driver = {
|
||||
.driver = {
|
||||
.name = "eeti_ts",
|
||||
.pm = &eeti_ts_pm,
|
||||
.of_match_table = of_match_ptr(of_eeti_ts_match),
|
||||
},
|
||||
.probe = eeti_ts_probe,
|
||||
.id_table = eeti_ts_id,
|
||||
|
@ -274,5 +271,5 @@ static struct i2c_driver eeti_ts_driver = {
|
|||
module_i2c_driver(eeti_ts_driver);
|
||||
|
||||
MODULE_DESCRIPTION("EETI Touchscreen driver");
|
||||
MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
|
||||
MODULE_AUTHOR("Daniel Mack <daniel@zonque.org>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Driver for EETI eGalax Multiple Touch Controller
|
||||
*
|
||||
* Copyright (C) 2011 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* based on max11801_ts.c
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* EETI eGalax serial touch screen controller is a I2C based multiple
|
||||
|
|
|
@ -352,6 +352,7 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv)
|
|||
|
||||
case 1: /* 6-byte protocol */
|
||||
input_set_abs_params(input_dev, ABS_PRESSURE, 0, 15, 0, 0);
|
||||
/* fall through */
|
||||
|
||||
case 2: /* 4-byte protocol */
|
||||
input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0);
|
||||
|
|
|
@ -1,16 +1,11 @@
|
|||
/*
|
||||
* Copyright (C) 2014-2015 Pengutronix, Markus Pargmann <mpa@pengutronix.de>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Based on driver from 2011:
|
||||
* Juergen Beisert, Pengutronix <kernel@pengutronix.de>
|
||||
*
|
||||
* This is the driver for the imx25 TCQ (Touchscreen Conversion Queue)
|
||||
* connected to the imx25 ADC.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// Copyright (C) 2014-2015 Pengutronix, Markus Pargmann <mpa@pengutronix.de>
|
||||
// Based on driver from 2011:
|
||||
// Juergen Beisert, Pengutronix <kernel@pengutronix.de>
|
||||
//
|
||||
// This is the driver for the imx25 TCQ (Touchscreen Conversion Queue)
|
||||
// connected to the imx25 ADC.
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
|
|
|
@ -20,10 +20,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
/*
|
||||
* Freescale i.MX6UL touchscreen controller driver
|
||||
*
|
||||
* Copyright (C) 2015 Freescale Semiconductor, 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.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// Freescale i.MX6UL touchscreen controller driver
|
||||
//
|
||||
// Copyright (C) 2015 Freescale Semiconductor, Inc.
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
|
|
|
@ -466,7 +466,7 @@ static bool raydium_i2c_boot_trigger(struct i2c_client *client)
|
|||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool raydium_i2c_fw_trigger(struct i2c_client *client)
|
||||
|
@ -492,7 +492,7 @@ static bool raydium_i2c_fw_trigger(struct i2c_client *client)
|
|||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static int raydium_i2c_check_path(struct i2c_client *client)
|
||||
|
|
|
@ -1142,7 +1142,7 @@ static int __maybe_unused wdt87xx_resume(struct device *dev)
|
|||
* The chip may have been reset while system is resuming,
|
||||
* give it some time to settle.
|
||||
*/
|
||||
mdelay(100);
|
||||
msleep(100);
|
||||
|
||||
error = wdt87xx_send_command(client, VND_CMD_START, 0);
|
||||
if (error)
|
||||
|
|
|
@ -3859,7 +3859,7 @@ static int __load_dirty_region_bitmap(struct raid_set *rs)
|
|||
/* Try loading the bitmap unless "raid0", which does not have one */
|
||||
if (!rs_is_raid0(rs) &&
|
||||
!test_and_set_bit(RT_FLAG_RS_BITMAP_LOADED, &rs->runtime_flags)) {
|
||||
r = bitmap_load(&rs->md);
|
||||
r = md_bitmap_load(&rs->md);
|
||||
if (r)
|
||||
DMERR("Failed to load bitmap");
|
||||
}
|
||||
|
@ -3987,8 +3987,8 @@ static int raid_preresume(struct dm_target *ti)
|
|||
/* Resize bitmap to adjust to changed region size (aka MD bitmap chunksize) */
|
||||
if (test_bit(RT_FLAG_RS_BITMAP_LOADED, &rs->runtime_flags) && mddev->bitmap &&
|
||||
mddev->bitmap_info.chunksize != to_bytes(rs->requested_bitmap_chunk_sectors)) {
|
||||
r = bitmap_resize(mddev->bitmap, mddev->dev_sectors,
|
||||
to_bytes(rs->requested_bitmap_chunk_sectors), 0);
|
||||
r = md_bitmap_resize(mddev->bitmap, mddev->dev_sectors,
|
||||
to_bytes(rs->requested_bitmap_chunk_sectors), 0);
|
||||
if (r)
|
||||
DMERR("Failed to resize bitmap");
|
||||
}
|
||||
|
|
|
@ -46,8 +46,8 @@ static inline char *bmname(struct bitmap *bitmap)
|
|||
* if we find our page, we increment the page's refcount so that it stays
|
||||
* allocated while we're using it
|
||||
*/
|
||||
static int bitmap_checkpage(struct bitmap_counts *bitmap,
|
||||
unsigned long page, int create, int no_hijack)
|
||||
static int md_bitmap_checkpage(struct bitmap_counts *bitmap,
|
||||
unsigned long page, int create, int no_hijack)
|
||||
__releases(bitmap->lock)
|
||||
__acquires(bitmap->lock)
|
||||
{
|
||||
|
@ -115,7 +115,7 @@ __acquires(bitmap->lock)
|
|||
/* if page is completely empty, put it back on the free list, or dealloc it */
|
||||
/* if page was hijacked, unmark the flag so it might get alloced next time */
|
||||
/* Note: lock should be held when calling this */
|
||||
static void bitmap_checkfree(struct bitmap_counts *bitmap, unsigned long page)
|
||||
static void md_bitmap_checkfree(struct bitmap_counts *bitmap, unsigned long page)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
|
@ -280,7 +280,7 @@ static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void bitmap_file_kick(struct bitmap *bitmap);
|
||||
static void md_bitmap_file_kick(struct bitmap *bitmap);
|
||||
/*
|
||||
* write out a page to a file
|
||||
*/
|
||||
|
@ -310,7 +310,7 @@ static void write_page(struct bitmap *bitmap, struct page *page, int wait)
|
|||
atomic_read(&bitmap->pending_writes)==0);
|
||||
}
|
||||
if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags))
|
||||
bitmap_file_kick(bitmap);
|
||||
md_bitmap_file_kick(bitmap);
|
||||
}
|
||||
|
||||
static void end_bitmap_write(struct buffer_head *bh, int uptodate)
|
||||
|
@ -421,11 +421,11 @@ static int read_page(struct file *file, unsigned long index,
|
|||
*/
|
||||
|
||||
/*
|
||||
* bitmap_wait_writes() should be called before writing any bitmap
|
||||
* md_bitmap_wait_writes() should be called before writing any bitmap
|
||||
* blocks, to ensure previous writes, particularly from
|
||||
* bitmap_daemon_work(), have completed.
|
||||
* md_bitmap_daemon_work(), have completed.
|
||||
*/
|
||||
static void bitmap_wait_writes(struct bitmap *bitmap)
|
||||
static void md_bitmap_wait_writes(struct bitmap *bitmap)
|
||||
{
|
||||
if (bitmap->storage.file)
|
||||
wait_event(bitmap->write_wait,
|
||||
|
@ -443,7 +443,7 @@ static void bitmap_wait_writes(struct bitmap *bitmap)
|
|||
|
||||
|
||||
/* update the event counter and sync the superblock to disk */
|
||||
void bitmap_update_sb(struct bitmap *bitmap)
|
||||
void md_bitmap_update_sb(struct bitmap *bitmap)
|
||||
{
|
||||
bitmap_super_t *sb;
|
||||
|
||||
|
@ -476,10 +476,10 @@ void bitmap_update_sb(struct bitmap *bitmap)
|
|||
kunmap_atomic(sb);
|
||||
write_page(bitmap, bitmap->storage.sb_page, 1);
|
||||
}
|
||||
EXPORT_SYMBOL(bitmap_update_sb);
|
||||
EXPORT_SYMBOL(md_bitmap_update_sb);
|
||||
|
||||
/* print out the bitmap file superblock */
|
||||
void bitmap_print_sb(struct bitmap *bitmap)
|
||||
void md_bitmap_print_sb(struct bitmap *bitmap)
|
||||
{
|
||||
bitmap_super_t *sb;
|
||||
|
||||
|
@ -518,7 +518,7 @@ void bitmap_print_sb(struct bitmap *bitmap)
|
|||
*
|
||||
* Returns: 0 on success, -Exxx on error
|
||||
*/
|
||||
static int bitmap_new_disk_sb(struct bitmap *bitmap)
|
||||
static int md_bitmap_new_disk_sb(struct bitmap *bitmap)
|
||||
{
|
||||
bitmap_super_t *sb;
|
||||
unsigned long chunksize, daemon_sleep, write_behind;
|
||||
|
@ -577,7 +577,7 @@ static int bitmap_new_disk_sb(struct bitmap *bitmap)
|
|||
}
|
||||
|
||||
/* read the superblock from the bitmap file and initialize some bitmap fields */
|
||||
static int bitmap_read_sb(struct bitmap *bitmap)
|
||||
static int md_bitmap_read_sb(struct bitmap *bitmap)
|
||||
{
|
||||
char *reason = NULL;
|
||||
bitmap_super_t *sb;
|
||||
|
@ -727,7 +727,7 @@ static int bitmap_read_sb(struct bitmap *bitmap)
|
|||
bitmap->mddev->bitmap_info.space > sectors_reserved)
|
||||
bitmap->mddev->bitmap_info.space = sectors_reserved;
|
||||
if (err) {
|
||||
bitmap_print_sb(bitmap);
|
||||
md_bitmap_print_sb(bitmap);
|
||||
if (bitmap->cluster_slot < 0)
|
||||
md_cluster_stop(bitmap->mddev);
|
||||
}
|
||||
|
@ -774,9 +774,9 @@ static inline struct page *filemap_get_page(struct bitmap_storage *store,
|
|||
return store->filemap[file_page_index(store, chunk)];
|
||||
}
|
||||
|
||||
static int bitmap_storage_alloc(struct bitmap_storage *store,
|
||||
unsigned long chunks, int with_super,
|
||||
int slot_number)
|
||||
static int md_bitmap_storage_alloc(struct bitmap_storage *store,
|
||||
unsigned long chunks, int with_super,
|
||||
int slot_number)
|
||||
{
|
||||
int pnum, offset = 0;
|
||||
unsigned long num_pages;
|
||||
|
@ -830,7 +830,7 @@ static int bitmap_storage_alloc(struct bitmap_storage *store,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void bitmap_file_unmap(struct bitmap_storage *store)
|
||||
static void md_bitmap_file_unmap(struct bitmap_storage *store)
|
||||
{
|
||||
struct page **map, *sb_page;
|
||||
int pages;
|
||||
|
@ -862,12 +862,12 @@ static void bitmap_file_unmap(struct bitmap_storage *store)
|
|||
* then it is no longer reliable, so we stop using it and we mark the file
|
||||
* as failed in the superblock
|
||||
*/
|
||||
static void bitmap_file_kick(struct bitmap *bitmap)
|
||||
static void md_bitmap_file_kick(struct bitmap *bitmap)
|
||||
{
|
||||
char *path, *ptr = NULL;
|
||||
|
||||
if (!test_and_set_bit(BITMAP_STALE, &bitmap->flags)) {
|
||||
bitmap_update_sb(bitmap);
|
||||
md_bitmap_update_sb(bitmap);
|
||||
|
||||
if (bitmap->storage.file) {
|
||||
path = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
|
@ -923,7 +923,7 @@ static inline int test_and_clear_page_attr(struct bitmap *bitmap, int pnum,
|
|||
* we set the bit immediately, then we record the page number so that
|
||||
* when an unplug occurs, we can flush the dirty pages out to disk
|
||||
*/
|
||||
static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
|
||||
static void md_bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
|
||||
{
|
||||
unsigned long bit;
|
||||
struct page *page;
|
||||
|
@ -952,7 +952,7 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
|
|||
set_page_attr(bitmap, page->index - node_offset, BITMAP_PAGE_DIRTY);
|
||||
}
|
||||
|
||||
static void bitmap_file_clear_bit(struct bitmap *bitmap, sector_t block)
|
||||
static void md_bitmap_file_clear_bit(struct bitmap *bitmap, sector_t block)
|
||||
{
|
||||
unsigned long bit;
|
||||
struct page *page;
|
||||
|
@ -980,7 +980,7 @@ static void bitmap_file_clear_bit(struct bitmap *bitmap, sector_t block)
|
|||
}
|
||||
}
|
||||
|
||||
static int bitmap_file_test_bit(struct bitmap *bitmap, sector_t block)
|
||||
static int md_bitmap_file_test_bit(struct bitmap *bitmap, sector_t block)
|
||||
{
|
||||
unsigned long bit;
|
||||
struct page *page;
|
||||
|
@ -1005,7 +1005,7 @@ static int bitmap_file_test_bit(struct bitmap *bitmap, sector_t block)
|
|||
/* this gets called when the md device is ready to unplug its underlying
|
||||
* (slave) device queues -- before we let any writes go down, we need to
|
||||
* sync the dirty pages of the bitmap file to disk */
|
||||
void bitmap_unplug(struct bitmap *bitmap)
|
||||
void md_bitmap_unplug(struct bitmap *bitmap)
|
||||
{
|
||||
unsigned long i;
|
||||
int dirty, need_write;
|
||||
|
@ -1025,7 +1025,7 @@ void bitmap_unplug(struct bitmap *bitmap)
|
|||
BITMAP_PAGE_NEEDWRITE);
|
||||
if (dirty || need_write) {
|
||||
if (!writing) {
|
||||
bitmap_wait_writes(bitmap);
|
||||
md_bitmap_wait_writes(bitmap);
|
||||
if (bitmap->mddev->queue)
|
||||
blk_add_trace_msg(bitmap->mddev->queue,
|
||||
"md bitmap_unplug");
|
||||
|
@ -1036,14 +1036,14 @@ void bitmap_unplug(struct bitmap *bitmap)
|
|||
}
|
||||
}
|
||||
if (writing)
|
||||
bitmap_wait_writes(bitmap);
|
||||
md_bitmap_wait_writes(bitmap);
|
||||
|
||||
if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags))
|
||||
bitmap_file_kick(bitmap);
|
||||
md_bitmap_file_kick(bitmap);
|
||||
}
|
||||
EXPORT_SYMBOL(bitmap_unplug);
|
||||
EXPORT_SYMBOL(md_bitmap_unplug);
|
||||
|
||||
static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed);
|
||||
static void md_bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed);
|
||||
/* * bitmap_init_from_disk -- called at bitmap_create time to initialize
|
||||
* the in-memory bitmap from the on-disk bitmap -- also, sets up the
|
||||
* memory mapping of the bitmap file
|
||||
|
@ -1055,7 +1055,7 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int n
|
|||
* We ignore all bits for sectors that end earlier than 'start'.
|
||||
* This is used when reading an out-of-date bitmap...
|
||||
*/
|
||||
static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
|
||||
static int md_bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
|
||||
{
|
||||
unsigned long i, chunks, index, oldindex, bit, node_offset = 0;
|
||||
struct page *page = NULL;
|
||||
|
@ -1078,9 +1078,9 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
|
|||
/* if the disk bit is set, set the memory bit */
|
||||
int needed = ((sector_t)(i+1) << (bitmap->counts.chunkshift)
|
||||
>= start);
|
||||
bitmap_set_memory_bits(bitmap,
|
||||
(sector_t)i << bitmap->counts.chunkshift,
|
||||
needed);
|
||||
md_bitmap_set_memory_bits(bitmap,
|
||||
(sector_t)i << bitmap->counts.chunkshift,
|
||||
needed);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1159,9 +1159,9 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
|
|||
/* if the disk bit is set, set the memory bit */
|
||||
int needed = ((sector_t)(i+1) << bitmap->counts.chunkshift
|
||||
>= start);
|
||||
bitmap_set_memory_bits(bitmap,
|
||||
(sector_t)i << bitmap->counts.chunkshift,
|
||||
needed);
|
||||
md_bitmap_set_memory_bits(bitmap,
|
||||
(sector_t)i << bitmap->counts.chunkshift,
|
||||
needed);
|
||||
bit_cnt++;
|
||||
}
|
||||
offset = 0;
|
||||
|
@ -1179,7 +1179,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
|
|||
return ret;
|
||||
}
|
||||
|
||||
void bitmap_write_all(struct bitmap *bitmap)
|
||||
void md_bitmap_write_all(struct bitmap *bitmap)
|
||||
{
|
||||
/* We don't actually write all bitmap blocks here,
|
||||
* just flag them as needing to be written
|
||||
|
@ -1198,16 +1198,16 @@ void bitmap_write_all(struct bitmap *bitmap)
|
|||
bitmap->allclean = 0;
|
||||
}
|
||||
|
||||
static void bitmap_count_page(struct bitmap_counts *bitmap,
|
||||
sector_t offset, int inc)
|
||||
static void md_bitmap_count_page(struct bitmap_counts *bitmap,
|
||||
sector_t offset, int inc)
|
||||
{
|
||||
sector_t chunk = offset >> bitmap->chunkshift;
|
||||
unsigned long page = chunk >> PAGE_COUNTER_SHIFT;
|
||||
bitmap->bp[page].count += inc;
|
||||
bitmap_checkfree(bitmap, page);
|
||||
md_bitmap_checkfree(bitmap, page);
|
||||
}
|
||||
|
||||
static void bitmap_set_pending(struct bitmap_counts *bitmap, sector_t offset)
|
||||
static void md_bitmap_set_pending(struct bitmap_counts *bitmap, sector_t offset)
|
||||
{
|
||||
sector_t chunk = offset >> bitmap->chunkshift;
|
||||
unsigned long page = chunk >> PAGE_COUNTER_SHIFT;
|
||||
|
@ -1217,16 +1217,16 @@ static void bitmap_set_pending(struct bitmap_counts *bitmap, sector_t offset)
|
|||
bp->pending = 1;
|
||||
}
|
||||
|
||||
static bitmap_counter_t *bitmap_get_counter(struct bitmap_counts *bitmap,
|
||||
sector_t offset, sector_t *blocks,
|
||||
int create);
|
||||
static bitmap_counter_t *md_bitmap_get_counter(struct bitmap_counts *bitmap,
|
||||
sector_t offset, sector_t *blocks,
|
||||
int create);
|
||||
|
||||
/*
|
||||
* bitmap daemon -- periodically wakes up to clean bits and flush pages
|
||||
* out to disk
|
||||
*/
|
||||
|
||||
void bitmap_daemon_work(struct mddev *mddev)
|
||||
void md_bitmap_daemon_work(struct mddev *mddev)
|
||||
{
|
||||
struct bitmap *bitmap;
|
||||
unsigned long j;
|
||||
|
@ -1301,10 +1301,8 @@ void bitmap_daemon_work(struct mddev *mddev)
|
|||
}
|
||||
counts->bp[j >> PAGE_COUNTER_SHIFT].pending = 0;
|
||||
}
|
||||
bmc = bitmap_get_counter(counts,
|
||||
block,
|
||||
&blocks, 0);
|
||||
|
||||
bmc = md_bitmap_get_counter(counts, block, &blocks, 0);
|
||||
if (!bmc) {
|
||||
j |= PAGE_COUNTER_MASK;
|
||||
continue;
|
||||
|
@ -1312,17 +1310,17 @@ void bitmap_daemon_work(struct mddev *mddev)
|
|||
if (*bmc == 1 && !bitmap->need_sync) {
|
||||
/* We can clear the bit */
|
||||
*bmc = 0;
|
||||
bitmap_count_page(counts, block, -1);
|
||||
bitmap_file_clear_bit(bitmap, block);
|
||||
md_bitmap_count_page(counts, block, -1);
|
||||
md_bitmap_file_clear_bit(bitmap, block);
|
||||
} else if (*bmc && *bmc <= 2) {
|
||||
*bmc = 1;
|
||||
bitmap_set_pending(counts, block);
|
||||
md_bitmap_set_pending(counts, block);
|
||||
bitmap->allclean = 0;
|
||||
}
|
||||
}
|
||||
spin_unlock_irq(&counts->lock);
|
||||
|
||||
bitmap_wait_writes(bitmap);
|
||||
md_bitmap_wait_writes(bitmap);
|
||||
/* Now start writeout on any page in NEEDWRITE that isn't DIRTY.
|
||||
* DIRTY pages need to be written by bitmap_unplug so it can wait
|
||||
* for them.
|
||||
|
@ -1352,9 +1350,9 @@ void bitmap_daemon_work(struct mddev *mddev)
|
|||
mutex_unlock(&mddev->bitmap_info.mutex);
|
||||
}
|
||||
|
||||
static bitmap_counter_t *bitmap_get_counter(struct bitmap_counts *bitmap,
|
||||
sector_t offset, sector_t *blocks,
|
||||
int create)
|
||||
static bitmap_counter_t *md_bitmap_get_counter(struct bitmap_counts *bitmap,
|
||||
sector_t offset, sector_t *blocks,
|
||||
int create)
|
||||
__releases(bitmap->lock)
|
||||
__acquires(bitmap->lock)
|
||||
{
|
||||
|
@ -1368,7 +1366,7 @@ __acquires(bitmap->lock)
|
|||
sector_t csize;
|
||||
int err;
|
||||
|
||||
err = bitmap_checkpage(bitmap, page, create, 0);
|
||||
err = md_bitmap_checkpage(bitmap, page, create, 0);
|
||||
|
||||
if (bitmap->bp[page].hijacked ||
|
||||
bitmap->bp[page].map == NULL)
|
||||
|
@ -1394,7 +1392,7 @@ __acquires(bitmap->lock)
|
|||
&(bitmap->bp[page].map[pageoff]);
|
||||
}
|
||||
|
||||
int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors, int behind)
|
||||
int md_bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors, int behind)
|
||||
{
|
||||
if (!bitmap)
|
||||
return 0;
|
||||
|
@ -1415,7 +1413,7 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
|
|||
bitmap_counter_t *bmc;
|
||||
|
||||
spin_lock_irq(&bitmap->counts.lock);
|
||||
bmc = bitmap_get_counter(&bitmap->counts, offset, &blocks, 1);
|
||||
bmc = md_bitmap_get_counter(&bitmap->counts, offset, &blocks, 1);
|
||||
if (!bmc) {
|
||||
spin_unlock_irq(&bitmap->counts.lock);
|
||||
return 0;
|
||||
|
@ -1437,8 +1435,8 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
|
|||
|
||||
switch (*bmc) {
|
||||
case 0:
|
||||
bitmap_file_set_bit(bitmap, offset);
|
||||
bitmap_count_page(&bitmap->counts, offset, 1);
|
||||
md_bitmap_file_set_bit(bitmap, offset);
|
||||
md_bitmap_count_page(&bitmap->counts, offset, 1);
|
||||
/* fall through */
|
||||
case 1:
|
||||
*bmc = 2;
|
||||
|
@ -1456,10 +1454,10 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(bitmap_startwrite);
|
||||
EXPORT_SYMBOL(md_bitmap_startwrite);
|
||||
|
||||
void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors,
|
||||
int success, int behind)
|
||||
void md_bitmap_endwrite(struct bitmap *bitmap, sector_t offset,
|
||||
unsigned long sectors, int success, int behind)
|
||||
{
|
||||
if (!bitmap)
|
||||
return;
|
||||
|
@ -1477,7 +1475,7 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto
|
|||
bitmap_counter_t *bmc;
|
||||
|
||||
spin_lock_irqsave(&bitmap->counts.lock, flags);
|
||||
bmc = bitmap_get_counter(&bitmap->counts, offset, &blocks, 0);
|
||||
bmc = md_bitmap_get_counter(&bitmap->counts, offset, &blocks, 0);
|
||||
if (!bmc) {
|
||||
spin_unlock_irqrestore(&bitmap->counts.lock, flags);
|
||||
return;
|
||||
|
@ -1498,7 +1496,7 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto
|
|||
|
||||
(*bmc)--;
|
||||
if (*bmc <= 2) {
|
||||
bitmap_set_pending(&bitmap->counts, offset);
|
||||
md_bitmap_set_pending(&bitmap->counts, offset);
|
||||
bitmap->allclean = 0;
|
||||
}
|
||||
spin_unlock_irqrestore(&bitmap->counts.lock, flags);
|
||||
|
@ -1509,7 +1507,7 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto
|
|||
sectors = 0;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(bitmap_endwrite);
|
||||
EXPORT_SYMBOL(md_bitmap_endwrite);
|
||||
|
||||
static int __bitmap_start_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks,
|
||||
int degraded)
|
||||
|
@ -1521,7 +1519,7 @@ static int __bitmap_start_sync(struct bitmap *bitmap, sector_t offset, sector_t
|
|||
return 1; /* always resync if no bitmap */
|
||||
}
|
||||
spin_lock_irq(&bitmap->counts.lock);
|
||||
bmc = bitmap_get_counter(&bitmap->counts, offset, blocks, 0);
|
||||
bmc = md_bitmap_get_counter(&bitmap->counts, offset, blocks, 0);
|
||||
rv = 0;
|
||||
if (bmc) {
|
||||
/* locked */
|
||||
|
@ -1539,8 +1537,8 @@ static int __bitmap_start_sync(struct bitmap *bitmap, sector_t offset, sector_t
|
|||
return rv;
|
||||
}
|
||||
|
||||
int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks,
|
||||
int degraded)
|
||||
int md_bitmap_start_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks,
|
||||
int degraded)
|
||||
{
|
||||
/* bitmap_start_sync must always report on multiples of whole
|
||||
* pages, otherwise resync (which is very PAGE_SIZE based) will
|
||||
|
@ -1561,9 +1559,9 @@ int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks,
|
|||
}
|
||||
return rv;
|
||||
}
|
||||
EXPORT_SYMBOL(bitmap_start_sync);
|
||||
EXPORT_SYMBOL(md_bitmap_start_sync);
|
||||
|
||||
void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, int aborted)
|
||||
void md_bitmap_end_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, int aborted)
|
||||
{
|
||||
bitmap_counter_t *bmc;
|
||||
unsigned long flags;
|
||||
|
@ -1573,7 +1571,7 @@ void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, i
|
|||
return;
|
||||
}
|
||||
spin_lock_irqsave(&bitmap->counts.lock, flags);
|
||||
bmc = bitmap_get_counter(&bitmap->counts, offset, blocks, 0);
|
||||
bmc = md_bitmap_get_counter(&bitmap->counts, offset, blocks, 0);
|
||||
if (bmc == NULL)
|
||||
goto unlock;
|
||||
/* locked */
|
||||
|
@ -1584,7 +1582,7 @@ void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, i
|
|||
*bmc |= NEEDED_MASK;
|
||||
else {
|
||||
if (*bmc <= 2) {
|
||||
bitmap_set_pending(&bitmap->counts, offset);
|
||||
md_bitmap_set_pending(&bitmap->counts, offset);
|
||||
bitmap->allclean = 0;
|
||||
}
|
||||
}
|
||||
|
@ -1592,9 +1590,9 @@ void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, i
|
|||
unlock:
|
||||
spin_unlock_irqrestore(&bitmap->counts.lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(bitmap_end_sync);
|
||||
EXPORT_SYMBOL(md_bitmap_end_sync);
|
||||
|
||||
void bitmap_close_sync(struct bitmap *bitmap)
|
||||
void md_bitmap_close_sync(struct bitmap *bitmap)
|
||||
{
|
||||
/* Sync has finished, and any bitmap chunks that weren't synced
|
||||
* properly have been aborted. It remains to us to clear the
|
||||
|
@ -1605,13 +1603,13 @@ void bitmap_close_sync(struct bitmap *bitmap)
|
|||
if (!bitmap)
|
||||
return;
|
||||
while (sector < bitmap->mddev->resync_max_sectors) {
|
||||
bitmap_end_sync(bitmap, sector, &blocks, 0);
|
||||
md_bitmap_end_sync(bitmap, sector, &blocks, 0);
|
||||
sector += blocks;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(bitmap_close_sync);
|
||||
EXPORT_SYMBOL(md_bitmap_close_sync);
|
||||
|
||||
void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector, bool force)
|
||||
void md_bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector, bool force)
|
||||
{
|
||||
sector_t s = 0;
|
||||
sector_t blocks;
|
||||
|
@ -1633,15 +1631,15 @@ void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector, bool force)
|
|||
sector &= ~((1ULL << bitmap->counts.chunkshift) - 1);
|
||||
s = 0;
|
||||
while (s < sector && s < bitmap->mddev->resync_max_sectors) {
|
||||
bitmap_end_sync(bitmap, s, &blocks, 0);
|
||||
md_bitmap_end_sync(bitmap, s, &blocks, 0);
|
||||
s += blocks;
|
||||
}
|
||||
bitmap->last_end_sync = jiffies;
|
||||
sysfs_notify(&bitmap->mddev->kobj, NULL, "sync_completed");
|
||||
}
|
||||
EXPORT_SYMBOL(bitmap_cond_end_sync);
|
||||
EXPORT_SYMBOL(md_bitmap_cond_end_sync);
|
||||
|
||||
void bitmap_sync_with_cluster(struct mddev *mddev,
|
||||
void md_bitmap_sync_with_cluster(struct mddev *mddev,
|
||||
sector_t old_lo, sector_t old_hi,
|
||||
sector_t new_lo, sector_t new_hi)
|
||||
{
|
||||
|
@ -1649,20 +1647,20 @@ void bitmap_sync_with_cluster(struct mddev *mddev,
|
|||
sector_t sector, blocks = 0;
|
||||
|
||||
for (sector = old_lo; sector < new_lo; ) {
|
||||
bitmap_end_sync(bitmap, sector, &blocks, 0);
|
||||
md_bitmap_end_sync(bitmap, sector, &blocks, 0);
|
||||
sector += blocks;
|
||||
}
|
||||
WARN((blocks > new_lo) && old_lo, "alignment is not correct for lo\n");
|
||||
|
||||
for (sector = old_hi; sector < new_hi; ) {
|
||||
bitmap_start_sync(bitmap, sector, &blocks, 0);
|
||||
md_bitmap_start_sync(bitmap, sector, &blocks, 0);
|
||||
sector += blocks;
|
||||
}
|
||||
WARN((blocks > new_hi) && old_hi, "alignment is not correct for hi\n");
|
||||
}
|
||||
EXPORT_SYMBOL(bitmap_sync_with_cluster);
|
||||
EXPORT_SYMBOL(md_bitmap_sync_with_cluster);
|
||||
|
||||
static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed)
|
||||
static void md_bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed)
|
||||
{
|
||||
/* For each chunk covered by any of these sectors, set the
|
||||
* counter to 2 and possibly set resync_needed. They should all
|
||||
|
@ -1672,15 +1670,15 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int n
|
|||
sector_t secs;
|
||||
bitmap_counter_t *bmc;
|
||||
spin_lock_irq(&bitmap->counts.lock);
|
||||
bmc = bitmap_get_counter(&bitmap->counts, offset, &secs, 1);
|
||||
bmc = md_bitmap_get_counter(&bitmap->counts, offset, &secs, 1);
|
||||
if (!bmc) {
|
||||
spin_unlock_irq(&bitmap->counts.lock);
|
||||
return;
|
||||
}
|
||||
if (!*bmc) {
|
||||
*bmc = 2;
|
||||
bitmap_count_page(&bitmap->counts, offset, 1);
|
||||
bitmap_set_pending(&bitmap->counts, offset);
|
||||
md_bitmap_count_page(&bitmap->counts, offset, 1);
|
||||
md_bitmap_set_pending(&bitmap->counts, offset);
|
||||
bitmap->allclean = 0;
|
||||
}
|
||||
if (needed)
|
||||
|
@ -1689,14 +1687,14 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int n
|
|||
}
|
||||
|
||||
/* dirty the memory and file bits for bitmap chunks "s" to "e" */
|
||||
void bitmap_dirty_bits(struct bitmap *bitmap, unsigned long s, unsigned long e)
|
||||
void md_bitmap_dirty_bits(struct bitmap *bitmap, unsigned long s, unsigned long e)
|
||||
{
|
||||
unsigned long chunk;
|
||||
|
||||
for (chunk = s; chunk <= e; chunk++) {
|
||||
sector_t sec = (sector_t)chunk << bitmap->counts.chunkshift;
|
||||
bitmap_set_memory_bits(bitmap, sec, 1);
|
||||
bitmap_file_set_bit(bitmap, sec);
|
||||
md_bitmap_set_memory_bits(bitmap, sec, 1);
|
||||
md_bitmap_file_set_bit(bitmap, sec);
|
||||
if (sec < bitmap->mddev->recovery_cp)
|
||||
/* We are asserting that the array is dirty,
|
||||
* so move the recovery_cp address back so
|
||||
|
@ -1709,7 +1707,7 @@ void bitmap_dirty_bits(struct bitmap *bitmap, unsigned long s, unsigned long e)
|
|||
/*
|
||||
* flush out any pending updates
|
||||
*/
|
||||
void bitmap_flush(struct mddev *mddev)
|
||||
void md_bitmap_flush(struct mddev *mddev)
|
||||
{
|
||||
struct bitmap *bitmap = mddev->bitmap;
|
||||
long sleep;
|
||||
|
@ -1722,18 +1720,18 @@ void bitmap_flush(struct mddev *mddev)
|
|||
*/
|
||||
sleep = mddev->bitmap_info.daemon_sleep * 2;
|
||||
bitmap->daemon_lastrun -= sleep;
|
||||
bitmap_daemon_work(mddev);
|
||||
md_bitmap_daemon_work(mddev);
|
||||
bitmap->daemon_lastrun -= sleep;
|
||||
bitmap_daemon_work(mddev);
|
||||
md_bitmap_daemon_work(mddev);
|
||||
bitmap->daemon_lastrun -= sleep;
|
||||
bitmap_daemon_work(mddev);
|
||||
bitmap_update_sb(bitmap);
|
||||
md_bitmap_daemon_work(mddev);
|
||||
md_bitmap_update_sb(bitmap);
|
||||
}
|
||||
|
||||
/*
|
||||
* free memory that was allocated
|
||||
*/
|
||||
void bitmap_free(struct bitmap *bitmap)
|
||||
void md_bitmap_free(struct bitmap *bitmap)
|
||||
{
|
||||
unsigned long k, pages;
|
||||
struct bitmap_page *bp;
|
||||
|
@ -1753,7 +1751,7 @@ void bitmap_free(struct bitmap *bitmap)
|
|||
atomic_read(&bitmap->pending_writes) == 0);
|
||||
|
||||
/* release the bitmap file */
|
||||
bitmap_file_unmap(&bitmap->storage);
|
||||
md_bitmap_file_unmap(&bitmap->storage);
|
||||
|
||||
bp = bitmap->counts.bp;
|
||||
pages = bitmap->counts.pages;
|
||||
|
@ -1767,9 +1765,9 @@ void bitmap_free(struct bitmap *bitmap)
|
|||
kfree(bp);
|
||||
kfree(bitmap);
|
||||
}
|
||||
EXPORT_SYMBOL(bitmap_free);
|
||||
EXPORT_SYMBOL(md_bitmap_free);
|
||||
|
||||
void bitmap_wait_behind_writes(struct mddev *mddev)
|
||||
void md_bitmap_wait_behind_writes(struct mddev *mddev)
|
||||
{
|
||||
struct bitmap *bitmap = mddev->bitmap;
|
||||
|
||||
|
@ -1783,14 +1781,14 @@ void bitmap_wait_behind_writes(struct mddev *mddev)
|
|||
}
|
||||
}
|
||||
|
||||
void bitmap_destroy(struct mddev *mddev)
|
||||
void md_bitmap_destroy(struct mddev *mddev)
|
||||
{
|
||||
struct bitmap *bitmap = mddev->bitmap;
|
||||
|
||||
if (!bitmap) /* there was no bitmap */
|
||||
return;
|
||||
|
||||
bitmap_wait_behind_writes(mddev);
|
||||
md_bitmap_wait_behind_writes(mddev);
|
||||
|
||||
mutex_lock(&mddev->bitmap_info.mutex);
|
||||
spin_lock(&mddev->lock);
|
||||
|
@ -1800,7 +1798,7 @@ void bitmap_destroy(struct mddev *mddev)
|
|||
if (mddev->thread)
|
||||
mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
|
||||
|
||||
bitmap_free(bitmap);
|
||||
md_bitmap_free(bitmap);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1808,7 +1806,7 @@ void bitmap_destroy(struct mddev *mddev)
|
|||
* if this returns an error, bitmap_destroy must be called to do clean up
|
||||
* once mddev->bitmap is set
|
||||
*/
|
||||
struct bitmap *bitmap_create(struct mddev *mddev, int slot)
|
||||
struct bitmap *md_bitmap_create(struct mddev *mddev, int slot)
|
||||
{
|
||||
struct bitmap *bitmap;
|
||||
sector_t blocks = mddev->resync_max_sectors;
|
||||
|
@ -1863,9 +1861,9 @@ struct bitmap *bitmap_create(struct mddev *mddev, int slot)
|
|||
* instructing us to create a new on-disk bitmap instance.
|
||||
*/
|
||||
if (test_and_clear_bit(MD_ARRAY_FIRST_USE, &mddev->flags))
|
||||
err = bitmap_new_disk_sb(bitmap);
|
||||
err = md_bitmap_new_disk_sb(bitmap);
|
||||
else
|
||||
err = bitmap_read_sb(bitmap);
|
||||
err = md_bitmap_read_sb(bitmap);
|
||||
} else {
|
||||
err = 0;
|
||||
if (mddev->bitmap_info.chunksize == 0 ||
|
||||
|
@ -1878,7 +1876,7 @@ struct bitmap *bitmap_create(struct mddev *mddev, int slot)
|
|||
goto error;
|
||||
|
||||
bitmap->daemon_lastrun = jiffies;
|
||||
err = bitmap_resize(bitmap, blocks, mddev->bitmap_info.chunksize, 1);
|
||||
err = md_bitmap_resize(bitmap, blocks, mddev->bitmap_info.chunksize, 1);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
|
@ -1891,11 +1889,11 @@ struct bitmap *bitmap_create(struct mddev *mddev, int slot)
|
|||
|
||||
return bitmap;
|
||||
error:
|
||||
bitmap_free(bitmap);
|
||||
md_bitmap_free(bitmap);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
int bitmap_load(struct mddev *mddev)
|
||||
int md_bitmap_load(struct mddev *mddev)
|
||||
{
|
||||
int err = 0;
|
||||
sector_t start = 0;
|
||||
|
@ -1915,10 +1913,10 @@ int bitmap_load(struct mddev *mddev)
|
|||
*/
|
||||
while (sector < mddev->resync_max_sectors) {
|
||||
sector_t blocks;
|
||||
bitmap_start_sync(bitmap, sector, &blocks, 0);
|
||||
md_bitmap_start_sync(bitmap, sector, &blocks, 0);
|
||||
sector += blocks;
|
||||
}
|
||||
bitmap_close_sync(bitmap);
|
||||
md_bitmap_close_sync(bitmap);
|
||||
|
||||
if (mddev->degraded == 0
|
||||
|| bitmap->events_cleared == mddev->events)
|
||||
|
@ -1927,7 +1925,7 @@ int bitmap_load(struct mddev *mddev)
|
|||
start = mddev->recovery_cp;
|
||||
|
||||
mutex_lock(&mddev->bitmap_info.mutex);
|
||||
err = bitmap_init_from_disk(bitmap, start);
|
||||
err = md_bitmap_init_from_disk(bitmap, start);
|
||||
mutex_unlock(&mddev->bitmap_info.mutex);
|
||||
|
||||
if (err)
|
||||
|
@ -1940,29 +1938,29 @@ int bitmap_load(struct mddev *mddev)
|
|||
mddev->thread->timeout = mddev->bitmap_info.daemon_sleep;
|
||||
md_wakeup_thread(mddev->thread);
|
||||
|
||||
bitmap_update_sb(bitmap);
|
||||
md_bitmap_update_sb(bitmap);
|
||||
|
||||
if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags))
|
||||
err = -EIO;
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bitmap_load);
|
||||
EXPORT_SYMBOL_GPL(md_bitmap_load);
|
||||
|
||||
struct bitmap *get_bitmap_from_slot(struct mddev *mddev, int slot)
|
||||
{
|
||||
int rv = 0;
|
||||
struct bitmap *bitmap;
|
||||
|
||||
bitmap = bitmap_create(mddev, slot);
|
||||
bitmap = md_bitmap_create(mddev, slot);
|
||||
if (IS_ERR(bitmap)) {
|
||||
rv = PTR_ERR(bitmap);
|
||||
return ERR_PTR(rv);
|
||||
}
|
||||
|
||||
rv = bitmap_init_from_disk(bitmap, 0);
|
||||
rv = md_bitmap_init_from_disk(bitmap, 0);
|
||||
if (rv) {
|
||||
bitmap_free(bitmap);
|
||||
md_bitmap_free(bitmap);
|
||||
return ERR_PTR(rv);
|
||||
}
|
||||
|
||||
|
@ -1973,7 +1971,7 @@ EXPORT_SYMBOL(get_bitmap_from_slot);
|
|||
/* Loads the bitmap associated with slot and copies the resync information
|
||||
* to our bitmap
|
||||
*/
|
||||
int bitmap_copy_from_slot(struct mddev *mddev, int slot,
|
||||
int md_bitmap_copy_from_slot(struct mddev *mddev, int slot,
|
||||
sector_t *low, sector_t *high, bool clear_bits)
|
||||
{
|
||||
int rv = 0, i, j;
|
||||
|
@ -1990,35 +1988,35 @@ int bitmap_copy_from_slot(struct mddev *mddev, int slot,
|
|||
counts = &bitmap->counts;
|
||||
for (j = 0; j < counts->chunks; j++) {
|
||||
block = (sector_t)j << counts->chunkshift;
|
||||
if (bitmap_file_test_bit(bitmap, block)) {
|
||||
if (md_bitmap_file_test_bit(bitmap, block)) {
|
||||
if (!lo)
|
||||
lo = block;
|
||||
hi = block;
|
||||
bitmap_file_clear_bit(bitmap, block);
|
||||
bitmap_set_memory_bits(mddev->bitmap, block, 1);
|
||||
bitmap_file_set_bit(mddev->bitmap, block);
|
||||
md_bitmap_file_clear_bit(bitmap, block);
|
||||
md_bitmap_set_memory_bits(mddev->bitmap, block, 1);
|
||||
md_bitmap_file_set_bit(mddev->bitmap, block);
|
||||
}
|
||||
}
|
||||
|
||||
if (clear_bits) {
|
||||
bitmap_update_sb(bitmap);
|
||||
md_bitmap_update_sb(bitmap);
|
||||
/* BITMAP_PAGE_PENDING is set, but bitmap_unplug needs
|
||||
* BITMAP_PAGE_DIRTY or _NEEDWRITE to write ... */
|
||||
for (i = 0; i < bitmap->storage.file_pages; i++)
|
||||
if (test_page_attr(bitmap, i, BITMAP_PAGE_PENDING))
|
||||
set_page_attr(bitmap, i, BITMAP_PAGE_NEEDWRITE);
|
||||
bitmap_unplug(bitmap);
|
||||
md_bitmap_unplug(bitmap);
|
||||
}
|
||||
bitmap_unplug(mddev->bitmap);
|
||||
md_bitmap_unplug(mddev->bitmap);
|
||||
*low = lo;
|
||||
*high = hi;
|
||||
|
||||
return rv;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bitmap_copy_from_slot);
|
||||
EXPORT_SYMBOL_GPL(md_bitmap_copy_from_slot);
|
||||
|
||||
|
||||
void bitmap_status(struct seq_file *seq, struct bitmap *bitmap)
|
||||
void md_bitmap_status(struct seq_file *seq, struct bitmap *bitmap)
|
||||
{
|
||||
unsigned long chunk_kb;
|
||||
struct bitmap_counts *counts;
|
||||
|
@ -2045,7 +2043,7 @@ void bitmap_status(struct seq_file *seq, struct bitmap *bitmap)
|
|||
seq_printf(seq, "\n");
|
||||
}
|
||||
|
||||
int bitmap_resize(struct bitmap *bitmap, sector_t blocks,
|
||||
int md_bitmap_resize(struct bitmap *bitmap, sector_t blocks,
|
||||
int chunksize, int init)
|
||||
{
|
||||
/* If chunk_size is 0, choose an appropriate chunk size.
|
||||
|
@ -2106,12 +2104,12 @@ int bitmap_resize(struct bitmap *bitmap, sector_t blocks,
|
|||
chunks = DIV_ROUND_UP_SECTOR_T(blocks, 1 << chunkshift);
|
||||
memset(&store, 0, sizeof(store));
|
||||
if (bitmap->mddev->bitmap_info.offset || bitmap->mddev->bitmap_info.file)
|
||||
ret = bitmap_storage_alloc(&store, chunks,
|
||||
!bitmap->mddev->bitmap_info.external,
|
||||
mddev_is_clustered(bitmap->mddev)
|
||||
? bitmap->cluster_slot : 0);
|
||||
ret = md_bitmap_storage_alloc(&store, chunks,
|
||||
!bitmap->mddev->bitmap_info.external,
|
||||
mddev_is_clustered(bitmap->mddev)
|
||||
? bitmap->cluster_slot : 0);
|
||||
if (ret) {
|
||||
bitmap_file_unmap(&store);
|
||||
md_bitmap_file_unmap(&store);
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -2120,7 +2118,7 @@ int bitmap_resize(struct bitmap *bitmap, sector_t blocks,
|
|||
new_bp = kcalloc(pages, sizeof(*new_bp), GFP_KERNEL);
|
||||
ret = -ENOMEM;
|
||||
if (!new_bp) {
|
||||
bitmap_file_unmap(&store);
|
||||
md_bitmap_file_unmap(&store);
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -2134,7 +2132,7 @@ int bitmap_resize(struct bitmap *bitmap, sector_t blocks,
|
|||
memcpy(page_address(store.sb_page),
|
||||
page_address(bitmap->storage.sb_page),
|
||||
sizeof(bitmap_super_t));
|
||||
bitmap_file_unmap(&bitmap->storage);
|
||||
md_bitmap_file_unmap(&bitmap->storage);
|
||||
bitmap->storage = store;
|
||||
|
||||
old_counts = bitmap->counts;
|
||||
|
@ -2154,7 +2152,7 @@ int bitmap_resize(struct bitmap *bitmap, sector_t blocks,
|
|||
if (mddev_is_clustered(bitmap->mddev)) {
|
||||
unsigned long page;
|
||||
for (page = 0; page < pages; page++) {
|
||||
ret = bitmap_checkpage(&bitmap->counts, page, 1, 1);
|
||||
ret = md_bitmap_checkpage(&bitmap->counts, page, 1, 1);
|
||||
if (ret) {
|
||||
unsigned long k;
|
||||
|
||||
|
@ -2184,27 +2182,23 @@ int bitmap_resize(struct bitmap *bitmap, sector_t blocks,
|
|||
bitmap_counter_t *bmc_old, *bmc_new;
|
||||
int set;
|
||||
|
||||
bmc_old = bitmap_get_counter(&old_counts, block,
|
||||
&old_blocks, 0);
|
||||
bmc_old = md_bitmap_get_counter(&old_counts, block, &old_blocks, 0);
|
||||
set = bmc_old && NEEDED(*bmc_old);
|
||||
|
||||
if (set) {
|
||||
bmc_new = bitmap_get_counter(&bitmap->counts, block,
|
||||
&new_blocks, 1);
|
||||
bmc_new = md_bitmap_get_counter(&bitmap->counts, block, &new_blocks, 1);
|
||||
if (*bmc_new == 0) {
|
||||
/* need to set on-disk bits too. */
|
||||
sector_t end = block + new_blocks;
|
||||
sector_t start = block >> chunkshift;
|
||||
start <<= chunkshift;
|
||||
while (start < end) {
|
||||
bitmap_file_set_bit(bitmap, block);
|
||||
md_bitmap_file_set_bit(bitmap, block);
|
||||
start += 1 << chunkshift;
|
||||
}
|
||||
*bmc_new = 2;
|
||||
bitmap_count_page(&bitmap->counts,
|
||||
block, 1);
|
||||
bitmap_set_pending(&bitmap->counts,
|
||||
block);
|
||||
md_bitmap_count_page(&bitmap->counts, block, 1);
|
||||
md_bitmap_set_pending(&bitmap->counts, block);
|
||||
}
|
||||
*bmc_new |= NEEDED_MASK;
|
||||
if (new_blocks < old_blocks)
|
||||
|
@ -2225,18 +2219,15 @@ int bitmap_resize(struct bitmap *bitmap, sector_t blocks,
|
|||
int i;
|
||||
while (block < (chunks << chunkshift)) {
|
||||
bitmap_counter_t *bmc;
|
||||
bmc = bitmap_get_counter(&bitmap->counts, block,
|
||||
&new_blocks, 1);
|
||||
bmc = md_bitmap_get_counter(&bitmap->counts, block, &new_blocks, 1);
|
||||
if (bmc) {
|
||||
/* new space. It needs to be resynced, so
|
||||
* we set NEEDED_MASK.
|
||||
*/
|
||||
if (*bmc == 0) {
|
||||
*bmc = NEEDED_MASK | 2;
|
||||
bitmap_count_page(&bitmap->counts,
|
||||
block, 1);
|
||||
bitmap_set_pending(&bitmap->counts,
|
||||
block);
|
||||
md_bitmap_count_page(&bitmap->counts, block, 1);
|
||||
md_bitmap_set_pending(&bitmap->counts, block);
|
||||
}
|
||||
}
|
||||
block += new_blocks;
|
||||
|
@ -2247,14 +2238,14 @@ int bitmap_resize(struct bitmap *bitmap, sector_t blocks,
|
|||
spin_unlock_irq(&bitmap->counts.lock);
|
||||
|
||||
if (!init) {
|
||||
bitmap_unplug(bitmap);
|
||||
md_bitmap_unplug(bitmap);
|
||||
bitmap->mddev->pers->quiesce(bitmap->mddev, 0);
|
||||
}
|
||||
ret = 0;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bitmap_resize);
|
||||
EXPORT_SYMBOL_GPL(md_bitmap_resize);
|
||||
|
||||
static ssize_t
|
||||
location_show(struct mddev *mddev, char *page)
|
||||
|
@ -2298,7 +2289,7 @@ location_store(struct mddev *mddev, const char *buf, size_t len)
|
|||
}
|
||||
if (mddev->pers) {
|
||||
mddev->pers->quiesce(mddev, 1);
|
||||
bitmap_destroy(mddev);
|
||||
md_bitmap_destroy(mddev);
|
||||
mddev->pers->quiesce(mddev, 0);
|
||||
}
|
||||
mddev->bitmap_info.offset = 0;
|
||||
|
@ -2337,18 +2328,18 @@ location_store(struct mddev *mddev, const char *buf, size_t len)
|
|||
if (mddev->pers) {
|
||||
struct bitmap *bitmap;
|
||||
mddev->pers->quiesce(mddev, 1);
|
||||
bitmap = bitmap_create(mddev, -1);
|
||||
bitmap = md_bitmap_create(mddev, -1);
|
||||
if (IS_ERR(bitmap))
|
||||
rv = PTR_ERR(bitmap);
|
||||
else {
|
||||
mddev->bitmap = bitmap;
|
||||
rv = bitmap_load(mddev);
|
||||
rv = md_bitmap_load(mddev);
|
||||
if (rv)
|
||||
mddev->bitmap_info.offset = 0;
|
||||
}
|
||||
mddev->pers->quiesce(mddev, 0);
|
||||
if (rv) {
|
||||
bitmap_destroy(mddev);
|
||||
md_bitmap_destroy(mddev);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -236,43 +236,43 @@ struct bitmap {
|
|||
/* the bitmap API */
|
||||
|
||||
/* these are used only by md/bitmap */
|
||||
struct bitmap *bitmap_create(struct mddev *mddev, int slot);
|
||||
int bitmap_load(struct mddev *mddev);
|
||||
void bitmap_flush(struct mddev *mddev);
|
||||
void bitmap_destroy(struct mddev *mddev);
|
||||
struct bitmap *md_bitmap_create(struct mddev *mddev, int slot);
|
||||
int md_bitmap_load(struct mddev *mddev);
|
||||
void md_bitmap_flush(struct mddev *mddev);
|
||||
void md_bitmap_destroy(struct mddev *mddev);
|
||||
|
||||
void bitmap_print_sb(struct bitmap *bitmap);
|
||||
void bitmap_update_sb(struct bitmap *bitmap);
|
||||
void bitmap_status(struct seq_file *seq, struct bitmap *bitmap);
|
||||
void md_bitmap_print_sb(struct bitmap *bitmap);
|
||||
void md_bitmap_update_sb(struct bitmap *bitmap);
|
||||
void md_bitmap_status(struct seq_file *seq, struct bitmap *bitmap);
|
||||
|
||||
int bitmap_setallbits(struct bitmap *bitmap);
|
||||
void bitmap_write_all(struct bitmap *bitmap);
|
||||
int md_bitmap_setallbits(struct bitmap *bitmap);
|
||||
void md_bitmap_write_all(struct bitmap *bitmap);
|
||||
|
||||
void bitmap_dirty_bits(struct bitmap *bitmap, unsigned long s, unsigned long e);
|
||||
void md_bitmap_dirty_bits(struct bitmap *bitmap, unsigned long s, unsigned long e);
|
||||
|
||||
/* these are exported */
|
||||
int bitmap_startwrite(struct bitmap *bitmap, sector_t offset,
|
||||
unsigned long sectors, int behind);
|
||||
void bitmap_endwrite(struct bitmap *bitmap, sector_t offset,
|
||||
int md_bitmap_startwrite(struct bitmap *bitmap, sector_t offset,
|
||||
unsigned long sectors, int behind);
|
||||
void md_bitmap_endwrite(struct bitmap *bitmap, sector_t offset,
|
||||
unsigned long sectors, int success, int behind);
|
||||
int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, int degraded);
|
||||
void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, int aborted);
|
||||
void bitmap_close_sync(struct bitmap *bitmap);
|
||||
void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector, bool force);
|
||||
void bitmap_sync_with_cluster(struct mddev *mddev,
|
||||
sector_t old_lo, sector_t old_hi,
|
||||
sector_t new_lo, sector_t new_hi);
|
||||
int md_bitmap_start_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, int degraded);
|
||||
void md_bitmap_end_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, int aborted);
|
||||
void md_bitmap_close_sync(struct bitmap *bitmap);
|
||||
void md_bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector, bool force);
|
||||
void md_bitmap_sync_with_cluster(struct mddev *mddev,
|
||||
sector_t old_lo, sector_t old_hi,
|
||||
sector_t new_lo, sector_t new_hi);
|
||||
|
||||
void bitmap_unplug(struct bitmap *bitmap);
|
||||
void bitmap_daemon_work(struct mddev *mddev);
|
||||
void md_bitmap_unplug(struct bitmap *bitmap);
|
||||
void md_bitmap_daemon_work(struct mddev *mddev);
|
||||
|
||||
int bitmap_resize(struct bitmap *bitmap, sector_t blocks,
|
||||
int chunksize, int init);
|
||||
int md_bitmap_resize(struct bitmap *bitmap, sector_t blocks,
|
||||
int chunksize, int init);
|
||||
struct bitmap *get_bitmap_from_slot(struct mddev *mddev, int slot);
|
||||
int bitmap_copy_from_slot(struct mddev *mddev, int slot,
|
||||
sector_t *lo, sector_t *hi, bool clear_bits);
|
||||
void bitmap_free(struct bitmap *bitmap);
|
||||
void bitmap_wait_behind_writes(struct mddev *mddev);
|
||||
int md_bitmap_copy_from_slot(struct mddev *mddev, int slot,
|
||||
sector_t *lo, sector_t *hi, bool clear_bits);
|
||||
void md_bitmap_free(struct bitmap *bitmap);
|
||||
void md_bitmap_wait_behind_writes(struct mddev *mddev);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -317,7 +317,7 @@ static void recover_bitmaps(struct md_thread *thread)
|
|||
str, ret);
|
||||
goto clear_bit;
|
||||
}
|
||||
ret = bitmap_copy_from_slot(mddev, slot, &lo, &hi, true);
|
||||
ret = md_bitmap_copy_from_slot(mddev, slot, &lo, &hi, true);
|
||||
if (ret) {
|
||||
pr_err("md-cluster: Could not copy data from bitmap %d\n", slot);
|
||||
goto clear_bit;
|
||||
|
@ -492,9 +492,7 @@ static void process_suspend_info(struct mddev *mddev,
|
|||
* resync thread is running in another node,
|
||||
* so we don't need to do the resync again
|
||||
* with the same section */
|
||||
bitmap_sync_with_cluster(mddev, cinfo->sync_low,
|
||||
cinfo->sync_hi,
|
||||
lo, hi);
|
||||
md_bitmap_sync_with_cluster(mddev, cinfo->sync_low, cinfo->sync_hi, lo, hi);
|
||||
cinfo->sync_low = lo;
|
||||
cinfo->sync_hi = hi;
|
||||
|
||||
|
@ -842,7 +840,7 @@ static int gather_all_resync_info(struct mddev *mddev, int total_slots)
|
|||
}
|
||||
|
||||
/* Read the disk bitmap sb and check if it needs recovery */
|
||||
ret = bitmap_copy_from_slot(mddev, i, &lo, &hi, false);
|
||||
ret = md_bitmap_copy_from_slot(mddev, i, &lo, &hi, false);
|
||||
if (ret) {
|
||||
pr_warn("md-cluster: Could not gather bitmaps from slot %d", i);
|
||||
lockres_free(bm_lockres);
|
||||
|
@ -1140,13 +1138,13 @@ static int cluster_check_sync_size(struct mddev *mddev)
|
|||
bm_lockres = lockres_init(mddev, str, NULL, 1);
|
||||
if (!bm_lockres) {
|
||||
pr_err("md-cluster: Cannot initialize %s\n", str);
|
||||
bitmap_free(bitmap);
|
||||
md_bitmap_free(bitmap);
|
||||
return -1;
|
||||
}
|
||||
bm_lockres->flags |= DLM_LKF_NOQUEUE;
|
||||
rv = dlm_lock_sync(bm_lockres, DLM_LOCK_PW);
|
||||
if (!rv)
|
||||
bitmap_update_sb(bitmap);
|
||||
md_bitmap_update_sb(bitmap);
|
||||
lockres_free(bm_lockres);
|
||||
|
||||
sb = kmap_atomic(bitmap->storage.sb_page);
|
||||
|
@ -1154,11 +1152,11 @@ static int cluster_check_sync_size(struct mddev *mddev)
|
|||
sync_size = sb->sync_size;
|
||||
else if (sync_size != sb->sync_size) {
|
||||
kunmap_atomic(sb);
|
||||
bitmap_free(bitmap);
|
||||
md_bitmap_free(bitmap);
|
||||
return -1;
|
||||
}
|
||||
kunmap_atomic(sb);
|
||||
bitmap_free(bitmap);
|
||||
md_bitmap_free(bitmap);
|
||||
}
|
||||
|
||||
return (my_sync_size == sync_size) ? 0 : -1;
|
||||
|
@ -1465,7 +1463,7 @@ static int gather_bitmaps(struct md_rdev *rdev)
|
|||
for (sn = 0; sn < mddev->bitmap_info.nodes; sn++) {
|
||||
if (sn == (cinfo->slot_number - 1))
|
||||
continue;
|
||||
err = bitmap_copy_from_slot(mddev, sn, &lo, &hi, false);
|
||||
err = md_bitmap_copy_from_slot(mddev, sn, &lo, &hi, false);
|
||||
if (err) {
|
||||
pr_warn("md-cluster: Could not gather bitmaps from slot %d", sn);
|
||||
goto out;
|
||||
|
|
|
@ -2568,7 +2568,7 @@ void md_update_sb(struct mddev *mddev, int force_change)
|
|||
if (mddev->queue)
|
||||
blk_add_trace_msg(mddev->queue, "md md_update_sb");
|
||||
rewrite:
|
||||
bitmap_update_sb(mddev->bitmap);
|
||||
md_bitmap_update_sb(mddev->bitmap);
|
||||
rdev_for_each(rdev, mddev) {
|
||||
char b[BDEVNAME_SIZE];
|
||||
|
||||
|
@ -4381,10 +4381,10 @@ bitmap_store(struct mddev *mddev, const char *buf, size_t len)
|
|||
if (buf == end) break;
|
||||
}
|
||||
if (*end && !isspace(*end)) break;
|
||||
bitmap_dirty_bits(mddev->bitmap, chunk, end_chunk);
|
||||
md_bitmap_dirty_bits(mddev->bitmap, chunk, end_chunk);
|
||||
buf = skip_spaces(end);
|
||||
}
|
||||
bitmap_unplug(mddev->bitmap); /* flush the bits to disk */
|
||||
md_bitmap_unplug(mddev->bitmap); /* flush the bits to disk */
|
||||
out:
|
||||
mddev_unlock(mddev);
|
||||
return len;
|
||||
|
@ -5612,7 +5612,7 @@ int md_run(struct mddev *mddev)
|
|||
(mddev->bitmap_info.file || mddev->bitmap_info.offset)) {
|
||||
struct bitmap *bitmap;
|
||||
|
||||
bitmap = bitmap_create(mddev, -1);
|
||||
bitmap = md_bitmap_create(mddev, -1);
|
||||
if (IS_ERR(bitmap)) {
|
||||
err = PTR_ERR(bitmap);
|
||||
pr_warn("%s: failed to create bitmap (%d)\n",
|
||||
|
@ -5627,7 +5627,7 @@ int md_run(struct mddev *mddev)
|
|||
pers->free(mddev, mddev->private);
|
||||
mddev->private = NULL;
|
||||
module_put(pers->owner);
|
||||
bitmap_destroy(mddev);
|
||||
md_bitmap_destroy(mddev);
|
||||
goto abort;
|
||||
}
|
||||
if (mddev->queue) {
|
||||
|
@ -5712,9 +5712,9 @@ static int do_md_run(struct mddev *mddev)
|
|||
err = md_run(mddev);
|
||||
if (err)
|
||||
goto out;
|
||||
err = bitmap_load(mddev);
|
||||
err = md_bitmap_load(mddev);
|
||||
if (err) {
|
||||
bitmap_destroy(mddev);
|
||||
md_bitmap_destroy(mddev);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -5856,7 +5856,7 @@ static void __md_stop_writes(struct mddev *mddev)
|
|||
mddev->pers->quiesce(mddev, 1);
|
||||
mddev->pers->quiesce(mddev, 0);
|
||||
}
|
||||
bitmap_flush(mddev);
|
||||
md_bitmap_flush(mddev);
|
||||
|
||||
if (mddev->ro == 0 &&
|
||||
((!mddev->in_sync && !mddev_is_clustered(mddev)) ||
|
||||
|
@ -5878,7 +5878,7 @@ EXPORT_SYMBOL_GPL(md_stop_writes);
|
|||
|
||||
static void mddev_detach(struct mddev *mddev)
|
||||
{
|
||||
bitmap_wait_behind_writes(mddev);
|
||||
md_bitmap_wait_behind_writes(mddev);
|
||||
if (mddev->pers && mddev->pers->quiesce) {
|
||||
mddev->pers->quiesce(mddev, 1);
|
||||
mddev->pers->quiesce(mddev, 0);
|
||||
|
@ -5891,7 +5891,7 @@ static void mddev_detach(struct mddev *mddev)
|
|||
static void __md_stop(struct mddev *mddev)
|
||||
{
|
||||
struct md_personality *pers = mddev->pers;
|
||||
bitmap_destroy(mddev);
|
||||
md_bitmap_destroy(mddev);
|
||||
mddev_detach(mddev);
|
||||
/* Ensure ->event_work is done */
|
||||
flush_workqueue(md_misc_wq);
|
||||
|
@ -6710,21 +6710,21 @@ static int set_bitmap_file(struct mddev *mddev, int fd)
|
|||
if (fd >= 0) {
|
||||
struct bitmap *bitmap;
|
||||
|
||||
bitmap = bitmap_create(mddev, -1);
|
||||
bitmap = md_bitmap_create(mddev, -1);
|
||||
mddev_suspend(mddev);
|
||||
if (!IS_ERR(bitmap)) {
|
||||
mddev->bitmap = bitmap;
|
||||
err = bitmap_load(mddev);
|
||||
err = md_bitmap_load(mddev);
|
||||
} else
|
||||
err = PTR_ERR(bitmap);
|
||||
if (err) {
|
||||
bitmap_destroy(mddev);
|
||||
md_bitmap_destroy(mddev);
|
||||
fd = -1;
|
||||
}
|
||||
mddev_resume(mddev);
|
||||
} else if (fd < 0) {
|
||||
mddev_suspend(mddev);
|
||||
bitmap_destroy(mddev);
|
||||
md_bitmap_destroy(mddev);
|
||||
mddev_resume(mddev);
|
||||
}
|
||||
}
|
||||
|
@ -7010,15 +7010,15 @@ static int update_array_info(struct mddev *mddev, mdu_array_info_t *info)
|
|||
mddev->bitmap_info.default_offset;
|
||||
mddev->bitmap_info.space =
|
||||
mddev->bitmap_info.default_space;
|
||||
bitmap = bitmap_create(mddev, -1);
|
||||
bitmap = md_bitmap_create(mddev, -1);
|
||||
mddev_suspend(mddev);
|
||||
if (!IS_ERR(bitmap)) {
|
||||
mddev->bitmap = bitmap;
|
||||
rv = bitmap_load(mddev);
|
||||
rv = md_bitmap_load(mddev);
|
||||
} else
|
||||
rv = PTR_ERR(bitmap);
|
||||
if (rv)
|
||||
bitmap_destroy(mddev);
|
||||
md_bitmap_destroy(mddev);
|
||||
mddev_resume(mddev);
|
||||
} else {
|
||||
/* remove the bitmap */
|
||||
|
@ -7043,7 +7043,7 @@ static int update_array_info(struct mddev *mddev, mdu_array_info_t *info)
|
|||
md_cluster_ops->leave(mddev);
|
||||
}
|
||||
mddev_suspend(mddev);
|
||||
bitmap_destroy(mddev);
|
||||
md_bitmap_destroy(mddev);
|
||||
mddev_resume(mddev);
|
||||
mddev->bitmap_info.offset = 0;
|
||||
}
|
||||
|
@ -7923,7 +7923,7 @@ static int md_seq_show(struct seq_file *seq, void *v)
|
|||
} else
|
||||
seq_printf(seq, "\n ");
|
||||
|
||||
bitmap_status(seq, mddev->bitmap);
|
||||
md_bitmap_status(seq, mddev->bitmap);
|
||||
|
||||
seq_printf(seq, "\n");
|
||||
}
|
||||
|
@ -8794,7 +8794,7 @@ void md_check_recovery(struct mddev *mddev)
|
|||
return;
|
||||
|
||||
if (mddev->bitmap)
|
||||
bitmap_daemon_work(mddev);
|
||||
md_bitmap_daemon_work(mddev);
|
||||
|
||||
if (signal_pending(current)) {
|
||||
if (mddev->pers->sync_request && !mddev->external) {
|
||||
|
@ -8931,7 +8931,7 @@ void md_check_recovery(struct mddev *mddev)
|
|||
* which has the bitmap stored on all devices.
|
||||
* So make sure all bitmap pages get written
|
||||
*/
|
||||
bitmap_write_all(mddev->bitmap);
|
||||
md_bitmap_write_all(mddev->bitmap);
|
||||
}
|
||||
INIT_WORK(&mddev->del_work, md_start_sync);
|
||||
queue_work(md_misc_wq, &mddev->del_work);
|
||||
|
@ -9179,7 +9179,7 @@ static void check_sb_changes(struct mddev *mddev, struct md_rdev *rdev)
|
|||
if (ret)
|
||||
pr_info("md-cluster: resize failed\n");
|
||||
else
|
||||
bitmap_update_sb(mddev->bitmap);
|
||||
md_bitmap_update_sb(mddev->bitmap);
|
||||
}
|
||||
|
||||
/* Check for change of roles in the active devices */
|
||||
|
|
|
@ -69,9 +69,9 @@ static struct dm_block_validator index_validator = {
|
|||
*/
|
||||
#define BITMAP_CSUM_XOR 240779
|
||||
|
||||
static void bitmap_prepare_for_write(struct dm_block_validator *v,
|
||||
struct dm_block *b,
|
||||
size_t block_size)
|
||||
static void dm_bitmap_prepare_for_write(struct dm_block_validator *v,
|
||||
struct dm_block *b,
|
||||
size_t block_size)
|
||||
{
|
||||
struct disk_bitmap_header *disk_header = dm_block_data(b);
|
||||
|
||||
|
@ -81,9 +81,9 @@ static void bitmap_prepare_for_write(struct dm_block_validator *v,
|
|||
BITMAP_CSUM_XOR));
|
||||
}
|
||||
|
||||
static int bitmap_check(struct dm_block_validator *v,
|
||||
struct dm_block *b,
|
||||
size_t block_size)
|
||||
static int dm_bitmap_check(struct dm_block_validator *v,
|
||||
struct dm_block *b,
|
||||
size_t block_size)
|
||||
{
|
||||
struct disk_bitmap_header *disk_header = dm_block_data(b);
|
||||
__le32 csum_disk;
|
||||
|
@ -108,8 +108,8 @@ static int bitmap_check(struct dm_block_validator *v,
|
|||
|
||||
static struct dm_block_validator dm_sm_bitmap_validator = {
|
||||
.name = "sm_bitmap",
|
||||
.prepare_for_write = bitmap_prepare_for_write,
|
||||
.check = bitmap_check
|
||||
.prepare_for_write = dm_bitmap_prepare_for_write,
|
||||
.check = dm_bitmap_check,
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
|
@ -124,7 +124,7 @@ static void *dm_bitmap_data(struct dm_block *b)
|
|||
|
||||
#define WORD_MASK_HIGH 0xAAAAAAAAAAAAAAAAULL
|
||||
|
||||
static unsigned bitmap_word_used(void *addr, unsigned b)
|
||||
static unsigned dm_bitmap_word_used(void *addr, unsigned b)
|
||||
{
|
||||
__le64 *words_le = addr;
|
||||
__le64 *w_le = words_le + (b >> ENTRIES_SHIFT);
|
||||
|
@ -170,7 +170,7 @@ static int sm_find_free(void *addr, unsigned begin, unsigned end,
|
|||
{
|
||||
while (begin < end) {
|
||||
if (!(begin & (ENTRIES_PER_WORD - 1)) &&
|
||||
bitmap_word_used(addr, begin)) {
|
||||
dm_bitmap_word_used(addr, begin)) {
|
||||
begin += ENTRIES_PER_WORD;
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -385,10 +385,10 @@ static void close_write(struct r1bio *r1_bio)
|
|||
r1_bio->behind_master_bio = NULL;
|
||||
}
|
||||
/* clear the bitmap if all writes complete successfully */
|
||||
bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector,
|
||||
r1_bio->sectors,
|
||||
!test_bit(R1BIO_Degraded, &r1_bio->state),
|
||||
test_bit(R1BIO_BehindIO, &r1_bio->state));
|
||||
md_bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector,
|
||||
r1_bio->sectors,
|
||||
!test_bit(R1BIO_Degraded, &r1_bio->state),
|
||||
test_bit(R1BIO_BehindIO, &r1_bio->state));
|
||||
md_write_end(r1_bio->mddev);
|
||||
}
|
||||
|
||||
|
@ -781,7 +781,7 @@ static int raid1_congested(struct mddev *mddev, int bits)
|
|||
static void flush_bio_list(struct r1conf *conf, struct bio *bio)
|
||||
{
|
||||
/* flush any pending bitmap writes to disk before proceeding w/ I/O */
|
||||
bitmap_unplug(conf->mddev->bitmap);
|
||||
md_bitmap_unplug(conf->mddev->bitmap);
|
||||
wake_up(&conf->wait_barrier);
|
||||
|
||||
while (bio) { /* submit pending writes */
|
||||
|
@ -1470,10 +1470,8 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
|
|||
alloc_behind_master_bio(r1_bio, bio);
|
||||
}
|
||||
|
||||
bitmap_startwrite(bitmap, r1_bio->sector,
|
||||
r1_bio->sectors,
|
||||
test_bit(R1BIO_BehindIO,
|
||||
&r1_bio->state));
|
||||
md_bitmap_startwrite(bitmap, r1_bio->sector, r1_bio->sectors,
|
||||
test_bit(R1BIO_BehindIO, &r1_bio->state));
|
||||
first_clone = 0;
|
||||
}
|
||||
|
||||
|
@ -1880,8 +1878,7 @@ static void end_sync_write(struct bio *bio)
|
|||
long sectors_to_go = r1_bio->sectors;
|
||||
/* make sure these bits doesn't get cleared. */
|
||||
do {
|
||||
bitmap_end_sync(mddev->bitmap, s,
|
||||
&sync_blocks, 1);
|
||||
md_bitmap_end_sync(mddev->bitmap, s, &sync_blocks, 1);
|
||||
s += sync_blocks;
|
||||
sectors_to_go -= sync_blocks;
|
||||
} while (sectors_to_go > 0);
|
||||
|
@ -2626,12 +2623,12 @@ static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr,
|
|||
* We can find the current addess in mddev->curr_resync
|
||||
*/
|
||||
if (mddev->curr_resync < max_sector) /* aborted */
|
||||
bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
|
||||
&sync_blocks, 1);
|
||||
md_bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
|
||||
&sync_blocks, 1);
|
||||
else /* completed sync */
|
||||
conf->fullsync = 0;
|
||||
|
||||
bitmap_close_sync(mddev->bitmap);
|
||||
md_bitmap_close_sync(mddev->bitmap);
|
||||
close_sync(conf);
|
||||
|
||||
if (mddev_is_clustered(mddev)) {
|
||||
|
@ -2651,7 +2648,7 @@ static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr,
|
|||
/* before building a request, check if we can skip these blocks..
|
||||
* This call the bitmap_start_sync doesn't actually record anything
|
||||
*/
|
||||
if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
|
||||
if (!md_bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
|
||||
!conf->fullsync && !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
|
||||
/* We can skip this block, and probably several more */
|
||||
*skipped = 1;
|
||||
|
@ -2669,7 +2666,7 @@ static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr,
|
|||
* sector_nr + two times RESYNC_SECTORS
|
||||
*/
|
||||
|
||||
bitmap_cond_end_sync(mddev->bitmap, sector_nr,
|
||||
md_bitmap_cond_end_sync(mddev->bitmap, sector_nr,
|
||||
mddev_is_clustered(mddev) && (sector_nr + 2 * RESYNC_SECTORS > conf->cluster_sync_high));
|
||||
|
||||
|
||||
|
@ -2828,8 +2825,8 @@ static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr,
|
|||
if (len == 0)
|
||||
break;
|
||||
if (sync_blocks == 0) {
|
||||
if (!bitmap_start_sync(mddev->bitmap, sector_nr,
|
||||
&sync_blocks, still_degraded) &&
|
||||
if (!md_bitmap_start_sync(mddev->bitmap, sector_nr,
|
||||
&sync_blocks, still_degraded) &&
|
||||
!conf->fullsync &&
|
||||
!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
|
||||
break;
|
||||
|
@ -3165,7 +3162,7 @@ static int raid1_resize(struct mddev *mddev, sector_t sectors)
|
|||
mddev->array_sectors > newsize)
|
||||
return -EINVAL;
|
||||
if (mddev->bitmap) {
|
||||
int ret = bitmap_resize(mddev->bitmap, newsize, 0, 0);
|
||||
int ret = md_bitmap_resize(mddev->bitmap, newsize, 0, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -440,10 +440,10 @@ static void raid10_end_read_request(struct bio *bio)
|
|||
static void close_write(struct r10bio *r10_bio)
|
||||
{
|
||||
/* clear the bitmap if all writes complete successfully */
|
||||
bitmap_endwrite(r10_bio->mddev->bitmap, r10_bio->sector,
|
||||
r10_bio->sectors,
|
||||
!test_bit(R10BIO_Degraded, &r10_bio->state),
|
||||
0);
|
||||
md_bitmap_endwrite(r10_bio->mddev->bitmap, r10_bio->sector,
|
||||
r10_bio->sectors,
|
||||
!test_bit(R10BIO_Degraded, &r10_bio->state),
|
||||
0);
|
||||
md_write_end(r10_bio->mddev);
|
||||
}
|
||||
|
||||
|
@ -917,7 +917,7 @@ static void flush_pending_writes(struct r10conf *conf)
|
|||
blk_start_plug(&plug);
|
||||
/* flush any pending bitmap writes to disk
|
||||
* before proceeding w/ I/O */
|
||||
bitmap_unplug(conf->mddev->bitmap);
|
||||
md_bitmap_unplug(conf->mddev->bitmap);
|
||||
wake_up(&conf->wait_barrier);
|
||||
|
||||
while (bio) { /* submit pending writes */
|
||||
|
@ -1102,7 +1102,7 @@ static void raid10_unplug(struct blk_plug_cb *cb, bool from_schedule)
|
|||
|
||||
/* we aren't scheduling, so we can do the write-out directly. */
|
||||
bio = bio_list_get(&plug->pending);
|
||||
bitmap_unplug(mddev->bitmap);
|
||||
md_bitmap_unplug(mddev->bitmap);
|
||||
wake_up(&conf->wait_barrier);
|
||||
|
||||
while (bio) { /* submit pending writes */
|
||||
|
@ -1519,7 +1519,7 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio,
|
|||
}
|
||||
|
||||
atomic_set(&r10_bio->remaining, 1);
|
||||
bitmap_startwrite(mddev->bitmap, r10_bio->sector, r10_bio->sectors, 0);
|
||||
md_bitmap_startwrite(mddev->bitmap, r10_bio->sector, r10_bio->sectors, 0);
|
||||
|
||||
for (i = 0; i < conf->copies; i++) {
|
||||
if (r10_bio->devs[i].bio)
|
||||
|
@ -2991,13 +2991,13 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
|
|||
|
||||
if (mddev->curr_resync < max_sector) { /* aborted */
|
||||
if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
|
||||
bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
|
||||
&sync_blocks, 1);
|
||||
md_bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
|
||||
&sync_blocks, 1);
|
||||
else for (i = 0; i < conf->geo.raid_disks; i++) {
|
||||
sector_t sect =
|
||||
raid10_find_virt(conf, mddev->curr_resync, i);
|
||||
bitmap_end_sync(mddev->bitmap, sect,
|
||||
&sync_blocks, 1);
|
||||
md_bitmap_end_sync(mddev->bitmap, sect,
|
||||
&sync_blocks, 1);
|
||||
}
|
||||
} else {
|
||||
/* completed sync */
|
||||
|
@ -3018,7 +3018,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
|
|||
}
|
||||
conf->fullsync = 0;
|
||||
}
|
||||
bitmap_close_sync(mddev->bitmap);
|
||||
md_bitmap_close_sync(mddev->bitmap);
|
||||
close_sync(conf);
|
||||
*skipped = 1;
|
||||
return sectors_skipped;
|
||||
|
@ -3112,8 +3112,8 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
|
|||
* we only need to recover the block if it is set in
|
||||
* the bitmap
|
||||
*/
|
||||
must_sync = bitmap_start_sync(mddev->bitmap, sect,
|
||||
&sync_blocks, 1);
|
||||
must_sync = md_bitmap_start_sync(mddev->bitmap, sect,
|
||||
&sync_blocks, 1);
|
||||
if (sync_blocks < max_sync)
|
||||
max_sync = sync_blocks;
|
||||
if (!must_sync &&
|
||||
|
@ -3158,8 +3158,8 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
|
|||
}
|
||||
}
|
||||
|
||||
must_sync = bitmap_start_sync(mddev->bitmap, sect,
|
||||
&sync_blocks, still_degraded);
|
||||
must_sync = md_bitmap_start_sync(mddev->bitmap, sect,
|
||||
&sync_blocks, still_degraded);
|
||||
|
||||
any_working = 0;
|
||||
for (j=0; j<conf->copies;j++) {
|
||||
|
@ -3335,13 +3335,12 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
|
|||
* safety reason, which ensures curr_resync_completed is
|
||||
* updated in bitmap_cond_end_sync.
|
||||
*/
|
||||
bitmap_cond_end_sync(mddev->bitmap, sector_nr,
|
||||
mddev_is_clustered(mddev) &&
|
||||
(sector_nr + 2 * RESYNC_SECTORS >
|
||||
conf->cluster_sync_high));
|
||||
md_bitmap_cond_end_sync(mddev->bitmap, sector_nr,
|
||||
mddev_is_clustered(mddev) &&
|
||||
(sector_nr + 2 * RESYNC_SECTORS > conf->cluster_sync_high));
|
||||
|
||||
if (!bitmap_start_sync(mddev->bitmap, sector_nr,
|
||||
&sync_blocks, mddev->degraded) &&
|
||||
if (!md_bitmap_start_sync(mddev->bitmap, sector_nr,
|
||||
&sync_blocks, mddev->degraded) &&
|
||||
!conf->fullsync && !test_bit(MD_RECOVERY_REQUESTED,
|
||||
&mddev->recovery)) {
|
||||
/* We can skip this block */
|
||||
|
@ -4022,7 +4021,7 @@ static int raid10_resize(struct mddev *mddev, sector_t sectors)
|
|||
mddev->array_sectors > size)
|
||||
return -EINVAL;
|
||||
if (mddev->bitmap) {
|
||||
int ret = bitmap_resize(mddev->bitmap, size, 0, 0);
|
||||
int ret = md_bitmap_resize(mddev->bitmap, size, 0, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
@ -4287,10 +4286,9 @@ static int raid10_start_reshape(struct mddev *mddev)
|
|||
spin_unlock_irq(&conf->device_lock);
|
||||
|
||||
if (mddev->delta_disks && mddev->bitmap) {
|
||||
ret = bitmap_resize(mddev->bitmap,
|
||||
raid10_size(mddev, 0,
|
||||
conf->geo.raid_disks),
|
||||
0, 0);
|
||||
ret = md_bitmap_resize(mddev->bitmap,
|
||||
raid10_size(mddev, 0, conf->geo.raid_disks),
|
||||
0, 0);
|
||||
if (ret)
|
||||
goto abort;
|
||||
}
|
||||
|
|
|
@ -324,10 +324,10 @@ void r5c_handle_cached_data_endio(struct r5conf *conf,
|
|||
if (sh->dev[i].written) {
|
||||
set_bit(R5_UPTODATE, &sh->dev[i].flags);
|
||||
r5c_return_dev_pending_writes(conf, &sh->dev[i]);
|
||||
bitmap_endwrite(conf->mddev->bitmap, sh->sector,
|
||||
STRIPE_SECTORS,
|
||||
!test_bit(STRIPE_DEGRADED, &sh->state),
|
||||
0);
|
||||
md_bitmap_endwrite(conf->mddev->bitmap, sh->sector,
|
||||
STRIPE_SECTORS,
|
||||
!test_bit(STRIPE_DEGRADED, &sh->state),
|
||||
0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3299,8 +3299,8 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx,
|
|||
*/
|
||||
set_bit(STRIPE_BITMAP_PENDING, &sh->state);
|
||||
spin_unlock_irq(&sh->stripe_lock);
|
||||
bitmap_startwrite(conf->mddev->bitmap, sh->sector,
|
||||
STRIPE_SECTORS, 0);
|
||||
md_bitmap_startwrite(conf->mddev->bitmap, sh->sector,
|
||||
STRIPE_SECTORS, 0);
|
||||
spin_lock_irq(&sh->stripe_lock);
|
||||
clear_bit(STRIPE_BITMAP_PENDING, &sh->state);
|
||||
if (!sh->batch_head) {
|
||||
|
@ -3390,8 +3390,8 @@ handle_failed_stripe(struct r5conf *conf, struct stripe_head *sh,
|
|||
bi = nextbi;
|
||||
}
|
||||
if (bitmap_end)
|
||||
bitmap_endwrite(conf->mddev->bitmap, sh->sector,
|
||||
STRIPE_SECTORS, 0, 0);
|
||||
md_bitmap_endwrite(conf->mddev->bitmap, sh->sector,
|
||||
STRIPE_SECTORS, 0, 0);
|
||||
bitmap_end = 0;
|
||||
/* and fail all 'written' */
|
||||
bi = sh->dev[i].written;
|
||||
|
@ -3436,8 +3436,8 @@ handle_failed_stripe(struct r5conf *conf, struct stripe_head *sh,
|
|||
}
|
||||
}
|
||||
if (bitmap_end)
|
||||
bitmap_endwrite(conf->mddev->bitmap, sh->sector,
|
||||
STRIPE_SECTORS, 0, 0);
|
||||
md_bitmap_endwrite(conf->mddev->bitmap, sh->sector,
|
||||
STRIPE_SECTORS, 0, 0);
|
||||
/* If we were in the middle of a write the parity block might
|
||||
* still be locked - so just clear all R5_LOCKED flags
|
||||
*/
|
||||
|
@ -3777,10 +3777,10 @@ static void handle_stripe_clean_event(struct r5conf *conf,
|
|||
bio_endio(wbi);
|
||||
wbi = wbi2;
|
||||
}
|
||||
bitmap_endwrite(conf->mddev->bitmap, sh->sector,
|
||||
STRIPE_SECTORS,
|
||||
!test_bit(STRIPE_DEGRADED, &sh->state),
|
||||
0);
|
||||
md_bitmap_endwrite(conf->mddev->bitmap, sh->sector,
|
||||
STRIPE_SECTORS,
|
||||
!test_bit(STRIPE_DEGRADED, &sh->state),
|
||||
0);
|
||||
if (head_sh->batch_head) {
|
||||
sh = list_first_entry(&sh->batch_list,
|
||||
struct stripe_head,
|
||||
|
@ -5543,10 +5543,10 @@ static void make_discard_request(struct mddev *mddev, struct bio *bi)
|
|||
for (d = 0;
|
||||
d < conf->raid_disks - conf->max_degraded;
|
||||
d++)
|
||||
bitmap_startwrite(mddev->bitmap,
|
||||
sh->sector,
|
||||
STRIPE_SECTORS,
|
||||
0);
|
||||
md_bitmap_startwrite(mddev->bitmap,
|
||||
sh->sector,
|
||||
STRIPE_SECTORS,
|
||||
0);
|
||||
sh->bm_seq = conf->seq_flush + 1;
|
||||
set_bit(STRIPE_BIT_DELAY, &sh->state);
|
||||
}
|
||||
|
@ -6024,11 +6024,11 @@ static inline sector_t raid5_sync_request(struct mddev *mddev, sector_t sector_n
|
|||
}
|
||||
|
||||
if (mddev->curr_resync < max_sector) /* aborted */
|
||||
bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
|
||||
&sync_blocks, 1);
|
||||
md_bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
|
||||
&sync_blocks, 1);
|
||||
else /* completed sync */
|
||||
conf->fullsync = 0;
|
||||
bitmap_close_sync(mddev->bitmap);
|
||||
md_bitmap_close_sync(mddev->bitmap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -6057,7 +6057,7 @@ static inline sector_t raid5_sync_request(struct mddev *mddev, sector_t sector_n
|
|||
}
|
||||
if (!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) &&
|
||||
!conf->fullsync &&
|
||||
!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
|
||||
!md_bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
|
||||
sync_blocks >= STRIPE_SECTORS) {
|
||||
/* we can skip this block, and probably more */
|
||||
sync_blocks /= STRIPE_SECTORS;
|
||||
|
@ -6065,7 +6065,7 @@ static inline sector_t raid5_sync_request(struct mddev *mddev, sector_t sector_n
|
|||
return sync_blocks * STRIPE_SECTORS; /* keep things rounded to whole stripes */
|
||||
}
|
||||
|
||||
bitmap_cond_end_sync(mddev->bitmap, sector_nr, false);
|
||||
md_bitmap_cond_end_sync(mddev->bitmap, sector_nr, false);
|
||||
|
||||
sh = raid5_get_active_stripe(conf, sector_nr, 0, 1, 0);
|
||||
if (sh == NULL) {
|
||||
|
@ -6088,7 +6088,7 @@ static inline sector_t raid5_sync_request(struct mddev *mddev, sector_t sector_n
|
|||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, still_degraded);
|
||||
md_bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, still_degraded);
|
||||
|
||||
set_bit(STRIPE_SYNC_REQUESTED, &sh->state);
|
||||
set_bit(STRIPE_HANDLE, &sh->state);
|
||||
|
@ -6289,7 +6289,7 @@ static void raid5d(struct md_thread *thread)
|
|||
/* Now is a good time to flush some bitmap updates */
|
||||
conf->seq_flush++;
|
||||
spin_unlock_irq(&conf->device_lock);
|
||||
bitmap_unplug(mddev->bitmap);
|
||||
md_bitmap_unplug(mddev->bitmap);
|
||||
spin_lock_irq(&conf->device_lock);
|
||||
conf->seq_write = conf->seq_flush;
|
||||
activate_bit_delay(conf, conf->temp_inactive_list);
|
||||
|
@ -7745,7 +7745,7 @@ static int raid5_resize(struct mddev *mddev, sector_t sectors)
|
|||
mddev->array_sectors > newsize)
|
||||
return -EINVAL;
|
||||
if (mddev->bitmap) {
|
||||
int ret = bitmap_resize(mddev->bitmap, sectors, 0, 0);
|
||||
int ret = md_bitmap_resize(mddev->bitmap, sectors, 0, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -104,6 +104,14 @@
|
|||
* contain all bit positions from 0 to 'bits' - 1.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Allocation and deallocation of bitmap.
|
||||
* Provided in lib/bitmap.c to avoid circular dependency.
|
||||
*/
|
||||
extern unsigned long *bitmap_alloc(unsigned int nbits, gfp_t flags);
|
||||
extern unsigned long *bitmap_zalloc(unsigned int nbits, gfp_t flags);
|
||||
extern void bitmap_free(const unsigned long *bitmap);
|
||||
|
||||
/*
|
||||
* lib/bitmap.c provides these functions:
|
||||
*/
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#ifndef _GPIO_KEYS_H
|
||||
#define _GPIO_KEYS_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct device;
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,10 +17,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
#ifndef _LINUX_JOYSTICK_H
|
||||
#define _LINUX_JOYSTICK_H
|
||||
|
|
|
@ -18,10 +18,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
#ifndef _UAPI_LINUX_JOYSTICK_H
|
||||
#define _UAPI_LINUX_JOYSTICK_H
|
||||
|
|
|
@ -189,6 +189,13 @@
|
|||
*
|
||||
*----------------------------- Connector settings ----------------------------
|
||||
*
|
||||
* unique-id
|
||||
* Values: <string>
|
||||
*
|
||||
* After device instance initialization each connector is assigned a
|
||||
* unique ID, so it can be identified by the backend by this ID.
|
||||
* This can be UUID or such.
|
||||
*
|
||||
* resolution
|
||||
* Values: <width, uint32_t>x<height, uint32_t>
|
||||
*
|
||||
|
@ -368,6 +375,7 @@
|
|||
#define XENDISPL_FIELD_EVT_CHANNEL "evt-event-channel"
|
||||
#define XENDISPL_FIELD_RESOLUTION "resolution"
|
||||
#define XENDISPL_FIELD_BE_ALLOC "be-alloc"
|
||||
#define XENDISPL_FIELD_UNIQUE_ID "unique-id"
|
||||
|
||||
/*
|
||||
******************************************************************************
|
||||
|
|
|
@ -51,6 +51,18 @@
|
|||
* corresponding entries in XenStore and puts 1 as the value of the entry.
|
||||
* If a feature is not supported then 0 must be set or feature entry omitted.
|
||||
*
|
||||
* feature-disable-keyboard
|
||||
* Values: <uint>
|
||||
*
|
||||
* If there is no need to expose a virtual keyboard device by the
|
||||
* frontend then this must be set to 1.
|
||||
*
|
||||
* feature-disable-pointer
|
||||
* Values: <uint>
|
||||
*
|
||||
* If there is no need to expose a virtual pointer device by the
|
||||
* frontend then this must be set to 1.
|
||||
*
|
||||
* feature-abs-pointer
|
||||
* Values: <uint>
|
||||
*
|
||||
|
@ -63,6 +75,22 @@
|
|||
* Backends, which support reporting of multi-touch events
|
||||
* should set this to 1.
|
||||
*
|
||||
* feature-raw-pointer
|
||||
* Values: <uint>
|
||||
*
|
||||
* Backends, which support reporting raw (unscaled) absolute coordinates
|
||||
* for pointer devices should set this to 1. Raw (unscaled) values have
|
||||
* a range of [0, 0x7fff].
|
||||
*
|
||||
*----------------------- Device Instance Parameters ------------------------
|
||||
*
|
||||
* unique-id
|
||||
* Values: <string>
|
||||
*
|
||||
* After device instance initialization it is assigned a unique ID,
|
||||
* so every instance of the frontend can be identified by the backend
|
||||
* by this ID. This can be UUID or such.
|
||||
*
|
||||
*------------------------- Pointer Device Parameters ------------------------
|
||||
*
|
||||
* width
|
||||
|
@ -77,6 +105,25 @@
|
|||
* Maximum Y coordinate (height) to be used by the frontend
|
||||
* while reporting input events, pixels, [0; UINT32_MAX].
|
||||
*
|
||||
*----------------------- Multi-touch Device Parameters ----------------------
|
||||
*
|
||||
* multi-touch-num-contacts
|
||||
* Values: <uint>
|
||||
*
|
||||
* Number of simultaneous touches reported.
|
||||
*
|
||||
* multi-touch-width
|
||||
* Values: <uint>
|
||||
*
|
||||
* Width of the touch area to be used by the frontend
|
||||
* while reporting input events, pixels, [0; UINT32_MAX].
|
||||
*
|
||||
* multi-touch-height
|
||||
* Values: <uint>
|
||||
*
|
||||
* Height of the touch area to be used by the frontend
|
||||
* while reporting input events, pixels, [0; UINT32_MAX].
|
||||
*
|
||||
*****************************************************************************
|
||||
* Frontend XenBus Nodes
|
||||
*****************************************************************************
|
||||
|
@ -98,6 +145,13 @@
|
|||
*
|
||||
* Request backend to report multi-touch events.
|
||||
*
|
||||
* request-raw-pointer
|
||||
* Values: <uint>
|
||||
*
|
||||
* Request backend to report raw unscaled absolute pointer coordinates.
|
||||
* This option is only valid if request-abs-pointer is also set.
|
||||
* Raw unscaled coordinates have the range [0, 0x7fff]
|
||||
*
|
||||
*----------------------- Request Transport Parameters -----------------------
|
||||
*
|
||||
* event-channel
|
||||
|
@ -117,25 +171,6 @@
|
|||
*
|
||||
* OBSOLETE, not recommended for use.
|
||||
* PFN of the shared page.
|
||||
*
|
||||
*----------------------- Multi-touch Device Parameters -----------------------
|
||||
*
|
||||
* multi-touch-num-contacts
|
||||
* Values: <uint>
|
||||
*
|
||||
* Number of simultaneous touches reported.
|
||||
*
|
||||
* multi-touch-width
|
||||
* Values: <uint>
|
||||
*
|
||||
* Width of the touch area to be used by the frontend
|
||||
* while reporting input events, pixels, [0; UINT32_MAX].
|
||||
*
|
||||
* multi-touch-height
|
||||
* Values: <uint>
|
||||
*
|
||||
* Height of the touch area to be used by the frontend
|
||||
* while reporting input events, pixels, [0; UINT32_MAX].
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -163,9 +198,13 @@
|
|||
|
||||
#define XENKBD_DRIVER_NAME "vkbd"
|
||||
|
||||
#define XENKBD_FIELD_FEAT_DSBL_KEYBRD "feature-disable-keyboard"
|
||||
#define XENKBD_FIELD_FEAT_DSBL_POINTER "feature-disable-pointer"
|
||||
#define XENKBD_FIELD_FEAT_ABS_POINTER "feature-abs-pointer"
|
||||
#define XENKBD_FIELD_FEAT_RAW_POINTER "feature-raw-pointer"
|
||||
#define XENKBD_FIELD_FEAT_MTOUCH "feature-multi-touch"
|
||||
#define XENKBD_FIELD_REQ_ABS_POINTER "request-abs-pointer"
|
||||
#define XENKBD_FIELD_REQ_RAW_POINTER "request-raw-pointer"
|
||||
#define XENKBD_FIELD_REQ_MTOUCH "request-multi-touch"
|
||||
#define XENKBD_FIELD_RING_GREF "page-gref"
|
||||
#define XENKBD_FIELD_EVT_CHANNEL "event-channel"
|
||||
|
@ -174,6 +213,7 @@
|
|||
#define XENKBD_FIELD_MT_WIDTH "multi-touch-width"
|
||||
#define XENKBD_FIELD_MT_HEIGHT "multi-touch-height"
|
||||
#define XENKBD_FIELD_MT_NUM_CONTACTS "multi-touch-num-contacts"
|
||||
#define XENKBD_FIELD_UNIQUE_ID "unique-id"
|
||||
|
||||
/* OBSOLETE, not recommended for use */
|
||||
#define XENKBD_FIELD_RING_REF "page-ref"
|
||||
|
|
|
@ -278,13 +278,11 @@
|
|||
* defined under the same device.
|
||||
*
|
||||
* unique-id
|
||||
* Values: <uint32_t>
|
||||
* Values: <string>
|
||||
*
|
||||
* After stream initialization it is assigned a unique ID (within the front
|
||||
* driver), so every stream of the frontend can be identified by the
|
||||
* backend by this ID. This is not equal to stream-idx as the later is
|
||||
* zero based within the device, but this index is contigous within the
|
||||
* driver.
|
||||
* After stream initialization it is assigned a unique ID, so every
|
||||
* stream of the frontend can be identified by the backend by this ID.
|
||||
* This can be UUID or such.
|
||||
*
|
||||
*-------------------- Stream Request Transport Parameters --------------------
|
||||
*
|
||||
|
|
20
lib/bitmap.c
20
lib/bitmap.c
|
@ -13,6 +13,7 @@
|
|||
#include <linux/bitops.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
|
@ -1125,6 +1126,25 @@ void bitmap_copy_le(unsigned long *dst, const unsigned long *src, unsigned int n
|
|||
EXPORT_SYMBOL(bitmap_copy_le);
|
||||
#endif
|
||||
|
||||
unsigned long *bitmap_alloc(unsigned int nbits, gfp_t flags)
|
||||
{
|
||||
return kmalloc_array(BITS_TO_LONGS(nbits), sizeof(unsigned long),
|
||||
flags);
|
||||
}
|
||||
EXPORT_SYMBOL(bitmap_alloc);
|
||||
|
||||
unsigned long *bitmap_zalloc(unsigned int nbits, gfp_t flags)
|
||||
{
|
||||
return bitmap_alloc(nbits, flags | __GFP_ZERO);
|
||||
}
|
||||
EXPORT_SYMBOL(bitmap_zalloc);
|
||||
|
||||
void bitmap_free(const unsigned long *bitmap)
|
||||
{
|
||||
kfree(bitmap);
|
||||
}
|
||||
EXPORT_SYMBOL(bitmap_free);
|
||||
|
||||
#if BITS_PER_LONG == 64
|
||||
/**
|
||||
* bitmap_from_arr32 - copy the contents of u32 array of bits to bitmap
|
||||
|
|
Loading…
Reference in New Issue