Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 278365
b: refs/heads/master
c: 7d31130
h: refs/heads/master
i:
  278363: cd67613
v: v3
  • Loading branch information
sjur.brandeland@stericsson.com authored and David S. Miller committed Dec 5, 2011
1 parent c23f440 commit ca2b57d
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0e4c7d85d5e522d5839bdc5745235428faf38d44
refs/heads/master: 7d3113042823344dcc175b0ea00a83d0273c98a4
34 changes: 33 additions & 1 deletion trunk/net/caif/caif_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ struct caif_device_entry {
struct net_device *netdev;
int __percpu *pcpu_refcnt;
spinlock_t flow_lock;
struct sk_buff *xoff_skb;
void (*xoff_skb_dtor)(struct sk_buff *skb);
bool xoff;
};

Expand Down Expand Up @@ -133,6 +135,7 @@ static struct caif_device_entry *caif_get(struct net_device *dev)
void caif_flow_cb(struct sk_buff *skb)
{
struct caif_device_entry *caifd;
void (*dtor)(struct sk_buff *skb) = NULL;
bool send_xoff;

WARN_ON(skb->dev == NULL);
Expand All @@ -145,8 +148,17 @@ void caif_flow_cb(struct sk_buff *skb)
spin_lock_bh(&caifd->flow_lock);
send_xoff = caifd->xoff;
caifd->xoff = 0;
if (!WARN_ON(caifd->xoff_skb_dtor == NULL)) {
WARN_ON(caifd->xoff_skb != skb);
dtor = caifd->xoff_skb_dtor;
caifd->xoff_skb = NULL;
caifd->xoff_skb_dtor = NULL;
}
spin_unlock_bh(&caifd->flow_lock);

if (dtor)
dtor(skb);

if (send_xoff)
caifd->layer.up->
ctrlcmd(caifd->layer.up,
Expand Down Expand Up @@ -210,8 +222,10 @@ static int transmit(struct cflayer *layer, struct cfpkt *pkt)
netif_queue_stopped(caifd->netdev),
qlen, high);
caifd->xoff = 1;
caifd->xoff_skb = skb;
caifd->xoff_skb_dtor = skb->destructor;
skb->destructor = caif_flow_cb;
spin_unlock_bh(&caifd->flow_lock);
skb_orphan(skb);

caifd->layer.up->ctrlcmd(caifd->layer.up,
_CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND,
Expand Down Expand Up @@ -420,6 +434,24 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what,
caifd->layer.up->ctrlcmd(caifd->layer.up,
_CAIF_CTRLCMD_PHYIF_DOWN_IND,
caifd->layer.id);

spin_lock_bh(&caifd->flow_lock);

/*
* Replace our xoff-destructor with original destructor.
* We trust that skb->destructor *always* is called before
* the skb reference is invalid. The hijacked SKB destructor
* takes the flow_lock so manipulating the skb->destructor here
* should be safe.
*/
if (caifd->xoff_skb_dtor != NULL && caifd->xoff_skb != NULL)
caifd->xoff_skb->destructor = caifd->xoff_skb_dtor;

caifd->xoff = 0;
caifd->xoff_skb_dtor = NULL;
caifd->xoff_skb = NULL;

spin_unlock_bh(&caifd->flow_lock);
caifd_put(caifd);
break;

Expand Down

0 comments on commit ca2b57d

Please sign in to comment.