This change adds support to keep track of total time spent by a SKB in UL and DL directions. Timestamps are recorded per SKB for the complete life cycle at following stages:- 1) Creation: At the time of SKB allocation. 2) Submission: While SKB being submitted to HSIC HW by bridge driver/ HSUSB Core by rmnet gadget driver. 3) Completion: In completion handler of the driver(bridge driver/ gadget rmnet driver). 4) Sent: While sending SKB to bridge driver/rmnet gadget driver. 5) Queued: While SKB being queued to HSIC HW by bridge driver/ HSUSB Core by rmnet gadget driver. 6) Done: In completion handler while freeing the SKB. debugfs node /sys/kernel/debug/data_hsic_bridge/timestamp represents the listing of timestamp for last 34 SKBs submitted in UL direction. debugfs node /sys/kernel/debug/ghsic_data_xport/timestamp represents the listing of timestamp for last 34 SKBs submitted in DL direction. Recording of the time stamp is controlled by the module parameter in rmnet bridge driver and rmnet gadget driver. To enable the recording of timestamp in rmnet bridge driver echo 1 > /sys/module/mdm_bridge/parameters/record_timestamp To enable the recording of timestamp in rmnet gadget driver echo 1 > /sys/module/g_android/parameters/record_timestamp Change-Id: I10e7c171eec6a01afbd48328ba006f776370ac92 Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
157 lines
4.0 KiB
C
157 lines
4.0 KiB
C
/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 and
|
|
* only version 2 as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
|
|
#ifndef __LINUX_USB_BRIDGE_H__
|
|
#define __LINUX_USB_BRIDGE_H__
|
|
|
|
#include <linux/netdevice.h>
|
|
#include <linux/usb.h>
|
|
|
|
/* bridge device 0: DUN
|
|
* bridge device 1 : Tethered RMNET
|
|
*/
|
|
#define MAX_BRIDGE_DEVICES 2
|
|
|
|
struct bridge_ops {
|
|
int (*send_pkt)(void *, void *, size_t actual);
|
|
void (*send_cbits)(void *, unsigned int);
|
|
|
|
/* flow control */
|
|
void (*unthrottle_tx)(void *);
|
|
};
|
|
|
|
#define TX_THROTTLED BIT(0)
|
|
#define RX_THROTTLED BIT(1)
|
|
|
|
struct bridge {
|
|
/* context of the gadget port using bridge driver */
|
|
void *ctx;
|
|
|
|
/* bridge device array index mapped to the gadget port array index.
|
|
* data bridge[ch_id] <-- bridge --> gadget port[ch_id]
|
|
*/
|
|
unsigned int ch_id;
|
|
|
|
/* flow control bits */
|
|
unsigned long flags;
|
|
|
|
/* data/ctrl bridge callbacks */
|
|
struct bridge_ops ops;
|
|
};
|
|
|
|
/**
|
|
* timestamp_info: stores timestamp info for skb life cycle during data
|
|
* transfer for tethered rmnet/DUN.
|
|
* @created: stores timestamp at the time of creation of SKB.
|
|
* @rx_queued: stores timestamp when SKB queued to HW to receive
|
|
* data.
|
|
* @rx_done: stores timestamp when skb queued to h/w is completed.
|
|
* @rx_done_sent: stores timestamp when SKB is sent from gadget rmnet/DUN
|
|
* driver to bridge rmnet/DUN driver or vice versa.
|
|
* @tx_queued: stores timestamp when SKB is queued to send data.
|
|
*
|
|
* note that size of this struct shouldnt exceed 48bytes that's the max skb->cb
|
|
* holds.
|
|
*/
|
|
struct timestamp_info {
|
|
struct data_bridge *dev;
|
|
|
|
unsigned int created;
|
|
unsigned int rx_queued;
|
|
unsigned int rx_done;
|
|
unsigned int rx_done_sent;
|
|
unsigned int tx_queued;
|
|
};
|
|
|
|
/* Maximum timestamp message length */
|
|
#define DBG_DATA_MSG 128UL
|
|
|
|
/* Maximum timestamp messages */
|
|
#define DBG_DATA_MAX 32UL
|
|
|
|
/* timestamp buffer descriptor */
|
|
struct timestamp_buf {
|
|
char (buf[DBG_DATA_MAX])[DBG_DATA_MSG]; /* buffer */
|
|
unsigned idx; /* index */
|
|
rwlock_t lck; /* lock */
|
|
};
|
|
|
|
#if defined(CONFIG_USB_QCOM_MDM_BRIDGE) || \
|
|
defined(CONFIG_USB_QCOM_MDM_BRIDGE_MODULE)
|
|
|
|
/* Bridge APIs called by gadget driver */
|
|
int ctrl_bridge_open(struct bridge *);
|
|
void ctrl_bridge_close(unsigned int);
|
|
int ctrl_bridge_write(unsigned int, char *, size_t);
|
|
int ctrl_bridge_set_cbits(unsigned int, unsigned int);
|
|
unsigned int ctrl_bridge_get_cbits_tohost(unsigned int);
|
|
int data_bridge_open(struct bridge *brdg);
|
|
void data_bridge_close(unsigned int);
|
|
int data_bridge_write(unsigned int , struct sk_buff *);
|
|
int data_bridge_unthrottle_rx(unsigned int);
|
|
|
|
/* defined in control bridge */
|
|
int ctrl_bridge_probe(struct usb_interface *, struct usb_host_endpoint *, int);
|
|
void ctrl_bridge_disconnect(unsigned int);
|
|
int ctrl_bridge_resume(unsigned int);
|
|
int ctrl_bridge_suspend(unsigned int);
|
|
|
|
#else
|
|
|
|
static inline int __maybe_unused ctrl_bridge_open(struct bridge *brdg)
|
|
{
|
|
return -ENODEV;
|
|
}
|
|
|
|
static inline void __maybe_unused ctrl_bridge_close(unsigned int id) { }
|
|
|
|
static inline int __maybe_unused ctrl_bridge_write(unsigned int id,
|
|
char *data, size_t size)
|
|
{
|
|
return -ENODEV;
|
|
}
|
|
|
|
static inline int __maybe_unused ctrl_bridge_set_cbits(unsigned int id,
|
|
unsigned int cbits)
|
|
{
|
|
return -ENODEV;
|
|
}
|
|
|
|
static inline unsigned int __maybe_unused
|
|
ctrl_bridge_get_cbits_tohost(unsigned int id)
|
|
{
|
|
return -ENODEV;
|
|
}
|
|
|
|
static inline int __maybe_unused data_bridge_open(struct bridge *brdg)
|
|
{
|
|
return -ENODEV;
|
|
}
|
|
|
|
static inline void __maybe_unused data_bridge_close(unsigned int id) { }
|
|
|
|
static inline int __maybe_unused data_bridge_write(unsigned int id,
|
|
struct sk_buff *skb)
|
|
{
|
|
return -ENODEV;
|
|
}
|
|
|
|
static inline int __maybe_unused data_bridge_unthrottle_rx(unsigned int id)
|
|
{
|
|
return -ENODEV;
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|