* [PATCH v3 04/12] HID: multitouch: store a per application quirks value
From: Benjamin Tissoires @ 2018-06-21 12:09 UTC (permalink / raw)
To: Jiri Kosina, Dmitry Torokhov
Cc: Mario.Limonciello, Peter Hutterer, linux-input, linux-kernel,
Benjamin Tissoires
In-Reply-To: <20180621120908.16706-1-benjamin.tissoires@redhat.com>
If a device has more than one multitouch collection, there is a chance
we need per tool quirks. This is the case for the Totem on the Dell
Canvas.
Note that thesysfs attribute quirks can now get out of sync, but there
should not be much users of it as it's debugging only.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
no changes in v2
no changes in v3
---
drivers/hid/hid-multitouch.c | 64 ++++++++++++++++++++++----------------------
1 file changed, 32 insertions(+), 32 deletions(-)
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index cd207e99d26a..beaac36f61a7 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -99,6 +99,9 @@ struct mt_slot {
struct mt_application {
struct list_head list;
unsigned int application;
+
+ __s32 quirks;
+
struct mt_slot curdata; /* placeholder of incoming data */
int cc_index; /* contact count field index in the report */
@@ -368,7 +371,6 @@ static ssize_t mt_set_quirks(struct device *dev,
struct mt_application *application;
unsigned long val;
- bool confidence_found = false;
if (kstrtoul(buf, 0, &val))
return -EINVAL;
@@ -376,13 +378,11 @@ static ssize_t mt_set_quirks(struct device *dev,
td->mtclass.quirks = val;
list_for_each_entry(application, &td->applications, list) {
- if (application->have_contact_count)
- confidence_found = true;
+ application->quirks = val;
+ if (!application->have_contact_count)
+ application->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
}
- if (!confidence_found)
- td->mtclass.quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
-
return count;
}
@@ -501,6 +501,7 @@ static struct mt_application *mt_allocate_application(struct mt_device *td,
mt_application->cc_index = -1;
mt_application->scantime_index = -1;
+ mt_application->quirks = td->mtclass.quirks;
list_add_tail(&mt_application->list, &td->applications);
@@ -590,7 +591,7 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
case HID_UP_DIGITIZER:
switch (usage->hid) {
case HID_DG_INRANGE:
- if (cls->quirks & MT_QUIRK_HOVERING) {
+ if (app->quirks & MT_QUIRK_HOVERING) {
hid_map_usage(hi, usage, bit, max,
EV_ABS, ABS_MT_DISTANCE);
input_set_abs_params(hi->input,
@@ -602,7 +603,7 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
if ((cls->name == MT_CLS_WIN_8 ||
cls->name == MT_CLS_WIN_8_DUAL) &&
field->application == HID_DG_TOUCHPAD)
- cls->quirks |= MT_QUIRK_CONFIDENCE;
+ app->quirks |= MT_QUIRK_CONFIDENCE;
mt_store_field(usage, td, hi);
return 1;
case HID_DG_TIPSWITCH:
@@ -618,7 +619,7 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
case HID_DG_WIDTH:
hid_map_usage(hi, usage, bit, max,
EV_ABS, ABS_MT_TOUCH_MAJOR);
- if (!(cls->quirks & MT_QUIRK_NO_AREA))
+ if (!(app->quirks & MT_QUIRK_NO_AREA))
set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field,
cls->sn_width);
mt_store_field(usage, td, hi);
@@ -626,7 +627,7 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
case HID_DG_HEIGHT:
hid_map_usage(hi, usage, bit, max,
EV_ABS, ABS_MT_TOUCH_MINOR);
- if (!(cls->quirks & MT_QUIRK_NO_AREA)) {
+ if (!(app->quirks & MT_QUIRK_NO_AREA)) {
set_abs(hi->input, ABS_MT_TOUCH_MINOR, field,
cls->sn_height);
@@ -700,7 +701,7 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
* MS PTP spec says that external buttons left and right have
* usages 2 and 3.
*/
- if ((cls->quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
+ if ((app->quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
field->application == HID_DG_TOUCHPAD &&
(usage->hid & HID_USAGE) > 1)
code--;
@@ -719,7 +720,7 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
static int mt_compute_slot(struct mt_device *td, struct mt_application *app,
struct input_dev *input)
{
- __s32 quirks = td->mtclass.quirks;
+ __s32 quirks = app->quirks;
if (quirks & MT_QUIRK_SLOT_IS_CONTACTID)
return app->curdata.contactid;
@@ -743,11 +744,11 @@ static int mt_compute_slot(struct mt_device *td, struct mt_application *app,
static void mt_complete_slot(struct mt_device *td, struct mt_application *app,
struct input_dev *input)
{
- if ((td->mtclass.quirks & MT_QUIRK_CONTACT_CNT_ACCURATE) &&
+ if ((app->quirks & MT_QUIRK_CONTACT_CNT_ACCURATE) &&
app->num_received >= app->num_expected)
return;
- if (app->curvalid || (td->mtclass.quirks & MT_QUIRK_ALWAYS_VALID)) {
+ if (app->curvalid || (app->quirks & MT_QUIRK_ALWAYS_VALID)) {
int active;
int slotnum = mt_compute_slot(td, app, input);
struct mt_slot *s = &app->curdata;
@@ -756,14 +757,14 @@ static void mt_complete_slot(struct mt_device *td, struct mt_application *app,
if (slotnum < 0 || slotnum >= td->maxcontacts)
return;
- if ((td->mtclass.quirks & MT_QUIRK_IGNORE_DUPLICATES) && mt) {
+ if ((app->quirks & MT_QUIRK_IGNORE_DUPLICATES) && mt) {
struct input_mt_slot *slot = &mt->slots[slotnum];
if (input_mt_is_active(slot) &&
input_mt_is_used(mt, slot))
return;
}
- if (!(td->mtclass.quirks & MT_QUIRK_CONFIDENCE))
+ if (!(app->quirks & MT_QUIRK_CONFIDENCE))
s->confidence_state = true;
active = (s->touch_state || s->inrange_state) &&
s->confidence_state;
@@ -784,7 +785,7 @@ static void mt_complete_slot(struct mt_device *td, struct mt_application *app,
* divided by two to match visual scale of touch
* for devices with this quirk
*/
- if (td->mtclass.quirks & MT_QUIRK_TOUCH_SIZE_SCALING) {
+ if (app->quirks & MT_QUIRK_TOUCH_SIZE_SCALING) {
major = major >> 1;
minor = minor >> 1;
}
@@ -815,7 +816,7 @@ static void mt_complete_slot(struct mt_device *td, struct mt_application *app,
static void mt_sync_frame(struct mt_device *td, struct mt_application *app,
struct input_dev *input)
{
- if (td->mtclass.quirks & MT_QUIRK_WIN8_PTP_BUTTONS)
+ if (app->quirks & MT_QUIRK_WIN8_PTP_BUTTONS)
input_event(input, EV_KEY, BTN_LEFT, app->left_button_state);
input_mt_sync_frame(input);
@@ -867,7 +868,7 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
struct mt_application *app, bool first_packet)
{
struct mt_device *td = hid_get_drvdata(hid);
- __s32 quirks = td->mtclass.quirks;
+ __s32 quirks = app->quirks;
struct input_dev *input = field->hidinput->input;
if (hid->claimed & HID_CLAIMED_INPUT) {
@@ -1017,7 +1018,7 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
* of a possible multi-packet frame be checking that the
* timestamp has changed.
*/
- if ((td->mtclass.quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
+ if ((app->quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
app->num_received == 0 &&
app->prev_scantime != scantime)
app->num_expected = contact_count;
@@ -1061,7 +1062,7 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
* only affect laggish machines and the ones that have a firmware
* defect.
*/
- if (td->mtclass.quirks & MT_QUIRK_STICKY_FINGERS) {
+ if (app->quirks & MT_QUIRK_STICKY_FINGERS) {
if (test_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags))
mod_timer(&td->release_timer,
jiffies + msecs_to_jiffies(100));
@@ -1091,7 +1092,7 @@ static int mt_touch_input_configured(struct hid_device *hdev,
if (cls->is_indirect)
app->mt_flags |= INPUT_MT_POINTER;
- if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
+ if (app->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
app->mt_flags |= INPUT_MT_DROP_UNUSED;
/* check for clickpads */
@@ -1119,6 +1120,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
struct mt_device *td = hid_get_drvdata(hdev);
struct mt_application *application;
+ application = mt_find_application(td, field->application);
+
/*
* If mtclass.export_all_inputs is not set, only map fields from
* TouchScreen or TouchPad collections. We need to ignore fields
@@ -1134,7 +1137,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
field->application != HID_CP_CONSUMER_CONTROL &&
field->application != HID_GD_WIRELESS_RADIO_CTLS &&
!(field->application == HID_VD_ASUS_CUSTOM_MEDIA_KEYS &&
- td->mtclass.quirks & MT_QUIRK_ASUS_CUSTOM_UP))
+ application->quirks & MT_QUIRK_ASUS_CUSTOM_UP))
return -1;
/*
@@ -1143,7 +1146,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
* map usages to input keys.
*/
if (field->application == HID_VD_ASUS_CUSTOM_MEDIA_KEYS &&
- td->mtclass.quirks & MT_QUIRK_ASUS_CUSTOM_UP &&
+ application->quirks & MT_QUIRK_ASUS_CUSTOM_UP &&
(usage->hid & HID_USAGE_PAGE) == HID_UP_CUSTOM) {
set_bit(EV_REP, hi->input->evbit);
if (field->flags & HID_MAIN_ITEM_VARIABLE)
@@ -1160,8 +1163,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
return 1;
}
- application = mt_find_application(td, field->application);
-
/*
* some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
* for the stylus.
@@ -1267,9 +1268,9 @@ static bool mt_need_to_apply_feature(struct hid_device *hdev,
return true;
case HID_DG_CONTACTMAX:
- if (td->mtclass.maxcontacts) {
+ if (cls->maxcontacts) {
max = min_t(int, field->logical_maximum,
- td->mtclass.maxcontacts);
+ cls->maxcontacts);
if (field->value[index] != max) {
field->value[index] = max;
return true;
@@ -1332,7 +1333,7 @@ static void mt_set_modes(struct hid_device *hdev, enum latency_mode latency,
static void mt_post_parse_default_settings(struct mt_device *td,
struct mt_application *app)
{
- __s32 quirks = td->mtclass.quirks;
+ __s32 quirks = app->quirks;
/* unknown serial device needs special quirks */
if (app->touches_by_report == 1) {
@@ -1343,13 +1344,12 @@ static void mt_post_parse_default_settings(struct mt_device *td,
quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
}
- td->mtclass.quirks = quirks;
+ app->quirks = quirks;
}
static void mt_post_parse(struct mt_device *td, struct mt_application *app)
{
struct mt_fields *f = td->fields;
- struct mt_class *cls = &td->mtclass;
if (app->touches_by_report > 0) {
int field_count_per_touch;
@@ -1359,7 +1359,7 @@ static void mt_post_parse(struct mt_device *td, struct mt_application *app)
}
if (app->cc_index < 0)
- cls->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
+ app->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
}
static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
--
2.14.3
^ permalink raw reply related
* [PATCH v3 03/12] HID: multitouch: Store per collection multitouch data
From: Benjamin Tissoires @ 2018-06-21 12:08 UTC (permalink / raw)
To: Jiri Kosina, Dmitry Torokhov
Cc: Mario.Limonciello, Peter Hutterer, linux-input, linux-kernel,
Benjamin Tissoires
In-Reply-To: <20180621120908.16706-1-benjamin.tissoires@redhat.com>
Currently, hid-multitouch can only handle one multitouch collection at
a time. This is an issue for the Dell Canvas, as the Totem (a dial tool)
is also using a multitouch-like collection.
Factor out the multitouch collection data in their own struct.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
changes in v2:
- changed the url of hid-tools
no changes in v3
---
drivers/hid/hid-multitouch.c | 380 ++++++++++++++++++++++++++-----------------
1 file changed, 230 insertions(+), 150 deletions(-)
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 91624a2240ca..cd207e99d26a 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -28,14 +28,11 @@
*/
/*
- * This driver is regularly tested thanks to the tool hid-test[1].
- * This tool relies on hid-replay[2] and a database of hid devices[3].
+ * This driver is regularly tested thanks to the test suite in hid-tools[1].
* Please run these regression tests before patching this module so that
* your patch won't break existing known devices.
*
- * [1] https://github.com/bentiss/hid-test
- * [2] https://github.com/bentiss/hid-replay
- * [3] https://github.com/bentiss/hid-devices
+ * [1] https://gitlab.freedesktop.org/libevdev/hid-tools
*/
#include <linux/device.h>
@@ -99,6 +96,37 @@ struct mt_slot {
bool has_azimuth; /* the contact reports azimuth */
};
+struct mt_application {
+ struct list_head list;
+ unsigned int application;
+ struct mt_slot curdata; /* placeholder of incoming data */
+
+ int cc_index; /* contact count field index in the report */
+ int cc_value_index; /* contact count value index in the field */
+ int scantime_index; /* scantime field index in the report */
+ int scantime_val_index; /* scantime value index in the field */
+ unsigned int last_slot_field; /* the last field of a slot */
+ bool curvalid; /* is the current contact valid? */
+
+ int left_button_state; /* left button state */
+ unsigned int mt_flags; /* flags to pass to input-mt */
+
+ __u8 num_received; /* how many contacts we received */
+ __u8 num_expected; /* expected last contact index */
+ __u8 buttons_count; /* number of physical buttons per touchpad */
+ __u8 touches_by_report; /* how many touches are present in one report:
+ * 1 means we should use a serial protocol
+ * > 1 means hybrid (multitouch) protocol
+ */
+
+ __s32 dev_time; /* the scan time provided by the device */
+ unsigned long jiffies; /* the frame's jiffies */
+ int timestamp; /* the timestamp to be sent */
+ int prev_scantime; /* scantime reported previously */
+
+ bool have_contact_count;
+};
+
struct mt_class {
__s32 name; /* MT_CLS */
__s32 quirks;
@@ -117,40 +145,24 @@ struct mt_fields {
};
struct mt_device {
- struct mt_slot curdata; /* placeholder of incoming data */
struct mt_class mtclass; /* our mt device class */
struct timer_list release_timer; /* to release sticky fingers */
struct hid_device *hdev; /* hid_device we're attached to */
struct mt_fields *fields; /* temporary placeholder for storing the
multitouch fields */
unsigned long mt_io_flags; /* mt flags (MT_IO_FLAGS_*) */
- int cc_index; /* contact count field index in the report */
- int cc_value_index; /* contact count value index in the field */
- int scantime_index; /* scantime field index in the report */
- int scantime_val_index; /* scantime value index in the field */
- int prev_scantime; /* scantime reported in the previous packet */
- int left_button_state; /* left button state */
- unsigned last_slot_field; /* the last field of a slot */
unsigned mt_report_id; /* the report ID of the multitouch device */
__u8 inputmode_value; /* InputMode HID feature value */
- __u8 num_received; /* how many contacts we received */
- __u8 num_expected; /* expected last contact index */
__u8 maxcontacts;
- __u8 touches_by_report; /* how many touches are present in one report:
- * 1 means we should use a serial protocol
- * > 1 means hybrid (multitouch) protocol */
- __u8 buttons_count; /* number of physical buttons per touchpad */
bool is_buttonpad; /* is this device a button pad? */
bool serial_maybe; /* need to check for serial protocol */
- bool curvalid; /* is the current contact valid? */
- unsigned mt_flags; /* flags to pass to input-mt */
- __s32 dev_time; /* the scan time provided by the device */
- unsigned long jiffies; /* the frame's jiffies */
- int timestamp; /* the timestamp to be sent */
+
+ struct list_head applications;
};
-static void mt_post_parse_default_settings(struct mt_device *td);
-static void mt_post_parse(struct mt_device *td);
+static void mt_post_parse_default_settings(struct mt_device *td,
+ struct mt_application *app);
+static void mt_post_parse(struct mt_device *td, struct mt_application *app);
/* classes of device behavior */
#define MT_CLS_DEFAULT 0x0001
@@ -203,10 +215,10 @@ static void mt_post_parse(struct mt_device *td);
* to a valid contact that was just read.
*/
-static int cypress_compute_slot(struct mt_device *td)
+static int cypress_compute_slot(struct mt_application *app)
{
- if (td->curdata.contactid != 0 || td->num_received == 0)
- return td->curdata.contactid;
+ if (app->curdata.contactid != 0 || app->num_received == 0)
+ return app->curdata.contactid;
else
return -1;
}
@@ -353,15 +365,22 @@ static ssize_t mt_set_quirks(struct device *dev,
{
struct hid_device *hdev = to_hid_device(dev);
struct mt_device *td = hid_get_drvdata(hdev);
+ struct mt_application *application;
unsigned long val;
+ bool confidence_found = false;
if (kstrtoul(buf, 0, &val))
return -EINVAL;
td->mtclass.quirks = val;
- if (td->cc_index < 0)
+ list_for_each_entry(application, &td->applications, list) {
+ if (application->have_contact_count)
+ confidence_found = true;
+ }
+
+ if (!confidence_found)
td->mtclass.quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
return count;
@@ -457,6 +476,55 @@ static void set_abs(struct input_dev *input, unsigned int code,
input_abs_set_res(input, code, hidinput_calc_abs_res(field, code));
}
+static struct mt_application *mt_allocate_application(struct mt_device *td,
+ unsigned int application)
+{
+ struct mt_application *mt_application;
+
+ mt_application = devm_kzalloc(&td->hdev->dev, sizeof(*mt_application),
+ GFP_KERNEL);
+ if (!mt_application)
+ return NULL;
+
+ mt_application->application = application;
+
+ if (application == HID_DG_TOUCHSCREEN)
+ mt_application->mt_flags |= INPUT_MT_DIRECT;
+
+ /*
+ * Model touchscreens providing buttons as touchpads.
+ */
+ if (application == HID_DG_TOUCHPAD) {
+ mt_application->mt_flags |= INPUT_MT_POINTER;
+ td->inputmode_value = MT_INPUTMODE_TOUCHPAD;
+ }
+
+ mt_application->cc_index = -1;
+ mt_application->scantime_index = -1;
+
+ list_add_tail(&mt_application->list, &td->applications);
+
+ return mt_application;
+}
+
+static struct mt_application *mt_find_application(struct mt_device *td,
+ unsigned int application)
+{
+ struct mt_application *tmp, *mt_application = NULL;
+
+ list_for_each_entry(tmp, &td->applications, list) {
+ if (application == tmp->application) {
+ mt_application = tmp;
+ break;
+ }
+ }
+
+ if (!mt_application)
+ mt_application = mt_allocate_application(td, application);
+
+ return mt_application;
+}
+
static void mt_store_field(struct hid_usage *usage, struct mt_device *td,
struct hid_input *hi)
{
@@ -470,28 +538,24 @@ static void mt_store_field(struct hid_usage *usage, struct mt_device *td,
static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
- unsigned long **bit, int *max)
+ unsigned long **bit, int *max, struct mt_application *app)
{
struct mt_device *td = hid_get_drvdata(hdev);
struct mt_class *cls = &td->mtclass;
int code;
struct hid_usage *prev_usage = NULL;
- if (field->application == HID_DG_TOUCHSCREEN)
- td->mt_flags |= INPUT_MT_DIRECT;
-
/*
* Model touchscreens providing buttons as touchpads.
*/
- if (field->application == HID_DG_TOUCHPAD ||
- (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) {
- td->mt_flags |= INPUT_MT_POINTER;
+ if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) {
+ app->mt_flags |= INPUT_MT_POINTER;
td->inputmode_value = MT_INPUTMODE_TOUCHPAD;
}
/* count the buttons on touchpads */
if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON)
- td->buttons_count++;
+ app->buttons_count++;
if (usage->usage_index)
prev_usage = &field->usage[usage->usage_index - 1];
@@ -501,33 +565,23 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
case HID_UP_GENDESK:
switch (usage->hid) {
case HID_GD_X:
- if (prev_usage && (prev_usage->hid == usage->hid)) {
- hid_map_usage(hi, usage, bit, max,
- EV_ABS, ABS_MT_TOOL_X);
- set_abs(hi->input, ABS_MT_TOOL_X, field,
- cls->sn_move);
- } else {
- hid_map_usage(hi, usage, bit, max,
- EV_ABS, ABS_MT_POSITION_X);
- set_abs(hi->input, ABS_MT_POSITION_X, field,
- cls->sn_move);
- }
+ if (prev_usage && (prev_usage->hid == usage->hid))
+ code = ABS_MT_TOOL_X;
+ else
+ code = ABS_MT_POSITION_X;
+ hid_map_usage(hi, usage, bit, max, EV_ABS, code);
+ set_abs(hi->input, code, field, cls->sn_move);
mt_store_field(usage, td, hi);
return 1;
case HID_GD_Y:
- if (prev_usage && (prev_usage->hid == usage->hid)) {
- hid_map_usage(hi, usage, bit, max,
- EV_ABS, ABS_MT_TOOL_Y);
- set_abs(hi->input, ABS_MT_TOOL_Y, field,
- cls->sn_move);
- } else {
- hid_map_usage(hi, usage, bit, max,
- EV_ABS, ABS_MT_POSITION_Y);
- set_abs(hi->input, ABS_MT_POSITION_Y, field,
- cls->sn_move);
- }
+ if (prev_usage && (prev_usage->hid == usage->hid))
+ code = ABS_MT_TOOL_Y;
+ else
+ code = ABS_MT_POSITION_Y;
+ hid_map_usage(hi, usage, bit, max, EV_ABS, code);
+ set_abs(hi->input, code, field, cls->sn_move);
mt_store_field(usage, td, hi);
return 1;
}
@@ -558,7 +612,7 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
return 1;
case HID_DG_CONTACTID:
mt_store_field(usage, td, hi);
- td->touches_by_report++;
+ app->touches_by_report++;
td->mt_report_id = field->report->id;
return 1;
case HID_DG_WIDTH:
@@ -602,20 +656,16 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
if (field->index >= field->report->maxfield ||
usage->usage_index >= field->report_count)
return 1;
- td->scantime_index = field->index;
- td->scantime_val_index = usage->usage_index;
- /*
- * We don't set td->last_slot_field as scan time is
- * global to the report.
- */
+ app->scantime_index = field->index;
+ app->scantime_val_index = usage->usage_index;
return 1;
case HID_DG_CONTACTCOUNT:
/* Ignore if indexes are out of bounds. */
if (field->index >= field->report->maxfield ||
usage->usage_index >= field->report_count)
return 1;
- td->cc_index = field->index;
- td->cc_value_index = usage->usage_index;
+ app->cc_index = field->index;
+ app->cc_value_index = usage->usage_index;
return 1;
case HID_DG_AZIMUTH:
hid_map_usage(hi, usage, bit, max,
@@ -666,39 +716,41 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
return 0;
}
-static int mt_compute_slot(struct mt_device *td, struct input_dev *input)
+static int mt_compute_slot(struct mt_device *td, struct mt_application *app,
+ struct input_dev *input)
{
__s32 quirks = td->mtclass.quirks;
if (quirks & MT_QUIRK_SLOT_IS_CONTACTID)
- return td->curdata.contactid;
+ return app->curdata.contactid;
if (quirks & MT_QUIRK_CYPRESS)
- return cypress_compute_slot(td);
+ return cypress_compute_slot(app);
if (quirks & MT_QUIRK_SLOT_IS_CONTACTNUMBER)
- return td->num_received;
+ return app->num_received;
if (quirks & MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE)
- return td->curdata.contactid - 1;
+ return app->curdata.contactid - 1;
- return input_mt_get_slot_by_key(input, td->curdata.contactid);
+ return input_mt_get_slot_by_key(input, app->curdata.contactid);
}
/*
* this function is called when a whole contact has been processed,
* so that it can assign it to a slot and store the data there
*/
-static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
+static void mt_complete_slot(struct mt_device *td, struct mt_application *app,
+ struct input_dev *input)
{
if ((td->mtclass.quirks & MT_QUIRK_CONTACT_CNT_ACCURATE) &&
- td->num_received >= td->num_expected)
+ app->num_received >= app->num_expected)
return;
- if (td->curvalid || (td->mtclass.quirks & MT_QUIRK_ALWAYS_VALID)) {
+ if (app->curvalid || (td->mtclass.quirks & MT_QUIRK_ALWAYS_VALID)) {
int active;
- int slotnum = mt_compute_slot(td, input);
- struct mt_slot *s = &td->curdata;
+ int slotnum = mt_compute_slot(td, app, input);
+ struct mt_slot *s = &app->curdata;
struct input_mt *mt = input->mt;
if (slotnum < 0 || slotnum >= td->maxcontacts)
@@ -753,23 +805,25 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
}
}
- td->num_received++;
+ app->num_received++;
}
/*
* this function is called when a whole packet has been received and processed,
* so that it can decide what to send to the input layer.
*/
-static void mt_sync_frame(struct mt_device *td, struct input_dev *input)
+static void mt_sync_frame(struct mt_device *td, struct mt_application *app,
+ struct input_dev *input)
{
if (td->mtclass.quirks & MT_QUIRK_WIN8_PTP_BUTTONS)
- input_event(input, EV_KEY, BTN_LEFT, td->left_button_state);
+ input_event(input, EV_KEY, BTN_LEFT, app->left_button_state);
input_mt_sync_frame(input);
- input_event(input, EV_MSC, MSC_TIMESTAMP, td->timestamp);
+ input_event(input, EV_MSC, MSC_TIMESTAMP, app->timestamp);
input_sync(input);
- td->num_received = 0;
- td->left_button_state = 0;
+ app->num_received = 0;
+ app->left_button_state = 0;
+
if (test_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags))
set_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags);
else
@@ -777,14 +831,13 @@ static void mt_sync_frame(struct mt_device *td, struct input_dev *input)
clear_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags);
}
-static int mt_compute_timestamp(struct mt_device *td, struct hid_field *field,
- __s32 value)
+static int mt_compute_timestamp(struct mt_application *app,
+ struct hid_field *field, __s32 value)
{
- long delta = value - td->dev_time;
- unsigned long jdelta = jiffies_to_usecs(jiffies - td->jiffies);
+ long delta = value - app->prev_scantime;
+ unsigned long jdelta = jiffies_to_usecs(jiffies - app->jiffies);
- td->jiffies = jiffies;
- td->dev_time = value;
+ app->jiffies = jiffies;
if (delta < 0)
delta += field->logical_maximum;
@@ -796,7 +849,7 @@ static int mt_compute_timestamp(struct mt_device *td, struct hid_field *field,
/* No data received for a while, resync the timestamp. */
return 0;
else
- return td->timestamp + delta;
+ return app->timestamp + delta;
}
static int mt_touch_event(struct hid_device *hid, struct hid_field *field,
@@ -811,7 +864,7 @@ static int mt_touch_event(struct hid_device *hid, struct hid_field *field,
static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
struct hid_usage *usage, __s32 value,
- bool first_packet)
+ struct mt_application *app, bool first_packet)
{
struct mt_device *td = hid_get_drvdata(hid);
__s32 quirks = td->mtclass.quirks;
@@ -821,47 +874,48 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
switch (usage->hid) {
case HID_DG_INRANGE:
if (quirks & MT_QUIRK_VALID_IS_INRANGE)
- td->curvalid = value;
+ app->curvalid = value;
if (quirks & MT_QUIRK_HOVERING)
- td->curdata.inrange_state = value;
+ app->curdata.inrange_state = value;
break;
case HID_DG_TIPSWITCH:
if (quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
- td->curvalid = value;
- td->curdata.touch_state = value;
+ app->curvalid = value;
+ app->curdata.touch_state = value;
break;
case HID_DG_CONFIDENCE:
if (quirks & MT_QUIRK_CONFIDENCE)
- td->curdata.confidence_state = value;
+ app->curdata.confidence_state = value;
if (quirks & MT_QUIRK_VALID_IS_CONFIDENCE)
- td->curvalid = value;
+ app->curvalid = value;
break;
case HID_DG_CONTACTID:
- td->curdata.contactid = value;
+ app->curdata.contactid = value;
break;
case HID_DG_TIPPRESSURE:
- td->curdata.p = value;
+ app->curdata.p = value;
break;
case HID_GD_X:
if (usage->code == ABS_MT_TOOL_X)
- td->curdata.cx = value;
+ app->curdata.cx = value;
else
- td->curdata.x = value;
+ app->curdata.x = value;
break;
case HID_GD_Y:
if (usage->code == ABS_MT_TOOL_Y)
- td->curdata.cy = value;
+ app->curdata.cy = value;
else
- td->curdata.y = value;
+ app->curdata.y = value;
break;
case HID_DG_WIDTH:
- td->curdata.w = value;
+ app->curdata.w = value;
break;
case HID_DG_HEIGHT:
- td->curdata.h = value;
+ app->curdata.h = value;
break;
case HID_DG_SCANTIME:
- td->timestamp = mt_compute_timestamp(td, field, value);
+ app->timestamp = mt_compute_timestamp(app, field,
+ value);
break;
case HID_DG_CONTACTCOUNT:
break;
@@ -878,8 +932,8 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
*/
if (value > field->logical_maximum / 2)
value -= field->logical_maximum;
- td->curdata.a = -value;
- td->curdata.has_azimuth = true;
+ app->curdata.a = -value;
+ app->curdata.has_azimuth = true;
break;
case HID_DG_TOUCH:
/* do nothing */
@@ -904,7 +958,7 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
*/
if ((quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
usage->type == EV_KEY && usage->code == BTN_LEFT) {
- td->left_button_state |= value;
+ app->left_button_state |= value;
return;
}
@@ -916,8 +970,9 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
if (usage->usage_index + 1 == field->report_count) {
/* we only take into account the last report. */
- if (usage->hid == td->last_slot_field)
- mt_complete_slot(td, field->hidinput->input);
+ if (usage->hid == app->last_slot_field)
+ mt_complete_slot(td, app,
+ field->hidinput->input);
}
}
@@ -926,26 +981,34 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
{
struct mt_device *td = hid_get_drvdata(hid);
+ struct mt_application *app;
struct hid_field *field;
bool first_packet;
unsigned count;
- int r, n, scantime = 0;
+ int r, n;
+ int scantime = 0;
+ int contact_count = -1;
/* sticky fingers release in progress, abort */
if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))
return;
+ app = mt_find_application(td, report->application);
+
+ if (!app)
+ return;
+
/*
* Includes multi-packet support where subsequent
* packets are sent with zero contactcount.
*/
- if (td->scantime_index >= 0) {
- field = report->field[td->scantime_index];
- scantime = field->value[td->scantime_val_index];
+ if (app->scantime_index >= 0) {
+ field = report->field[app->scantime_index];
+ scantime = field->value[app->scantime_val_index];
}
- if (td->cc_index >= 0) {
- struct hid_field *field = report->field[td->cc_index];
- int value = field->value[td->cc_value_index];
+ if (app->cc_index >= 0) {
+ field = report->field[app->cc_index];
+ contact_count = field->value[app->cc_value_index];
/*
* For Win8 PTPs the first packet (td->num_received == 0) may
@@ -955,15 +1018,16 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
* timestamp has changed.
*/
if ((td->mtclass.quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
- td->num_received == 0 && td->prev_scantime != scantime)
- td->num_expected = value;
+ app->num_received == 0 &&
+ app->prev_scantime != scantime)
+ app->num_expected = contact_count;
/* A non 0 contact count always indicates a first packet */
- else if (value)
- td->num_expected = value;
+ else if (contact_count)
+ app->num_expected = contact_count;
}
- td->prev_scantime = scantime;
+ app->prev_scantime = scantime;
- first_packet = td->num_received == 0;
+ first_packet = app->num_received == 0;
for (r = 0; r < report->maxfield; r++) {
field = report->field[r];
count = field->report_count;
@@ -973,11 +1037,11 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
for (n = 0; n < count; n++)
mt_process_mt_event(hid, field, &field->usage[n],
- field->value[n], first_packet);
+ field->value[n], app, first_packet);
}
- if (td->num_received >= td->num_expected)
- mt_sync_frame(td, report->field[0]->hidinput->input);
+ if (app->num_received >= app->num_expected)
+ mt_sync_frame(td, app, report->field[0]->hidinput->input);
/*
* Windows 8 specs says 2 things:
@@ -1009,7 +1073,8 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
}
static int mt_touch_input_configured(struct hid_device *hdev,
- struct hid_input *hi)
+ struct hid_input *hi,
+ struct mt_application *app)
{
struct mt_device *td = hid_get_drvdata(hdev);
struct mt_class *cls = &td->mtclass;
@@ -1019,28 +1084,29 @@ static int mt_touch_input_configured(struct hid_device *hdev,
if (!td->maxcontacts)
td->maxcontacts = MT_DEFAULT_MAXCONTACT;
- mt_post_parse(td);
+ mt_post_parse(td, app);
if (td->serial_maybe)
- mt_post_parse_default_settings(td);
+ mt_post_parse_default_settings(td, app);
if (cls->is_indirect)
- td->mt_flags |= INPUT_MT_POINTER;
+ app->mt_flags |= INPUT_MT_POINTER;
if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
- td->mt_flags |= INPUT_MT_DROP_UNUSED;
+ app->mt_flags |= INPUT_MT_DROP_UNUSED;
/* check for clickpads */
- if ((td->mt_flags & INPUT_MT_POINTER) && (td->buttons_count == 1))
+ if ((app->mt_flags & INPUT_MT_POINTER) &&
+ (app->buttons_count == 1))
td->is_buttonpad = true;
if (td->is_buttonpad)
__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
- ret = input_mt_init_slots(input, td->maxcontacts, td->mt_flags);
+ ret = input_mt_init_slots(input, td->maxcontacts, app->mt_flags);
if (ret)
return ret;
- td->mt_flags = 0;
+ app->mt_flags = 0;
return 0;
}
@@ -1051,6 +1117,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
unsigned long **bit, int *max)
{
struct mt_device *td = hid_get_drvdata(hdev);
+ struct mt_application *application;
/*
* If mtclass.export_all_inputs is not set, only map fields from
@@ -1093,6 +1160,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
return 1;
}
+ application = mt_find_application(td, field->application);
+
/*
* some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
* for the stylus.
@@ -1109,7 +1178,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
if (field->application == HID_DG_TOUCHSCREEN ||
field->application == HID_DG_TOUCHPAD)
- return mt_touch_input_mapping(hdev, hi, field, usage, bit, max);
+ return mt_touch_input_mapping(hdev, hi, field, usage, bit, max,
+ application);
/* let hid-core decide for the others */
return 0;
@@ -1259,12 +1329,13 @@ static void mt_set_modes(struct hid_device *hdev, enum latency_mode latency,
}
}
-static void mt_post_parse_default_settings(struct mt_device *td)
+static void mt_post_parse_default_settings(struct mt_device *td,
+ struct mt_application *app)
{
__s32 quirks = td->mtclass.quirks;
/* unknown serial device needs special quirks */
- if (td->touches_by_report == 1) {
+ if (app->touches_by_report == 1) {
quirks |= MT_QUIRK_ALWAYS_VALID;
quirks &= ~MT_QUIRK_NOT_SEEN_MEANS_UP;
quirks &= ~MT_QUIRK_VALID_IS_INRANGE;
@@ -1275,17 +1346,19 @@ static void mt_post_parse_default_settings(struct mt_device *td)
td->mtclass.quirks = quirks;
}
-static void mt_post_parse(struct mt_device *td)
+static void mt_post_parse(struct mt_device *td, struct mt_application *app)
{
struct mt_fields *f = td->fields;
struct mt_class *cls = &td->mtclass;
- if (td->touches_by_report > 0) {
- int field_count_per_touch = f->length / td->touches_by_report;
- td->last_slot_field = f->usages[field_count_per_touch - 1];
+ if (app->touches_by_report > 0) {
+ int field_count_per_touch;
+
+ field_count_per_touch = f->length / app->touches_by_report;
+ app->last_slot_field = f->usages[field_count_per_touch - 1];
}
- if (td->cc_index < 0)
+ if (app->cc_index < 0)
cls->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
}
@@ -1295,13 +1368,17 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
char *name;
const char *suffix = NULL;
unsigned int application = 0;
+ struct mt_application *mt_application = NULL;
struct hid_report *report;
int ret;
list_for_each_entry(report, &hi->reports, hidinput_list) {
application = report->application;
+ mt_application = mt_find_application(td, application);
+
if (report->id == td->mt_report_id) {
- ret = mt_touch_input_configured(hdev, hi);
+ ret = mt_touch_input_configured(hdev, hi,
+ mt_application);
if (ret)
return ret;
}
@@ -1390,6 +1467,7 @@ static void mt_fix_const_fields(struct hid_device *hdev, unsigned int usage)
static void mt_release_contacts(struct hid_device *hid)
{
struct hid_input *hidinput;
+ struct mt_application *application;
struct mt_device *td = hid_get_drvdata(hid);
list_for_each_entry(hidinput, &hid->inputs, list) {
@@ -1409,7 +1487,9 @@ static void mt_release_contacts(struct hid_device *hid)
}
}
- td->num_received = 0;
+ list_for_each_entry(application, &td->applications, list) {
+ application->num_received = 0;
+ }
}
static void mt_expired_timeout(struct timer_list *t)
@@ -1449,11 +1529,11 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
td->hdev = hdev;
td->mtclass = *mtclass;
td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN;
- td->cc_index = -1;
- td->scantime_index = -1;
td->mt_report_id = -1;
hid_set_drvdata(hdev, td);
+ INIT_LIST_HEAD(&td->applications);
+
td->fields = devm_kzalloc(&hdev->dev, sizeof(struct mt_fields),
GFP_KERNEL);
if (!td->fields) {
--
2.14.3
^ permalink raw reply related
* [PATCH v3 02/12] HID: multitouch: make sure the static list of class is not changed
From: Benjamin Tissoires @ 2018-06-21 12:08 UTC (permalink / raw)
To: Jiri Kosina, Dmitry Torokhov
Cc: Mario.Limonciello, Peter Hutterer, linux-input, linux-kernel,
Benjamin Tissoires
In-Reply-To: <20180621120908.16706-1-benjamin.tissoires@redhat.com>
const is a magic keyword here :)
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
no changes in v2
no changes in v3
---
drivers/hid/hid-multitouch.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 45968f7970f8..91624a2240ca 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -211,7 +211,7 @@ static int cypress_compute_slot(struct mt_device *td)
return -1;
}
-static struct mt_class mt_classes[] = {
+static const struct mt_class mt_classes[] = {
{ .name = MT_CLS_DEFAULT,
.quirks = MT_QUIRK_ALWAYS_VALID |
MT_QUIRK_CONTACT_CNT_ACCURATE },
@@ -1432,7 +1432,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
int ret, i;
struct mt_device *td;
- struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */
+ const struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */
for (i = 0; mt_classes[i].name ; i++) {
if (id->driver_data == mt_classes[i].name) {
--
2.14.3
^ permalink raw reply related
* [PATCH v3 01/12] input: add MT_TOOL_DIAL
From: Benjamin Tissoires @ 2018-06-21 12:08 UTC (permalink / raw)
To: Jiri Kosina, Dmitry Torokhov
Cc: Mario.Limonciello, Peter Hutterer, linux-input, linux-kernel,
Benjamin Tissoires
In-Reply-To: <20180621120908.16706-1-benjamin.tissoires@redhat.com>
A dial is a tool you place on a multitouch surface which reports its
orientation or a relative angle of rotation when rotating its knob.
Some examples are the Dell Totem (on the Canvas 27"), the Microsoft Dial,
or the Griffin Powermate, though the later can't be put on a touch surface.
We give some extra space to account for other types of fingers if we need
(MT_TOOL_THUMB)
Slightly change the documentation to not make it mandatory to update each
MT_TOOL we add.
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
new in v2 (extracted from previous series in its own patch)
changes in v3:
- re-insert the change in include/uapi/linux/input.h
---
Documentation/input/multi-touch-protocol.rst | 12 ++++++------
include/uapi/linux/input.h | 3 ++-
2 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/Documentation/input/multi-touch-protocol.rst b/Documentation/input/multi-touch-protocol.rst
index b51751a0cd5d..6be70342e709 100644
--- a/Documentation/input/multi-touch-protocol.rst
+++ b/Documentation/input/multi-touch-protocol.rst
@@ -310,12 +310,12 @@ ABS_MT_TOOL_Y
ABS_MT_TOOL_TYPE
The type of approaching tool. A lot of kernel drivers cannot distinguish
between different tool types, such as a finger or a pen. In such cases, the
- event should be omitted. The protocol currently supports MT_TOOL_FINGER,
- MT_TOOL_PEN, and MT_TOOL_PALM [#f2]_. For type B devices, this event is
- handled by input core; drivers should instead use
- input_mt_report_slot_state(). A contact's ABS_MT_TOOL_TYPE may change over
- time while still touching the device, because the firmware may not be able
- to determine which tool is being used when it first appears.
+ event should be omitted. The protocol currently mainly supports
+ MT_TOOL_FINGER, MT_TOOL_PEN, and MT_TOOL_PALM [#f2]_.
+ For type B devices, this event is handled by input core; drivers should
+ instead use input_mt_report_slot_state(). A contact's ABS_MT_TOOL_TYPE may
+ change over time while still touching the device, because the firmware may
+ not be able to determine which tool is being used when it first appears.
ABS_MT_BLOB_ID
The BLOB_ID groups several packets together into one arbitrarily shaped
diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
index 7288a7c573cc..e931b0468b6d 100644
--- a/include/uapi/linux/input.h
+++ b/include/uapi/linux/input.h
@@ -273,7 +273,8 @@ struct input_mask {
#define MT_TOOL_FINGER 0
#define MT_TOOL_PEN 1
#define MT_TOOL_PALM 2
-#define MT_TOOL_MAX 2
+#define MT_TOOL_DIAL 10
+#define MT_TOOL_MAX 10
/*
* Values describing the status of a force-feedback effect
--
2.14.3
^ permalink raw reply related
* [PATCH v3 00/12] Hid multitouch rewrite, support os system multi-axis devices, take 3
From: Benjamin Tissoires @ 2018-06-21 12:08 UTC (permalink / raw)
To: Jiri Kosina, Dmitry Torokhov
Cc: Mario.Limonciello, Peter Hutterer, linux-input, linux-kernel,
Benjamin Tissoires
This is a small v3 of my previous series.
I dropped the first patch as requested by Dmitry and added his acked-by
in the new 1/12.
Cheers,
Benjamin
Benjamin Tissoires (12):
input: add MT_TOOL_DIAL
HID: multitouch: make sure the static list of class is not changed
HID: multitouch: Store per collection multitouch data
HID: multitouch: store a per application quirks value
HID: multitouch: ditch mt_report_id
HID: multitouch: remove one copy of values
HID: input: enable Totem on the Dell Canvas 27
HID: core: do not upper bound the collection stack
HID: microsoft: support the Surface Dial
HID: multitouch: report MT_TOOL_PALM for non-confident touches
HID: multitouch: touchscreens also use confidence reports
HID: multitouch: handle palm for touchscreens
Documentation/input/multi-touch-protocol.rst | 12 +-
drivers/hid/hid-core.c | 17 +-
drivers/hid/hid-input.c | 3 +
drivers/hid/hid-microsoft.c | 49 +-
drivers/hid/hid-multitouch.c | 996 ++++++++++++++++-----------
include/linux/hid.h | 15 +-
include/uapi/linux/input.h | 3 +-
7 files changed, 684 insertions(+), 411 deletions(-)
--
2.14.3
^ permalink raw reply
* Re: [PATCH] HID: core: allow concurrent registration of drivers
From: Benjamin Tissoires @ 2018-06-21 12:04 UTC (permalink / raw)
To: Mario Limonciello; +Cc: Jiri Kosina, open list:HID CORE LAYER, lkml
In-Reply-To: <4635b69c79704cc3beee5f97d9e739f2@ausx13mpc120.AMER.DELL.COM>
Hi,
On Mon, Jun 4, 2018 at 10:37 PM, <Mario.Limonciello@dell.com> wrote:
> Benjamin,
>
> I had to make a minor change since I didn't see
>> #define HID_STAT_DUP_DETECTED BIT(2)
> In Linus's tree.
>
> I tested with master today though and it seems to be working now with your patch across
> several boot attempts.
>
> Tested-by: Mario Limonciello <mario.limonciello@dell.com>
Thanks a lot Mario.
Jiri, I do not see this patch in your tree. Could you take it soon-ish
so we can backport it in 4.17 ASAP?
Cheers,
Benjamin
>
> Thanks,
>
>> -----Original Message-----
>> From: Benjamin Tissoires [mailto:benjamin.tissoires@redhat.com]
>> Sent: Thursday, May 31, 2018 6:49 AM
>> To: Jiri Kosina; Limonciello, Mario
>> Cc: linux-input@vger.kernel.org; linux-kernel@vger.kernel.org; Benjamin Tissoires
>> Subject: [PATCH] HID: core: allow concurrent registration of drivers
>>
>> Detected on the Dell XPS 9365.
>> The laptop has 2 devices that benefit from the hid-generic auto-unbinding.
>> When those 2 devices are presented to the userspace, udev loads both
>> wacom and hid-multitouch. When this happens, the code in
>> __hid_bus_reprobe_drivers() is called concurrently and the second device
>> gets reprobed twice.
>> An other bug in the power_supply subsystem prevent to remove the wacom
>> driver if it just finished its initialization, which basically kills
>> the wacom node.
>>
>> Fixes c17a7476e4c4 ("HID: core: rewrite the hid-generic automatic unbind")
>>
>> Cc: stable@vger.kernel.org # v4.17
>> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
>> ---
>>
>> Hi Mario,
>>
>> can you please test this on your faulty XPS?
>> I think it'll fix the issue, but I can not reproduce, so better wait for
>> your confirmation.
>>
>> Jiri, ideally I would love to see this in v4.17 final, but Mario seems
>> to be on PTO until next week. I guess we'll just push this in v4.17.1
>> then. Also, if you can double check that it makes sense, that would be
>> nice :)
>>
>> Cheers,
>> Benjamin
>>
>> drivers/hid/hid-core.c | 5 ++++-
>> include/linux/hid.h | 3 ++-
>> 2 files changed, 6 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
>> index 2f7367b1de00..7afed0c0f9e5 100644
>> --- a/drivers/hid/hid-core.c
>> +++ b/drivers/hid/hid-core.c
>> @@ -1960,6 +1960,8 @@ static int hid_device_probe(struct device *dev)
>> }
>> hdev->io_started = false;
>>
>> + clear_bit(ffs(HID_STAT_REPROBED), &hdev->status);
>> +
>> if (!hdev->driver) {
>> id = hid_match_device(hdev, hdrv);
>> if (id == NULL) {
>> @@ -2223,7 +2225,8 @@ static int __hid_bus_reprobe_drivers(struct device *dev,
>> void *data)
>> struct hid_device *hdev = to_hid_device(dev);
>>
>> if (hdev->driver == hdrv &&
>> - !hdrv->match(hdev, hid_ignore_special_drivers))
>> + !hdrv->match(hdev, hid_ignore_special_drivers) &&
>> + !test_and_set_bit(ffs(HID_STAT_REPROBED), &hdev->status))
>> return device_reprobe(dev);
>>
>> return 0;
>> diff --git a/include/linux/hid.h b/include/linux/hid.h
>> index ee2510019033..aee281522c6d 100644
>> --- a/include/linux/hid.h
>> +++ b/include/linux/hid.h
>> @@ -517,6 +517,7 @@ struct hid_output_fifo {
>> #define HID_STAT_ADDED BIT(0)
>> #define HID_STAT_PARSED BIT(1)
>> #define HID_STAT_DUP_DETECTED BIT(2)
>> +#define HID_STAT_REPROBED BIT(3)
>>
>> struct hid_input {
>> struct list_head list;
>> @@ -585,7 +586,7 @@ struct hid_device {
>> /* device report descriptor */
>> bool battery_avoid_query;
>> #endif
>>
>> - unsigned int status; /* see
>> STAT flags above */
>> + unsigned long status; /* see
>> STAT flags above */
>> unsigned claimed; /*
>> Claimed by hidinput, hiddev? */
>> unsigned quirks; /* Various
>> quirks the device can pull on us */
>> bool io_started; /* If IO has started
>> */
>> --
>> 2.14.3
>
^ permalink raw reply
* Re: [PATCH v7 0/4] mfd/regulator/clk/input: bd71837: ROHM BD71837 PMIC driver
From: Matti Vaittinen @ 2018-06-21 10:34 UTC (permalink / raw)
To: mturquette, sboyd, robh+dt, mark.rutland, lee.jones, lgirdwood,
broonie, mazziesaccount, arnd, dmitry.torokhov, sre, chenjh,
andrew.smirnov, linus.walleij, kstewart, heiko, gregkh
Cc: linux-clk, devicetree, linux-kernel, linux-input, mikko.mutanen,
heikki.haikola
In-Reply-To: <cover.1529404894.git.matti.vaittinen@fi.rohmeurope.com>
On Tue, Jun 19, 2018 at 01:55:31PM +0300, Matti Vaittinen wrote:
> Patch series adding support for ROHM BD71837 PMIC.
>
What is the preferred way when I send updated patches:
1. always resend _all_ unapplied patches even if there is no changes to
some of them. (patch-vN mail thread contains _all_ unapplied patches)
2. only resend changed patches (patch-vN mail thread contains only
patches that were changed from patch-vN-1)
I have currently used approach 1 - so that no patches would be
accidentally forgotten - but downside is that people need to check if
they have already reviewed some of the patches. I'd rather not caused
any extra work. What is the most convenient way for you guys?
Br,
Matti Vaittinen
^ permalink raw reply
* Re: [PATCH v7 4/4] input/power: Add driver for BD71837/BD71847 PMIC power button
From: Matti Vaittinen @ 2018-06-21 10:25 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: mturquette, sboyd, robh+dt, mark.rutland, lee.jones, lgirdwood,
broonie, mazziesaccount, arnd, sre, chenjh, andrew.smirnov,
linus.walleij, kstewart, heiko, gregkh, linux-clk, devicetree,
linux-kernel, linux-input, mikko.mutanen, heikki.haikola
In-Reply-To: <20180620064316.GB28784@localhost.localdomain>
On Wed, Jun 20, 2018 at 09:43:16AM +0300, Matti Vaittinen wrote:
> On Tue, Jun 19, 2018 at 10:50:28AM -0700, Dmitry Torokhov wrote:
> > Hi Matti,
> >
> > On Tue, Jun 19, 2018 at 01:57:09PM +0300, Matti Vaittinen wrote:
> > > ROHM BD71837 PMIC power button driver providing power-key press
> > > information to user-space.
> > >
> > > Signed-off-by: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
> > > ---
> > > drivers/input/misc/Kconfig | 10 +++++
> > > drivers/input/misc/Makefile | 1 +
> > > drivers/input/misc/bd718xx-pwrkey.c | 90 +++++++++++++++++++++++++++++++++++++
> > > 3 files changed, 101 insertions(+)
> > > create mode 100644 drivers/input/misc/bd718xx-pwrkey.c
> > >
> > > + platform_set_drvdata(pdev, pk);
> > > + err = regmap_update_bits(pk->mfd->regmap,
> > > + BD71837_REG_PWRONCONFIG0,
> > > + BD718XX_PWRBTN_SHORT_PRESS_MASK,
> > > + BD718XX_PWRBTN_SHORT_PRESS_10MS);
> >
> > This seems to be the only custom bit of set up in the driver, the rest I
> > think can easily be handled by gpio-keys.c in interrupt-only mode. Maybe
> > we could move this into MFD piece and drop this driver?
I did following in MFD driver - is this what you suggested:
+static struct gpio_keys_button btns[] = {
+ {
+ .code = KEY_POWER,
+ .gpio = -1,
+ .type = EV_KEY,
+ },
+};
+
+static struct gpio_keys_platform_data bd718xx_powerkey_data = {
+ .buttons = &btns[0],
+ .nbuttons = ARRAY_SIZE(btns),
+ .name = "bd718xx-pwrkey",
+};
+
+/* bd71837 multi function cells */
+
+static struct mfd_cell bd71837_mfd_cells[] = {
+ {
+ .name = "bd71837-clk",
+ }, {
+ .name = "gpio-keys",
+ .platform_data = &bd718xx_powerkey_data,
+ .pdata_size = sizeof(bd718xx_powerkey_data),
+ }, {
//snip
+static int bd71837_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
// snip
+ ret = regmap_add_irq_chip(bd71837->regmap, bd71837->chip_irq,
+ IRQF_ONESHOT, 0,
+ &bd71837_irq_chip, &bd71837->irq_data);
+ if (ret < 0) {
+ dev_err(bd71837->dev, "Failed to add irq_chip %d\n", ret);
+ goto err_out;
+ }
+ /* I think this should be done conditionally and only when pwrkey is used
+ * What would be the correct way to decide if we want to touch rhw button
+ * press detection times?
+ */
+ ret = regmap_update_bits(bd71837->regmap,
+ BD71837_REG_PWRONCONFIG0,
+ BD718XX_PWRBTN_PRESS_DURATION_MASK,
+ BD718XX_PWRBTN_SHORT_PRESS_10MS);
+ if (ret < 0) {
+ dev_err(bd71837->dev, "Failed to configure button short press timeout %d\n", ret);
+ goto err_out;
+ }
+ /* According to BD71847 datasheet the HW default for long press detection
+ * is 10ms. So letch change it to 10 sec so we can actually get the short
+ * push and allow gracefull shut down
+ */
+ ret = regmap_update_bits(bd71837->regmap,
+ BD71837_REG_PWRONCONFIG1,
+ BD718XX_PWRBTN_PRESS_DURATION_MASK,
+ BD718XX_PWRBTN_LONG_PRESS_10S);
+ if (ret < 0) {
+ dev_err(bd71837->dev, "Failed to configure button long press timeout %d\n", ret);
+ goto err_out;
+ }
+ btns[0].irq = regmap_irq_get_virq(bd71837->irq_data,
+ BD71837_INT_PWRBTN_S);
+
+ if (btns[0].irq < 0) {
+ ret = btns[0].irq;
+ goto err_out;
+ }
+
+ ret = mfd_add_devices(bd71837->dev, PLATFORM_DEVID_AUTO,
+ bd71837_mfd_cells, ARRAY_SIZE(bd71837_mfd_cells),
+ NULL, 0,
+ regmap_irq_get_domain(bd71837->irq_data));
If looks is Ok I will send new patch with this approach at next week -
unless I get lost during the traditional midsummer festival here in
Finland.
> Finally, there may be cases when power button is not attached to PMIC
> or is needing different configuration for 'short push'. This is why I
> would prefer having own Kconfig option for this power-key driver. I am
> not sure if it is easily doable if we use gpio_keys?
What would be the preferred mechanism for skipping the button push duration
configurations (time it takes for PMIC to detect short or long push)? Or
setting the durations to values user(s) would prefer? To me this sounds again
something we could configure from DT. Would adding propereties
rohm,short-press-ms and rohm,long-press-ms sound reasonable? I will send
the first version with no option to skip/specify the configuration
(fixed 10ms for short press, 10 sec for long press) but I would like to add
support for specifying the duration as next step.
Br,
Matti Vaittinen
^ permalink raw reply
* Re: [PATCH v3 3/5] bitmap: Add bitmap_alloc(), bitmap_zalloc() and bitmap_free()
From: Andy Shevchenko @ 2018-06-21 2:13 UTC (permalink / raw)
To: Andrew Morton
Cc: Dmitry Torokhov, Andy Shevchenko, agk, Mike Snitzer,
device-mapper development, shli, linux-raid,
linux-input@vger.kernel.org, Yury Norov, lkml, Mika Westerberg,
Joe Perches
In-Reply-To: <20180618161056.e52efd0e8bd36211e60705a2@linux-foundation.org>
On Tue, Jun 19, 2018 at 2:10 AM, Andrew Morton
<akpm@linux-foundation.org> wrote:
> On Mon, 18 Jun 2018 15:01:43 -0700 Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:
>> We can't as we end up including bitmap.h (by the way of cpumask.h)
>> form slab.h, so we gen circular dependency.
>
It's not just so easy. See below.
> That info should have been in the changelog, and probably a code
> comment.
>
>> Maybe if we removed memcg
>> stuff from slab.h so we do not need to include workqueue.h...
>
> Or move the basic slab API stuff out of slab.h into a new header. Or
> create a new, standalone work_struct.h - that looks pretty simple.
I tried to move out work_struct, it didn't help. There are actually
several circular dependencies that ends in bitmap.h either way or
another.
First one is
slab.h -> gfp.h -> mmzone.h -> nodemask.h -> bitmap.h
And so on...
Splitting out kXalloc stuff to a separate header won't help, I think,
because of the above.
Splitting out struct work_struct is just a tip of an iceberg.
Splitting out memcg stuff won't help in the similar way.
I'm all ears for (a better) solution.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH v2 03/10] input: rohm_bu21023: switch to i2c_lock_bus(..., I2C_LOCK_SEGMENT)
From: Dmitry Torokhov @ 2018-06-20 20:28 UTC (permalink / raw)
To: Peter Rosin
Cc: linux-kernel, Peter Huewe, Jarkko Sakkinen, Jason Gunthorpe,
Arnd Bergmann, Greg Kroah-Hartman, Brian Norris, Gregory Fong,
Florian Fainelli, bcm-kernel-feedback-list, Sekhar Nori,
Kevin Hilman, Haavard Skinnemoen, Kukjin Kim, Krzysztof Kozlowski,
Orson Zhai, Baolin Wang, Chunyan Zhang, Wolfram Sang,
Guenter Roeck
In-Reply-To: <20180620051803.12206-4-peda@axentia.se>
On Wed, Jun 20, 2018 at 07:17:56AM +0200, Peter Rosin wrote:
> Locking the root adapter for __i2c_transfer will deadlock if the
> device sits behind a mux-locked I2C mux. Switch to the finer-grained
> i2c_lock_bus with the I2C_LOCK_SEGMENT flag. If the device does not
> sit behind a mux-locked mux, the two locking variants are equivalent.
>
> Signed-off-by: Peter Rosin <peda@axentia.se>
Still
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Feel free to merge through I2C tree.
> ---
> drivers/input/touchscreen/rohm_bu21023.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/input/touchscreen/rohm_bu21023.c b/drivers/input/touchscreen/rohm_bu21023.c
> index bda0500c9b57..714affdd742f 100644
> --- a/drivers/input/touchscreen/rohm_bu21023.c
> +++ b/drivers/input/touchscreen/rohm_bu21023.c
> @@ -304,7 +304,7 @@ static int rohm_i2c_burst_read(struct i2c_client *client, u8 start, void *buf,
> msg[1].len = len;
> msg[1].buf = buf;
>
> - i2c_lock_adapter(adap);
> + i2c_lock_bus(adap, I2C_LOCK_SEGMENT);
>
> for (i = 0; i < 2; i++) {
> if (__i2c_transfer(adap, &msg[i], 1) < 0) {
> @@ -313,7 +313,7 @@ static int rohm_i2c_burst_read(struct i2c_client *client, u8 start, void *buf,
> }
> }
>
> - i2c_unlock_adapter(adap);
> + i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);
>
> return ret;
> }
> --
> 2.11.0
>
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH v2 5/5] Input: evdev - Switch to bitmap_zalloc()
From: Dmitry Torokhov @ 2018-06-20 20:26 UTC (permalink / raw)
To: Yury Norov
Cc: Andy Shevchenko, Alasdair Kergon, Mike Snitzer, dm-devel,
Shaohua Li, linux-raid, linux-input, Andrew Morton, linux-kernel,
mika.westerberg
In-Reply-To: <20180620081321.GB19364@yury-thinkpad>
On Wed, Jun 20, 2018 at 11:13:21AM +0300, Yury Norov wrote:
> On Tue, Jun 19, 2018 at 11:33:16AM -0700, Dmitry Torokhov wrote:
> > External Email
> >
> > On Sat, Jun 16, 2018 at 12:42:31AM +0300, Yury Norov wrote:
> > > Hi Andy,
> > >
> > > On Fri, Jun 15, 2018 at 04:20:17PM +0300, Andy Shevchenko wrote:
> > > > Switch to bitmap_zalloc() to show clearly what we are allocating.
> > > > Besides that it returns pointer of bitmap type instead of opaque void *.
> > > >
> > > > Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> > > > Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> > > > ---
> > > > drivers/input/evdev.c | 16 +++++++---------
> > > > 1 file changed, 7 insertions(+), 9 deletions(-)
> > > >
> > > > diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
> > > > index c81c79d01d93..370206f987f9 100644
> > > > --- a/drivers/input/evdev.c
> > > > +++ b/drivers/input/evdev.c
> > > > @@ -481,7 +481,7 @@ static int evdev_release(struct inode *inode, struct file *file)
> > > > evdev_detach_client(evdev, client);
> > > >
> > > > for (i = 0; i < EV_CNT; ++i)
> > > > - kfree(client->evmasks[i]);
> > > > + bitmap_free(client->evmasks[i]);
> > > >
> > > > kvfree(client);
> > > >
> > > > @@ -925,17 +925,15 @@ static int evdev_handle_get_val(struct evdev_client *client,
> > > > {
> > > > int ret;
> > > > unsigned long *mem;
> > > > - size_t len;
> > > >
> > > > - len = BITS_TO_LONGS(maxbit) * sizeof(unsigned long);
> > > > - mem = kmalloc(len, GFP_KERNEL);
> > > > + mem = bitmap_alloc(maxbit, GFP_KERNEL);
> > > > if (!mem)
> > > > return -ENOMEM;
> > >
> > > But in commit message you say you switch to bitmap_zalloc(). IIUC
> > > bitmap_alloc() is OK here. But could you please update comment to
> > > avoid confusing.
> > >
> > > >
> > > > spin_lock_irq(&dev->event_lock);
> > > > spin_lock(&client->buffer_lock);
> > > >
> > > > - memcpy(mem, bits, len);
> > > > + bitmap_copy(mem, bits, maxbit);
> > > >
> > > > spin_unlock(&dev->event_lock);
> > > >
> > > > @@ -947,7 +945,7 @@ static int evdev_handle_get_val(struct evdev_client *client,
> > > > if (ret < 0)
> > > > evdev_queue_syn_dropped(client);
> > > >
> > > > - kfree(mem);
> > > > + bitmap_free(mem);
> > > >
> > > > return ret;
> > > > }
> > > > @@ -1003,13 +1001,13 @@ static int evdev_set_mask(struct evdev_client *client,
> > > > if (!cnt)
> > > > return 0;
> > > >
> > > > - mask = kcalloc(sizeof(unsigned long), BITS_TO_LONGS(cnt), GFP_KERNEL);
> > > > + mask = bitmap_zalloc(cnt, GFP_KERNEL);
> > > > if (!mask)
> > > > return -ENOMEM;
> > > >
> > > > error = bits_from_user(mask, cnt - 1, codes_size, codes, compat);
> > >
> > > If my understanding of bits_from_user() correct, here you can also use
> > > bitmap_alloc(), true?
> >
> > bits_from_user() copies as much as user supplied, we want to zero out
> > the tail to make sure there is no garbage, so we want to use
> > kcalloc/kzalloc/bitmap_zalloc here.
>
> I don't understand that. Tail bits of bitmap (i.e. after last used bit
> till the end of last word) are always ignored by kernel code and there's
> no matter what was stored in that bits.
Users can supply as little as one long word worth of data (codes_size =
maxlen = 4). You really do not want the rest of the mask you will be
applying to contain random heap garbage.
>
> (With the exception of copying bitmap from kernel to userspace. For this
> case we have bitmap_copy_clear_tail() to avoid unintended exposing kernel
> data to user.)
>
> If you know any bitmap function that don't ignore tail bits, this is a
> bug and should be fixed.
>
> By the way, bits_from_user() is bad-designed because it takes 2 size
> arguments - maxbit and maxlen, and should be reworked. There's a
> single user of this function, and I suspect, it can be switched to
> existing core API, like bitmap_from_arr32().
I'm afraid you suspect wrong, as (unfortunately, but it is ABI now) we
are not dealing with masks consisting of u32 or u64 elements, but
"unsigned long" elements, which change size depending on 32/64 bit
architecture and whether we are dealing with compat or native userspace.
It also needs both maxbit and maxlen, because one is kernel's limit
while the other is limit from userspace POV and you need to reconcile
both to make sure you do not overrun buffers on either side.
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH v4 04/26] docs: fix broken references with multiple hints
From: Rob Herring @ 2018-06-20 15:26 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Mark Rutland, linux-fbdev, Dmitry Torokhov,
Linux Doc Mailing List, David Airlie, Roy Pledge, dri-devel,
Benjamin Tissoires, devel, Jonathan Corbet, James Morris,
Ingo Molnar, linux-input, Serge E. Hallyn, devicetree,
Bartlomiej Zolnierkiewicz, Jiri Kosina, Steven Rostedt,
Mauro Carvalho Chehab, linux-gpio, Greg Kroah-Hartman, linux-usb,
linux-kernel, linux-security-module
In-Reply-To: <75c14f6d84eef8c10787e85ddc172afebee116d6.1529079119.git.mchehab+samsung@kernel.org>
On Fri, Jun 15, 2018 at 01:30:32PM -0300, Mauro Carvalho Chehab wrote:
> The script:
> ./scripts/documentation-file-ref-check --fix
>
> Gives multiple hints for broken references on some files.
> Manually use the one that applies for some files.
>
> Acked-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
> ---
> Documentation/ABI/obsolete/sysfs-gpio | 2 +-
> .../devicetree/bindings/display/bridge/tda998x.txt | 2 +-
Acked-by: Rob Herring <robh@kernel.org>
> Documentation/trace/events.rst | 2 +-
> Documentation/trace/tracepoint-analysis.rst | 2 +-
> Documentation/translations/zh_CN/SubmittingDrivers | 2 +-
> Documentation/translations/zh_CN/gpio.txt | 4 ++--
> MAINTAINERS | 2 +-
> drivers/hid/usbhid/Kconfig | 2 +-
> drivers/input/Kconfig | 4 ++--
> drivers/input/joystick/Kconfig | 4 ++--
> drivers/input/joystick/iforce/Kconfig | 4 ++--
> drivers/input/serio/Kconfig | 4 ++--
> drivers/staging/fsl-mc/bus/dpio/dpio-driver.txt | 2 +-
> drivers/video/fbdev/skeletonfb.c | 8 ++++----
> include/linux/tracepoint.h | 2 +-
> security/device_cgroup.c | 2 +-
> 16 files changed, 24 insertions(+), 24 deletions(-)
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply
* Re: [PATCH v3 0/5] bitmap: Introduce alloc/free helpers
From: Andy Shevchenko @ 2018-06-20 10:16 UTC (permalink / raw)
To: Yury Norov
Cc: Alasdair Kergon, Mike Snitzer, dm-devel, Shaohua Li, linux-raid,
Dmitry Torokhov, linux-input, Andrew Morton, linux-kernel,
mika.westerberg, Joe Perches
In-Reply-To: <20180620072721.GA19364@yury-thinkpad>
On Wed, 2018-06-20 at 10:33 +0300, Yury Norov wrote:
> On Mon, Jun 18, 2018 at 04:09:58PM +0300, Andy Shevchenko wrote:
> > External Email
> >
> > A lot of code is using allocation of bitmaps using BITS_PER_LONG()
> > macro and
> > sizeof(unsigned long) operator. The readability suffers because of
> > this.
> >
> > The series introduces three helpers, i.e. bitmap_alloc(),
> > bitmap_zalloc() and
> > bitmap_free(), to make it more cleaner.
>
> tools/include/linux/bitmap.h already has bitmap_alloc(),
TBH, I don't give a crap about tools. They invented something that might
or might not follow kernel APIs. At the end, it's a user space.
> and it corresponds to bitmap_zalloc() in this patch. It may
> cause problems in future if people will copy functions that
> use bitmap_alloc between kernel code and tools. So I think
> we have to propagate this API to tools and update existing
> users of bitmap_alloc() in tools.
Propose a patch then. Perhaps I need to inform tools people about new
API coming, but that's all what I can do. Existing something in tools/
does not and should not prevent extending / changing kernel internal
APIs.
> What about code that calls specific alloc functions, like
> memblock_virt_alloc() and pcpu_mem_zalloc() in mm/percpu.c,
What about it? It's not in scope of this API for sure. The above
mentioned functions have a very limited area of usage.
Your example also a bit complicated, since it's not allocating _just_ a
bitmap, but a structure _with_ embedded bitmap.
> or devm_kcalloc() in drivers/dma/edma.c?
There is no such file in the tree. You perhaps referred to
drivers/dma/ti/edma.c.
Yes, this is a candidate to convert later on if anyone wants to do it
(with introducing devm_bitmap_alloc() / devm_bitmap_zalloc() helpers).
> If we are going to
> unify bitmap allocations in kernel, we should think about
> unification of that cases too. Should it be additional
> flag or optional pointer to the exact allocator in
> bitmap_{,z}alloc()?
So, I prefer one step at a time. Especially taking into consideration
the problems I have to solve now with those simplest helpers I proposed.
>
> Yury
>
> > Patch 1 is a preparatory to avoid namespace collisions between
> > bitmap API and
> > MD bitmap. No functional changes intended.
> >
> > Patch 2 is just orphaned from previous release cycle.
> >
> > Patch 3 introduces new helpers.
> >
> > Patches 4 and 5 is just an example how to use new helpers. Locally I
> > have like
> > dozen of them against different subsystems and drivers.
> >
> > Ideally it would go through Input subsystem, thus, needs an Ack from
> > MD maintainer(s).
> >
> > Since v2:
> > - fix compilation issue in MD bitmap code
> > - elaborate changes in commit message of patch 5
> >
> > Since v1:
> > - added namespace fix patch against MD bitmap API
> > - moved functions to lib/bitmap.c to avoid circular dependencies
> > - appended Dmitry's tags
> >
> > Andy Shevchenko (5):
> > md: Avoid namespace collision with bitmap API
> > bitmap: Drop unnecessary 0 check for u32 array operations
> > bitmap: Add bitmap_alloc(), bitmap_zalloc() and bitmap_free()
> > Input: gpio-keys - Switch to bitmap_zalloc()
> > Input: evdev - Switch to bitmap API
> >
> > drivers/input/evdev.c | 16 +-
> > drivers/input/keyboard/gpio_keys.c | 8 +-
> > drivers/md/dm-raid.c | 6 +-
> > drivers/md/md-bitmap.c | 301 +++++++++----
> > -----
> > drivers/md/md-bitmap.h | 46 +--
> > drivers/md/md-cluster.c | 16 +-
> > drivers/md/md.c | 44 +--
> > .../md/persistent-data/dm-space-map-common.c | 12 +-
> > drivers/md/raid1.c | 20 +-
> > drivers/md/raid10.c | 26 +-
> > drivers/md/raid5-cache.c | 2 +-
> > drivers/md/raid5.c | 24 +-
> > include/linux/bitmap.h | 8 +
> > lib/bitmap.c | 28 +-
> > 14 files changed, 283 insertions(+), 274 deletions(-)
> >
> > --
> > 2.17.1
--
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy
^ permalink raw reply
* Re: [PATCH v2 5/5] Input: evdev - Switch to bitmap_zalloc()
From: Yury Norov @ 2018-06-20 8:13 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Mike Snitzer, mika.westerberg, linux-kernel, linux-raid, dm-devel,
linux-input, Andrew Morton, Andy Shevchenko, Shaohua Li,
Alasdair Kergon
In-Reply-To: <20180619183316.GI71788@dtor-ws>
On Tue, Jun 19, 2018 at 11:33:16AM -0700, Dmitry Torokhov wrote:
> External Email
>
> On Sat, Jun 16, 2018 at 12:42:31AM +0300, Yury Norov wrote:
> > Hi Andy,
> >
> > On Fri, Jun 15, 2018 at 04:20:17PM +0300, Andy Shevchenko wrote:
> > > Switch to bitmap_zalloc() to show clearly what we are allocating.
> > > Besides that it returns pointer of bitmap type instead of opaque void *.
> > >
> > > Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> > > Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> > > ---
> > > drivers/input/evdev.c | 16 +++++++---------
> > > 1 file changed, 7 insertions(+), 9 deletions(-)
> > >
> > > diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
> > > index c81c79d01d93..370206f987f9 100644
> > > --- a/drivers/input/evdev.c
> > > +++ b/drivers/input/evdev.c
> > > @@ -481,7 +481,7 @@ static int evdev_release(struct inode *inode, struct file *file)
> > > evdev_detach_client(evdev, client);
> > >
> > > for (i = 0; i < EV_CNT; ++i)
> > > - kfree(client->evmasks[i]);
> > > + bitmap_free(client->evmasks[i]);
> > >
> > > kvfree(client);
> > >
> > > @@ -925,17 +925,15 @@ static int evdev_handle_get_val(struct evdev_client *client,
> > > {
> > > int ret;
> > > unsigned long *mem;
> > > - size_t len;
> > >
> > > - len = BITS_TO_LONGS(maxbit) * sizeof(unsigned long);
> > > - mem = kmalloc(len, GFP_KERNEL);
> > > + mem = bitmap_alloc(maxbit, GFP_KERNEL);
> > > if (!mem)
> > > return -ENOMEM;
> >
> > But in commit message you say you switch to bitmap_zalloc(). IIUC
> > bitmap_alloc() is OK here. But could you please update comment to
> > avoid confusing.
> >
> > >
> > > spin_lock_irq(&dev->event_lock);
> > > spin_lock(&client->buffer_lock);
> > >
> > > - memcpy(mem, bits, len);
> > > + bitmap_copy(mem, bits, maxbit);
> > >
> > > spin_unlock(&dev->event_lock);
> > >
> > > @@ -947,7 +945,7 @@ static int evdev_handle_get_val(struct evdev_client *client,
> > > if (ret < 0)
> > > evdev_queue_syn_dropped(client);
> > >
> > > - kfree(mem);
> > > + bitmap_free(mem);
> > >
> > > return ret;
> > > }
> > > @@ -1003,13 +1001,13 @@ static int evdev_set_mask(struct evdev_client *client,
> > > if (!cnt)
> > > return 0;
> > >
> > > - mask = kcalloc(sizeof(unsigned long), BITS_TO_LONGS(cnt), GFP_KERNEL);
> > > + mask = bitmap_zalloc(cnt, GFP_KERNEL);
> > > if (!mask)
> > > return -ENOMEM;
> > >
> > > error = bits_from_user(mask, cnt - 1, codes_size, codes, compat);
> >
> > If my understanding of bits_from_user() correct, here you can also use
> > bitmap_alloc(), true?
>
> bits_from_user() copies as much as user supplied, we want to zero out
> the tail to make sure there is no garbage, so we want to use
> kcalloc/kzalloc/bitmap_zalloc here.
I don't understand that. Tail bits of bitmap (i.e. after last used bit
till the end of last word) are always ignored by kernel code and there's
no matter what was stored in that bits.
(With the exception of copying bitmap from kernel to userspace. For this
case we have bitmap_copy_clear_tail() to avoid unintended exposing kernel
data to user.)
If you know any bitmap function that don't ignore tail bits, this is a
bug and should be fixed.
By the way, bits_from_user() is bad-designed because it takes 2 size
arguments - maxbit and maxlen, and should be reworked. There's a
single user of this function, and I suspect, it can be switched to
existing core API, like bitmap_from_arr32().
Yury
^ permalink raw reply
* Re: [PATCH v3 0/5] bitmap: Introduce alloc/free helpers
From: Yury Norov @ 2018-06-20 7:33 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Mike Snitzer, mika.westerberg, Dmitry Torokhov, linux-kernel,
linux-raid, dm-devel, linux-input, Joe Perches, Andrew Morton,
Shaohua Li, Alasdair Kergon
In-Reply-To: <20180618131003.88110-1-andriy.shevchenko@linux.intel.com>
On Mon, Jun 18, 2018 at 04:09:58PM +0300, Andy Shevchenko wrote:
> External Email
>
> A lot of code is using allocation of bitmaps using BITS_PER_LONG() macro and
> sizeof(unsigned long) operator. The readability suffers because of this.
>
> The series introduces three helpers, i.e. bitmap_alloc(), bitmap_zalloc() and
> bitmap_free(), to make it more cleaner.
tools/include/linux/bitmap.h already has bitmap_alloc(),
and it corresponds to bitmap_zalloc() in this patch. It may
cause problems in future if people will copy functions that
use bitmap_alloc between kernel code and tools. So I think
we have to propagate this API to tools and update existing
users of bitmap_alloc() in tools.
What about code that calls specific alloc functions, like
memblock_virt_alloc() and pcpu_mem_zalloc() in mm/percpu.c,
or devm_kcalloc() in drivers/dma/edma.c? If we are going to
unify bitmap allocations in kernel, we should think about
unification of that cases too. Should it be additional
flag or optional pointer to the exact allocator in
bitmap_{,z}alloc()?
Yury
> Patch 1 is a preparatory to avoid namespace collisions between bitmap API and
> MD bitmap. No functional changes intended.
>
> Patch 2 is just orphaned from previous release cycle.
>
> Patch 3 introduces new helpers.
>
> Patches 4 and 5 is just an example how to use new helpers. Locally I have like
> dozen of them against different subsystems and drivers.
>
> Ideally it would go through Input subsystem, thus, needs an Ack from MD maintainer(s).
>
> Since v2:
> - fix compilation issue in MD bitmap code
> - elaborate changes in commit message of patch 5
>
> Since v1:
> - added namespace fix patch against MD bitmap API
> - moved functions to lib/bitmap.c to avoid circular dependencies
> - appended Dmitry's tags
>
> Andy Shevchenko (5):
> md: Avoid namespace collision with bitmap API
> bitmap: Drop unnecessary 0 check for u32 array operations
> bitmap: Add bitmap_alloc(), bitmap_zalloc() and bitmap_free()
> Input: gpio-keys - Switch to bitmap_zalloc()
> Input: evdev - Switch to bitmap API
>
> drivers/input/evdev.c | 16 +-
> drivers/input/keyboard/gpio_keys.c | 8 +-
> drivers/md/dm-raid.c | 6 +-
> drivers/md/md-bitmap.c | 301 +++++++++---------
> drivers/md/md-bitmap.h | 46 +--
> drivers/md/md-cluster.c | 16 +-
> drivers/md/md.c | 44 +--
> .../md/persistent-data/dm-space-map-common.c | 12 +-
> drivers/md/raid1.c | 20 +-
> drivers/md/raid10.c | 26 +-
> drivers/md/raid5-cache.c | 2 +-
> drivers/md/raid5.c | 24 +-
> include/linux/bitmap.h | 8 +
> lib/bitmap.c | 28 +-
> 14 files changed, 283 insertions(+), 274 deletions(-)
>
> --
> 2.17.1
^ permalink raw reply
* Re: [PATCH v7 4/4] input/power: Add driver for BD71837/BD71847 PMIC power button
From: Matti Vaittinen @ 2018-06-20 6:43 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: mturquette, sboyd, robh+dt, mark.rutland, lee.jones, lgirdwood,
broonie, mazziesaccount, arnd, sre, chenjh, andrew.smirnov,
linus.walleij, kstewart, heiko, gregkh, linux-clk, devicetree,
linux-kernel, linux-input, mikko.mutanen, heikki.haikola
In-Reply-To: <20180619175028.GA71788@dtor-ws>
Hello Dmitry,
First of all - thanks for taking the time to review the patch =)
On Tue, Jun 19, 2018 at 10:50:28AM -0700, Dmitry Torokhov wrote:
> Hi Matti,
>
> On Tue, Jun 19, 2018 at 01:57:09PM +0300, Matti Vaittinen wrote:
> > ROHM BD71837 PMIC power button driver providing power-key press
> > information to user-space.
> >
> > Signed-off-by: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
> > ---
> > drivers/input/misc/Kconfig | 10 +++++
> > drivers/input/misc/Makefile | 1 +
> > drivers/input/misc/bd718xx-pwrkey.c | 90 +++++++++++++++++++++++++++++++++++++
> > 3 files changed, 101 insertions(+)
> > create mode 100644 drivers/input/misc/bd718xx-pwrkey.c
> >
> > + platform_set_drvdata(pdev, pk);
> > + err = regmap_update_bits(pk->mfd->regmap,
> > + BD71837_REG_PWRONCONFIG0,
> > + BD718XX_PWRBTN_SHORT_PRESS_MASK,
> > + BD718XX_PWRBTN_SHORT_PRESS_10MS);
>
> This seems to be the only custom bit of set up in the driver, the rest I
> think can easily be handled by gpio-keys.c in interrupt-only mode. Maybe
> we could move this into MFD piece and drop this driver?
I looked at the gpio_keys.c (for first time so please bear with me if I
ask something you consider as obvious). This is also the first time I am
dealing with input subsystem drivers. So this patch was kind of "RFC"
because I am unsure if this is the best way...
HW we are dealing with is a PMIC which can hace a power-button attached.
HW can generate 3 different types of interrupts for power button
presses:
1. interrupt when button is pressed or released. (Eg. if someone just
hits the button we get two interrupts of this type). We get no 'position
information' from PMIC - just the irqs. Hence it is difficult to know if
buttown was pressed or released. This is the reason why I decided not to
use this IRQ (at least not for now).
2. interrupt when button is pressed for 'short time'. Short time is
configurable and IRQ is generated when button is released based on the
duration it was held down. The limit for 'short time' can be configured.
By default if button is pressed longer than 3 seconds but less than 10
seconds the the PMIC detects 'short push'.
3. interrupt when button is pressed for 'long time'. Mechanism is same
as with short push. Default time is button held over 10 seconds. This
interrupt is not handled if PMIC provides power to processor as PMIC
will cut the power when long push is detected.
So the custom piece is setting the 'short push detection' time from
t > 3 sec to t > 10 msec. Driver is then using short push irq.
This means that we don't detect button press if it is shorter than 10ms.
But we don't need any button state information in driver either. This is
why I decided to use the short push irq - is it Ok?
After this explanation - the gpio_keys_irq_isr seems to be doing exactly
what is needed for short push handling (as far as I can tell). Now it
boils down to question how we should bundle the MFD and gpio_keys
together?
Should I just fill the gpio_keys_platform_data for gpio_keys in MFD
driver? After my short browsing of existing MFD drivers I did not see
any other drivers doing that. This is why I wonder if this is a correct
approach?
Still if MFD is configuring the button presses the gpio_keys for this chip
should only be used if MFD is used, right? Hence the gpio_keys driver
should be instantiaed from MFD, right?
Another option would be using DT and adding gpio_keys node to MFD node
or to simple-bus node. But I have an idea that this would make Rob
unhappy :) I had lenghty discussion with him about declaring the PMIC
as interrupt-controller in device-tree - and I was kindly educated that
it was not the way to go :) I'd rather not started this discussion
again.
Finally, there may be cases when power button is not attached to PMIC
or is needing different configuration for 'short push'. This is why I
would prefer having own Kconfig option for this power-key driver. I am
not sure if it is easily doable if we use gpio_keys?
Can you please give me some further pointer on how I could use the
gpio_keys from MFD?
Best Regards
Matti Vaittinen
^ permalink raw reply
* [PATCH v2 10/10] i2c: remove i2c_lock_adapter and use i2c_lock_bus directly
From: Peter Rosin @ 2018-06-20 5:18 UTC (permalink / raw)
To: linux-kernel
Cc: Peter Rosin, Peter Huewe, Jarkko Sakkinen, Jason Gunthorpe,
Arnd Bergmann, Greg Kroah-Hartman, Brian Norris, Gregory Fong,
Florian Fainelli, bcm-kernel-feedback-list, Sekhar Nori,
Kevin Hilman, Haavard Skinnemoen, Kukjin Kim, Krzysztof Kozlowski,
Orson Zhai, Baolin Wang, Chunyan Zhang, Wolfram Sang,
Guenter Roeck
In-Reply-To: <20180620051803.12206-1-peda@axentia.se>
The i2c_lock_adapter name is ambiguous since it is unclear if it
refers to the root adapter or the adapter you name in the argument.
The natural interpretation is the adapter you name in the argument,
but there are historical reasons for that not being the case; it
in fact locks the root adapter. Just remove the function and force
users to spell out the I2C_LOCK_ROOT_ADAPTER name to indicate what
is really going on. Also remove i2c_unlock_adapter, of course.
This patch was generated with
git grep -l 'i2c_\(un\)\?lock_adapter' \
| xargs sed -i 's/i2c_\(un\)\?lock_adapter(\([^)]*\))/'\
'i2c_\1lock_bus(\2, I2C_LOCK_ROOT_ADAPTER)/g'
followed by white-space touch-up.
Signed-off-by: Peter Rosin <peda@axentia.se>
---
drivers/i2c/busses/i2c-brcmstb.c | 8 ++++----
drivers/i2c/busses/i2c-davinci.c | 4 ++--
drivers/i2c/busses/i2c-gpio.c | 40 +++++++++++++++++++-------------------
drivers/i2c/busses/i2c-s3c2410.c | 4 ++--
drivers/i2c/busses/i2c-sprd.c | 8 ++++----
drivers/i2c/i2c-core-slave.c | 8 ++++----
drivers/iio/temperature/mlx90614.c | 4 ++--
include/linux/i2c.h | 12 ------------
8 files changed, 38 insertions(+), 50 deletions(-)
diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c
index 78792b4d6437..826d32049996 100644
--- a/drivers/i2c/busses/i2c-brcmstb.c
+++ b/drivers/i2c/busses/i2c-brcmstb.c
@@ -689,9 +689,9 @@ static int brcmstb_i2c_suspend(struct device *dev)
{
struct brcmstb_i2c_dev *i2c_dev = dev_get_drvdata(dev);
- i2c_lock_adapter(&i2c_dev->adapter);
+ i2c_lock_bus(&i2c_dev->adapter, I2C_LOCK_ROOT_ADAPTER);
i2c_dev->is_suspended = true;
- i2c_unlock_adapter(&i2c_dev->adapter);
+ i2c_unlock_bus(&i2c_dev->adapter, I2C_LOCK_ROOT_ADAPTER);
return 0;
}
@@ -700,10 +700,10 @@ static int brcmstb_i2c_resume(struct device *dev)
{
struct brcmstb_i2c_dev *i2c_dev = dev_get_drvdata(dev);
- i2c_lock_adapter(&i2c_dev->adapter);
+ i2c_lock_bus(&i2c_dev->adapter, I2C_LOCK_ROOT_ADAPTER);
brcmstb_i2c_set_bsc_reg_defaults(i2c_dev);
i2c_dev->is_suspended = false;
- i2c_unlock_adapter(&i2c_dev->adapter);
+ i2c_unlock_bus(&i2c_dev->adapter, I2C_LOCK_ROOT_ADAPTER);
return 0;
}
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 75d6ab177055..d945a2654c2f 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -714,14 +714,14 @@ static int i2c_davinci_cpufreq_transition(struct notifier_block *nb,
dev = container_of(nb, struct davinci_i2c_dev, freq_transition);
- i2c_lock_adapter(&dev->adapter);
+ i2c_lock_bus(&dev->adapter, I2C_LOCK_ROOT_ADAPTER);
if (val == CPUFREQ_PRECHANGE) {
davinci_i2c_reset_ctrl(dev, 0);
} else if (val == CPUFREQ_POSTCHANGE) {
i2c_davinci_calc_clk_dividers(dev);
davinci_i2c_reset_ctrl(dev, 1);
}
- i2c_unlock_adapter(&dev->adapter);
+ i2c_unlock_bus(&dev->adapter, I2C_LOCK_ROOT_ADAPTER);
return 0;
}
diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
index 005e6e0330c2..9d63337efa82 100644
--- a/drivers/i2c/busses/i2c-gpio.c
+++ b/drivers/i2c/busses/i2c-gpio.c
@@ -78,24 +78,24 @@ static struct dentry *i2c_gpio_debug_dir;
#define getscl(bd) ((bd)->getscl((bd)->data))
#define WIRE_ATTRIBUTE(wire) \
-static int fops_##wire##_get(void *data, u64 *val) \
-{ \
- struct i2c_gpio_private_data *priv = data; \
- \
- i2c_lock_adapter(&priv->adap); \
- *val = get##wire(&priv->bit_data); \
- i2c_unlock_adapter(&priv->adap); \
- return 0; \
-} \
-static int fops_##wire##_set(void *data, u64 val) \
-{ \
- struct i2c_gpio_private_data *priv = data; \
- \
- i2c_lock_adapter(&priv->adap); \
- set##wire(&priv->bit_data, val); \
- i2c_unlock_adapter(&priv->adap); \
- return 0; \
-} \
+static int fops_##wire##_get(void *data, u64 *val) \
+{ \
+ struct i2c_gpio_private_data *priv = data; \
+ \
+ i2c_lock_bus(&priv->adap, I2C_LOCK_ROOT_ADAPTER); \
+ *val = get##wire(&priv->bit_data); \
+ i2c_unlock_bus(&priv->adap, I2C_LOCK_ROOT_ADAPTER); \
+ return 0; \
+} \
+static int fops_##wire##_set(void *data, u64 val) \
+{ \
+ struct i2c_gpio_private_data *priv = data; \
+ \
+ i2c_lock_bus(&priv->adap, I2C_LOCK_ROOT_ADAPTER); \
+ set##wire(&priv->bit_data, val); \
+ i2c_unlock_bus(&priv->adap, I2C_LOCK_ROOT_ADAPTER); \
+ return 0; \
+} \
DEFINE_DEBUGFS_ATTRIBUTE(fops_##wire, fops_##wire##_get, fops_##wire##_set, "%llu\n")
WIRE_ATTRIBUTE(scl);
@@ -113,7 +113,7 @@ static int fops_incomplete_transfer_set(void *data, u64 addr)
/* ADDR (7 bit) + RD (1 bit) + SDA hi (1 bit) */
pattern = (addr << 2) | 3;
- i2c_lock_adapter(&priv->adap);
+ i2c_lock_bus(&priv->adap, I2C_LOCK_ROOT_ADAPTER);
/* START condition */
setsda(bit_data, 0);
@@ -129,7 +129,7 @@ static int fops_incomplete_transfer_set(void *data, u64 addr)
udelay(bit_data->udelay);
}
- i2c_unlock_adapter(&priv->adap);
+ i2c_unlock_bus(&priv->adap, I2C_LOCK_ROOT_ADAPTER);
return 0;
}
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 9fe2b6951895..2f2e28d60ef5 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -919,9 +919,9 @@ static int s3c24xx_i2c_cpufreq_transition(struct notifier_block *nb,
if ((val == CPUFREQ_POSTCHANGE && delta_f < 0) ||
(val == CPUFREQ_PRECHANGE && delta_f > 0)) {
- i2c_lock_adapter(&i2c->adap);
+ i2c_lock_bus(&i2c->adap, I2C_LOCK_ROOT_ADAPTER);
ret = s3c24xx_i2c_clockrate(i2c, &got);
- i2c_unlock_adapter(&i2c->adap);
+ i2c_unlock_bus(&i2c->adap, I2C_LOCK_ROOT_ADAPTER);
if (ret < 0)
dev_err(i2c->dev, "cannot find frequency (%d)\n", ret);
diff --git a/drivers/i2c/busses/i2c-sprd.c b/drivers/i2c/busses/i2c-sprd.c
index 4053259bccb8..a94e724f51dc 100644
--- a/drivers/i2c/busses/i2c-sprd.c
+++ b/drivers/i2c/busses/i2c-sprd.c
@@ -590,9 +590,9 @@ static int __maybe_unused sprd_i2c_suspend_noirq(struct device *pdev)
{
struct sprd_i2c *i2c_dev = dev_get_drvdata(pdev);
- i2c_lock_adapter(&i2c_dev->adap);
+ i2c_lock_bus(&i2c_dev->adap, I2C_LOCK_ROOT_ADAPTER);
i2c_dev->is_suspended = true;
- i2c_unlock_adapter(&i2c_dev->adap);
+ i2c_unlock_bus(&i2c_dev->adap, I2C_LOCK_ROOT_ADAPTER);
return pm_runtime_force_suspend(pdev);
}
@@ -601,9 +601,9 @@ static int __maybe_unused sprd_i2c_resume_noirq(struct device *pdev)
{
struct sprd_i2c *i2c_dev = dev_get_drvdata(pdev);
- i2c_lock_adapter(&i2c_dev->adap);
+ i2c_lock_bus(&i2c_dev->adap, I2C_LOCK_ROOT_ADAPTER);
i2c_dev->is_suspended = false;
- i2c_unlock_adapter(&i2c_dev->adap);
+ i2c_unlock_bus(&i2c_dev->adap, I2C_LOCK_ROOT_ADAPTER);
return pm_runtime_force_resume(pdev);
}
diff --git a/drivers/i2c/i2c-core-slave.c b/drivers/i2c/i2c-core-slave.c
index 4a78c65e9971..47a9f70a24a9 100644
--- a/drivers/i2c/i2c-core-slave.c
+++ b/drivers/i2c/i2c-core-slave.c
@@ -47,9 +47,9 @@ int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb)
client->slave_cb = slave_cb;
- i2c_lock_adapter(client->adapter);
+ i2c_lock_bus(client->adapter, I2C_LOCK_ROOT_ADAPTER);
ret = client->adapter->algo->reg_slave(client);
- i2c_unlock_adapter(client->adapter);
+ i2c_unlock_bus(client->adapter, I2C_LOCK_ROOT_ADAPTER);
if (ret) {
client->slave_cb = NULL;
@@ -69,9 +69,9 @@ int i2c_slave_unregister(struct i2c_client *client)
return -EOPNOTSUPP;
}
- i2c_lock_adapter(client->adapter);
+ i2c_lock_bus(client->adapter, I2C_LOCK_ROOT_ADAPTER);
ret = client->adapter->algo->unreg_slave(client);
- i2c_unlock_adapter(client->adapter);
+ i2c_unlock_bus(client->adapter, I2C_LOCK_ROOT_ADAPTER);
if (ret == 0)
client->slave_cb = NULL;
diff --git a/drivers/iio/temperature/mlx90614.c b/drivers/iio/temperature/mlx90614.c
index d619e8634a00..13a4cec64ea8 100644
--- a/drivers/iio/temperature/mlx90614.c
+++ b/drivers/iio/temperature/mlx90614.c
@@ -433,11 +433,11 @@ static int mlx90614_wakeup(struct mlx90614_data *data)
dev_dbg(&data->client->dev, "Requesting wake-up");
- i2c_lock_adapter(data->client->adapter);
+ i2c_lock_bus(data->client->adapter, I2C_LOCK_ROOT_ADAPTER);
gpiod_direction_output(data->wakeup_gpio, 0);
msleep(MLX90614_TIMING_WAKEUP);
gpiod_direction_input(data->wakeup_gpio);
- i2c_unlock_adapter(data->client->adapter);
+ i2c_unlock_bus(data->client->adapter, I2C_LOCK_ROOT_ADAPTER);
data->ready_timestamp = jiffies +
msecs_to_jiffies(MLX90614_TIMING_STARTUP);
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 254cd34eeae2..795e3a860afe 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -754,18 +754,6 @@ i2c_unlock_bus(struct i2c_adapter *adapter, unsigned int flags)
adapter->lock_ops->unlock_bus(adapter, flags);
}
-static inline void
-i2c_lock_adapter(struct i2c_adapter *adapter)
-{
- i2c_lock_bus(adapter, I2C_LOCK_ROOT_ADAPTER);
-}
-
-static inline void
-i2c_unlock_adapter(struct i2c_adapter *adapter)
-{
- i2c_unlock_bus(adapter, I2C_LOCK_ROOT_ADAPTER);
-}
-
/*flags for the client struct: */
#define I2C_CLIENT_PEC 0x04 /* Use Packet Error Checking */
#define I2C_CLIENT_TEN 0x10 /* we have a ten bit chip address */
--
2.11.0
^ permalink raw reply related
* [PATCH v2 09/10] mfd: 88pm860x-i2c: switch to i2c_lock_bus(..., I2C_LOCK_SEGMENT)
From: Peter Rosin @ 2018-06-20 5:18 UTC (permalink / raw)
To: linux-kernel
Cc: Peter Rosin, Peter Huewe, Jarkko Sakkinen, Jason Gunthorpe,
Arnd Bergmann, Greg Kroah-Hartman, Brian Norris, Gregory Fong,
Florian Fainelli, bcm-kernel-feedback-list, Sekhar Nori,
Kevin Hilman, Haavard Skinnemoen, Kukjin Kim, Krzysztof Kozlowski,
Orson Zhai, Baolin Wang, Chunyan Zhang, Wolfram Sang,
Guenter Roeck
In-Reply-To: <20180620051803.12206-1-peda@axentia.se>
Locking the root adapter for __i2c_transfer will deadlock if the
device sits behind a mux-locked I2C mux. Switch to the finer-grained
i2c_lock_bus with the I2C_LOCK_SEGMENT flag. If the device does not
sit behind a mux-locked mux, the two locking variants are equivalent.
Signed-off-by: Peter Rosin <peda@axentia.se>
---
drivers/mfd/88pm860x-i2c.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/mfd/88pm860x-i2c.c b/drivers/mfd/88pm860x-i2c.c
index 84e313107233..7b9052ea7413 100644
--- a/drivers/mfd/88pm860x-i2c.c
+++ b/drivers/mfd/88pm860x-i2c.c
@@ -146,14 +146,14 @@ int pm860x_page_reg_write(struct i2c_client *i2c, int reg,
unsigned char zero;
int ret;
- i2c_lock_adapter(i2c->adapter);
+ i2c_lock_bus(i2c->adapter, I2C_LOCK_SEGMENT);
read_device(i2c, 0xFA, 0, &zero);
read_device(i2c, 0xFB, 0, &zero);
read_device(i2c, 0xFF, 0, &zero);
ret = write_device(i2c, reg, 1, &data);
read_device(i2c, 0xFE, 0, &zero);
read_device(i2c, 0xFC, 0, &zero);
- i2c_unlock_adapter(i2c->adapter);
+ i2c_unlock_bus(i2c->adapter, I2C_LOCK_SEGMENT);
return ret;
}
EXPORT_SYMBOL(pm860x_page_reg_write);
@@ -164,14 +164,14 @@ int pm860x_page_bulk_read(struct i2c_client *i2c, int reg,
unsigned char zero = 0;
int ret;
- i2c_lock_adapter(i2c->adapter);
+ i2c_lock_bus(i2c->adapter, I2C_LOCK_SEGMENT);
read_device(i2c, 0xfa, 0, &zero);
read_device(i2c, 0xfb, 0, &zero);
read_device(i2c, 0xff, 0, &zero);
ret = read_device(i2c, reg, count, buf);
read_device(i2c, 0xFE, 0, &zero);
read_device(i2c, 0xFC, 0, &zero);
- i2c_unlock_adapter(i2c->adapter);
+ i2c_unlock_bus(i2c->adapter, I2C_LOCK_SEGMENT);
return ret;
}
EXPORT_SYMBOL(pm860x_page_bulk_read);
--
2.11.0
^ permalink raw reply related
* [PATCH v2 08/10] media: tda18271: switch to i2c_lock_bus(..., I2C_LOCK_SEGMENT)
From: Peter Rosin @ 2018-06-20 5:18 UTC (permalink / raw)
To: linux-kernel
Cc: Peter Rosin, Peter Huewe, Jarkko Sakkinen, Jason Gunthorpe,
Arnd Bergmann, Greg Kroah-Hartman, Brian Norris, Gregory Fong,
Florian Fainelli, bcm-kernel-feedback-list, Sekhar Nori,
Kevin Hilman, Haavard Skinnemoen, Kukjin Kim, Krzysztof Kozlowski,
Orson Zhai, Baolin Wang, Chunyan Zhang, Wolfram Sang,
Guenter Roeck
In-Reply-To: <20180620051803.12206-1-peda@axentia.se>
Locking the root adapter for __i2c_transfer will deadlock if the
device sits behind a mux-locked I2C mux. Switch to the finer-grained
i2c_lock_bus with the I2C_LOCK_SEGMENT flag. If the device does not
sit behind a mux-locked mux, the two locking variants are equivalent.
Signed-off-by: Peter Rosin <peda@axentia.se>
---
drivers/media/tuners/tda18271-common.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/media/tuners/tda18271-common.c b/drivers/media/tuners/tda18271-common.c
index 7e81cd887c13..054b3b747dae 100644
--- a/drivers/media/tuners/tda18271-common.c
+++ b/drivers/media/tuners/tda18271-common.c
@@ -225,7 +225,7 @@ static int __tda18271_write_regs(struct dvb_frontend *fe, int idx, int len,
*/
if (lock_i2c) {
tda18271_i2c_gate_ctrl(fe, 1);
- i2c_lock_adapter(priv->i2c_props.adap);
+ i2c_lock_bus(priv->i2c_props.adap, I2C_LOCK_SEGMENT);
}
while (len) {
if (max > len)
@@ -246,7 +246,7 @@ static int __tda18271_write_regs(struct dvb_frontend *fe, int idx, int len,
len -= max;
}
if (lock_i2c) {
- i2c_unlock_adapter(priv->i2c_props.adap);
+ i2c_unlock_bus(priv->i2c_props.adap, I2C_LOCK_SEGMENT);
tda18271_i2c_gate_ctrl(fe, 0);
}
@@ -300,7 +300,7 @@ int tda18271_init_regs(struct dvb_frontend *fe)
* as those could cause bad things
*/
tda18271_i2c_gate_ctrl(fe, 1);
- i2c_lock_adapter(priv->i2c_props.adap);
+ i2c_lock_bus(priv->i2c_props.adap, I2C_LOCK_SEGMENT);
/* initialize registers */
switch (priv->id) {
@@ -516,7 +516,7 @@ int tda18271_init_regs(struct dvb_frontend *fe)
/* synchronize */
__tda18271_write_regs(fe, R_EP1, 1, false);
- i2c_unlock_adapter(priv->i2c_props.adap);
+ i2c_unlock_bus(priv->i2c_props.adap, I2C_LOCK_SEGMENT);
tda18271_i2c_gate_ctrl(fe, 0);
return 0;
--
2.11.0
^ permalink raw reply related
* [PATCH v2 07/10] media: tda1004x: switch to i2c_lock_bus(..., I2C_LOCK_SEGMENT)
From: Peter Rosin @ 2018-06-20 5:18 UTC (permalink / raw)
To: linux-kernel
Cc: Peter Rosin, Peter Huewe, Jarkko Sakkinen, Jason Gunthorpe,
Arnd Bergmann, Greg Kroah-Hartman, Brian Norris, Gregory Fong,
Florian Fainelli, bcm-kernel-feedback-list, Sekhar Nori,
Kevin Hilman, Haavard Skinnemoen, Kukjin Kim, Krzysztof Kozlowski,
Orson Zhai, Baolin Wang, Chunyan Zhang, Wolfram Sang,
Guenter Roeck
In-Reply-To: <20180620051803.12206-1-peda@axentia.se>
Locking the root adapter for __i2c_transfer will deadlock if the
device sits behind a mux-locked I2C mux. Switch to the finer-grained
i2c_lock_bus with the I2C_LOCK_SEGMENT flag. If the device does not
sit behind a mux-locked mux, the two locking variants are equivalent.
Signed-off-by: Peter Rosin <peda@axentia.se>
---
drivers/media/dvb-frontends/tda1004x.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/media/dvb-frontends/tda1004x.c b/drivers/media/dvb-frontends/tda1004x.c
index 7dcfb4a4b2d0..9d3261bf5090 100644
--- a/drivers/media/dvb-frontends/tda1004x.c
+++ b/drivers/media/dvb-frontends/tda1004x.c
@@ -329,7 +329,7 @@ static int tda1004x_do_upload(struct tda1004x_state *state,
tda1004x_write_byteI(state, dspCodeCounterReg, 0);
fw_msg.addr = state->config->demod_address;
- i2c_lock_adapter(state->i2c);
+ i2c_lock_bus(state->i2c, I2C_LOCK_SEGMENT);
buf[0] = dspCodeInReg;
while (pos != len) {
// work out how much to send this time
@@ -342,14 +342,14 @@ static int tda1004x_do_upload(struct tda1004x_state *state,
fw_msg.len = tx_size + 1;
if (__i2c_transfer(state->i2c, &fw_msg, 1) != 1) {
printk(KERN_ERR "tda1004x: Error during firmware upload\n");
- i2c_unlock_adapter(state->i2c);
+ i2c_unlock_bus(state->i2c, I2C_LOCK_SEGMENT);
return -EIO;
}
pos += tx_size;
dprintk("%s: fw_pos=0x%x\n", __func__, pos);
}
- i2c_unlock_adapter(state->i2c);
+ i2c_unlock_bus(state->i2c, I2C_LOCK_SEGMENT);
/* give the DSP a chance to settle 03/10/05 Hac */
msleep(100);
--
2.11.0
^ permalink raw reply related
* [PATCH v2 06/10] media: rtl2830: switch to i2c_lock_bus(..., I2C_LOCK_SEGMENT)
From: Peter Rosin @ 2018-06-20 5:17 UTC (permalink / raw)
To: linux-kernel
Cc: Peter Rosin, Peter Huewe, Jarkko Sakkinen, Jason Gunthorpe,
Arnd Bergmann, Greg Kroah-Hartman, Brian Norris, Gregory Fong,
Florian Fainelli, bcm-kernel-feedback-list, Sekhar Nori,
Kevin Hilman, Haavard Skinnemoen, Kukjin Kim, Krzysztof Kozlowski,
Orson Zhai, Baolin Wang, Chunyan Zhang, Wolfram Sang,
Guenter Roeck
In-Reply-To: <20180620051803.12206-1-peda@axentia.se>
Locking the root adapter for __i2c_transfer will deadlock if the
device sits behind a mux-locked I2C mux. Switch to the finer-grained
i2c_lock_bus with the I2C_LOCK_SEGMENT flag. If the device does not
sit behind a mux-locked mux, the two locking variants are equivalent.
Signed-off-by: Peter Rosin <peda@axentia.se>
---
drivers/media/dvb-frontends/rtl2830.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c
index 7bbfe11d11ed..91d12e6a03d5 100644
--- a/drivers/media/dvb-frontends/rtl2830.c
+++ b/drivers/media/dvb-frontends/rtl2830.c
@@ -24,9 +24,9 @@ static int rtl2830_bulk_write(struct i2c_client *client, unsigned int reg,
struct rtl2830_dev *dev = i2c_get_clientdata(client);
int ret;
- i2c_lock_adapter(client->adapter);
+ i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
ret = regmap_bulk_write(dev->regmap, reg, val, val_count);
- i2c_unlock_adapter(client->adapter);
+ i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
return ret;
}
@@ -36,9 +36,9 @@ static int rtl2830_update_bits(struct i2c_client *client, unsigned int reg,
struct rtl2830_dev *dev = i2c_get_clientdata(client);
int ret;
- i2c_lock_adapter(client->adapter);
+ i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
ret = regmap_update_bits(dev->regmap, reg, mask, val);
- i2c_unlock_adapter(client->adapter);
+ i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
return ret;
}
@@ -48,9 +48,9 @@ static int rtl2830_bulk_read(struct i2c_client *client, unsigned int reg,
struct rtl2830_dev *dev = i2c_get_clientdata(client);
int ret;
- i2c_lock_adapter(client->adapter);
+ i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
ret = regmap_bulk_read(dev->regmap, reg, val, val_count);
- i2c_unlock_adapter(client->adapter);
+ i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
return ret;
}
--
2.11.0
^ permalink raw reply related
* [PATCH v2 05/10] media: drxk_hard: switch to i2c_lock_bus(..., I2C_LOCK_SEGMENT)
From: Peter Rosin @ 2018-06-20 5:17 UTC (permalink / raw)
To: linux-kernel
Cc: Peter Rosin, Peter Huewe, Jarkko Sakkinen, Jason Gunthorpe,
Arnd Bergmann, Greg Kroah-Hartman, Brian Norris, Gregory Fong,
Florian Fainelli, bcm-kernel-feedback-list, Sekhar Nori,
Kevin Hilman, Haavard Skinnemoen, Kukjin Kim, Krzysztof Kozlowski,
Orson Zhai, Baolin Wang, Chunyan Zhang, Wolfram Sang,
Guenter Roeck
In-Reply-To: <20180620051803.12206-1-peda@axentia.se>
Locking the root adapter for __i2c_transfer will deadlock if the
device sits behind a mux-locked I2C mux. Switch to the finer-grained
i2c_lock_bus with the I2C_LOCK_SEGMENT flag. If the device does not
sit behind a mux-locked mux, the two locking variants are equivalent.
Signed-off-by: Peter Rosin <peda@axentia.se>
---
drivers/media/dvb-frontends/drxk_hard.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c
index 5a26ad93be10..29c36f95d624 100644
--- a/drivers/media/dvb-frontends/drxk_hard.c
+++ b/drivers/media/dvb-frontends/drxk_hard.c
@@ -213,7 +213,7 @@ static inline u32 log10times100(u32 value)
static int drxk_i2c_lock(struct drxk_state *state)
{
- i2c_lock_adapter(state->i2c);
+ i2c_lock_bus(state->i2c, I2C_LOCK_SEGMENT);
state->drxk_i2c_exclusive_lock = true;
return 0;
@@ -224,7 +224,7 @@ static void drxk_i2c_unlock(struct drxk_state *state)
if (!state->drxk_i2c_exclusive_lock)
return;
- i2c_unlock_adapter(state->i2c);
+ i2c_unlock_bus(state->i2c, I2C_LOCK_SEGMENT);
state->drxk_i2c_exclusive_lock = false;
}
--
2.11.0
^ permalink raw reply related
* [PATCH v2 04/10] media: af9013: switch to i2c_lock_bus(..., I2C_LOCK_SEGMENT)
From: Peter Rosin @ 2018-06-20 5:17 UTC (permalink / raw)
To: linux-kernel
Cc: Peter Rosin, Peter Huewe, Jarkko Sakkinen, Jason Gunthorpe,
Arnd Bergmann, Greg Kroah-Hartman, Brian Norris, Gregory Fong,
Florian Fainelli, bcm-kernel-feedback-list, Sekhar Nori,
Kevin Hilman, Haavard Skinnemoen, Kukjin Kim, Krzysztof Kozlowski,
Orson Zhai, Baolin Wang, Chunyan Zhang, Wolfram Sang,
Guenter Roeck
In-Reply-To: <20180620051803.12206-1-peda@axentia.se>
Locking the root adapter for __i2c_transfer will deadlock if the
device sits behind a mux-locked I2C mux. Switch to the finer-grained
i2c_lock_bus with the I2C_LOCK_SEGMENT flag. If the device does not
sit behind a mux-locked mux, the two locking variants are equivalent.
Signed-off-by: Peter Rosin <peda@axentia.se>
---
drivers/media/dvb-frontends/af9013.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/media/dvb-frontends/af9013.c b/drivers/media/dvb-frontends/af9013.c
index 482bce49819a..99361c113bca 100644
--- a/drivers/media/dvb-frontends/af9013.c
+++ b/drivers/media/dvb-frontends/af9013.c
@@ -1312,10 +1312,10 @@ static int af9013_wregs(struct i2c_client *client, u8 cmd, u16 reg,
memcpy(&buf[3], val, len);
if (lock)
- i2c_lock_adapter(client->adapter);
+ i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
ret = __i2c_transfer(client->adapter, msg, 1);
if (lock)
- i2c_unlock_adapter(client->adapter);
+ i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
if (ret < 0) {
goto err;
} else if (ret != 1) {
@@ -1353,10 +1353,10 @@ static int af9013_rregs(struct i2c_client *client, u8 cmd, u16 reg,
buf[2] = cmd;
if (lock)
- i2c_lock_adapter(client->adapter);
+ i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
ret = __i2c_transfer(client->adapter, msg, 2);
if (lock)
- i2c_unlock_adapter(client->adapter);
+ i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
if (ret < 0) {
goto err;
} else if (ret != 2) {
--
2.11.0
^ permalink raw reply related
* [PATCH v2 03/10] input: rohm_bu21023: switch to i2c_lock_bus(..., I2C_LOCK_SEGMENT)
From: Peter Rosin @ 2018-06-20 5:17 UTC (permalink / raw)
To: linux-kernel
Cc: Peter Rosin, Peter Huewe, Jarkko Sakkinen, Jason Gunthorpe,
Arnd Bergmann, Greg Kroah-Hartman, Brian Norris, Gregory Fong,
Florian Fainelli, bcm-kernel-feedback-list, Sekhar Nori,
Kevin Hilman, Haavard Skinnemoen, Kukjin Kim, Krzysztof Kozlowski,
Orson Zhai, Baolin Wang, Chunyan Zhang, Wolfram Sang,
Guenter Roeck
In-Reply-To: <20180620051803.12206-1-peda@axentia.se>
Locking the root adapter for __i2c_transfer will deadlock if the
device sits behind a mux-locked I2C mux. Switch to the finer-grained
i2c_lock_bus with the I2C_LOCK_SEGMENT flag. If the device does not
sit behind a mux-locked mux, the two locking variants are equivalent.
Signed-off-by: Peter Rosin <peda@axentia.se>
---
drivers/input/touchscreen/rohm_bu21023.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/input/touchscreen/rohm_bu21023.c b/drivers/input/touchscreen/rohm_bu21023.c
index bda0500c9b57..714affdd742f 100644
--- a/drivers/input/touchscreen/rohm_bu21023.c
+++ b/drivers/input/touchscreen/rohm_bu21023.c
@@ -304,7 +304,7 @@ static int rohm_i2c_burst_read(struct i2c_client *client, u8 start, void *buf,
msg[1].len = len;
msg[1].buf = buf;
- i2c_lock_adapter(adap);
+ i2c_lock_bus(adap, I2C_LOCK_SEGMENT);
for (i = 0; i < 2; i++) {
if (__i2c_transfer(adap, &msg[i], 1) < 0) {
@@ -313,7 +313,7 @@ static int rohm_i2c_burst_read(struct i2c_client *client, u8 start, void *buf,
}
}
- i2c_unlock_adapter(adap);
+ i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);
return ret;
}
--
2.11.0
^ permalink raw reply related
* [PATCH v2 02/10] i2c: mux: pca9541: switch to i2c_lock_bus(..., I2C_LOCK_SEGMENT)
From: Peter Rosin @ 2018-06-20 5:17 UTC (permalink / raw)
To: linux-kernel
Cc: Peter Rosin, Peter Huewe, Jarkko Sakkinen, Jason Gunthorpe,
Arnd Bergmann, Greg Kroah-Hartman, Brian Norris, Gregory Fong,
Florian Fainelli, bcm-kernel-feedback-list, Sekhar Nori,
Kevin Hilman, Haavard Skinnemoen, Kukjin Kim, Krzysztof Kozlowski,
Orson Zhai, Baolin Wang, Chunyan Zhang, Wolfram Sang,
Guenter Roeck
In-Reply-To: <20180620051803.12206-1-peda@axentia.se>
Locking the root adapter for __i2c_transfer will deadlock if the
device sits behind a mux-locked I2C mux. Switch to the finer-grained
i2c_lock_bus with the I2C_LOCK_SEGMENT flag. If the device does not
sit behind a mux-locked mux, the two locking variants are equivalent.
Signed-off-by: Peter Rosin <peda@axentia.se>
---
drivers/i2c/muxes/i2c-mux-pca9541.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c b/drivers/i2c/muxes/i2c-mux-pca9541.c
index 6a39adaf433f..bc7c8cee5a8c 100644
--- a/drivers/i2c/muxes/i2c-mux-pca9541.c
+++ b/drivers/i2c/muxes/i2c-mux-pca9541.c
@@ -345,11 +345,11 @@ static int pca9541_probe(struct i2c_client *client,
/*
* I2C accesses are unprotected here.
- * We have to lock the adapter before releasing the bus.
+ * We have to lock the I2C segment before releasing the bus.
*/
- i2c_lock_adapter(adap);
+ i2c_lock_bus(adap, I2C_LOCK_SEGMENT);
pca9541_release_bus(client);
- i2c_unlock_adapter(adap);
+ i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);
/* Create mux adapter */
--
2.11.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox