Commit 409f0a90 authored by David S. Miller's avatar David S. Miller

Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6

Conflicts:
	drivers/net/wireless/iwlwifi/iwl-agn.c
	drivers/net/wireless/iwlwifi/iwl3945-base.c
parents 59372183 0b492fce
...@@ -1482,6 +1482,7 @@ el3_resume(struct device *pdev) ...@@ -1482,6 +1482,7 @@ el3_resume(struct device *pdev)
spin_lock_irqsave(&lp->lock, flags); spin_lock_irqsave(&lp->lock, flags);
outw(PowerUp, ioaddr + EL3_CMD); outw(PowerUp, ioaddr + EL3_CMD);
EL3WINDOW(0);
el3_up(dev); el3_up(dev);
if (netif_running(dev)) if (netif_running(dev))
......
...@@ -437,6 +437,22 @@ enum features { ...@@ -437,6 +437,22 @@ enum features {
RTL_FEATURE_GMII = (1 << 2), RTL_FEATURE_GMII = (1 << 2),
}; };
struct rtl8169_counters {
__le64 tx_packets;
__le64 rx_packets;
__le64 tx_errors;
__le32 rx_errors;
__le16 rx_missed;
__le16 align_errors;
__le32 tx_one_collision;
__le32 tx_multi_collision;
__le64 rx_unicast;
__le64 rx_broadcast;
__le32 rx_multicast;
__le16 tx_aborted;
__le16 tx_underun;
};
struct rtl8169_private { struct rtl8169_private {
void __iomem *mmio_addr; /* memory map physical address */ void __iomem *mmio_addr; /* memory map physical address */
struct pci_dev *pci_dev; /* Index of PCI device */ struct pci_dev *pci_dev; /* Index of PCI device */
...@@ -480,6 +496,7 @@ struct rtl8169_private { ...@@ -480,6 +496,7 @@ struct rtl8169_private {
unsigned features; unsigned features;
struct mii_if_info mii; struct mii_if_info mii;
struct rtl8169_counters counters;
}; };
MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>"); MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
...@@ -1100,22 +1117,6 @@ static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = { ...@@ -1100,22 +1117,6 @@ static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = {
"tx_underrun", "tx_underrun",
}; };
struct rtl8169_counters {
__le64 tx_packets;
__le64 rx_packets;
__le64 tx_errors;
__le32 rx_errors;
__le16 rx_missed;
__le16 align_errors;
__le32 tx_one_collision;
__le32 tx_multi_collision;
__le64 rx_unicast;
__le64 rx_broadcast;
__le32 rx_multicast;
__le16 tx_aborted;
__le16 tx_underun;
};
static int rtl8169_get_sset_count(struct net_device *dev, int sset) static int rtl8169_get_sset_count(struct net_device *dev, int sset)
{ {
switch (sset) { switch (sset) {
...@@ -1126,16 +1127,21 @@ static int rtl8169_get_sset_count(struct net_device *dev, int sset) ...@@ -1126,16 +1127,21 @@ static int rtl8169_get_sset_count(struct net_device *dev, int sset)
} }
} }
static void rtl8169_get_ethtool_stats(struct net_device *dev, static void rtl8169_update_counters(struct net_device *dev)
struct ethtool_stats *stats, u64 *data)
{ {
struct rtl8169_private *tp = netdev_priv(dev); struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr; void __iomem *ioaddr = tp->mmio_addr;
struct rtl8169_counters *counters; struct rtl8169_counters *counters;
dma_addr_t paddr; dma_addr_t paddr;
u32 cmd; u32 cmd;
int wait = 1000;
ASSERT_RTNL(); /*
* Some chips are unable to dump tally counters when the receiver
* is disabled.
*/
if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0)
return;
counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr); counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr);
if (!counters) if (!counters)
...@@ -1146,31 +1152,45 @@ static void rtl8169_get_ethtool_stats(struct net_device *dev, ...@@ -1146,31 +1152,45 @@ static void rtl8169_get_ethtool_stats(struct net_device *dev,
RTL_W32(CounterAddrLow, cmd); RTL_W32(CounterAddrLow, cmd);
RTL_W32(CounterAddrLow, cmd | CounterDump); RTL_W32(CounterAddrLow, cmd | CounterDump);
while (RTL_R32(CounterAddrLow) & CounterDump) { while (wait--) {
if (msleep_interruptible(1)) if ((RTL_R32(CounterAddrLow) & CounterDump) == 0) {
/* copy updated counters */
memcpy(&tp->counters, counters, sizeof(*counters));
break; break;
} }
udelay(10);
}
RTL_W32(CounterAddrLow, 0); RTL_W32(CounterAddrLow, 0);
RTL_W32(CounterAddrHigh, 0); RTL_W32(CounterAddrHigh, 0);
data[0] = le64_to_cpu(counters->tx_packets);
data[1] = le64_to_cpu(counters->rx_packets);
data[2] = le64_to_cpu(counters->tx_errors);
data[3] = le32_to_cpu(counters->rx_errors);
data[4] = le16_to_cpu(counters->rx_missed);
data[5] = le16_to_cpu(counters->align_errors);
data[6] = le32_to_cpu(counters->tx_one_collision);
data[7] = le32_to_cpu(counters->tx_multi_collision);
data[8] = le64_to_cpu(counters->rx_unicast);
data[9] = le64_to_cpu(counters->rx_broadcast);
data[10] = le32_to_cpu(counters->rx_multicast);
data[11] = le16_to_cpu(counters->tx_aborted);
data[12] = le16_to_cpu(counters->tx_underun);
pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr); pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr);
} }
static void rtl8169_get_ethtool_stats(struct net_device *dev,
struct ethtool_stats *stats, u64 *data)
{
struct rtl8169_private *tp = netdev_priv(dev);
ASSERT_RTNL();
rtl8169_update_counters(dev);
data[0] = le64_to_cpu(tp->counters.tx_packets);
data[1] = le64_to_cpu(tp->counters.rx_packets);
data[2] = le64_to_cpu(tp->counters.tx_errors);
data[3] = le32_to_cpu(tp->counters.rx_errors);
data[4] = le16_to_cpu(tp->counters.rx_missed);
data[5] = le16_to_cpu(tp->counters.align_errors);
data[6] = le32_to_cpu(tp->counters.tx_one_collision);
data[7] = le32_to_cpu(tp->counters.tx_multi_collision);
data[8] = le64_to_cpu(tp->counters.rx_unicast);
data[9] = le64_to_cpu(tp->counters.rx_broadcast);
data[10] = le32_to_cpu(tp->counters.rx_multicast);
data[11] = le16_to_cpu(tp->counters.tx_aborted);
data[12] = le16_to_cpu(tp->counters.tx_underun);
}
static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
{ {
switch(stringset) { switch(stringset) {
...@@ -3682,6 +3702,9 @@ static int rtl8169_close(struct net_device *dev) ...@@ -3682,6 +3702,9 @@ static int rtl8169_close(struct net_device *dev)
struct rtl8169_private *tp = netdev_priv(dev); struct rtl8169_private *tp = netdev_priv(dev);
struct pci_dev *pdev = tp->pci_dev; struct pci_dev *pdev = tp->pci_dev;
/* update counters before going down */
rtl8169_update_counters(dev);
rtl8169_down(dev); rtl8169_down(dev);
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
......
...@@ -2221,6 +2221,8 @@ static int gem_do_start(struct net_device *dev) ...@@ -2221,6 +2221,8 @@ static int gem_do_start(struct net_device *dev)
gp->running = 1; gp->running = 1;
napi_enable(&gp->napi);
if (gp->lstate == link_up) { if (gp->lstate == link_up) {
netif_carrier_on(gp->dev); netif_carrier_on(gp->dev);
gem_set_link_modes(gp); gem_set_link_modes(gp);
...@@ -2238,6 +2240,8 @@ static int gem_do_start(struct net_device *dev) ...@@ -2238,6 +2240,8 @@ static int gem_do_start(struct net_device *dev)
spin_lock_irqsave(&gp->lock, flags); spin_lock_irqsave(&gp->lock, flags);
spin_lock(&gp->tx_lock); spin_lock(&gp->tx_lock);
napi_disable(&gp->napi);
gp->running = 0; gp->running = 0;
gem_reset(gp); gem_reset(gp);
gem_clean_rings(gp); gem_clean_rings(gp);
...@@ -2338,8 +2342,6 @@ static int gem_open(struct net_device *dev) ...@@ -2338,8 +2342,6 @@ static int gem_open(struct net_device *dev)
if (!gp->asleep) if (!gp->asleep)
rc = gem_do_start(dev); rc = gem_do_start(dev);
gp->opened = (rc == 0); gp->opened = (rc == 0);
if (gp->opened)
napi_enable(&gp->napi);
mutex_unlock(&gp->pm_mutex); mutex_unlock(&gp->pm_mutex);
...@@ -2476,8 +2478,6 @@ static int gem_resume(struct pci_dev *pdev) ...@@ -2476,8 +2478,6 @@ static int gem_resume(struct pci_dev *pdev)
/* Re-attach net device */ /* Re-attach net device */
netif_device_attach(dev); netif_device_attach(dev);
napi_enable(&gp->napi);
} }
spin_lock_irqsave(&gp->lock, flags); spin_lock_irqsave(&gp->lock, flags);
......
...@@ -2629,6 +2629,14 @@ static int __devinit happy_meal_sbus_probe_one(struct of_device *op, int is_qfe) ...@@ -2629,6 +2629,14 @@ static int __devinit happy_meal_sbus_probe_one(struct of_device *op, int is_qfe)
int i, qfe_slot = -1; int i, qfe_slot = -1;
int err = -ENODEV; int err = -ENODEV;
sbus_dp = to_of_device(op->dev.parent)->node;
if (is_qfe)
sbus_dp = to_of_device(op->dev.parent->parent)->node;
/* We can match PCI devices too, do not accept those here. */
if (strcmp(sbus_dp->name, "sbus"))
return err;
if (is_qfe) { if (is_qfe) {
qp = quattro_sbus_find(op); qp = quattro_sbus_find(op);
if (qp == NULL) if (qp == NULL)
...@@ -2734,10 +2742,6 @@ static int __devinit happy_meal_sbus_probe_one(struct of_device *op, int is_qfe) ...@@ -2734,10 +2742,6 @@ static int __devinit happy_meal_sbus_probe_one(struct of_device *op, int is_qfe)
if (qp != NULL) if (qp != NULL)
hp->happy_flags |= HFLAG_QUATTRO; hp->happy_flags |= HFLAG_QUATTRO;
sbus_dp = to_of_device(op->dev.parent)->node;
if (is_qfe)
sbus_dp = to_of_device(op->dev.parent->parent)->node;
/* Get the supported DVMA burst sizes from our Happy SBUS. */ /* Get the supported DVMA burst sizes from our Happy SBUS. */
hp->happy_bursts = of_getintprop_default(sbus_dp, hp->happy_bursts = of_getintprop_default(sbus_dp,
"burst-sizes", 0x00); "burst-sizes", 0x00);
......
...@@ -483,6 +483,9 @@ void iwl_clear_stations_table(struct iwl_priv *priv) ...@@ -483,6 +483,9 @@ void iwl_clear_stations_table(struct iwl_priv *priv)
priv->num_stations = 0; priv->num_stations = 0;
memset(priv->stations, 0, sizeof(priv->stations)); memset(priv->stations, 0, sizeof(priv->stations));
/* clean ucode key table bit map */
priv->ucode_key_table = 0;
spin_unlock_irqrestore(&priv->sta_lock, flags); spin_unlock_irqrestore(&priv->sta_lock, flags);
} }
EXPORT_SYMBOL(iwl_clear_stations_table); EXPORT_SYMBOL(iwl_clear_stations_table);
......
...@@ -282,6 +282,18 @@ static inline void dmaengine_put(void) ...@@ -282,6 +282,18 @@ static inline void dmaengine_put(void)
} }
#endif #endif
#ifdef CONFIG_NET_DMA
#define net_dmaengine_get() dmaengine_get()
#define net_dmaengine_put() dmaengine_put()
#else
static inline void net_dmaengine_get(void)
{
}
static inline void net_dmaengine_put(void)
{
}
#endif
dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan, dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan,
void *dest, void *src, size_t len); void *dest, void *src, size_t len);
dma_cookie_t dma_async_memcpy_buf_to_pg(struct dma_chan *chan, dma_cookie_t dma_async_memcpy_buf_to_pg(struct dma_chan *chan,
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/types.h>
#include <net/9p/9p.h> #include <net/9p/9p.h>
#include <net/9p/client.h> #include <net/9p/client.h>
#include "protocol.h" #include "protocol.h"
...@@ -160,29 +161,32 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) ...@@ -160,29 +161,32 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
break; break;
case 'w':{ case 'w':{
int16_t *val = va_arg(ap, int16_t *); int16_t *val = va_arg(ap, int16_t *);
if (pdu_read(pdu, val, sizeof(*val))) { __le16 le_val;
if (pdu_read(pdu, &le_val, sizeof(le_val))) {
errcode = -EFAULT; errcode = -EFAULT;
break; break;
} }
*val = cpu_to_le16(*val); *val = le16_to_cpu(le_val);
} }
break; break;
case 'd':{ case 'd':{
int32_t *val = va_arg(ap, int32_t *); int32_t *val = va_arg(ap, int32_t *);
if (pdu_read(pdu, val, sizeof(*val))) { __le32 le_val;
if (pdu_read(pdu, &le_val, sizeof(le_val))) {
errcode = -EFAULT; errcode = -EFAULT;
break; break;
} }
*val = cpu_to_le32(*val); *val = le32_to_cpu(le_val);
} }
break; break;
case 'q':{ case 'q':{
int64_t *val = va_arg(ap, int64_t *); int64_t *val = va_arg(ap, int64_t *);
if (pdu_read(pdu, val, sizeof(*val))) { __le64 le_val;
if (pdu_read(pdu, &le_val, sizeof(le_val))) {
errcode = -EFAULT; errcode = -EFAULT;
break; break;
} }
*val = cpu_to_le64(*val); *val = le64_to_cpu(le_val);
} }
break; break;
case 's':{ case 's':{
...@@ -362,19 +366,19 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) ...@@ -362,19 +366,19 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
} }
break; break;
case 'w':{ case 'w':{
int16_t val = va_arg(ap, int); __le16 val = cpu_to_le16(va_arg(ap, int));
if (pdu_write(pdu, &val, sizeof(val))) if (pdu_write(pdu, &val, sizeof(val)))
errcode = -EFAULT; errcode = -EFAULT;
} }
break; break;
case 'd':{ case 'd':{
int32_t val = va_arg(ap, int32_t); __le32 val = cpu_to_le32(va_arg(ap, int32_t));
if (pdu_write(pdu, &val, sizeof(val))) if (pdu_write(pdu, &val, sizeof(val)))
errcode = -EFAULT; errcode = -EFAULT;
} }
break; break;
case 'q':{ case 'q':{
int64_t val = va_arg(ap, int64_t); __le64 val = cpu_to_le64(va_arg(ap, int64_t));
if (pdu_write(pdu, &val, sizeof(val))) if (pdu_write(pdu, &val, sizeof(val)))
errcode = -EFAULT; errcode = -EFAULT;
} }
......
...@@ -1105,7 +1105,7 @@ int dev_open(struct net_device *dev) ...@@ -1105,7 +1105,7 @@ int dev_open(struct net_device *dev)
/* /*
* Enable NET_DMA * Enable NET_DMA
*/ */
dmaengine_get(); net_dmaengine_get();
/* /*
* Initialize multicasting status * Initialize multicasting status
...@@ -1187,7 +1187,7 @@ int dev_close(struct net_device *dev) ...@@ -1187,7 +1187,7 @@ int dev_close(struct net_device *dev)
/* /*
* Shutdown NET_DMA * Shutdown NET_DMA
*/ */
dmaengine_put(); net_dmaengine_put();
return 0; return 0;
} }
......
...@@ -1994,8 +1994,8 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -1994,8 +1994,8 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
if (!net_eq(neigh_parms_net(p), net)) if (!net_eq(neigh_parms_net(p), net))
continue; continue;
if (nidx++ < neigh_skip) if (nidx < neigh_skip)
continue; goto next;
if (neightbl_fill_param_info(skb, tbl, p, if (neightbl_fill_param_info(skb, tbl, p,
NETLINK_CB(cb->skb).pid, NETLINK_CB(cb->skb).pid,
...@@ -2003,6 +2003,8 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -2003,6 +2003,8 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
RTM_NEWNEIGHTBL, RTM_NEWNEIGHTBL,
NLM_F_MULTI) <= 0) NLM_F_MULTI) <= 0)
goto out; goto out;
next:
nidx++;
} }
neigh_skip = 0; neigh_skip = 0;
...@@ -2082,12 +2084,10 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, ...@@ -2082,12 +2084,10 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
if (h > s_h) if (h > s_h)
s_idx = 0; s_idx = 0;
for (n = tbl->hash_buckets[h], idx = 0; n; n = n->next) { for (n = tbl->hash_buckets[h], idx = 0; n; n = n->next) {
int lidx;
if (dev_net(n->dev) != net) if (dev_net(n->dev) != net)
continue; continue;
lidx = idx++; if (idx < s_idx)
if (lidx < s_idx) goto next;
continue;
if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).pid, if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq, cb->nlh->nlmsg_seq,
RTM_NEWNEIGH, RTM_NEWNEIGH,
...@@ -2096,6 +2096,8 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, ...@@ -2096,6 +2096,8 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
rc = -1; rc = -1;
goto out; goto out;
} }
next:
idx++;
} }
} }
read_unlock_bh(&tbl->lock); read_unlock_bh(&tbl->lock);
......
...@@ -663,14 +663,10 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, ...@@ -663,14 +663,10 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
th->urg_ptr = 0; th->urg_ptr = 0;
/* The urg_mode check is necessary during a below snd_una win probe */ /* The urg_mode check is necessary during a below snd_una win probe */
if (unlikely(tcp_urg_mode(tp))) { if (unlikely(tcp_urg_mode(tp) &&
if (between(tp->snd_up, tcb->seq + 1, tcb->seq + 0xFFFF)) { between(tp->snd_up, tcb->seq + 1, tcb->seq + 0xFFFF))) {
th->urg_ptr = htons(tp->snd_up - tcb->seq); th->urg_ptr = htons(tp->snd_up - tcb->seq);
th->urg = 1; th->urg = 1;
} else if (after(tcb->seq + 0xFFFF, tp->snd_nxt)) {
th->urg_ptr = 0xFFFF;
th->urg = 1;
}
} }
tcp_options_write((__be32 *)(th + 1), tp, &opts, &md5_hash_location); tcp_options_write((__be32 *)(th + 1), tp, &opts, &md5_hash_location);
......
...@@ -1231,11 +1231,10 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, ...@@ -1231,11 +1231,10 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
int proto) int proto)
{ {
struct sock *sk; struct sock *sk;
struct udphdr *uh = udp_hdr(skb); struct udphdr *uh;
unsigned short ulen; unsigned short ulen;
struct rtable *rt = (struct rtable*)skb->dst; struct rtable *rt = (struct rtable*)skb->dst;
__be32 saddr = ip_hdr(skb)->saddr; __be32 saddr, daddr;
__be32 daddr = ip_hdr(skb)->daddr;
struct net *net = dev_net(skb->dev); struct net *net = dev_net(skb->dev);
/* /*
...@@ -1244,6 +1243,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, ...@@ -1244,6 +1243,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
if (!pskb_may_pull(skb, sizeof(struct udphdr))) if (!pskb_may_pull(skb, sizeof(struct udphdr)))
goto drop; /* No space for header. */ goto drop; /* No space for header. */
uh = udp_hdr(skb);
ulen = ntohs(uh->len); ulen = ntohs(uh->len);
if (ulen > skb->len) if (ulen > skb->len)
goto short_packet; goto short_packet;
...@@ -1258,6 +1258,9 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, ...@@ -1258,6 +1258,9 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
if (udp4_csum_init(skb, uh, proto)) if (udp4_csum_init(skb, uh, proto))
goto csum_error; goto csum_error;
saddr = ip_hdr(skb)->saddr;
daddr = ip_hdr(skb)->daddr;
if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST)) if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
return __udp4_lib_mcast_deliver(net, skb, uh, return __udp4_lib_mcast_deliver(net, skb, uh,
saddr, daddr, udptable); saddr, daddr, udptable);
......
...@@ -323,17 +323,21 @@ static struct ip6_flowlabel * ...@@ -323,17 +323,21 @@ static struct ip6_flowlabel *
fl_create(struct net *net, struct in6_flowlabel_req *freq, char __user *optval, fl_create(struct net *net, struct in6_flowlabel_req *freq, char __user *optval,
int optlen, int *err_p) int optlen, int *err_p)
{ {
struct ip6_flowlabel *fl; struct ip6_flowlabel *fl = NULL;
int olen; int olen;
int addr_type; int addr_type;
int err; int err;
olen = optlen - CMSG_ALIGN(sizeof(*freq));
err = -EINVAL;
if (olen > 64 * 1024)
goto done;
err = -ENOMEM; err = -ENOMEM;
fl = kzalloc(sizeof(*fl), GFP_KERNEL); fl = kzalloc(sizeof(*fl), GFP_KERNEL);
if (fl == NULL) if (fl == NULL)
goto done; goto done;
olen = optlen - CMSG_ALIGN(sizeof(*freq));
if (olen > 0) { if (olen > 0) {
struct msghdr msg; struct msghdr msg;
struct flowi flowi; struct flowi flowi;
......
...@@ -1105,6 +1105,18 @@ static inline int ip6_ufo_append_data(struct sock *sk, ...@@ -1105,6 +1105,18 @@ static inline int ip6_ufo_append_data(struct sock *sk,
return err; return err;
} }
static inline struct ipv6_opt_hdr *ip6_opt_dup(struct ipv6_opt_hdr *src,
gfp_t gfp)
{
return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL;
}
static inline struct ipv6_rt_hdr *ip6_rthdr_dup(struct ipv6_rt_hdr *src,
gfp_t gfp)
{
return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL;
}
int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
int offset, int len, int odd, struct sk_buff *skb), int offset, int len, int odd, struct sk_buff *skb),
void *from, int length, int transhdrlen, void *from, int length, int transhdrlen,
...@@ -1130,17 +1142,37 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, ...@@ -1130,17 +1142,37 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
* setup for corking * setup for corking
*/ */
if (opt) { if (opt) {
if (np->cork.opt == NULL) { if (WARN_ON(np->cork.opt))
np->cork.opt = kmalloc(opt->tot_len, return -EINVAL;
sk->sk_allocation);
np->cork.opt = kmalloc(opt->tot_len, sk->sk_allocation);
if (unlikely(np->cork.opt == NULL)) if (unlikely(np->cork.opt == NULL))
return -ENOBUFS; return -ENOBUFS;
} else if (np->cork.opt->tot_len < opt->tot_len) {
printk(KERN_DEBUG "ip6_append_data: invalid option length\n"); np->cork.opt->tot_len = opt->tot_len;
return -EINVAL; np->cork.opt->opt_flen = opt->opt_flen;
} np->cork.opt->opt_nflen = opt->opt_nflen;
memcpy(np->cork.opt, opt, opt->tot_len);
inet->cork.flags |= IPCORK_OPT; np->cork.opt->dst0opt = ip6_opt_dup(opt->dst0opt,
sk->sk_allocation);
if (opt->dst0opt && !np->cork.opt->dst0opt)
return -ENOBUFS;
np->cork.opt->dst1opt = ip6_opt_dup(opt->dst1opt,
sk->sk_allocation);
if (opt->dst1opt && !np->cork.opt->dst1opt)
return -ENOBUFS;
np->cork.opt->hopopt = ip6_opt_dup(opt->hopopt,
sk->sk_allocation);
if (opt->hopopt && !np->cork.opt->hopopt)
return -ENOBUFS;
np->cork.opt->srcrt = ip6_rthdr_dup(opt->srcrt,
sk->sk_allocation);
if (opt->srcrt && !np->cork.opt->srcrt)
return -ENOBUFS;
/* need source address above miyazawa*/ /* need source address above miyazawa*/
} }
dst_hold(&rt->u.dst); dst_hold(&rt->u.dst);
...@@ -1167,7 +1199,6 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, ...@@ -1167,7 +1199,6 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
} else { } else {
rt = (struct rt6_info *)inet->cork.dst; rt = (struct rt6_info *)inet->cork.dst;
fl = &inet->cork.fl; fl = &inet->cork.fl;
if (inet->cork.flags & IPCORK_OPT)
opt = np->cork.opt; opt = np->cork.opt;
transhdrlen = 0; transhdrlen = 0;
exthdrlen = 0; exthdrlen = 0;
...@@ -1407,9 +1438,15 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, ...@@ -1407,9 +1438,15 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np) static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np)
{ {
inet->cork.flags &= ~IPCORK_OPT; if (np->cork.opt) {
kfree(np->cork.opt->dst0opt);
kfree(np->cork.opt->dst1opt);
kfree(np->cork.opt->hopopt);
kfree(np->cork.opt->srcrt);
kfree(np->cork.opt); kfree(np->cork.opt);
np->cork.opt = NULL; np->cork.opt = NULL;
}
if (inet->cork.dst) { if (inet->cork.dst) {
dst_release(inet->cork.dst); dst_release(inet->cork.dst);
inet->cork.dst = NULL; inet->cork.dst = NULL;
......
...@@ -284,13 +284,13 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock, ...@@ -284,13 +284,13 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
if (IS_ERR(trans)) { if (IS_ERR(trans)) {
call = ERR_CAST(trans); call = ERR_CAST(trans);
trans = NULL; trans = NULL;
goto out; goto out_notrans;
} }
} else { } else {
trans = rx->trans; trans = rx->trans;
if (!trans) { if (!trans) {
call = ERR_PTR(-ENOTCONN); call = ERR_PTR(-ENOTCONN);
goto out; goto out_notrans;
} }
atomic_inc(&trans->usage); atomic_inc(&trans->usage);
} }
...@@ -315,6 +315,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock, ...@@ -315,6 +315,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
rxrpc_put_bundle(trans, bundle); rxrpc_put_bundle(trans, bundle);
out: out:
rxrpc_put_transport(trans); rxrpc_put_transport(trans);
out_notrans:
release_sock(&rx->sk); release_sock(&rx->sk);
_leave(" = %p", call); _leave(" = %p", call);
return call; return call;
......
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