Skip to content

Commit

Permalink
Ported spinlock fix in IRQ handlers to hid-g13, hid-g15 and hid-g110
Browse files Browse the repository at this point in the history
See commit 7953045
  • Loading branch information
CMoH committed Jun 24, 2011
1 parent b730748 commit 8c418d1
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 65 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -3,6 +3,7 @@
*.ko
*.mod.c
*.o
*.o.d
.tmp_versions
Module.symvers
modules.order
52 changes: 29 additions & 23 deletions hid-g110.c
Expand Up @@ -395,14 +395,15 @@ static int g110_input_setkeycode(struct input_dev *dev,
int scancode,
int keycode)
{
unsigned long irq_flags;
int old_keycode;
int i;
struct g110_data *data = input_get_g110data(dev);

if (scancode >= dev->keycodemax)
return -EINVAL;

spin_lock(&data->lock);
spin_lock_irqsave(&data->lock, irq_flags);

old_keycode = data->keycode[scancode];
data->keycode[scancode] = keycode;
Expand All @@ -417,7 +418,7 @@ static int g110_input_setkeycode(struct input_dev *dev,
}
}

spin_unlock(&data->lock);
spin_unlock_irqrestore(&data->lock, irq_flags);

return 0;
}
Expand Down Expand Up @@ -719,6 +720,7 @@ static ssize_t g110_name_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
unsigned long irq_flags;
struct g110_data *data = dev_get_drvdata(dev);
int result;

Expand All @@ -727,9 +729,9 @@ static ssize_t g110_name_show(struct device *dev,
return 1;
}

spin_lock(&data->lock);
spin_lock_irqsave(&data->lock, irq_flags);
result = sprintf(buf, "%s", data->name);
spin_unlock(&data->lock);
spin_unlock_irqrestore(&data->lock, irq_flags);

return result;
}
Expand All @@ -738,11 +740,12 @@ static ssize_t g110_name_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
unsigned long irq_flags;
struct g110_data *data = dev_get_drvdata(dev);
size_t limit = count;
char *end;

spin_lock(&data->lock);
spin_lock_irqsave(&data->lock, irq_flags);

if (data->name != NULL) {
kfree(data->name);
Expand All @@ -763,7 +766,7 @@ static ssize_t g110_name_store(struct device *dev,
strncpy(data->name, buf, limit);
}

spin_unlock(&data->lock);
spin_unlock_irqrestore(&data->lock, irq_flags);

return count;
}
Expand Down Expand Up @@ -910,20 +913,21 @@ static int g110_raw_event(struct hid_device *hdev,
struct hid_report *report,
u8 *raw_data, int size)
{
unsigned long irq_flags;
/*
* On initialization receive a 258 byte message with
* data = 6 0 255 255 255 255 255 255 255 255 ...
*/
* On initialization receive a 258 byte message with
* data = 6 0 255 255 255 255 255 255 255 255 ...
*/
struct g110_data *data;
data = dev_get_drvdata(&hdev->dev);

spin_lock(&data->lock);
spin_lock_irqsave(&data->lock, irq_flags);

if (unlikely(data->need_reset)) {
g110_rgb_send(hdev);
g110_led_send(hdev);
data->need_reset = 0;
spin_unlock(&data->lock);
spin_unlock_irqrestore(&data->lock, irq_flags);
return 1;
}

Expand Down Expand Up @@ -953,11 +957,11 @@ static int g110_raw_event(struct hid_device *hdev,
data->ready_stages == G110_READY_STAGE_3)
complete_all(&data->ready);

spin_unlock(&data->lock);
spin_unlock_irqrestore(&data->lock, irq_flags);
return 1;
}

spin_unlock(&data->lock);
spin_unlock_irqrestore(&data->lock, irq_flags);

if (likely(report->id == 2)) {
g110_raw_event_process_input(hdev, data, raw_data);
Expand Down Expand Up @@ -1030,6 +1034,7 @@ static int g110_ep1_read(struct hid_device *hdev)
static int g110_probe(struct hid_device *hdev,
const struct hid_device_id *id)
{
unsigned long irq_flags;
int error;
struct g110_data *data;
int i;
Expand Down Expand Up @@ -1231,15 +1236,15 @@ static int g110_probe(struct hid_device *hdev,
wait_for_completion_timeout(&data->ready, HZ);

/* Protect data->ready_stages before checking whether we're ready to proceed */
spin_lock(&data->lock);
spin_lock_irqsave(&data->lock, irq_flags);
if (data->ready_stages != G110_READY_STAGE_1) {
dev_warn(&hdev->dev, G110_NAME " hasn't completed stage 1 yet, forging ahead with initialization\n");
/* Force the stage */
data->ready_stages = G110_READY_STAGE_1;
}
init_completion(&data->ready);
data->ready_stages |= G110_READY_SUBSTAGE_4;
spin_unlock(&data->lock);
spin_unlock_irqrestore(&data->lock, irq_flags);

/*
* Send the init report, then follow with the input report to trigger
Expand All @@ -1250,15 +1255,15 @@ static int g110_probe(struct hid_device *hdev,
wait_for_completion_timeout(&data->ready, HZ);

/* Protect data->ready_stages before checking whether we're ready to proceed */
spin_lock(&data->lock);
spin_lock_irqsave(&data->lock, irq_flags);
if (data->ready_stages != G110_READY_STAGE_2) {
dev_warn(&hdev->dev, G110_NAME " hasn't completed stage 2 yet, forging ahead with initialization\n");
/* Force the stage */
data->ready_stages = G110_READY_STAGE_2;
}
init_completion(&data->ready);
data->ready_stages |= G110_READY_SUBSTAGE_6;
spin_unlock(&data->lock);
spin_unlock_irqrestore(&data->lock, irq_flags);

/*
* Clear the LEDs
Expand All @@ -1279,7 +1284,7 @@ static int g110_probe(struct hid_device *hdev,
wait_for_completion_timeout(&data->ready, HZ);

/* Protect data->ready_stages before checking whether we're ready to proceed */
spin_lock(&data->lock);
spin_lock_irqsave(&data->lock, irq_flags);

if (data->ready_stages != G110_READY_STAGE_3) {
dev_warn(&hdev->dev, G110_NAME " hasn't completed stage 3 yet, forging ahead with initialization\n");
Expand All @@ -1289,7 +1294,7 @@ static int g110_probe(struct hid_device *hdev,
dbg_hid(G110_NAME " stage 3 complete\n");
}

spin_unlock(&data->lock);
spin_unlock_irqrestore(&data->lock, irq_flags);

g110_set_keymap_switching(hdev, 1);

Expand Down Expand Up @@ -1368,12 +1373,13 @@ static void g110_remove(struct hid_device *hdev)
}

static void g110_post_reset_start(struct hid_device *hdev)
{
struct g110_data *data = hid_get_g110data(hdev);
{
unsigned long irq_flags;
struct g110_data *data = hid_get_g110data(hdev);

spin_lock(&data->lock);
spin_lock_irqsave(&data->lock, irq_flags);
data->need_reset = 1;
spin_unlock(&data->lock);
spin_unlock_irqrestore(&data->lock, irq_flags);
}

static const struct hid_device_id g110_devices[] = {
Expand Down
49 changes: 28 additions & 21 deletions hid-g13.c
Expand Up @@ -321,14 +321,15 @@ static int g13_input_setkeycode(struct input_dev *dev,
int scancode,
int keycode)
{
unsigned long irq_flags;
int old_keycode;
int i;
struct g13_data *data = input_get_g13data(dev);

if (scancode >= dev->keycodemax)
return -EINVAL;

spin_lock(&data->lock);
spin_lock_irqsave(&data->lock, irq_flags);

old_keycode = data->keycode[scancode];
data->keycode[scancode] = keycode;
Expand All @@ -343,7 +344,7 @@ static int g13_input_setkeycode(struct input_dev *dev,
}
}

spin_unlock(&data->lock);
spin_unlock_irqrestore(&data->lock, irq_flags);

return 0;
}
Expand Down Expand Up @@ -645,6 +646,7 @@ static ssize_t g13_name_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
unsigned long irq_flags;
struct g13_data *data = dev_get_drvdata(dev);
int result;

Expand All @@ -653,9 +655,9 @@ static ssize_t g13_name_show(struct device *dev,
return 1;
}

spin_lock(&data->lock);
spin_lock_irqsave(&data->lock, irq_flags);
result = sprintf(buf, "%s", data->name);
spin_unlock(&data->lock);
spin_unlock_irqrestore(&data->lock, irq_flags);

return result;
}
Expand All @@ -664,11 +666,12 @@ static ssize_t g13_name_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
unsigned long irq_flags;
struct g13_data *data = dev_get_drvdata(dev);
size_t limit = count;
char *end;

spin_lock(&data->lock);
spin_lock_irqsave(&data->lock, irq_flags);

if (data->name != NULL) {
kfree(data->name);
Expand All @@ -689,7 +692,7 @@ static ssize_t g13_name_store(struct device *dev,
strncpy(data->name, buf, limit);
}

spin_unlock(&data->lock);
spin_unlock_irqrestore(&data->lock, irq_flags);

return count;
}
Expand Down Expand Up @@ -920,20 +923,22 @@ static int g13_raw_event(struct hid_device *hdev,
struct hid_report *report,
u8 *raw_data, int size)
{
unsigned long irq_flags;

/*
* On initialization receive a 258 byte message with
* data = 6 0 255 255 255 255 255 255 255 255 ...
*/
* On initialization receive a 258 byte message with
* data = 6 0 255 255 255 255 255 255 255 255 ...
*/
struct g13_data *data;
data = dev_get_drvdata(&hdev->dev);

spin_lock(&data->lock);
spin_lock_irqsave(&data->lock, irq_flags);

if (unlikely(data->need_reset)) {
g13_rgb_send(hdev);
g13_led_send(hdev);
data->need_reset = 0;
spin_unlock(&data->lock);
spin_unlock_irqrestore(&data->lock, irq_flags);
return 1;
}

Expand Down Expand Up @@ -963,11 +968,11 @@ static int g13_raw_event(struct hid_device *hdev,
data->ready_stages == G13_READY_STAGE_3)
complete_all(&data->ready);

spin_unlock(&data->lock);
spin_unlock_irqrestore(&data->lock, irq_flags);
return 1;
}

spin_unlock(&data->lock);
spin_unlock_irqrestore(&data->lock, irq_flags);

if (likely(report->id == 1)) {
g13_raw_event_process_input(hdev, data, raw_data);
Expand All @@ -992,6 +997,7 @@ static void g13_initialize_keymap(struct g13_data *data)
static int g13_probe(struct hid_device *hdev,
const struct hid_device_id *id)
{
unsigned long irq_flags;
int error;
struct g13_data *data;
int i;
Expand Down Expand Up @@ -1220,15 +1226,15 @@ static int g13_probe(struct hid_device *hdev,
wait_for_completion_timeout(&data->ready, HZ);

/* Protect data->ready_stages before checking whether we're ready to proceed */
spin_lock(&data->lock);
spin_lock_irqsave(&data->lock, irq_flags);
if (data->ready_stages != G13_READY_STAGE_1) {
dev_warn(&hdev->dev, G13_NAME " hasn't completed stage 1 yet, forging ahead with initialization\n");
/* Force the stage */
data->ready_stages = G13_READY_STAGE_1;
}
init_completion(&data->ready);
data->ready_stages |= G13_READY_SUBSTAGE_4;
spin_unlock(&data->lock);
spin_unlock_irqrestore(&data->lock, irq_flags);

/*
* Send the init report, then follow with the input report to trigger
Expand All @@ -1239,15 +1245,15 @@ static int g13_probe(struct hid_device *hdev,
wait_for_completion_timeout(&data->ready, HZ);

/* Protect data->ready_stages before checking whether we're ready to proceed */
spin_lock(&data->lock);
spin_lock_irqsave(&data->lock, irq_flags);
if (data->ready_stages != G13_READY_STAGE_2) {
dev_warn(&hdev->dev, G13_NAME " hasn't completed stage 2 yet, forging ahead with initialization\n");
/* Force the stage */
data->ready_stages = G13_READY_STAGE_2;
}
init_completion(&data->ready);
data->ready_stages |= G13_READY_SUBSTAGE_6;
spin_unlock(&data->lock);
spin_unlock_irqrestore(&data->lock, irq_flags);

/*
* Clear the LEDs
Expand All @@ -1266,7 +1272,7 @@ static int g13_probe(struct hid_device *hdev,
wait_for_completion_timeout(&data->ready, HZ);

/* Protect data->ready_stages before checking whether we're ready to proceed */
spin_lock(&data->lock);
spin_lock_irqsave(&data->lock, irq_flags);

if (data->ready_stages != G13_READY_STAGE_3) {
dev_warn(&hdev->dev, G13_NAME " hasn't completed stage 3 yet, forging ahead with initialization\n");
Expand All @@ -1276,7 +1282,7 @@ static int g13_probe(struct hid_device *hdev,
dbg_hid(G13_NAME " stage 3 complete\n");
}

spin_unlock(&data->lock);
spin_unlock_irqrestore(&data->lock, irq_flags);

g13_set_keymap_switching(hdev, 1);

Expand Down Expand Up @@ -1348,11 +1354,12 @@ static void g13_remove(struct hid_device *hdev)

static void g13_post_reset_start(struct hid_device *hdev)
{
unsigned long irq_flags;
struct g13_data *data = hid_get_g13data(hdev);

spin_lock(&data->lock);
spin_lock_irqsave(&data->lock, irq_flags);
data->need_reset = 1;
spin_unlock(&data->lock);
spin_unlock_irqrestore(&data->lock, irq_flags);
}

static const struct hid_device_id g13_devices[] = {
Expand Down

0 comments on commit 8c418d1

Please sign in to comment.