Re: [PATCH] net: thunderx: rework mac addresses list to u64 array
On Thu, Apr 05, 2018 at 09:07:49AM -0700, Vadim Lomovtsev wrote: > > > > > + mc_list = kmalloc(sizeof(*mc_list) + > > > + sizeof(u64) * > > > netdev_mc_count(netdev), > > > + GFP_ATOMIC); > > > > kmalloc_array(), please. > > In this case it would require two memory allocation calls to kmalloc() for > xcast_addr_list struct and to kmalloc_array() for 'mc' addresses, becasue of > different data types and so two null-ptr checks .. this is what I'd like get > rid off. > > My idea of this was to keep number of array elements and themselves within the > same memory block/page to reduce number of memory allocation requests, number > of allocated pages/blocks and avoid possible memory fragmentation (however, I > believe > the latter is already handled at the mm layer). Indeed, lets keep it as-is.
Re: [PATCH] net: thunderx: rework mac addresses list to u64 array
On Thu, Apr 05, 2018 at 09:07:49AM -0700, Vadim Lomovtsev wrote: > > > > > + mc_list = kmalloc(sizeof(*mc_list) + > > > + sizeof(u64) * > > > netdev_mc_count(netdev), > > > + GFP_ATOMIC); > > > > kmalloc_array(), please. > > In this case it would require two memory allocation calls to kmalloc() for > xcast_addr_list struct and to kmalloc_array() for 'mc' addresses, becasue of > different data types and so two null-ptr checks .. this is what I'd like get > rid off. > > My idea of this was to keep number of array elements and themselves within the > same memory block/page to reduce number of memory allocation requests, number > of allocated pages/blocks and avoid possible memory fragmentation (however, I > believe > the latter is already handled at the mm layer). Indeed, lets keep it as-is.
Re: [PATCH] net: thunderx: rework mac addresses list to u64 array
Hi Christoph, Thank you for your feedback and time. On Thu, Apr 05, 2018 at 08:07:48AM -0700, Christoph Hellwig wrote: > > struct xcast_addr_list { > > - struct list_head list; > > int count; > > + u64 mc[0]; > > Please use the standard C99 syntax here: > > u64 mc[]; Ok, will update. > > > + mc_list = kmalloc(sizeof(*mc_list) + > > + sizeof(u64) * > > netdev_mc_count(netdev), > > + GFP_ATOMIC); > > kmalloc_array(), please. In this case it would require two memory allocation calls to kmalloc() for xcast_addr_list struct and to kmalloc_array() for 'mc' addresses, becasue of different data types and so two null-ptr checks .. this is what I'd like get rid off. My idea of this was to keep number of array elements and themselves within the same memory block/page to reduce number of memory allocation requests, number of allocated pages/blocks and avoid possible memory fragmentation (however, I believe the latter is already handled at the mm layer). WBR, Vadim
Re: [PATCH] net: thunderx: rework mac addresses list to u64 array
Hi Christoph, Thank you for your feedback and time. On Thu, Apr 05, 2018 at 08:07:48AM -0700, Christoph Hellwig wrote: > > struct xcast_addr_list { > > - struct list_head list; > > int count; > > + u64 mc[0]; > > Please use the standard C99 syntax here: > > u64 mc[]; Ok, will update. > > > + mc_list = kmalloc(sizeof(*mc_list) + > > + sizeof(u64) * > > netdev_mc_count(netdev), > > + GFP_ATOMIC); > > kmalloc_array(), please. In this case it would require two memory allocation calls to kmalloc() for xcast_addr_list struct and to kmalloc_array() for 'mc' addresses, becasue of different data types and so two null-ptr checks .. this is what I'd like get rid off. My idea of this was to keep number of array elements and themselves within the same memory block/page to reduce number of memory allocation requests, number of allocated pages/blocks and avoid possible memory fragmentation (however, I believe the latter is already handled at the mm layer). WBR, Vadim
Re: [PATCH] net: thunderx: rework mac addresses list to u64 array
> struct xcast_addr_list { > - struct list_head list; > int count; > + u64 mc[0]; Please use the standard C99 syntax here: u64 mc[]; > + mc_list = kmalloc(sizeof(*mc_list) + > + sizeof(u64) * > netdev_mc_count(netdev), > + GFP_ATOMIC); kmalloc_array(), please.
Re: [PATCH] net: thunderx: rework mac addresses list to u64 array
> struct xcast_addr_list { > - struct list_head list; > int count; > + u64 mc[0]; Please use the standard C99 syntax here: u64 mc[]; > + mc_list = kmalloc(sizeof(*mc_list) + > + sizeof(u64) * > netdev_mc_count(netdev), > + GFP_ATOMIC); kmalloc_array(), please.
Re: [PATCH] net: thunderx: rework mac addresses list to u64 array
[correct Roberts' address] On Thu, Apr 05, 2018 at 07:57:56AM -0700, Vadim Lomovtsev wrote: > From: Vadim Lomovtsev> > It is too expensive to pass u64 values via linked list, instead > allocate array for them by overall number of mac addresses from netdev. > > This eventually removes multiple kmalloc() calls, aviod memory > fragmentation and allow to put single null check on kmalloc > return value in order to prevent a potential null pointer dereference. > > Addresses-Coverity-ID: 1467429 ("Dereference null return value") > Fixes: 37c3347eb247 ("net: thunderx: add ndo_set_rx_mode callback > implementation for VF") > Signed-off-by: Vadim Lomovtsev > --- > drivers/net/ethernet/cavium/thunder/nic.h| 7 +- > drivers/net/ethernet/cavium/thunder/nicvf_main.c | 28 > +--- > 2 files changed, 11 insertions(+), 24 deletions(-) > > diff --git a/drivers/net/ethernet/cavium/thunder/nic.h > b/drivers/net/ethernet/cavium/thunder/nic.h > index 5fc46c5a4f36..da052159f014 100644 > --- a/drivers/net/ethernet/cavium/thunder/nic.h > +++ b/drivers/net/ethernet/cavium/thunder/nic.h > @@ -265,14 +265,9 @@ struct nicvf_drv_stats { > > struct cavium_ptp; > > -struct xcast_addr { > - struct list_head list; > - u64 addr; > -}; > - > struct xcast_addr_list { > - struct list_head list; > int count; > + u64 mc[0]; > }; > > struct nicvf_work { > diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c > b/drivers/net/ethernet/cavium/thunder/nicvf_main.c > index 1e9a31fef729..a26d8bc92e01 100644 > --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c > +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c > @@ -1929,7 +1929,7 @@ static void nicvf_set_rx_mode_task(struct work_struct > *work_arg) > work.work); > struct nicvf *nic = container_of(vf_work, struct nicvf, rx_mode_work); > union nic_mbx mbx = {}; > - struct xcast_addr *xaddr, *next; > + u8 idx = 0; > > if (!vf_work) > return; > @@ -1956,16 +1956,10 @@ static void nicvf_set_rx_mode_task(struct work_struct > *work_arg) > /* check if we have any specific MACs to be added to PF DMAC filter */ > if (vf_work->mc) { > /* now go through kernel list of MACs and add them one by one */ > - list_for_each_entry_safe(xaddr, next, > - _work->mc->list, list) { > + for (idx = 0; idx < vf_work->mc->count; idx++) { > mbx.xcast.msg = NIC_MBOX_MSG_ADD_MCAST; > - mbx.xcast.data.mac = xaddr->addr; > + mbx.xcast.data.mac = vf_work->mc->mc[idx]; > nicvf_send_msg_to_pf(nic, ); > - > - /* after receiving ACK from PF release memory */ > - list_del(>list); > - kfree(xaddr); > - vf_work->mc->count--; > } > kfree(vf_work->mc); > } > @@ -1996,17 +1990,15 @@ static void nicvf_set_rx_mode(struct net_device > *netdev) > mode |= BGX_XCAST_MCAST_FILTER; > /* here we need to copy mc addrs */ > if (netdev_mc_count(netdev)) { > - struct xcast_addr *xaddr; > - > - mc_list = kmalloc(sizeof(*mc_list), GFP_ATOMIC); > - INIT_LIST_HEAD(_list->list); > + mc_list = kmalloc(sizeof(*mc_list) + > + sizeof(u64) * > netdev_mc_count(netdev), > + GFP_ATOMIC); > + if (unlikely(!mc_list)) > + return; > + mc_list->count = 0; > netdev_hw_addr_list_for_each(ha, >mc) { > - xaddr = kmalloc(sizeof(*xaddr), > - GFP_ATOMIC); > - xaddr->addr = > + mc_list->mc[mc_list->count] = > ether_addr_to_u64(ha->addr); > - list_add_tail(>list, > - _list->list); > mc_list->count++; > } > } > -- > 2.14.3 >
Re: [PATCH] net: thunderx: rework mac addresses list to u64 array
[correct Roberts' address] On Thu, Apr 05, 2018 at 07:57:56AM -0700, Vadim Lomovtsev wrote: > From: Vadim Lomovtsev > > It is too expensive to pass u64 values via linked list, instead > allocate array for them by overall number of mac addresses from netdev. > > This eventually removes multiple kmalloc() calls, aviod memory > fragmentation and allow to put single null check on kmalloc > return value in order to prevent a potential null pointer dereference. > > Addresses-Coverity-ID: 1467429 ("Dereference null return value") > Fixes: 37c3347eb247 ("net: thunderx: add ndo_set_rx_mode callback > implementation for VF") > Signed-off-by: Vadim Lomovtsev > --- > drivers/net/ethernet/cavium/thunder/nic.h| 7 +- > drivers/net/ethernet/cavium/thunder/nicvf_main.c | 28 > +--- > 2 files changed, 11 insertions(+), 24 deletions(-) > > diff --git a/drivers/net/ethernet/cavium/thunder/nic.h > b/drivers/net/ethernet/cavium/thunder/nic.h > index 5fc46c5a4f36..da052159f014 100644 > --- a/drivers/net/ethernet/cavium/thunder/nic.h > +++ b/drivers/net/ethernet/cavium/thunder/nic.h > @@ -265,14 +265,9 @@ struct nicvf_drv_stats { > > struct cavium_ptp; > > -struct xcast_addr { > - struct list_head list; > - u64 addr; > -}; > - > struct xcast_addr_list { > - struct list_head list; > int count; > + u64 mc[0]; > }; > > struct nicvf_work { > diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c > b/drivers/net/ethernet/cavium/thunder/nicvf_main.c > index 1e9a31fef729..a26d8bc92e01 100644 > --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c > +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c > @@ -1929,7 +1929,7 @@ static void nicvf_set_rx_mode_task(struct work_struct > *work_arg) > work.work); > struct nicvf *nic = container_of(vf_work, struct nicvf, rx_mode_work); > union nic_mbx mbx = {}; > - struct xcast_addr *xaddr, *next; > + u8 idx = 0; > > if (!vf_work) > return; > @@ -1956,16 +1956,10 @@ static void nicvf_set_rx_mode_task(struct work_struct > *work_arg) > /* check if we have any specific MACs to be added to PF DMAC filter */ > if (vf_work->mc) { > /* now go through kernel list of MACs and add them one by one */ > - list_for_each_entry_safe(xaddr, next, > - _work->mc->list, list) { > + for (idx = 0; idx < vf_work->mc->count; idx++) { > mbx.xcast.msg = NIC_MBOX_MSG_ADD_MCAST; > - mbx.xcast.data.mac = xaddr->addr; > + mbx.xcast.data.mac = vf_work->mc->mc[idx]; > nicvf_send_msg_to_pf(nic, ); > - > - /* after receiving ACK from PF release memory */ > - list_del(>list); > - kfree(xaddr); > - vf_work->mc->count--; > } > kfree(vf_work->mc); > } > @@ -1996,17 +1990,15 @@ static void nicvf_set_rx_mode(struct net_device > *netdev) > mode |= BGX_XCAST_MCAST_FILTER; > /* here we need to copy mc addrs */ > if (netdev_mc_count(netdev)) { > - struct xcast_addr *xaddr; > - > - mc_list = kmalloc(sizeof(*mc_list), GFP_ATOMIC); > - INIT_LIST_HEAD(_list->list); > + mc_list = kmalloc(sizeof(*mc_list) + > + sizeof(u64) * > netdev_mc_count(netdev), > + GFP_ATOMIC); > + if (unlikely(!mc_list)) > + return; > + mc_list->count = 0; > netdev_hw_addr_list_for_each(ha, >mc) { > - xaddr = kmalloc(sizeof(*xaddr), > - GFP_ATOMIC); > - xaddr->addr = > + mc_list->mc[mc_list->count] = > ether_addr_to_u64(ha->addr); > - list_add_tail(>list, > - _list->list); > mc_list->count++; > } > } > -- > 2.14.3 >