245 lines
6.7 KiB
C
Executable File
245 lines
6.7 KiB
C
Executable File
#include "nvt_bus.h"
|
|
#include "nvt_util_dbg.h"
|
|
#include "nvt_icfg.h"
|
|
|
|
/**
|
|
* nvt_bus_txdata - send tx skb to bus
|
|
* @nvt_bus: bus structrue
|
|
* @skb: tx skb buffer
|
|
*
|
|
* this function will call bus tx_data ops to send it to bus.
|
|
*
|
|
* Return: zero - success
|
|
* negative - failure
|
|
*/
|
|
s32 nvt_bus_txdata(struct _nvt_bus *nvt_bus, struct sk_buff *skb)
|
|
{
|
|
s32 err = 0;
|
|
|
|
#ifdef BUS_UTILIZATION
|
|
//do not accept any tx data when we are in bus utilization mode
|
|
if (nvt_bus->nvt_bu->tx_enable) {
|
|
return -1;
|
|
}
|
|
#endif
|
|
err = nvt_bus->nvt_wdev_bus_ops.tx_data(nvt_bus, skb);
|
|
|
|
return err;
|
|
}
|
|
|
|
/**
|
|
* nvt_bus_attach - nvt bus allocation and initialization
|
|
* @dev - set nvt_bus to this device
|
|
* @bus_ops - nvt_bus operation table
|
|
*
|
|
* Return: a nvt_bus pointer
|
|
*/
|
|
struct _nvt_bus *nvt_bus_attach(struct device *dev,
|
|
struct _nvt_wdev_bus_ops bus_ops)
|
|
{
|
|
s32 ret = 0;
|
|
struct _nvt_bus *nvt_bus;
|
|
nvt_bus = kzalloc(sizeof(struct _nvt_bus), GFP_ATOMIC);
|
|
if (nvt_bus == NULL) {
|
|
nvt_dbg(ERROR, "%s: Alloc nvt_bus failed\n", __func__);
|
|
ret = -ENOMEM;
|
|
goto alloc_failed;
|
|
}
|
|
|
|
nvt_bus->icfg_pkg_buff = kzalloc(sizeof(struct _nvt_icfg_pkt_buff),
|
|
GFP_ATOMIC);
|
|
mutex_init(&nvt_bus->icfg_pkg_buff->iconfig_mutex);
|
|
|
|
nvt_bus->dev = dev;
|
|
nvt_bus->state = NVT_BUS_STATE_DOWN;
|
|
dev_set_drvdata(dev, nvt_bus);
|
|
nvt_bus->nvt_wdev_bus_ops = bus_ops;
|
|
|
|
init_waitqueue_head(&nvt_bus->fw_rdy_wait);
|
|
nvt_bus->fw_rdy_completed = 0;
|
|
|
|
//20160122 nash: bus statistic
|
|
nvt_bus->statistic.pkt_tx_cnt = 0;
|
|
nvt_bus->statistic.pkt_rx_cnt = 0;
|
|
nvt_bus->statistic.pkt_tx_err_cnt = 0;
|
|
nvt_bus->statistic.pkt_rx_err_cnt = 0;
|
|
|
|
nvt_bus->statistic.ctl_tx_cnt = 0;
|
|
nvt_bus->statistic.ctl_rx_cnt = 0;
|
|
nvt_bus->statistic.ctl_tx_err_cnt = 0;
|
|
nvt_bus->statistic.ctl_rx_err_cnt = 0;
|
|
|
|
#ifdef BUS_UTILIZATION
|
|
nvt_bus->nvt_bu = kzalloc(sizeof(struct _nvt_bus_utilization),
|
|
GFP_ATOMIC);
|
|
if (!nvt_bus->nvt_bu) {
|
|
nvt_dbg(ERROR, "%s: bus utilization alloc fail\n", __func__);
|
|
kfree(nvt_bus);
|
|
return NULL;
|
|
}
|
|
|
|
nvt_bus->nvt_bu->tx_enable = false;
|
|
nvt_bus->nvt_bu->rx_enable = false;
|
|
nvt_bus->nvt_bu->tx_total_cnt = 0;
|
|
nvt_bus->nvt_bu->tx_runtime_cnt = 0;
|
|
nvt_bus->nvt_bu->rx_total_cnt = 0;
|
|
nvt_bus->nvt_bu->rx_runtime_cnt = 0;
|
|
nvt_bus->nvt_bu->start_time = 0;
|
|
nvt_bus->nvt_bu->end_time = 0;
|
|
nvt_bus->nvt_bu->total_pkt_size_in_byte = 0;
|
|
nvt_bus->nvt_bu->tx_mode = NVT_BUS_BU_TX_VARIABLE_LEN;
|
|
#endif
|
|
|
|
return nvt_bus;
|
|
alloc_failed:
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* nvt_bus_detach - free nvt_bus
|
|
* @dev - get nvt_bus to this device
|
|
*
|
|
*
|
|
* Return: 0 for success, a negative value for fail
|
|
*/
|
|
s32 nvt_bus_detach(struct device *dev)
|
|
{
|
|
struct _nvt_bus *nvt_bus = dev_get_drvdata(dev);
|
|
kfree(nvt_bus);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* nvt_bus_register_txdone_callback - register your own TX done callback
|
|
* function
|
|
* @nvt_bus: nvt_bus structure
|
|
* @txdone_cb: callback function pointer
|
|
*
|
|
* Register your own TX done callback function by this function. When TX done,
|
|
* your callback would be executed
|
|
*
|
|
* Return: 0:success, -1:fail
|
|
*/
|
|
s32 nvt_bus_register_txdone_callback(struct _nvt_bus *nvt_bus,
|
|
void (*txdone_cb)(struct sk_buff *, s32 status_code))
|
|
{
|
|
if (nvt_bus == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
nvt_bus->tx_done_callback = txdone_cb;
|
|
return 0;
|
|
}
|
|
|
|
#ifdef BUS_UTILIZATION
|
|
/**
|
|
* nvt_bus_bu_tx_on - control TX bus utilization on or off
|
|
* @nvt_bus: nvt bus structure
|
|
* @on: true:on, false:off
|
|
* @pkt_cnt: packet number for transmit
|
|
*
|
|
* Return: 0:success, -1:fail
|
|
*/
|
|
s32 nvt_bus_bu_tx_on(struct _nvt_bus *nvt_bus, bool on, u32 pkt_cnt)
|
|
{
|
|
if (!nvt_bus) {
|
|
return -1;
|
|
}
|
|
|
|
if (on) {
|
|
nvt_bus->nvt_bu->tx_total_cnt = pkt_cnt;
|
|
nvt_bus->nvt_bu->tx_runtime_cnt = 0;
|
|
nvt_bus->nvt_bu->start_time = get_jiffies_64();
|
|
nvt_bus->nvt_bu->total_pkt_size_in_byte = 0;
|
|
nvt_bus->nvt_bu->tx_enable = true;
|
|
} else {
|
|
nvt_bus->nvt_bu->tx_enable = false;
|
|
nvt_bus->nvt_bu->tx_total_cnt = 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* nvt_bus_bu_rx_on - control RX bus utilization on or off
|
|
* @nvt_bus: nvt bus structure
|
|
* @on: true:on, false:off
|
|
* @pkt_cnt: packet number for transmit
|
|
*
|
|
* Return: 0:success, -1:fail
|
|
*/
|
|
s32 nvt_bus_bu_rx_on(struct _nvt_bus *nvt_bus, bool on, u32 pkt_cnt)
|
|
{
|
|
if (!nvt_bus) {
|
|
return -1;
|
|
}
|
|
|
|
if (on) {
|
|
nvt_bus->nvt_bu->rx_total_cnt = pkt_cnt;
|
|
nvt_bus->nvt_bu->rx_runtime_cnt = 0;
|
|
nvt_bus->nvt_bu->start_time = 0;
|
|
nvt_bus->nvt_bu->total_pkt_size_in_byte = 0;
|
|
nvt_bus->nvt_bu->rx_enable = true;
|
|
} else {
|
|
nvt_bus->nvt_bu->rx_enable = false;
|
|
nvt_bus->nvt_bu->rx_total_cnt = 0;
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/**
|
|
* nvt_bus_bu_show_result - show bus utilization result for both TX/RX
|
|
* @nvt_bus: nvt bus structure
|
|
* @is_tx: true:TX, false:RX
|
|
*
|
|
* Return: none
|
|
*/
|
|
void nvt_bus_bu_show_result(struct _nvt_bus *nvt_bus, bool is_tx)
|
|
{
|
|
u64 interval = 0;
|
|
u64 bu_rate = 0;
|
|
u8 *str_tbl[2] = {"TX", "RX"};
|
|
u8 *str;
|
|
s32 pkt_cnt = 0;
|
|
u32 ret_val;
|
|
|
|
if (!nvt_bus) {
|
|
nvt_dbg(ERROR, "%s: nvt_bus is NULL!!\n", __func__);
|
|
return;
|
|
}
|
|
|
|
nvt_bus->nvt_bu->end_time = get_jiffies_64();
|
|
interval = nvt_bus->nvt_bu->end_time - nvt_bus->nvt_bu->start_time;
|
|
|
|
if (is_tx) {
|
|
nvt_bus->nvt_bu->tx_enable = false;
|
|
str = str_tbl[0];
|
|
pkt_cnt = nvt_bus->nvt_bu->tx_runtime_cnt;
|
|
} else {
|
|
nvt_bus->nvt_bu->rx_enable = false;
|
|
str = str_tbl[1];
|
|
pkt_cnt = nvt_bus->nvt_bu->rx_runtime_cnt;
|
|
}
|
|
|
|
nvt_dbg(INFO, "\n[BU]: %s %d packets took %llu jiffies\n",
|
|
str, pkt_cnt, interval);
|
|
|
|
nvt_dbg(INFO, "[BU]: total pkt size=%llu\n",
|
|
nvt_bus->nvt_bu->total_pkt_size_in_byte);
|
|
|
|
bu_rate = nvt_bus->nvt_bu->total_pkt_size_in_byte * HZ;
|
|
if (interval > 0) {
|
|
ret_val = do_div(bu_rate, interval);
|
|
bu_rate *= 8;
|
|
nvt_dbg(INFO, "[BU]: SDIO %s bus utilization: %llu bps\n",
|
|
str, bu_rate);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
#endif
|
|
|