diff options
author | sjur.brandeland@stericsson.com <sjur.brandeland@stericsson.com> | 2011-05-12 22:44:04 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-05-15 17:45:55 -0400 |
commit | b3ccfbe4098a5542177d0f34e8979f32e7d606e1 (patch) | |
tree | 3f0046e3b519ea253db222abcb761af34b8a1718 /net/caif/chnl_net.c | |
parent | 43e3692101086add8719c3b8b50b05c9ac5b14e1 (diff) |
caif: Protected in-flight packets using dev or sock refcont.
CAIF Socket Layer and ip-interface registers reference counters
in CAIF service layer. The functions sock_hold, sock_put and
dev_hold, dev_put are used by CAIF Stack to protect from freeing
memory while packets are in-flight.
Signed-off-by: Sjur Brændeland <sjur.brandeland@stericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/caif/chnl_net.c')
-rw-r--r-- | net/caif/chnl_net.c | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c index 6008d6dc18a0..9ef8f1660ee1 100644 --- a/net/caif/chnl_net.c +++ b/net/caif/chnl_net.c | |||
@@ -153,6 +153,18 @@ static void close_work(struct work_struct *work) | |||
153 | } | 153 | } |
154 | static DECLARE_WORK(close_worker, close_work); | 154 | static DECLARE_WORK(close_worker, close_work); |
155 | 155 | ||
156 | static void chnl_hold(struct cflayer *lyr) | ||
157 | { | ||
158 | struct chnl_net *priv = container_of(lyr, struct chnl_net, chnl); | ||
159 | dev_hold(priv->netdev); | ||
160 | } | ||
161 | |||
162 | static void chnl_put(struct cflayer *lyr) | ||
163 | { | ||
164 | struct chnl_net *priv = container_of(lyr, struct chnl_net, chnl); | ||
165 | dev_put(priv->netdev); | ||
166 | } | ||
167 | |||
156 | static void chnl_flowctrl_cb(struct cflayer *layr, enum caif_ctrlcmd flow, | 168 | static void chnl_flowctrl_cb(struct cflayer *layr, enum caif_ctrlcmd flow, |
157 | int phyid) | 169 | int phyid) |
158 | { | 170 | { |
@@ -190,6 +202,7 @@ static void chnl_flowctrl_cb(struct cflayer *layr, enum caif_ctrlcmd flow, | |||
190 | netif_wake_queue(priv->netdev); | 202 | netif_wake_queue(priv->netdev); |
191 | break; | 203 | break; |
192 | case CAIF_CTRLCMD_INIT_RSP: | 204 | case CAIF_CTRLCMD_INIT_RSP: |
205 | caif_client_register_refcnt(&priv->chnl, chnl_hold, chnl_put); | ||
193 | priv->state = CAIF_CONNECTED; | 206 | priv->state = CAIF_CONNECTED; |
194 | priv->flowenabled = true; | 207 | priv->flowenabled = true; |
195 | netif_wake_queue(priv->netdev); | 208 | netif_wake_queue(priv->netdev); |
@@ -373,11 +386,18 @@ static const struct net_device_ops netdev_ops = { | |||
373 | .ndo_start_xmit = chnl_net_start_xmit, | 386 | .ndo_start_xmit = chnl_net_start_xmit, |
374 | }; | 387 | }; |
375 | 388 | ||
389 | static void chnl_net_destructor(struct net_device *dev) | ||
390 | { | ||
391 | struct chnl_net *priv = netdev_priv(dev); | ||
392 | caif_free_client(&priv->chnl); | ||
393 | free_netdev(dev); | ||
394 | } | ||
395 | |||
376 | static void ipcaif_net_setup(struct net_device *dev) | 396 | static void ipcaif_net_setup(struct net_device *dev) |
377 | { | 397 | { |
378 | struct chnl_net *priv; | 398 | struct chnl_net *priv; |
379 | dev->netdev_ops = &netdev_ops; | 399 | dev->netdev_ops = &netdev_ops; |
380 | dev->destructor = free_netdev; | 400 | dev->destructor = chnl_net_destructor; |
381 | dev->flags |= IFF_NOARP; | 401 | dev->flags |= IFF_NOARP; |
382 | dev->flags |= IFF_POINTOPOINT; | 402 | dev->flags |= IFF_POINTOPOINT; |
383 | dev->mtu = GPRS_PDP_MTU; | 403 | dev->mtu = GPRS_PDP_MTU; |
@@ -391,7 +411,7 @@ static void ipcaif_net_setup(struct net_device *dev) | |||
391 | priv->conn_req.link_selector = CAIF_LINK_HIGH_BANDW; | 411 | priv->conn_req.link_selector = CAIF_LINK_HIGH_BANDW; |
392 | priv->conn_req.priority = CAIF_PRIO_LOW; | 412 | priv->conn_req.priority = CAIF_PRIO_LOW; |
393 | /* Insert illegal value */ | 413 | /* Insert illegal value */ |
394 | priv->conn_req.sockaddr.u.dgm.connection_id = -1; | 414 | priv->conn_req.sockaddr.u.dgm.connection_id = 0; |
395 | priv->flowenabled = false; | 415 | priv->flowenabled = false; |
396 | 416 | ||
397 | init_waitqueue_head(&priv->netmgmt_wq); | 417 | init_waitqueue_head(&priv->netmgmt_wq); |
@@ -453,6 +473,10 @@ static int ipcaif_newlink(struct net *src_net, struct net_device *dev, | |||
453 | pr_warn("device rtml registration failed\n"); | 473 | pr_warn("device rtml registration failed\n"); |
454 | else | 474 | else |
455 | list_add(&caifdev->list_field, &chnl_net_list); | 475 | list_add(&caifdev->list_field, &chnl_net_list); |
476 | |||
477 | /* Take ifindex as connection-id if null */ | ||
478 | if (caifdev->conn_req.sockaddr.u.dgm.connection_id == 0) | ||
479 | caifdev->conn_req.sockaddr.u.dgm.connection_id = dev->ifindex; | ||
456 | return ret; | 480 | return ret; |
457 | } | 481 | } |
458 | 482 | ||