/* add a page worth of packets to a freelist */ NDIS_STATUS shared_lb_addpage( IN shared_info_t *shared, IN struct lbfree *l, IN BOOLEAN piomode, page_t *page, IN uint ipp, IN uint lbdatasz ) { struct lbuf *lb; char *va; ULONG pa; uint i; ASSERT(l->npages < (ROUNDUP(l->total, ipp) / ipp)); /* add it to the page list */ l->pages[l->npages] = *page; l->npages++; /* * Split each page into one or more LBUFSZ chunks, * link them together, and put each on the freelist. */ va = page->va; pa = page->pa.LowPart; for (i = 0; i < ipp; i++) { char *vbuf = NULL; uint pbuf = 0; lb = (struct lbuf*)(va + lbdatasz); if (lbdatasz) { vbuf = va; pbuf = pa; } /* initialize lbuf fields */ lb->link = lb->next = NULL; lb->head = lb->data = lb->tail = vbuf; lb->end = (uchar*)lb; lb->len = 0; lb->pa = piomode? 0xdeadbeef: pbuf; lb->p = NULL; lb->l = l; /* put it on the freelist */ shared_lb_put(shared, l, lb); if (lbdatasz) { va += LBUFSZ; pa += LBUFSZ; } else va += sizeof(struct lbuf); } return (NDIS_STATUS_SUCCESS); }
/* bust apart and free an rx ndis packet and buffer descriptor and lbuf */ void shared_free_ndispacket( IN shared_info_t *shared, IN ND_PKT *p ) { struct lbuf *lb; /* pick the associated lbuf off the ndis packet */ lb = (struct lbuf*) NEXTP(p); ASSERT(lb); ASSERT(lb->p == p); NEXTP(p) = NULL; lb->p = NULL; /* free the ndis packet and buffer descriptors */ shared_free_pkt(p); /* put our lbuf back on the freelist */ shared_lb_put(shared, lb->l, lb); }
static void BCMFASTPATH bcm_rpc_tp_pktfree(rpc_tp_info_t * rpcb, rpc_buf_t *b, bool send) { uint32 free_cnt = 0; #if defined(NDIS) struct lbuf *lb = (struct lbuf*)b; struct lbuf *next; ASSERT(rpcb); ASSERT(lb != NULL); do { next = lb->next; lb->next = NULL; ASSERT(lb->p == NULL); shared_lb_put(rpcb->sh, lb->l, lb); free_cnt++; lb = next; } while (lb); #else struct sk_buff *skb = (struct sk_buff*)b, *next; #if defined(CTFPOOL) next = skb; while (next != NULL) { next = next->next; free_cnt++; } PKTFREE(rpcb->osh, skb, FALSE); #else while (skb) { next = skb->next; if (skb->destructor) { /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if destructor exists */ dev_kfree_skb_any(skb); } else { /* can free immediately (even in_irq()) if destructor does not exist */ dev_kfree_skb(skb); } skb = next; free_cnt++; } #endif /* defined(CTFPOOL) */ RPC_TP_LOCK(rpcb); rpcb->buf_cnt_inuse -= free_cnt; if (rpcb->rxflowctrl && (rpcb->buf_cnt_inuse < RPCRX_WM_LO)) { rpcb->rxflowctrl = FALSE; RPC_TP_ERR(("%s, rxflowctrl change to %d\n", __FUNCTION__, rpcb->rxflowctrl)); dbus_flowctrl_rx(rpcb->bus, FALSE); } RPC_TP_UNLOCK(rpcb); #endif /* NDIS */ }