673 lines · c
1/**********************************************************************2 * Author: Cavium, Inc.3 *4 * Contact: support@cavium.com5 * Please include "LiquidIO" in the subject.6 *7 * Copyright (c) 2003-2017 Cavium, Inc.8 *9 * This file is free software; you can redistribute it and/or modify10 * it under the terms of the GNU General Public License, Version 2, as11 * published by the Free Software Foundation.12 *13 * This file is distributed in the hope that it will be useful, but14 * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty15 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or16 * NONINFRINGEMENT. See the GNU General Public License for more details.17 ***********************************************************************/18#include <linux/pci.h>19#include <linux/if_vlan.h>20#include "liquidio_common.h"21#include "octeon_droq.h"22#include "octeon_iq.h"23#include "response_manager.h"24#include "octeon_device.h"25#include "octeon_nic.h"26#include "octeon_main.h"27#include "octeon_network.h"28#include "lio_vf_rep.h"29 30static int lio_vf_rep_open(struct net_device *ndev);31static int lio_vf_rep_stop(struct net_device *ndev);32static netdev_tx_t lio_vf_rep_pkt_xmit(struct sk_buff *skb,33 struct net_device *ndev);34static void lio_vf_rep_tx_timeout(struct net_device *netdev, unsigned int txqueue);35static int lio_vf_rep_phys_port_name(struct net_device *dev,36 char *buf, size_t len);37static void lio_vf_rep_get_stats64(struct net_device *dev,38 struct rtnl_link_stats64 *stats64);39static int lio_vf_rep_change_mtu(struct net_device *ndev, int new_mtu);40static int lio_vf_get_port_parent_id(struct net_device *dev,41 struct netdev_phys_item_id *ppid);42 43static const struct net_device_ops lio_vf_rep_ndev_ops = {44 .ndo_open = lio_vf_rep_open,45 .ndo_stop = lio_vf_rep_stop,46 .ndo_start_xmit = lio_vf_rep_pkt_xmit,47 .ndo_tx_timeout = lio_vf_rep_tx_timeout,48 .ndo_get_phys_port_name = lio_vf_rep_phys_port_name,49 .ndo_get_stats64 = lio_vf_rep_get_stats64,50 .ndo_change_mtu = lio_vf_rep_change_mtu,51 .ndo_get_port_parent_id = lio_vf_get_port_parent_id,52};53 54static int55lio_vf_rep_send_soft_command(struct octeon_device *oct,56 void *req, int req_size,57 void *resp, int resp_size)58{59 int tot_resp_size = sizeof(struct lio_vf_rep_resp) + resp_size;60 struct octeon_soft_command *sc = NULL;61 struct lio_vf_rep_resp *rep_resp;62 void *sc_req;63 int err;64 65 sc = (struct octeon_soft_command *)66 octeon_alloc_soft_command(oct, req_size,67 tot_resp_size, 0);68 if (!sc)69 return -ENOMEM;70 71 init_completion(&sc->complete);72 sc->sc_status = OCTEON_REQUEST_PENDING;73 74 sc_req = (struct lio_vf_rep_req *)sc->virtdptr;75 memcpy(sc_req, req, req_size);76 77 rep_resp = (struct lio_vf_rep_resp *)sc->virtrptr;78 memset(rep_resp, 0, tot_resp_size);79 WRITE_ONCE(rep_resp->status, 1);80 81 sc->iq_no = 0;82 octeon_prepare_soft_command(oct, sc, OPCODE_NIC,83 OPCODE_NIC_VF_REP_CMD, 0, 0, 0);84 85 err = octeon_send_soft_command(oct, sc);86 if (err == IQ_SEND_FAILED)87 goto free_buff;88 89 err = wait_for_sc_completion_timeout(oct, sc, 0);90 if (err)91 return err;92 93 err = READ_ONCE(rep_resp->status) ? -EBUSY : 0;94 if (err)95 dev_err(&oct->pci_dev->dev, "VF rep send config failed\n");96 else if (resp)97 memcpy(resp, (rep_resp + 1), resp_size);98 99 WRITE_ONCE(sc->caller_is_done, true);100 return err;101 102free_buff:103 octeon_free_soft_command(oct, sc);104 105 return err;106}107 108static int109lio_vf_rep_open(struct net_device *ndev)110{111 struct lio_vf_rep_desc *vf_rep = netdev_priv(ndev);112 struct lio_vf_rep_req rep_cfg;113 struct octeon_device *oct;114 int ret;115 116 oct = vf_rep->oct;117 118 memset(&rep_cfg, 0, sizeof(rep_cfg));119 rep_cfg.req_type = LIO_VF_REP_REQ_STATE;120 rep_cfg.ifidx = vf_rep->ifidx;121 rep_cfg.rep_state.state = LIO_VF_REP_STATE_UP;122 123 ret = lio_vf_rep_send_soft_command(oct, &rep_cfg,124 sizeof(rep_cfg), NULL, 0);125 126 if (ret) {127 dev_err(&oct->pci_dev->dev,128 "VF_REP open failed with err %d\n", ret);129 return -EIO;130 }131 132 atomic_set(&vf_rep->ifstate, (atomic_read(&vf_rep->ifstate) |133 LIO_IFSTATE_RUNNING));134 135 netif_carrier_on(ndev);136 netif_start_queue(ndev);137 138 return 0;139}140 141static int142lio_vf_rep_stop(struct net_device *ndev)143{144 struct lio_vf_rep_desc *vf_rep = netdev_priv(ndev);145 struct lio_vf_rep_req rep_cfg;146 struct octeon_device *oct;147 int ret;148 149 oct = vf_rep->oct;150 151 memset(&rep_cfg, 0, sizeof(rep_cfg));152 rep_cfg.req_type = LIO_VF_REP_REQ_STATE;153 rep_cfg.ifidx = vf_rep->ifidx;154 rep_cfg.rep_state.state = LIO_VF_REP_STATE_DOWN;155 156 ret = lio_vf_rep_send_soft_command(oct, &rep_cfg,157 sizeof(rep_cfg), NULL, 0);158 159 if (ret) {160 dev_err(&oct->pci_dev->dev,161 "VF_REP dev stop failed with err %d\n", ret);162 return -EIO;163 }164 165 atomic_set(&vf_rep->ifstate, (atomic_read(&vf_rep->ifstate) &166 ~LIO_IFSTATE_RUNNING));167 168 netif_tx_disable(ndev);169 netif_carrier_off(ndev);170 171 return 0;172}173 174static void175lio_vf_rep_tx_timeout(struct net_device *ndev, unsigned int txqueue)176{177 netif_trans_update(ndev);178 179 netif_wake_queue(ndev);180}181 182static void183lio_vf_rep_get_stats64(struct net_device *dev,184 struct rtnl_link_stats64 *stats64)185{186 struct lio_vf_rep_desc *vf_rep = netdev_priv(dev);187 188 /* Swap tx and rx stats as VF rep is a switch port */189 stats64->tx_packets = vf_rep->stats.rx_packets;190 stats64->tx_bytes = vf_rep->stats.rx_bytes;191 stats64->tx_dropped = vf_rep->stats.rx_dropped;192 193 stats64->rx_packets = vf_rep->stats.tx_packets;194 stats64->rx_bytes = vf_rep->stats.tx_bytes;195 stats64->rx_dropped = vf_rep->stats.tx_dropped;196}197 198static int199lio_vf_rep_change_mtu(struct net_device *ndev, int new_mtu)200{201 struct lio_vf_rep_desc *vf_rep = netdev_priv(ndev);202 struct lio_vf_rep_req rep_cfg;203 struct octeon_device *oct;204 int ret;205 206 oct = vf_rep->oct;207 208 memset(&rep_cfg, 0, sizeof(rep_cfg));209 rep_cfg.req_type = LIO_VF_REP_REQ_MTU;210 rep_cfg.ifidx = vf_rep->ifidx;211 rep_cfg.rep_mtu.mtu = cpu_to_be32(new_mtu);212 213 ret = lio_vf_rep_send_soft_command(oct, &rep_cfg,214 sizeof(rep_cfg), NULL, 0);215 if (ret) {216 dev_err(&oct->pci_dev->dev,217 "Change MTU failed with err %d\n", ret);218 return -EIO;219 }220 221 WRITE_ONCE(ndev->mtu, new_mtu);222 223 return 0;224}225 226static int227lio_vf_rep_phys_port_name(struct net_device *dev,228 char *buf, size_t len)229{230 struct lio_vf_rep_desc *vf_rep = netdev_priv(dev);231 struct octeon_device *oct = vf_rep->oct;232 int ret;233 234 ret = snprintf(buf, len, "pf%dvf%d", oct->pf_num,235 vf_rep->ifidx - oct->pf_num * 64 - 1);236 if (ret >= len)237 return -EOPNOTSUPP;238 239 return 0;240}241 242static struct net_device *243lio_vf_rep_get_ndev(struct octeon_device *oct, int ifidx)244{245 int vf_id, max_vfs = CN23XX_MAX_VFS_PER_PF + 1;246 int vfid_mask = max_vfs - 1;247 248 if (ifidx <= oct->pf_num * max_vfs ||249 ifidx >= oct->pf_num * max_vfs + max_vfs)250 return NULL;251 252 /* ifidx 1-63 for PF0 VFs253 * ifidx 65-127 for PF1 VFs254 */255 vf_id = (ifidx & vfid_mask) - 1;256 257 return oct->vf_rep_list.ndev[vf_id];258}259 260static void261lio_vf_rep_copy_packet(struct octeon_device *oct,262 struct sk_buff *skb,263 int len)264{265 if (likely(len > MIN_SKB_SIZE)) {266 struct octeon_skb_page_info *pg_info;267 unsigned char *va;268 269 pg_info = ((struct octeon_skb_page_info *)(skb->cb));270 if (pg_info->page) {271 va = page_address(pg_info->page) +272 pg_info->page_offset;273 memcpy(skb->data, va, MIN_SKB_SIZE);274 skb_put(skb, MIN_SKB_SIZE);275 skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,276 pg_info->page,277 pg_info->page_offset + MIN_SKB_SIZE,278 len - MIN_SKB_SIZE,279 LIO_RXBUFFER_SZ);280 }281 } else {282 struct octeon_skb_page_info *pg_info =283 ((struct octeon_skb_page_info *)(skb->cb));284 285 skb_copy_to_linear_data(skb, page_address(pg_info->page) +286 pg_info->page_offset, len);287 skb_put(skb, len);288 put_page(pg_info->page);289 }290}291 292static int293lio_vf_rep_pkt_recv(struct octeon_recv_info *recv_info, void *buf)294{295 struct octeon_recv_pkt *recv_pkt = recv_info->recv_pkt;296 struct lio_vf_rep_desc *vf_rep;297 struct net_device *vf_ndev;298 struct octeon_device *oct;299 union octeon_rh *rh;300 struct sk_buff *skb;301 int i, ifidx;302 303 oct = lio_get_device(recv_pkt->octeon_id);304 if (!oct)305 goto free_buffers;306 307 skb = recv_pkt->buffer_ptr[0];308 rh = &recv_pkt->rh;309 ifidx = rh->r.ossp;310 311 vf_ndev = lio_vf_rep_get_ndev(oct, ifidx);312 if (!vf_ndev)313 goto free_buffers;314 315 vf_rep = netdev_priv(vf_ndev);316 if (!(atomic_read(&vf_rep->ifstate) & LIO_IFSTATE_RUNNING) ||317 recv_pkt->buffer_count > 1)318 goto free_buffers;319 320 skb->dev = vf_ndev;321 322 /* Multiple buffers are not used for vf_rep packets.323 * So just buffer_size[0] is valid.324 */325 lio_vf_rep_copy_packet(oct, skb, recv_pkt->buffer_size[0]);326 327 skb_pull(skb, rh->r_dh.len * BYTES_PER_DHLEN_UNIT);328 skb->protocol = eth_type_trans(skb, skb->dev);329 skb->ip_summed = CHECKSUM_NONE;330 331 netif_rx(skb);332 333 octeon_free_recv_info(recv_info);334 335 return 0;336 337free_buffers:338 for (i = 0; i < recv_pkt->buffer_count; i++)339 recv_buffer_free(recv_pkt->buffer_ptr[i]);340 341 octeon_free_recv_info(recv_info);342 343 return 0;344}345 346static void347lio_vf_rep_packet_sent_callback(struct octeon_device *oct,348 u32 status, void *buf)349{350 struct octeon_soft_command *sc = (struct octeon_soft_command *)buf;351 struct sk_buff *skb = sc->ctxptr;352 struct net_device *ndev = skb->dev;353 u32 iq_no;354 355 dma_unmap_single(&oct->pci_dev->dev, sc->dmadptr,356 sc->datasize, DMA_TO_DEVICE);357 dev_kfree_skb_any(skb);358 iq_no = sc->iq_no;359 octeon_free_soft_command(oct, sc);360 361 if (octnet_iq_is_full(oct, iq_no))362 return;363 364 if (netif_queue_stopped(ndev))365 netif_wake_queue(ndev);366}367 368static netdev_tx_t369lio_vf_rep_pkt_xmit(struct sk_buff *skb, struct net_device *ndev)370{371 struct lio_vf_rep_desc *vf_rep = netdev_priv(ndev);372 struct net_device *parent_ndev = vf_rep->parent_ndev;373 struct octeon_device *oct = vf_rep->oct;374 struct octeon_instr_pki_ih3 *pki_ih3;375 struct octeon_soft_command *sc;376 struct lio *parent_lio;377 int status;378 379 parent_lio = GET_LIO(parent_ndev);380 381 if (!(atomic_read(&vf_rep->ifstate) & LIO_IFSTATE_RUNNING) ||382 skb->len <= 0)383 goto xmit_failed;384 385 if (octnet_iq_is_full(vf_rep->oct, parent_lio->txq)) {386 dev_err(&oct->pci_dev->dev, "VF rep: Device IQ full\n");387 netif_stop_queue(ndev);388 return NETDEV_TX_BUSY;389 }390 391 sc = (struct octeon_soft_command *)392 octeon_alloc_soft_command(oct, 0, 16, 0);393 if (!sc) {394 dev_err(&oct->pci_dev->dev, "VF rep: Soft command alloc failed\n");395 goto xmit_failed;396 }397 398 /* Multiple buffers are not used for vf_rep packets. */399 if (skb_shinfo(skb)->nr_frags != 0) {400 dev_err(&oct->pci_dev->dev, "VF rep: nr_frags != 0. Dropping packet\n");401 octeon_free_soft_command(oct, sc);402 goto xmit_failed;403 }404 405 sc->dmadptr = dma_map_single(&oct->pci_dev->dev,406 skb->data, skb->len, DMA_TO_DEVICE);407 if (dma_mapping_error(&oct->pci_dev->dev, sc->dmadptr)) {408 dev_err(&oct->pci_dev->dev, "VF rep: DMA mapping failed\n");409 octeon_free_soft_command(oct, sc);410 goto xmit_failed;411 }412 413 sc->virtdptr = skb->data;414 sc->datasize = skb->len;415 sc->ctxptr = skb;416 sc->iq_no = parent_lio->txq;417 418 octeon_prepare_soft_command(oct, sc, OPCODE_NIC, OPCODE_NIC_VF_REP_PKT,419 vf_rep->ifidx, 0, 0);420 pki_ih3 = (struct octeon_instr_pki_ih3 *)&sc->cmd.cmd3.pki_ih3;421 pki_ih3->tagtype = ORDERED_TAG;422 423 sc->callback = lio_vf_rep_packet_sent_callback;424 sc->callback_arg = sc;425 426 status = octeon_send_soft_command(oct, sc);427 if (status == IQ_SEND_FAILED) {428 dma_unmap_single(&oct->pci_dev->dev, sc->dmadptr,429 sc->datasize, DMA_TO_DEVICE);430 octeon_free_soft_command(oct, sc);431 goto xmit_failed;432 }433 434 if (status == IQ_SEND_STOP)435 netif_stop_queue(ndev);436 437 netif_trans_update(ndev);438 439 return NETDEV_TX_OK;440 441xmit_failed:442 dev_kfree_skb_any(skb);443 444 return NETDEV_TX_OK;445}446 447static int lio_vf_get_port_parent_id(struct net_device *dev,448 struct netdev_phys_item_id *ppid)449{450 struct lio_vf_rep_desc *vf_rep = netdev_priv(dev);451 struct net_device *parent_ndev = vf_rep->parent_ndev;452 struct lio *lio = GET_LIO(parent_ndev);453 454 ppid->id_len = ETH_ALEN;455 ether_addr_copy(ppid->id, (void *)&lio->linfo.hw_addr + 2);456 457 return 0;458}459 460static void461lio_vf_rep_fetch_stats(struct work_struct *work)462{463 struct cavium_wk *wk = (struct cavium_wk *)work;464 struct lio_vf_rep_desc *vf_rep = wk->ctxptr;465 struct lio_vf_rep_stats stats;466 struct lio_vf_rep_req rep_cfg;467 struct octeon_device *oct;468 int ret;469 470 oct = vf_rep->oct;471 472 memset(&rep_cfg, 0, sizeof(rep_cfg));473 rep_cfg.req_type = LIO_VF_REP_REQ_STATS;474 rep_cfg.ifidx = vf_rep->ifidx;475 476 ret = lio_vf_rep_send_soft_command(oct, &rep_cfg, sizeof(rep_cfg),477 &stats, sizeof(stats));478 479 if (!ret) {480 octeon_swap_8B_data((u64 *)&stats, (sizeof(stats) >> 3));481 memcpy(&vf_rep->stats, &stats, sizeof(stats));482 }483 484 schedule_delayed_work(&vf_rep->stats_wk.work,485 msecs_to_jiffies(LIO_VF_REP_STATS_POLL_TIME_MS));486}487 488int489lio_vf_rep_create(struct octeon_device *oct)490{491 struct lio_vf_rep_desc *vf_rep;492 struct net_device *ndev;493 int i, num_vfs;494 495 if (oct->eswitch_mode != DEVLINK_ESWITCH_MODE_SWITCHDEV)496 return 0;497 498 if (!oct->sriov_info.sriov_enabled)499 return 0;500 501 num_vfs = oct->sriov_info.num_vfs_alloced;502 503 oct->vf_rep_list.num_vfs = 0;504 for (i = 0; i < num_vfs; i++) {505 ndev = alloc_etherdev(sizeof(struct lio_vf_rep_desc));506 507 if (!ndev) {508 dev_err(&oct->pci_dev->dev,509 "VF rep device %d creation failed\n", i);510 goto cleanup;511 }512 513 ndev->min_mtu = LIO_MIN_MTU_SIZE;514 ndev->max_mtu = LIO_MAX_MTU_SIZE;515 ndev->netdev_ops = &lio_vf_rep_ndev_ops;516 517 vf_rep = netdev_priv(ndev);518 memset(vf_rep, 0, sizeof(*vf_rep));519 520 vf_rep->ndev = ndev;521 vf_rep->oct = oct;522 vf_rep->parent_ndev = oct->props[0].netdev;523 vf_rep->ifidx = (oct->pf_num * 64) + i + 1;524 525 eth_hw_addr_random(ndev);526 527 if (register_netdev(ndev)) {528 dev_err(&oct->pci_dev->dev, "VF rep nerdev registration failed\n");529 530 free_netdev(ndev);531 goto cleanup;532 }533 534 netif_carrier_off(ndev);535 536 INIT_DELAYED_WORK(&vf_rep->stats_wk.work,537 lio_vf_rep_fetch_stats);538 vf_rep->stats_wk.ctxptr = (void *)vf_rep;539 schedule_delayed_work(&vf_rep->stats_wk.work,540 msecs_to_jiffies541 (LIO_VF_REP_STATS_POLL_TIME_MS));542 oct->vf_rep_list.num_vfs++;543 oct->vf_rep_list.ndev[i] = ndev;544 }545 546 if (octeon_register_dispatch_fn(oct, OPCODE_NIC,547 OPCODE_NIC_VF_REP_PKT,548 lio_vf_rep_pkt_recv, oct)) {549 dev_err(&oct->pci_dev->dev, "VF rep Dispatch func registration failed\n");550 551 goto cleanup;552 }553 554 return 0;555 556cleanup:557 for (i = 0; i < oct->vf_rep_list.num_vfs; i++) {558 ndev = oct->vf_rep_list.ndev[i];559 oct->vf_rep_list.ndev[i] = NULL;560 if (ndev) {561 vf_rep = netdev_priv(ndev);562 cancel_delayed_work_sync563 (&vf_rep->stats_wk.work);564 unregister_netdev(ndev);565 free_netdev(ndev);566 }567 }568 569 oct->vf_rep_list.num_vfs = 0;570 571 return -1;572}573 574void575lio_vf_rep_destroy(struct octeon_device *oct)576{577 struct lio_vf_rep_desc *vf_rep;578 struct net_device *ndev;579 int i;580 581 if (oct->eswitch_mode != DEVLINK_ESWITCH_MODE_SWITCHDEV)582 return;583 584 if (!oct->sriov_info.sriov_enabled)585 return;586 587 for (i = 0; i < oct->vf_rep_list.num_vfs; i++) {588 ndev = oct->vf_rep_list.ndev[i];589 oct->vf_rep_list.ndev[i] = NULL;590 if (ndev) {591 vf_rep = netdev_priv(ndev);592 cancel_delayed_work_sync593 (&vf_rep->stats_wk.work);594 netif_tx_disable(ndev);595 netif_carrier_off(ndev);596 597 unregister_netdev(ndev);598 free_netdev(ndev);599 }600 }601 602 oct->vf_rep_list.num_vfs = 0;603}604 605static int606lio_vf_rep_netdev_event(struct notifier_block *nb,607 unsigned long event, void *ptr)608{609 struct net_device *ndev = netdev_notifier_info_to_dev(ptr);610 struct lio_vf_rep_desc *vf_rep;611 struct lio_vf_rep_req rep_cfg;612 struct octeon_device *oct;613 int ret;614 615 switch (event) {616 case NETDEV_REGISTER:617 case NETDEV_CHANGENAME:618 break;619 620 default:621 return NOTIFY_DONE;622 }623 624 if (ndev->netdev_ops != &lio_vf_rep_ndev_ops)625 return NOTIFY_DONE;626 627 vf_rep = netdev_priv(ndev);628 oct = vf_rep->oct;629 630 if (strlen(ndev->name) > LIO_IF_NAME_SIZE) {631 dev_err(&oct->pci_dev->dev,632 "Device name change sync failed as the size is > %d\n",633 LIO_IF_NAME_SIZE);634 return NOTIFY_DONE;635 }636 637 memset(&rep_cfg, 0, sizeof(rep_cfg));638 rep_cfg.req_type = LIO_VF_REP_REQ_DEVNAME;639 rep_cfg.ifidx = vf_rep->ifidx;640 strscpy(rep_cfg.rep_name.name, ndev->name,641 sizeof(rep_cfg.rep_name.name));642 643 ret = lio_vf_rep_send_soft_command(oct, &rep_cfg,644 sizeof(rep_cfg), NULL, 0);645 if (ret)646 dev_err(&oct->pci_dev->dev,647 "vf_rep netdev name change failed with err %d\n", ret);648 649 return NOTIFY_DONE;650}651 652static struct notifier_block lio_vf_rep_netdev_notifier = {653 .notifier_call = lio_vf_rep_netdev_event,654};655 656int657lio_vf_rep_modinit(void)658{659 if (register_netdevice_notifier(&lio_vf_rep_netdev_notifier)) {660 pr_err("netdev notifier registration failed\n");661 return -EFAULT;662 }663 664 return 0;665}666 667void668lio_vf_rep_modexit(void)669{670 if (unregister_netdevice_notifier(&lio_vf_rep_netdev_notifier))671 pr_err("netdev notifier unregister failed\n");672}673