mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-03 21:45:08 -04:00
enic: Simplify RX handler function
Split up RX handler functions in preparation for moving to a page pool based implementation. No functional changes. Co-developed-by: Nelson Escobar <neescoba@cisco.com> Signed-off-by: Nelson Escobar <neescoba@cisco.com> Co-developed-by: Satish Kharat <satishkh@cisco.com> Signed-off-by: Satish Kharat <satishkh@cisco.com> Signed-off-by: John Daley <johndale@cisco.com> Link: https://patch.msgid.link/20250205235416.25410-3-johndale@cisco.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
fe57762c64
commit
eab3726347
@@ -50,6 +50,94 @@ int enic_rq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc, u8 type,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void enic_rq_set_skb_flags(struct vnic_rq *vrq, u8 type, u32 rss_hash,
|
||||
u8 rss_type, u8 fcoe, u8 fcoe_fc_crc_ok,
|
||||
u8 vlan_stripped, u8 csum_not_calc,
|
||||
u8 tcp_udp_csum_ok, u8 ipv6, u8 ipv4_csum_ok,
|
||||
u16 vlan_tci, struct sk_buff *skb)
|
||||
{
|
||||
struct enic *enic = vnic_dev_priv(vrq->vdev);
|
||||
struct net_device *netdev = enic->netdev;
|
||||
struct enic_rq_stats *rqstats = &enic->rq[vrq->index].stats;
|
||||
bool outer_csum_ok = true, encap = false;
|
||||
|
||||
if ((netdev->features & NETIF_F_RXHASH) && rss_hash && type == 3) {
|
||||
switch (rss_type) {
|
||||
case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv4:
|
||||
case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6:
|
||||
case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6_EX:
|
||||
skb_set_hash(skb, rss_hash, PKT_HASH_TYPE_L4);
|
||||
rqstats->l4_rss_hash++;
|
||||
break;
|
||||
case CQ_ENET_RQ_DESC_RSS_TYPE_IPv4:
|
||||
case CQ_ENET_RQ_DESC_RSS_TYPE_IPv6:
|
||||
case CQ_ENET_RQ_DESC_RSS_TYPE_IPv6_EX:
|
||||
skb_set_hash(skb, rss_hash, PKT_HASH_TYPE_L3);
|
||||
rqstats->l3_rss_hash++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (enic->vxlan.vxlan_udp_port_number) {
|
||||
switch (enic->vxlan.patch_level) {
|
||||
case 0:
|
||||
if (fcoe) {
|
||||
encap = true;
|
||||
outer_csum_ok = fcoe_fc_crc_ok;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (type == 7 && (rss_hash & BIT(0))) {
|
||||
encap = true;
|
||||
outer_csum_ok = (rss_hash & BIT(1)) &&
|
||||
(rss_hash & BIT(2));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Hardware does not provide whole packet checksum. It only
|
||||
* provides pseudo checksum. Since hw validates the packet
|
||||
* checksum but not provide us the checksum value. use
|
||||
* CHECSUM_UNNECESSARY.
|
||||
*
|
||||
* In case of encap pkt tcp_udp_csum_ok/tcp_udp_csum_ok is
|
||||
* inner csum_ok. outer_csum_ok is set by hw when outer udp
|
||||
* csum is correct or is zero.
|
||||
*/
|
||||
if ((netdev->features & NETIF_F_RXCSUM) && !csum_not_calc &&
|
||||
tcp_udp_csum_ok && outer_csum_ok && (ipv4_csum_ok || ipv6)) {
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
skb->csum_level = encap;
|
||||
if (encap)
|
||||
rqstats->csum_unnecessary_encap++;
|
||||
else
|
||||
rqstats->csum_unnecessary++;
|
||||
}
|
||||
|
||||
if (vlan_stripped) {
|
||||
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci);
|
||||
rqstats->vlan_stripped++;
|
||||
}
|
||||
}
|
||||
|
||||
static bool enic_rq_pkt_error(struct vnic_rq *vrq, u8 packet_error, u8 fcs_ok,
|
||||
u16 bytes_written)
|
||||
{
|
||||
struct enic *enic = vnic_dev_priv(vrq->vdev);
|
||||
struct enic_rq_stats *rqstats = &enic->rq[vrq->index].stats;
|
||||
|
||||
if (packet_error) {
|
||||
if (!fcs_ok) {
|
||||
if (bytes_written > 0)
|
||||
rqstats->bad_fcs++;
|
||||
else if (bytes_written == 0)
|
||||
rqstats->pkt_truncated++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int enic_rq_alloc_buf(struct vnic_rq *rq)
|
||||
{
|
||||
struct enic *enic = vnic_dev_priv(rq->vdev);
|
||||
@@ -113,7 +201,6 @@ void enic_rq_indicate_buf(struct vnic_rq *rq, struct cq_desc *cq_desc,
|
||||
u8 packet_error;
|
||||
u16 q_number, completed_index, bytes_written, vlan_tci, checksum;
|
||||
u32 rss_hash;
|
||||
bool outer_csum_ok = true, encap = false;
|
||||
|
||||
rqstats->packets++;
|
||||
if (skipped) {
|
||||
@@ -132,14 +219,7 @@ void enic_rq_indicate_buf(struct vnic_rq *rq, struct cq_desc *cq_desc,
|
||||
&tcp, &ipv4_csum_ok, &ipv6, &ipv4, &ipv4_fragment,
|
||||
&fcs_ok);
|
||||
|
||||
if (packet_error) {
|
||||
if (!fcs_ok) {
|
||||
if (bytes_written > 0)
|
||||
rqstats->bad_fcs++;
|
||||
else if (bytes_written == 0)
|
||||
rqstats->pkt_truncated++;
|
||||
}
|
||||
|
||||
if (enic_rq_pkt_error(rq, packet_error, fcs_ok, bytes_written)) {
|
||||
dma_unmap_single(&enic->pdev->dev, buf->dma_addr, buf->len,
|
||||
DMA_FROM_DEVICE);
|
||||
dev_kfree_skb_any(skb);
|
||||
@@ -162,66 +242,10 @@ void enic_rq_indicate_buf(struct vnic_rq *rq, struct cq_desc *cq_desc,
|
||||
skb_put(skb, bytes_written);
|
||||
skb->protocol = eth_type_trans(skb, netdev);
|
||||
skb_record_rx_queue(skb, q_number);
|
||||
if ((netdev->features & NETIF_F_RXHASH) && rss_hash &&
|
||||
type == 3) {
|
||||
switch (rss_type) {
|
||||
case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv4:
|
||||
case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6:
|
||||
case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6_EX:
|
||||
skb_set_hash(skb, rss_hash, PKT_HASH_TYPE_L4);
|
||||
rqstats->l4_rss_hash++;
|
||||
break;
|
||||
case CQ_ENET_RQ_DESC_RSS_TYPE_IPv4:
|
||||
case CQ_ENET_RQ_DESC_RSS_TYPE_IPv6:
|
||||
case CQ_ENET_RQ_DESC_RSS_TYPE_IPv6_EX:
|
||||
skb_set_hash(skb, rss_hash, PKT_HASH_TYPE_L3);
|
||||
rqstats->l3_rss_hash++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (enic->vxlan.vxlan_udp_port_number) {
|
||||
switch (enic->vxlan.patch_level) {
|
||||
case 0:
|
||||
if (fcoe) {
|
||||
encap = true;
|
||||
outer_csum_ok = fcoe_fc_crc_ok;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (type == 7 &&
|
||||
(rss_hash & BIT(0))) {
|
||||
encap = true;
|
||||
outer_csum_ok = (rss_hash & BIT(1)) &&
|
||||
(rss_hash & BIT(2));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Hardware does not provide whole packet checksum. It only
|
||||
* provides pseudo checksum. Since hw validates the packet
|
||||
* checksum but not provide us the checksum value. use
|
||||
* CHECSUM_UNNECESSARY.
|
||||
*
|
||||
* In case of encap pkt tcp_udp_csum_ok/tcp_udp_csum_ok is
|
||||
* inner csum_ok. outer_csum_ok is set by hw when outer udp
|
||||
* csum is correct or is zero.
|
||||
*/
|
||||
if ((netdev->features & NETIF_F_RXCSUM) && !csum_not_calc &&
|
||||
tcp_udp_csum_ok && outer_csum_ok &&
|
||||
(ipv4_csum_ok || ipv6)) {
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
skb->csum_level = encap;
|
||||
if (encap)
|
||||
rqstats->csum_unnecessary_encap++;
|
||||
else
|
||||
rqstats->csum_unnecessary++;
|
||||
}
|
||||
|
||||
if (vlan_stripped) {
|
||||
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci);
|
||||
rqstats->vlan_stripped++;
|
||||
}
|
||||
enic_rq_set_skb_flags(rq, type, rss_hash, rss_type, fcoe,
|
||||
fcoe_fc_crc_ok, vlan_stripped,
|
||||
csum_not_calc, tcp_udp_csum_ok, ipv6,
|
||||
ipv4_csum_ok, vlan_tci, skb);
|
||||
skb_mark_napi_id(skb, &enic->napi[rq->index]);
|
||||
if (!(netdev->features & NETIF_F_GRO))
|
||||
netif_receive_skb(skb);
|
||||
|
||||
Reference in New Issue
Block a user