Skip to content
This repository was archived by the owner on Dec 20, 2023. It is now read-only.

Commit ca110b0

Browse files
Alex ElderKevinAlavik
Alex Elder
authored andcommitted
greybus: introduce protocol abstraction
Define a protocol structure that will allow protocols to be registered dynamically. For now we just introduce a bookkeeping data structure. Upcoming patches will move protocol-related methods into the protocol structure, and will start registering protocol handlers dynamically. A list of connections using a given protocol is maintained so we can tell when a protocol is no longer in use. This may not be necessary (we could use a kref instead) but it may turn out to be a good way to clean things up. The interface is gb_protocol_get() and gb_protocol_put() for a connection, allowing the protocol to be looked up and the connection structure to be inserted into its list. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
1 parent 6e1f178 commit ca110b0

File tree

7 files changed

+167
-6
lines changed

7 files changed

+167
-6
lines changed

Diff for: drivers/staging/greybus/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ greybus-y := core.o \
77
module.o \
88
interface.o \
99
connection.o \
10+
protocol.o \
1011
operation.o \
1112
i2c-gb.o \
1213
gpio-gb.o \

Diff for: drivers/staging/greybus/connection.c

+13-4
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ protocol_id_show(struct device *dev, struct device_attribute *attr, char *buf)
116116
{
117117
struct gb_connection *connection = to_gb_connection(dev);
118118

119-
return sprintf(buf, "%d", connection->protocol_id);
119+
return sprintf(buf, "%d", connection->protocol->id);
120120
}
121121
static DEVICE_ATTR_RO(protocol_id);
122122

@@ -162,17 +162,23 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface,
162162
if (!connection)
163163
return NULL;
164164

165+
INIT_LIST_HEAD(&connection->protocol_links);
166+
if (!gb_protocol_get(connection, protocol_id)) {
167+
kfree(connection);
168+
return NULL;
169+
}
170+
165171
hd = interface->gmod->hd;
166172
connection->hd = hd; /* XXX refcount? */
167173
if (!gb_connection_hd_cport_id_alloc(connection)) {
168174
/* kref_put(connection->hd); */
175+
gb_protocol_put(connection);
169176
kfree(connection);
170177
return NULL;
171178
}
172179

173180
connection->interface = interface;
174181
connection->interface_cport_id = cport_id;
175-
connection->protocol_id = protocol_id;
176182
connection->state = GB_CONNECTION_STATE_DISABLED;
177183

178184
connection->dev.parent = &interface->dev;
@@ -188,6 +194,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface,
188194
if (retval) {
189195
gb_connection_hd_cport_id_free(connection);
190196
/* kref_put(connection->hd); */
197+
gb_protocol_put(connection);
191198
kfree(connection);
192199
return NULL;
193200
}
@@ -228,6 +235,8 @@ void gb_connection_destroy(struct gb_connection *connection)
228235
spin_unlock_irq(&gb_connections_lock);
229236

230237
gb_connection_hd_cport_id_free(connection);
238+
/* kref_put(connection->hd); */
239+
gb_protocol_put(connection);
231240

232241
device_del(&connection->dev);
233242
}
@@ -267,7 +276,7 @@ int gb_connection_init(struct gb_connection *connection)
267276

268277
/* Need to enable the connection to initialize it */
269278
connection->state = GB_CONNECTION_STATE_ENABLED;
270-
switch (connection->protocol_id) {
279+
switch (connection->protocol->id) {
271280
case GREYBUS_PROTOCOL_I2C:
272281
connection->handler = &gb_i2c_connection_handler;
273282
break;
@@ -287,7 +296,7 @@ int gb_connection_init(struct gb_connection *connection)
287296
case GREYBUS_PROTOCOL_VENDOR:
288297
default:
289298
gb_connection_err(connection, "unimplemented protocol %hhu",
290-
connection->protocol_id);
299+
connection->protocol->id);
291300
ret = -ENXIO;
292301
break;
293302
}

Diff for: drivers/staging/greybus/connection.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ struct gb_connection {
3939

4040
struct rb_node hd_node;
4141
struct list_head interface_links;
42-
u8 protocol_id;
42+
43+
struct gb_protocol *protocol;
44+
struct list_head protocol_links;
4345

4446
enum gb_connection_state state;
4547

Diff for: drivers/staging/greybus/greybus.h

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "module.h"
2727
#include "interface.h"
2828
#include "connection.h"
29+
#include "protocol.h"
2930
#include "operation.h"
3031

3132

Diff for: drivers/staging/greybus/operation.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ static gb_operation_recv_handler gb_operation_recv_handlers[] = {
200200

201201
static void gb_operation_request_handle(struct gb_operation *operation)
202202
{
203-
u8 protocol_id = operation->connection->protocol_id;
203+
u8 protocol_id = operation->connection->protocol->id;
204204

205205
/* Subtract one from array size to stay within u8 range */
206206
if (protocol_id <= (u8)(ARRAY_SIZE(gb_operation_recv_handlers) - 1)) {

Diff for: drivers/staging/greybus/protocol.c

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Greybus protocol handling
3+
*
4+
* Copyright 2014 Google Inc.
5+
*
6+
* Released under the GPLv2 only.
7+
*/
8+
9+
#include "greybus.h"
10+
11+
/* Global list of registered protocols */
12+
static DEFINE_SPINLOCK(gb_protocols_lock);
13+
static LIST_HEAD(gb_protocols);
14+
15+
/* Caller must hold gb_protocols_lock */
16+
struct gb_protocol *_gb_protocol_find(u8 id)
17+
{
18+
struct gb_protocol *protocol;
19+
20+
list_for_each_entry(protocol, &gb_protocols, links)
21+
if (protocol->id == id)
22+
return protocol;
23+
return NULL;
24+
}
25+
26+
/* This is basically for debug */
27+
static struct gb_protocol *gb_protocol_find(u8 id)
28+
{
29+
struct gb_protocol *protocol;
30+
31+
spin_lock_irq(&gb_protocols_lock);
32+
protocol = _gb_protocol_find(id);
33+
spin_unlock_irq(&gb_protocols_lock);
34+
35+
return protocol;
36+
}
37+
38+
/* Returns true if protocol was succesfully registered, false otherwise */
39+
bool gb_protocol_register(u8 id)
40+
{
41+
struct gb_protocol *protocol;
42+
struct gb_protocol *existing;
43+
44+
/* Initialize it speculatively */
45+
protocol = kzalloc(sizeof(*protocol), GFP_KERNEL);
46+
if (!protocol)
47+
return false;
48+
protocol->id = id;
49+
INIT_LIST_HEAD(&protocol->connections);
50+
51+
spin_lock_irq(&gb_protocols_lock);
52+
existing = _gb_protocol_find(id);
53+
if (!existing)
54+
list_add(&protocol->links, &gb_protocols);
55+
spin_unlock_irq(&gb_protocols_lock);
56+
57+
if (existing) {
58+
kfree(protocol);
59+
protocol = NULL;
60+
}
61+
62+
return protocol != NULL;
63+
}
64+
65+
/* Returns true if successful, false otherwise */
66+
bool gb_protocol_deregister(struct gb_protocol *protocol)
67+
{
68+
spin_lock_irq(&gb_protocols_lock);
69+
if (list_empty(&protocol->connections))
70+
list_del(&protocol->links);
71+
else
72+
protocol = NULL; /* Protocol is still in use */
73+
spin_unlock_irq(&gb_protocols_lock);
74+
kfree(protocol);
75+
76+
return protocol != NULL;
77+
}
78+
79+
/* Returns true if successful, false otherwise */
80+
bool gb_protocol_get(struct gb_connection *connection, u8 id)
81+
{
82+
struct gb_protocol *protocol;
83+
84+
/* Sanity */
85+
if (!list_empty(&connection->protocol_links) ||
86+
!connection->protocol->id) {
87+
gb_connection_err(connection,
88+
"connection already has protocol");
89+
return false;
90+
}
91+
92+
spin_lock_irq(&gb_protocols_lock);
93+
protocol = _gb_protocol_find(id);
94+
if (protocol)
95+
list_add(&connection->protocol_links, &protocol->connections);
96+
spin_unlock_irq(&gb_protocols_lock);
97+
connection->protocol = protocol;
98+
99+
return protocol != NULL;
100+
}
101+
102+
void gb_protocol_put(struct gb_connection *connection)
103+
{
104+
struct gb_protocol *protocol = connection->protocol;
105+
106+
/* Sanity checks */
107+
if (list_empty(&connection->protocol_links)) {
108+
gb_connection_err(connection,
109+
"connection protocol not recorded");
110+
return;
111+
}
112+
if (!protocol || gb_protocol_find(protocol->id) != protocol) {
113+
gb_connection_err(connection,
114+
"connection has undefined protocol");
115+
return;
116+
}
117+
118+
spin_lock_irq(&gb_protocols_lock);
119+
list_del(&connection->protocol_links);
120+
connection->protocol = NULL;
121+
spin_unlock_irq(&gb_protocols_lock);
122+
}

Diff for: drivers/staging/greybus/protocol.h

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Greybus protocol handling
3+
*
4+
* Copyright 2014 Google Inc.
5+
*
6+
* Released under the GPLv2 only.
7+
*/
8+
9+
#ifndef __PROTOCOL_H
10+
#define __PROTOCOL_H
11+
12+
#include "greybus.h"
13+
14+
struct gb_protocol {
15+
u8 id;
16+
struct list_head connections; /* protocol users */
17+
struct list_head links; /* global list */
18+
};
19+
20+
bool gb_protocol_register(u8 id);
21+
bool gb_protocol_deregister(struct gb_protocol *protocol);
22+
23+
bool gb_protocol_get(struct gb_connection *connection, u8 id);
24+
void gb_protocol_put(struct gb_connection *connection);
25+
26+
#endif /* __PROTOCOL_H */

0 commit comments

Comments
 (0)