diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/atm/solos-pci.c | 30 |
1 files changed, 28 insertions, 2 deletions
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 4c87dfb01566..c289b6251c19 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c | |||
@@ -132,6 +132,7 @@ static int fpga_tx(struct solos_card *); | |||
132 | static irqreturn_t solos_irq(int irq, void *dev_id); | 132 | static irqreturn_t solos_irq(int irq, void *dev_id); |
133 | static struct atm_vcc* find_vcc(struct atm_dev *dev, short vpi, int vci); | 133 | static struct atm_vcc* find_vcc(struct atm_dev *dev, short vpi, int vci); |
134 | static int list_vccs(int vci); | 134 | static int list_vccs(int vci); |
135 | static void release_vccs(struct atm_dev *dev); | ||
135 | static int atm_init(struct solos_card *); | 136 | static int atm_init(struct solos_card *); |
136 | static void atm_remove(struct solos_card *); | 137 | static void atm_remove(struct solos_card *); |
137 | static int send_command(struct solos_card *card, int dev, const char *buf, size_t size); | 138 | static int send_command(struct solos_card *card, int dev, const char *buf, size_t size); |
@@ -332,7 +333,10 @@ static int process_status(struct solos_card *card, int port, struct sk_buff *skb | |||
332 | str = next_string(skb); | 333 | str = next_string(skb); |
333 | if (!strcmp(str, "Showtime")) | 334 | if (!strcmp(str, "Showtime")) |
334 | state = ATM_PHY_SIG_FOUND; | 335 | state = ATM_PHY_SIG_FOUND; |
335 | else state = ATM_PHY_SIG_LOST; | 336 | else { |
337 | state = ATM_PHY_SIG_LOST; | ||
338 | release_vccs(card->atmdev[port]); | ||
339 | } | ||
336 | 340 | ||
337 | card->atmdev[port]->link_rate = rate_down; | 341 | card->atmdev[port]->link_rate = rate_down; |
338 | card->atmdev[port]->signal = state; | 342 | card->atmdev[port]->signal = state; |
@@ -683,7 +687,7 @@ static int list_vccs(int vci) | |||
683 | vcc->vci); | 687 | vcc->vci); |
684 | } | 688 | } |
685 | } else { | 689 | } else { |
686 | for(i=0; i<32; i++){ | 690 | for(i = 0; i < VCC_HTABLE_SIZE; i++){ |
687 | head = &vcc_hash[i]; | 691 | head = &vcc_hash[i]; |
688 | sk_for_each(s, node, head) { | 692 | sk_for_each(s, node, head) { |
689 | num_found ++; | 693 | num_found ++; |
@@ -699,6 +703,28 @@ static int list_vccs(int vci) | |||
699 | return num_found; | 703 | return num_found; |
700 | } | 704 | } |
701 | 705 | ||
706 | static void release_vccs(struct atm_dev *dev) | ||
707 | { | ||
708 | int i; | ||
709 | |||
710 | write_lock_irq(&vcc_sklist_lock); | ||
711 | for (i = 0; i < VCC_HTABLE_SIZE; i++) { | ||
712 | struct hlist_head *head = &vcc_hash[i]; | ||
713 | struct hlist_node *node, *tmp; | ||
714 | struct sock *s; | ||
715 | struct atm_vcc *vcc; | ||
716 | |||
717 | sk_for_each_safe(s, node, tmp, head) { | ||
718 | vcc = atm_sk(s); | ||
719 | if (vcc->dev == dev) { | ||
720 | vcc_release_async(vcc, -EPIPE); | ||
721 | sk_del_node_init(s); | ||
722 | } | ||
723 | } | ||
724 | } | ||
725 | write_unlock_irq(&vcc_sklist_lock); | ||
726 | } | ||
727 | |||
702 | 728 | ||
703 | static int popen(struct atm_vcc *vcc) | 729 | static int popen(struct atm_vcc *vcc) |
704 | { | 730 | { |