Commit e29d4363174949a7a4e46f670993d7ff43342c1c

Authored by David S. Miller
1 parent 5bfa2a17f2

Revert "isdn: isdn_ppp: Use SKB list facilities instead of home-grown implementation."

This reverts commit 38783e671399b5405f1fd177d602c400a9577ae6.

It causes kernel bugzilla #14594

Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 2 changed files with 164 additions and 190 deletions Side-by-side Diff

drivers/isdn/i4l/isdn_ppp.c
... ... @@ -1535,10 +1535,8 @@
1535 1535 int sz = ISDN_MAX_CHANNELS*sizeof(ippp_bundle);
1536 1536 if( (isdn_ppp_bundle_arr = kzalloc(sz, GFP_KERNEL)) == NULL )
1537 1537 return -ENOMEM;
1538   - for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
  1538 + for( i = 0; i < ISDN_MAX_CHANNELS; i++ )
1539 1539 spin_lock_init(&isdn_ppp_bundle_arr[i].lock);
1540   - skb_queue_head_init(&isdn_ppp_bundle_arr[i].frags);
1541   - }
1542 1540 return 0;
1543 1541 }
1544 1542  
... ... @@ -1571,7 +1569,7 @@
1571 1569 if ((lp->netdev->pb = isdn_ppp_mp_bundle_alloc()) == NULL)
1572 1570 return -ENOMEM;
1573 1571 lp->next = lp->last = lp; /* nobody else in a queue */
1574   - skb_queue_head_init(&lp->netdev->pb->frags);
  1572 + lp->netdev->pb->frags = NULL;
1575 1573 lp->netdev->pb->frames = 0;
1576 1574 lp->netdev->pb->seq = UINT_MAX;
1577 1575 }
1578 1576  
1579 1577  
1580 1578  
1581 1579  
1582 1580  
... ... @@ -1583,29 +1581,28 @@
1583 1581  
1584 1582 static u32 isdn_ppp_mp_get_seq( int short_seq,
1585 1583 struct sk_buff * skb, u32 last_seq );
1586   -static void isdn_ppp_mp_discard(ippp_bundle *mp, struct sk_buff *from,
1587   - struct sk_buff *to);
1588   -static void isdn_ppp_mp_reassembly(isdn_net_dev *net_dev, isdn_net_local *lp,
1589   - struct sk_buff *from, struct sk_buff *to,
1590   - u32 lastseq);
1591   -static void isdn_ppp_mp_free_skb(ippp_bundle *mp, struct sk_buff *skb);
  1584 +static struct sk_buff * isdn_ppp_mp_discard( ippp_bundle * mp,
  1585 + struct sk_buff * from, struct sk_buff * to );
  1586 +static void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp,
  1587 + struct sk_buff * from, struct sk_buff * to );
  1588 +static void isdn_ppp_mp_free_skb( ippp_bundle * mp, struct sk_buff * skb );
1592 1589 static void isdn_ppp_mp_print_recv_pkt( int slot, struct sk_buff * skb );
1593 1590  
1594 1591 static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
1595   - struct sk_buff *skb)
  1592 + struct sk_buff *skb)
1596 1593 {
1597   - struct sk_buff *newfrag, *frag, *start, *nextf;
1598   - u32 newseq, minseq, thisseq;
1599   - isdn_mppp_stats *stats;
1600 1594 struct ippp_struct *is;
  1595 + isdn_net_local * lpq;
  1596 + ippp_bundle * mp;
  1597 + isdn_mppp_stats * stats;
  1598 + struct sk_buff * newfrag, * frag, * start, *nextf;
  1599 + u32 newseq, minseq, thisseq;
1601 1600 unsigned long flags;
1602   - isdn_net_local *lpq;
1603   - ippp_bundle *mp;
1604 1601 int slot;
1605 1602  
1606 1603 spin_lock_irqsave(&net_dev->pb->lock, flags);
1607   - mp = net_dev->pb;
1608   - stats = &mp->stats;
  1604 + mp = net_dev->pb;
  1605 + stats = &mp->stats;
1609 1606 slot = lp->ppp_slot;
1610 1607 if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
1611 1608 printk(KERN_ERR "%s: lp->ppp_slot(%d)\n",
1612 1609  
1613 1610  
1614 1611  
1615 1612  
... ... @@ -1616,19 +1613,20 @@
1616 1613 return;
1617 1614 }
1618 1615 is = ippp_table[slot];
1619   - if (++mp->frames > stats->max_queue_len)
  1616 + if( ++mp->frames > stats->max_queue_len )
1620 1617 stats->max_queue_len = mp->frames;
1621   -
  1618 +
1622 1619 if (is->debug & 0x8)
1623 1620 isdn_ppp_mp_print_recv_pkt(lp->ppp_slot, skb);
1624 1621  
1625   - newseq = isdn_ppp_mp_get_seq(is->mpppcfg & SC_IN_SHORT_SEQ,
1626   - skb, is->last_link_seqno);
  1622 + newseq = isdn_ppp_mp_get_seq(is->mpppcfg & SC_IN_SHORT_SEQ,
  1623 + skb, is->last_link_seqno);
1627 1624  
  1625 +
1628 1626 /* if this packet seq # is less than last already processed one,
1629 1627 * toss it right away, but check for sequence start case first
1630 1628 */
1631   - if (mp->seq > MP_LONGSEQ_MAX && (newseq & MP_LONGSEQ_MAXBIT)) {
  1629 + if( mp->seq > MP_LONGSEQ_MAX && (newseq & MP_LONGSEQ_MAXBIT) ) {
1632 1630 mp->seq = newseq; /* the first packet: required for
1633 1631 * rfc1990 non-compliant clients --
1634 1632 * prevents constant packet toss */
... ... @@ -1638,7 +1636,7 @@
1638 1636 spin_unlock_irqrestore(&mp->lock, flags);
1639 1637 return;
1640 1638 }
1641   -
  1639 +
1642 1640 /* find the minimum received sequence number over all links */
1643 1641 is->last_link_seqno = minseq = newseq;
1644 1642 for (lpq = net_dev->queue;;) {
1645 1643  
1646 1644  
1647 1645  
... ... @@ -1659,31 +1657,22 @@
1659 1657 * packets */
1660 1658 newfrag = skb;
1661 1659  
1662   - /* Insert new fragment into the proper sequence slot. */
1663   - skb_queue_walk(&mp->frags, frag) {
1664   - if (MP_SEQ(frag) == newseq) {
1665   - isdn_ppp_mp_free_skb(mp, newfrag);
1666   - newfrag = NULL;
1667   - break;
1668   - }
1669   - if (MP_LT(newseq, MP_SEQ(frag))) {
1670   - __skb_queue_before(&mp->frags, frag, newfrag);
1671   - newfrag = NULL;
1672   - break;
1673   - }
1674   - }
1675   - if (newfrag)
1676   - __skb_queue_tail(&mp->frags, newfrag);
  1660 + /* if this new fragment is before the first one, then enqueue it now. */
  1661 + if ((frag = mp->frags) == NULL || MP_LT(newseq, MP_SEQ(frag))) {
  1662 + newfrag->next = frag;
  1663 + mp->frags = frag = newfrag;
  1664 + newfrag = NULL;
  1665 + }
1677 1666  
1678   - frag = skb_peek(&mp->frags);
1679   - start = ((MP_FLAGS(frag) & MP_BEGIN_FRAG) &&
1680   - (MP_SEQ(frag) == mp->seq)) ? frag : NULL;
1681   - if (!start)
1682   - goto check_overflow;
  1667 + start = MP_FLAGS(frag) & MP_BEGIN_FRAG &&
  1668 + MP_SEQ(frag) == mp->seq ? frag : NULL;
1683 1669  
1684   - /* main fragment traversing loop
  1670 + /*
  1671 + * main fragment traversing loop
1685 1672 *
1686 1673 * try to accomplish several tasks:
  1674 + * - insert new fragment into the proper sequence slot (once that's done
  1675 + * newfrag will be set to NULL)
1687 1676 * - reassemble any complete fragment sequence (non-null 'start'
1688 1677 * indicates there is a continguous sequence present)
1689 1678 * - discard any incomplete sequences that are below minseq -- due
1690 1679  
1691 1680  
1692 1681  
1693 1682  
1694 1683  
1695 1684  
1696 1685  
1697 1686  
1698 1687  
... ... @@ -1692,46 +1681,71 @@
1692 1681 * come to complete such sequence and it should be discarded
1693 1682 *
1694 1683 * loop completes when we accomplished the following tasks:
  1684 + * - new fragment is inserted in the proper sequence ('newfrag' is
  1685 + * set to NULL)
1695 1686 * - we hit a gap in the sequence, so no reassembly/processing is
1696 1687 * possible ('start' would be set to NULL)
1697 1688 *
1698 1689 * algorithm for this code is derived from code in the book
1699 1690 * 'PPP Design And Debugging' by James Carlson (Addison-Wesley)
1700 1691 */
1701   - skb_queue_walk_safe(&mp->frags, frag, nextf) {
1702   - thisseq = MP_SEQ(frag);
  1692 + while (start != NULL || newfrag != NULL) {
1703 1693  
1704   - /* check for misplaced start */
1705   - if (start != frag && (MP_FLAGS(frag) & MP_BEGIN_FRAG)) {
1706   - printk(KERN_WARNING"isdn_mppp(seq %d): new "
1707   - "BEGIN flag with no prior END", thisseq);
1708   - stats->seqerrs++;
1709   - stats->frame_drops++;
1710   - isdn_ppp_mp_discard(mp, start, frag);
1711   - start = frag;
1712   - } else if (MP_LE(thisseq, minseq)) {
1713   - if (MP_FLAGS(frag) & MP_BEGIN_FRAG)
  1694 + thisseq = MP_SEQ(frag);
  1695 + nextf = frag->next;
  1696 +
  1697 + /* drop any duplicate fragments */
  1698 + if (newfrag != NULL && thisseq == newseq) {
  1699 + isdn_ppp_mp_free_skb(mp, newfrag);
  1700 + newfrag = NULL;
  1701 + }
  1702 +
  1703 + /* insert new fragment before next element if possible. */
  1704 + if (newfrag != NULL && (nextf == NULL ||
  1705 + MP_LT(newseq, MP_SEQ(nextf)))) {
  1706 + newfrag->next = nextf;
  1707 + frag->next = nextf = newfrag;
  1708 + newfrag = NULL;
  1709 + }
  1710 +
  1711 + if (start != NULL) {
  1712 + /* check for misplaced start */
  1713 + if (start != frag && (MP_FLAGS(frag) & MP_BEGIN_FRAG)) {
  1714 + printk(KERN_WARNING"isdn_mppp(seq %d): new "
  1715 + "BEGIN flag with no prior END", thisseq);
  1716 + stats->seqerrs++;
  1717 + stats->frame_drops++;
  1718 + start = isdn_ppp_mp_discard(mp, start,frag);
  1719 + nextf = frag->next;
  1720 + }
  1721 + } else if (MP_LE(thisseq, minseq)) {
  1722 + if (MP_FLAGS(frag) & MP_BEGIN_FRAG)
1714 1723 start = frag;
1715   - else {
  1724 + else {
1716 1725 if (MP_FLAGS(frag) & MP_END_FRAG)
1717   - stats->frame_drops++;
1718   - __skb_unlink(skb, &mp->frags);
  1726 + stats->frame_drops++;
  1727 + if( mp->frags == frag )
  1728 + mp->frags = nextf;
1719 1729 isdn_ppp_mp_free_skb(mp, frag);
  1730 + frag = nextf;
1720 1731 continue;
1721   - }
  1732 + }
1722 1733 }
1723   -
1724   - /* if we have end fragment, then we have full reassembly
1725   - * sequence -- reassemble and process packet now
  1734 +
  1735 + /* if start is non-null and we have end fragment, then
  1736 + * we have full reassembly sequence -- reassemble
  1737 + * and process packet now
1726 1738 */
1727   - if (MP_FLAGS(frag) & MP_END_FRAG) {
1728   - minseq = mp->seq = (thisseq+1) & MP_LONGSEQ_MASK;
1729   - /* Reassemble the packet then dispatch it */
1730   - isdn_ppp_mp_reassembly(net_dev, lp, start, frag, thisseq);
  1739 + if (start != NULL && (MP_FLAGS(frag) & MP_END_FRAG)) {
  1740 + minseq = mp->seq = (thisseq+1) & MP_LONGSEQ_MASK;
  1741 + /* Reassemble the packet then dispatch it */
  1742 + isdn_ppp_mp_reassembly(net_dev, lp, start, nextf);
  1743 +
  1744 + start = NULL;
  1745 + frag = NULL;
1731 1746  
1732   - start = NULL;
1733   - frag = NULL;
1734   - }
  1747 + mp->frags = nextf;
  1748 + }
1735 1749  
1736 1750 /* check if need to update start pointer: if we just
1737 1751 * reassembled the packet and sequence is contiguous
1738 1752  
1739 1753  
1740 1754  
... ... @@ -1742,25 +1756,26 @@
1742 1756 * below low watermark and set start to the next frag or
1743 1757 * clear start ptr.
1744 1758 */
1745   - if (nextf != (struct sk_buff *)&mp->frags &&
  1759 + if (nextf != NULL &&
1746 1760 ((thisseq+1) & MP_LONGSEQ_MASK) == MP_SEQ(nextf)) {
1747   - /* if we just reassembled and the next one is here,
1748   - * then start another reassembly.
1749   - */
1750   - if (frag == NULL) {
  1761 + /* if we just reassembled and the next one is here,
  1762 + * then start another reassembly. */
  1763 +
  1764 + if (frag == NULL) {
1751 1765 if (MP_FLAGS(nextf) & MP_BEGIN_FRAG)
1752   - start = nextf;
1753   - else {
1754   - printk(KERN_WARNING"isdn_mppp(seq %d):"
1755   - " END flag with no following "
1756   - "BEGIN", thisseq);
  1766 + start = nextf;
  1767 + else
  1768 + {
  1769 + printk(KERN_WARNING"isdn_mppp(seq %d):"
  1770 + " END flag with no following "
  1771 + "BEGIN", thisseq);
1757 1772 stats->seqerrs++;
1758 1773 }
1759 1774 }
1760   - } else {
1761   - if (nextf != (struct sk_buff *)&mp->frags &&
1762   - frag != NULL &&
1763   - MP_LT(thisseq, minseq)) {
  1775 +
  1776 + } else {
  1777 + if ( nextf != NULL && frag != NULL &&
  1778 + MP_LT(thisseq, minseq)) {
1764 1779 /* we've got a break in the sequence
1765 1780 * and we not at the end yet
1766 1781 * and we did not just reassembled
1767 1782  
1768 1783  
1769 1784  
1770 1785  
1771 1786  
1772 1787  
... ... @@ -1769,39 +1784,41 @@
1769 1784 * discard all the frames below low watermark
1770 1785 * and start over */
1771 1786 stats->frame_drops++;
1772   - isdn_ppp_mp_discard(mp, start, nextf);
  1787 + mp->frags = isdn_ppp_mp_discard(mp,start,nextf);
1773 1788 }
1774 1789 /* break in the sequence, no reassembly */
1775   - start = NULL;
1776   - }
1777   - if (!start)
1778   - break;
1779   - }
1780   -
1781   -check_overflow:
  1790 + start = NULL;
  1791 + }
  1792 +
  1793 + frag = nextf;
  1794 + } /* while -- main loop */
  1795 +
  1796 + if (mp->frags == NULL)
  1797 + mp->frags = frag;
  1798 +
1782 1799 /* rather straighforward way to deal with (not very) possible
1783   - * queue overflow
1784   - */
  1800 + * queue overflow */
1785 1801 if (mp->frames > MP_MAX_QUEUE_LEN) {
1786 1802 stats->overflows++;
1787   - skb_queue_walk_safe(&mp->frags, frag, nextf) {
1788   - if (mp->frames <= MP_MAX_QUEUE_LEN)
1789   - break;
1790   - __skb_unlink(frag, &mp->frags);
1791   - isdn_ppp_mp_free_skb(mp, frag);
  1803 + while (mp->frames > MP_MAX_QUEUE_LEN) {
  1804 + frag = mp->frags->next;
  1805 + isdn_ppp_mp_free_skb(mp, mp->frags);
  1806 + mp->frags = frag;
1792 1807 }
1793 1808 }
1794 1809 spin_unlock_irqrestore(&mp->lock, flags);
1795 1810 }
1796 1811  
1797   -static void isdn_ppp_mp_cleanup(isdn_net_local *lp)
  1812 +static void isdn_ppp_mp_cleanup( isdn_net_local * lp )
1798 1813 {
1799   - struct sk_buff *skb, *tmp;
1800   -
1801   - skb_queue_walk_safe(&lp->netdev->pb->frags, skb, tmp) {
1802   - __skb_unlink(skb, &lp->netdev->pb->frags);
1803   - isdn_ppp_mp_free_skb(lp->netdev->pb, skb);
  1814 + struct sk_buff * frag = lp->netdev->pb->frags;
  1815 + struct sk_buff * nextfrag;
  1816 + while( frag ) {
  1817 + nextfrag = frag->next;
  1818 + isdn_ppp_mp_free_skb(lp->netdev->pb, frag);
  1819 + frag = nextfrag;
1804 1820 }
  1821 + lp->netdev->pb->frags = NULL;
1805 1822 }
1806 1823  
1807 1824 static u32 isdn_ppp_mp_get_seq( int short_seq,
1808 1825  
1809 1826  
1810 1827  
1811 1828  
1812 1829  
1813 1830  
1814 1831  
1815 1832  
1816 1833  
1817 1834  
1818 1835  
1819 1836  
1820 1837  
1821 1838  
1822 1839  
1823 1840  
... ... @@ -1838,115 +1855,72 @@
1838 1855 return seq;
1839 1856 }
1840 1857  
1841   -static void isdn_ppp_mp_discard(ippp_bundle *mp, struct sk_buff *from,
1842   - struct sk_buff *to)
  1858 +struct sk_buff * isdn_ppp_mp_discard( ippp_bundle * mp,
  1859 + struct sk_buff * from, struct sk_buff * to )
1843 1860 {
1844   - if (from) {
1845   - struct sk_buff *skb, *tmp;
1846   - int freeing = 0;
1847   -
1848   - skb_queue_walk_safe(&mp->frags, skb, tmp) {
1849   - if (skb == to)
1850   - break;
1851   - if (skb == from)
1852   - freeing = 1;
1853   - if (!freeing)
1854   - continue;
1855   - __skb_unlink(skb, &mp->frags);
1856   - isdn_ppp_mp_free_skb(mp, skb);
  1861 + if( from )
  1862 + while (from != to) {
  1863 + struct sk_buff * next = from->next;
  1864 + isdn_ppp_mp_free_skb(mp, from);
  1865 + from = next;
1857 1866 }
1858   - }
  1867 + return from;
1859 1868 }
1860 1869  
1861   -static unsigned int calc_tot_len(struct sk_buff_head *queue,
1862   - struct sk_buff *from, struct sk_buff *to)
  1870 +void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp,
  1871 + struct sk_buff * from, struct sk_buff * to )
1863 1872 {
1864   - unsigned int tot_len = 0;
1865   - struct sk_buff *skb;
1866   - int found_start = 0;
1867   -
1868   - skb_queue_walk(queue, skb) {
1869   - if (skb == from)
1870   - found_start = 1;
1871   - if (!found_start)
1872   - continue;
1873   - tot_len += skb->len - MP_HEADER_LEN;
1874   - if (skb == to)
1875   - break;
1876   - }
1877   - return tot_len;
1878   -}
1879   -
1880   -/* Reassemble packet using fragments in the reassembly queue from
1881   - * 'from' until 'to', inclusive.
1882   - */
1883   -static void isdn_ppp_mp_reassembly(isdn_net_dev *net_dev, isdn_net_local *lp,
1884   - struct sk_buff *from, struct sk_buff *to,
1885   - u32 lastseq)
1886   -{
1887   - ippp_bundle *mp = net_dev->pb;
1888   - unsigned int tot_len;
1889   - struct sk_buff *skb;
  1873 + ippp_bundle * mp = net_dev->pb;
1890 1874 int proto;
  1875 + struct sk_buff * skb;
  1876 + unsigned int tot_len;
1891 1877  
1892 1878 if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
1893 1879 printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
1894 1880 __func__, lp->ppp_slot);
1895 1881 return;
1896 1882 }
1897   -
1898   - tot_len = calc_tot_len(&mp->frags, from, to);
1899   -
1900   - if (MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG)) {
1901   - if (ippp_table[lp->ppp_slot]->debug & 0x40)
  1883 + if( MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG) ) {
  1884 + if( ippp_table[lp->ppp_slot]->debug & 0x40 )
1902 1885 printk(KERN_DEBUG "isdn_mppp: reassembly: frame %d, "
1903   - "len %d\n", MP_SEQ(from), from->len);
  1886 + "len %d\n", MP_SEQ(from), from->len );
1904 1887 skb = from;
1905 1888 skb_pull(skb, MP_HEADER_LEN);
1906   - __skb_unlink(skb, &mp->frags);
1907 1889 mp->frames--;
1908 1890 } else {
1909   - struct sk_buff *walk, *tmp;
1910   - int found_start = 0;
  1891 + struct sk_buff * frag;
  1892 + int n;
1911 1893  
1912   - if (ippp_table[lp->ppp_slot]->debug & 0x40)
1913   - printk(KERN_DEBUG"isdn_mppp: reassembling frames %d "
1914   - "to %d, len %d\n", MP_SEQ(from), lastseq,
1915   - tot_len);
  1894 + for(tot_len=n=0, frag=from; frag != to; frag=frag->next, n++)
  1895 + tot_len += frag->len - MP_HEADER_LEN;
1916 1896  
1917   - skb = dev_alloc_skb(tot_len);
1918   - if (!skb)
  1897 + if( ippp_table[lp->ppp_slot]->debug & 0x40 )
  1898 + printk(KERN_DEBUG"isdn_mppp: reassembling frames %d "
  1899 + "to %d, len %d\n", MP_SEQ(from),
  1900 + (MP_SEQ(from)+n-1) & MP_LONGSEQ_MASK, tot_len );
  1901 + if( (skb = dev_alloc_skb(tot_len)) == NULL ) {
1919 1902 printk(KERN_ERR "isdn_mppp: cannot allocate sk buff "
1920   - "of size %d\n", tot_len);
  1903 + "of size %d\n", tot_len);
  1904 + isdn_ppp_mp_discard(mp, from, to);
  1905 + return;
  1906 + }
1921 1907  
1922   - found_start = 0;
1923   - skb_queue_walk_safe(&mp->frags, walk, tmp) {
1924   - if (walk == from)
1925   - found_start = 1;
1926   - if (!found_start)
1927   - continue;
  1908 + while( from != to ) {
  1909 + unsigned int len = from->len - MP_HEADER_LEN;
1928 1910  
1929   - if (skb) {
1930   - unsigned int len = walk->len - MP_HEADER_LEN;
1931   - skb_copy_from_linear_data_offset(walk, MP_HEADER_LEN,
1932   - skb_put(skb, len),
1933   - len);
1934   - }
1935   - __skb_unlink(walk, &mp->frags);
1936   - isdn_ppp_mp_free_skb(mp, walk);
1937   -
1938   - if (walk == to)
1939   - break;
  1911 + skb_copy_from_linear_data_offset(from, MP_HEADER_LEN,
  1912 + skb_put(skb,len),
  1913 + len);
  1914 + frag = from->next;
  1915 + isdn_ppp_mp_free_skb(mp, from);
  1916 + from = frag;
1940 1917 }
1941 1918 }
1942   - if (!skb)
1943   - return;
1944   -
1945 1919 proto = isdn_ppp_strip_proto(skb);
1946 1920 isdn_ppp_push_higher(net_dev, lp, skb, proto);
1947 1921 }
1948 1922  
1949   -static void isdn_ppp_mp_free_skb(ippp_bundle *mp, struct sk_buff *skb)
  1923 +static void isdn_ppp_mp_free_skb(ippp_bundle * mp, struct sk_buff * skb)
1950 1924 {
1951 1925 dev_kfree_skb(skb);
1952 1926 mp->frames--;
include/linux/isdn_ppp.h
... ... @@ -157,7 +157,7 @@
157 157  
158 158 typedef struct {
159 159 int mp_mrru; /* unused */
160   - struct sk_buff_head frags; /* fragments sl list */
  160 + struct sk_buff * frags; /* fragments sl list -- use skb->next */
161 161 long frames; /* number of frames in the frame list */
162 162 unsigned int seq; /* last processed packet seq #: any packets
163 163 * with smaller seq # will be dropped