Skip to content

Commit b71441b

Browse files
committed
Merge branch 'ibmveth-rr-performance'
Nick Child says: ==================== ibmveth RR performance This patchset aims to increase the ibmveth drivers small packet request response rate. These 2 patches address: 1. NAPI rescheduling technique 2. Driver-side processing of small packets Testing over several netperf tcp_rr connections, we saw a 30% increase in transactions per second. No regressions were observed in other workloads. ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 7e1d512 + b5381a5 commit b71441b

File tree

1 file changed

+75
-97
lines changed

1 file changed

+75
-97
lines changed

drivers/net/ethernet/ibm/ibmveth.c

Lines changed: 75 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@
3939
#include "ibmveth.h"
4040

4141
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);
4344
static unsigned long ibmveth_get_desired_dma(struct vio_dev *vdev);
4445

4546
static struct kobj_type ktype_veth_pool;
@@ -226,6 +227,16 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter,
226227
for (i = 0; i < count; ++i) {
227228
union ibmveth_buf_desc desc;
228229

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+
229240
skb = netdev_alloc_skb(adapter->netdev, pool->buff_size);
230241

231242
if (!skb) {
@@ -235,64 +246,60 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter,
235246
break;
236247
}
237248

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-
247249
dma_addr = dma_map_single(&adapter->vdev->dev, skb->data,
248250
pool->buff_size, DMA_FROM_DEVICE);
249251

250252
if (dma_mapping_error(&adapter->vdev->dev, dma_addr))
251253
goto failure;
252254

253-
pool->free_map[free_index] = IBM_VETH_INVALID_MAP;
254255
pool->dma_addr[index] = dma_addr;
255256
pool->skbuff[index] = skb;
256257

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-
263258
if (rx_flush) {
264259
unsigned int len = min(pool->buff_size,
265-
adapter->netdev->mtu +
266-
IBMVETH_BUFF_OH);
260+
adapter->netdev->mtu +
261+
IBMVETH_BUFF_OH);
267262
ibmveth_flush_buffer(skb->data, len);
268263
}
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+
269272
lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address,
270273
desc.desc);
271274

272275
if (lpar_rc != H_SUCCESS) {
276+
netdev_warn(adapter->netdev,
277+
"%sadd_logical_lan failed %lu\n",
278+
skb ? "" : "When recycling: ", lpar_rc);
273279
goto failure;
274-
} else {
275-
buffers_added++;
276-
adapter->replenish_add_buff_success++;
277280
}
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++;
278289
}
279290

280291
mb();
281292
atomic_add(buffers_added, &(pool->available));
282293
return;
283294

284295
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))
292298
dma_unmap_single(&adapter->vdev->dev,
293299
pool->dma_addr[index], pool->buff_size,
294300
DMA_FROM_DEVICE);
295-
dev_kfree_skb_any(skb);
301+
dev_kfree_skb_any(pool->skbuff[index]);
302+
pool->skbuff[index] = NULL;
296303
adapter->replenish_add_buff_failure++;
297304

298305
mb();
@@ -365,7 +372,7 @@ static void ibmveth_free_buffer_pool(struct ibmveth_adapter *adapter,
365372

366373
/* remove a buffer from a pool */
367374
static void ibmveth_remove_buffer_from_pool(struct ibmveth_adapter *adapter,
368-
u64 correlator)
375+
u64 correlator, bool reuse)
369376
{
370377
unsigned int pool = correlator >> 32;
371378
unsigned int index = correlator & 0xffffffffUL;
@@ -376,15 +383,23 @@ static void ibmveth_remove_buffer_from_pool(struct ibmveth_adapter *adapter,
376383
BUG_ON(index >= adapter->rx_buff_pool[pool].size);
377384

378385
skb = adapter->rx_buff_pool[pool].skbuff[index];
379-
380386
BUG_ON(skb == NULL);
381387

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;
383397

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+
}
388403

389404
free_index = adapter->rx_buff_pool[pool].producer_index;
390405
adapter->rx_buff_pool[pool].producer_index++;
@@ -411,51 +426,13 @@ static inline struct sk_buff *ibmveth_rxq_get_buffer(struct ibmveth_adapter *ada
411426
return adapter->rx_buff_pool[pool].skbuff[index];
412427
}
413428

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)
416431
{
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;
455433

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);
459436

460437
if (++adapter->rx_queue.index == adapter->rx_queue.num_slots) {
461438
adapter->rx_queue.index = 0;
@@ -1337,6 +1314,7 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)
13371314
unsigned long lpar_rc;
13381315
u16 mss = 0;
13391316

1317+
restart_poll:
13401318
while (frames_processed < budget) {
13411319
if (!ibmveth_rxq_pending_buffer(adapter))
13421320
break;
@@ -1346,7 +1324,7 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)
13461324
wmb(); /* suggested by larson1 */
13471325
adapter->rx_invalid_buffer++;
13481326
netdev_dbg(netdev, "recycling invalid buffer\n");
1349-
ibmveth_rxq_recycle_buffer(adapter);
1327+
ibmveth_rxq_harvest_buffer(adapter, true);
13501328
} else {
13511329
struct sk_buff *skb, *new_skb;
13521330
int length = ibmveth_rxq_frame_length(adapter);
@@ -1379,11 +1357,10 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)
13791357
if (rx_flush)
13801358
ibmveth_flush_buffer(skb->data,
13811359
length + offset);
1382-
if (!ibmveth_rxq_recycle_buffer(adapter))
1383-
kfree_skb(skb);
1360+
ibmveth_rxq_harvest_buffer(adapter, true);
13841361
skb = new_skb;
13851362
} else {
1386-
ibmveth_rxq_harvest_buffer(adapter);
1363+
ibmveth_rxq_harvest_buffer(adapter, false);
13871364
skb_reserve(skb, offset);
13881365
}
13891366

@@ -1420,24 +1397,25 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)
14201397

14211398
ibmveth_replenish_task(adapter);
14221399

1423-
if (frames_processed < budget) {
1424-
napi_complete_done(napi, frames_processed);
1400+
if (frames_processed == budget)
1401+
goto out;
14251402

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;
14311405

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);
14331411

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;
14391416
}
14401417

1418+
out:
14411419
return frames_processed;
14421420
}
14431421

0 commit comments

Comments
 (0)