@@ -21,14 +21,26 @@ static void enic_intr_update_pkt_size(struct vnic_rx_bytes_counter *pkt_size,
2121 pkt_size -> small_pkt_bytes_cnt += pkt_len ;
2222}
2323
24- int enic_rq_service (struct vnic_dev * vdev , struct cq_desc * cq_desc , u8 type ,
25- u16 q_number , u16 completed_index , void * opaque )
24+ static void enic_rq_cq_desc_dec (struct cq_enet_rq_desc * desc , u8 * type ,
25+ u8 * color , u16 * q_number , u16 * completed_index )
2626{
27- struct enic * enic = vnic_dev_priv (vdev );
28-
29- vnic_rq_service (& enic -> rq [q_number ].vrq , cq_desc , completed_index ,
30- VNIC_RQ_RETURN_DESC , enic_rq_indicate_buf , opaque );
31- return 0 ;
27+ /* type_color is the last field for all cq structs */
28+ u8 type_color = desc -> type_color ;
29+
30+ /* Make sure color bit is read from desc *before* other fields
31+ * are read from desc. Hardware guarantees color bit is last
32+ * bit (byte) written. Adding the rmb() prevents the compiler
33+ * and/or CPU from reordering the reads which would potentially
34+ * result in reading stale values.
35+ */
36+ rmb ();
37+
38+ * q_number = le16_to_cpu (desc -> q_number_rss_type_flags ) &
39+ CQ_DESC_Q_NUM_MASK ;
40+ * completed_index = le16_to_cpu (desc -> completed_index_flags ) &
41+ CQ_DESC_COMP_NDX_MASK ;
42+ * color = (type_color >> CQ_DESC_COLOR_SHIFT ) & CQ_DESC_COLOR_MASK ;
43+ * type = type_color & CQ_DESC_TYPE_MASK ;
3244}
3345
3446static void enic_rq_set_skb_flags (struct vnic_rq * vrq , u8 type , u32 rss_hash ,
@@ -101,10 +113,9 @@ static void enic_rq_set_skb_flags(struct vnic_rq *vrq, u8 type, u32 rss_hash,
101113 }
102114}
103115
104- static void cq_enet_rq_desc_dec (struct cq_enet_rq_desc * desc , u8 * type ,
105- u8 * color , u16 * q_number , u16 * completed_index ,
106- u8 * ingress_port , u8 * fcoe , u8 * eop , u8 * sop ,
107- u8 * rss_type , u8 * csum_not_calc , u32 * rss_hash ,
116+ static void cq_enet_rq_desc_dec (struct cq_enet_rq_desc * desc , u8 * ingress_port ,
117+ u8 * fcoe , u8 * eop , u8 * sop , u8 * rss_type ,
118+ u8 * csum_not_calc , u32 * rss_hash ,
108119 u16 * bytes_written , u8 * packet_error ,
109120 u8 * vlan_stripped , u16 * vlan_tci ,
110121 u16 * checksum , u8 * fcoe_sof ,
@@ -117,9 +128,6 @@ static void cq_enet_rq_desc_dec(struct cq_enet_rq_desc *desc, u8 *type,
117128 u16 q_number_rss_type_flags ;
118129 u16 bytes_written_flags ;
119130
120- cq_desc_dec ((struct cq_desc * )desc , type ,
121- color , q_number , completed_index );
122-
123131 completed_index_flags = le16_to_cpu (desc -> completed_index_flags );
124132 q_number_rss_type_flags =
125133 le16_to_cpu (desc -> q_number_rss_type_flags );
@@ -249,37 +257,33 @@ void enic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf)
249257 buf -> os_buf = NULL ;
250258}
251259
252- void enic_rq_indicate_buf (struct vnic_rq * rq , struct cq_desc * cq_desc ,
253- struct vnic_rq_buf * buf , int skipped , void * opaque )
260+ static void enic_rq_indicate_buf (struct enic * enic , struct vnic_rq * rq ,
261+ struct vnic_rq_buf * buf ,
262+ struct cq_enet_rq_desc * cq_desc , u8 type ,
263+ u16 q_number , u16 completed_index )
254264{
255- struct enic * enic = vnic_dev_priv (rq -> vdev );
256265 struct sk_buff * skb ;
257266 struct vnic_cq * cq = & enic -> cq [enic_cq_rq (enic , rq -> index )];
258267 struct enic_rq_stats * rqstats = & enic -> rq [rq -> index ].stats ;
259268 struct napi_struct * napi ;
260269
261- u8 type , color , eop , sop , ingress_port , vlan_stripped ;
270+ u8 eop , sop , ingress_port , vlan_stripped ;
262271 u8 fcoe , fcoe_sof , fcoe_fc_crc_ok , fcoe_enc_error , fcoe_eof ;
263272 u8 tcp_udp_csum_ok , udp , tcp , ipv4_csum_ok ;
264273 u8 ipv6 , ipv4 , ipv4_fragment , fcs_ok , rss_type , csum_not_calc ;
265274 u8 packet_error ;
266- u16 q_number , completed_index , bytes_written , vlan_tci , checksum ;
275+ u16 bytes_written , vlan_tci , checksum ;
267276 u32 rss_hash ;
268277
269278 rqstats -> packets ++ ;
270- if (skipped ) {
271- rqstats -> desc_skip ++ ;
272- return ;
273- }
274279
275- cq_enet_rq_desc_dec ((struct cq_enet_rq_desc * )cq_desc , & type , & color ,
276- & q_number , & completed_index , & ingress_port , & fcoe ,
277- & eop , & sop , & rss_type , & csum_not_calc , & rss_hash ,
278- & bytes_written , & packet_error , & vlan_stripped ,
279- & vlan_tci , & checksum , & fcoe_sof , & fcoe_fc_crc_ok ,
280- & fcoe_enc_error , & fcoe_eof , & tcp_udp_csum_ok , & udp ,
281- & tcp , & ipv4_csum_ok , & ipv6 , & ipv4 , & ipv4_fragment ,
282- & fcs_ok );
280+ cq_enet_rq_desc_dec (cq_desc , & ingress_port ,
281+ & fcoe , & eop , & sop , & rss_type , & csum_not_calc ,
282+ & rss_hash , & bytes_written , & packet_error ,
283+ & vlan_stripped , & vlan_tci , & checksum , & fcoe_sof ,
284+ & fcoe_fc_crc_ok , & fcoe_enc_error , & fcoe_eof ,
285+ & tcp_udp_csum_ok , & udp , & tcp , & ipv4_csum_ok , & ipv6 ,
286+ & ipv4 , & ipv4_fragment , & fcs_ok );
283287
284288 if (enic_rq_pkt_error (rq , packet_error , fcs_ok , bytes_written ))
285289 return ;
@@ -324,3 +328,56 @@ void enic_rq_indicate_buf(struct vnic_rq *rq, struct cq_desc *cq_desc,
324328 rqstats -> pkt_truncated ++ ;
325329 }
326330}
331+
332+ static void enic_rq_service (struct enic * enic , struct cq_enet_rq_desc * cq_desc ,
333+ u8 type , u16 q_number , u16 completed_index )
334+ {
335+ struct enic_rq_stats * rqstats = & enic -> rq [q_number ].stats ;
336+ struct vnic_rq * vrq = & enic -> rq [q_number ].vrq ;
337+ struct vnic_rq_buf * vrq_buf = vrq -> to_clean ;
338+ int skipped ;
339+
340+ while (1 ) {
341+ skipped = (vrq_buf -> index != completed_index );
342+ if (!skipped )
343+ enic_rq_indicate_buf (enic , vrq , vrq_buf , cq_desc , type ,
344+ q_number , completed_index );
345+ else
346+ rqstats -> desc_skip ++ ;
347+
348+ vrq -> ring .desc_avail ++ ;
349+ vrq -> to_clean = vrq_buf -> next ;
350+ vrq_buf = vrq_buf -> next ;
351+ if (!skipped )
352+ break ;
353+ }
354+ }
355+
356+ unsigned int enic_rq_cq_service (struct enic * enic , unsigned int cq_index ,
357+ unsigned int work_to_do )
358+ {
359+ struct vnic_cq * cq = & enic -> cq [cq_index ];
360+ struct cq_enet_rq_desc * cq_desc ;
361+ u16 q_number , completed_index ;
362+ unsigned int work_done = 0 ;
363+ u8 type , color ;
364+
365+ cq_desc = (struct cq_enet_rq_desc * )vnic_cq_to_clean (cq );
366+
367+ enic_rq_cq_desc_dec (cq_desc , & type , & color , & q_number ,
368+ & completed_index );
369+
370+ while (color != cq -> last_color ) {
371+ enic_rq_service (enic , cq_desc , type , q_number , completed_index );
372+ vnic_cq_inc_to_clean (cq );
373+
374+ if (++ work_done >= work_to_do )
375+ break ;
376+
377+ cq_desc = (struct cq_enet_rq_desc * )vnic_cq_to_clean (cq );
378+ enic_rq_cq_desc_dec (cq_desc , & type , & color , & q_number ,
379+ & completed_index );
380+ }
381+
382+ return work_done ;
383+ }
0 commit comments