From: sunil.kovv...@gmail.com Date: Mon, 7 Mar 2016 13:05:56 +0530 > From: Sunil Goutham <sgout...@cavium.com> > > Instead of calling get_page() for every receive buffer carved out > of page, set page's usage count at the end, to reduce no of atomic > calls. > > Signed-off-by: Sunil Goutham <sgout...@cavium.com> > --- > drivers/net/ethernet/cavium/thunder/nic.h | 1 + > drivers/net/ethernet/cavium/thunder/nicvf_queues.c | 31 ++++++++++++++----- > 2 files changed, 24 insertions(+), 8 deletions(-) > > diff --git a/drivers/net/ethernet/cavium/thunder/nic.h > b/drivers/net/ethernet/cavium/thunder/nic.h > index 00cc915..5628aea 100644 > --- a/drivers/net/ethernet/cavium/thunder/nic.h > +++ b/drivers/net/ethernet/cavium/thunder/nic.h > @@ -285,6 +285,7 @@ struct nicvf { > u32 speed; > struct page *rb_page; > u32 rb_page_offset; > + u16 rb_pageref; > bool rb_alloc_fail; > bool rb_work_scheduled; > struct delayed_work rbdr_work; > diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c > b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c > index 0dd1abf..fa05e34 100644 > --- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c > +++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c > @@ -18,6 +18,15 @@ > #include "q_struct.h" > #include "nicvf_queues.h" > > +static void nicvf_get_page(struct nicvf *nic) > +{ > + if (!nic->rb_pageref || !nic->rb_page) > + return; > + > + atomic_add(nic->rb_pageref, &nic->rb_page->_count); > + nic->rb_pageref = 0; > +} > + > /* Poll a register for a specific value */ > static int nicvf_poll_reg(struct nicvf *nic, int qidx, > u64 reg, int bit_pos, int bits, int val) > @@ -81,16 +90,15 @@ static inline int nicvf_alloc_rcv_buffer(struct nicvf > *nic, gfp_t gfp, > int order = (PAGE_SIZE <= 4096) ? PAGE_ALLOC_COSTLY_ORDER : 0; > > /* Check if request can be accomodated in previous allocated page */ > - if (nic->rb_page) { > - if ((nic->rb_page_offset + buf_len + buf_len) > > - (PAGE_SIZE << order)) { > - nic->rb_page = NULL; > - } else { > - nic->rb_page_offset += buf_len; > - get_page(nic->rb_page); > - } > + if (nic->rb_page && > + ((nic->rb_page_offset + buf_len) < (PAGE_SIZE << order))) { > + nic->rb_pageref++; > + goto ret; > }
I do not see how this can sanely work. By deferring the atomic increment of the page count, you create a window of time during which the consumer can release the page and prematurely free it. I'm not applying this, as it looks extremely buggy. Sorry.