static void nicvf_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *reg) { struct nicvf *nic = netdev_priv(dev); u64 *p = (u64 *)reg; u64 reg_offset; int mbox, key, stat, q; int i = 0; regs->version = 0; memset(p, 0, NIC_VF_REG_COUNT); p[i++] = nicvf_reg_read(nic, NIC_VNIC_CFG); /* Mailbox registers */ for (mbox = 0; mbox < NIC_PF_VF_MAILBOX_SIZE; mbox++) p[i++] = nicvf_reg_read(nic, NIC_VF_PF_MAILBOX_0_1 | (mbox << 3)); p[i++] = nicvf_reg_read(nic, NIC_VF_INT); p[i++] = nicvf_reg_read(nic, NIC_VF_INT_W1S); p[i++] = nicvf_reg_read(nic, NIC_VF_ENA_W1C); p[i++] = nicvf_reg_read(nic, NIC_VF_ENA_W1S); p[i++] = nicvf_reg_read(nic, NIC_VNIC_RSS_CFG); for (key = 0; key < RSS_HASH_KEY_SIZE; key++) p[i++] = nicvf_reg_read(nic, NIC_VNIC_RSS_KEY_0_4 | (key << 3)); /* Tx/Rx statistics */ for (stat = 0; stat < TX_STATS_ENUM_LAST; stat++) p[i++] = nicvf_reg_read(nic, NIC_VNIC_TX_STAT_0_4 | (stat << 3)); for (i = 0; i < RX_STATS_ENUM_LAST; i++) p[i++] = nicvf_reg_read(nic, NIC_VNIC_RX_STAT_0_13 | (stat << 3)); p[i++] = nicvf_reg_read(nic, NIC_QSET_RQ_GEN_CFG); /* All completion queue's registers */ for (q = 0; q < MAX_CMP_QUEUES_PER_QS; q++) { p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_CFG, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_CFG2, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_THRESH, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_BASE, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_HEAD, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_TAIL, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_DOOR, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_STATUS, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_STATUS2, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_DEBUG, q); } /* All receive queue's registers */ for (q = 0; q < MAX_RCV_QUEUES_PER_QS; q++) { p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RQ_0_7_CFG, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RQ_0_7_STAT_0_1, q); reg_offset = NIC_QSET_RQ_0_7_STAT_0_1 | (1 << 3); p[i++] = nicvf_queue_reg_read(nic, reg_offset, q); } for (q = 0; q < MAX_SND_QUEUES_PER_QS; q++) { p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_CFG, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_THRESH, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_BASE, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_HEAD, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_TAIL, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_DOOR, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_STATUS, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_DEBUG, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_CNM_CHG, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_STAT_0_1, q); reg_offset = NIC_QSET_SQ_0_7_STAT_0_1 | (1 << 3); p[i++] = nicvf_queue_reg_read(nic, reg_offset, q); } for (q = 0; q < MAX_RCV_BUF_DESC_RINGS_PER_QS; q++) { p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_CFG, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_THRESH, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_BASE, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_HEAD, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_TAIL, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_DOOR, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_STATUS0, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_STATUS1, q); reg_offset = NIC_QSET_RBDR_0_1_PREFETCH_STATUS; p[i++] = nicvf_queue_reg_read(nic, reg_offset, q); } }
static int nicvf_set_rss_hash_opts(struct nicvf *nic, struct ethtool_rxnfc *info) { struct nicvf_rss_info *rss = &nic->rss_info; u64 rss_cfg = nicvf_reg_read(nic, NIC_VNIC_RSS_CFG); if (!rss->enable) netdev_err(nic->netdev, "RSS is disabled, hash cannot be set\n"); netdev_info(nic->netdev, "Set RSS flow type = %d, data = %lld\n", info->flow_type, info->data); if (!(info->data & RXH_IP_SRC) || !(info->data & RXH_IP_DST)) return -EINVAL; switch (info->flow_type) { case TCP_V4_FLOW: case TCP_V6_FLOW: switch (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { case 0: rss_cfg &= ~(1ULL << RSS_HASH_TCP); break; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): rss_cfg |= (1ULL << RSS_HASH_TCP); break; default: return -EINVAL; } break; case UDP_V4_FLOW: case UDP_V6_FLOW: switch (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { case 0: rss_cfg &= ~(1ULL << RSS_HASH_UDP); break; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): rss_cfg |= (1ULL << RSS_HASH_UDP); break; default: return -EINVAL; } break; case SCTP_V4_FLOW: case SCTP_V6_FLOW: switch (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { case 0: rss_cfg &= ~(1ULL << RSS_HASH_L4ETC); break; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): rss_cfg |= (1ULL << RSS_HASH_L4ETC); break; default: return -EINVAL; } break; case IPV4_FLOW: case IPV6_FLOW: rss_cfg = RSS_HASH_IP; break; default: return -EINVAL; } nicvf_reg_write(nic, NIC_VNIC_RSS_CFG, rss_cfg); return 0; }
int nicvf_handle_mbx_intr(struct nicvf *nic) { struct nic_mbx mbx; uint64_t *mbx_data = (uint64_t *)&mbx; uint64_t mbx_addr = NIC_VF_PF_MAILBOX_0_1; size_t i; for (i = 0; i < NIC_PF_VF_MAILBOX_SIZE; i++) { *mbx_data = nicvf_reg_read(nic, mbx_addr); mbx_data++; mbx_addr += sizeof(uint64_t); } /* Overwrite the message so we won't receive it again */ nicvf_reg_write(nic, NIC_VF_PF_MAILBOX_0_1, 0x0); nicvf_mbox_log("msg received id=0x%hhx %s (VF%d)", mbx.msg.msg, nicvf_mbox_msg_str(mbx.msg.msg), nic->vf_id); switch (mbx.msg.msg) { case NIC_MBOX_MSG_READY: nic->vf_id = mbx.nic_cfg.vf_id & 0x7F; nic->tns_mode = mbx.nic_cfg.tns_mode & 0x7F; nic->node = mbx.nic_cfg.node_id; nic->sqs_mode = mbx.nic_cfg.sqs_mode; nic->loopback_supported = mbx.nic_cfg.loopback_supported; ether_addr_copy((struct ether_addr *)mbx.nic_cfg.mac_addr, (struct ether_addr *)nic->mac_addr); nic->pf_acked = true; break; case NIC_MBOX_MSG_ACK: nic->pf_acked = true; break; case NIC_MBOX_MSG_NACK: nic->pf_nacked = true; break; case NIC_MBOX_MSG_RSS_SIZE: nic->rss_info.rss_size = mbx.rss_size.ind_tbl_size; nic->pf_acked = true; break; case NIC_MBOX_MSG_BGX_LINK_CHANGE: nic->link_up = mbx.link_status.link_up; nic->duplex = mbx.link_status.duplex; nic->speed = mbx.link_status.speed; nic->pf_acked = true; break; case NIC_MBOX_MSG_ALLOC_SQS: assert_primary(nic); if (mbx.sqs_alloc.qs_count != nic->sqs_count) { nicvf_log_error("Received %" PRIu8 "/%" PRIu8 " secondary qsets", mbx.sqs_alloc.qs_count, nic->sqs_count); abort(); } for (i = 0; i < mbx.sqs_alloc.qs_count; i++) { if (mbx.sqs_alloc.svf[i] != nic->snicvf[i]->vf_id) { nicvf_log_error("Received secondary qset[%zu] " "ID %" PRIu8 " expected %" PRIu8, i, mbx.sqs_alloc.svf[i], nic->snicvf[i]->vf_id); abort(); } } nic->pf_acked = true; break; default: nicvf_log_error("Invalid message from PF, msg_id=0x%hhx %s", mbx.msg.msg, nicvf_mbox_msg_str(mbx.msg.msg)); break; } nicvf_smp_wmb(); return mbx.msg.msg; }