greybus: loopback: add sink to loopback protocol
Loopback sink command will operate as an amalgam of the ping and tranfer operations. Sink will send an ACK'd variable size operation over greybus. Unlike the transfer type which transmits the received data back, the sink type will simply ACK without sending the received data back. This patch adds the kernel side of the sink command. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
parent
a598f4384d
commit
384a7a3c4f
@ -668,6 +668,7 @@ struct gb_uart_serial_state_request {
|
||||
#define GB_LOOPBACK_TYPE_PROTOCOL_VERSION 0x01
|
||||
#define GB_LOOPBACK_TYPE_PING 0x02
|
||||
#define GB_LOOPBACK_TYPE_TRANSFER 0x03
|
||||
#define GB_LOOPBACK_TYPE_SINK 0x04
|
||||
|
||||
struct gb_loopback_transfer_request {
|
||||
__le32 len;
|
||||
|
@ -114,6 +114,7 @@ static void gb_loopback_check_attr(struct gb_loopback *gb)
|
||||
switch (gb->type) {
|
||||
case GB_LOOPBACK_TYPE_PING:
|
||||
case GB_LOOPBACK_TYPE_TRANSFER:
|
||||
case GB_LOOPBACK_TYPE_SINK:
|
||||
break;
|
||||
default:
|
||||
gb->type = 0;
|
||||
@ -164,6 +165,31 @@ static struct attribute *loopback_attrs[] = {
|
||||
};
|
||||
ATTRIBUTE_GROUPS(loopback);
|
||||
|
||||
static int gb_loopback_sink(struct gb_loopback *gb,
|
||||
struct timeval *tping, u32 len)
|
||||
{
|
||||
struct timeval ts, te;
|
||||
u64 elapsed_nsecs;
|
||||
struct gb_loopback_transfer_request *request;
|
||||
int retval;
|
||||
|
||||
request = kmalloc(len + sizeof(*request), GFP_KERNEL);
|
||||
if (!request)
|
||||
return -ENOMEM;
|
||||
|
||||
request->len = cpu_to_le32(len);
|
||||
|
||||
do_gettimeofday(&ts);
|
||||
retval = gb_operation_sync(gb->connection, GB_LOOPBACK_TYPE_SINK,
|
||||
request, len + sizeof(*request), NULL, 0);
|
||||
do_gettimeofday(&te);
|
||||
elapsed_nsecs = timeval_to_ns(&te) - timeval_to_ns(&ts);
|
||||
*tping = ns_to_timeval(elapsed_nsecs);
|
||||
|
||||
kfree(request);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int gb_loopback_transfer(struct gb_loopback *gb,
|
||||
struct timeval *tping, u32 len)
|
||||
{
|
||||
@ -235,6 +261,7 @@ static int gb_loopback_request_recv(u8 type, struct gb_operation *operation)
|
||||
"module-initiated version operation\n");
|
||||
return -EINVAL;
|
||||
case GB_LOOPBACK_TYPE_PING:
|
||||
case GB_LOOPBACK_TYPE_SINK:
|
||||
return 0;
|
||||
case GB_LOOPBACK_TYPE_TRANSFER:
|
||||
if (operation->request->payload_size < sizeof(*request)) {
|
||||
@ -345,6 +372,8 @@ static int gb_loopback_fn(void *data)
|
||||
error = gb_loopback_ping(gb, &tlat);
|
||||
else if (gb->type == GB_LOOPBACK_TYPE_TRANSFER)
|
||||
error = gb_loopback_transfer(gb, &tlat, gb->size);
|
||||
else if (gb->type == GB_LOOPBACK_TYPE_SINK)
|
||||
error = gb_loopback_sink(gb, &tlat, gb->size);
|
||||
if (error)
|
||||
gb->error++;
|
||||
if (gb->ts.tv_usec == 0 && gb->ts.tv_sec == 0) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user