staging: comedi: 8255_pci: fix possible NULL deref during detach
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / line6 / dumprequest.c
CommitLineData
705ececd 1/*
e1a164d7 2 * Line6 Linux USB driver - 0.9.1beta
705ececd 3 *
1027f476 4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
705ececd
MG
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation, version 2.
9 *
10 */
11
5a0e3ad6
TH
12#include <linux/slab.h>
13
1027f476 14#include "driver.h"
705ececd
MG
15#include "dumprequest.h"
16
705ececd
MG
17/*
18 Set "dump in progress" flag.
19*/
20void line6_dump_started(struct line6_dump_request *l6dr, int dest)
21{
22 l6dr->in_progress = dest;
23}
24
25/*
26 Invalidate current channel, i.e., set "dump in progress" flag.
27 Reading from the "dump" special file blocks until dump is completed.
28*/
29void line6_invalidate_current(struct line6_dump_request *l6dr)
30{
31 line6_dump_started(l6dr, LINE6_DUMP_CURRENT);
32}
33
34/*
35 Clear "dump in progress" flag and notify waiting processes.
36*/
37void line6_dump_finished(struct line6_dump_request *l6dr)
38{
39 l6dr->in_progress = LINE6_DUMP_NONE;
1027f476 40 wake_up(&l6dr->wait);
705ececd
MG
41}
42
43/*
44 Send an asynchronous channel dump request.
45*/
766f9d20 46int line6_dump_request_async(struct line6_dump_request *l6dr,
1027f476 47 struct usb_line6 *line6, int num, int dest)
705ececd
MG
48{
49 int ret;
1027f476 50 line6_dump_started(l6dr, dest);
766f9d20
GKH
51 ret = line6_send_raw_message_async(line6, l6dr->reqbufs[num].buffer,
52 l6dr->reqbufs[num].length);
705ececd 53
766f9d20 54 if (ret < 0)
705ececd
MG
55 line6_dump_finished(l6dr);
56
57 return ret;
58}
59
60/*
1027f476 61 Wait for completion (interruptible).
705ececd 62*/
1027f476 63int line6_dump_wait_interruptible(struct line6_dump_request *l6dr)
705ececd 64{
e1a164d7
MG
65 return wait_event_interruptible(l6dr->wait,
66 l6dr->in_progress == LINE6_DUMP_NONE);
705ececd
MG
67}
68
69/*
70 Wait for completion.
71*/
1027f476
MG
72void line6_dump_wait(struct line6_dump_request *l6dr)
73{
74 wait_event(l6dr->wait, l6dr->in_progress == LINE6_DUMP_NONE);
75}
76
77/*
78 Wait for completion (with timeout).
79*/
80int line6_dump_wait_timeout(struct line6_dump_request *l6dr, long timeout)
705ececd 81{
e1a164d7
MG
82 return wait_event_timeout(l6dr->wait,
83 l6dr->in_progress == LINE6_DUMP_NONE,
84 timeout);
705ececd
MG
85}
86
87/*
88 Initialize dump request buffer.
89*/
766f9d20
GKH
90int line6_dumpreq_initbuf(struct line6_dump_request *l6dr, const void *buf,
91 size_t len, int num)
705ececd 92{
94002c07 93 l6dr->reqbufs[num].buffer = kmemdup(buf, len, GFP_KERNEL);
766f9d20
GKH
94 if (l6dr->reqbufs[num].buffer == NULL)
95 return -ENOMEM;
705ececd
MG
96 l6dr->reqbufs[num].length = len;
97 return 0;
98}
99
100/*
101 Initialize dump request data structure (including one buffer).
102*/
766f9d20
GKH
103int line6_dumpreq_init(struct line6_dump_request *l6dr, const void *buf,
104 size_t len)
705ececd
MG
105{
106 int ret;
107 ret = line6_dumpreq_initbuf(l6dr, buf, len, 0);
766f9d20
GKH
108 if (ret < 0)
109 return ret;
705ececd 110 init_waitqueue_head(&l6dr->wait);
705ececd
MG
111 return 0;
112}
113
114/*
115 Destruct dump request data structure.
116*/
117void line6_dumpreq_destructbuf(struct line6_dump_request *l6dr, int num)
118{
766f9d20
GKH
119 if (l6dr == NULL)
120 return;
121 if (l6dr->reqbufs[num].buffer == NULL)
122 return;
705ececd
MG
123 kfree(l6dr->reqbufs[num].buffer);
124 l6dr->reqbufs[num].buffer = NULL;
125}
126
127/*
128 Destruct dump request data structure.
129*/
130void line6_dumpreq_destruct(struct line6_dump_request *l6dr)
131{
766f9d20
GKH
132 if (l6dr->reqbufs[0].buffer == NULL)
133 return;
705ececd 134 line6_dumpreq_destructbuf(l6dr, 0);
705ececd 135}