Commit b770261a authored by Armin Schindler's avatar Armin Schindler Committed by Linus Torvalds

[PATCH] 2.6 ISDN CAPI: low-level drivers skb free fix

CAPI skb freeing fix. On sending, the hardware/low-level
driver may free a skb on no error only. The application/core
side must take care otherwise.

Author: Carsten Paeth, Armin Schindler
parent ef33e507
...@@ -512,7 +512,8 @@ static void send_message(capidrv_contr * card, _cmsg * cmsg) ...@@ -512,7 +512,8 @@ static void send_message(capidrv_contr * card, _cmsg * cmsg)
len = CAPIMSG_LEN(cmsg->buf); len = CAPIMSG_LEN(cmsg->buf);
skb = alloc_skb(len, GFP_ATOMIC); skb = alloc_skb(len, GFP_ATOMIC);
memcpy(skb_put(skb, len), cmsg->buf, len); memcpy(skb_put(skb, len), cmsg->buf, len);
capi20_put_message(&global.ap, skb); if (capi20_put_message(&global.ap, skb) != CAPI_NOERROR)
kfree_skb(skb);
} }
/* -------- state machine -------------------------------------------- */ /* -------- state machine -------------------------------------------- */
......
...@@ -389,7 +389,7 @@ u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) ...@@ -389,7 +389,7 @@ u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
CAPIMSG_NCCI(skb->data), CAPIMSG_NCCI(skb->data),
CAPIMSG_MSGID(skb->data)); CAPIMSG_MSGID(skb->data));
if (retval != CAPI_NOERROR) if (retval != CAPI_NOERROR)
goto out; return retval;
dlen = CAPIMSG_DATALEN(skb->data); dlen = CAPIMSG_DATALEN(skb->data);
...@@ -399,16 +399,14 @@ u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) ...@@ -399,16 +399,14 @@ u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
b1_put_slice(port, skb->data + len, dlen); b1_put_slice(port, skb->data + len, dlen);
spin_unlock_irqrestore(&card->lock, flags); spin_unlock_irqrestore(&card->lock, flags);
} else { } else {
retval = CAPI_NOERROR;
spin_lock_irqsave(&card->lock, flags); spin_lock_irqsave(&card->lock, flags);
b1_put_byte(port, SEND_MESSAGE); b1_put_byte(port, SEND_MESSAGE);
b1_put_slice(port, skb->data, len); b1_put_slice(port, skb->data, len);
spin_unlock_irqrestore(&card->lock, flags); spin_unlock_irqrestore(&card->lock, flags);
} }
out:
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
return retval; return CAPI_NOERROR;
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
......
...@@ -839,8 +839,6 @@ u16 b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) ...@@ -839,8 +839,6 @@ u16 b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
} }
if (retval == CAPI_NOERROR) if (retval == CAPI_NOERROR)
b1dma_queue_tx(card, skb); b1dma_queue_tx(card, skb);
else
dev_kfree_skb_any(skb);
return retval; return retval;
} }
......
...@@ -1029,8 +1029,6 @@ static u16 c4_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) ...@@ -1029,8 +1029,6 @@ static u16 c4_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
spin_lock_irqsave(&card->lock, flags); spin_lock_irqsave(&card->lock, flags);
c4_dispatch_tx(card); c4_dispatch_tx(card);
spin_unlock_irqrestore(&card->lock, flags); spin_unlock_irqrestore(&card->lock, flags);
} else {
dev_kfree_skb_any(skb);
} }
return retval; return retval;
} }
......
...@@ -472,7 +472,7 @@ static u16 t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) ...@@ -472,7 +472,7 @@ static u16 t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
CAPIMSG_NCCI(skb->data), CAPIMSG_NCCI(skb->data),
CAPIMSG_MSGID(skb->data)); CAPIMSG_MSGID(skb->data));
if (retval != CAPI_NOERROR) if (retval != CAPI_NOERROR)
goto out; return retval;
dlen = CAPIMSG_DATALEN(skb->data); dlen = CAPIMSG_DATALEN(skb->data);
...@@ -482,16 +482,15 @@ static u16 t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) ...@@ -482,16 +482,15 @@ static u16 t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
t1_put_slice(port, skb->data + len, dlen); t1_put_slice(port, skb->data + len, dlen);
spin_unlock_irqrestore(&card->lock, flags); spin_unlock_irqrestore(&card->lock, flags);
} else { } else {
retval = CAPI_NOERROR;
spin_lock_irqsave(&card->lock, flags); spin_lock_irqsave(&card->lock, flags);
b1_put_byte(port, SEND_MESSAGE); b1_put_byte(port, SEND_MESSAGE);
t1_put_slice(port, skb->data, len); t1_put_slice(port, skb->data, len);
spin_unlock_irqrestore(&card->lock, flags); spin_unlock_irqrestore(&card->lock, flags);
} }
out:
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
return retval; return CAPI_NOERROR;
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
......
/* $Id: capifunc.c,v 1.61.4.2 2004/05/05 16:09:25 armin Exp $ /* $Id: capifunc.c,v 1.61.4.5 2004/08/27 20:10:12 armin Exp $
* *
* ISDN interface module for Eicon active cards DIVA. * ISDN interface module for Eicon active cards DIVA.
* CAPI Interface common functions * CAPI Interface common functions
...@@ -998,6 +998,7 @@ static u16 diva_send_message(struct capi_ctr *ctrl, ...@@ -998,6 +998,7 @@ static u16 diva_send_message(struct capi_ctr *ctrl,
write_end: write_end:
diva_os_leave_spin_lock(&api_lock, &old_irql, "send message"); diva_os_leave_spin_lock(&api_lock, &old_irql, "send message");
if (retval == CAPI_NOERROR)
diva_os_free_message_buffer(dmb); diva_os_free_message_buffer(dmb);
return retval; return retval;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment