greybus: Merge branch 'master' into branch 'svc'.
This drags in the firmware driver, and the start of some loopback changes. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
commit
d706ef8f1b
@ -9,6 +9,7 @@ greybus-y := core.o \
|
||||
protocol.o \
|
||||
control.o \
|
||||
svc.o \
|
||||
firmware.o \
|
||||
operation.o
|
||||
|
||||
gb-phy-y := gpbridge.o \
|
||||
|
@ -11,6 +11,10 @@
|
||||
|
||||
#include "greybus.h"
|
||||
|
||||
#define GB_CONNECTION_TS_KFIFO_ELEMENTS 2
|
||||
#define GB_CONNECTION_TS_KFIFO_LEN \
|
||||
(GB_CONNECTION_TS_KFIFO_ELEMENTS * sizeof(struct timeval))
|
||||
|
||||
static DEFINE_SPINLOCK(gb_connections_lock);
|
||||
|
||||
/* This is only used at initialization time; no locking is required. */
|
||||
@ -63,6 +67,29 @@ void greybus_data_rcvd(struct greybus_host_device *hd, u16 cport_id,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(greybus_data_rcvd);
|
||||
|
||||
void gb_connection_push_timestamp(struct gb_connection *connection)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
do_gettimeofday(&tv);
|
||||
kfifo_in_locked(&connection->ts_kfifo, (void *)&tv,
|
||||
sizeof(struct timeval), &connection->lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gb_connection_push_timestamp);
|
||||
|
||||
int gb_connection_pop_timestamp(struct gb_connection *connection,
|
||||
struct timeval *tv)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (!kfifo_len(&connection->ts_kfifo))
|
||||
return -ENOMEM;
|
||||
retval = kfifo_out_locked(&connection->ts_kfifo, (void *)tv,
|
||||
sizeof(*tv), &connection->lock);
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gb_connection_pop_timestamp);
|
||||
|
||||
static ssize_t state_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
@ -102,6 +129,7 @@ static void gb_connection_release(struct device *dev)
|
||||
struct gb_connection *connection = to_gb_connection(dev);
|
||||
|
||||
destroy_workqueue(connection->wq);
|
||||
kfifo_free(&connection->ts_kfifo);
|
||||
kfree(connection);
|
||||
}
|
||||
|
||||
@ -222,6 +250,10 @@ gb_connection_create_range(struct greybus_host_device *hd,
|
||||
if (!connection->wq)
|
||||
goto err_free_connection;
|
||||
|
||||
if (kfifo_alloc(&connection->ts_kfifo, GB_CONNECTION_TS_KFIFO_LEN,
|
||||
GFP_KERNEL))
|
||||
goto err_free_connection;
|
||||
|
||||
connection->dev.parent = parent;
|
||||
connection->dev.bus = &greybus_bus_type;
|
||||
connection->dev.type = &greybus_connection_type;
|
||||
@ -238,7 +270,7 @@ gb_connection_create_range(struct greybus_host_device *hd,
|
||||
pr_err("failed to add connection device for cport 0x%04hx\n",
|
||||
cport_id);
|
||||
|
||||
goto err_remove_ida;
|
||||
goto err_free_kfifo;
|
||||
}
|
||||
|
||||
spin_lock_irq(&gb_connections_lock);
|
||||
@ -264,6 +296,8 @@ gb_connection_create_range(struct greybus_host_device *hd,
|
||||
|
||||
return connection;
|
||||
|
||||
err_free_kfifo:
|
||||
kfifo_free(&connection->ts_kfifo);
|
||||
err_free_connection:
|
||||
kfree(connection);
|
||||
err_remove_ida:
|
||||
@ -394,7 +428,19 @@ int gb_connection_init(struct gb_connection *connection)
|
||||
* this for SVC as that is initiated by the SVC.
|
||||
*/
|
||||
if (connection->hd_cport_id != GB_SVC_CPORT_ID) {
|
||||
ret = gb_protocol_get_version(connection, NULL, 0);
|
||||
bool send_request = false;
|
||||
|
||||
/*
|
||||
* We need to send the protocol version of the firmware protocol
|
||||
* supported by AP and so this special case.
|
||||
*/
|
||||
if (connection->protocol->id == GREYBUS_PROTOCOL_FIRMWARE)
|
||||
send_request = true;
|
||||
|
||||
// FIXME: Should we always send the protocol version AP can
|
||||
// support ?
|
||||
|
||||
ret = gb_protocol_get_version(connection, send_request);
|
||||
if (ret) {
|
||||
dev_err(&connection->dev,
|
||||
"Failed to get version CPort-%d (%d)\n",
|
||||
|
@ -11,6 +11,7 @@
|
||||
#define __CONNECTION_H
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/kfifo.h>
|
||||
|
||||
enum gb_connection_state {
|
||||
GB_CONNECTION_STATE_INVALID = 0,
|
||||
@ -42,6 +43,7 @@ struct gb_connection {
|
||||
struct list_head operations;
|
||||
|
||||
struct workqueue_struct *wq;
|
||||
struct kfifo ts_kfifo;
|
||||
|
||||
atomic_t op_cycle;
|
||||
|
||||
@ -65,6 +67,9 @@ void gb_hd_connections_exit(struct greybus_host_device *hd);
|
||||
|
||||
void greybus_data_rcvd(struct greybus_host_device *hd, u16 cport_id,
|
||||
u8 *data, size_t length);
|
||||
void gb_connection_push_timestamp(struct gb_connection *connection);
|
||||
int gb_connection_pop_timestamp(struct gb_connection *connection,
|
||||
struct timeval *tv);
|
||||
|
||||
void gb_connection_bind_protocol(struct gb_connection *connection);
|
||||
|
||||
|
@ -308,8 +308,16 @@ static int __init gb_init(void)
|
||||
goto error_svc;
|
||||
}
|
||||
|
||||
retval = gb_firmware_protocol_init();
|
||||
if (retval) {
|
||||
pr_err("gb_firmware_protocol_init failed\n");
|
||||
goto error_firmware;
|
||||
}
|
||||
|
||||
return 0; /* Success */
|
||||
|
||||
error_firmware:
|
||||
gb_svc_protocol_exit();
|
||||
error_svc:
|
||||
gb_control_protocol_exit();
|
||||
error_control:
|
||||
@ -327,6 +335,7 @@ module_init(gb_init);
|
||||
|
||||
static void __exit gb_exit(void)
|
||||
{
|
||||
gb_firmware_protocol_exit();
|
||||
gb_svc_protocol_exit();
|
||||
gb_control_protocol_exit();
|
||||
gb_endo_exit();
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "greybus.h"
|
||||
#include "kernel_ver.h"
|
||||
#include "connection.h"
|
||||
|
||||
/* Memory sizes for the buffers sent to/from the ES1 controller */
|
||||
#define ES1_GBUF_MSG_SIZE_MAX 2048
|
||||
@ -215,6 +216,7 @@ static int message_send(struct greybus_host_device *hd, u16 cport_id,
|
||||
usb_sndbulkpipe(udev, es1->cport_out_endpoint),
|
||||
message->buffer, buffer_size,
|
||||
cport_out_callback, message);
|
||||
gb_connection_push_timestamp(message->operation->connection);
|
||||
retval = usb_submit_urb(urb, gfp_mask);
|
||||
if (retval) {
|
||||
pr_err("error %d submitting URB\n", retval);
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "greybus.h"
|
||||
#include "kernel_ver.h"
|
||||
#include "connection.h"
|
||||
|
||||
/* Memory sizes for the buffers sent to/from the ES1 controller */
|
||||
#define ES1_GBUF_MSG_SIZE_MAX 2048
|
||||
@ -311,6 +312,7 @@ static int message_send(struct greybus_host_device *hd, u16 cport_id,
|
||||
es1->cport_out[bulk_ep_set].endpoint),
|
||||
message->buffer, buffer_size,
|
||||
cport_out_callback, message);
|
||||
gb_connection_push_timestamp(message->operation->connection);
|
||||
retval = usb_submit_urb(urb, gfp_mask);
|
||||
if (retval) {
|
||||
pr_err("error %d submitting URB\n", retval);
|
||||
|
199
drivers/staging/greybus/firmware.c
Normal file
199
drivers/staging/greybus/firmware.c
Normal file
@ -0,0 +1,199 @@
|
||||
/*
|
||||
* FIRMWARE Greybus driver.
|
||||
*
|
||||
* Copyright 2015 Google Inc.
|
||||
* Copyright 2015 Linaro Ltd.
|
||||
*
|
||||
* Released under the GPLv2 only.
|
||||
*/
|
||||
|
||||
#include <linux/firmware.h>
|
||||
|
||||
#include "greybus.h"
|
||||
|
||||
struct gb_firmware {
|
||||
struct gb_connection *connection;
|
||||
const struct firmware *fw;
|
||||
};
|
||||
|
||||
static void free_firmware(struct gb_firmware *firmware)
|
||||
{
|
||||
release_firmware(firmware->fw);
|
||||
firmware->fw = NULL;
|
||||
}
|
||||
|
||||
/* This returns path of the firmware blob on the disk */
|
||||
static int download_firmware(struct gb_firmware *firmware, u8 stage)
|
||||
{
|
||||
struct gb_connection *connection = firmware->connection;
|
||||
struct gb_interface *intf = connection->bundle->intf;
|
||||
char firmware_name[28];
|
||||
|
||||
/* Already have a firmware, free it */
|
||||
if (firmware->fw)
|
||||
free_firmware(firmware);
|
||||
|
||||
/*
|
||||
* Create firmware name
|
||||
*
|
||||
* XXX Name it properly..
|
||||
*/
|
||||
sprintf(firmware_name, "ara:%04x:%04x:%04x:%04x:%04x.fw", intf->unipro_mfg_id,
|
||||
intf->unipro_prod_id, intf->ara_vend_id, intf->ara_prod_id,
|
||||
stage);
|
||||
|
||||
return request_firmware(&firmware->fw, firmware_name, &connection->dev);
|
||||
}
|
||||
|
||||
static int gb_firmware_size_request(struct gb_operation *op)
|
||||
{
|
||||
struct gb_connection *connection = op->connection;
|
||||
struct gb_firmware *firmware = connection->private;
|
||||
struct gb_firmware_size_request *size_request = op->request->payload;
|
||||
struct gb_firmware_size_response *size_response;
|
||||
struct device *dev = &connection->dev;
|
||||
int ret;
|
||||
|
||||
if (op->request->payload_size != sizeof(*size_request)) {
|
||||
dev_err(dev, "%s: illegal size of firmware size request (%zu != %zu)\n",
|
||||
__func__, op->request->payload_size,
|
||||
sizeof(*size_request));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = download_firmware(firmware, size_request->stage);
|
||||
if (ret) {
|
||||
dev_err(dev, "%s: failed to download firmware (%d)\n", __func__,
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!gb_operation_response_alloc(op, sizeof(*size_response),
|
||||
GFP_KERNEL)) {
|
||||
dev_err(dev, "%s: error allocating response\n", __func__);
|
||||
free_firmware(firmware);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
size_response = op->response->payload;
|
||||
size_response->size = cpu_to_le32(firmware->fw->size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gb_firmware_get_firmware(struct gb_operation *op)
|
||||
{
|
||||
struct gb_connection *connection = op->connection;
|
||||
struct gb_firmware *firmware = connection->private;
|
||||
struct gb_firmware_get_firmware_request *firmware_request = op->request->payload;
|
||||
struct gb_firmware_get_firmware_response *firmware_response;
|
||||
struct device *dev = &connection->dev;
|
||||
unsigned int offset, size;
|
||||
|
||||
if (op->request->payload_size != sizeof(*firmware_request)) {
|
||||
dev_err(dev, "%s: Illegal size of get firmware request (%zu %zu)\n",
|
||||
__func__, op->request->payload_size,
|
||||
sizeof(*firmware_request));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!firmware->fw) {
|
||||
dev_err(dev, "%s: firmware not available\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
offset = le32_to_cpu(firmware_request->offset);
|
||||
size = le32_to_cpu(firmware_request->size);
|
||||
|
||||
if (!gb_operation_response_alloc(op, sizeof(*firmware_response) + size,
|
||||
GFP_KERNEL)) {
|
||||
dev_err(dev, "%s: error allocating response\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
firmware_response = op->response->payload;
|
||||
memcpy(firmware_response->data, firmware->fw->data + offset, size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gb_firmware_ready_to_boot(struct gb_operation *op)
|
||||
{
|
||||
struct gb_connection *connection = op->connection;
|
||||
struct gb_firmware_ready_to_boot_request *rtb_request = op->request->payload;
|
||||
struct device *dev = &connection->dev;
|
||||
u8 stage, status;
|
||||
|
||||
if (op->request->payload_size != sizeof(*rtb_request)) {
|
||||
dev_err(dev, "%s: Illegal size of ready to boot request (%zu %zu)\n",
|
||||
__func__, op->request->payload_size,
|
||||
sizeof(*rtb_request));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
stage = rtb_request->stage;
|
||||
status = rtb_request->status;
|
||||
|
||||
/* Return error if the blob was invalid */
|
||||
if (status == GB_FIRMWARE_BOOT_STATUS_INVALID)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* XXX Should we return error for insecure firmware?
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gb_firmware_request_recv(u8 type, struct gb_operation *op)
|
||||
{
|
||||
switch (type) {
|
||||
case GB_FIRMWARE_TYPE_FIRMWARE_SIZE:
|
||||
return gb_firmware_size_request(op);
|
||||
case GB_FIRMWARE_TYPE_GET_FIRMWARE:
|
||||
return gb_firmware_get_firmware(op);
|
||||
case GB_FIRMWARE_TYPE_READY_TO_BOOT:
|
||||
return gb_firmware_ready_to_boot(op);
|
||||
default:
|
||||
dev_err(&op->connection->dev,
|
||||
"unsupported request: %hhu\n", type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int gb_firmware_connection_init(struct gb_connection *connection)
|
||||
{
|
||||
struct gb_firmware *firmware;
|
||||
|
||||
firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
|
||||
if (!firmware)
|
||||
return -ENOMEM;
|
||||
|
||||
firmware->connection = connection;
|
||||
connection->private = firmware;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gb_firmware_connection_exit(struct gb_connection *connection)
|
||||
{
|
||||
struct gb_firmware *firmware = connection->private;
|
||||
|
||||
/* Release firmware */
|
||||
if (firmware->fw)
|
||||
free_firmware(firmware);
|
||||
|
||||
connection->private = NULL;
|
||||
kfree(firmware);
|
||||
}
|
||||
|
||||
static struct gb_protocol firmware_protocol = {
|
||||
.name = "firmware",
|
||||
.id = GREYBUS_PROTOCOL_FIRMWARE,
|
||||
.major = GB_FIRMWARE_VERSION_MAJOR,
|
||||
.minor = GB_FIRMWARE_VERSION_MINOR,
|
||||
.connection_init = gb_firmware_connection_init,
|
||||
.connection_exit = gb_firmware_connection_exit,
|
||||
.request_recv = gb_firmware_request_recv,
|
||||
};
|
||||
gb_builtin_protocol_driver(firmware_protocol);
|
16
drivers/staging/greybus/firmware.h
Normal file
16
drivers/staging/greybus/firmware.h
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Greybus firmware code
|
||||
*
|
||||
* Copyright 2015 Google Inc.
|
||||
* Copyright 2015 Linaro Ltd.
|
||||
*
|
||||
* Released under the GPLv2 only.
|
||||
*/
|
||||
|
||||
#ifndef __FIRMWARE_H
|
||||
#define __FIRMWARE_H
|
||||
|
||||
int gb_firmware_protocol_init(void);
|
||||
void gb_firmware_protocol_exit(void);
|
||||
|
||||
#endif /* __FIRMWARE_H */
|
@ -27,6 +27,7 @@
|
||||
#include "manifest.h"
|
||||
#include "endo.h"
|
||||
#include "svc.h"
|
||||
#include "firmware.h"
|
||||
#include "module.h"
|
||||
#include "control.h"
|
||||
#include "interface.h"
|
||||
|
@ -43,6 +43,7 @@ enum greybus_protocol {
|
||||
GREYBUS_PROTOCOL_I2S_RECEIVER = 0x12,
|
||||
GREYBUS_PROTOCOL_I2S_TRANSMITTER = 0x13,
|
||||
GREYBUS_PROTOCOL_SVC = 0x14,
|
||||
GREYBUS_PROTOCOL_FIRMWARE = 0x15,
|
||||
/* ... */
|
||||
GREYBUS_PROTOCOL_RAW = 0xfe,
|
||||
GREYBUS_PROTOCOL_VENDOR = 0xff,
|
||||
@ -70,6 +71,7 @@ enum greybus_class_type {
|
||||
GREYBUS_CLASS_I2S_RECEIVER = 0x12,
|
||||
GREYBUS_CLASS_I2S_TRANSMITTER = 0x13,
|
||||
GREYBUS_CLASS_SVC = 0x14,
|
||||
GREYBUS_CLASS_FIRMWARE = 0x15,
|
||||
/* ... */
|
||||
GREYBUS_CLASS_RAW = 0xfe,
|
||||
GREYBUS_CLASS_VENDOR = 0xff,
|
||||
|
@ -146,6 +146,60 @@ struct gb_control_disconnected_request {
|
||||
};
|
||||
/* Control protocol [dis]connected response has no payload */
|
||||
|
||||
|
||||
/* Firmware Protocol */
|
||||
|
||||
/* Version of the Greybus firmware protocol we support */
|
||||
#define GB_FIRMWARE_VERSION_MAJOR 0x00
|
||||
#define GB_FIRMWARE_VERSION_MINOR 0x01
|
||||
|
||||
/* Greybus firmware request types */
|
||||
#define GB_FIRMWARE_TYPE_INVALID 0x00
|
||||
#define GB_FIRMWARE_TYPE_PROTOCOL_VERSION 0x01
|
||||
#define GB_FIRMWARE_TYPE_FIRMWARE_SIZE 0x02
|
||||
#define GB_FIRMWARE_TYPE_GET_FIRMWARE 0x03
|
||||
#define GB_FIRMWARE_TYPE_READY_TO_BOOT 0x04
|
||||
|
||||
/* Greybus firmware boot stages */
|
||||
#define GB_FIRMWARE_BOOT_STAGE_ONE 0x01 /* Reserved for the boot ROM */
|
||||
#define GB_FIRMWARE_BOOT_STAGE_TWO 0x02 /* Firmware package to be loaded by the boot ROM */
|
||||
#define GB_FIRMWARE_BOOT_STAGE_THREE 0x03 /* Module personality package loaded by Stage 2 firmware */
|
||||
|
||||
/* Greybus firmware ready to boot status */
|
||||
#define GB_FIRMWARE_BOOT_STATUS_INVALID 0x00 /* Firmware blob could not be validated */
|
||||
#define GB_FIRMWARE_BOOT_STATUS_INSECURE 0x01 /* Firmware blob is valid but insecure */
|
||||
#define GB_FIRMWARE_BOOT_STATUS_SECURE 0x02 /* Firmware blob is valid and secure */
|
||||
|
||||
/* Max firmware data fetch size in bytes */
|
||||
#define GB_FIRMWARE_FETCH_MAX 2000
|
||||
|
||||
/* Firmware protocol firmware size request/response */
|
||||
struct gb_firmware_size_request {
|
||||
__u8 stage;
|
||||
};
|
||||
|
||||
struct gb_firmware_size_response {
|
||||
__le32 size;
|
||||
};
|
||||
|
||||
/* Firmware protocol get firmware request/response */
|
||||
struct gb_firmware_get_firmware_request {
|
||||
__le32 offset;
|
||||
__le32 size;
|
||||
};
|
||||
|
||||
struct gb_firmware_get_firmware_response {
|
||||
__u8 data[0];
|
||||
};
|
||||
|
||||
/* Firmware protocol Ready to boot request */
|
||||
struct gb_firmware_ready_to_boot_request {
|
||||
__u8 stage;
|
||||
__u8 status;
|
||||
};
|
||||
/* Firmware protocol Ready to boot response has no payload */
|
||||
|
||||
|
||||
/* I2C */
|
||||
|
||||
/* Version of the Greybus i2c protocol we support */
|
||||
|
@ -28,6 +28,12 @@ struct gb_interface {
|
||||
char *product_string;
|
||||
u64 unique_id;
|
||||
|
||||
/* Information taken from the hotplug event */
|
||||
u32 unipro_mfg_id;
|
||||
u32 unipro_prod_id;
|
||||
u32 ara_vend_id;
|
||||
u32 ara_prod_id;
|
||||
|
||||
struct gb_module *module;
|
||||
struct greybus_host_device *hd;
|
||||
};
|
||||
|
@ -22,6 +22,8 @@
|
||||
|
||||
#include "greybus.h"
|
||||
|
||||
#define NSEC_PER_DAY 86400000000000ULL
|
||||
|
||||
struct gb_loopback_stats {
|
||||
u32 min;
|
||||
u32 max;
|
||||
@ -219,6 +221,19 @@ static struct attribute *loopback_attrs[] = {
|
||||
};
|
||||
ATTRIBUTE_GROUPS(loopback);
|
||||
|
||||
static void gb_loopback_calc_latency(struct gb_loopback *gb,
|
||||
struct timeval *ts, struct timeval *te)
|
||||
{
|
||||
u64 t1, t2;
|
||||
|
||||
t1 = timeval_to_ns(ts);
|
||||
t2 = timeval_to_ns(te);
|
||||
if (t2 > t1)
|
||||
gb->elapsed_nsecs = t2 - t1;
|
||||
else
|
||||
gb->elapsed_nsecs = NSEC_PER_DAY - t2 + t1;
|
||||
}
|
||||
|
||||
static int gb_loopback_sink(struct gb_loopback *gb, u32 len)
|
||||
{
|
||||
struct timeval ts, te;
|
||||
@ -236,7 +251,7 @@ static int gb_loopback_sink(struct gb_loopback *gb, u32 len)
|
||||
request, len + sizeof(*request), NULL, 0);
|
||||
|
||||
do_gettimeofday(&te);
|
||||
gb->elapsed_nsecs = timeval_to_ns(&te) - timeval_to_ns(&ts);
|
||||
gb_loopback_calc_latency(gb, &ts, &te);
|
||||
|
||||
kfree(request);
|
||||
return retval;
|
||||
@ -265,7 +280,7 @@ static int gb_loopback_transfer(struct gb_loopback *gb, u32 len)
|
||||
request, len + sizeof(*request),
|
||||
response, len + sizeof(*response));
|
||||
do_gettimeofday(&te);
|
||||
gb->elapsed_nsecs = timeval_to_ns(&te) - timeval_to_ns(&ts);
|
||||
gb_loopback_calc_latency(gb, &ts, &te);
|
||||
|
||||
if (retval)
|
||||
goto gb_error;
|
||||
@ -289,7 +304,7 @@ static int gb_loopback_ping(struct gb_loopback *gb)
|
||||
retval = gb_operation_sync(gb->connection, GB_LOOPBACK_TYPE_PING,
|
||||
NULL, 0, NULL, 0);
|
||||
do_gettimeofday(&te);
|
||||
gb->elapsed_nsecs = timeval_to_ns(&te) - timeval_to_ns(&ts);
|
||||
gb_loopback_calc_latency(gb, &ts, &te);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -163,12 +163,20 @@ struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor)
|
||||
return protocol;
|
||||
}
|
||||
|
||||
int gb_protocol_get_version(struct gb_connection *connection, void *request,
|
||||
int request_size)
|
||||
int gb_protocol_get_version(struct gb_connection *connection, bool send_request)
|
||||
{
|
||||
struct gb_protocol_version_response response;
|
||||
struct gb_protocol_version_response *request = NULL;
|
||||
int request_size = 0;
|
||||
int retval;
|
||||
|
||||
if (send_request) {
|
||||
response.major = connection->protocol->major;
|
||||
response.minor = connection->protocol->minor;
|
||||
request = &response;
|
||||
request_size = sizeof(*request);
|
||||
}
|
||||
|
||||
retval = gb_operation_sync(connection, GB_REQUEST_TYPE_PROTOCOL_VERSION,
|
||||
request, request_size, &response,
|
||||
sizeof(response));
|
||||
|
@ -44,8 +44,7 @@ int gb_protocol_deregister(struct gb_protocol *protocol);
|
||||
__gb_protocol_register(protocol, THIS_MODULE)
|
||||
|
||||
struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor);
|
||||
int gb_protocol_get_version(struct gb_connection *connection, void *request,
|
||||
int request_size);
|
||||
int gb_protocol_get_version(struct gb_connection *connection, bool send_request);
|
||||
|
||||
void gb_protocol_put(struct gb_protocol *protocol);
|
||||
|
||||
|
@ -276,20 +276,12 @@ static void svc_process_hotplug(struct work_struct *work)
|
||||
struct device *dev = &connection->dev;
|
||||
struct gb_interface *intf;
|
||||
u8 intf_id, device_id;
|
||||
u32 unipro_mfg_id;
|
||||
u32 unipro_prod_id;
|
||||
u32 ara_vend_id;
|
||||
u32 ara_prod_id;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Grab the information we need.
|
||||
*/
|
||||
intf_id = hotplug->intf_id;
|
||||
unipro_mfg_id = le32_to_cpu(hotplug->data.unipro_mfg_id);
|
||||
unipro_prod_id = le32_to_cpu(hotplug->data.unipro_prod_id);
|
||||
ara_vend_id = le32_to_cpu(hotplug->data.ara_vend_id);
|
||||
ara_prod_id = le32_to_cpu(hotplug->data.ara_prod_id);
|
||||
|
||||
intf = gb_interface_create(hd, intf_id);
|
||||
if (!intf) {
|
||||
@ -298,6 +290,11 @@ static void svc_process_hotplug(struct work_struct *work)
|
||||
goto free_svc_hotplug;
|
||||
}
|
||||
|
||||
intf->unipro_mfg_id = le32_to_cpu(hotplug->data.unipro_mfg_id);
|
||||
intf->unipro_prod_id = le32_to_cpu(hotplug->data.unipro_prod_id);
|
||||
intf->ara_vend_id = le32_to_cpu(hotplug->data.ara_vend_id);
|
||||
intf->ara_prod_id = le32_to_cpu(hotplug->data.ara_prod_id);
|
||||
|
||||
/*
|
||||
* Create a device id for the interface:
|
||||
* - device id 0 (GB_DEVICE_ID_SVC) belongs to the SVC
|
||||
|
Loading…
x
Reference in New Issue
Block a user