diff options
-rw-r--r-- | drivers/net/wimax/i2400m/netdev.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c index f67af4291f8c..599aa4eb9baa 100644 --- a/drivers/net/wimax/i2400m/netdev.c +++ b/drivers/net/wimax/i2400m/netdev.c | |||
@@ -89,7 +89,10 @@ enum { | |||
89 | * The MTU is 1400 or less | 89 | * The MTU is 1400 or less |
90 | */ | 90 | */ |
91 | I2400M_MAX_MTU = 1400, | 91 | I2400M_MAX_MTU = 1400, |
92 | I2400M_TX_TIMEOUT = HZ, | 92 | /* 20 secs? yep, this is the maximum timeout that the device |
93 | * might take to get out of IDLE / negotiate it with the base | ||
94 | * station. We add 1sec for good measure. */ | ||
95 | I2400M_TX_TIMEOUT = 21 * HZ, | ||
93 | I2400M_TX_QLEN = 5, | 96 | I2400M_TX_QLEN = 5, |
94 | }; | 97 | }; |
95 | 98 | ||
@@ -151,6 +154,7 @@ void i2400m_wake_tx_work(struct work_struct *ws) | |||
151 | { | 154 | { |
152 | int result; | 155 | int result; |
153 | struct i2400m *i2400m = container_of(ws, struct i2400m, wake_tx_ws); | 156 | struct i2400m *i2400m = container_of(ws, struct i2400m, wake_tx_ws); |
157 | struct net_device *net_dev = i2400m->wimax_dev.net_dev; | ||
154 | struct device *dev = i2400m_dev(i2400m); | 158 | struct device *dev = i2400m_dev(i2400m); |
155 | struct sk_buff *skb = i2400m->wake_tx_skb; | 159 | struct sk_buff *skb = i2400m->wake_tx_skb; |
156 | unsigned long flags; | 160 | unsigned long flags; |
@@ -166,6 +170,11 @@ void i2400m_wake_tx_work(struct work_struct *ws) | |||
166 | dev_err(dev, "WAKE&TX: skb dissapeared!\n"); | 170 | dev_err(dev, "WAKE&TX: skb dissapeared!\n"); |
167 | goto out_put; | 171 | goto out_put; |
168 | } | 172 | } |
173 | /* If we have, somehow, lost the connection after this was | ||
174 | * queued, don't do anything; this might be the device got | ||
175 | * reset or just disconnected. */ | ||
176 | if (unlikely(!netif_carrier_ok(net_dev))) | ||
177 | goto out_kfree; | ||
169 | result = i2400m_cmd_exit_idle(i2400m); | 178 | result = i2400m_cmd_exit_idle(i2400m); |
170 | if (result == -EILSEQ) | 179 | if (result == -EILSEQ) |
171 | result = 0; | 180 | result = 0; |
@@ -176,7 +185,8 @@ void i2400m_wake_tx_work(struct work_struct *ws) | |||
176 | goto error; | 185 | goto error; |
177 | } | 186 | } |
178 | result = wait_event_timeout(i2400m->state_wq, | 187 | result = wait_event_timeout(i2400m->state_wq, |
179 | i2400m->state != I2400M_SS_IDLE, 5 * HZ); | 188 | i2400m->state != I2400M_SS_IDLE, |
189 | net_dev->watchdog_timeo - HZ/2); | ||
180 | if (result == 0) | 190 | if (result == 0) |
181 | result = -ETIMEDOUT; | 191 | result = -ETIMEDOUT; |
182 | if (result < 0) { | 192 | if (result < 0) { |
@@ -187,8 +197,9 @@ void i2400m_wake_tx_work(struct work_struct *ws) | |||
187 | } | 197 | } |
188 | msleep(20); /* device still needs some time or it drops it */ | 198 | msleep(20); /* device still needs some time or it drops it */ |
189 | result = i2400m_tx(i2400m, skb->data, skb->len, I2400M_PT_DATA); | 199 | result = i2400m_tx(i2400m, skb->data, skb->len, I2400M_PT_DATA); |
190 | netif_wake_queue(i2400m->wimax_dev.net_dev); | ||
191 | error: | 200 | error: |
201 | netif_wake_queue(net_dev); | ||
202 | out_kfree: | ||
192 | kfree_skb(skb); /* refcount transferred by _hard_start_xmit() */ | 203 | kfree_skb(skb); /* refcount transferred by _hard_start_xmit() */ |
193 | out_put: | 204 | out_put: |
194 | i2400m_put(i2400m); | 205 | i2400m_put(i2400m); |