diff options
Diffstat (limited to 'net/caif/chnl_net.c')
-rw-r--r-- | net/caif/chnl_net.c | 67 |
1 files changed, 57 insertions, 10 deletions
diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c index 610966abe2dc..4293e190ec53 100644 --- a/net/caif/chnl_net.c +++ b/net/caif/chnl_net.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include <net/caif/caif_dev.h> | 23 | #include <net/caif/caif_dev.h> |
24 | 24 | ||
25 | /* GPRS PDP connection has MTU to 1500 */ | 25 | /* GPRS PDP connection has MTU to 1500 */ |
26 | #define SIZE_MTU 1500 | 26 | #define GPRS_PDP_MTU 1500 |
27 | /* 5 sec. connect timeout */ | 27 | /* 5 sec. connect timeout */ |
28 | #define CONNECT_TIMEOUT (5 * HZ) | 28 | #define CONNECT_TIMEOUT (5 * HZ) |
29 | #define CAIF_NET_DEFAULT_QUEUE_LEN 500 | 29 | #define CAIF_NET_DEFAULT_QUEUE_LEN 500 |
@@ -232,6 +232,8 @@ static int chnl_net_open(struct net_device *dev) | |||
232 | { | 232 | { |
233 | struct chnl_net *priv = NULL; | 233 | struct chnl_net *priv = NULL; |
234 | int result = -1; | 234 | int result = -1; |
235 | int llifindex, headroom, tailroom, mtu; | ||
236 | struct net_device *lldev; | ||
235 | ASSERT_RTNL(); | 237 | ASSERT_RTNL(); |
236 | priv = netdev_priv(dev); | 238 | priv = netdev_priv(dev); |
237 | if (!priv) { | 239 | if (!priv) { |
@@ -241,41 +243,88 @@ static int chnl_net_open(struct net_device *dev) | |||
241 | 243 | ||
242 | if (priv->state != CAIF_CONNECTING) { | 244 | if (priv->state != CAIF_CONNECTING) { |
243 | priv->state = CAIF_CONNECTING; | 245 | priv->state = CAIF_CONNECTING; |
244 | result = caif_connect_client(&priv->conn_req, &priv->chnl); | 246 | result = caif_connect_client(&priv->conn_req, &priv->chnl, |
247 | &llifindex, &headroom, &tailroom); | ||
245 | if (result != 0) { | 248 | if (result != 0) { |
246 | priv->state = CAIF_DISCONNECTED; | ||
247 | pr_debug("CAIF: %s(): err: " | 249 | pr_debug("CAIF: %s(): err: " |
248 | "Unable to register and open device," | 250 | "Unable to register and open device," |
249 | " Err:%d\n", | 251 | " Err:%d\n", |
250 | __func__, | 252 | __func__, |
251 | result); | 253 | result); |
252 | return result; | 254 | goto error; |
255 | } | ||
256 | |||
257 | lldev = dev_get_by_index(dev_net(dev), llifindex); | ||
258 | |||
259 | if (lldev == NULL) { | ||
260 | pr_debug("CAIF: %s(): no interface?\n", __func__); | ||
261 | result = -ENODEV; | ||
262 | goto error; | ||
263 | } | ||
264 | |||
265 | dev->needed_tailroom = tailroom + lldev->needed_tailroom; | ||
266 | dev->hard_header_len = headroom + lldev->hard_header_len + | ||
267 | lldev->needed_tailroom; | ||
268 | |||
269 | /* | ||
270 | * MTU, head-room etc is not know before we have a | ||
271 | * CAIF link layer device available. MTU calculation may | ||
272 | * override initial RTNL configuration. | ||
273 | * MTU is minimum of current mtu, link layer mtu pluss | ||
274 | * CAIF head and tail, and PDP GPRS contexts max MTU. | ||
275 | */ | ||
276 | mtu = min_t(int, dev->mtu, lldev->mtu - (headroom + tailroom)); | ||
277 | mtu = min_t(int, GPRS_PDP_MTU, mtu); | ||
278 | dev_set_mtu(dev, mtu); | ||
279 | dev_put(lldev); | ||
280 | |||
281 | if (mtu < 100) { | ||
282 | pr_warning("CAIF: %s(): " | ||
283 | "CAIF Interface MTU too small (%d)\n", | ||
284 | __func__, mtu); | ||
285 | result = -ENODEV; | ||
286 | goto error; | ||
253 | } | 287 | } |
254 | } | 288 | } |
255 | 289 | ||
290 | rtnl_unlock(); /* Release RTNL lock during connect wait */ | ||
291 | |||
256 | result = wait_event_interruptible_timeout(priv->netmgmt_wq, | 292 | result = wait_event_interruptible_timeout(priv->netmgmt_wq, |
257 | priv->state != CAIF_CONNECTING, | 293 | priv->state != CAIF_CONNECTING, |
258 | CONNECT_TIMEOUT); | 294 | CONNECT_TIMEOUT); |
259 | 295 | ||
296 | rtnl_lock(); | ||
297 | |||
260 | if (result == -ERESTARTSYS) { | 298 | if (result == -ERESTARTSYS) { |
261 | pr_debug("CAIF: %s(): wait_event_interruptible" | 299 | pr_debug("CAIF: %s(): wait_event_interruptible" |
262 | " woken by a signal\n", __func__); | 300 | " woken by a signal\n", __func__); |
263 | return -ERESTARTSYS; | 301 | result = -ERESTARTSYS; |
302 | goto error; | ||
264 | } | 303 | } |
304 | |||
265 | if (result == 0) { | 305 | if (result == 0) { |
266 | pr_debug("CAIF: %s(): connect timeout\n", __func__); | 306 | pr_debug("CAIF: %s(): connect timeout\n", __func__); |
267 | caif_disconnect_client(&priv->chnl); | 307 | caif_disconnect_client(&priv->chnl); |
268 | priv->state = CAIF_DISCONNECTED; | 308 | priv->state = CAIF_DISCONNECTED; |
269 | pr_debug("CAIF: %s(): state disconnected\n", __func__); | 309 | pr_debug("CAIF: %s(): state disconnected\n", __func__); |
270 | return -ETIMEDOUT; | 310 | result = -ETIMEDOUT; |
311 | goto error; | ||
271 | } | 312 | } |
272 | 313 | ||
273 | if (priv->state != CAIF_CONNECTED) { | 314 | if (priv->state != CAIF_CONNECTED) { |
274 | pr_debug("CAIF: %s(): connect failed\n", __func__); | 315 | pr_debug("CAIF: %s(): connect failed\n", __func__); |
275 | return -ECONNREFUSED; | 316 | result = -ECONNREFUSED; |
317 | goto error; | ||
276 | } | 318 | } |
277 | pr_debug("CAIF: %s(): CAIF Netdevice connected\n", __func__); | 319 | pr_debug("CAIF: %s(): CAIF Netdevice connected\n", __func__); |
278 | return 0; | 320 | return 0; |
321 | |||
322 | error: | ||
323 | caif_disconnect_client(&priv->chnl); | ||
324 | priv->state = CAIF_DISCONNECTED; | ||
325 | pr_debug("CAIF: %s(): state disconnected\n", __func__); | ||
326 | return result; | ||
327 | |||
279 | } | 328 | } |
280 | 329 | ||
281 | static int chnl_net_stop(struct net_device *dev) | 330 | static int chnl_net_stop(struct net_device *dev) |
@@ -321,9 +370,7 @@ static void ipcaif_net_setup(struct net_device *dev) | |||
321 | dev->destructor = free_netdev; | 370 | dev->destructor = free_netdev; |
322 | dev->flags |= IFF_NOARP; | 371 | dev->flags |= IFF_NOARP; |
323 | dev->flags |= IFF_POINTOPOINT; | 372 | dev->flags |= IFF_POINTOPOINT; |
324 | dev->needed_headroom = CAIF_NEEDED_HEADROOM; | 373 | dev->mtu = GPRS_PDP_MTU; |
325 | dev->needed_tailroom = CAIF_NEEDED_TAILROOM; | ||
326 | dev->mtu = SIZE_MTU; | ||
327 | dev->tx_queue_len = CAIF_NET_DEFAULT_QUEUE_LEN; | 374 | dev->tx_queue_len = CAIF_NET_DEFAULT_QUEUE_LEN; |
328 | 375 | ||
329 | priv = netdev_priv(dev); | 376 | priv = netdev_priv(dev); |