+int
+ionic_lif_set_features(struct ionic_lif *lif)
+{
+ struct ionic_admin_ctx ctx = {
+ .pending_work = true,
+ .cmd.lif_setattr = {
+ .opcode = IONIC_CMD_LIF_SETATTR,
+ .index = lif->index,
+ .attr = IONIC_LIF_ATTR_FEATURES,
+ .features = lif->features,
+ },
+ };
+ int err;
+
+ err = ionic_adminq_post_wait(lif, &ctx);
+ if (err)
+ return err;
+
+ lif->hw_features = (ctx.cmd.lif_setattr.features &
+ ctx.comp.lif_setattr.features);
+
+ if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG)
+ IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG");
+ if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP)
+ IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP");
+ if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER)
+ IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER");
+ if (lif->hw_features & IONIC_ETH_HW_RX_HASH)
+ IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH");
+ if (lif->hw_features & IONIC_ETH_HW_TX_SG)
+ IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG");
+ if (lif->hw_features & IONIC_ETH_HW_RX_SG)
+ IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG");
+ if (lif->hw_features & IONIC_ETH_HW_TX_CSUM)
+ IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM");
+ if (lif->hw_features & IONIC_ETH_HW_RX_CSUM)
+ IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM");
+ if (lif->hw_features & IONIC_ETH_HW_TSO)
+ IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO");
+ if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6)
+ IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6");
+ if (lif->hw_features & IONIC_ETH_HW_TSO_ECN)
+ IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN");
+ if (lif->hw_features & IONIC_ETH_HW_TSO_GRE)
+ IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE");
+ if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM)
+ IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM");
+ if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4)
+ IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4");
+ if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6)
+ IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6");
+ if (lif->hw_features & IONIC_ETH_HW_TSO_UDP)
+ IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP");
+ if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM)
+ IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM");
+
+ return 0;
+}
+
+static int
+ionic_station_set(struct ionic_lif *lif)
+{
+ struct ionic_admin_ctx ctx = {
+ .pending_work = true,
+ .cmd.lif_getattr = {
+ .opcode = IONIC_CMD_LIF_GETATTR,
+ .index = lif->index,
+ .attr = IONIC_LIF_ATTR_MAC,
+ },
+ };
+ int err;
+
+ IONIC_PRINT_CALL();
+
+ err = ionic_adminq_post_wait(lif, &ctx);
+ if (err)
+ return err;
+
+ if (!rte_is_zero_ether_addr((struct rte_ether_addr *)
+ lif->mac_addr)) {
+ IONIC_PRINT(INFO, "deleting station MAC addr");
+
+ ionic_lif_addr_del(lif, lif->mac_addr);
+ }
+
+ memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN);
+
+ if (rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) {
+ IONIC_PRINT(NOTICE, "empty MAC addr (VF?)");
+ return 0;
+ }
+
+ IONIC_PRINT(DEBUG, "adding station MAC addr");
+
+ ionic_lif_addr_add(lif, lif->mac_addr);
+
+ return 0;
+}
+
+static void
+ionic_lif_set_name(struct ionic_lif *lif)
+{
+ struct ionic_admin_ctx ctx = {
+ .pending_work = true,
+ .cmd.lif_setattr = {
+ .opcode = IONIC_CMD_LIF_SETATTR,
+ .index = lif->index,
+ .attr = IONIC_LIF_ATTR_NAME,
+ },
+ };
+
+ snprintf(ctx.cmd.lif_setattr.name, sizeof(ctx.cmd.lif_setattr.name),
+ "%d", lif->port_id);
+
+ ionic_adminq_post_wait(lif, &ctx);
+}
+