aboutsummaryrefslogtreecommitdiffstats
path: root/net/caif/chnl_net.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/caif/chnl_net.c')
-rw-r--r--net/caif/chnl_net.c67
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
322error:
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
281static int chnl_net_stop(struct net_device *dev) 330static 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);