diff --git a/vmkdrivers/src_9/vmklinux_9/vmware/linux_net.c b/vmkdrivers/src_9/vmklinux_9/vmware/linux_net.c index 325e5d1c78f7618aa25001003eebf100dba29137..0caa7b9c3a85e0c7c4612fc71981daf2a731d16e 100644 --- a/vmkdrivers/src_9/vmklinux_9/vmware/linux_net.c +++ b/vmkdrivers/src_9/vmklinux_9/vmware/linux_net.c @@ -427,7 +427,7 @@ int netif_receive_skb(struct sk_buff *skb) { struct net_device *dev = skb->dev; - vmk_NetPoll pollPriv; + vmk_NetPoll netPoll; vmk_Worldlet wdt; struct napi_struct *napi = NULL; vmk_PktHandle *pkt; @@ -440,7 +440,7 @@ netif_receive_skb(struct sk_buff *skb) * skb->napi->rxPktList. */ if (skb->napi == NULL) { - if (unlikely(vmk_WorldletGetCurrent(&wdt, (void **)&pollPriv) != VMK_OK)) { + if (unlikely(vmk_WorldletGetCurrent(&wdt, (void **)&netPoll) != VMK_OK)) { VMK_ASSERT(VMK_FALSE); dev_kfree_skb_any(skb); dev->linnet_rx_dropped++; @@ -449,14 +449,26 @@ netif_receive_skb(struct sk_buff *skb) } else { /* * When the system is in the panic/debug status, the current worldlet is the - * debug worldlet rather than the napi_poll worldlet. In this case, put the + * debug worldlet rather than the NetPollWorldlet. In this case, put the * arrived packets into debugPktList. This list will be processed by * FlushRxBuffers, because netdump/netdebug will bypass the vswitch to read * the packets. */ - if (vmk_NetPollGetCurrent(&pollPriv) == VMK_OK) { - napi = (struct napi_struct *)vmk_NetPollGetPrivate(pollPriv); + if (vmk_NetPollGetCurrent(&netPoll) == VMK_OK) { + void *priv = vmk_NetPollGetPrivate(netPoll); + if (pollpriv_type(priv) == NETPOLL_DEFAULT) { + napi = pollpriv_napi(priv); + } else { + spin_lock(&dev->napi_lock); + list_for_each_entry(napi, &dev->napi_list, dev_list) { + if (napi->dev_poll && test_bit(NAPI_STATE_SCHED, &napi->state)) { + break; + } + } + spin_unlock(&dev->napi_lock); + } } + if (!napi || vmk_SystemCheckState(VMK_SYSTEM_STATE_PANIC)) { pkt = skb->pkt; status = map_skb_to_pkt(skb); @@ -475,7 +487,7 @@ netif_receive_skb(struct sk_buff *skb) } goto done; } else { - VMK_ASSERT(pollPriv != NULL); + VMK_ASSERT(netPoll != NULL); skb->napi = napi; } } @@ -519,10 +531,10 @@ EXPORT_SYMBOL(netif_receive_skb); */ static vmk_Bool -napi_poll(void *ptr) +napi_poll(void *ptr) { VMK_ReturnStatus status = VMK_OK; - struct napi_struct *napi = (struct napi_struct *)ptr; + struct napi_struct *napi = pollpriv_napi(ptr); /* * napi_schedule_prep()/napi_schedule() depend on accurately seeing whether @@ -574,9 +586,9 @@ napi_poll(void *ptr) */ static vmk_Bool -netdev_poll(void *private) +netdev_poll(void *ptr) { - struct net_device *dev = private; + struct net_device *dev = pollpriv_net_device(ptr); vmk_Bool needWork; struct napi_struct *napi; VMK_ReturnStatus status = VMK_OK; @@ -646,7 +658,7 @@ napi_poll_init(struct napi_struct *napi) napi->vector = 0; pollInit.poll = napi_poll; - pollInit.priv = napi; + pollInit.priv = pollpriv_embed(napi, NETPOLL_DEFAULT); if (napi->dev->features & NETIF_F_CNA) { pollInit.deliveryCallback = LinuxCNA_Poll; @@ -730,9 +742,9 @@ netdev_poll_init(struct net_device *dev) dev->napi_wdt_priv.dev = dev; dev->napi_wdt_priv.napi = NULL; - + pollInit.poll = netdev_poll; - pollInit.priv = dev; + pollInit.priv = pollpriv_embed(dev, NETPOLL_BACKUP); if (dev->features & NETIF_F_CNA) { pollInit.deliveryCallback = LinuxCNADev_Poll; @@ -1154,6 +1166,15 @@ skb_gen_pkt_frags(struct sk_buff *skb) } } + /* + * PR 922606: + * Set skb frag ownership to vmkernel, such that vmklinux won't try + * to free those MPNs if the skb needs to be dropped later. Instead, + * the frags/SGs will be freed when the associated pkt is destroyed + * by vmkernel. + */ + vmklnx_set_skb_frags_owner_vmkernel(skb); + /* * Since we removed packet completion in vmklinux, we * cannot support skb chaining anymore. @@ -1445,18 +1466,15 @@ skb_release_data(struct sk_buff *skb) if ((in_irq() || irqs_disabled()) && !vmklnx_is_panic()) { vmk_PktReleaseIRQ(skb->pkt); } else { - vmk_NetPoll pollPriv; - struct napi_struct *napi; + vmk_NetPoll netPoll; /* * Try to queue packets in NAPI's compPktList in order to * release them in batch, but first thoroughly check if we * got called from a napi context (PR #396873). */ - if (vmk_NetPollGetCurrent(&pollPriv) == VMK_OK && - (napi = (struct napi_struct *) vmk_NetPollGetPrivate(pollPriv)) != NULL && - napi->net_poll_type == NETPOLL_DEFAULT) { - vmk_NetPollQueueCompPkt(pollPriv, skb->pkt); + if (vmk_NetPollGetCurrent(&netPoll) == VMK_OK) { + vmk_NetPollQueueCompPkt(netPoll, skb->pkt); } else { vmk_PktRelease(skb->pkt); } @@ -2282,6 +2300,7 @@ vmklnx_netif_set_poll_cna(struct napi_struct *napi) pollInit.priv = napi; pollInit.deliveryCallback = LinuxCNA_Poll; } + pollInit.priv = pollpriv_embed(pollInit.priv, napi->net_poll_type); pollInit.features = VMK_NETPOLL_CUSTOM_DELIVERY_CALLBACK; vmk_NetPollChangeCallback(napi->net_poll, &pollInit); } @@ -6918,7 +6937,7 @@ FlushRxBuffers(void* clientData) { struct net_device* dev = (struct net_device*)clientData; struct napi_struct* napi = NULL; - vmk_NetPoll pollPriv; + vmk_NetPoll netPoll; VMKLNX_DEBUG(1, "client data, now net_device:%p", dev); @@ -6931,7 +6950,7 @@ FlushRxBuffers(void* clientData) * Bypass the vswitch to receive the packets when the system is in the * panic/debug mode. */ - if (vmk_NetPollGetCurrent(&pollPriv) != VMK_OK) { + if (vmk_NetPollGetCurrent(&netPoll) != VMK_OK) { if (debugPktList == NULL) { debugPktList = (vmk_PktList) vmk_HeapAlloc(vmklnxLowHeap, vmk_PktListSizeInBytes);