1
0
Fork 0

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
  ...
hifive-unleashed-5.1
Linus Torvalds 2018-08-18 16:48:07 -07:00
commit 08b5fa8199
99 changed files with 1472 additions and 971 deletions

View File

@ -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.

View File

@ -7,6 +7,7 @@ PROPERTIES
Value type: <string> Value type: <string>
Definition: must be one of: Definition: must be one of:
"qcom,pm8941-pwrkey" "qcom,pm8941-pwrkey"
"qcom,pm8941-resin"
- reg: - reg:
Usage: required Usage: required
@ -32,6 +33,14 @@ PROPERTIES
Definition: presence of this property indicates that the KPDPWR_N pin Definition: presence of this property indicates that the KPDPWR_N pin
should be configured for pull up. 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 EXAMPLE
pwrkey@800 { pwrkey@800 {
@ -40,4 +49,5 @@ EXAMPLE
interrupts = <0x0 0x8 0 IRQ_TYPE_EDGE_BOTH>; interrupts = <0x0 0x8 0 IRQ_TYPE_EDGE_BOTH>;
debounce = <15625>; debounce = <15625>;
bias-pull-up; bias-pull-up;
linux,code = <KEY_POWER>;
}; };

View File

@ -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>;
};
/* ... */
};

View File

@ -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>;
};
};

View File

@ -11340,6 +11340,13 @@ S: Maintained
F: include/linux/personality.h F: include/linux/personality.h
F: include/uapi/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 PHONET PROTOCOL
M: Remi Denis-Courmont <courmisch@gmail.com> M: Remi Denis-Courmont <courmisch@gmail.com>
S: Supported S: Supported

View File

@ -20,10 +20,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

View File

@ -481,7 +481,7 @@ static int evdev_release(struct inode *inode, struct file *file)
evdev_detach_client(evdev, client); evdev_detach_client(evdev, client);
for (i = 0; i < EV_CNT; ++i) for (i = 0; i < EV_CNT; ++i)
kfree(client->evmasks[i]); bitmap_free(client->evmasks[i]);
kvfree(client); kvfree(client);
@ -925,17 +925,15 @@ static int evdev_handle_get_val(struct evdev_client *client,
{ {
int ret; int ret;
unsigned long *mem; unsigned long *mem;
size_t len;
len = BITS_TO_LONGS(maxbit) * sizeof(unsigned long); mem = bitmap_alloc(maxbit, GFP_KERNEL);
mem = kmalloc(len, GFP_KERNEL);
if (!mem) if (!mem)
return -ENOMEM; return -ENOMEM;
spin_lock_irq(&dev->event_lock); spin_lock_irq(&dev->event_lock);
spin_lock(&client->buffer_lock); spin_lock(&client->buffer_lock);
memcpy(mem, bits, len); bitmap_copy(mem, bits, maxbit);
spin_unlock(&dev->event_lock); spin_unlock(&dev->event_lock);
@ -947,7 +945,7 @@ static int evdev_handle_get_val(struct evdev_client *client,
if (ret < 0) if (ret < 0)
evdev_queue_syn_dropped(client); evdev_queue_syn_dropped(client);
kfree(mem); bitmap_free(mem);
return ret; return ret;
} }
@ -1003,13 +1001,13 @@ static int evdev_set_mask(struct evdev_client *client,
if (!cnt) if (!cnt)
return 0; return 0;
mask = kcalloc(sizeof(unsigned long), BITS_TO_LONGS(cnt), GFP_KERNEL); mask = bitmap_zalloc(cnt, GFP_KERNEL);
if (!mask) if (!mask)
return -ENOMEM; return -ENOMEM;
error = bits_from_user(mask, cnt - 1, codes_size, codes, compat); error = bits_from_user(mask, cnt - 1, codes_size, codes, compat);
if (error < 0) { if (error < 0) {
kfree(mask); bitmap_free(mask);
return error; return error;
} }
@ -1018,7 +1016,7 @@ static int evdev_set_mask(struct evdev_client *client,
client->evmasks[type] = mask; client->evmasks[type] = mask;
spin_unlock_irqrestore(&client->buffer_lock, flags); spin_unlock_irqrestore(&client->buffer_lock, flags);
kfree(oldmask); bitmap_free(oldmask);
return 0; return 0;
} }

View File

@ -20,10 +20,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <asm/io.h>

View File

@ -20,10 +20,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <asm/io.h>

View File

@ -21,10 +21,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <asm/io.h>

View File

@ -480,11 +480,19 @@ EXPORT_SYMBOL(input_inject_event);
*/ */
void input_alloc_absinfo(struct input_dev *dev) void input_alloc_absinfo(struct input_dev *dev)
{ {
if (!dev->absinfo) if (dev->absinfo)
dev->absinfo = kcalloc(ABS_CNT, sizeof(*dev->absinfo), return;
GFP_KERNEL);
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); EXPORT_SYMBOL(input_alloc_absinfo);

View File

@ -20,10 +20,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/kernel.h>

View File

@ -20,10 +20,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/delay.h>

View File

@ -20,10 +20,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/types.h>

View File

@ -20,10 +20,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/delay.h>

View File

@ -20,10 +20,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/kernel.h>

View File

@ -23,10 +23,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #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); db9_saturn_write_sub(port, type, 3, powered, 0);
return data[0] = 0xe3; return data[0] = 0xe3;
} }
/* else: fall through */
default: default:
return data[0]; return data[0];
} }
@ -282,11 +279,14 @@ static int db9_saturn_report(unsigned char id, unsigned char data[60], struct in
switch (data[j]) { switch (data[j]) {
case 0x16: /* multi controller (analog 4 axis) */ case 0x16: /* multi controller (analog 4 axis) */
input_report_abs(dev, db9_abs[5], data[j + 6]); input_report_abs(dev, db9_abs[5], data[j + 6]);
/* fall through */
case 0x15: /* mission stick (analog 3 axis) */ case 0x15: /* mission stick (analog 3 axis) */
input_report_abs(dev, db9_abs[3], data[j + 4]); input_report_abs(dev, db9_abs[3], data[j + 4]);
input_report_abs(dev, db9_abs[4], data[j + 5]); input_report_abs(dev, db9_abs[4], data[j + 5]);
/* fall through */
case 0x13: /* racing controller (analog 1 axis) */ case 0x13: /* racing controller (analog 1 axis) */
input_report_abs(dev, db9_abs[2], data[j + 3]); input_report_abs(dev, db9_abs[2], data[j + 3]);
/* fall through */
case 0x34: /* saturn keyboard (udlr ZXC ASD QE Esc) */ case 0x34: /* saturn keyboard (udlr ZXC ASD QE Esc) */
case 0x02: /* digital pad (digital 2 axis + buttons) */ case 0x02: /* digital pad (digital 2 axis + buttons) */
input_report_abs(dev, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64)); 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_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_abs(dev2, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
input_report_key(dev2, BTN_TRIGGER, ~data & DB9_FIRE1); input_report_key(dev2, BTN_TRIGGER, ~data & DB9_FIRE1);
/* fall through */
case DB9_MULTI_0802: case DB9_MULTI_0802:

View File

@ -24,10 +24,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

View File

@ -20,10 +20,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/delay.h>

View File

@ -20,10 +20,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/kernel.h>

View File

@ -20,10 +20,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/kernel.h>

View File

@ -19,10 +19,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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" #include "iforce.h"
@ -56,7 +52,7 @@ static int make_magnitude_modifier(struct iforce* iforce,
iforce_send_packet(iforce, FF_CMD_MAGNITUDE, data); 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; return 0;
} }
@ -178,7 +174,7 @@ static int make_condition_modifier(struct iforce* iforce,
data[9] = (100 * lsat) >> 16; data[9] = (100 * lsat) >> 16;
iforce_send_packet(iforce, FF_CMD_CONDITION, data); 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; return 0;
} }

View File

@ -19,10 +19,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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" #include "iforce.h"
@ -33,21 +29,14 @@ MODULE_LICENSE("GPL");
static signed short btn_joystick[] = static signed short btn_joystick[] =
{ BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE, { 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[] = static signed short btn_joystick_avb[] =
{ BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE, { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE,
BTN_BASE2, BTN_BASE3, BTN_BASE4, -1 }; BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_DEAD, -1 };
static signed short btn_wheel[] = 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_GEAR_DOWN, BTN_GEAR_UP, BTN_BASE, BTN_BASE2, BTN_BASE3,
BTN_BASE4, BTN_BASE5, BTN_BASE6, -1 }; 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 }, { 0x044f, 0xa01c, "Thrustmaster Motor Sport GT", btn_wheel, abs_wheel, ff_iforce },
{ 0x046d, 0xc281, "Logitech WingMan Force", btn_joystick, abs_joystick, 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 }, { 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, 0x020a, "AVB Top Shot Pegasus", btn_joystick_avb, abs_avb_pegasus, ff_iforce },
{ 0x05ef, 0x8884, "AVB Mag Turbo Force", btn_avb_wheel, abs_wheel, ff_iforce }, { 0x05ef, 0x8884, "AVB Mag Turbo Force", btn_wheel, abs_wheel, ff_iforce },
{ 0x05ef, 0x8888, "AVB Top Shot Force Feedback Racing Wheel", btn_avb_tw, 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, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //?
{ 0x061c, 0xc084, "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 }, //? { 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++) for (i = 0; c[i]; i++)
if (!iforce_get_id_packet(iforce, c + 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. * 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++) for (i = 0; iforce->type->btn[i] >= 0; i++)
set_bit(iforce->type->btn[i], input_dev->keybit); 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++) { for (i = 0; iforce->type->abs[i] >= 0; i++) {

View File

@ -19,10 +19,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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" #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}}; } 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; dev_dbg(iforce->dev->dev.parent, "%s %s cmd = %04x, data = %*ph\n",
__func__, msg, cmd, LO(cmd), data);
printk(KERN_DEBUG __FILE__ ": %s cmd = %04x, data = ", msg, cmd);
for (i = 0; i < LO(cmd); i++)
printk("%02x ", data[i]);
printk("\n");
} }
/* /*
@ -255,7 +247,7 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet)
iforce->cr.bRequest = packet[0]; iforce->cr.bRequest = packet[0];
iforce->ctrl->dev = iforce->usbdev; iforce->ctrl->dev = iforce->usbdev;
status = usb_submit_urb(iforce->ctrl, GFP_ATOMIC); status = usb_submit_urb(iforce->ctrl, GFP_KERNEL);
if (status) { if (status) {
dev_err(&iforce->intf->dev, dev_err(&iforce->intf->dev,
"usb_submit_urb failed %d\n", status); "usb_submit_urb failed %d\n", status);

View File

@ -19,10 +19,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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" #include "iforce.h"

View File

@ -19,10 +19,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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" #include "iforce.h"

View File

@ -19,10 +19,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #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); int iforce_control_playback(struct iforce*, u16 id, unsigned int);
void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data); void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data);
int iforce_send_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); int iforce_get_id_packet(struct iforce *iforce, char *packet);
/* iforce-ff.c */ /* iforce-ff.c */

View File

@ -23,10 +23,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/kernel.h>

View File

@ -21,10 +21,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/module.h>

View File

@ -20,10 +20,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/kernel.h>

View File

@ -3,7 +3,6 @@
* Driver for Phoenix RC Flight Controller Adapter * Driver for Phoenix RC Flight Controller Adapter
* *
* Copyright (C) 2018 Marcus Folkesson <marcus.folkesson@gmail.com> * Copyright (C) 2018 Marcus Folkesson <marcus.folkesson@gmail.com>
*
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
@ -16,31 +15,22 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/input.h> #include <linux/input.h>
#define PXRC_VENDOR_ID (0x1781) #define PXRC_VENDOR_ID 0x1781
#define PXRC_PRODUCT_ID (0x0898) #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);
struct pxrc { struct pxrc {
struct input_dev *input; struct input_dev *input;
struct usb_device *udev;
struct usb_interface *intf; struct usb_interface *intf;
struct urb *urb; struct urb *urb;
struct mutex pm_mutex; struct mutex pm_mutex;
bool is_open; bool is_open;
__u8 epaddr;
char phys[64]; char phys[64];
unsigned char *data;
size_t bsize;
}; };
static void pxrc_usb_irq(struct urb *urb) static void pxrc_usb_irq(struct urb *urb)
{ {
struct pxrc *pxrc = urb->context; struct pxrc *pxrc = urb->context;
u8 *data = urb->transfer_buffer;
int error; int error;
switch (urb->status) { switch (urb->status) {
@ -68,15 +58,15 @@ static void pxrc_usb_irq(struct urb *urb)
} }
if (urb->actual_length == 8) { if (urb->actual_length == 8) {
input_report_abs(pxrc->input, ABS_X, pxrc->data[0]); input_report_abs(pxrc->input, ABS_X, data[0]);
input_report_abs(pxrc->input, ABS_Y, pxrc->data[2]); input_report_abs(pxrc->input, ABS_Y, data[2]);
input_report_abs(pxrc->input, ABS_RX, pxrc->data[3]); input_report_abs(pxrc->input, ABS_RX, data[3]);
input_report_abs(pxrc->input, ABS_RY, pxrc->data[4]); input_report_abs(pxrc->input, ABS_RY, data[4]);
input_report_abs(pxrc->input, ABS_RUDDER, pxrc->data[5]); input_report_abs(pxrc->input, ABS_RUDDER, data[5]);
input_report_abs(pxrc->input, ABS_THROTTLE, pxrc->data[6]); input_report_abs(pxrc->input, ABS_THROTTLE, data[6]);
input_report_abs(pxrc->input, ABS_MISC, pxrc->data[7]); 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: exit:
@ -120,61 +110,73 @@ static void pxrc_close(struct input_dev *input)
mutex_unlock(&pxrc->pm_mutex); 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; struct pxrc *pxrc = _pxrc;
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;
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); struct usb_device *udev = interface_to_usbdev(intf);
if (pxrc->input == NULL) { struct pxrc *pxrc;
dev_err(&pxrc->intf->dev, "couldn't allocate input device\n"); 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; return -ENOMEM;
} }
pxrc->input->name = "PXRC Flight Controller Adapter"; 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; 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->open = pxrc_open;
pxrc->input->close = pxrc_close; pxrc->input->close = pxrc_close;
@ -190,46 +192,16 @@ static int pxrc_input_init(struct pxrc *pxrc)
input_set_drvdata(pxrc->input, pxrc); input_set_drvdata(pxrc->input, pxrc);
return input_register_device(pxrc->input); error = input_register_device(pxrc->input);
} if (error)
return error;
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;
return 0; return 0;
err_free_urb:
usb_free_urb(pxrc->urb);
error:
return retval;
} }
static void pxrc_disconnect(struct usb_interface *intf) static void pxrc_disconnect(struct usb_interface *intf)
{ {
struct pxrc *pxrc = usb_get_intfdata(intf); /* All driver resources are devm-managed. */
usb_free_urb(pxrc->urb);
usb_set_intfdata(intf, NULL);
} }
static int pxrc_suspend(struct usb_interface *intf, pm_message_t message) 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); 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 = { static struct usb_driver pxrc_driver = {
.name = "pxrc", .name = "pxrc",
.probe = pxrc_probe, .probe = pxrc_probe,

View File

@ -20,10 +20,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/delay.h>

View File

@ -24,10 +24,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/kernel.h>

View File

@ -23,10 +23,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/kernel.h>

View File

@ -21,10 +21,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/kernel.h>

View File

@ -23,10 +23,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/delay.h>

View File

@ -23,10 +23,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/kernel.h>

View File

@ -20,10 +20,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/kernel.h>

View File

@ -885,6 +885,7 @@ static int adp5589_probe(struct i2c_client *client,
switch (id->driver_data) { switch (id->driver_data) {
case ADP5585_02: case ADP5585_02:
kpad->support_row5 = true; kpad->support_row5 = true;
/* fall through */
case ADP5585_01: case ADP5585_01:
kpad->is_adp5585 = true; kpad->is_adp5585 = true;
kpad->var = &const_adp5585; kpad->var = &const_adp5585;

View File

@ -23,10 +23,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/module.h>

View File

@ -34,10 +34,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/module.h>

View File

@ -1,25 +1,15 @@
/* // SPDX-License-Identifier: GPL-2.0
* ChromeOS EC keyboard driver // ChromeOS EC keyboard driver
* //
* Copyright (C) 2012 Google, Inc // Copyright (C) 2012 Google, Inc.
* //
* This software is licensed under the terms of the GNU General Public // This driver uses the ChromeOS EC byte-level message-based protocol for
* License version 2, as published by the Free Software Foundation, and // communicating the keyboard state (which keys are pressed) from a keyboard EC
* may be copied, distributed, and modified under those terms. // 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
* This program is distributed in the hope that it will be useful, // motivation for this is to keep the EC firmware as simple as possible, since
* but WITHOUT ANY WARRANTY; without even the implied warranty of // it cannot be easily upgraded and EC flash/IRAM space is relatively
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // expensive.
* 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.
*/
#include <linux/module.h> #include <linux/module.h>
#include <linux/bitops.h> #include <linux/bitops.h>
@ -170,9 +160,6 @@ static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev,
int col, row; int col, row;
int new_state; int new_state;
int old_state; int old_state;
int num_cols;
num_cols = len;
if (ckdev->ghost_filter && cros_ec_keyb_has_ghosting(ckdev, kb_state)) { 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; u32 val;
unsigned int ev_type; 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) { switch (ckdev->ec->event_data.event_type) {
case EC_MKBP_EVENT_KEY_MATRIX: case EC_MKBP_EVENT_KEY_MATRIX:
if (device_may_wakeup(ckdev->dev)) { pm_wakeup_event(ckdev->dev, 0);
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;
}
if (ckdev->ec->event_size != ckdev->cols) { if (ckdev->ec->event_size != ckdev->cols) {
dev_err(ckdev->dev, dev_err(ckdev->dev,
@ -268,10 +253,7 @@ static int cros_ec_keyb_work(struct notifier_block *nb,
break; break;
case EC_MKBP_EVENT_SYSRQ: case EC_MKBP_EVENT_SYSRQ:
if (device_may_wakeup(ckdev->dev)) pm_wakeup_event(ckdev->dev, 0);
pm_wakeup_event(ckdev->dev, 0);
else if (queued_during_suspend)
return NOTIFY_OK;
val = get_unaligned_le32(&ckdev->ec->event_data.data.sysrq); val = get_unaligned_le32(&ckdev->ec->event_data.data.sysrq);
dev_dbg(ckdev->dev, "sysrq code from EC: %#x\n", val); 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_BUTTON:
case EC_MKBP_EVENT_SWITCH: case EC_MKBP_EVENT_SWITCH:
if (device_may_wakeup(ckdev->dev)) pm_wakeup_event(ckdev->dev, 0);
pm_wakeup_event(ckdev->dev, 0);
else if (queued_during_suspend)
return NOTIFY_OK;
if (ckdev->ec->event_data.event_type == EC_MKBP_EVENT_BUTTON) { if (ckdev->ec->event_data.event_type == EC_MKBP_EVENT_BUTTON) {
val = get_unaligned_le32( val = get_unaligned_le32(
@ -683,6 +662,6 @@ static struct platform_driver cros_ec_keyb_driver = {
module_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_DESCRIPTION("ChromeOS EC keyboard driver");
MODULE_ALIAS("platform:cros-ec-keyb"); MODULE_ALIAS("platform:cros-ec-keyb");

View File

@ -196,7 +196,7 @@ static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata,
ssize_t ret; ssize_t ret;
int i; int i;
bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL); bits = bitmap_zalloc(n_events, GFP_KERNEL);
if (!bits) if (!bits)
return -ENOMEM; return -ENOMEM;
@ -216,7 +216,7 @@ static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata,
buf[ret++] = '\n'; buf[ret++] = '\n';
buf[ret] = '\0'; buf[ret] = '\0';
kfree(bits); bitmap_free(bits);
return ret; return ret;
} }
@ -240,7 +240,7 @@ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata,
ssize_t error; ssize_t error;
int i; int i;
bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL); bits = bitmap_zalloc(n_events, GFP_KERNEL);
if (!bits) if (!bits)
return -ENOMEM; return -ENOMEM;
@ -284,7 +284,7 @@ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata,
mutex_unlock(&ddata->disable_lock); mutex_unlock(&ddata->disable_lock);
out: out:
kfree(bits); bitmap_free(bits);
return error; return error;
} }

View File

@ -1,11 +1,7 @@
/* // SPDX-License-Identifier: GPL-2.0
* Driver for the IMX keypad port. //
* Copyright (C) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com> // 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.
*/
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/delay.h> #include <linux/delay.h>

View File

@ -20,10 +20,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/slab.h>

View File

@ -1,14 +1,7 @@
/* // SPDX-License-Identifier: GPL-2.0+
* Driver for the IMX SNVS ON/OFF Power Key //
* Copyright (C) 2015 Freescale Semiconductor, Inc. All Rights Reserved. // 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
*/
#include <linux/device.h> #include <linux/device.h>
#include <linux/err.h> #include <linux/err.h>

View File

@ -23,10 +23,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/slab.h>

View File

@ -20,10 +20,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/delay.h>

View File

@ -20,10 +20,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/slab.h>

View File

@ -466,7 +466,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
remote->in_endpoint = endpoint; remote->in_endpoint = endpoint;
remote->toggle = -1; /* Set to -1 so we will always not match the toggle from the first remote message. */ 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) { if (!remote->in_buffer) {
error = -ENOMEM; error = -ENOMEM;
goto fail1; goto fail1;

View File

@ -20,6 +20,7 @@
#include <linux/log2.h> #include <linux/log2.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/regmap.h> #include <linux/regmap.h>
@ -28,6 +29,7 @@
#define PON_RT_STS 0x10 #define PON_RT_STS 0x10
#define PON_KPDPWR_N_SET BIT(0) #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_CTL 0x5a
#define PON_PS_HOLD_RST_CTL2 0x5b #define PON_PS_HOLD_RST_CTL2 0x5b
@ -38,10 +40,15 @@
#define PON_PULL_CTL 0x70 #define PON_PULL_CTL 0x70
#define PON_KPDPWR_PULL_UP BIT(1) #define PON_KPDPWR_PULL_UP BIT(1)
#define PON_RESIN_PULL_UP BIT(0)
#define PON_DBC_CTL 0x71 #define PON_DBC_CTL 0x71
#define PON_DBC_DELAY_MASK 0x7 #define PON_DBC_DELAY_MASK 0x7
struct pm8941_data {
unsigned int pull_up_bit;
unsigned int status_bit;
};
struct pm8941_pwrkey { struct pm8941_pwrkey {
struct device *dev; struct device *dev;
@ -52,6 +59,9 @@ struct pm8941_pwrkey {
unsigned int revision; unsigned int revision;
struct notifier_block reboot_notifier; struct notifier_block reboot_notifier;
u32 code;
const struct pm8941_data *data;
}; };
static int pm8941_reboot_notify(struct notifier_block *nb, 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) if (error)
return IRQ_HANDLED; 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); input_sync(pwrkey->input);
return IRQ_HANDLED; return IRQ_HANDLED;
@ -157,6 +168,7 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
{ {
struct pm8941_pwrkey *pwrkey; struct pm8941_pwrkey *pwrkey;
bool pull_up; bool pull_up;
struct device *parent;
u32 req_delay; u32 req_delay;
int error; int error;
@ -175,12 +187,30 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
pwrkey->dev = &pdev->dev; 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) { 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); pwrkey->irq = platform_get_irq(pdev, 0);
if (pwrkey->irq < 0) { if (pwrkey->irq < 0) {
@ -188,11 +218,6 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
return pwrkey->irq; 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, error = regmap_read(pwrkey->regmap, pwrkey->baseaddr + PON_REV2,
&pwrkey->revision); &pwrkey->revision);
if (error) { if (error) {
@ -200,13 +225,21 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
return error; 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); pwrkey->input = devm_input_allocate_device(&pdev->dev);
if (!pwrkey->input) { if (!pwrkey->input) {
dev_dbg(&pdev->dev, "unable to allocate input device\n"); dev_dbg(&pdev->dev, "unable to allocate input device\n");
return -ENOMEM; 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->name = "pm8941_pwrkey";
pwrkey->input->phys = "pm8941_pwrkey/input0"; 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, error = regmap_update_bits(pwrkey->regmap,
pwrkey->baseaddr + PON_PULL_CTL, pwrkey->baseaddr + PON_PULL_CTL,
PON_KPDPWR_PULL_UP, pwrkey->data->pull_up_bit,
pull_up ? PON_KPDPWR_PULL_UP : 0); pull_up ? pwrkey->data->pull_up_bit : 0);
if (error) { if (error) {
dev_err(&pdev->dev, "failed to set pull: %d\n", error); dev_err(&pdev->dev, "failed to set pull: %d\n", error);
return error; return error;
@ -271,8 +304,19 @@ static int pm8941_pwrkey_remove(struct platform_device *pdev)
return 0; 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[] = { 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); MODULE_DEVICE_TABLE(of, pm8941_pwr_key_id_table);

View File

@ -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) static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_device *pm)
{ {
pm->data = usb_alloc_coherent(udev, POWERMATE_PAYLOAD_SIZE_MAX, pm->data = usb_alloc_coherent(udev, POWERMATE_PAYLOAD_SIZE_MAX,
GFP_ATOMIC, &pm->data_dma); GFP_KERNEL, &pm->data_dma);
if (!pm->data) if (!pm->data)
return -1; return -1;

View File

@ -63,6 +63,9 @@ static void xenkbd_disconnect_backend(struct xenkbd_info *);
static void xenkbd_handle_motion_event(struct xenkbd_info *info, static void xenkbd_handle_motion_event(struct xenkbd_info *info,
struct xenkbd_motion *motion) 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_X, motion->rel_x);
input_report_rel(info->ptr, REL_Y, motion->rel_y); input_report_rel(info->ptr, REL_Y, motion->rel_y);
if (motion->rel_z) 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, static void xenkbd_handle_position_event(struct xenkbd_info *info,
struct xenkbd_position *pos) 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_X, pos->abs_x);
input_report_abs(info->ptr, ABS_Y, pos->abs_y); input_report_abs(info->ptr, ABS_Y, pos->abs_y);
if (pos->rel_z) if (pos->rel_z)
@ -97,6 +103,9 @@ static void xenkbd_handle_key_event(struct xenkbd_info *info,
return; return;
} }
if (unlikely(!dev))
return;
input_event(dev, EV_KEY, key->keycode, value); input_event(dev, EV_KEY, key->keycode, value);
input_sync(dev); input_sync(dev);
} }
@ -192,7 +201,7 @@ static int xenkbd_probe(struct xenbus_device *dev,
const struct xenbus_device_id *id) const struct xenbus_device_id *id)
{ {
int ret, i; int ret, i;
unsigned int abs, touch; bool with_mtouch, with_kbd, with_ptr;
struct xenkbd_info *info; struct xenkbd_info *info;
struct input_dev *kbd, *ptr, *mtouch; struct input_dev *kbd, *ptr, *mtouch;
@ -211,106 +220,127 @@ static int xenkbd_probe(struct xenbus_device *dev,
if (!info->page) if (!info->page)
goto error_nomem; goto error_nomem;
/* Set input abs params to match backend screen res */ /*
abs = xenbus_read_unsigned(dev->otherend, * The below are reverse logic, e.g. if the feature is set, then
XENKBD_FIELD_FEAT_ABS_POINTER, 0); * do not expose the corresponding virtual device.
ptr_size[KPARAM_X] = xenbus_read_unsigned(dev->otherend, */
XENKBD_FIELD_WIDTH, with_kbd = !xenbus_read_unsigned(dev->otherend,
ptr_size[KPARAM_X]); XENKBD_FIELD_FEAT_DSBL_KEYBRD, 0);
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;
}
}
touch = xenbus_read_unsigned(dev->nodename, with_ptr = !xenbus_read_unsigned(dev->otherend,
XENKBD_FIELD_FEAT_MTOUCH, 0); XENKBD_FIELD_FEAT_DSBL_POINTER, 0);
if (touch) {
/* 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, ret = xenbus_write(XBT_NIL, dev->nodename,
XENKBD_FIELD_REQ_MTOUCH, "1"); XENKBD_FIELD_REQ_MTOUCH, "1");
if (ret) { if (ret) {
pr_warn("xenkbd: can't request multi-touch"); pr_warn("xenkbd: can't request multi-touch");
touch = 0; with_mtouch = 0;
} }
} }
/* keyboard */ /* keyboard */
kbd = input_allocate_device(); if (with_kbd) {
if (!kbd) kbd = input_allocate_device();
goto error_nomem; if (!kbd)
kbd->name = "Xen Virtual Keyboard"; goto error_nomem;
kbd->phys = info->phys; kbd->name = "Xen Virtual Keyboard";
kbd->id.bustype = BUS_PCI; kbd->phys = info->phys;
kbd->id.vendor = 0x5853; kbd->id.bustype = BUS_PCI;
kbd->id.product = 0xffff; kbd->id.vendor = 0x5853;
kbd->id.product = 0xffff;
__set_bit(EV_KEY, kbd->evbit); __set_bit(EV_KEY, kbd->evbit);
for (i = KEY_ESC; i < KEY_UNKNOWN; i++) for (i = KEY_ESC; i < KEY_UNKNOWN; i++)
__set_bit(i, kbd->keybit); __set_bit(i, kbd->keybit);
for (i = KEY_OK; i < KEY_MAX; i++) for (i = KEY_OK; i < KEY_MAX; i++)
__set_bit(i, kbd->keybit); __set_bit(i, kbd->keybit);
ret = input_register_device(kbd); ret = input_register_device(kbd);
if (ret) { if (ret) {
input_free_device(kbd); input_free_device(kbd);
xenbus_dev_fatal(dev, ret, "input_register_device(kbd)"); xenbus_dev_fatal(dev, ret,
goto error; "input_register_device(kbd)");
goto error;
}
info->kbd = kbd;
} }
info->kbd = kbd;
/* pointing device */ /* pointing device */
ptr = input_allocate_device(); if (with_ptr) {
if (!ptr) unsigned int abs;
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 input abs params to match backend screen res */
__set_bit(EV_ABS, ptr->evbit); abs = xenbus_read_unsigned(dev->otherend,
input_set_abs_params(ptr, ABS_X, 0, ptr_size[KPARAM_X], 0, 0); XENKBD_FIELD_FEAT_ABS_POINTER, 0);
input_set_abs_params(ptr, ABS_Y, 0, ptr_size[KPARAM_Y], 0, 0); ptr_size[KPARAM_X] = xenbus_read_unsigned(dev->otherend,
} else { XENKBD_FIELD_WIDTH,
input_set_capability(ptr, EV_REL, REL_X); ptr_size[KPARAM_X]);
input_set_capability(ptr, EV_REL, REL_Y); 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 */ /* multi-touch device */
if (touch) { if (with_mtouch) {
int num_cont, width, height; int num_cont, width, height;
mtouch = input_allocate_device(); mtouch = input_allocate_device();
if (!mtouch) if (!mtouch)
goto error_nomem; goto error_nomem;
num_cont = xenbus_read_unsigned(info->xbdev->nodename, num_cont = xenbus_read_unsigned(info->xbdev->otherend,
XENKBD_FIELD_MT_NUM_CONTACTS, XENKBD_FIELD_MT_NUM_CONTACTS,
1); 1);
width = xenbus_read_unsigned(info->xbdev->nodename, width = xenbus_read_unsigned(info->xbdev->otherend,
XENKBD_FIELD_MT_WIDTH, XENKBD_FIELD_MT_WIDTH,
XENFB_WIDTH); XENFB_WIDTH);
height = xenbus_read_unsigned(info->xbdev->nodename, height = xenbus_read_unsigned(info->xbdev->otherend,
XENKBD_FIELD_MT_HEIGHT, XENKBD_FIELD_MT_HEIGHT,
XENFB_HEIGHT); XENFB_HEIGHT);
@ -346,6 +376,11 @@ static int xenkbd_probe(struct xenbus_device *dev,
info->mtouch = mtouch; info->mtouch = mtouch;
} }
if (!(with_kbd || with_ptr || with_mtouch)) {
ret = -ENXIO;
goto error;
}
ret = xenkbd_connect_backend(dev, info); ret = xenkbd_connect_backend(dev, info);
if (ret < 0) if (ret < 0)
goto error; goto error;

View File

@ -894,12 +894,12 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
/* allocate usb buffers */ /* allocate usb buffers */
yld->irq_data = usb_alloc_coherent(udev, USB_PKT_LEN, 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) if (yld->irq_data == NULL)
return usb_cleanup(yld, -ENOMEM); return usb_cleanup(yld, -ENOMEM);
yld->ctl_data = usb_alloc_coherent(udev, USB_PKT_LEN, yld->ctl_data = usb_alloc_coherent(udev, USB_PKT_LEN,
GFP_ATOMIC, &yld->ctl_dma); GFP_KERNEL, &yld->ctl_dma);
if (!yld->ctl_data) if (!yld->ctl_data)
return usb_cleanup(yld, -ENOMEM); return usb_cleanup(yld, -ENOMEM);

View File

@ -472,6 +472,7 @@ static int atp_status_check(struct urb *urb)
dev->info->datalen, dev->urb->actual_length); dev->info->datalen, dev->urb->actual_length);
dev->overflow_warned = true; dev->overflow_warned = true;
} }
/* fall through */
case -ECONNRESET: case -ECONNRESET:
case -ENOENT: case -ENOENT:
case -ESHUTDOWN: case -ESHUTDOWN:
@ -810,7 +811,7 @@ static int atp_open(struct input_dev *input)
{ {
struct atp *dev = input_get_drvdata(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; return -EIO;
dev->open = true; dev->open = true;
@ -976,7 +977,7 @@ static int atp_recover(struct atp *dev)
if (error) if (error)
return 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 -EIO;
return 0; return 0;
@ -994,7 +995,7 @@ static int atp_resume(struct usb_interface *iface)
{ {
struct atp *dev = usb_get_intfdata(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 -EIO;
return 0; return 0;

View File

@ -2554,6 +2554,7 @@ static int cyapa_gen5_do_operational_check(struct cyapa *cyapa)
} }
cyapa->state = CYAPA_STATE_GEN5_APP; cyapa->state = CYAPA_STATE_GEN5_APP;
/* fall through */
case CYAPA_STATE_GEN5_APP: case CYAPA_STATE_GEN5_APP:
/* /*

View File

@ -680,6 +680,7 @@ static int cyapa_gen6_operational_check(struct cyapa *cyapa)
} }
cyapa->state = CYAPA_STATE_GEN6_APP; cyapa->state = CYAPA_STATE_GEN6_APP;
/* fall through */
case CYAPA_STATE_GEN6_APP: case CYAPA_STATE_GEN6_APP:
/* /*

View File

@ -387,7 +387,7 @@ static int elan_smbus_prepare_fw_update(struct i2c_client *client)
len = i2c_smbus_read_block_data(client, len = i2c_smbus_read_block_data(client,
ETP_SMBUS_IAP_PASSWORD_READ, ETP_SMBUS_IAP_PASSWORD_READ,
val); val);
if (len < sizeof(u16)) { if (len < (int)sizeof(u16)) {
error = len < 0 ? len : -EIO; error = len < 0 ? len : -EIO;
dev_err(dev, "failed to read iap password: %d\n", dev_err(dev, "failed to read iap password: %d\n",
error); error);

View File

@ -340,7 +340,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
*/ */
if (packet[3] & 0x80) if (packet[3] & 0x80)
fingers = 4; fingers = 4;
/* pass through... */ /* fall through */
case 1: case 1:
/* /*
* byte 1: . . . . x11 x10 x9 x8 * byte 1: . . . . x11 x10 x9 x8

View File

@ -26,10 +26,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/module.h>

View File

@ -27,10 +27,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/module.h>

View File

@ -23,10 +23,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/module.h>

View File

@ -20,10 +20,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/delay.h>
@ -143,7 +139,8 @@ static void sermouse_process_ms(struct sermouse *sermouse, signed char data)
switch (sermouse->type) { switch (sermouse->type) {
case SERIO_MS: case SERIO_MS:
sermouse->type = SERIO_MP; sermouse->type = SERIO_MP;
/* fall through */
case SERIO_MP: case SERIO_MP:
if ((data >> 2) & 3) break; /* M++ Wireless Extension packet. */ 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_MZP:
case SERIO_MZPP: case SERIO_MZPP:
input_report_key(dev, BTN_SIDE, (data >> 5) & 1); input_report_key(dev, BTN_SIDE, (data >> 5) & 1);
/* fall through */
case SERIO_MZ: case SERIO_MZ:
input_report_key(dev, BTN_MIDDLE, (data >> 4) & 1); input_report_key(dev, BTN_MIDDLE, (data >> 4) & 1);

View File

@ -20,10 +20,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/delay.h>

View File

@ -573,6 +573,9 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id)
port = &i8042_ports[port_no]; port = &i8042_ports[port_no];
serio = port->exists ? port->serio : NULL; 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", filter_dbg(port->driver_bound, data, "<- i8042 (interrupt, %d, %d%s%s)\n",
port_no, irq, port_no, irq,
dfl & SERIO_PARITY ? ", bad parity" : "", dfl & SERIO_PARITY ? ", bad parity" : "",

View File

@ -23,10 +23,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/module.h>

View File

@ -21,10 +21,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/module.h>

View File

@ -20,10 +20,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

View File

@ -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, aiptek->data = usb_alloc_coherent(usbdev, AIPTEK_PACKET_LENGTH,
GFP_ATOMIC, &aiptek->data_dma); GFP_KERNEL, &aiptek->data_dma);
if (!aiptek->data) { if (!aiptek->data) {
dev_warn(&intf->dev, "cannot allocate usb buffer\n"); dev_warn(&intf->dev, "cannot allocate usb buffer\n");
goto fail1; goto fail1;

View File

@ -164,6 +164,18 @@ config TOUCHSCREEN_BU21013
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called bu21013_ts. 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 config TOUCHSCREEN_CHIPONE_ICN8318
tristate "chipone icn8318 touchscreen controller" tristate "chipone icn8318 touchscreen controller"
depends on GPIOLIB || COMPILE_TEST depends on GPIOLIB || COMPILE_TEST

View File

@ -19,6 +19,7 @@ obj-$(CONFIG_TOUCHSCREEN_AR1021_I2C) += ar1021_i2c.o
obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o
obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o
obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_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_ICN8318) += chipone_icn8318.o
obj-$(CONFIG_TOUCHSCREEN_CHIPONE_ICN8505) += chipone_icn8505.o obj-$(CONFIG_TOUCHSCREEN_CHIPONE_ICN8505) += chipone_icn8505.o
obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o

View File

@ -75,6 +75,7 @@
#define MXT_SPT_DIGITIZER_T43 43 #define MXT_SPT_DIGITIZER_T43 43
#define MXT_SPT_MESSAGECOUNT_T44 44 #define MXT_SPT_MESSAGECOUNT_T44 44
#define MXT_SPT_CTECONFIG_T46 46 #define MXT_SPT_CTECONFIG_T46 46
#define MXT_SPT_DYNAMICCONFIGURATIONCONTAINER_T71 71
#define MXT_TOUCH_MULTITOUCHSCREEN_T100 100 #define MXT_TOUCH_MULTITOUCHSCREEN_T100 100
/* MXT_GEN_MESSAGE_T5 object */ /* MXT_GEN_MESSAGE_T5 object */
@ -88,12 +89,12 @@
#define MXT_COMMAND_DIAGNOSTIC 5 #define MXT_COMMAND_DIAGNOSTIC 5
/* Define for T6 status byte */ /* Define for T6 status byte */
#define MXT_T6_STATUS_RESET (1 << 7) #define MXT_T6_STATUS_RESET BIT(7)
#define MXT_T6_STATUS_OFL (1 << 6) #define MXT_T6_STATUS_OFL BIT(6)
#define MXT_T6_STATUS_SIGERR (1 << 5) #define MXT_T6_STATUS_SIGERR BIT(5)
#define MXT_T6_STATUS_CAL (1 << 4) #define MXT_T6_STATUS_CAL BIT(4)
#define MXT_T6_STATUS_CFGERR (1 << 3) #define MXT_T6_STATUS_CFGERR BIT(3)
#define MXT_T6_STATUS_COMSERR (1 << 2) #define MXT_T6_STATUS_COMSERR BIT(2)
/* MXT_GEN_POWER_T7 field */ /* MXT_GEN_POWER_T7 field */
struct t7_config { struct t7_config {
@ -112,14 +113,14 @@ struct t7_config {
#define MXT_T9_RANGE 18 #define MXT_T9_RANGE 18
/* MXT_TOUCH_MULTI_T9 status */ /* MXT_TOUCH_MULTI_T9 status */
#define MXT_T9_UNGRIP (1 << 0) #define MXT_T9_UNGRIP BIT(0)
#define MXT_T9_SUPPRESS (1 << 1) #define MXT_T9_SUPPRESS BIT(1)
#define MXT_T9_AMP (1 << 2) #define MXT_T9_AMP BIT(2)
#define MXT_T9_VECTOR (1 << 3) #define MXT_T9_VECTOR BIT(3)
#define MXT_T9_MOVE (1 << 4) #define MXT_T9_MOVE BIT(4)
#define MXT_T9_RELEASE (1 << 5) #define MXT_T9_RELEASE BIT(5)
#define MXT_T9_PRESS (1 << 6) #define MXT_T9_PRESS BIT(6)
#define MXT_T9_DETECT (1 << 7) #define MXT_T9_DETECT BIT(7)
struct t9_range { struct t9_range {
__le16 x; __le16 x;
@ -127,9 +128,9 @@ struct t9_range {
} __packed; } __packed;
/* MXT_TOUCH_MULTI_T9 orient */ /* MXT_TOUCH_MULTI_T9 orient */
#define MXT_T9_ORIENT_SWITCH (1 << 0) #define MXT_T9_ORIENT_SWITCH BIT(0)
#define MXT_T9_ORIENT_INVERTX (1 << 1) #define MXT_T9_ORIENT_INVERTX BIT(1)
#define MXT_T9_ORIENT_INVERTY (1 << 2) #define MXT_T9_ORIENT_INVERTY BIT(2)
/* MXT_SPT_COMMSCONFIG_T18 */ /* MXT_SPT_COMMSCONFIG_T18 */
#define MXT_COMMS_CTRL 0 #define MXT_COMMS_CTRL 0
@ -214,7 +215,7 @@ enum t100_type {
#define MXT_FRAME_CRC_PASS 0x04 #define MXT_FRAME_CRC_PASS 0x04
#define MXT_APP_CRC_FAIL 0x40 /* valid 7 8 bit only */ #define MXT_APP_CRC_FAIL 0x40 /* valid 7 8 bit only */
#define MXT_BOOT_STATUS_MASK 0x3f #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 #define MXT_BOOT_ID_MASK 0x1f
/* Touchscreen absolute values */ /* Touchscreen absolute values */
@ -276,6 +277,19 @@ enum mxt_suspend_mode {
MXT_SUSPEND_T9_CTRL = 1, 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 */ /* Each client has this additional data */
struct mxt_data { struct mxt_data {
struct i2c_client *client; struct i2c_client *client;
@ -317,6 +331,7 @@ struct mxt_data {
u8 T6_reportid; u8 T6_reportid;
u16 T6_address; u16 T6_address;
u16 T7_address; u16 T7_address;
u16 T71_address;
u8 T9_reportid_min; u8 T9_reportid_min;
u8 T9_reportid_max; u8 T9_reportid_max;
u8 T19_reportid; u8 T19_reportid;
@ -382,6 +397,7 @@ static bool mxt_object_readable(unsigned int type)
case MXT_SPT_USERDATA_T38: case MXT_SPT_USERDATA_T38:
case MXT_SPT_DIGITIZER_T43: case MXT_SPT_DIGITIZER_T43:
case MXT_SPT_CTECONFIG_T46: case MXT_SPT_CTECONFIG_T46:
case MXT_SPT_DYNAMICCONFIGURATIONCONTAINER_T71:
return true; return true;
default: default:
return false; return false;
@ -712,13 +728,13 @@ static void mxt_proc_t6_messages(struct mxt_data *data, u8 *msg)
u8 status = msg[1]; u8 status = msg[1];
u32 crc = msg[2] | (msg[3] << 8) | (msg[4] << 16); u32 crc = msg[2] | (msg[3] << 8) | (msg[4] << 16);
complete(&data->crc_completion);
if (crc != data->config_crc) { if (crc != data->config_crc) {
data->config_crc = crc; data->config_crc = crc;
dev_dbg(dev, "T6 Config Checksum: 0x%06X\n", crc); dev_dbg(dev, "T6 Config Checksum: 0x%06X\n", crc);
} }
complete(&data->crc_completion);
/* Detect reset */ /* Detect reset */
if (status & MXT_T6_STATUS_RESET) if (status & MXT_T6_STATUS_RESET)
complete(&data->reset_completion); complete(&data->reset_completion);
@ -827,6 +843,10 @@ static void mxt_proc_t9_message(struct mxt_data *data, u8 *message)
mxt_input_sync(data); mxt_input_sync(data);
} }
/* if active, pressure must be non-zero */
if (!amplitude)
amplitude = MXT_PRESSURE_DEFAULT;
/* Touch active */ /* Touch active */
input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 1); input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 1);
input_report_abs(input_dev, ABS_MT_POSITION_X, x); 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; return crc;
} }
static int mxt_prepare_cfg_mem(struct mxt_data *data, static int mxt_prepare_cfg_mem(struct mxt_data *data, struct mxt_cfg *cfg)
const struct firmware *cfg,
unsigned int data_pos,
unsigned int cfg_start_ofs,
u8 *config_mem,
size_t config_mem_size)
{ {
struct device *dev = &data->client->dev; struct device *dev = &data->client->dev;
struct mxt_object *object; struct mxt_object *object;
@ -1295,9 +1310,9 @@ static int mxt_prepare_cfg_mem(struct mxt_data *data,
u16 reg; u16 reg;
u8 val; u8 val;
while (data_pos < cfg->size) { while (cfg->raw_pos < cfg->raw_size) {
/* Read type, instance, length */ /* 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); &type, &instance, &size, &offset);
if (ret == 0) { if (ret == 0) {
/* EOF */ /* 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"); dev_err(dev, "Bad format: failed to parse object\n");
return -EINVAL; return -EINVAL;
} }
data_pos += offset; cfg->raw_pos += offset;
object = mxt_get_object(data, type); object = mxt_get_object(data, type);
if (!object) { if (!object) {
/* Skip object */ /* Skip object */
for (i = 0; i < size; i++) { 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); &val, &offset);
if (ret != 1) { if (ret != 1) {
dev_err(dev, "Bad format in T%d at %d\n", dev_err(dev, "Bad format in T%d at %d\n",
type, i); type, i);
return -EINVAL; return -EINVAL;
} }
data_pos += offset; cfg->raw_pos += offset;
} }
continue; continue;
} }
@ -1354,7 +1369,7 @@ static int mxt_prepare_cfg_mem(struct mxt_data *data,
reg = object->start_address + mxt_obj_size(object) * instance; reg = object->start_address + mxt_obj_size(object) * instance;
for (i = 0; i < size; i++) { for (i = 0; i < size; i++) {
ret = sscanf(cfg->data + data_pos, "%hhx%n", ret = sscanf(cfg->raw + cfg->raw_pos, "%hhx%n",
&val, &val,
&offset); &offset);
if (ret != 1) { if (ret != 1) {
@ -1362,15 +1377,15 @@ static int mxt_prepare_cfg_mem(struct mxt_data *data,
type, i); type, i);
return -EINVAL; return -EINVAL;
} }
data_pos += offset; cfg->raw_pos += offset;
if (i > mxt_obj_size(object)) if (i > mxt_obj_size(object))
continue; continue;
byte_offset = reg + i - cfg_start_ofs; byte_offset = reg + i - cfg->start_ofs;
if (byte_offset >= 0 && byte_offset < config_mem_size) { if (byte_offset >= 0 && byte_offset < cfg->mem_size) {
*(config_mem + byte_offset) = val; *(cfg->mem + byte_offset) = val;
} else { } else {
dev_err(dev, "Bad object: reg:%d, T%d, ofs=%d\n", dev_err(dev, "Bad object: reg:%d, T%d, ofs=%d\n",
reg, object->type, byte_offset); reg, object->type, byte_offset);
@ -1382,22 +1397,21 @@ static int mxt_prepare_cfg_mem(struct mxt_data *data,
return 0; return 0;
} }
static int mxt_upload_cfg_mem(struct mxt_data *data, unsigned int cfg_start, static int mxt_upload_cfg_mem(struct mxt_data *data, struct mxt_cfg *cfg)
u8 *config_mem, size_t config_mem_size)
{ {
unsigned int byte_offset = 0; unsigned int byte_offset = 0;
int error; int error;
/* Write configuration as blocks */ /* Write configuration as blocks */
while (byte_offset < config_mem_size) { while (byte_offset < cfg->mem_size) {
unsigned int size = config_mem_size - byte_offset; unsigned int size = cfg->mem_size - byte_offset;
if (size > MXT_MAX_BLOCK_WRITE) if (size > MXT_MAX_BLOCK_WRITE)
size = MXT_MAX_BLOCK_WRITE; size = MXT_MAX_BLOCK_WRITE;
error = __mxt_write_reg(data->client, error = __mxt_write_reg(data->client,
cfg_start + byte_offset, cfg->start_ofs + byte_offset,
size, config_mem + byte_offset); size, cfg->mem + byte_offset);
if (error) { if (error) {
dev_err(&data->client->dev, dev_err(&data->client->dev,
"Config write error, ret=%d\n", error); "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 * <SIZE> - 2-byte object size as hex
* <CONTENTS> - array of <SIZE> 1-byte hex values * <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 device *dev = &data->client->dev;
struct mxt_info cfg_info; struct mxt_cfg cfg;
int ret; int ret;
int offset; int offset;
int data_pos;
int i; int i;
int cfg_start_ofs;
u32 info_crc, config_crc, calculated_crc; u32 info_crc, config_crc, calculated_crc;
u8 *config_mem; u16 crc_start = 0;
size_t config_mem_size;
/* 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); 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"); 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 */ /* Load information block and check */
for (i = 0; i < sizeof(struct mxt_info); i++) { for (i = 0; i < sizeof(struct mxt_info); i++) {
ret = sscanf(cfg->data + data_pos, "%hhx%n", ret = sscanf(cfg.raw + cfg.raw_pos, "%hhx%n",
(unsigned char *)&cfg_info + i, (unsigned char *)&cfg.info + i,
&offset); &offset);
if (ret != 1) { if (ret != 1) {
dev_err(dev, "Bad format\n"); 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"); 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"); dev_err(dev, "Variant ID mismatch!\n");
return -EINVAL; ret = -EINVAL;
goto release_raw;
} }
/* Read CRCs */ /* 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) { if (ret != 1) {
dev_err(dev, "Bad format: failed to parse Info CRC\n"); 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) { if (ret != 1) {
dev_err(dev, "Bad format: failed to parse Config CRC\n"); 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 * 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 */ /* 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) + data->info->object_num * sizeof(struct mxt_object) +
MXT_INFO_CHECKSUM_SIZE; MXT_INFO_CHECKSUM_SIZE;
config_mem_size = data->mem_size - cfg_start_ofs; cfg.mem_size = data->mem_size - cfg.start_ofs;
config_mem = kzalloc(config_mem_size, GFP_KERNEL); cfg.mem = kzalloc(cfg.mem_size, GFP_KERNEL);
if (!config_mem) { if (!cfg.mem) {
dev_err(dev, "Failed to allocate memory\n"); ret = -ENOMEM;
return -ENOMEM; goto release_raw;
} }
ret = mxt_prepare_cfg_mem(data, cfg, data_pos, cfg_start_ofs, ret = mxt_prepare_cfg_mem(data, &cfg);
config_mem, config_mem_size);
if (ret) if (ret)
goto release_mem; goto release_mem;
/* Calculate crc of the received configs (not the raw config file) */ /* Calculate crc of the received configs (not the raw config file) */
if (data->T7_address < cfg_start_ofs) { if (data->T71_address)
dev_err(dev, "Bad T7 address, T7addr = %x, config offset %x\n", crc_start = data->T71_address;
data->T7_address, cfg_start_ofs); else if (data->T7_address)
ret = 0; crc_start = data->T7_address;
goto release_mem; 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, ret = mxt_upload_cfg_mem(data, &cfg);
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);
if (ret) if (ret)
goto release_mem; 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 */ /* T7 config may have changed */
mxt_init_t7_power_cfg(data); mxt_init_t7_power_cfg(data);
release_raw:
kfree(cfg.raw);
release_mem: release_mem:
kfree(config_mem); kfree(cfg.mem);
return ret; return ret;
} }
@ -1591,6 +1617,7 @@ static void mxt_free_object_table(struct mxt_data *data)
data->T5_msg_size = 0; data->T5_msg_size = 0;
data->T6_reportid = 0; data->T6_reportid = 0;
data->T7_address = 0; data->T7_address = 0;
data->T71_address = 0;
data->T9_reportid_min = 0; data->T9_reportid_min = 0;
data->T9_reportid_max = 0; data->T9_reportid_max = 0;
data->T19_reportid = 0; data->T19_reportid = 0;
@ -1656,12 +1683,16 @@ static int mxt_parse_object_table(struct mxt_data *data,
case MXT_GEN_POWER_T7: case MXT_GEN_POWER_T7:
data->T7_address = object->start_address; data->T7_address = object->start_address;
break; break;
case MXT_SPT_DYNAMICCONFIGURATIONCONTAINER_T71:
data->T71_address = object->start_address;
break;
case MXT_TOUCH_MULTI_T9: case MXT_TOUCH_MULTI_T9:
data->multitouch = 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_min = min_id;
data->T9_reportid_max = max_id; data->T9_reportid_max = min_id +
data->num_touchids = object->num_report_ids object->num_report_ids - 1;
* mxt_obj_instances(object); data->num_touchids = object->num_report_ids;
break; break;
case MXT_SPT_MESSAGECOUNT_T44: case MXT_SPT_MESSAGECOUNT_T44:
data->T44_address = object->start_address; data->T44_address = object->start_address;
@ -1981,10 +2012,8 @@ static int mxt_initialize_input_device(struct mxt_data *data)
/* Register input device */ /* Register input device */
input_dev = input_allocate_device(); input_dev = input_allocate_device();
if (!input_dev) { if (!input_dev)
dev_err(dev, "Failed to allocate memory\n");
return -ENOMEM; return -ENOMEM;
}
input_dev->name = "Atmel maXTouch Touchscreen"; input_dev->name = "Atmel maXTouch Touchscreen";
input_dev->phys = data->phys; input_dev->phys = data->phys;
@ -2054,12 +2083,6 @@ static int mxt_initialize_input_device(struct mxt_data *data)
0, 255, 0, 0); 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 && if (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 &&
data->t100_aux_vect) { data->t100_aux_vect) {
input_set_abs_params(input_dev, ABS_MT_ORIENTATION, input_set_abs_params(input_dev, ABS_MT_ORIENTATION,

View File

@ -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");

View File

@ -1,9 +1,9 @@
/* /*
* Touch Screen driver for EETI's I2C connected touch screen panels * 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: * 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 * Based on migor_ts.c
* Copyright (c) 2008 Magnus Damm * Copyright (c) 2008 Magnus Damm
@ -25,28 +25,22 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/input/touchscreen.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/of.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <asm/unaligned.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 eeti_ts {
struct i2c_client *client; struct i2c_client *client;
struct input_dev *input; struct input_dev *input;
struct gpio_desc *attn_gpio; struct gpio_desc *attn_gpio;
struct touchscreen_properties props;
bool running; bool running;
}; };
@ -73,17 +67,10 @@ static void eeti_ts_report_event(struct eeti_ts *eeti, u8 *buf)
x >>= res - EETI_TS_BITDEPTH; x >>= res - EETI_TS_BITDEPTH;
y >>= 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) if (buf[0] & REPORT_BIT_HAS_PRESSURE)
input_report_abs(eeti->input, ABS_PRESSURE, buf[5]); input_report_abs(eeti->input, ABS_PRESSURE, buf[5]);
input_report_abs(eeti->input, ABS_X, x); touchscreen_report_pos(eeti->input, &eeti->props, x, y, false);
input_report_abs(eeti->input, ABS_Y, y);
input_report_key(eeti->input, BTN_TOUCH, buf[0] & REPORT_BIT_PRESSED); input_report_key(eeti->input, BTN_TOUCH, buf[0] & REPORT_BIT_PRESSED);
input_sync(eeti->input); 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_Y, 0, EETI_MAXVAL, 0, 0);
input_set_abs_params(input, ABS_PRESSURE, 0, 0xff, 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->name = client->name;
input->id.bustype = BUS_I2C; input->id.bustype = BUS_I2C;
input->open = eeti_ts_open; 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); 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 = { static struct i2c_driver eeti_ts_driver = {
.driver = { .driver = {
.name = "eeti_ts", .name = "eeti_ts",
.pm = &eeti_ts_pm, .pm = &eeti_ts_pm,
.of_match_table = of_match_ptr(of_eeti_ts_match),
}, },
.probe = eeti_ts_probe, .probe = eeti_ts_probe,
.id_table = eeti_ts_id, .id_table = eeti_ts_id,
@ -274,5 +271,5 @@ static struct i2c_driver eeti_ts_driver = {
module_i2c_driver(eeti_ts_driver); module_i2c_driver(eeti_ts_driver);
MODULE_DESCRIPTION("EETI Touchscreen driver"); MODULE_DESCRIPTION("EETI Touchscreen driver");
MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); MODULE_AUTHOR("Daniel Mack <daniel@zonque.org>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

View File

@ -1,13 +1,10 @@
// SPDX-License-Identifier: GPL-2.0
/* /*
* Driver for EETI eGalax Multiple Touch Controller * Driver for EETI eGalax Multiple Touch Controller
* *
* Copyright (C) 2011 Freescale Semiconductor, Inc. * Copyright (C) 2011 Freescale Semiconductor, Inc.
* *
* based on max11801_ts.c * 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 /* EETI eGalax serial touch screen controller is a I2C based multiple

View File

@ -352,6 +352,7 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv)
case 1: /* 6-byte protocol */ case 1: /* 6-byte protocol */
input_set_abs_params(input_dev, ABS_PRESSURE, 0, 15, 0, 0); input_set_abs_params(input_dev, ABS_PRESSURE, 0, 15, 0, 0);
/* fall through */
case 2: /* 4-byte protocol */ case 2: /* 4-byte protocol */
input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0); input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0);

View File

@ -1,16 +1,11 @@
/* // SPDX-License-Identifier: GPL-2.0
* Copyright (C) 2014-2015 Pengutronix, Markus Pargmann <mpa@pengutronix.de> //
* // Copyright (C) 2014-2015 Pengutronix, Markus Pargmann <mpa@pengutronix.de>
* This program is free software; you can redistribute it and/or modify it under // Based on driver from 2011:
* the terms of the GNU General Public License version 2 as published by the // Juergen Beisert, Pengutronix <kernel@pengutronix.de>
* Free Software Foundation. //
* // This is the driver for the imx25 TCQ (Touchscreen Conversion Queue)
* Based on driver from 2011: // connected to the imx25 ADC.
* 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/clk.h>
#include <linux/device.h> #include <linux/device.h>

View File

@ -20,10 +20,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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> #include <linux/errno.h>

View File

@ -1,12 +1,8 @@
/* // SPDX-License-Identifier: GPL-2.0
* Freescale i.MX6UL touchscreen controller driver //
* // Freescale i.MX6UL touchscreen controller driver
* Copyright (C) 2015 Freescale Semiconductor, Inc. //
* // 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.
*/
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/kernel.h> #include <linux/kernel.h>

View File

@ -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) 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) static int raydium_i2c_check_path(struct i2c_client *client)

View File

@ -1142,7 +1142,7 @@ static int __maybe_unused wdt87xx_resume(struct device *dev)
* The chip may have been reset while system is resuming, * The chip may have been reset while system is resuming,
* give it some time to settle. * give it some time to settle.
*/ */
mdelay(100); msleep(100);
error = wdt87xx_send_command(client, VND_CMD_START, 0); error = wdt87xx_send_command(client, VND_CMD_START, 0);
if (error) if (error)

View File

@ -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 */ /* Try loading the bitmap unless "raid0", which does not have one */
if (!rs_is_raid0(rs) && if (!rs_is_raid0(rs) &&
!test_and_set_bit(RT_FLAG_RS_BITMAP_LOADED, &rs->runtime_flags)) { !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) if (r)
DMERR("Failed to load bitmap"); 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) */ /* 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 && if (test_bit(RT_FLAG_RS_BITMAP_LOADED, &rs->runtime_flags) && mddev->bitmap &&
mddev->bitmap_info.chunksize != to_bytes(rs->requested_bitmap_chunk_sectors)) { mddev->bitmap_info.chunksize != to_bytes(rs->requested_bitmap_chunk_sectors)) {
r = bitmap_resize(mddev->bitmap, mddev->dev_sectors, r = md_bitmap_resize(mddev->bitmap, mddev->dev_sectors,
to_bytes(rs->requested_bitmap_chunk_sectors), 0); to_bytes(rs->requested_bitmap_chunk_sectors), 0);
if (r) if (r)
DMERR("Failed to resize bitmap"); DMERR("Failed to resize bitmap");
} }

View File

@ -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 * if we find our page, we increment the page's refcount so that it stays
* allocated while we're using it * allocated while we're using it
*/ */
static int bitmap_checkpage(struct bitmap_counts *bitmap, static int md_bitmap_checkpage(struct bitmap_counts *bitmap,
unsigned long page, int create, int no_hijack) unsigned long page, int create, int no_hijack)
__releases(bitmap->lock) __releases(bitmap->lock)
__acquires(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 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 */ /* if page was hijacked, unmark the flag so it might get alloced next time */
/* Note: lock should be held when calling this */ /* 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; char *ptr;
@ -280,7 +280,7 @@ restart:
return -EINVAL; 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 * 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); atomic_read(&bitmap->pending_writes)==0);
} }
if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags)) 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) static void end_bitmap_write(struct buffer_head *bh, int uptodate)
@ -421,11 +421,11 @@ out:
*/ */
/* /*
* 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 * 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) if (bitmap->storage.file)
wait_event(bitmap->write_wait, 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 */ /* 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; bitmap_super_t *sb;
@ -476,10 +476,10 @@ void bitmap_update_sb(struct bitmap *bitmap)
kunmap_atomic(sb); kunmap_atomic(sb);
write_page(bitmap, bitmap->storage.sb_page, 1); 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 */ /* 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; bitmap_super_t *sb;
@ -518,7 +518,7 @@ void bitmap_print_sb(struct bitmap *bitmap)
* *
* Returns: 0 on success, -Exxx on error * 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; bitmap_super_t *sb;
unsigned long chunksize, daemon_sleep, write_behind; 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 */ /* 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; char *reason = NULL;
bitmap_super_t *sb; bitmap_super_t *sb;
@ -727,7 +727,7 @@ out_no_sb:
bitmap->mddev->bitmap_info.space > sectors_reserved) bitmap->mddev->bitmap_info.space > sectors_reserved)
bitmap->mddev->bitmap_info.space = sectors_reserved; bitmap->mddev->bitmap_info.space = sectors_reserved;
if (err) { if (err) {
bitmap_print_sb(bitmap); md_bitmap_print_sb(bitmap);
if (bitmap->cluster_slot < 0) if (bitmap->cluster_slot < 0)
md_cluster_stop(bitmap->mddev); 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)]; return store->filemap[file_page_index(store, chunk)];
} }
static int bitmap_storage_alloc(struct bitmap_storage *store, static int md_bitmap_storage_alloc(struct bitmap_storage *store,
unsigned long chunks, int with_super, unsigned long chunks, int with_super,
int slot_number) int slot_number)
{ {
int pnum, offset = 0; int pnum, offset = 0;
unsigned long num_pages; unsigned long num_pages;
@ -830,7 +830,7 @@ static int bitmap_storage_alloc(struct bitmap_storage *store,
return 0; 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; struct page **map, *sb_page;
int pages; 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 * then it is no longer reliable, so we stop using it and we mark the file
* as failed in the superblock * 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; char *path, *ptr = NULL;
if (!test_and_set_bit(BITMAP_STALE, &bitmap->flags)) { if (!test_and_set_bit(BITMAP_STALE, &bitmap->flags)) {
bitmap_update_sb(bitmap); md_bitmap_update_sb(bitmap);
if (bitmap->storage.file) { if (bitmap->storage.file) {
path = kmalloc(PAGE_SIZE, GFP_KERNEL); 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 * 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 * 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; unsigned long bit;
struct page *page; 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); 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; unsigned long bit;
struct page *page; 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; unsigned long bit;
struct page *page; 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 /* 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 * (slave) device queues -- before we let any writes go down, we need to
* sync the dirty pages of the bitmap file to disk */ * 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; unsigned long i;
int dirty, need_write; int dirty, need_write;
@ -1025,7 +1025,7 @@ void bitmap_unplug(struct bitmap *bitmap)
BITMAP_PAGE_NEEDWRITE); BITMAP_PAGE_NEEDWRITE);
if (dirty || need_write) { if (dirty || need_write) {
if (!writing) { if (!writing) {
bitmap_wait_writes(bitmap); md_bitmap_wait_writes(bitmap);
if (bitmap->mddev->queue) if (bitmap->mddev->queue)
blk_add_trace_msg(bitmap->mddev->queue, blk_add_trace_msg(bitmap->mddev->queue,
"md bitmap_unplug"); "md bitmap_unplug");
@ -1036,14 +1036,14 @@ void bitmap_unplug(struct bitmap *bitmap)
} }
} }
if (writing) if (writing)
bitmap_wait_writes(bitmap); md_bitmap_wait_writes(bitmap);
if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags)) 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 /* * bitmap_init_from_disk -- called at bitmap_create time to initialize
* the in-memory bitmap from the on-disk bitmap -- also, sets up the * the in-memory bitmap from the on-disk bitmap -- also, sets up the
* memory mapping of the bitmap file * 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'. * We ignore all bits for sectors that end earlier than 'start'.
* This is used when reading an out-of-date bitmap... * 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; unsigned long i, chunks, index, oldindex, bit, node_offset = 0;
struct page *page = NULL; 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 */ /* if the disk bit is set, set the memory bit */
int needed = ((sector_t)(i+1) << (bitmap->counts.chunkshift) int needed = ((sector_t)(i+1) << (bitmap->counts.chunkshift)
>= start); >= start);
bitmap_set_memory_bits(bitmap, md_bitmap_set_memory_bits(bitmap,
(sector_t)i << bitmap->counts.chunkshift, (sector_t)i << bitmap->counts.chunkshift,
needed); needed);
} }
return 0; 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 */ /* if the disk bit is set, set the memory bit */
int needed = ((sector_t)(i+1) << bitmap->counts.chunkshift int needed = ((sector_t)(i+1) << bitmap->counts.chunkshift
>= start); >= start);
bitmap_set_memory_bits(bitmap, md_bitmap_set_memory_bits(bitmap,
(sector_t)i << bitmap->counts.chunkshift, (sector_t)i << bitmap->counts.chunkshift,
needed); needed);
bit_cnt++; bit_cnt++;
} }
offset = 0; offset = 0;
@ -1179,7 +1179,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
return ret; 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, /* We don't actually write all bitmap blocks here,
* just flag them as needing to be written * just flag them as needing to be written
@ -1198,16 +1198,16 @@ void bitmap_write_all(struct bitmap *bitmap)
bitmap->allclean = 0; bitmap->allclean = 0;
} }
static void bitmap_count_page(struct bitmap_counts *bitmap, static void md_bitmap_count_page(struct bitmap_counts *bitmap,
sector_t offset, int inc) sector_t offset, int inc)
{ {
sector_t chunk = offset >> bitmap->chunkshift; sector_t chunk = offset >> bitmap->chunkshift;
unsigned long page = chunk >> PAGE_COUNTER_SHIFT; unsigned long page = chunk >> PAGE_COUNTER_SHIFT;
bitmap->bp[page].count += inc; 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; sector_t chunk = offset >> bitmap->chunkshift;
unsigned long page = chunk >> PAGE_COUNTER_SHIFT; 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; bp->pending = 1;
} }
static bitmap_counter_t *bitmap_get_counter(struct bitmap_counts *bitmap, static bitmap_counter_t *md_bitmap_get_counter(struct bitmap_counts *bitmap,
sector_t offset, sector_t *blocks, sector_t offset, sector_t *blocks,
int create); int create);
/* /*
* bitmap daemon -- periodically wakes up to clean bits and flush pages * bitmap daemon -- periodically wakes up to clean bits and flush pages
* out to disk * out to disk
*/ */
void bitmap_daemon_work(struct mddev *mddev) void md_bitmap_daemon_work(struct mddev *mddev)
{ {
struct bitmap *bitmap; struct bitmap *bitmap;
unsigned long j; unsigned long j;
@ -1301,10 +1301,8 @@ void bitmap_daemon_work(struct mddev *mddev)
} }
counts->bp[j >> PAGE_COUNTER_SHIFT].pending = 0; 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) { if (!bmc) {
j |= PAGE_COUNTER_MASK; j |= PAGE_COUNTER_MASK;
continue; continue;
@ -1312,17 +1310,17 @@ void bitmap_daemon_work(struct mddev *mddev)
if (*bmc == 1 && !bitmap->need_sync) { if (*bmc == 1 && !bitmap->need_sync) {
/* We can clear the bit */ /* We can clear the bit */
*bmc = 0; *bmc = 0;
bitmap_count_page(counts, block, -1); md_bitmap_count_page(counts, block, -1);
bitmap_file_clear_bit(bitmap, block); md_bitmap_file_clear_bit(bitmap, block);
} else if (*bmc && *bmc <= 2) { } else if (*bmc && *bmc <= 2) {
*bmc = 1; *bmc = 1;
bitmap_set_pending(counts, block); md_bitmap_set_pending(counts, block);
bitmap->allclean = 0; bitmap->allclean = 0;
} }
} }
spin_unlock_irq(&counts->lock); 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. /* 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 * DIRTY pages need to be written by bitmap_unplug so it can wait
* for them. * for them.
@ -1352,9 +1350,9 @@ void bitmap_daemon_work(struct mddev *mddev)
mutex_unlock(&mddev->bitmap_info.mutex); mutex_unlock(&mddev->bitmap_info.mutex);
} }
static bitmap_counter_t *bitmap_get_counter(struct bitmap_counts *bitmap, static bitmap_counter_t *md_bitmap_get_counter(struct bitmap_counts *bitmap,
sector_t offset, sector_t *blocks, sector_t offset, sector_t *blocks,
int create) int create)
__releases(bitmap->lock) __releases(bitmap->lock)
__acquires(bitmap->lock) __acquires(bitmap->lock)
{ {
@ -1368,7 +1366,7 @@ __acquires(bitmap->lock)
sector_t csize; sector_t csize;
int err; int err;
err = bitmap_checkpage(bitmap, page, create, 0); err = md_bitmap_checkpage(bitmap, page, create, 0);
if (bitmap->bp[page].hijacked || if (bitmap->bp[page].hijacked ||
bitmap->bp[page].map == NULL) bitmap->bp[page].map == NULL)
@ -1394,7 +1392,7 @@ __acquires(bitmap->lock)
&(bitmap->bp[page].map[pageoff]); &(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) if (!bitmap)
return 0; return 0;
@ -1415,7 +1413,7 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
bitmap_counter_t *bmc; bitmap_counter_t *bmc;
spin_lock_irq(&bitmap->counts.lock); 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) { if (!bmc) {
spin_unlock_irq(&bitmap->counts.lock); spin_unlock_irq(&bitmap->counts.lock);
return 0; return 0;
@ -1437,8 +1435,8 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
switch (*bmc) { switch (*bmc) {
case 0: case 0:
bitmap_file_set_bit(bitmap, offset); md_bitmap_file_set_bit(bitmap, offset);
bitmap_count_page(&bitmap->counts, offset, 1); md_bitmap_count_page(&bitmap->counts, offset, 1);
/* fall through */ /* fall through */
case 1: case 1:
*bmc = 2; *bmc = 2;
@ -1456,10 +1454,10 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
} }
return 0; return 0;
} }
EXPORT_SYMBOL(bitmap_startwrite); EXPORT_SYMBOL(md_bitmap_startwrite);
void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors, void md_bitmap_endwrite(struct bitmap *bitmap, sector_t offset,
int success, int behind) unsigned long sectors, int success, int behind)
{ {
if (!bitmap) if (!bitmap)
return; return;
@ -1477,7 +1475,7 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto
bitmap_counter_t *bmc; bitmap_counter_t *bmc;
spin_lock_irqsave(&bitmap->counts.lock, flags); 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) { if (!bmc) {
spin_unlock_irqrestore(&bitmap->counts.lock, flags); spin_unlock_irqrestore(&bitmap->counts.lock, flags);
return; return;
@ -1498,7 +1496,7 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto
(*bmc)--; (*bmc)--;
if (*bmc <= 2) { if (*bmc <= 2) {
bitmap_set_pending(&bitmap->counts, offset); md_bitmap_set_pending(&bitmap->counts, offset);
bitmap->allclean = 0; bitmap->allclean = 0;
} }
spin_unlock_irqrestore(&bitmap->counts.lock, flags); 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; 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, static int __bitmap_start_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks,
int degraded) 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 */ return 1; /* always resync if no bitmap */
} }
spin_lock_irq(&bitmap->counts.lock); 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; rv = 0;
if (bmc) { if (bmc) {
/* locked */ /* locked */
@ -1539,8 +1537,8 @@ static int __bitmap_start_sync(struct bitmap *bitmap, sector_t offset, sector_t
return rv; return rv;
} }
int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, int md_bitmap_start_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks,
int degraded) int degraded)
{ {
/* bitmap_start_sync must always report on multiples of whole /* bitmap_start_sync must always report on multiples of whole
* pages, otherwise resync (which is very PAGE_SIZE based) will * 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; 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; bitmap_counter_t *bmc;
unsigned long flags; unsigned long flags;
@ -1573,7 +1571,7 @@ void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, i
return; return;
} }
spin_lock_irqsave(&bitmap->counts.lock, flags); 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) if (bmc == NULL)
goto unlock; goto unlock;
/* locked */ /* locked */
@ -1584,7 +1582,7 @@ void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, i
*bmc |= NEEDED_MASK; *bmc |= NEEDED_MASK;
else { else {
if (*bmc <= 2) { if (*bmc <= 2) {
bitmap_set_pending(&bitmap->counts, offset); md_bitmap_set_pending(&bitmap->counts, offset);
bitmap->allclean = 0; bitmap->allclean = 0;
} }
} }
@ -1592,9 +1590,9 @@ void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, i
unlock: unlock:
spin_unlock_irqrestore(&bitmap->counts.lock, flags); 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 /* Sync has finished, and any bitmap chunks that weren't synced
* properly have been aborted. It remains to us to clear the * properly have been aborted. It remains to us to clear the
@ -1605,13 +1603,13 @@ void bitmap_close_sync(struct bitmap *bitmap)
if (!bitmap) if (!bitmap)
return; return;
while (sector < bitmap->mddev->resync_max_sectors) { while (sector < bitmap->mddev->resync_max_sectors) {
bitmap_end_sync(bitmap, sector, &blocks, 0); md_bitmap_end_sync(bitmap, sector, &blocks, 0);
sector += blocks; 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 s = 0;
sector_t blocks; 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); sector &= ~((1ULL << bitmap->counts.chunkshift) - 1);
s = 0; s = 0;
while (s < sector && s < bitmap->mddev->resync_max_sectors) { 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; s += blocks;
} }
bitmap->last_end_sync = jiffies; bitmap->last_end_sync = jiffies;
sysfs_notify(&bitmap->mddev->kobj, NULL, "sync_completed"); 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 old_lo, sector_t old_hi,
sector_t new_lo, sector_t new_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; sector_t sector, blocks = 0;
for (sector = old_lo; sector < new_lo; ) { for (sector = old_lo; sector < new_lo; ) {
bitmap_end_sync(bitmap, sector, &blocks, 0); md_bitmap_end_sync(bitmap, sector, &blocks, 0);
sector += blocks; sector += blocks;
} }
WARN((blocks > new_lo) && old_lo, "alignment is not correct for lo\n"); WARN((blocks > new_lo) && old_lo, "alignment is not correct for lo\n");
for (sector = old_hi; sector < new_hi; ) { for (sector = old_hi; sector < new_hi; ) {
bitmap_start_sync(bitmap, sector, &blocks, 0); md_bitmap_start_sync(bitmap, sector, &blocks, 0);
sector += blocks; sector += blocks;
} }
WARN((blocks > new_hi) && old_hi, "alignment is not correct for hi\n"); 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 /* For each chunk covered by any of these sectors, set the
* counter to 2 and possibly set resync_needed. They should all * 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; sector_t secs;
bitmap_counter_t *bmc; bitmap_counter_t *bmc;
spin_lock_irq(&bitmap->counts.lock); 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) { if (!bmc) {
spin_unlock_irq(&bitmap->counts.lock); spin_unlock_irq(&bitmap->counts.lock);
return; return;
} }
if (!*bmc) { if (!*bmc) {
*bmc = 2; *bmc = 2;
bitmap_count_page(&bitmap->counts, offset, 1); md_bitmap_count_page(&bitmap->counts, offset, 1);
bitmap_set_pending(&bitmap->counts, offset); md_bitmap_set_pending(&bitmap->counts, offset);
bitmap->allclean = 0; bitmap->allclean = 0;
} }
if (needed) 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" */ /* 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; unsigned long chunk;
for (chunk = s; chunk <= e; chunk++) { for (chunk = s; chunk <= e; chunk++) {
sector_t sec = (sector_t)chunk << bitmap->counts.chunkshift; sector_t sec = (sector_t)chunk << bitmap->counts.chunkshift;
bitmap_set_memory_bits(bitmap, sec, 1); md_bitmap_set_memory_bits(bitmap, sec, 1);
bitmap_file_set_bit(bitmap, sec); md_bitmap_file_set_bit(bitmap, sec);
if (sec < bitmap->mddev->recovery_cp) if (sec < bitmap->mddev->recovery_cp)
/* We are asserting that the array is dirty, /* We are asserting that the array is dirty,
* so move the recovery_cp address back so * 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 * flush out any pending updates
*/ */
void bitmap_flush(struct mddev *mddev) void md_bitmap_flush(struct mddev *mddev)
{ {
struct bitmap *bitmap = mddev->bitmap; struct bitmap *bitmap = mddev->bitmap;
long sleep; long sleep;
@ -1722,18 +1720,18 @@ void bitmap_flush(struct mddev *mddev)
*/ */
sleep = mddev->bitmap_info.daemon_sleep * 2; sleep = mddev->bitmap_info.daemon_sleep * 2;
bitmap->daemon_lastrun -= sleep; bitmap->daemon_lastrun -= sleep;
bitmap_daemon_work(mddev); md_bitmap_daemon_work(mddev);
bitmap->daemon_lastrun -= sleep; bitmap->daemon_lastrun -= sleep;
bitmap_daemon_work(mddev); md_bitmap_daemon_work(mddev);
bitmap->daemon_lastrun -= sleep; bitmap->daemon_lastrun -= sleep;
bitmap_daemon_work(mddev); md_bitmap_daemon_work(mddev);
bitmap_update_sb(bitmap); md_bitmap_update_sb(bitmap);
} }
/* /*
* free memory that was allocated * free memory that was allocated
*/ */
void bitmap_free(struct bitmap *bitmap) void md_bitmap_free(struct bitmap *bitmap)
{ {
unsigned long k, pages; unsigned long k, pages;
struct bitmap_page *bp; struct bitmap_page *bp;
@ -1753,7 +1751,7 @@ void bitmap_free(struct bitmap *bitmap)
atomic_read(&bitmap->pending_writes) == 0); atomic_read(&bitmap->pending_writes) == 0);
/* release the bitmap file */ /* release the bitmap file */
bitmap_file_unmap(&bitmap->storage); md_bitmap_file_unmap(&bitmap->storage);
bp = bitmap->counts.bp; bp = bitmap->counts.bp;
pages = bitmap->counts.pages; pages = bitmap->counts.pages;
@ -1767,9 +1765,9 @@ void bitmap_free(struct bitmap *bitmap)
kfree(bp); kfree(bp);
kfree(bitmap); 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; 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; struct bitmap *bitmap = mddev->bitmap;
if (!bitmap) /* there was no bitmap */ if (!bitmap) /* there was no bitmap */
return; return;
bitmap_wait_behind_writes(mddev); md_bitmap_wait_behind_writes(mddev);
mutex_lock(&mddev->bitmap_info.mutex); mutex_lock(&mddev->bitmap_info.mutex);
spin_lock(&mddev->lock); spin_lock(&mddev->lock);
@ -1800,7 +1798,7 @@ void bitmap_destroy(struct mddev *mddev)
if (mddev->thread) if (mddev->thread)
mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT; 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 * if this returns an error, bitmap_destroy must be called to do clean up
* once mddev->bitmap is set * 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; struct bitmap *bitmap;
sector_t blocks = mddev->resync_max_sectors; 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. * instructing us to create a new on-disk bitmap instance.
*/ */
if (test_and_clear_bit(MD_ARRAY_FIRST_USE, &mddev->flags)) 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 else
err = bitmap_read_sb(bitmap); err = md_bitmap_read_sb(bitmap);
} else { } else {
err = 0; err = 0;
if (mddev->bitmap_info.chunksize == 0 || if (mddev->bitmap_info.chunksize == 0 ||
@ -1878,7 +1876,7 @@ struct bitmap *bitmap_create(struct mddev *mddev, int slot)
goto error; goto error;
bitmap->daemon_lastrun = jiffies; 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) if (err)
goto error; goto error;
@ -1891,11 +1889,11 @@ struct bitmap *bitmap_create(struct mddev *mddev, int slot)
return bitmap; return bitmap;
error: error:
bitmap_free(bitmap); md_bitmap_free(bitmap);
return ERR_PTR(err); return ERR_PTR(err);
} }
int bitmap_load(struct mddev *mddev) int md_bitmap_load(struct mddev *mddev)
{ {
int err = 0; int err = 0;
sector_t start = 0; sector_t start = 0;
@ -1915,10 +1913,10 @@ int bitmap_load(struct mddev *mddev)
*/ */
while (sector < mddev->resync_max_sectors) { while (sector < mddev->resync_max_sectors) {
sector_t blocks; sector_t blocks;
bitmap_start_sync(bitmap, sector, &blocks, 0); md_bitmap_start_sync(bitmap, sector, &blocks, 0);
sector += blocks; sector += blocks;
} }
bitmap_close_sync(bitmap); md_bitmap_close_sync(bitmap);
if (mddev->degraded == 0 if (mddev->degraded == 0
|| bitmap->events_cleared == mddev->events) || bitmap->events_cleared == mddev->events)
@ -1927,7 +1925,7 @@ int bitmap_load(struct mddev *mddev)
start = mddev->recovery_cp; start = mddev->recovery_cp;
mutex_lock(&mddev->bitmap_info.mutex); 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); mutex_unlock(&mddev->bitmap_info.mutex);
if (err) if (err)
@ -1940,29 +1938,29 @@ int bitmap_load(struct mddev *mddev)
mddev->thread->timeout = mddev->bitmap_info.daemon_sleep; mddev->thread->timeout = mddev->bitmap_info.daemon_sleep;
md_wakeup_thread(mddev->thread); md_wakeup_thread(mddev->thread);
bitmap_update_sb(bitmap); md_bitmap_update_sb(bitmap);
if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags)) if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags))
err = -EIO; err = -EIO;
out: out:
return err; return err;
} }
EXPORT_SYMBOL_GPL(bitmap_load); EXPORT_SYMBOL_GPL(md_bitmap_load);
struct bitmap *get_bitmap_from_slot(struct mddev *mddev, int slot) struct bitmap *get_bitmap_from_slot(struct mddev *mddev, int slot)
{ {
int rv = 0; int rv = 0;
struct bitmap *bitmap; struct bitmap *bitmap;
bitmap = bitmap_create(mddev, slot); bitmap = md_bitmap_create(mddev, slot);
if (IS_ERR(bitmap)) { if (IS_ERR(bitmap)) {
rv = PTR_ERR(bitmap); rv = PTR_ERR(bitmap);
return ERR_PTR(rv); return ERR_PTR(rv);
} }
rv = bitmap_init_from_disk(bitmap, 0); rv = md_bitmap_init_from_disk(bitmap, 0);
if (rv) { if (rv) {
bitmap_free(bitmap); md_bitmap_free(bitmap);
return ERR_PTR(rv); 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 /* Loads the bitmap associated with slot and copies the resync information
* to our bitmap * 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) sector_t *low, sector_t *high, bool clear_bits)
{ {
int rv = 0, i, j; int rv = 0, i, j;
@ -1990,35 +1988,35 @@ int bitmap_copy_from_slot(struct mddev *mddev, int slot,
counts = &bitmap->counts; counts = &bitmap->counts;
for (j = 0; j < counts->chunks; j++) { for (j = 0; j < counts->chunks; j++) {
block = (sector_t)j << counts->chunkshift; block = (sector_t)j << counts->chunkshift;
if (bitmap_file_test_bit(bitmap, block)) { if (md_bitmap_file_test_bit(bitmap, block)) {
if (!lo) if (!lo)
lo = block; lo = block;
hi = block; hi = block;
bitmap_file_clear_bit(bitmap, block); md_bitmap_file_clear_bit(bitmap, block);
bitmap_set_memory_bits(mddev->bitmap, block, 1); md_bitmap_set_memory_bits(mddev->bitmap, block, 1);
bitmap_file_set_bit(mddev->bitmap, block); md_bitmap_file_set_bit(mddev->bitmap, block);
} }
} }
if (clear_bits) { if (clear_bits) {
bitmap_update_sb(bitmap); md_bitmap_update_sb(bitmap);
/* BITMAP_PAGE_PENDING is set, but bitmap_unplug needs /* BITMAP_PAGE_PENDING is set, but bitmap_unplug needs
* BITMAP_PAGE_DIRTY or _NEEDWRITE to write ... */ * BITMAP_PAGE_DIRTY or _NEEDWRITE to write ... */
for (i = 0; i < bitmap->storage.file_pages; i++) for (i = 0; i < bitmap->storage.file_pages; i++)
if (test_page_attr(bitmap, i, BITMAP_PAGE_PENDING)) if (test_page_attr(bitmap, i, BITMAP_PAGE_PENDING))
set_page_attr(bitmap, i, BITMAP_PAGE_NEEDWRITE); 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; *low = lo;
*high = hi; *high = hi;
return rv; 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; unsigned long chunk_kb;
struct bitmap_counts *counts; struct bitmap_counts *counts;
@ -2045,7 +2043,7 @@ void bitmap_status(struct seq_file *seq, struct bitmap *bitmap)
seq_printf(seq, "\n"); 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) int chunksize, int init)
{ {
/* If chunk_size is 0, choose an appropriate chunk size. /* 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); chunks = DIV_ROUND_UP_SECTOR_T(blocks, 1 << chunkshift);
memset(&store, 0, sizeof(store)); memset(&store, 0, sizeof(store));
if (bitmap->mddev->bitmap_info.offset || bitmap->mddev->bitmap_info.file) if (bitmap->mddev->bitmap_info.offset || bitmap->mddev->bitmap_info.file)
ret = bitmap_storage_alloc(&store, chunks, ret = md_bitmap_storage_alloc(&store, chunks,
!bitmap->mddev->bitmap_info.external, !bitmap->mddev->bitmap_info.external,
mddev_is_clustered(bitmap->mddev) mddev_is_clustered(bitmap->mddev)
? bitmap->cluster_slot : 0); ? bitmap->cluster_slot : 0);
if (ret) { if (ret) {
bitmap_file_unmap(&store); md_bitmap_file_unmap(&store);
goto err; goto err;
} }
@ -2120,7 +2118,7 @@ int bitmap_resize(struct bitmap *bitmap, sector_t blocks,
new_bp = kcalloc(pages, sizeof(*new_bp), GFP_KERNEL); new_bp = kcalloc(pages, sizeof(*new_bp), GFP_KERNEL);
ret = -ENOMEM; ret = -ENOMEM;
if (!new_bp) { if (!new_bp) {
bitmap_file_unmap(&store); md_bitmap_file_unmap(&store);
goto err; goto err;
} }
@ -2134,7 +2132,7 @@ int bitmap_resize(struct bitmap *bitmap, sector_t blocks,
memcpy(page_address(store.sb_page), memcpy(page_address(store.sb_page),
page_address(bitmap->storage.sb_page), page_address(bitmap->storage.sb_page),
sizeof(bitmap_super_t)); sizeof(bitmap_super_t));
bitmap_file_unmap(&bitmap->storage); md_bitmap_file_unmap(&bitmap->storage);
bitmap->storage = store; bitmap->storage = store;
old_counts = bitmap->counts; old_counts = bitmap->counts;
@ -2154,7 +2152,7 @@ int bitmap_resize(struct bitmap *bitmap, sector_t blocks,
if (mddev_is_clustered(bitmap->mddev)) { if (mddev_is_clustered(bitmap->mddev)) {
unsigned long page; unsigned long page;
for (page = 0; page < pages; 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) { if (ret) {
unsigned long k; unsigned long k;
@ -2184,27 +2182,23 @@ int bitmap_resize(struct bitmap *bitmap, sector_t blocks,
bitmap_counter_t *bmc_old, *bmc_new; bitmap_counter_t *bmc_old, *bmc_new;
int set; int set;
bmc_old = bitmap_get_counter(&old_counts, block, bmc_old = md_bitmap_get_counter(&old_counts, block, &old_blocks, 0);
&old_blocks, 0);
set = bmc_old && NEEDED(*bmc_old); set = bmc_old && NEEDED(*bmc_old);
if (set) { if (set) {
bmc_new = bitmap_get_counter(&bitmap->counts, block, bmc_new = md_bitmap_get_counter(&bitmap->counts, block, &new_blocks, 1);
&new_blocks, 1);
if (*bmc_new == 0) { if (*bmc_new == 0) {
/* need to set on-disk bits too. */ /* need to set on-disk bits too. */
sector_t end = block + new_blocks; sector_t end = block + new_blocks;
sector_t start = block >> chunkshift; sector_t start = block >> chunkshift;
start <<= chunkshift; start <<= chunkshift;
while (start < end) { while (start < end) {
bitmap_file_set_bit(bitmap, block); md_bitmap_file_set_bit(bitmap, block);
start += 1 << chunkshift; start += 1 << chunkshift;
} }
*bmc_new = 2; *bmc_new = 2;
bitmap_count_page(&bitmap->counts, md_bitmap_count_page(&bitmap->counts, block, 1);
block, 1); md_bitmap_set_pending(&bitmap->counts, block);
bitmap_set_pending(&bitmap->counts,
block);
} }
*bmc_new |= NEEDED_MASK; *bmc_new |= NEEDED_MASK;
if (new_blocks < old_blocks) if (new_blocks < old_blocks)
@ -2225,18 +2219,15 @@ int bitmap_resize(struct bitmap *bitmap, sector_t blocks,
int i; int i;
while (block < (chunks << chunkshift)) { while (block < (chunks << chunkshift)) {
bitmap_counter_t *bmc; bitmap_counter_t *bmc;
bmc = bitmap_get_counter(&bitmap->counts, block, bmc = md_bitmap_get_counter(&bitmap->counts, block, &new_blocks, 1);
&new_blocks, 1);
if (bmc) { if (bmc) {
/* new space. It needs to be resynced, so /* new space. It needs to be resynced, so
* we set NEEDED_MASK. * we set NEEDED_MASK.
*/ */
if (*bmc == 0) { if (*bmc == 0) {
*bmc = NEEDED_MASK | 2; *bmc = NEEDED_MASK | 2;
bitmap_count_page(&bitmap->counts, md_bitmap_count_page(&bitmap->counts, block, 1);
block, 1); md_bitmap_set_pending(&bitmap->counts, block);
bitmap_set_pending(&bitmap->counts,
block);
} }
} }
block += new_blocks; block += new_blocks;
@ -2247,14 +2238,14 @@ int bitmap_resize(struct bitmap *bitmap, sector_t blocks,
spin_unlock_irq(&bitmap->counts.lock); spin_unlock_irq(&bitmap->counts.lock);
if (!init) { if (!init) {
bitmap_unplug(bitmap); md_bitmap_unplug(bitmap);
bitmap->mddev->pers->quiesce(bitmap->mddev, 0); bitmap->mddev->pers->quiesce(bitmap->mddev, 0);
} }
ret = 0; ret = 0;
err: err:
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(bitmap_resize); EXPORT_SYMBOL_GPL(md_bitmap_resize);
static ssize_t static ssize_t
location_show(struct mddev *mddev, char *page) 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) { if (mddev->pers) {
mddev->pers->quiesce(mddev, 1); mddev->pers->quiesce(mddev, 1);
bitmap_destroy(mddev); md_bitmap_destroy(mddev);
mddev->pers->quiesce(mddev, 0); mddev->pers->quiesce(mddev, 0);
} }
mddev->bitmap_info.offset = 0; mddev->bitmap_info.offset = 0;
@ -2337,18 +2328,18 @@ location_store(struct mddev *mddev, const char *buf, size_t len)
if (mddev->pers) { if (mddev->pers) {
struct bitmap *bitmap; struct bitmap *bitmap;
mddev->pers->quiesce(mddev, 1); mddev->pers->quiesce(mddev, 1);
bitmap = bitmap_create(mddev, -1); bitmap = md_bitmap_create(mddev, -1);
if (IS_ERR(bitmap)) if (IS_ERR(bitmap))
rv = PTR_ERR(bitmap); rv = PTR_ERR(bitmap);
else { else {
mddev->bitmap = bitmap; mddev->bitmap = bitmap;
rv = bitmap_load(mddev); rv = md_bitmap_load(mddev);
if (rv) if (rv)
mddev->bitmap_info.offset = 0; mddev->bitmap_info.offset = 0;
} }
mddev->pers->quiesce(mddev, 0); mddev->pers->quiesce(mddev, 0);
if (rv) { if (rv) {
bitmap_destroy(mddev); md_bitmap_destroy(mddev);
goto out; goto out;
} }
} }

View File

@ -236,43 +236,43 @@ struct bitmap {
/* the bitmap API */ /* the bitmap API */
/* these are used only by md/bitmap */ /* these are used only by md/bitmap */
struct bitmap *bitmap_create(struct mddev *mddev, int slot); struct bitmap *md_bitmap_create(struct mddev *mddev, int slot);
int bitmap_load(struct mddev *mddev); int md_bitmap_load(struct mddev *mddev);
void bitmap_flush(struct mddev *mddev); void md_bitmap_flush(struct mddev *mddev);
void bitmap_destroy(struct mddev *mddev); void md_bitmap_destroy(struct mddev *mddev);
void bitmap_print_sb(struct bitmap *bitmap); void md_bitmap_print_sb(struct bitmap *bitmap);
void bitmap_update_sb(struct bitmap *bitmap); void md_bitmap_update_sb(struct bitmap *bitmap);
void bitmap_status(struct seq_file *seq, struct bitmap *bitmap); void md_bitmap_status(struct seq_file *seq, struct bitmap *bitmap);
int bitmap_setallbits(struct bitmap *bitmap); int md_bitmap_setallbits(struct bitmap *bitmap);
void bitmap_write_all(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 */ /* these are exported */
int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, int md_bitmap_startwrite(struct bitmap *bitmap, sector_t offset,
unsigned long sectors, int behind); unsigned long sectors, int behind);
void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, void md_bitmap_endwrite(struct bitmap *bitmap, sector_t offset,
unsigned long sectors, int success, int behind); unsigned long sectors, int success, int behind);
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);
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);
void bitmap_close_sync(struct bitmap *bitmap); void md_bitmap_close_sync(struct bitmap *bitmap);
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);
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 old_lo, sector_t old_hi,
sector_t new_lo, sector_t new_hi); sector_t new_lo, sector_t new_hi);
void bitmap_unplug(struct bitmap *bitmap); void md_bitmap_unplug(struct bitmap *bitmap);
void bitmap_daemon_work(struct mddev *mddev); void md_bitmap_daemon_work(struct mddev *mddev);
int bitmap_resize(struct bitmap *bitmap, sector_t blocks, int md_bitmap_resize(struct bitmap *bitmap, sector_t blocks,
int chunksize, int init); int chunksize, int init);
struct bitmap *get_bitmap_from_slot(struct mddev *mddev, int slot); struct bitmap *get_bitmap_from_slot(struct mddev *mddev, int slot);
int bitmap_copy_from_slot(struct mddev *mddev, int slot, int md_bitmap_copy_from_slot(struct mddev *mddev, int slot,
sector_t *lo, sector_t *hi, bool clear_bits); sector_t *lo, sector_t *hi, bool clear_bits);
void bitmap_free(struct bitmap *bitmap); void md_bitmap_free(struct bitmap *bitmap);
void bitmap_wait_behind_writes(struct mddev *mddev); void md_bitmap_wait_behind_writes(struct mddev *mddev);
#endif #endif
#endif #endif

View File

@ -317,7 +317,7 @@ static void recover_bitmaps(struct md_thread *thread)
str, ret); str, ret);
goto clear_bit; 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) { if (ret) {
pr_err("md-cluster: Could not copy data from bitmap %d\n", slot); pr_err("md-cluster: Could not copy data from bitmap %d\n", slot);
goto clear_bit; goto clear_bit;
@ -492,9 +492,7 @@ static void process_suspend_info(struct mddev *mddev,
* resync thread is running in another node, * resync thread is running in another node,
* so we don't need to do the resync again * so we don't need to do the resync again
* with the same section */ * with the same section */
bitmap_sync_with_cluster(mddev, cinfo->sync_low, md_bitmap_sync_with_cluster(mddev, cinfo->sync_low, cinfo->sync_hi, lo, hi);
cinfo->sync_hi,
lo, hi);
cinfo->sync_low = lo; cinfo->sync_low = lo;
cinfo->sync_hi = hi; 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 */ /* 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) { if (ret) {
pr_warn("md-cluster: Could not gather bitmaps from slot %d", i); pr_warn("md-cluster: Could not gather bitmaps from slot %d", i);
lockres_free(bm_lockres); 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); bm_lockres = lockres_init(mddev, str, NULL, 1);
if (!bm_lockres) { if (!bm_lockres) {
pr_err("md-cluster: Cannot initialize %s\n", str); pr_err("md-cluster: Cannot initialize %s\n", str);
bitmap_free(bitmap); md_bitmap_free(bitmap);
return -1; return -1;
} }
bm_lockres->flags |= DLM_LKF_NOQUEUE; bm_lockres->flags |= DLM_LKF_NOQUEUE;
rv = dlm_lock_sync(bm_lockres, DLM_LOCK_PW); rv = dlm_lock_sync(bm_lockres, DLM_LOCK_PW);
if (!rv) if (!rv)
bitmap_update_sb(bitmap); md_bitmap_update_sb(bitmap);
lockres_free(bm_lockres); lockres_free(bm_lockres);
sb = kmap_atomic(bitmap->storage.sb_page); 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; sync_size = sb->sync_size;
else if (sync_size != sb->sync_size) { else if (sync_size != sb->sync_size) {
kunmap_atomic(sb); kunmap_atomic(sb);
bitmap_free(bitmap); md_bitmap_free(bitmap);
return -1; return -1;
} }
kunmap_atomic(sb); kunmap_atomic(sb);
bitmap_free(bitmap); md_bitmap_free(bitmap);
} }
return (my_sync_size == sync_size) ? 0 : -1; 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++) { for (sn = 0; sn < mddev->bitmap_info.nodes; sn++) {
if (sn == (cinfo->slot_number - 1)) if (sn == (cinfo->slot_number - 1))
continue; continue;
err = bitmap_copy_from_slot(mddev, sn, &lo, &hi, false); err = md_bitmap_copy_from_slot(mddev, sn, &lo, &hi, false);
if (err) { if (err) {
pr_warn("md-cluster: Could not gather bitmaps from slot %d", sn); pr_warn("md-cluster: Could not gather bitmaps from slot %d", sn);
goto out; goto out;

View File

@ -2568,7 +2568,7 @@ repeat:
if (mddev->queue) if (mddev->queue)
blk_add_trace_msg(mddev->queue, "md md_update_sb"); blk_add_trace_msg(mddev->queue, "md md_update_sb");
rewrite: rewrite:
bitmap_update_sb(mddev->bitmap); md_bitmap_update_sb(mddev->bitmap);
rdev_for_each(rdev, mddev) { rdev_for_each(rdev, mddev) {
char b[BDEVNAME_SIZE]; char b[BDEVNAME_SIZE];
@ -4381,10 +4381,10 @@ bitmap_store(struct mddev *mddev, const char *buf, size_t len)
if (buf == end) break; if (buf == end) break;
} }
if (*end && !isspace(*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); buf = skip_spaces(end);
} }
bitmap_unplug(mddev->bitmap); /* flush the bits to disk */ md_bitmap_unplug(mddev->bitmap); /* flush the bits to disk */
out: out:
mddev_unlock(mddev); mddev_unlock(mddev);
return len; return len;
@ -5612,7 +5612,7 @@ int md_run(struct mddev *mddev)
(mddev->bitmap_info.file || mddev->bitmap_info.offset)) { (mddev->bitmap_info.file || mddev->bitmap_info.offset)) {
struct bitmap *bitmap; struct bitmap *bitmap;
bitmap = bitmap_create(mddev, -1); bitmap = md_bitmap_create(mddev, -1);
if (IS_ERR(bitmap)) { if (IS_ERR(bitmap)) {
err = PTR_ERR(bitmap); err = PTR_ERR(bitmap);
pr_warn("%s: failed to create bitmap (%d)\n", pr_warn("%s: failed to create bitmap (%d)\n",
@ -5627,7 +5627,7 @@ int md_run(struct mddev *mddev)
pers->free(mddev, mddev->private); pers->free(mddev, mddev->private);
mddev->private = NULL; mddev->private = NULL;
module_put(pers->owner); module_put(pers->owner);
bitmap_destroy(mddev); md_bitmap_destroy(mddev);
goto abort; goto abort;
} }
if (mddev->queue) { if (mddev->queue) {
@ -5712,9 +5712,9 @@ static int do_md_run(struct mddev *mddev)
err = md_run(mddev); err = md_run(mddev);
if (err) if (err)
goto out; goto out;
err = bitmap_load(mddev); err = md_bitmap_load(mddev);
if (err) { if (err) {
bitmap_destroy(mddev); md_bitmap_destroy(mddev);
goto out; goto out;
} }
@ -5856,7 +5856,7 @@ static void __md_stop_writes(struct mddev *mddev)
mddev->pers->quiesce(mddev, 1); mddev->pers->quiesce(mddev, 1);
mddev->pers->quiesce(mddev, 0); mddev->pers->quiesce(mddev, 0);
} }
bitmap_flush(mddev); md_bitmap_flush(mddev);
if (mddev->ro == 0 && if (mddev->ro == 0 &&
((!mddev->in_sync && !mddev_is_clustered(mddev)) || ((!mddev->in_sync && !mddev_is_clustered(mddev)) ||
@ -5878,7 +5878,7 @@ EXPORT_SYMBOL_GPL(md_stop_writes);
static void mddev_detach(struct mddev *mddev) static void mddev_detach(struct mddev *mddev)
{ {
bitmap_wait_behind_writes(mddev); md_bitmap_wait_behind_writes(mddev);
if (mddev->pers && mddev->pers->quiesce) { if (mddev->pers && mddev->pers->quiesce) {
mddev->pers->quiesce(mddev, 1); mddev->pers->quiesce(mddev, 1);
mddev->pers->quiesce(mddev, 0); mddev->pers->quiesce(mddev, 0);
@ -5891,7 +5891,7 @@ static void mddev_detach(struct mddev *mddev)
static void __md_stop(struct mddev *mddev) static void __md_stop(struct mddev *mddev)
{ {
struct md_personality *pers = mddev->pers; struct md_personality *pers = mddev->pers;
bitmap_destroy(mddev); md_bitmap_destroy(mddev);
mddev_detach(mddev); mddev_detach(mddev);
/* Ensure ->event_work is done */ /* Ensure ->event_work is done */
flush_workqueue(md_misc_wq); flush_workqueue(md_misc_wq);
@ -6710,21 +6710,21 @@ static int set_bitmap_file(struct mddev *mddev, int fd)
if (fd >= 0) { if (fd >= 0) {
struct bitmap *bitmap; struct bitmap *bitmap;
bitmap = bitmap_create(mddev, -1); bitmap = md_bitmap_create(mddev, -1);
mddev_suspend(mddev); mddev_suspend(mddev);
if (!IS_ERR(bitmap)) { if (!IS_ERR(bitmap)) {
mddev->bitmap = bitmap; mddev->bitmap = bitmap;
err = bitmap_load(mddev); err = md_bitmap_load(mddev);
} else } else
err = PTR_ERR(bitmap); err = PTR_ERR(bitmap);
if (err) { if (err) {
bitmap_destroy(mddev); md_bitmap_destroy(mddev);
fd = -1; fd = -1;
} }
mddev_resume(mddev); mddev_resume(mddev);
} else if (fd < 0) { } else if (fd < 0) {
mddev_suspend(mddev); mddev_suspend(mddev);
bitmap_destroy(mddev); md_bitmap_destroy(mddev);
mddev_resume(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.default_offset;
mddev->bitmap_info.space = mddev->bitmap_info.space =
mddev->bitmap_info.default_space; mddev->bitmap_info.default_space;
bitmap = bitmap_create(mddev, -1); bitmap = md_bitmap_create(mddev, -1);
mddev_suspend(mddev); mddev_suspend(mddev);
if (!IS_ERR(bitmap)) { if (!IS_ERR(bitmap)) {
mddev->bitmap = bitmap; mddev->bitmap = bitmap;
rv = bitmap_load(mddev); rv = md_bitmap_load(mddev);
} else } else
rv = PTR_ERR(bitmap); rv = PTR_ERR(bitmap);
if (rv) if (rv)
bitmap_destroy(mddev); md_bitmap_destroy(mddev);
mddev_resume(mddev); mddev_resume(mddev);
} else { } else {
/* remove the bitmap */ /* 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); md_cluster_ops->leave(mddev);
} }
mddev_suspend(mddev); mddev_suspend(mddev);
bitmap_destroy(mddev); md_bitmap_destroy(mddev);
mddev_resume(mddev); mddev_resume(mddev);
mddev->bitmap_info.offset = 0; mddev->bitmap_info.offset = 0;
} }
@ -7923,7 +7923,7 @@ static int md_seq_show(struct seq_file *seq, void *v)
} else } else
seq_printf(seq, "\n "); seq_printf(seq, "\n ");
bitmap_status(seq, mddev->bitmap); md_bitmap_status(seq, mddev->bitmap);
seq_printf(seq, "\n"); seq_printf(seq, "\n");
} }
@ -8794,7 +8794,7 @@ void md_check_recovery(struct mddev *mddev)
return; return;
if (mddev->bitmap) if (mddev->bitmap)
bitmap_daemon_work(mddev); md_bitmap_daemon_work(mddev);
if (signal_pending(current)) { if (signal_pending(current)) {
if (mddev->pers->sync_request && !mddev->external) { 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. * which has the bitmap stored on all devices.
* So make sure all bitmap pages get written * 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); INIT_WORK(&mddev->del_work, md_start_sync);
queue_work(md_misc_wq, &mddev->del_work); 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) if (ret)
pr_info("md-cluster: resize failed\n"); pr_info("md-cluster: resize failed\n");
else else
bitmap_update_sb(mddev->bitmap); md_bitmap_update_sb(mddev->bitmap);
} }
/* Check for change of roles in the active devices */ /* Check for change of roles in the active devices */

View File

@ -69,9 +69,9 @@ static struct dm_block_validator index_validator = {
*/ */
#define BITMAP_CSUM_XOR 240779 #define BITMAP_CSUM_XOR 240779
static void bitmap_prepare_for_write(struct dm_block_validator *v, static void dm_bitmap_prepare_for_write(struct dm_block_validator *v,
struct dm_block *b, struct dm_block *b,
size_t block_size) size_t block_size)
{ {
struct disk_bitmap_header *disk_header = dm_block_data(b); 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)); BITMAP_CSUM_XOR));
} }
static int bitmap_check(struct dm_block_validator *v, static int dm_bitmap_check(struct dm_block_validator *v,
struct dm_block *b, struct dm_block *b,
size_t block_size) size_t block_size)
{ {
struct disk_bitmap_header *disk_header = dm_block_data(b); struct disk_bitmap_header *disk_header = dm_block_data(b);
__le32 csum_disk; __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 = { static struct dm_block_validator dm_sm_bitmap_validator = {
.name = "sm_bitmap", .name = "sm_bitmap",
.prepare_for_write = bitmap_prepare_for_write, .prepare_for_write = dm_bitmap_prepare_for_write,
.check = bitmap_check .check = dm_bitmap_check,
}; };
/*----------------------------------------------------------------*/ /*----------------------------------------------------------------*/
@ -124,7 +124,7 @@ static void *dm_bitmap_data(struct dm_block *b)
#define WORD_MASK_HIGH 0xAAAAAAAAAAAAAAAAULL #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 *words_le = addr;
__le64 *w_le = words_le + (b >> ENTRIES_SHIFT); __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) { while (begin < end) {
if (!(begin & (ENTRIES_PER_WORD - 1)) && if (!(begin & (ENTRIES_PER_WORD - 1)) &&
bitmap_word_used(addr, begin)) { dm_bitmap_word_used(addr, begin)) {
begin += ENTRIES_PER_WORD; begin += ENTRIES_PER_WORD;
continue; continue;
} }

View File

@ -385,10 +385,10 @@ static void close_write(struct r1bio *r1_bio)
r1_bio->behind_master_bio = NULL; r1_bio->behind_master_bio = NULL;
} }
/* clear the bitmap if all writes complete successfully */ /* clear the bitmap if all writes complete successfully */
bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector, md_bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector,
r1_bio->sectors, r1_bio->sectors,
!test_bit(R1BIO_Degraded, &r1_bio->state), !test_bit(R1BIO_Degraded, &r1_bio->state),
test_bit(R1BIO_BehindIO, &r1_bio->state)); test_bit(R1BIO_BehindIO, &r1_bio->state));
md_write_end(r1_bio->mddev); 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) static void flush_bio_list(struct r1conf *conf, struct bio *bio)
{ {
/* flush any pending bitmap writes to disk before proceeding w/ I/O */ /* 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); wake_up(&conf->wait_barrier);
while (bio) { /* submit pending writes */ 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); alloc_behind_master_bio(r1_bio, bio);
} }
bitmap_startwrite(bitmap, r1_bio->sector, md_bitmap_startwrite(bitmap, r1_bio->sector, r1_bio->sectors,
r1_bio->sectors, test_bit(R1BIO_BehindIO, &r1_bio->state));
test_bit(R1BIO_BehindIO,
&r1_bio->state));
first_clone = 0; first_clone = 0;
} }
@ -1880,8 +1878,7 @@ static void end_sync_write(struct bio *bio)
long sectors_to_go = r1_bio->sectors; long sectors_to_go = r1_bio->sectors;
/* make sure these bits doesn't get cleared. */ /* make sure these bits doesn't get cleared. */
do { do {
bitmap_end_sync(mddev->bitmap, s, md_bitmap_end_sync(mddev->bitmap, s, &sync_blocks, 1);
&sync_blocks, 1);
s += sync_blocks; s += sync_blocks;
sectors_to_go -= sync_blocks; sectors_to_go -= sync_blocks;
} while (sectors_to_go > 0); } 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 * We can find the current addess in mddev->curr_resync
*/ */
if (mddev->curr_resync < max_sector) /* aborted */ if (mddev->curr_resync < max_sector) /* aborted */
bitmap_end_sync(mddev->bitmap, mddev->curr_resync, md_bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
&sync_blocks, 1); &sync_blocks, 1);
else /* completed sync */ else /* completed sync */
conf->fullsync = 0; conf->fullsync = 0;
bitmap_close_sync(mddev->bitmap); md_bitmap_close_sync(mddev->bitmap);
close_sync(conf); close_sync(conf);
if (mddev_is_clustered(mddev)) { 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.. /* before building a request, check if we can skip these blocks..
* This call the bitmap_start_sync doesn't actually record anything * 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)) { !conf->fullsync && !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
/* We can skip this block, and probably several more */ /* We can skip this block, and probably several more */
*skipped = 1; *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 * 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)); 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) if (len == 0)
break; break;
if (sync_blocks == 0) { if (sync_blocks == 0) {
if (!bitmap_start_sync(mddev->bitmap, sector_nr, if (!md_bitmap_start_sync(mddev->bitmap, sector_nr,
&sync_blocks, still_degraded) && &sync_blocks, still_degraded) &&
!conf->fullsync && !conf->fullsync &&
!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
break; break;
@ -3165,7 +3162,7 @@ static int raid1_resize(struct mddev *mddev, sector_t sectors)
mddev->array_sectors > newsize) mddev->array_sectors > newsize)
return -EINVAL; return -EINVAL;
if (mddev->bitmap) { if (mddev->bitmap) {
int ret = bitmap_resize(mddev->bitmap, newsize, 0, 0); int ret = md_bitmap_resize(mddev->bitmap, newsize, 0, 0);
if (ret) if (ret)
return ret; return ret;
} }

View File

@ -440,10 +440,10 @@ static void raid10_end_read_request(struct bio *bio)
static void close_write(struct r10bio *r10_bio) static void close_write(struct r10bio *r10_bio)
{ {
/* clear the bitmap if all writes complete successfully */ /* clear the bitmap if all writes complete successfully */
bitmap_endwrite(r10_bio->mddev->bitmap, r10_bio->sector, md_bitmap_endwrite(r10_bio->mddev->bitmap, r10_bio->sector,
r10_bio->sectors, r10_bio->sectors,
!test_bit(R10BIO_Degraded, &r10_bio->state), !test_bit(R10BIO_Degraded, &r10_bio->state),
0); 0);
md_write_end(r10_bio->mddev); md_write_end(r10_bio->mddev);
} }
@ -917,7 +917,7 @@ static void flush_pending_writes(struct r10conf *conf)
blk_start_plug(&plug); blk_start_plug(&plug);
/* flush any pending bitmap writes to disk /* flush any pending bitmap writes to disk
* before proceeding w/ I/O */ * before proceeding w/ I/O */
bitmap_unplug(conf->mddev->bitmap); md_bitmap_unplug(conf->mddev->bitmap);
wake_up(&conf->wait_barrier); wake_up(&conf->wait_barrier);
while (bio) { /* submit pending writes */ 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. */ /* we aren't scheduling, so we can do the write-out directly. */
bio = bio_list_get(&plug->pending); bio = bio_list_get(&plug->pending);
bitmap_unplug(mddev->bitmap); md_bitmap_unplug(mddev->bitmap);
wake_up(&conf->wait_barrier); wake_up(&conf->wait_barrier);
while (bio) { /* submit pending writes */ while (bio) { /* submit pending writes */
@ -1519,7 +1519,7 @@ retry_write:
} }
atomic_set(&r10_bio->remaining, 1); 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++) { for (i = 0; i < conf->copies; i++) {
if (r10_bio->devs[i].bio) 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 (mddev->curr_resync < max_sector) { /* aborted */
if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
bitmap_end_sync(mddev->bitmap, mddev->curr_resync, md_bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
&sync_blocks, 1); &sync_blocks, 1);
else for (i = 0; i < conf->geo.raid_disks; i++) { else for (i = 0; i < conf->geo.raid_disks; i++) {
sector_t sect = sector_t sect =
raid10_find_virt(conf, mddev->curr_resync, i); raid10_find_virt(conf, mddev->curr_resync, i);
bitmap_end_sync(mddev->bitmap, sect, md_bitmap_end_sync(mddev->bitmap, sect,
&sync_blocks, 1); &sync_blocks, 1);
} }
} else { } else {
/* completed sync */ /* completed sync */
@ -3018,7 +3018,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
} }
conf->fullsync = 0; conf->fullsync = 0;
} }
bitmap_close_sync(mddev->bitmap); md_bitmap_close_sync(mddev->bitmap);
close_sync(conf); close_sync(conf);
*skipped = 1; *skipped = 1;
return sectors_skipped; 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 * we only need to recover the block if it is set in
* the bitmap * the bitmap
*/ */
must_sync = bitmap_start_sync(mddev->bitmap, sect, must_sync = md_bitmap_start_sync(mddev->bitmap, sect,
&sync_blocks, 1); &sync_blocks, 1);
if (sync_blocks < max_sync) if (sync_blocks < max_sync)
max_sync = sync_blocks; max_sync = sync_blocks;
if (!must_sync && 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, must_sync = md_bitmap_start_sync(mddev->bitmap, sect,
&sync_blocks, still_degraded); &sync_blocks, still_degraded);
any_working = 0; any_working = 0;
for (j=0; j<conf->copies;j++) { 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 * safety reason, which ensures curr_resync_completed is
* updated in bitmap_cond_end_sync. * updated in bitmap_cond_end_sync.
*/ */
bitmap_cond_end_sync(mddev->bitmap, sector_nr, md_bitmap_cond_end_sync(mddev->bitmap, sector_nr,
mddev_is_clustered(mddev) && mddev_is_clustered(mddev) &&
(sector_nr + 2 * RESYNC_SECTORS > (sector_nr + 2 * RESYNC_SECTORS > conf->cluster_sync_high));
conf->cluster_sync_high));
if (!bitmap_start_sync(mddev->bitmap, sector_nr, if (!md_bitmap_start_sync(mddev->bitmap, sector_nr,
&sync_blocks, mddev->degraded) && &sync_blocks, mddev->degraded) &&
!conf->fullsync && !test_bit(MD_RECOVERY_REQUESTED, !conf->fullsync && !test_bit(MD_RECOVERY_REQUESTED,
&mddev->recovery)) { &mddev->recovery)) {
/* We can skip this block */ /* We can skip this block */
@ -4022,7 +4021,7 @@ static int raid10_resize(struct mddev *mddev, sector_t sectors)
mddev->array_sectors > size) mddev->array_sectors > size)
return -EINVAL; return -EINVAL;
if (mddev->bitmap) { if (mddev->bitmap) {
int ret = bitmap_resize(mddev->bitmap, size, 0, 0); int ret = md_bitmap_resize(mddev->bitmap, size, 0, 0);
if (ret) if (ret)
return ret; return ret;
} }
@ -4287,10 +4286,9 @@ static int raid10_start_reshape(struct mddev *mddev)
spin_unlock_irq(&conf->device_lock); spin_unlock_irq(&conf->device_lock);
if (mddev->delta_disks && mddev->bitmap) { if (mddev->delta_disks && mddev->bitmap) {
ret = bitmap_resize(mddev->bitmap, ret = md_bitmap_resize(mddev->bitmap,
raid10_size(mddev, 0, raid10_size(mddev, 0, conf->geo.raid_disks),
conf->geo.raid_disks), 0, 0);
0, 0);
if (ret) if (ret)
goto abort; goto abort;
} }

View File

@ -324,10 +324,10 @@ void r5c_handle_cached_data_endio(struct r5conf *conf,
if (sh->dev[i].written) { if (sh->dev[i].written) {
set_bit(R5_UPTODATE, &sh->dev[i].flags); set_bit(R5_UPTODATE, &sh->dev[i].flags);
r5c_return_dev_pending_writes(conf, &sh->dev[i]); r5c_return_dev_pending_writes(conf, &sh->dev[i]);
bitmap_endwrite(conf->mddev->bitmap, sh->sector, md_bitmap_endwrite(conf->mddev->bitmap, sh->sector,
STRIPE_SECTORS, STRIPE_SECTORS,
!test_bit(STRIPE_DEGRADED, &sh->state), !test_bit(STRIPE_DEGRADED, &sh->state),
0); 0);
} }
} }
} }

View File

@ -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); set_bit(STRIPE_BITMAP_PENDING, &sh->state);
spin_unlock_irq(&sh->stripe_lock); spin_unlock_irq(&sh->stripe_lock);
bitmap_startwrite(conf->mddev->bitmap, sh->sector, md_bitmap_startwrite(conf->mddev->bitmap, sh->sector,
STRIPE_SECTORS, 0); STRIPE_SECTORS, 0);
spin_lock_irq(&sh->stripe_lock); spin_lock_irq(&sh->stripe_lock);
clear_bit(STRIPE_BITMAP_PENDING, &sh->state); clear_bit(STRIPE_BITMAP_PENDING, &sh->state);
if (!sh->batch_head) { if (!sh->batch_head) {
@ -3390,8 +3390,8 @@ handle_failed_stripe(struct r5conf *conf, struct stripe_head *sh,
bi = nextbi; bi = nextbi;
} }
if (bitmap_end) if (bitmap_end)
bitmap_endwrite(conf->mddev->bitmap, sh->sector, md_bitmap_endwrite(conf->mddev->bitmap, sh->sector,
STRIPE_SECTORS, 0, 0); STRIPE_SECTORS, 0, 0);
bitmap_end = 0; bitmap_end = 0;
/* and fail all 'written' */ /* and fail all 'written' */
bi = sh->dev[i].written; bi = sh->dev[i].written;
@ -3436,8 +3436,8 @@ handle_failed_stripe(struct r5conf *conf, struct stripe_head *sh,
} }
} }
if (bitmap_end) if (bitmap_end)
bitmap_endwrite(conf->mddev->bitmap, sh->sector, md_bitmap_endwrite(conf->mddev->bitmap, sh->sector,
STRIPE_SECTORS, 0, 0); STRIPE_SECTORS, 0, 0);
/* If we were in the middle of a write the parity block might /* If we were in the middle of a write the parity block might
* still be locked - so just clear all R5_LOCKED flags * still be locked - so just clear all R5_LOCKED flags
*/ */
@ -3777,10 +3777,10 @@ returnbi:
bio_endio(wbi); bio_endio(wbi);
wbi = wbi2; wbi = wbi2;
} }
bitmap_endwrite(conf->mddev->bitmap, sh->sector, md_bitmap_endwrite(conf->mddev->bitmap, sh->sector,
STRIPE_SECTORS, STRIPE_SECTORS,
!test_bit(STRIPE_DEGRADED, &sh->state), !test_bit(STRIPE_DEGRADED, &sh->state),
0); 0);
if (head_sh->batch_head) { if (head_sh->batch_head) {
sh = list_first_entry(&sh->batch_list, sh = list_first_entry(&sh->batch_list,
struct stripe_head, struct stripe_head,
@ -5543,10 +5543,10 @@ static void make_discard_request(struct mddev *mddev, struct bio *bi)
for (d = 0; for (d = 0;
d < conf->raid_disks - conf->max_degraded; d < conf->raid_disks - conf->max_degraded;
d++) d++)
bitmap_startwrite(mddev->bitmap, md_bitmap_startwrite(mddev->bitmap,
sh->sector, sh->sector,
STRIPE_SECTORS, STRIPE_SECTORS,
0); 0);
sh->bm_seq = conf->seq_flush + 1; sh->bm_seq = conf->seq_flush + 1;
set_bit(STRIPE_BIT_DELAY, &sh->state); 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 */ if (mddev->curr_resync < max_sector) /* aborted */
bitmap_end_sync(mddev->bitmap, mddev->curr_resync, md_bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
&sync_blocks, 1); &sync_blocks, 1);
else /* completed sync */ else /* completed sync */
conf->fullsync = 0; conf->fullsync = 0;
bitmap_close_sync(mddev->bitmap); md_bitmap_close_sync(mddev->bitmap);
return 0; 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) && if (!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) &&
!conf->fullsync && !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) { sync_blocks >= STRIPE_SECTORS) {
/* we can skip this block, and probably more */ /* we can skip this block, and probably more */
sync_blocks /= STRIPE_SECTORS; 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 */ 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); sh = raid5_get_active_stripe(conf, sector_nr, 0, 1, 0);
if (sh == NULL) { if (sh == NULL) {
@ -6088,7 +6088,7 @@ static inline sector_t raid5_sync_request(struct mddev *mddev, sector_t sector_n
} }
rcu_read_unlock(); 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_SYNC_REQUESTED, &sh->state);
set_bit(STRIPE_HANDLE, &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 */ /* Now is a good time to flush some bitmap updates */
conf->seq_flush++; conf->seq_flush++;
spin_unlock_irq(&conf->device_lock); spin_unlock_irq(&conf->device_lock);
bitmap_unplug(mddev->bitmap); md_bitmap_unplug(mddev->bitmap);
spin_lock_irq(&conf->device_lock); spin_lock_irq(&conf->device_lock);
conf->seq_write = conf->seq_flush; conf->seq_write = conf->seq_flush;
activate_bit_delay(conf, conf->temp_inactive_list); 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) mddev->array_sectors > newsize)
return -EINVAL; return -EINVAL;
if (mddev->bitmap) { if (mddev->bitmap) {
int ret = bitmap_resize(mddev->bitmap, sectors, 0, 0); int ret = md_bitmap_resize(mddev->bitmap, sectors, 0, 0);
if (ret) if (ret)
return ret; return ret;
} }

View File

@ -104,6 +104,14 @@
* contain all bit positions from 0 to 'bits' - 1. * 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: * lib/bitmap.c provides these functions:
*/ */

View File

@ -2,6 +2,8 @@
#ifndef _GPIO_KEYS_H #ifndef _GPIO_KEYS_H
#define _GPIO_KEYS_H #define _GPIO_KEYS_H
#include <linux/types.h>
struct device; struct device;
/** /**

View File

@ -17,10 +17,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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 #ifndef _LINUX_JOYSTICK_H
#define _LINUX_JOYSTICK_H #define _LINUX_JOYSTICK_H

View File

@ -18,10 +18,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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 #ifndef _UAPI_LINUX_JOYSTICK_H
#define _UAPI_LINUX_JOYSTICK_H #define _UAPI_LINUX_JOYSTICK_H

View File

@ -189,6 +189,13 @@
* *
*----------------------------- Connector settings ---------------------------- *----------------------------- 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 * resolution
* Values: <width, uint32_t>x<height, uint32_t> * Values: <width, uint32_t>x<height, uint32_t>
* *
@ -368,6 +375,7 @@
#define XENDISPL_FIELD_EVT_CHANNEL "evt-event-channel" #define XENDISPL_FIELD_EVT_CHANNEL "evt-event-channel"
#define XENDISPL_FIELD_RESOLUTION "resolution" #define XENDISPL_FIELD_RESOLUTION "resolution"
#define XENDISPL_FIELD_BE_ALLOC "be-alloc" #define XENDISPL_FIELD_BE_ALLOC "be-alloc"
#define XENDISPL_FIELD_UNIQUE_ID "unique-id"
/* /*
****************************************************************************** ******************************************************************************

View File

@ -51,6 +51,18 @@
* corresponding entries in XenStore and puts 1 as the value of the entry. * 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. * 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 * feature-abs-pointer
* Values: <uint> * Values: <uint>
* *
@ -63,6 +75,22 @@
* Backends, which support reporting of multi-touch events * Backends, which support reporting of multi-touch events
* should set this to 1. * 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 ------------------------ *------------------------- Pointer Device Parameters ------------------------
* *
* width * width
@ -77,6 +105,25 @@
* Maximum Y coordinate (height) to be used by the frontend * Maximum Y coordinate (height) to be used by the frontend
* while reporting input events, pixels, [0; UINT32_MAX]. * 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 * Frontend XenBus Nodes
***************************************************************************** *****************************************************************************
@ -98,6 +145,13 @@
* *
* Request backend to report multi-touch events. * 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 ----------------------- *----------------------- Request Transport Parameters -----------------------
* *
* event-channel * event-channel
@ -117,25 +171,6 @@
* *
* OBSOLETE, not recommended for use. * OBSOLETE, not recommended for use.
* PFN of the shared page. * 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_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_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_FEAT_MTOUCH "feature-multi-touch"
#define XENKBD_FIELD_REQ_ABS_POINTER "request-abs-pointer" #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_REQ_MTOUCH "request-multi-touch"
#define XENKBD_FIELD_RING_GREF "page-gref" #define XENKBD_FIELD_RING_GREF "page-gref"
#define XENKBD_FIELD_EVT_CHANNEL "event-channel" #define XENKBD_FIELD_EVT_CHANNEL "event-channel"
@ -174,6 +213,7 @@
#define XENKBD_FIELD_MT_WIDTH "multi-touch-width" #define XENKBD_FIELD_MT_WIDTH "multi-touch-width"
#define XENKBD_FIELD_MT_HEIGHT "multi-touch-height" #define XENKBD_FIELD_MT_HEIGHT "multi-touch-height"
#define XENKBD_FIELD_MT_NUM_CONTACTS "multi-touch-num-contacts" #define XENKBD_FIELD_MT_NUM_CONTACTS "multi-touch-num-contacts"
#define XENKBD_FIELD_UNIQUE_ID "unique-id"
/* OBSOLETE, not recommended for use */ /* OBSOLETE, not recommended for use */
#define XENKBD_FIELD_RING_REF "page-ref" #define XENKBD_FIELD_RING_REF "page-ref"

View File

@ -278,13 +278,11 @@
* defined under the same device. * defined under the same device.
* *
* unique-id * unique-id
* Values: <uint32_t> * Values: <string>
* *
* After stream initialization it is assigned a unique ID (within the front * After stream initialization it is assigned a unique ID, so every
* driver), so every stream of the frontend can be identified by the * stream of the frontend can be identified by the backend by this ID.
* backend by this ID. This is not equal to stream-idx as the later is * This can be UUID or such.
* zero based within the device, but this index is contigous within the
* driver.
* *
*-------------------- Stream Request Transport Parameters -------------------- *-------------------- Stream Request Transport Parameters --------------------
* *

View File

@ -13,6 +13,7 @@
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/bug.h> #include <linux/bug.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/uaccess.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); EXPORT_SYMBOL(bitmap_copy_le);
#endif #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 #if BITS_PER_LONG == 64
/** /**
* bitmap_from_arr32 - copy the contents of u32 array of bits to bitmap * bitmap_from_arr32 - copy the contents of u32 array of bits to bitmap