@@ -51,6 +51,7 @@ struct vdevice_status {
51
51
struct usb_shadow {
52
52
struct xenusb_urb_request req ;
53
53
struct urb * urb ;
54
+ bool in_flight ;
54
55
};
55
56
56
57
struct xenhcd_info {
@@ -720,6 +721,12 @@ static void xenhcd_gnttab_done(struct xenhcd_info *info, unsigned int id)
720
721
int nr_segs = 0 ;
721
722
int i ;
722
723
724
+ if (!shadow -> in_flight ) {
725
+ xenhcd_set_error (info , "Illegal request id" );
726
+ return ;
727
+ }
728
+ shadow -> in_flight = false;
729
+
723
730
nr_segs = shadow -> req .nr_buffer_segs ;
724
731
725
732
if (xenusb_pipeisoc (shadow -> req .pipe ))
@@ -803,6 +810,7 @@ static int xenhcd_do_request(struct xenhcd_info *info, struct urb_priv *urbp)
803
810
804
811
info -> urb_ring .req_prod_pvt ++ ;
805
812
info -> shadow [id ].urb = urb ;
813
+ info -> shadow [id ].in_flight = true;
806
814
807
815
RING_PUSH_REQUESTS_AND_CHECK_NOTIFY (& info -> urb_ring , notify );
808
816
if (notify )
@@ -931,10 +939,27 @@ static int xenhcd_unlink_urb(struct xenhcd_info *info, struct urb_priv *urbp)
931
939
return ret ;
932
940
}
933
941
934
- static int xenhcd_urb_request_done (struct xenhcd_info * info )
942
+ static void xenhcd_res_to_urb (struct xenhcd_info * info ,
943
+ struct xenusb_urb_response * res , struct urb * urb )
944
+ {
945
+ if (unlikely (!urb ))
946
+ return ;
947
+
948
+ if (res -> actual_length > urb -> transfer_buffer_length )
949
+ urb -> actual_length = urb -> transfer_buffer_length ;
950
+ else if (res -> actual_length < 0 )
951
+ urb -> actual_length = 0 ;
952
+ else
953
+ urb -> actual_length = res -> actual_length ;
954
+ urb -> error_count = res -> error_count ;
955
+ urb -> start_frame = res -> start_frame ;
956
+ xenhcd_giveback_urb (info , urb , res -> status );
957
+ }
958
+
959
+ static int xenhcd_urb_request_done (struct xenhcd_info * info ,
960
+ unsigned int * eoiflag )
935
961
{
936
962
struct xenusb_urb_response res ;
937
- struct urb * urb ;
938
963
RING_IDX i , rp ;
939
964
__u16 id ;
940
965
int more_to_do = 0 ;
@@ -961,16 +986,12 @@ static int xenhcd_urb_request_done(struct xenhcd_info *info)
961
986
xenhcd_gnttab_done (info , id );
962
987
if (info -> error )
963
988
goto err ;
964
- urb = info -> shadow [id ].urb ;
965
- if (likely (urb )) {
966
- urb -> actual_length = res .actual_length ;
967
- urb -> error_count = res .error_count ;
968
- urb -> start_frame = res .start_frame ;
969
- xenhcd_giveback_urb (info , urb , res .status );
970
- }
989
+ xenhcd_res_to_urb (info , & res , info -> shadow [id ].urb );
971
990
}
972
991
973
992
xenhcd_add_id_to_freelist (info , id );
993
+
994
+ * eoiflag = 0 ;
974
995
}
975
996
info -> urb_ring .rsp_cons = i ;
976
997
@@ -988,7 +1009,7 @@ static int xenhcd_urb_request_done(struct xenhcd_info *info)
988
1009
return 0 ;
989
1010
}
990
1011
991
- static int xenhcd_conn_notify (struct xenhcd_info * info )
1012
+ static int xenhcd_conn_notify (struct xenhcd_info * info , unsigned int * eoiflag )
992
1013
{
993
1014
struct xenusb_conn_response res ;
994
1015
struct xenusb_conn_request * req ;
@@ -1033,6 +1054,8 @@ static int xenhcd_conn_notify(struct xenhcd_info *info)
1033
1054
info -> conn_ring .req_prod_pvt );
1034
1055
req -> id = id ;
1035
1056
info -> conn_ring .req_prod_pvt ++ ;
1057
+
1058
+ * eoiflag = 0 ;
1036
1059
}
1037
1060
1038
1061
if (rc != info -> conn_ring .req_prod_pvt )
@@ -1055,14 +1078,19 @@ static int xenhcd_conn_notify(struct xenhcd_info *info)
1055
1078
static irqreturn_t xenhcd_int (int irq , void * dev_id )
1056
1079
{
1057
1080
struct xenhcd_info * info = (struct xenhcd_info * )dev_id ;
1081
+ unsigned int eoiflag = XEN_EOI_FLAG_SPURIOUS ;
1058
1082
1059
- if (unlikely (info -> error ))
1083
+ if (unlikely (info -> error )) {
1084
+ xen_irq_lateeoi (irq , XEN_EOI_FLAG_SPURIOUS );
1060
1085
return IRQ_HANDLED ;
1086
+ }
1061
1087
1062
- while (xenhcd_urb_request_done (info ) | xenhcd_conn_notify (info ))
1088
+ while (xenhcd_urb_request_done (info , & eoiflag ) |
1089
+ xenhcd_conn_notify (info , & eoiflag ))
1063
1090
/* Yield point for this unbounded loop. */
1064
1091
cond_resched ();
1065
1092
1093
+ xen_irq_lateeoi (irq , eoiflag );
1066
1094
return IRQ_HANDLED ;
1067
1095
}
1068
1096
@@ -1139,9 +1167,9 @@ static int xenhcd_setup_rings(struct xenbus_device *dev,
1139
1167
goto fail ;
1140
1168
}
1141
1169
1142
- err = bind_evtchn_to_irq (info -> evtchn );
1170
+ err = bind_evtchn_to_irq_lateeoi (info -> evtchn );
1143
1171
if (err <= 0 ) {
1144
- xenbus_dev_fatal (dev , err , "bind_evtchn_to_irq " );
1172
+ xenbus_dev_fatal (dev , err , "bind_evtchn_to_irq_lateeoi " );
1145
1173
goto fail ;
1146
1174
}
1147
1175
@@ -1494,6 +1522,7 @@ static struct usb_hcd *xenhcd_create_hcd(struct xenbus_device *dev)
1494
1522
for (i = 0 ; i < XENUSB_URB_RING_SIZE ; i ++ ) {
1495
1523
info -> shadow [i ].req .id = i + 1 ;
1496
1524
info -> shadow [i ].urb = NULL ;
1525
+ info -> shadow [i ].in_flight = false;
1497
1526
}
1498
1527
info -> shadow [XENUSB_URB_RING_SIZE - 1 ].req .id = 0x0fff ;
1499
1528
0 commit comments