]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/atm/solos-pci.c
solos-pci: Fix race condition in tasklet RX handling
[net-next-2.6.git] / drivers / atm / solos-pci.c
index ded76c4c9f4f1599d6b8087eff93d9247e4f8526..f916ddf63938a03444c2ad6e4d8a6b63c46212aa 100644 (file)
@@ -383,7 +383,7 @@ static int process_status(struct solos_card *card, int port, struct sk_buff *skb
 
        /* Anything but 'Showtime' is down */
        if (strcmp(state_str, "Showtime")) {
-               card->atmdev[port]->signal = ATM_PHY_SIG_LOST;
+               atm_dev_signal_change(card->atmdev[port], ATM_PHY_SIG_LOST);
                release_vccs(card->atmdev[port]);
                dev_info(&card->dev->dev, "Port %d: %s\n", port, state_str);
                return 0;
@@ -401,7 +401,7 @@ static int process_status(struct solos_card *card, int port, struct sk_buff *skb
                 snr[0]?", SNR ":"", snr, attn[0]?", Attn ":"", attn);
        
        card->atmdev[port]->link_rate = rate_down / 424;
-       card->atmdev[port]->signal = ATM_PHY_SIG_FOUND;
+       atm_dev_signal_change(card->atmdev[port], ATM_PHY_SIG_FOUND);
 
        return 0;
 }
@@ -781,7 +781,8 @@ static struct atm_vcc *find_vcc(struct atm_dev *dev, short vpi, int vci)
        sk_for_each(s, node, head) {
                vcc = atm_sk(s);
                if (vcc->dev == dev && vcc->vci == vci &&
-                   vcc->vpi == vpi && vcc->qos.rxtp.traffic_class != ATM_NONE)
+                   vcc->vpi == vpi && vcc->qos.rxtp.traffic_class != ATM_NONE &&
+                   test_bit(ATM_VF_READY, &vcc->flags))
                        goto out;
        }
        vcc = NULL;
@@ -907,6 +908,10 @@ static void pclose(struct atm_vcc *vcc)
        clear_bit(ATM_VF_ADDR, &vcc->flags);
        clear_bit(ATM_VF_READY, &vcc->flags);
 
+       /* Hold up vcc_destroy_socket() (our caller) until solos_bh() in the
+          tasklet has finished processing any incoming packets (and, more to
+          the point, using the vcc pointer). */
+       tasklet_unlock_wait(&card->tlet);
        return;
 }
 
@@ -1246,7 +1251,7 @@ static int atm_init(struct solos_card *card)
                card->atmdev[i]->ci_range.vci_bits = 16;
                card->atmdev[i]->dev_data = card;
                card->atmdev[i]->phy_data = (void *)(unsigned long)i;
-               card->atmdev[i]->signal = ATM_PHY_SIG_UNKNOWN;
+               atm_dev_signal_change(card->atmdev[i], ATM_PHY_SIG_UNKNOWN);
 
                skb = alloc_skb(sizeof(*header), GFP_ATOMIC);
                if (!skb) {