39
39
#include "ibmveth.h"
40
40
41
41
static irqreturn_t ibmveth_interrupt (int irq , void * dev_instance );
42
- static void ibmveth_rxq_harvest_buffer (struct ibmveth_adapter * adapter );
42
+ static void ibmveth_rxq_harvest_buffer (struct ibmveth_adapter * adapter ,
43
+ bool reuse );
43
44
static unsigned long ibmveth_get_desired_dma (struct vio_dev * vdev );
44
45
45
46
static struct kobj_type ktype_veth_pool ;
@@ -226,6 +227,16 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter,
226
227
for (i = 0 ; i < count ; ++ i ) {
227
228
union ibmveth_buf_desc desc ;
228
229
230
+ free_index = pool -> consumer_index ;
231
+ index = pool -> free_map [free_index ];
232
+ skb = NULL ;
233
+
234
+ BUG_ON (index == IBM_VETH_INVALID_MAP );
235
+
236
+ /* are we allocating a new buffer or recycling an old one */
237
+ if (pool -> skbuff [index ])
238
+ goto reuse ;
239
+
229
240
skb = netdev_alloc_skb (adapter -> netdev , pool -> buff_size );
230
241
231
242
if (!skb ) {
@@ -235,64 +246,60 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter,
235
246
break ;
236
247
}
237
248
238
- free_index = pool -> consumer_index ;
239
- pool -> consumer_index ++ ;
240
- if (pool -> consumer_index >= pool -> size )
241
- pool -> consumer_index = 0 ;
242
- index = pool -> free_map [free_index ];
243
-
244
- BUG_ON (index == IBM_VETH_INVALID_MAP );
245
- BUG_ON (pool -> skbuff [index ] != NULL );
246
-
247
249
dma_addr = dma_map_single (& adapter -> vdev -> dev , skb -> data ,
248
250
pool -> buff_size , DMA_FROM_DEVICE );
249
251
250
252
if (dma_mapping_error (& adapter -> vdev -> dev , dma_addr ))
251
253
goto failure ;
252
254
253
- pool -> free_map [free_index ] = IBM_VETH_INVALID_MAP ;
254
255
pool -> dma_addr [index ] = dma_addr ;
255
256
pool -> skbuff [index ] = skb ;
256
257
257
- correlator = ((u64 )pool -> index << 32 ) | index ;
258
- * (u64 * )skb -> data = correlator ;
259
-
260
- desc .fields .flags_len = IBMVETH_BUF_VALID | pool -> buff_size ;
261
- desc .fields .address = dma_addr ;
262
-
263
258
if (rx_flush ) {
264
259
unsigned int len = min (pool -> buff_size ,
265
- adapter -> netdev -> mtu +
266
- IBMVETH_BUFF_OH );
260
+ adapter -> netdev -> mtu +
261
+ IBMVETH_BUFF_OH );
267
262
ibmveth_flush_buffer (skb -> data , len );
268
263
}
264
+ reuse :
265
+ dma_addr = pool -> dma_addr [index ];
266
+ desc .fields .flags_len = IBMVETH_BUF_VALID | pool -> buff_size ;
267
+ desc .fields .address = dma_addr ;
268
+
269
+ correlator = ((u64 )pool -> index << 32 ) | index ;
270
+ * (u64 * )pool -> skbuff [index ]-> data = correlator ;
271
+
269
272
lpar_rc = h_add_logical_lan_buffer (adapter -> vdev -> unit_address ,
270
273
desc .desc );
271
274
272
275
if (lpar_rc != H_SUCCESS ) {
276
+ netdev_warn (adapter -> netdev ,
277
+ "%sadd_logical_lan failed %lu\n" ,
278
+ skb ? "" : "When recycling: " , lpar_rc );
273
279
goto failure ;
274
- } else {
275
- buffers_added ++ ;
276
- adapter -> replenish_add_buff_success ++ ;
277
280
}
281
+
282
+ pool -> free_map [free_index ] = IBM_VETH_INVALID_MAP ;
283
+ pool -> consumer_index ++ ;
284
+ if (pool -> consumer_index >= pool -> size )
285
+ pool -> consumer_index = 0 ;
286
+
287
+ buffers_added ++ ;
288
+ adapter -> replenish_add_buff_success ++ ;
278
289
}
279
290
280
291
mb ();
281
292
atomic_add (buffers_added , & (pool -> available ));
282
293
return ;
283
294
284
295
failure :
285
- pool -> free_map [free_index ] = index ;
286
- pool -> skbuff [index ] = NULL ;
287
- if (pool -> consumer_index == 0 )
288
- pool -> consumer_index = pool -> size - 1 ;
289
- else
290
- pool -> consumer_index -- ;
291
- if (!dma_mapping_error (& adapter -> vdev -> dev , dma_addr ))
296
+
297
+ if (dma_addr && !dma_mapping_error (& adapter -> vdev -> dev , dma_addr ))
292
298
dma_unmap_single (& adapter -> vdev -> dev ,
293
299
pool -> dma_addr [index ], pool -> buff_size ,
294
300
DMA_FROM_DEVICE );
295
- dev_kfree_skb_any (skb );
301
+ dev_kfree_skb_any (pool -> skbuff [index ]);
302
+ pool -> skbuff [index ] = NULL ;
296
303
adapter -> replenish_add_buff_failure ++ ;
297
304
298
305
mb ();
@@ -365,7 +372,7 @@ static void ibmveth_free_buffer_pool(struct ibmveth_adapter *adapter,
365
372
366
373
/* remove a buffer from a pool */
367
374
static void ibmveth_remove_buffer_from_pool (struct ibmveth_adapter * adapter ,
368
- u64 correlator )
375
+ u64 correlator , bool reuse )
369
376
{
370
377
unsigned int pool = correlator >> 32 ;
371
378
unsigned int index = correlator & 0xffffffffUL ;
@@ -376,15 +383,23 @@ static void ibmveth_remove_buffer_from_pool(struct ibmveth_adapter *adapter,
376
383
BUG_ON (index >= adapter -> rx_buff_pool [pool ].size );
377
384
378
385
skb = adapter -> rx_buff_pool [pool ].skbuff [index ];
379
-
380
386
BUG_ON (skb == NULL );
381
387
382
- adapter -> rx_buff_pool [pool ].skbuff [index ] = NULL ;
388
+ /* if we are going to reuse the buffer then keep the pointers around
389
+ * but mark index as available. replenish will see the skb pointer and
390
+ * assume it is to be recycled.
391
+ */
392
+ if (!reuse ) {
393
+ /* remove the skb pointer to mark free. actual freeing is done
394
+ * by upper level networking after gro_recieve
395
+ */
396
+ adapter -> rx_buff_pool [pool ].skbuff [index ] = NULL ;
383
397
384
- dma_unmap_single (& adapter -> vdev -> dev ,
385
- adapter -> rx_buff_pool [pool ].dma_addr [index ],
386
- adapter -> rx_buff_pool [pool ].buff_size ,
387
- DMA_FROM_DEVICE );
398
+ dma_unmap_single (& adapter -> vdev -> dev ,
399
+ adapter -> rx_buff_pool [pool ].dma_addr [index ],
400
+ adapter -> rx_buff_pool [pool ].buff_size ,
401
+ DMA_FROM_DEVICE );
402
+ }
388
403
389
404
free_index = adapter -> rx_buff_pool [pool ].producer_index ;
390
405
adapter -> rx_buff_pool [pool ].producer_index ++ ;
@@ -411,51 +426,13 @@ static inline struct sk_buff *ibmveth_rxq_get_buffer(struct ibmveth_adapter *ada
411
426
return adapter -> rx_buff_pool [pool ].skbuff [index ];
412
427
}
413
428
414
- /* recycle the current buffer on the rx queue */
415
- static int ibmveth_rxq_recycle_buffer ( struct ibmveth_adapter * adapter )
429
+ static void ibmveth_rxq_harvest_buffer ( struct ibmveth_adapter * adapter ,
430
+ bool reuse )
416
431
{
417
- u32 q_index = adapter -> rx_queue .index ;
418
- u64 correlator = adapter -> rx_queue .queue_addr [q_index ].correlator ;
419
- unsigned int pool = correlator >> 32 ;
420
- unsigned int index = correlator & 0xffffffffUL ;
421
- union ibmveth_buf_desc desc ;
422
- unsigned long lpar_rc ;
423
- int ret = 1 ;
424
-
425
- BUG_ON (pool >= IBMVETH_NUM_BUFF_POOLS );
426
- BUG_ON (index >= adapter -> rx_buff_pool [pool ].size );
427
-
428
- if (!adapter -> rx_buff_pool [pool ].active ) {
429
- ibmveth_rxq_harvest_buffer (adapter );
430
- ibmveth_free_buffer_pool (adapter , & adapter -> rx_buff_pool [pool ]);
431
- goto out ;
432
- }
433
-
434
- desc .fields .flags_len = IBMVETH_BUF_VALID |
435
- adapter -> rx_buff_pool [pool ].buff_size ;
436
- desc .fields .address = adapter -> rx_buff_pool [pool ].dma_addr [index ];
437
-
438
- lpar_rc = h_add_logical_lan_buffer (adapter -> vdev -> unit_address , desc .desc );
439
-
440
- if (lpar_rc != H_SUCCESS ) {
441
- netdev_dbg (adapter -> netdev , "h_add_logical_lan_buffer failed "
442
- "during recycle rc=%ld" , lpar_rc );
443
- ibmveth_remove_buffer_from_pool (adapter , adapter -> rx_queue .queue_addr [adapter -> rx_queue .index ].correlator );
444
- ret = 0 ;
445
- }
446
-
447
- if (++ adapter -> rx_queue .index == adapter -> rx_queue .num_slots ) {
448
- adapter -> rx_queue .index = 0 ;
449
- adapter -> rx_queue .toggle = !adapter -> rx_queue .toggle ;
450
- }
451
-
452
- out :
453
- return ret ;
454
- }
432
+ u64 cor ;
455
433
456
- static void ibmveth_rxq_harvest_buffer (struct ibmveth_adapter * adapter )
457
- {
458
- ibmveth_remove_buffer_from_pool (adapter , adapter -> rx_queue .queue_addr [adapter -> rx_queue .index ].correlator );
434
+ cor = adapter -> rx_queue .queue_addr [adapter -> rx_queue .index ].correlator ;
435
+ ibmveth_remove_buffer_from_pool (adapter , cor , reuse );
459
436
460
437
if (++ adapter -> rx_queue .index == adapter -> rx_queue .num_slots ) {
461
438
adapter -> rx_queue .index = 0 ;
@@ -1337,6 +1314,7 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)
1337
1314
unsigned long lpar_rc ;
1338
1315
u16 mss = 0 ;
1339
1316
1317
+ restart_poll :
1340
1318
while (frames_processed < budget ) {
1341
1319
if (!ibmveth_rxq_pending_buffer (adapter ))
1342
1320
break ;
@@ -1346,7 +1324,7 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)
1346
1324
wmb (); /* suggested by larson1 */
1347
1325
adapter -> rx_invalid_buffer ++ ;
1348
1326
netdev_dbg (netdev , "recycling invalid buffer\n" );
1349
- ibmveth_rxq_recycle_buffer (adapter );
1327
+ ibmveth_rxq_harvest_buffer (adapter , true );
1350
1328
} else {
1351
1329
struct sk_buff * skb , * new_skb ;
1352
1330
int length = ibmveth_rxq_frame_length (adapter );
@@ -1379,11 +1357,10 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)
1379
1357
if (rx_flush )
1380
1358
ibmveth_flush_buffer (skb -> data ,
1381
1359
length + offset );
1382
- if (!ibmveth_rxq_recycle_buffer (adapter ))
1383
- kfree_skb (skb );
1360
+ ibmveth_rxq_harvest_buffer (adapter , true);
1384
1361
skb = new_skb ;
1385
1362
} else {
1386
- ibmveth_rxq_harvest_buffer (adapter );
1363
+ ibmveth_rxq_harvest_buffer (adapter , false );
1387
1364
skb_reserve (skb , offset );
1388
1365
}
1389
1366
@@ -1420,24 +1397,25 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)
1420
1397
1421
1398
ibmveth_replenish_task (adapter );
1422
1399
1423
- if (frames_processed < budget ) {
1424
- napi_complete_done ( napi , frames_processed ) ;
1400
+ if (frames_processed == budget )
1401
+ goto out ;
1425
1402
1426
- /* We think we are done - reenable interrupts,
1427
- * then check once more to make sure we are done.
1428
- */
1429
- lpar_rc = h_vio_signal (adapter -> vdev -> unit_address ,
1430
- VIO_IRQ_ENABLE );
1403
+ if (!napi_complete_done (napi , frames_processed ))
1404
+ goto out ;
1431
1405
1432
- BUG_ON (lpar_rc != H_SUCCESS );
1406
+ /* We think we are done - reenable interrupts,
1407
+ * then check once more to make sure we are done.
1408
+ */
1409
+ lpar_rc = h_vio_signal (adapter -> vdev -> unit_address , VIO_IRQ_ENABLE );
1410
+ BUG_ON (lpar_rc != H_SUCCESS );
1433
1411
1434
- if (ibmveth_rxq_pending_buffer (adapter ) &&
1435
- napi_schedule (napi )) {
1436
- lpar_rc = h_vio_signal (adapter -> vdev -> unit_address ,
1437
- VIO_IRQ_DISABLE );
1438
- }
1412
+ if (ibmveth_rxq_pending_buffer (adapter ) && napi_schedule (napi )) {
1413
+ lpar_rc = h_vio_signal (adapter -> vdev -> unit_address ,
1414
+ VIO_IRQ_DISABLE );
1415
+ goto restart_poll ;
1439
1416
}
1440
1417
1418
+ out :
1441
1419
return frames_processed ;
1442
1420
}
1443
1421
0 commit comments