diff options
5 files changed, 151 insertions, 0 deletions
diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c index e8b290473ee2..bc9861c90ea3 100644 --- a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c +++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c | |||
@@ -1497,3 +1497,57 @@ void cn23xx_tell_vf_its_macaddr_changed(struct octeon_device *oct, int vfidx, | |||
1497 | octeon_mbox_write(oct, &mbox_cmd); | 1497 | octeon_mbox_write(oct, &mbox_cmd); |
1498 | } | 1498 | } |
1499 | } | 1499 | } |
1500 | |||
1501 | static void | ||
1502 | cn23xx_get_vf_stats_callback(struct octeon_device *oct, | ||
1503 | struct octeon_mbox_cmd *cmd, void *arg) | ||
1504 | { | ||
1505 | struct oct_vf_stats_ctx *ctx = arg; | ||
1506 | |||
1507 | memcpy(ctx->stats, cmd->data, sizeof(struct oct_vf_stats)); | ||
1508 | atomic_set(&ctx->status, 1); | ||
1509 | } | ||
1510 | |||
1511 | int cn23xx_get_vf_stats(struct octeon_device *oct, int vfidx, | ||
1512 | struct oct_vf_stats *stats) | ||
1513 | { | ||
1514 | u32 timeout = HZ; // 1sec | ||
1515 | struct octeon_mbox_cmd mbox_cmd; | ||
1516 | struct oct_vf_stats_ctx ctx; | ||
1517 | u32 count = 0, ret; | ||
1518 | |||
1519 | if (!(oct->sriov_info.vf_drv_loaded_mask & (1ULL << vfidx))) | ||
1520 | return -1; | ||
1521 | |||
1522 | if (sizeof(struct oct_vf_stats) > sizeof(mbox_cmd.data)) | ||
1523 | return -1; | ||
1524 | |||
1525 | mbox_cmd.msg.u64 = 0; | ||
1526 | mbox_cmd.msg.s.type = OCTEON_MBOX_REQUEST; | ||
1527 | mbox_cmd.msg.s.resp_needed = 1; | ||
1528 | mbox_cmd.msg.s.cmd = OCTEON_GET_VF_STATS; | ||
1529 | mbox_cmd.msg.s.len = 1; | ||
1530 | mbox_cmd.q_no = vfidx * oct->sriov_info.rings_per_vf; | ||
1531 | mbox_cmd.recv_len = 0; | ||
1532 | mbox_cmd.recv_status = 0; | ||
1533 | mbox_cmd.fn = (octeon_mbox_callback_t)cn23xx_get_vf_stats_callback; | ||
1534 | ctx.stats = stats; | ||
1535 | atomic_set(&ctx.status, 0); | ||
1536 | mbox_cmd.fn_arg = (void *)&ctx; | ||
1537 | memset(mbox_cmd.data, 0, sizeof(mbox_cmd.data)); | ||
1538 | octeon_mbox_write(oct, &mbox_cmd); | ||
1539 | |||
1540 | do { | ||
1541 | schedule_timeout_uninterruptible(1); | ||
1542 | } while ((atomic_read(&ctx.status) == 0) && (count++ < timeout)); | ||
1543 | |||
1544 | ret = atomic_read(&ctx.status); | ||
1545 | if (ret == 0) { | ||
1546 | octeon_mbox_cancel(oct, 0); | ||
1547 | dev_err(&oct->pci_dev->dev, "Unable to get stats from VF-%d, timedout\n", | ||
1548 | vfidx); | ||
1549 | return -1; | ||
1550 | } | ||
1551 | |||
1552 | return 0; | ||
1553 | } | ||
diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.h b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.h index 2aba5247b6d8..63b3de4f2bfe 100644 --- a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.h +++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.h | |||
@@ -43,6 +43,15 @@ struct octeon_cn23xx_pf { | |||
43 | 43 | ||
44 | #define CN23XX_SLI_DEF_BP 0x40 | 44 | #define CN23XX_SLI_DEF_BP 0x40 |
45 | 45 | ||
46 | struct oct_vf_stats { | ||
47 | u64 rx_packets; | ||
48 | u64 tx_packets; | ||
49 | u64 rx_bytes; | ||
50 | u64 tx_bytes; | ||
51 | u64 broadcast; | ||
52 | u64 multicast; | ||
53 | }; | ||
54 | |||
46 | int setup_cn23xx_octeon_pf_device(struct octeon_device *oct); | 55 | int setup_cn23xx_octeon_pf_device(struct octeon_device *oct); |
47 | 56 | ||
48 | int validate_cn23xx_pf_config_info(struct octeon_device *oct, | 57 | int validate_cn23xx_pf_config_info(struct octeon_device *oct, |
@@ -56,4 +65,7 @@ int cn23xx_fw_loaded(struct octeon_device *oct); | |||
56 | 65 | ||
57 | void cn23xx_tell_vf_its_macaddr_changed(struct octeon_device *oct, int vfidx, | 66 | void cn23xx_tell_vf_its_macaddr_changed(struct octeon_device *oct, int vfidx, |
58 | u8 *mac); | 67 | u8 *mac); |
68 | |||
69 | int cn23xx_get_vf_stats(struct octeon_device *oct, int ifidx, | ||
70 | struct oct_vf_stats *stats); | ||
59 | #endif | 71 | #endif |
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c index 44c2a0c1bbdd..f3891ae11b02 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c | |||
@@ -3326,6 +3326,31 @@ static const struct switchdev_ops lio_pf_switchdev_ops = { | |||
3326 | .switchdev_port_attr_get = lio_pf_switchdev_attr_get, | 3326 | .switchdev_port_attr_get = lio_pf_switchdev_attr_get, |
3327 | }; | 3327 | }; |
3328 | 3328 | ||
3329 | static int liquidio_get_vf_stats(struct net_device *netdev, int vfidx, | ||
3330 | struct ifla_vf_stats *vf_stats) | ||
3331 | { | ||
3332 | struct lio *lio = GET_LIO(netdev); | ||
3333 | struct octeon_device *oct = lio->oct_dev; | ||
3334 | struct oct_vf_stats stats; | ||
3335 | int ret; | ||
3336 | |||
3337 | if (vfidx < 0 || vfidx >= oct->sriov_info.num_vfs_alloced) | ||
3338 | return -EINVAL; | ||
3339 | |||
3340 | memset(&stats, 0, sizeof(struct oct_vf_stats)); | ||
3341 | ret = cn23xx_get_vf_stats(oct, vfidx, &stats); | ||
3342 | if (!ret) { | ||
3343 | vf_stats->rx_packets = stats.rx_packets; | ||
3344 | vf_stats->tx_packets = stats.tx_packets; | ||
3345 | vf_stats->rx_bytes = stats.rx_bytes; | ||
3346 | vf_stats->tx_bytes = stats.tx_bytes; | ||
3347 | vf_stats->broadcast = stats.broadcast; | ||
3348 | vf_stats->multicast = stats.multicast; | ||
3349 | } | ||
3350 | |||
3351 | return ret; | ||
3352 | } | ||
3353 | |||
3329 | static const struct net_device_ops lionetdevops = { | 3354 | static const struct net_device_ops lionetdevops = { |
3330 | .ndo_open = liquidio_open, | 3355 | .ndo_open = liquidio_open, |
3331 | .ndo_stop = liquidio_stop, | 3356 | .ndo_stop = liquidio_stop, |
@@ -3348,6 +3373,7 @@ static const struct net_device_ops lionetdevops = { | |||
3348 | .ndo_get_vf_config = liquidio_get_vf_config, | 3373 | .ndo_get_vf_config = liquidio_get_vf_config, |
3349 | .ndo_set_vf_trust = liquidio_set_vf_trust, | 3374 | .ndo_set_vf_trust = liquidio_set_vf_trust, |
3350 | .ndo_set_vf_link_state = liquidio_set_vf_link_state, | 3375 | .ndo_set_vf_link_state = liquidio_set_vf_link_state, |
3376 | .ndo_get_vf_stats = liquidio_get_vf_stats, | ||
3351 | }; | 3377 | }; |
3352 | 3378 | ||
3353 | /** \brief Entry point for the liquidio module | 3379 | /** \brief Entry point for the liquidio module |
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c b/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c index 28e74ee23ff8..021d99cd1665 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c +++ b/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "octeon_device.h" | 24 | #include "octeon_device.h" |
25 | #include "octeon_main.h" | 25 | #include "octeon_main.h" |
26 | #include "octeon_mailbox.h" | 26 | #include "octeon_mailbox.h" |
27 | #include "cn23xx_pf_device.h" | ||
27 | 28 | ||
28 | /** | 29 | /** |
29 | * octeon_mbox_read: | 30 | * octeon_mbox_read: |
@@ -205,6 +206,26 @@ int octeon_mbox_write(struct octeon_device *oct, | |||
205 | return ret; | 206 | return ret; |
206 | } | 207 | } |
207 | 208 | ||
209 | static void get_vf_stats(struct octeon_device *oct, | ||
210 | struct oct_vf_stats *stats) | ||
211 | { | ||
212 | int i; | ||
213 | |||
214 | for (i = 0; i < oct->num_iqs; i++) { | ||
215 | if (!oct->instr_queue[i]) | ||
216 | continue; | ||
217 | stats->tx_packets += oct->instr_queue[i]->stats.tx_done; | ||
218 | stats->tx_bytes += oct->instr_queue[i]->stats.tx_tot_bytes; | ||
219 | } | ||
220 | |||
221 | for (i = 0; i < oct->num_oqs; i++) { | ||
222 | if (!oct->droq[i]) | ||
223 | continue; | ||
224 | stats->rx_packets += oct->droq[i]->stats.rx_pkts_received; | ||
225 | stats->rx_bytes += oct->droq[i]->stats.rx_bytes_received; | ||
226 | } | ||
227 | } | ||
228 | |||
208 | /** | 229 | /** |
209 | * octeon_mbox_process_cmd: | 230 | * octeon_mbox_process_cmd: |
210 | * @mbox: Pointer mailbox | 231 | * @mbox: Pointer mailbox |
@@ -250,6 +271,15 @@ static int octeon_mbox_process_cmd(struct octeon_mbox *mbox, | |||
250 | mbox_cmd->msg.s.params); | 271 | mbox_cmd->msg.s.params); |
251 | break; | 272 | break; |
252 | 273 | ||
274 | case OCTEON_GET_VF_STATS: | ||
275 | dev_dbg(&oct->pci_dev->dev, "Got VF stats request. Sending data back\n"); | ||
276 | mbox_cmd->msg.s.type = OCTEON_MBOX_RESPONSE; | ||
277 | mbox_cmd->msg.s.resp_needed = 1; | ||
278 | mbox_cmd->msg.s.len = 1 + | ||
279 | sizeof(struct oct_vf_stats) / sizeof(u64); | ||
280 | get_vf_stats(oct, (struct oct_vf_stats *)mbox_cmd->data); | ||
281 | octeon_mbox_write(oct, mbox_cmd); | ||
282 | break; | ||
253 | default: | 283 | default: |
254 | break; | 284 | break; |
255 | } | 285 | } |
@@ -322,3 +352,25 @@ int octeon_mbox_process_message(struct octeon_mbox *mbox) | |||
322 | 352 | ||
323 | return 0; | 353 | return 0; |
324 | } | 354 | } |
355 | |||
356 | int octeon_mbox_cancel(struct octeon_device *oct, int q_no) | ||
357 | { | ||
358 | struct octeon_mbox *mbox = oct->mbox[q_no]; | ||
359 | struct octeon_mbox_cmd *mbox_cmd; | ||
360 | unsigned long flags = 0; | ||
361 | |||
362 | spin_lock_irqsave(&mbox->lock, flags); | ||
363 | mbox_cmd = &mbox->mbox_resp; | ||
364 | |||
365 | if (!(mbox->state & OCTEON_MBOX_STATE_RESPONSE_PENDING)) { | ||
366 | spin_unlock_irqrestore(&mbox->lock, flags); | ||
367 | return 1; | ||
368 | } | ||
369 | |||
370 | mbox->state = OCTEON_MBOX_STATE_IDLE; | ||
371 | memset(mbox_cmd, 0, sizeof(*mbox_cmd)); | ||
372 | writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg); | ||
373 | spin_unlock_irqrestore(&mbox->lock, flags); | ||
374 | |||
375 | return 0; | ||
376 | } | ||
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.h b/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.h index 1def22afeff1..d92bd7e16477 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.h +++ b/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.h | |||
@@ -25,6 +25,7 @@ | |||
25 | #define OCTEON_VF_ACTIVE 0x1 | 25 | #define OCTEON_VF_ACTIVE 0x1 |
26 | #define OCTEON_VF_FLR_REQUEST 0x2 | 26 | #define OCTEON_VF_FLR_REQUEST 0x2 |
27 | #define OCTEON_PF_CHANGED_VF_MACADDR 0x4 | 27 | #define OCTEON_PF_CHANGED_VF_MACADDR 0x4 |
28 | #define OCTEON_GET_VF_STATS 0x8 | ||
28 | 29 | ||
29 | /*Macro for Read acknowldgement*/ | 30 | /*Macro for Read acknowldgement*/ |
30 | #define OCTEON_PFVFACK 0xffffffffffffffffULL | 31 | #define OCTEON_PFVFACK 0xffffffffffffffffULL |
@@ -107,9 +108,15 @@ struct octeon_mbox { | |||
107 | 108 | ||
108 | }; | 109 | }; |
109 | 110 | ||
111 | struct oct_vf_stats_ctx { | ||
112 | atomic_t status; | ||
113 | struct oct_vf_stats *stats; | ||
114 | }; | ||
115 | |||
110 | int octeon_mbox_read(struct octeon_mbox *mbox); | 116 | int octeon_mbox_read(struct octeon_mbox *mbox); |
111 | int octeon_mbox_write(struct octeon_device *oct, | 117 | int octeon_mbox_write(struct octeon_device *oct, |
112 | struct octeon_mbox_cmd *mbox_cmd); | 118 | struct octeon_mbox_cmd *mbox_cmd); |
113 | int octeon_mbox_process_message(struct octeon_mbox *mbox); | 119 | int octeon_mbox_process_message(struct octeon_mbox *mbox); |
120 | int octeon_mbox_cancel(struct octeon_device *oct, int q_no); | ||
114 | 121 | ||
115 | #endif | 122 | #endif |