19c067b84SDoug Ambrisko /* SPDX-License-Identifier: BSD-3-Clause 29c067b84SDoug Ambrisko * Copyright 2008-2017 Cisco Systems, Inc. All rights reserved. 39c067b84SDoug Ambrisko * Copyright 2007 Nuova Systems, Inc. All rights reserved. 49c067b84SDoug Ambrisko */ 59c067b84SDoug Ambrisko 69c067b84SDoug Ambrisko #include "enic.h" 79c067b84SDoug Ambrisko #include "enic_compat.h" 89c067b84SDoug Ambrisko #include "wq_enet_desc.h" 99c067b84SDoug Ambrisko #include "rq_enet_desc.h" 109c067b84SDoug Ambrisko #include "cq_enet_desc.h" 119c067b84SDoug Ambrisko #include "vnic_resource.h" 129c067b84SDoug Ambrisko #include "vnic_enet.h" 139c067b84SDoug Ambrisko #include "vnic_dev.h" 149c067b84SDoug Ambrisko #include "vnic_wq.h" 159c067b84SDoug Ambrisko #include "vnic_rq.h" 169c067b84SDoug Ambrisko #include "vnic_cq.h" 179c067b84SDoug Ambrisko #include "vnic_intr.h" 189c067b84SDoug Ambrisko #include "vnic_stats.h" 199c067b84SDoug Ambrisko #include "vnic_nic.h" 209c067b84SDoug Ambrisko #include "vnic_rss.h" 219c067b84SDoug Ambrisko #include "enic_res.h" 229c067b84SDoug Ambrisko #include "enic.h" 239c067b84SDoug Ambrisko 249c067b84SDoug Ambrisko int enic_get_vnic_config(struct enic *enic) 259c067b84SDoug Ambrisko { 269c067b84SDoug Ambrisko struct vnic_enet_config *c = &enic->config; 279c067b84SDoug Ambrisko int err; 289c067b84SDoug Ambrisko err = vnic_dev_get_mac_addr(enic->vdev, enic->mac_addr); 299c067b84SDoug Ambrisko if (err) { 309c067b84SDoug Ambrisko dev_err(enic_get_dev(enic), 319c067b84SDoug Ambrisko "Error getting MAC addr, %d\n", err); 329c067b84SDoug Ambrisko return err; 339c067b84SDoug Ambrisko } 349c067b84SDoug Ambrisko 359c067b84SDoug Ambrisko #define GET_CONFIG(m) \ 369c067b84SDoug Ambrisko do { \ 379c067b84SDoug Ambrisko err = vnic_dev_spec(enic->vdev, \ 389c067b84SDoug Ambrisko offsetof(struct vnic_enet_config, m), \ 399c067b84SDoug Ambrisko sizeof(c->m), &c->m); \ 409c067b84SDoug Ambrisko if (err) { \ 419c067b84SDoug Ambrisko dev_err(enic_get_dev(enic), \ 429c067b84SDoug Ambrisko "Error getting %s, %d\n", #m, err); \ 439c067b84SDoug Ambrisko return err; \ 449c067b84SDoug Ambrisko } \ 459c067b84SDoug Ambrisko } while (0) 469c067b84SDoug Ambrisko 479c067b84SDoug Ambrisko GET_CONFIG(flags); 489c067b84SDoug Ambrisko GET_CONFIG(wq_desc_count); 499c067b84SDoug Ambrisko GET_CONFIG(rq_desc_count); 509c067b84SDoug Ambrisko GET_CONFIG(mtu); 519c067b84SDoug Ambrisko GET_CONFIG(intr_timer_type); 529c067b84SDoug Ambrisko GET_CONFIG(intr_mode); 539c067b84SDoug Ambrisko GET_CONFIG(intr_timer_usec); 549c067b84SDoug Ambrisko GET_CONFIG(loop_tag); 559c067b84SDoug Ambrisko GET_CONFIG(num_arfs); 569c067b84SDoug Ambrisko GET_CONFIG(max_pkt_size); 579c067b84SDoug Ambrisko 589c067b84SDoug Ambrisko /* max packet size is only defined in newer VIC firmware 599c067b84SDoug Ambrisko * and will be 0 for legacy firmware and VICs 609c067b84SDoug Ambrisko */ 619c067b84SDoug Ambrisko if (c->max_pkt_size > ENIC_DEFAULT_RX_MAX_PKT_SIZE) 629c067b84SDoug Ambrisko enic->max_mtu = c->max_pkt_size - (ETHER_HDR_LEN + 4); 639c067b84SDoug Ambrisko else 649c067b84SDoug Ambrisko enic->max_mtu = ENIC_DEFAULT_RX_MAX_PKT_SIZE 659c067b84SDoug Ambrisko - (ETHER_HDR_LEN + 4); 669c067b84SDoug Ambrisko if (c->mtu == 0) 679c067b84SDoug Ambrisko c->mtu = 1500; 689c067b84SDoug Ambrisko 699c067b84SDoug Ambrisko enic->adv_filters = vnic_dev_capable_adv_filters(enic->vdev); 709c067b84SDoug Ambrisko 719c067b84SDoug Ambrisko err = vnic_dev_capable_filter_mode(enic->vdev, &enic->flow_filter_mode, 729c067b84SDoug Ambrisko &enic->filter_actions); 739c067b84SDoug Ambrisko if (err) { 749c067b84SDoug Ambrisko dev_err(enic_get_dev(enic), 759c067b84SDoug Ambrisko "Error getting filter modes, %d\n", err); 769c067b84SDoug Ambrisko return err; 779c067b84SDoug Ambrisko } 789c067b84SDoug Ambrisko vnic_dev_capable_udp_rss_weak(enic->vdev, &enic->nic_cfg_chk, 799c067b84SDoug Ambrisko &enic->udp_rss_weak); 809c067b84SDoug Ambrisko 819c067b84SDoug Ambrisko c->wq_desc_count = 829c067b84SDoug Ambrisko min_t(u32, ENIC_MAX_WQ_DESCS, 839c067b84SDoug Ambrisko max_t(u32, ENIC_MIN_WQ_DESCS, 849c067b84SDoug Ambrisko c->wq_desc_count)); 859c067b84SDoug Ambrisko c->wq_desc_count &= 0xffffffe0; /* must be aligned to groups of 32 */ 869c067b84SDoug Ambrisko 879c067b84SDoug Ambrisko c->rq_desc_count = 889c067b84SDoug Ambrisko min_t(u32, ENIC_MAX_RQ_DESCS, 899c067b84SDoug Ambrisko max_t(u32, ENIC_MIN_RQ_DESCS, 909c067b84SDoug Ambrisko c->rq_desc_count)); 919c067b84SDoug Ambrisko c->rq_desc_count &= 0xffffffe0; /* must be aligned to groups of 32 */ 929c067b84SDoug Ambrisko 939c067b84SDoug Ambrisko c->intr_timer_usec = min_t(u32, c->intr_timer_usec, 949c067b84SDoug Ambrisko vnic_dev_get_intr_coal_timer_max(enic->vdev)); 959c067b84SDoug Ambrisko 969c067b84SDoug Ambrisko dev_info(enic_get_dev(enic), 979c067b84SDoug Ambrisko "vNIC MAC addr %02x:%02x:%02x:%02x:%02x:%02x " 98*0acab8b3SDoug Ambrisko "wq/rq %d/%d mtu %d, max mtu:%d\n", 999c067b84SDoug Ambrisko enic->mac_addr[0], enic->mac_addr[1], enic->mac_addr[2], 1009c067b84SDoug Ambrisko enic->mac_addr[3], enic->mac_addr[4], enic->mac_addr[5], 1019c067b84SDoug Ambrisko c->wq_desc_count, c->rq_desc_count, 102*0acab8b3SDoug Ambrisko c->mtu, enic->max_mtu); 1039c067b84SDoug Ambrisko dev_info(enic_get_dev(enic), "vNIC csum tx/rx %s/%s " 1049c067b84SDoug Ambrisko "rss %s intr mode %s type %s timer %d usec " 1059c067b84SDoug Ambrisko "loopback tag 0x%04x\n", 1069c067b84SDoug Ambrisko ENIC_SETTING(enic, TXCSUM) ? "yes" : "no", 1079c067b84SDoug Ambrisko ENIC_SETTING(enic, RXCSUM) ? "yes" : "no", 1089c067b84SDoug Ambrisko ENIC_SETTING(enic, RSS) ? 1099c067b84SDoug Ambrisko (ENIC_SETTING(enic, RSSHASH_UDPIPV4) ? "+UDP" : 1109c067b84SDoug Ambrisko ((enic->udp_rss_weak ? "+udp" : 1119c067b84SDoug Ambrisko "yes"))) : "no", 1129c067b84SDoug Ambrisko c->intr_mode == VENET_INTR_MODE_INTX ? "INTx" : 1139c067b84SDoug Ambrisko c->intr_mode == VENET_INTR_MODE_MSI ? "MSI" : 1149c067b84SDoug Ambrisko c->intr_mode == VENET_INTR_MODE_ANY ? "any" : 1159c067b84SDoug Ambrisko "unknown", 1169c067b84SDoug Ambrisko c->intr_timer_type == VENET_INTR_TYPE_MIN ? "min" : 1179c067b84SDoug Ambrisko c->intr_timer_type == VENET_INTR_TYPE_IDLE ? "idle" : 1189c067b84SDoug Ambrisko "unknown", 1199c067b84SDoug Ambrisko c->intr_timer_usec, 1209c067b84SDoug Ambrisko c->loop_tag); 1219c067b84SDoug Ambrisko 1229c067b84SDoug Ambrisko /* RSS settings from vNIC */ 1239c067b84SDoug Ambrisko enic->reta_size = ENIC_RSS_RETA_SIZE; 1249c067b84SDoug Ambrisko enic->hash_key_size = ENIC_RSS_HASH_KEY_SIZE; 1259c067b84SDoug Ambrisko enic->flow_type_rss_offloads = 0; 1269c067b84SDoug Ambrisko 1279c067b84SDoug Ambrisko /* Zero offloads if RSS is not enabled */ 1289c067b84SDoug Ambrisko if (!ENIC_SETTING(enic, RSS)) 1299c067b84SDoug Ambrisko enic->flow_type_rss_offloads = 0; 1309c067b84SDoug Ambrisko 1319c067b84SDoug Ambrisko enic->vxlan = ENIC_SETTING(enic, VXLAN) && 1329c067b84SDoug Ambrisko vnic_dev_capable_vxlan(enic->vdev); 1339c067b84SDoug Ambrisko /* 1349c067b84SDoug Ambrisko * Default hardware capabilities. enic_dev_init() may add additional 1359c067b84SDoug Ambrisko * flags if it enables overlay offloads. 1369c067b84SDoug Ambrisko */ 1379c067b84SDoug Ambrisko enic->tx_queue_offload_capa = 0; 1389c067b84SDoug Ambrisko return 0; 1399c067b84SDoug Ambrisko } 1409c067b84SDoug Ambrisko 1419c067b84SDoug Ambrisko int enic_add_vlan(struct enic *enic, u16 vlanid) 1429c067b84SDoug Ambrisko { 1439c067b84SDoug Ambrisko u64 a0 = vlanid, a1 = 0; 1449c067b84SDoug Ambrisko int wait = 1000; 1459c067b84SDoug Ambrisko int err; 1469c067b84SDoug Ambrisko 1479c067b84SDoug Ambrisko err = vnic_dev_cmd(enic->vdev, CMD_VLAN_ADD, &a0, &a1, wait); 1489c067b84SDoug Ambrisko if (err) 1499c067b84SDoug Ambrisko dev_err(enic_get_dev(enic), "Can't add vlan id, %d\n", err); 1509c067b84SDoug Ambrisko 1519c067b84SDoug Ambrisko return err; 1529c067b84SDoug Ambrisko } 1539c067b84SDoug Ambrisko 1549c067b84SDoug Ambrisko int enic_del_vlan(struct enic *enic, u16 vlanid) 1559c067b84SDoug Ambrisko { 1569c067b84SDoug Ambrisko u64 a0 = vlanid, a1 = 0; 1579c067b84SDoug Ambrisko int wait = 1000; 1589c067b84SDoug Ambrisko int err; 1599c067b84SDoug Ambrisko 1609c067b84SDoug Ambrisko err = vnic_dev_cmd(enic->vdev, CMD_VLAN_DEL, &a0, &a1, wait); 1619c067b84SDoug Ambrisko if (err) 1629c067b84SDoug Ambrisko dev_err(enic_get_dev(enic), "Can't delete vlan id, %d\n", err); 1639c067b84SDoug Ambrisko 1649c067b84SDoug Ambrisko return err; 1659c067b84SDoug Ambrisko } 1669c067b84SDoug Ambrisko 1679c067b84SDoug Ambrisko int enic_set_nic_cfg(struct enic *enic, u8 rss_default_cpu, u8 rss_hash_type, 1689c067b84SDoug Ambrisko u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable, u8 tso_ipid_split_en, 1699c067b84SDoug Ambrisko u8 ig_vlan_strip_en) 1709c067b84SDoug Ambrisko { 1719c067b84SDoug Ambrisko enum vnic_devcmd_cmd cmd; 1729c067b84SDoug Ambrisko u64 a0, a1; 1739c067b84SDoug Ambrisko u32 nic_cfg; 1749c067b84SDoug Ambrisko int wait = 1000; 1759c067b84SDoug Ambrisko 1769c067b84SDoug Ambrisko vnic_set_nic_cfg(&nic_cfg, rss_default_cpu, 1779c067b84SDoug Ambrisko rss_hash_type, rss_hash_bits, rss_base_cpu, 1789c067b84SDoug Ambrisko rss_enable, tso_ipid_split_en, ig_vlan_strip_en); 1799c067b84SDoug Ambrisko 1809c067b84SDoug Ambrisko a0 = nic_cfg; 1819c067b84SDoug Ambrisko a1 = 0; 1829c067b84SDoug Ambrisko cmd = enic->nic_cfg_chk ? CMD_NIC_CFG_CHK : CMD_NIC_CFG; 1839c067b84SDoug Ambrisko return vnic_dev_cmd(enic->vdev, cmd, &a0, &a1, wait); 1849c067b84SDoug Ambrisko } 1859c067b84SDoug Ambrisko 1869c067b84SDoug Ambrisko void enic_get_res_counts(struct enic *enic) 1879c067b84SDoug Ambrisko { 1889c067b84SDoug Ambrisko enic->conf_wq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_WQ); 1899c067b84SDoug Ambrisko enic->conf_rq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_RQ); 1909c067b84SDoug Ambrisko enic->conf_cq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_CQ); 1919c067b84SDoug Ambrisko enic->conf_intr_count = vnic_dev_get_res_count(enic->vdev, 1929c067b84SDoug Ambrisko RES_TYPE_INTR_CTRL); 1939c067b84SDoug Ambrisko 1949c067b84SDoug Ambrisko dev_info(enic_get_dev(enic), 1959c067b84SDoug Ambrisko "vNIC resources avail: wq %d rq %d cq %d intr %d\n", 1969c067b84SDoug Ambrisko enic->conf_wq_count, enic->conf_rq_count, 1979c067b84SDoug Ambrisko enic->conf_cq_count, enic->conf_intr_count); 1989c067b84SDoug Ambrisko enic->conf_rq_count = min(enic->conf_rq_count, enic->conf_wq_count); 1999c067b84SDoug Ambrisko enic->conf_wq_count = enic->conf_rq_count; 2009c067b84SDoug Ambrisko enic->conf_cq_count = enic->conf_rq_count + enic->conf_wq_count; 2019c067b84SDoug Ambrisko dev_info(enic_get_dev(enic), 2029c067b84SDoug Ambrisko "vNIC resources iflib: wq %d rq %d cq %d intr %d\n", 2039c067b84SDoug Ambrisko enic->conf_wq_count, enic->conf_rq_count, 2049c067b84SDoug Ambrisko enic->conf_cq_count, enic->conf_intr_count); 2059c067b84SDoug Ambrisko dev_info(enic_get_dev(enic), 2069c067b84SDoug Ambrisko "vNIC resources avail: wq_desc %d rq_desc %d\n", 2079c067b84SDoug Ambrisko enic->config.wq_desc_count, enic->config.rq_desc_count); 2089c067b84SDoug Ambrisko 2099c067b84SDoug Ambrisko enic->wq_count = enic->conf_wq_count; 2109c067b84SDoug Ambrisko enic->rq_count = enic->conf_rq_count; 2119c067b84SDoug Ambrisko enic->cq_count = enic->conf_cq_count; 2129c067b84SDoug Ambrisko } 213