[PATCH] solos-pci: don't call vcc->pop() after pclose()
From: Krzysztof Mazur <hidden>
Date: 2012-11-29 12:43:48
Also in:
lkml
Subsystem:
atm, the rest · Maintainers:
Chas Williams, Linus Torvalds
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:quoted
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 <redacted> --- 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