]>
Commit | Line | Data |
---|---|---|
38f540a8 GKH |
1 | From stable-bounces@linux.kernel.org Thu Oct 18 03:05:05 2007 |
2 | From: Karsten Keil <kkeil@suse.de> | |
3 | Date: Thu, 18 Oct 2007 03:04:31 -0700 | |
4 | Subject: i4l: fix random freezes with AVM B1 drivers | |
5 | To: torvalds@linux-foundation.org | |
6 | Cc: akpm@linux-foundation.org, stable@kernel.org, kkeil@suse.de | |
7 | Message-ID: <200710181004.l9IA4VVS005629@imap1.linux-foundation.org> | |
8 | ||
9 | ||
10 | From: Karsten Keil <kkeil@suse.de> | |
11 | ||
12 | patch 9713d9e650045f7f2afd81d58a068827be306993 in mainline. | |
13 | ||
14 | This fix the same issue which was debbuged for the C4 controller for the B1 | |
15 | versions. | |
16 | ||
17 | The capilib_ function modify or traverse a linked list without locking. | |
18 | ||
19 | This patch extends the existing locking to the calls of these function to | |
20 | prevent access to a list which is in the middle of a modification. | |
21 | ||
22 | Signed-off-by: Karsten Keil <kkeil@suse.de> | |
23 | Signed-off-by: Andrew Morton <akpm@linux-foundation.org> | |
24 | Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> | |
25 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
26 | ||
27 | --- | |
28 | drivers/isdn/hardware/avm/b1.c | 28 +++++++++++++--------------- | |
29 | 1 file changed, 13 insertions(+), 15 deletions(-) | |
30 | ||
31 | --- a/drivers/isdn/hardware/avm/b1.c | |
32 | +++ b/drivers/isdn/hardware/avm/b1.c | |
33 | @@ -321,12 +321,15 @@ void b1_reset_ctr(struct capi_ctr *ctrl) | |
34 | avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); | |
35 | avmcard *card = cinfo->card; | |
36 | unsigned int port = card->port; | |
37 | + unsigned long flags; | |
38 | ||
39 | b1_reset(port); | |
40 | b1_reset(port); | |
41 | ||
42 | memset(cinfo->version, 0, sizeof(cinfo->version)); | |
43 | + spin_lock_irqsave(&card->lock, flags); | |
44 | capilib_release(&cinfo->ncci_head); | |
45 | + spin_unlock_irqrestore(&card->lock, flags); | |
46 | capi_ctr_reseted(ctrl); | |
47 | } | |
48 | ||
49 | @@ -361,9 +364,8 @@ void b1_release_appl(struct capi_ctr *ct | |
50 | unsigned int port = card->port; | |
51 | unsigned long flags; | |
52 | ||
53 | - capilib_release_appl(&cinfo->ncci_head, appl); | |
54 | - | |
55 | spin_lock_irqsave(&card->lock, flags); | |
56 | + capilib_release_appl(&cinfo->ncci_head, appl); | |
57 | b1_put_byte(port, SEND_RELEASE); | |
58 | b1_put_word(port, appl); | |
59 | spin_unlock_irqrestore(&card->lock, flags); | |
60 | @@ -380,27 +382,27 @@ u16 b1_send_message(struct capi_ctr *ctr | |
61 | u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data); | |
62 | u16 dlen, retval; | |
63 | ||
64 | + spin_lock_irqsave(&card->lock, flags); | |
65 | if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) { | |
66 | retval = capilib_data_b3_req(&cinfo->ncci_head, | |
67 | CAPIMSG_APPID(skb->data), | |
68 | CAPIMSG_NCCI(skb->data), | |
69 | CAPIMSG_MSGID(skb->data)); | |
70 | - if (retval != CAPI_NOERROR) | |
71 | + if (retval != CAPI_NOERROR) { | |
72 | + spin_unlock_irqrestore(&card->lock, flags); | |
73 | return retval; | |
74 | + } | |
75 | ||
76 | dlen = CAPIMSG_DATALEN(skb->data); | |
77 | ||
78 | - spin_lock_irqsave(&card->lock, flags); | |
79 | b1_put_byte(port, SEND_DATA_B3_REQ); | |
80 | b1_put_slice(port, skb->data, len); | |
81 | b1_put_slice(port, skb->data + len, dlen); | |
82 | - spin_unlock_irqrestore(&card->lock, flags); | |
83 | } else { | |
84 | - spin_lock_irqsave(&card->lock, flags); | |
85 | b1_put_byte(port, SEND_MESSAGE); | |
86 | b1_put_slice(port, skb->data, len); | |
87 | - spin_unlock_irqrestore(&card->lock, flags); | |
88 | } | |
89 | + spin_unlock_irqrestore(&card->lock, flags); | |
90 | ||
91 | dev_kfree_skb_any(skb); | |
92 | return CAPI_NOERROR; | |
93 | @@ -534,17 +536,17 @@ irqreturn_t b1_interrupt(int interrupt, | |
94 | ||
95 | ApplId = (unsigned) b1_get_word(card->port); | |
96 | MsgLen = b1_get_slice(card->port, card->msgbuf); | |
97 | - spin_unlock_irqrestore(&card->lock, flags); | |
98 | if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) { | |
99 | printk(KERN_ERR "%s: incoming packet dropped\n", | |
100 | card->name); | |
101 | + spin_unlock_irqrestore(&card->lock, flags); | |
102 | } else { | |
103 | memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); | |
104 | if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_CONF) | |
105 | capilib_data_b3_conf(&cinfo->ncci_head, ApplId, | |
106 | CAPIMSG_NCCI(skb->data), | |
107 | CAPIMSG_MSGID(skb->data)); | |
108 | - | |
109 | + spin_unlock_irqrestore(&card->lock, flags); | |
110 | capi_ctr_handle_message(ctrl, ApplId, skb); | |
111 | } | |
112 | break; | |
113 | @@ -554,21 +556,17 @@ irqreturn_t b1_interrupt(int interrupt, | |
114 | ApplId = b1_get_word(card->port); | |
115 | NCCI = b1_get_word(card->port); | |
116 | WindowSize = b1_get_word(card->port); | |
117 | - spin_unlock_irqrestore(&card->lock, flags); | |
118 | - | |
119 | capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize); | |
120 | - | |
121 | + spin_unlock_irqrestore(&card->lock, flags); | |
122 | break; | |
123 | ||
124 | case RECEIVE_FREE_NCCI: | |
125 | ||
126 | ApplId = b1_get_word(card->port); | |
127 | NCCI = b1_get_word(card->port); | |
128 | - spin_unlock_irqrestore(&card->lock, flags); | |
129 | - | |
130 | if (NCCI != 0xffffffff) | |
131 | capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI); | |
132 | - | |
133 | + spin_unlock_irqrestore(&card->lock, flags); | |
134 | break; | |
135 | ||
136 | case RECEIVE_START: |