mirror of
https://github.com/torvalds/linux.git
synced 2024-12-04 01:51:34 +00:00
liquidio: Added ndo_get_vf_stats support
Added the ndo to gather VF statistics through the PF. Collect VF statistics via mailbox from VF. Signed-off-by: Intiyaz Basha <intiyaz.basha@cavium.com> Signed-off-by: Felix Manlunas <felix.manlunas@cavium.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
eaa008d3b3
commit
cea395ac86
@ -1497,3 +1497,57 @@ void cn23xx_tell_vf_its_macaddr_changed(struct octeon_device *oct, int vfidx,
|
||||
octeon_mbox_write(oct, &mbox_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cn23xx_get_vf_stats_callback(struct octeon_device *oct,
|
||||
struct octeon_mbox_cmd *cmd, void *arg)
|
||||
{
|
||||
struct oct_vf_stats_ctx *ctx = arg;
|
||||
|
||||
memcpy(ctx->stats, cmd->data, sizeof(struct oct_vf_stats));
|
||||
atomic_set(&ctx->status, 1);
|
||||
}
|
||||
|
||||
int cn23xx_get_vf_stats(struct octeon_device *oct, int vfidx,
|
||||
struct oct_vf_stats *stats)
|
||||
{
|
||||
u32 timeout = HZ; // 1sec
|
||||
struct octeon_mbox_cmd mbox_cmd;
|
||||
struct oct_vf_stats_ctx ctx;
|
||||
u32 count = 0, ret;
|
||||
|
||||
if (!(oct->sriov_info.vf_drv_loaded_mask & (1ULL << vfidx)))
|
||||
return -1;
|
||||
|
||||
if (sizeof(struct oct_vf_stats) > sizeof(mbox_cmd.data))
|
||||
return -1;
|
||||
|
||||
mbox_cmd.msg.u64 = 0;
|
||||
mbox_cmd.msg.s.type = OCTEON_MBOX_REQUEST;
|
||||
mbox_cmd.msg.s.resp_needed = 1;
|
||||
mbox_cmd.msg.s.cmd = OCTEON_GET_VF_STATS;
|
||||
mbox_cmd.msg.s.len = 1;
|
||||
mbox_cmd.q_no = vfidx * oct->sriov_info.rings_per_vf;
|
||||
mbox_cmd.recv_len = 0;
|
||||
mbox_cmd.recv_status = 0;
|
||||
mbox_cmd.fn = (octeon_mbox_callback_t)cn23xx_get_vf_stats_callback;
|
||||
ctx.stats = stats;
|
||||
atomic_set(&ctx.status, 0);
|
||||
mbox_cmd.fn_arg = (void *)&ctx;
|
||||
memset(mbox_cmd.data, 0, sizeof(mbox_cmd.data));
|
||||
octeon_mbox_write(oct, &mbox_cmd);
|
||||
|
||||
do {
|
||||
schedule_timeout_uninterruptible(1);
|
||||
} while ((atomic_read(&ctx.status) == 0) && (count++ < timeout));
|
||||
|
||||
ret = atomic_read(&ctx.status);
|
||||
if (ret == 0) {
|
||||
octeon_mbox_cancel(oct, 0);
|
||||
dev_err(&oct->pci_dev->dev, "Unable to get stats from VF-%d, timedout\n",
|
||||
vfidx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -43,6 +43,15 @@ struct octeon_cn23xx_pf {
|
||||
|
||||
#define CN23XX_SLI_DEF_BP 0x40
|
||||
|
||||
struct oct_vf_stats {
|
||||
u64 rx_packets;
|
||||
u64 tx_packets;
|
||||
u64 rx_bytes;
|
||||
u64 tx_bytes;
|
||||
u64 broadcast;
|
||||
u64 multicast;
|
||||
};
|
||||
|
||||
int setup_cn23xx_octeon_pf_device(struct octeon_device *oct);
|
||||
|
||||
int validate_cn23xx_pf_config_info(struct octeon_device *oct,
|
||||
@ -56,4 +65,7 @@ int cn23xx_fw_loaded(struct octeon_device *oct);
|
||||
|
||||
void cn23xx_tell_vf_its_macaddr_changed(struct octeon_device *oct, int vfidx,
|
||||
u8 *mac);
|
||||
|
||||
int cn23xx_get_vf_stats(struct octeon_device *oct, int ifidx,
|
||||
struct oct_vf_stats *stats);
|
||||
#endif
|
||||
|
@ -3326,6 +3326,31 @@ static const struct switchdev_ops lio_pf_switchdev_ops = {
|
||||
.switchdev_port_attr_get = lio_pf_switchdev_attr_get,
|
||||
};
|
||||
|
||||
static int liquidio_get_vf_stats(struct net_device *netdev, int vfidx,
|
||||
struct ifla_vf_stats *vf_stats)
|
||||
{
|
||||
struct lio *lio = GET_LIO(netdev);
|
||||
struct octeon_device *oct = lio->oct_dev;
|
||||
struct oct_vf_stats stats;
|
||||
int ret;
|
||||
|
||||
if (vfidx < 0 || vfidx >= oct->sriov_info.num_vfs_alloced)
|
||||
return -EINVAL;
|
||||
|
||||
memset(&stats, 0, sizeof(struct oct_vf_stats));
|
||||
ret = cn23xx_get_vf_stats(oct, vfidx, &stats);
|
||||
if (!ret) {
|
||||
vf_stats->rx_packets = stats.rx_packets;
|
||||
vf_stats->tx_packets = stats.tx_packets;
|
||||
vf_stats->rx_bytes = stats.rx_bytes;
|
||||
vf_stats->tx_bytes = stats.tx_bytes;
|
||||
vf_stats->broadcast = stats.broadcast;
|
||||
vf_stats->multicast = stats.multicast;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct net_device_ops lionetdevops = {
|
||||
.ndo_open = liquidio_open,
|
||||
.ndo_stop = liquidio_stop,
|
||||
@ -3348,6 +3373,7 @@ static const struct net_device_ops lionetdevops = {
|
||||
.ndo_get_vf_config = liquidio_get_vf_config,
|
||||
.ndo_set_vf_trust = liquidio_set_vf_trust,
|
||||
.ndo_set_vf_link_state = liquidio_set_vf_link_state,
|
||||
.ndo_get_vf_stats = liquidio_get_vf_stats,
|
||||
};
|
||||
|
||||
/** \brief Entry point for the liquidio module
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "octeon_device.h"
|
||||
#include "octeon_main.h"
|
||||
#include "octeon_mailbox.h"
|
||||
#include "cn23xx_pf_device.h"
|
||||
|
||||
/**
|
||||
* octeon_mbox_read:
|
||||
@ -205,6 +206,26 @@ int octeon_mbox_write(struct octeon_device *oct,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void get_vf_stats(struct octeon_device *oct,
|
||||
struct oct_vf_stats *stats)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < oct->num_iqs; i++) {
|
||||
if (!oct->instr_queue[i])
|
||||
continue;
|
||||
stats->tx_packets += oct->instr_queue[i]->stats.tx_done;
|
||||
stats->tx_bytes += oct->instr_queue[i]->stats.tx_tot_bytes;
|
||||
}
|
||||
|
||||
for (i = 0; i < oct->num_oqs; i++) {
|
||||
if (!oct->droq[i])
|
||||
continue;
|
||||
stats->rx_packets += oct->droq[i]->stats.rx_pkts_received;
|
||||
stats->rx_bytes += oct->droq[i]->stats.rx_bytes_received;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* octeon_mbox_process_cmd:
|
||||
* @mbox: Pointer mailbox
|
||||
@ -250,6 +271,15 @@ static int octeon_mbox_process_cmd(struct octeon_mbox *mbox,
|
||||
mbox_cmd->msg.s.params);
|
||||
break;
|
||||
|
||||
case OCTEON_GET_VF_STATS:
|
||||
dev_dbg(&oct->pci_dev->dev, "Got VF stats request. Sending data back\n");
|
||||
mbox_cmd->msg.s.type = OCTEON_MBOX_RESPONSE;
|
||||
mbox_cmd->msg.s.resp_needed = 1;
|
||||
mbox_cmd->msg.s.len = 1 +
|
||||
sizeof(struct oct_vf_stats) / sizeof(u64);
|
||||
get_vf_stats(oct, (struct oct_vf_stats *)mbox_cmd->data);
|
||||
octeon_mbox_write(oct, mbox_cmd);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -322,3 +352,25 @@ int octeon_mbox_process_message(struct octeon_mbox *mbox)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int octeon_mbox_cancel(struct octeon_device *oct, int q_no)
|
||||
{
|
||||
struct octeon_mbox *mbox = oct->mbox[q_no];
|
||||
struct octeon_mbox_cmd *mbox_cmd;
|
||||
unsigned long flags = 0;
|
||||
|
||||
spin_lock_irqsave(&mbox->lock, flags);
|
||||
mbox_cmd = &mbox->mbox_resp;
|
||||
|
||||
if (!(mbox->state & OCTEON_MBOX_STATE_RESPONSE_PENDING)) {
|
||||
spin_unlock_irqrestore(&mbox->lock, flags);
|
||||
return 1;
|
||||
}
|
||||
|
||||
mbox->state = OCTEON_MBOX_STATE_IDLE;
|
||||
memset(mbox_cmd, 0, sizeof(*mbox_cmd));
|
||||
writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
|
||||
spin_unlock_irqrestore(&mbox->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
#define OCTEON_VF_ACTIVE 0x1
|
||||
#define OCTEON_VF_FLR_REQUEST 0x2
|
||||
#define OCTEON_PF_CHANGED_VF_MACADDR 0x4
|
||||
#define OCTEON_GET_VF_STATS 0x8
|
||||
|
||||
/*Macro for Read acknowldgement*/
|
||||
#define OCTEON_PFVFACK 0xffffffffffffffffULL
|
||||
@ -107,9 +108,15 @@ struct octeon_mbox {
|
||||
|
||||
};
|
||||
|
||||
struct oct_vf_stats_ctx {
|
||||
atomic_t status;
|
||||
struct oct_vf_stats *stats;
|
||||
};
|
||||
|
||||
int octeon_mbox_read(struct octeon_mbox *mbox);
|
||||
int octeon_mbox_write(struct octeon_device *oct,
|
||||
struct octeon_mbox_cmd *mbox_cmd);
|
||||
int octeon_mbox_process_message(struct octeon_mbox *mbox);
|
||||
int octeon_mbox_cancel(struct octeon_device *oct, int q_no);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user