On Thu, Nov 29, 2012 at 11:55:43AM +0000, David Woodhouse wrote: > On Thu, 2012-11-29 at 11:57 +0100, Krzysztof Mazur wrote: > > do we really need to wait here? > > Why don't just do something like that: > > > > tasklet_disable(&card->tlet); > > spin_lock(&card->tx_queue_lock); > > for each skb in queue > > SKB_CB(skb)->vcc = NULL; > > spin_unlock(&card->tx_queue_lock); > > tasklet_enable(&card->tlet); > > > > or if we really want to call vcc->pop() for such skbs: > > > > tasklet_disable(&card->tlet); > > spin_lock(&card->tx_queue_lock); > > for each skb in queue { > > skb_get(skb); > > solos_pop(SKB_CB(skb)->vcc, skb); > > SKB_CB(skb)->vcc = NULL; > > } > > spin_unlock(&card->tx_queue_lock); > > tasklet_enable(&card->tlet); > > Yes, we could certainly remove the packets from the tx_queue first. > > However, in the card->using_dma case there might be a skb for this vcc > *currently* being DMA'd, and we'd still need to wait for that one.
Removing packets from tx_queue is not needed. We can transmit packets also after close. We just can't call vcc->pop() after close, so we can just set SKB_CB(skb)->vcc of such packets to NULL so fpga_tx() won't call vcc->pop(). Maybe I was not precise enough, I'm think that all we need is something like that: -- >8 -- Subject: [PATCH] solos-pci: don't call vcc->pop() after pclose() After atmdev_ops->close() we cannot use vcc->pop() because the vcc may, and probably will be destroyed. We can just set vcc for such frames to NULL because fpga_tx() after completion will call dev_kfree_skb() in that case. Signed-off-by: Krzysztof Mazur <krzys...@podlesie.net> --- drivers/atm/solos-pci.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 9851093..aabe021 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -868,6 +868,19 @@ static void pclose(struct atm_vcc *vcc) struct solos_card *card = vcc->dev->dev_data; struct sk_buff *skb; struct pkt_hdr *header; + unsigned int port; + + tasklet_disable(&card->tlet); + spin_lock(&card->tx_queue_lock); + for (port = 0; port < card->nr_ports; port++) + skb_queue_walk(&card->tx_queue[port], skb) + if (SKB_CB(skb)->vcc == vcc) { + skb_get(skb); + solos_pop(SKB_CB(skb)->vcc, skb); + SKB_CB(skb)->vcc = NULL; + } + spin_unlock(&card->tx_queue_lock); + tasklet_enable(&card->tlet); skb = alloc_skb(sizeof(*header), GFP_ATOMIC); if (!skb) { -- 1.8.0.411.g71a7da8 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/