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>
This commit is contained in:
committed by
David S. Miller
parent
43e3692101
commit
b3ccfbe409
@ -153,6 +153,18 @@ static void close_work(struct work_struct *work)
|
||||
}
|
||||
static DECLARE_WORK(close_worker, close_work);
|
||||
|
||||
static void chnl_hold(struct cflayer *lyr)
|
||||
{
|
||||
struct chnl_net *priv = container_of(lyr, struct chnl_net, chnl);
|
||||
dev_hold(priv->netdev);
|
||||
}
|
||||
|
||||
static void chnl_put(struct cflayer *lyr)
|
||||
{
|
||||
struct chnl_net *priv = container_of(lyr, struct chnl_net, chnl);
|
||||
dev_put(priv->netdev);
|
||||
}
|
||||
|
||||
static void chnl_flowctrl_cb(struct cflayer *layr, enum caif_ctrlcmd flow,
|
||||
int phyid)
|
||||
{
|
||||
@ -190,6 +202,7 @@ static void chnl_flowctrl_cb(struct cflayer *layr, enum caif_ctrlcmd flow,
|
||||
netif_wake_queue(priv->netdev);
|
||||
break;
|
||||
case CAIF_CTRLCMD_INIT_RSP:
|
||||
caif_client_register_refcnt(&priv->chnl, chnl_hold, chnl_put);
|
||||
priv->state = CAIF_CONNECTED;
|
||||
priv->flowenabled = true;
|
||||
netif_wake_queue(priv->netdev);
|
||||
@ -373,11 +386,18 @@ static const struct net_device_ops netdev_ops = {
|
||||
.ndo_start_xmit = chnl_net_start_xmit,
|
||||
};
|
||||
|
||||
static void chnl_net_destructor(struct net_device *dev)
|
||||
{
|
||||
struct chnl_net *priv = netdev_priv(dev);
|
||||
caif_free_client(&priv->chnl);
|
||||
free_netdev(dev);
|
||||
}
|
||||
|
||||
static void ipcaif_net_setup(struct net_device *dev)
|
||||
{
|
||||
struct chnl_net *priv;
|
||||
dev->netdev_ops = &netdev_ops;
|
||||
dev->destructor = free_netdev;
|
||||
dev->destructor = chnl_net_destructor;
|
||||
dev->flags |= IFF_NOARP;
|
||||
dev->flags |= IFF_POINTOPOINT;
|
||||
dev->mtu = GPRS_PDP_MTU;
|
||||
@ -391,7 +411,7 @@ static void ipcaif_net_setup(struct net_device *dev)
|
||||
priv->conn_req.link_selector = CAIF_LINK_HIGH_BANDW;
|
||||
priv->conn_req.priority = CAIF_PRIO_LOW;
|
||||
/* Insert illegal value */
|
||||
priv->conn_req.sockaddr.u.dgm.connection_id = -1;
|
||||
priv->conn_req.sockaddr.u.dgm.connection_id = 0;
|
||||
priv->flowenabled = false;
|
||||
|
||||
init_waitqueue_head(&priv->netmgmt_wq);
|
||||
@ -453,6 +473,10 @@ static int ipcaif_newlink(struct net *src_net, struct net_device *dev,
|
||||
pr_warn("device rtml registration failed\n");
|
||||
else
|
||||
list_add(&caifdev->list_field, &chnl_net_list);
|
||||
|
||||
/* Take ifindex as connection-id if null */
|
||||
if (caifdev->conn_req.sockaddr.u.dgm.connection_id == 0)
|
||||
caifdev->conn_req.sockaddr.u.dgm.connection_id = dev->ifindex;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user