@@ -61,11 +61,21 @@ MODULE_VERSION(NTB_NETDEV_VER);
61
61
MODULE_LICENSE ("Dual BSD/GPL" );
62
62
MODULE_AUTHOR ("Intel Corporation" );
63
63
64
+ /* Time in usecs for tx resource reaper */
65
+ static unsigned int tx_time = 1 ;
66
+
67
+ /* Number of descriptors to free before resuming tx */
68
+ static unsigned int tx_start = 10 ;
69
+
70
+ /* Number of descriptors still available before stop upper layer tx */
71
+ static unsigned int tx_stop = 5 ;
72
+
64
73
struct ntb_netdev {
65
74
struct list_head list ;
66
75
struct pci_dev * pdev ;
67
76
struct net_device * ndev ;
68
77
struct ntb_transport_qp * qp ;
78
+ struct timer_list tx_timer ;
69
79
};
70
80
71
81
#define NTB_TX_TIMEOUT_MS 1000
@@ -136,11 +146,42 @@ static void ntb_netdev_rx_handler(struct ntb_transport_qp *qp, void *qp_data,
136
146
}
137
147
}
138
148
149
+ static int __ntb_netdev_maybe_stop_tx (struct net_device * netdev ,
150
+ struct ntb_transport_qp * qp , int size )
151
+ {
152
+ struct ntb_netdev * dev = netdev_priv (netdev );
153
+
154
+ netif_stop_queue (netdev );
155
+ /* Make sure to see the latest value of ntb_transport_tx_free_entry()
156
+ * since the queue was last started.
157
+ */
158
+ smp_mb ();
159
+
160
+ if (likely (ntb_transport_tx_free_entry (qp ) < size )) {
161
+ mod_timer (& dev -> tx_timer , jiffies + usecs_to_jiffies (tx_time ));
162
+ return - EBUSY ;
163
+ }
164
+
165
+ netif_start_queue (netdev );
166
+ return 0 ;
167
+ }
168
+
169
+ static int ntb_netdev_maybe_stop_tx (struct net_device * ndev ,
170
+ struct ntb_transport_qp * qp , int size )
171
+ {
172
+ if (netif_queue_stopped (ndev ) ||
173
+ (ntb_transport_tx_free_entry (qp ) >= size ))
174
+ return 0 ;
175
+
176
+ return __ntb_netdev_maybe_stop_tx (ndev , qp , size );
177
+ }
178
+
139
179
static void ntb_netdev_tx_handler (struct ntb_transport_qp * qp , void * qp_data ,
140
180
void * data , int len )
141
181
{
142
182
struct net_device * ndev = qp_data ;
143
183
struct sk_buff * skb ;
184
+ struct ntb_netdev * dev = netdev_priv (ndev );
144
185
145
186
skb = data ;
146
187
if (!skb || !ndev )
@@ -155,6 +196,15 @@ static void ntb_netdev_tx_handler(struct ntb_transport_qp *qp, void *qp_data,
155
196
}
156
197
157
198
dev_kfree_skb (skb );
199
+
200
+ if (ntb_transport_tx_free_entry (dev -> qp ) >= tx_start ) {
201
+ /* Make sure anybody stopping the queue after this sees the new
202
+ * value of ntb_transport_tx_free_entry()
203
+ */
204
+ smp_mb ();
205
+ if (netif_queue_stopped (ndev ))
206
+ netif_wake_queue (ndev );
207
+ }
158
208
}
159
209
160
210
static netdev_tx_t ntb_netdev_start_xmit (struct sk_buff * skb ,
@@ -163,10 +213,15 @@ static netdev_tx_t ntb_netdev_start_xmit(struct sk_buff *skb,
163
213
struct ntb_netdev * dev = netdev_priv (ndev );
164
214
int rc ;
165
215
216
+ ntb_netdev_maybe_stop_tx (ndev , dev -> qp , tx_stop );
217
+
166
218
rc = ntb_transport_tx_enqueue (dev -> qp , skb , skb -> data , skb -> len );
167
219
if (rc )
168
220
goto err ;
169
221
222
+ /* check for next submit */
223
+ ntb_netdev_maybe_stop_tx (ndev , dev -> qp , tx_stop );
224
+
170
225
return NETDEV_TX_OK ;
171
226
172
227
err :
@@ -175,6 +230,23 @@ static netdev_tx_t ntb_netdev_start_xmit(struct sk_buff *skb,
175
230
return NETDEV_TX_BUSY ;
176
231
}
177
232
233
+ static void ntb_netdev_tx_timer (unsigned long data )
234
+ {
235
+ struct net_device * ndev = (struct net_device * )data ;
236
+ struct ntb_netdev * dev = netdev_priv (ndev );
237
+
238
+ if (ntb_transport_tx_free_entry (dev -> qp ) < tx_stop ) {
239
+ mod_timer (& dev -> tx_timer , jiffies + msecs_to_jiffies (tx_time ));
240
+ } else {
241
+ /* Make sure anybody stopping the queue after this sees the new
242
+ * value of ntb_transport_tx_free_entry()
243
+ */
244
+ smp_mb ();
245
+ if (netif_queue_stopped (ndev ))
246
+ netif_wake_queue (ndev );
247
+ }
248
+ }
249
+
178
250
static int ntb_netdev_open (struct net_device * ndev )
179
251
{
180
252
struct ntb_netdev * dev = netdev_priv (ndev );
@@ -197,8 +269,11 @@ static int ntb_netdev_open(struct net_device *ndev)
197
269
}
198
270
}
199
271
272
+ setup_timer (& dev -> tx_timer , ntb_netdev_tx_timer , (unsigned long )ndev );
273
+
200
274
netif_carrier_off (ndev );
201
275
ntb_transport_link_up (dev -> qp );
276
+ netif_start_queue (ndev );
202
277
203
278
return 0 ;
204
279
@@ -219,6 +294,8 @@ static int ntb_netdev_close(struct net_device *ndev)
219
294
while ((skb = ntb_transport_rx_remove (dev -> qp , & len )))
220
295
dev_kfree_skb (skb );
221
296
297
+ del_timer_sync (& dev -> tx_timer );
298
+
222
299
return 0 ;
223
300
}
224
301
0 commit comments