.connection_init = gb_battery_connection_init,
.connection_exit = gb_battery_connection_exit,
};
+
+static struct gb_protocol battery_protocol = {
+ .id = GREYBUS_PROTOCOL_BATTERY,
+ .major = 0,
+ .minor = 1,
+};
+
+bool gb_battery_protocol_init(void)
+{
+ return gb_protocol_register(&battery_protocol);
+}
+
+void gb_battery_protocol_exit(void)
+{
+ gb_protocol_deregister(&battery_protocol);
+}
goto error_operation;
}
- return 0;
+ if (!gb_protocol_init()) {
+ /* This only fails for duplicate protocol registration */
+ retval = -EEXIST;
+ pr_err("gb_protocol_init failed\n");
+ goto error_protocol;
+ }
+ return 0; /* Success */
+
+error_protocol:
+ gb_operation_exit();
error_operation:
gb_gbuf_exit();
-
error_gbuf:
gb_ap_exit();
-
error_ap:
bus_unregister(&greybus_bus_type);
-
error_bus:
gb_debugfs_cleanup();
.connection_init = gb_gpio_connection_init,
.connection_exit = gb_gpio_connection_exit,
};
+
+static struct gb_protocol gpio_protocol = {
+ .id = GREYBUS_PROTOCOL_GPIO,
+ .major = 0,
+ .minor = 1,
+};
+
+bool gb_gpio_protocol_init(void)
+{
+ return gb_protocol_register(&gpio_protocol);
+}
+
+void gb_gpio_protocol_exit(void)
+{
+ gb_protocol_deregister(&gpio_protocol);
+}
GREYBUS_PROTOCOL_I2C = 0x03,
GREYBUS_PROTOCOL_UART = 0x04,
GREYBUS_PROTOCOL_HID = 0x05,
+ GREYBUS_PROTOCOL_SDIO = 0x06,
GREYBUS_PROTOCOL_BATTERY = 0x08,
GREYBUS_PROTOCOL_LED = 0x0e,
/* ... */
.connection_init = gb_i2c_connection_init,
.connection_exit = gb_i2c_connection_exit,
};
+
+static struct gb_protocol i2c_protocol = {
+ .id = GREYBUS_PROTOCOL_I2C,
+ .major = 0,
+ .minor = 1,
+};
+
+bool gb_i2c_protocol_init(void)
+{
+ return gb_protocol_register(&i2c_protocol);
+}
+
+void gb_i2c_protocol_exit(void)
+{
+ gb_protocol_deregister(&i2c_protocol);
+}
}
/* Returns true if protocol was succesfully registered, false otherwise */
-bool gb_protocol_register(u8 id, u8 major, u8 minor)
+bool gb_protocol_register(struct gb_protocol *protocol)
{
- struct gb_protocol *protocol;
struct gb_protocol *existing;
-
- /* Initialize it speculatively */
- protocol = kzalloc(sizeof(*protocol), GFP_KERNEL);
- if (!protocol)
- return false;
- protocol->id = id;
- protocol->major = major;
- protocol->minor = minor;
+ u8 id = protocol->id;
+ u8 major = protocol->major;
+ u8 minor = protocol->minor;
/*
* The protocols list is sorted first by protocol id (low to
/* A matching protocol has already been registered */
spin_unlock_irq(&gb_protocols_lock);
- kfree(protocol);
return false;
}
return true;
}
-/* Returns true if successful, false otherwise */
+/*
+ * De-register a previously registered protocol.
+ *
+ * XXX Currently this fails (and reports an error to the caller) if
+ * XXX the protocol is currently in use. We may want to forcefully
+ * XXX kill off a protocol and all its active users at some point.
+ * XXX But I think that's better handled by quescing modules that
+ * XXX have users and having those users drop their reference.
+ *
+ * Returns true if successful, false otherwise.
+ */
bool gb_protocol_deregister(struct gb_protocol *protocol)
{
u8 protocol_count = 0;
list_del(&protocol->links);
}
spin_unlock_irq(&gb_protocols_lock);
- kfree(protocol);
return protocol && !protocol_count;
}
pr_err("protocol id %hhu version %hhu.%hhu not found\n",
protocol->id, major, minor);
}
+
+bool gb_protocol_init(void)
+{
+ bool ret = true;
+
+ if (!gb_battery_protocol_init()) {
+ pr_err("error initializing battery protocol\n");
+ ret = false;
+ }
+ if (!gb_gpio_protocol_init()) {
+ pr_err("error initializing gpio protocol\n");
+ ret = false;
+ }
+ if (!gb_i2c_protocol_init()) {
+ pr_err("error initializing i2c protocol\n");
+ ret = false;
+ }
+ if (!gb_uart_protocol_init()) {
+ pr_err("error initializing uart protocol\n");
+ ret = false;
+ }
+ if (!gb_sdio_protocol_init()) {
+ pr_err("error initializing sdio protocol\n");
+ ret = false;
+ }
+ return ret;
+}
+
+void gb_protocol_exit(void)
+{
+ gb_sdio_protocol_exit();
+ gb_uart_protocol_exit();
+ gb_i2c_protocol_exit();
+ gb_gpio_protocol_exit();
+ gb_battery_protocol_exit();
+}
struct list_head links; /* global list */
};
-bool gb_protocol_register(u8 id, u8 major, u8 minor);
+bool gb_protocol_register(struct gb_protocol *protocol);
bool gb_protocol_deregister(struct gb_protocol *protocol);
struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor);
void gb_protocol_put(struct gb_protocol *protocol);
+/*
+ * These are defined in their respective protocol source files.
+ * Declared here for now. They could be added via modules, or maybe
+ * just use initcalls (which level?).
+ */
+extern bool gb_battery_protocol_init(void);
+extern void gb_battery_protocol_exit(void);
+
+extern bool gb_gpio_protocol_init(void);
+extern void gb_gpio_protocol_exit(void);
+
+extern bool gb_i2c_protocol_init(void);
+extern void gb_i2c_protocol_exit(void);
+
+extern bool gb_uart_protocol_init(void);
+extern void gb_uart_protocol_exit(void);
+
+extern bool gb_sdio_protocol_init(void);
+extern void gb_sdio_protocol_exit(void);
+
+bool gb_protocol_init(void);
+void gb_protocol_exit(void);
+
#endif /* __PROTOCOL_H */
.connection_init = gb_sdio_connection_init,
.connection_exit = gb_sdio_connection_exit,
};
+
+static struct gb_protocol sdio_protocol = {
+ .id = GREYBUS_PROTOCOL_SDIO,
+ .major = 0,
+ .minor = 1,
+};
+
+bool gb_sdio_protocol_init(void)
+{
+ return gb_protocol_register(&sdio_protocol);
+}
+
+void gb_sdio_protocol_exit(void)
+{
+ gb_protocol_deregister(&sdio_protocol);
+}
.connection_init = gb_uart_connection_init,
.connection_exit = gb_uart_connection_exit,
};
+
+static struct gb_protocol uart_protocol = {
+ .id = GREYBUS_PROTOCOL_UART,
+ .major = 0,
+ .minor = 1,
+};
+
+bool gb_uart_protocol_init(void)
+{
+ return gb_protocol_register(&uart_protocol);
+}
+
+void gb_uart_protocol_exit(void)
+{
+ gb_protocol_deregister(&uart_protocol);
+}