@@ -50,6 +50,94 @@ int enic_rq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc, u8 type,
50
50
return 0 ;
51
51
}
52
52
53
+ static void enic_rq_set_skb_flags (struct vnic_rq * vrq , u8 type , u32 rss_hash ,
54
+ u8 rss_type , u8 fcoe , u8 fcoe_fc_crc_ok ,
55
+ u8 vlan_stripped , u8 csum_not_calc ,
56
+ u8 tcp_udp_csum_ok , u8 ipv6 , u8 ipv4_csum_ok ,
57
+ u16 vlan_tci , struct sk_buff * skb )
58
+ {
59
+ struct enic * enic = vnic_dev_priv (vrq -> vdev );
60
+ struct net_device * netdev = enic -> netdev ;
61
+ struct enic_rq_stats * rqstats = & enic -> rq [vrq -> index ].stats ;
62
+ bool outer_csum_ok = true, encap = false;
63
+
64
+ if ((netdev -> features & NETIF_F_RXHASH ) && rss_hash && type == 3 ) {
65
+ switch (rss_type ) {
66
+ case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv4 :
67
+ case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6 :
68
+ case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6_EX :
69
+ skb_set_hash (skb , rss_hash , PKT_HASH_TYPE_L4 );
70
+ rqstats -> l4_rss_hash ++ ;
71
+ break ;
72
+ case CQ_ENET_RQ_DESC_RSS_TYPE_IPv4 :
73
+ case CQ_ENET_RQ_DESC_RSS_TYPE_IPv6 :
74
+ case CQ_ENET_RQ_DESC_RSS_TYPE_IPv6_EX :
75
+ skb_set_hash (skb , rss_hash , PKT_HASH_TYPE_L3 );
76
+ rqstats -> l3_rss_hash ++ ;
77
+ break ;
78
+ }
79
+ }
80
+ if (enic -> vxlan .vxlan_udp_port_number ) {
81
+ switch (enic -> vxlan .patch_level ) {
82
+ case 0 :
83
+ if (fcoe ) {
84
+ encap = true;
85
+ outer_csum_ok = fcoe_fc_crc_ok ;
86
+ }
87
+ break ;
88
+ case 2 :
89
+ if (type == 7 && (rss_hash & BIT (0 ))) {
90
+ encap = true;
91
+ outer_csum_ok = (rss_hash & BIT (1 )) &&
92
+ (rss_hash & BIT (2 ));
93
+ }
94
+ break ;
95
+ }
96
+ }
97
+
98
+ /* Hardware does not provide whole packet checksum. It only
99
+ * provides pseudo checksum. Since hw validates the packet
100
+ * checksum but not provide us the checksum value. use
101
+ * CHECSUM_UNNECESSARY.
102
+ *
103
+ * In case of encap pkt tcp_udp_csum_ok/tcp_udp_csum_ok is
104
+ * inner csum_ok. outer_csum_ok is set by hw when outer udp
105
+ * csum is correct or is zero.
106
+ */
107
+ if ((netdev -> features & NETIF_F_RXCSUM ) && !csum_not_calc &&
108
+ tcp_udp_csum_ok && outer_csum_ok && (ipv4_csum_ok || ipv6 )) {
109
+ skb -> ip_summed = CHECKSUM_UNNECESSARY ;
110
+ skb -> csum_level = encap ;
111
+ if (encap )
112
+ rqstats -> csum_unnecessary_encap ++ ;
113
+ else
114
+ rqstats -> csum_unnecessary ++ ;
115
+ }
116
+
117
+ if (vlan_stripped ) {
118
+ __vlan_hwaccel_put_tag (skb , htons (ETH_P_8021Q ), vlan_tci );
119
+ rqstats -> vlan_stripped ++ ;
120
+ }
121
+ }
122
+
123
+ static bool enic_rq_pkt_error (struct vnic_rq * vrq , u8 packet_error , u8 fcs_ok ,
124
+ u16 bytes_written )
125
+ {
126
+ struct enic * enic = vnic_dev_priv (vrq -> vdev );
127
+ struct enic_rq_stats * rqstats = & enic -> rq [vrq -> index ].stats ;
128
+
129
+ if (packet_error ) {
130
+ if (!fcs_ok ) {
131
+ if (bytes_written > 0 )
132
+ rqstats -> bad_fcs ++ ;
133
+ else if (bytes_written == 0 )
134
+ rqstats -> pkt_truncated ++ ;
135
+ }
136
+ return true;
137
+ }
138
+ return false;
139
+ }
140
+
53
141
int enic_rq_alloc_buf (struct vnic_rq * rq )
54
142
{
55
143
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,
113
201
u8 packet_error ;
114
202
u16 q_number , completed_index , bytes_written , vlan_tci , checksum ;
115
203
u32 rss_hash ;
116
- bool outer_csum_ok = true, encap = false;
117
204
118
205
rqstats -> packets ++ ;
119
206
if (skipped ) {
@@ -132,14 +219,7 @@ void enic_rq_indicate_buf(struct vnic_rq *rq, struct cq_desc *cq_desc,
132
219
& tcp , & ipv4_csum_ok , & ipv6 , & ipv4 , & ipv4_fragment ,
133
220
& fcs_ok );
134
221
135
- if (packet_error ) {
136
- if (!fcs_ok ) {
137
- if (bytes_written > 0 )
138
- rqstats -> bad_fcs ++ ;
139
- else if (bytes_written == 0 )
140
- rqstats -> pkt_truncated ++ ;
141
- }
142
-
222
+ if (enic_rq_pkt_error (rq , packet_error , fcs_ok , bytes_written )) {
143
223
dma_unmap_single (& enic -> pdev -> dev , buf -> dma_addr , buf -> len ,
144
224
DMA_FROM_DEVICE );
145
225
dev_kfree_skb_any (skb );
@@ -162,66 +242,10 @@ void enic_rq_indicate_buf(struct vnic_rq *rq, struct cq_desc *cq_desc,
162
242
skb_put (skb , bytes_written );
163
243
skb -> protocol = eth_type_trans (skb , netdev );
164
244
skb_record_rx_queue (skb , q_number );
165
- if ((netdev -> features & NETIF_F_RXHASH ) && rss_hash &&
166
- type == 3 ) {
167
- switch (rss_type ) {
168
- case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv4 :
169
- case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6 :
170
- case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6_EX :
171
- skb_set_hash (skb , rss_hash , PKT_HASH_TYPE_L4 );
172
- rqstats -> l4_rss_hash ++ ;
173
- break ;
174
- case CQ_ENET_RQ_DESC_RSS_TYPE_IPv4 :
175
- case CQ_ENET_RQ_DESC_RSS_TYPE_IPv6 :
176
- case CQ_ENET_RQ_DESC_RSS_TYPE_IPv6_EX :
177
- skb_set_hash (skb , rss_hash , PKT_HASH_TYPE_L3 );
178
- rqstats -> l3_rss_hash ++ ;
179
- break ;
180
- }
181
- }
182
- if (enic -> vxlan .vxlan_udp_port_number ) {
183
- switch (enic -> vxlan .patch_level ) {
184
- case 0 :
185
- if (fcoe ) {
186
- encap = true;
187
- outer_csum_ok = fcoe_fc_crc_ok ;
188
- }
189
- break ;
190
- case 2 :
191
- if (type == 7 &&
192
- (rss_hash & BIT (0 ))) {
193
- encap = true;
194
- outer_csum_ok = (rss_hash & BIT (1 )) &&
195
- (rss_hash & BIT (2 ));
196
- }
197
- break ;
198
- }
199
- }
200
-
201
- /* Hardware does not provide whole packet checksum. It only
202
- * provides pseudo checksum. Since hw validates the packet
203
- * checksum but not provide us the checksum value. use
204
- * CHECSUM_UNNECESSARY.
205
- *
206
- * In case of encap pkt tcp_udp_csum_ok/tcp_udp_csum_ok is
207
- * inner csum_ok. outer_csum_ok is set by hw when outer udp
208
- * csum is correct or is zero.
209
- */
210
- if ((netdev -> features & NETIF_F_RXCSUM ) && !csum_not_calc &&
211
- tcp_udp_csum_ok && outer_csum_ok &&
212
- (ipv4_csum_ok || ipv6 )) {
213
- skb -> ip_summed = CHECKSUM_UNNECESSARY ;
214
- skb -> csum_level = encap ;
215
- if (encap )
216
- rqstats -> csum_unnecessary_encap ++ ;
217
- else
218
- rqstats -> csum_unnecessary ++ ;
219
- }
220
-
221
- if (vlan_stripped ) {
222
- __vlan_hwaccel_put_tag (skb , htons (ETH_P_8021Q ), vlan_tci );
223
- rqstats -> vlan_stripped ++ ;
224
- }
245
+ enic_rq_set_skb_flags (rq , type , rss_hash , rss_type , fcoe ,
246
+ fcoe_fc_crc_ok , vlan_stripped ,
247
+ csum_not_calc , tcp_udp_csum_ok , ipv6 ,
248
+ ipv4_csum_ok , vlan_tci , skb );
225
249
skb_mark_napi_id (skb , & enic -> napi [rq -> index ]);
226
250
if (!(netdev -> features & NETIF_F_GRO ))
227
251
netif_receive_skb (skb );
0 commit comments