Commit 3985c7ce authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6:
  isdn: mISDN: socket: fix information leak to userland
  netdev: can: Change mail address of Hans J. Koch
  pcnet_cs: add new_id
  net: Truncate recvfrom and sendto length to INT_MAX.
  RDS: Let rds_message_alloc_sgs() return NULL
  RDS: Copy rds_iovecs into kernel memory instead of rereading from userspace
  RDS: Clean up error handling in rds_cmsg_rdma_args
  RDS: Return -EINVAL if rds_rdma_pages returns an error
  net: fix rds_iovec page count overflow
  can: pch_can: fix section mismatch warning by using a whitelisted name
  can: pch_can: fix sparse warning
  netxen_nic: Fix the tx queue manipulation bug in netxen_nic_probe
  ip_gre: fix fallback tunnel setup
  vmxnet: trivial annotation of protocol constant
  vmxnet3: remove unnecessary byteswapping in BAR writing macros
  ipv6/udp: report SndbufErrors and RcvbufErrors
  phy/marvell: rename 88ec048 to 88e1318s and fix mscr1 addr
parents fcf744a9 ce384d91
...@@ -392,6 +392,7 @@ data_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -392,6 +392,7 @@ data_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
if (dev) { if (dev) {
struct mISDN_devinfo di; struct mISDN_devinfo di;
memset(&di, 0, sizeof(di));
di.id = dev->id; di.id = dev->id;
di.Dprotocols = dev->Dprotocols; di.Dprotocols = dev->Dprotocols;
di.Bprotocols = dev->Bprotocols | get_all_Bprotocols(); di.Bprotocols = dev->Bprotocols | get_all_Bprotocols();
...@@ -672,6 +673,7 @@ base_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -672,6 +673,7 @@ base_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
if (dev) { if (dev) {
struct mISDN_devinfo di; struct mISDN_devinfo di;
memset(&di, 0, sizeof(di));
di.id = dev->id; di.id = dev->id;
di.Dprotocols = dev->Dprotocols; di.Dprotocols = dev->Dprotocols;
di.Bprotocols = dev->Bprotocols | get_all_Bprotocols(); di.Bprotocols = dev->Bprotocols | get_all_Bprotocols();
......
/* /*
* at91_can.c - CAN network driver for AT91 SoC CAN controller * at91_can.c - CAN network driver for AT91 SoC CAN controller
* *
* (C) 2007 by Hans J. Koch <hjk@linutronix.de> * (C) 2007 by Hans J. Koch <hjk@hansjkoch.de>
* (C) 2008, 2009, 2010 by Marc Kleine-Budde <kernel@pengutronix.de> * (C) 2008, 2009, 2010 by Marc Kleine-Budde <kernel@pengutronix.de>
* *
* This software may be distributed under the terms of the GNU General * This software may be distributed under the terms of the GNU General
......
...@@ -213,12 +213,12 @@ static DEFINE_PCI_DEVICE_TABLE(pch_pci_tbl) = { ...@@ -213,12 +213,12 @@ static DEFINE_PCI_DEVICE_TABLE(pch_pci_tbl) = {
}; };
MODULE_DEVICE_TABLE(pci, pch_pci_tbl); MODULE_DEVICE_TABLE(pci, pch_pci_tbl);
static inline void pch_can_bit_set(u32 *addr, u32 mask) static inline void pch_can_bit_set(void __iomem *addr, u32 mask)
{ {
iowrite32(ioread32(addr) | mask, addr); iowrite32(ioread32(addr) | mask, addr);
} }
static inline void pch_can_bit_clear(u32 *addr, u32 mask) static inline void pch_can_bit_clear(void __iomem *addr, u32 mask)
{ {
iowrite32(ioread32(addr) & ~mask, addr); iowrite32(ioread32(addr) & ~mask, addr);
} }
...@@ -1437,7 +1437,7 @@ static int __devinit pch_can_probe(struct pci_dev *pdev, ...@@ -1437,7 +1437,7 @@ static int __devinit pch_can_probe(struct pci_dev *pdev,
return rc; return rc;
} }
static struct pci_driver pch_can_pcidev = { static struct pci_driver pch_can_pci_driver = {
.name = "pch_can", .name = "pch_can",
.id_table = pch_pci_tbl, .id_table = pch_pci_tbl,
.probe = pch_can_probe, .probe = pch_can_probe,
...@@ -1448,13 +1448,13 @@ static struct pci_driver pch_can_pcidev = { ...@@ -1448,13 +1448,13 @@ static struct pci_driver pch_can_pcidev = {
static int __init pch_can_pci_init(void) static int __init pch_can_pci_init(void)
{ {
return pci_register_driver(&pch_can_pcidev); return pci_register_driver(&pch_can_pci_driver);
} }
module_init(pch_can_pci_init); module_init(pch_can_pci_init);
static void __exit pch_can_pci_exit(void) static void __exit pch_can_pci_exit(void)
{ {
pci_unregister_driver(&pch_can_pcidev); pci_unregister_driver(&pch_can_pci_driver);
} }
module_exit(pch_can_pci_exit); module_exit(pch_can_pci_exit);
......
...@@ -1240,7 +1240,6 @@ netxen_setup_netdev(struct netxen_adapter *adapter, ...@@ -1240,7 +1240,6 @@ netxen_setup_netdev(struct netxen_adapter *adapter,
dev_warn(&pdev->dev, "failed to read mac addr\n"); dev_warn(&pdev->dev, "failed to read mac addr\n");
netif_carrier_off(netdev); netif_carrier_off(netdev);
netif_stop_queue(netdev);
err = register_netdev(netdev); err = register_netdev(netdev);
if (err) { if (err) {
......
...@@ -1536,6 +1536,7 @@ static struct pcmcia_device_id pcnet_ids[] = { ...@@ -1536,6 +1536,7 @@ static struct pcmcia_device_id pcnet_ids[] = {
PCMCIA_DEVICE_PROD_ID12("COMPU-SHACK", "FASTline PCMCIA 10/100 Fast-Ethernet", 0xfa2e424d, 0x3953d9b9), PCMCIA_DEVICE_PROD_ID12("COMPU-SHACK", "FASTline PCMCIA 10/100 Fast-Ethernet", 0xfa2e424d, 0x3953d9b9),
PCMCIA_DEVICE_PROD_ID12("CONTEC", "C-NET(PC)C-10L", 0x21cab552, 0xf6f90722), PCMCIA_DEVICE_PROD_ID12("CONTEC", "C-NET(PC)C-10L", 0x21cab552, 0xf6f90722),
PCMCIA_DEVICE_PROD_ID12("corega", "FEther PCC-TXF", 0x0a21501a, 0xa51564a2), PCMCIA_DEVICE_PROD_ID12("corega", "FEther PCC-TXF", 0x0a21501a, 0xa51564a2),
PCMCIA_DEVICE_PROD_ID12("corega", "Ether CF-TD", 0x0a21501a, 0x6589340a),
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-T", 0x5261440f, 0xfa9d85bd), PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-T", 0x5261440f, 0xfa9d85bd),
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-TD", 0x5261440f, 0xc49bd73d), PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-TD", 0x5261440f, 0xc49bd73d),
PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d), PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d),
......
...@@ -74,8 +74,8 @@ ...@@ -74,8 +74,8 @@
#define MII_88E1121_PHY_MSCR_TX_DELAY BIT(4) #define MII_88E1121_PHY_MSCR_TX_DELAY BIT(4)
#define MII_88E1121_PHY_MSCR_DELAY_MASK (~(0x3 << 4)) #define MII_88E1121_PHY_MSCR_DELAY_MASK (~(0x3 << 4))
#define MII_88EC048_PHY_MSCR1_REG 16 #define MII_88E1318S_PHY_MSCR1_REG 16
#define MII_88EC048_PHY_MSCR1_PAD_ODD BIT(6) #define MII_88E1318S_PHY_MSCR1_PAD_ODD BIT(6)
#define MII_88E1121_PHY_LED_CTRL 16 #define MII_88E1121_PHY_LED_CTRL 16
#define MII_88E1121_PHY_LED_PAGE 3 #define MII_88E1121_PHY_LED_PAGE 3
...@@ -240,7 +240,7 @@ static int m88e1121_config_aneg(struct phy_device *phydev) ...@@ -240,7 +240,7 @@ static int m88e1121_config_aneg(struct phy_device *phydev)
return err; return err;
} }
static int m88ec048_config_aneg(struct phy_device *phydev) static int m88e1318_config_aneg(struct phy_device *phydev)
{ {
int err, oldpage, mscr; int err, oldpage, mscr;
...@@ -251,10 +251,10 @@ static int m88ec048_config_aneg(struct phy_device *phydev) ...@@ -251,10 +251,10 @@ static int m88ec048_config_aneg(struct phy_device *phydev)
if (err < 0) if (err < 0)
return err; return err;
mscr = phy_read(phydev, MII_88EC048_PHY_MSCR1_REG); mscr = phy_read(phydev, MII_88E1318S_PHY_MSCR1_REG);
mscr |= MII_88EC048_PHY_MSCR1_PAD_ODD; mscr |= MII_88E1318S_PHY_MSCR1_PAD_ODD;
err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr); err = phy_write(phydev, MII_88E1318S_PHY_MSCR1_REG, mscr);
if (err < 0) if (err < 0)
return err; return err;
...@@ -659,12 +659,12 @@ static struct phy_driver marvell_drivers[] = { ...@@ -659,12 +659,12 @@ static struct phy_driver marvell_drivers[] = {
.driver = { .owner = THIS_MODULE }, .driver = { .owner = THIS_MODULE },
}, },
{ {
.phy_id = MARVELL_PHY_ID_88EC048, .phy_id = MARVELL_PHY_ID_88E1318S,
.phy_id_mask = MARVELL_PHY_ID_MASK, .phy_id_mask = MARVELL_PHY_ID_MASK,
.name = "Marvell 88EC048", .name = "Marvell 88E1318S",
.features = PHY_GBIT_FEATURES, .features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT, .flags = PHY_HAS_INTERRUPT,
.config_aneg = &m88ec048_config_aneg, .config_aneg = &m88e1318_config_aneg,
.read_status = &marvell_read_status, .read_status = &marvell_read_status,
.ack_interrupt = &marvell_ack_interrupt, .ack_interrupt = &marvell_ack_interrupt,
.config_intr = &marvell_config_intr, .config_intr = &marvell_config_intr,
......
...@@ -873,7 +873,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq, ...@@ -873,7 +873,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) + count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) +
skb_shinfo(skb)->nr_frags + 1; skb_shinfo(skb)->nr_frags + 1;
ctx.ipv4 = (skb->protocol == __constant_ntohs(ETH_P_IP)); ctx.ipv4 = (skb->protocol == cpu_to_be16(ETH_P_IP));
ctx.mss = skb_shinfo(skb)->gso_size; ctx.mss = skb_shinfo(skb)->gso_size;
if (ctx.mss) { if (ctx.mss) {
......
...@@ -330,14 +330,14 @@ struct vmxnet3_adapter { ...@@ -330,14 +330,14 @@ struct vmxnet3_adapter {
}; };
#define VMXNET3_WRITE_BAR0_REG(adapter, reg, val) \ #define VMXNET3_WRITE_BAR0_REG(adapter, reg, val) \
writel(cpu_to_le32(val), (adapter)->hw_addr0 + (reg)) writel((val), (adapter)->hw_addr0 + (reg))
#define VMXNET3_READ_BAR0_REG(adapter, reg) \ #define VMXNET3_READ_BAR0_REG(adapter, reg) \
le32_to_cpu(readl((adapter)->hw_addr0 + (reg))) readl((adapter)->hw_addr0 + (reg))
#define VMXNET3_WRITE_BAR1_REG(adapter, reg, val) \ #define VMXNET3_WRITE_BAR1_REG(adapter, reg, val) \
writel(cpu_to_le32(val), (adapter)->hw_addr1 + (reg)) writel((val), (adapter)->hw_addr1 + (reg))
#define VMXNET3_READ_BAR1_REG(adapter, reg) \ #define VMXNET3_READ_BAR1_REG(adapter, reg) \
le32_to_cpu(readl((adapter)->hw_addr1 + (reg))) readl((adapter)->hw_addr1 + (reg))
#define VMXNET3_WAKE_QUEUE_THRESHOLD(tq) (5) #define VMXNET3_WAKE_QUEUE_THRESHOLD(tq) (5)
#define VMXNET3_RX_ALLOC_THRESHOLD(rq, ring_idx, adapter) \ #define VMXNET3_RX_ALLOC_THRESHOLD(rq, ring_idx, adapter) \
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#define MARVELL_PHY_ID_88E1121R 0x01410cb0 #define MARVELL_PHY_ID_88E1121R 0x01410cb0
#define MARVELL_PHY_ID_88E1145 0x01410cd0 #define MARVELL_PHY_ID_88E1145 0x01410cd0
#define MARVELL_PHY_ID_88E1240 0x01410e30 #define MARVELL_PHY_ID_88E1240 0x01410e30
#define MARVELL_PHY_ID_88EC048 0x01410e90 #define MARVELL_PHY_ID_88E1318S 0x01410e90
/* struct phy_device dev_flags definitions */ /* struct phy_device dev_flags definitions */
#define MARVELL_PHY_M1145_FLAGS_RESISTANCE 0x00000001 #define MARVELL_PHY_M1145_FLAGS_RESISTANCE 0x00000001
......
...@@ -1325,7 +1325,6 @@ static void ipgre_fb_tunnel_init(struct net_device *dev) ...@@ -1325,7 +1325,6 @@ static void ipgre_fb_tunnel_init(struct net_device *dev)
{ {
struct ip_tunnel *tunnel = netdev_priv(dev); struct ip_tunnel *tunnel = netdev_priv(dev);
struct iphdr *iph = &tunnel->parms.iph; struct iphdr *iph = &tunnel->parms.iph;
struct ipgre_net *ign = net_generic(dev_net(dev), ipgre_net_id);
tunnel->dev = dev; tunnel->dev = dev;
strcpy(tunnel->parms.name, dev->name); strcpy(tunnel->parms.name, dev->name);
...@@ -1336,7 +1335,6 @@ static void ipgre_fb_tunnel_init(struct net_device *dev) ...@@ -1336,7 +1335,6 @@ static void ipgre_fb_tunnel_init(struct net_device *dev)
tunnel->hlen = sizeof(struct iphdr) + 4; tunnel->hlen = sizeof(struct iphdr) + 4;
dev_hold(dev); dev_hold(dev);
rcu_assign_pointer(ign->tunnels_wc[0], tunnel);
} }
...@@ -1383,10 +1381,12 @@ static int __net_init ipgre_init_net(struct net *net) ...@@ -1383,10 +1381,12 @@ static int __net_init ipgre_init_net(struct net *net)
if ((err = register_netdev(ign->fb_tunnel_dev))) if ((err = register_netdev(ign->fb_tunnel_dev)))
goto err_reg_dev; goto err_reg_dev;
rcu_assign_pointer(ign->tunnels_wc[0],
netdev_priv(ign->fb_tunnel_dev));
return 0; return 0;
err_reg_dev: err_reg_dev:
free_netdev(ign->fb_tunnel_dev); ipgre_dev_free(ign->fb_tunnel_dev);
err_alloc_dev: err_alloc_dev:
return err; return err;
} }
......
...@@ -126,6 +126,8 @@ static const struct snmp_mib snmp6_udp6_list[] = { ...@@ -126,6 +126,8 @@ static const struct snmp_mib snmp6_udp6_list[] = {
SNMP_MIB_ITEM("Udp6NoPorts", UDP_MIB_NOPORTS), SNMP_MIB_ITEM("Udp6NoPorts", UDP_MIB_NOPORTS),
SNMP_MIB_ITEM("Udp6InErrors", UDP_MIB_INERRORS), SNMP_MIB_ITEM("Udp6InErrors", UDP_MIB_INERRORS),
SNMP_MIB_ITEM("Udp6OutDatagrams", UDP_MIB_OUTDATAGRAMS), SNMP_MIB_ITEM("Udp6OutDatagrams", UDP_MIB_OUTDATAGRAMS),
SNMP_MIB_ITEM("Udp6RcvbufErrors", UDP_MIB_RCVBUFERRORS),
SNMP_MIB_ITEM("Udp6SndbufErrors", UDP_MIB_SNDBUFERRORS),
SNMP_MIB_SENTINEL SNMP_MIB_SENTINEL
}; };
...@@ -134,6 +136,8 @@ static const struct snmp_mib snmp6_udplite6_list[] = { ...@@ -134,6 +136,8 @@ static const struct snmp_mib snmp6_udplite6_list[] = {
SNMP_MIB_ITEM("UdpLite6NoPorts", UDP_MIB_NOPORTS), SNMP_MIB_ITEM("UdpLite6NoPorts", UDP_MIB_NOPORTS),
SNMP_MIB_ITEM("UdpLite6InErrors", UDP_MIB_INERRORS), SNMP_MIB_ITEM("UdpLite6InErrors", UDP_MIB_INERRORS),
SNMP_MIB_ITEM("UdpLite6OutDatagrams", UDP_MIB_OUTDATAGRAMS), SNMP_MIB_ITEM("UdpLite6OutDatagrams", UDP_MIB_OUTDATAGRAMS),
SNMP_MIB_ITEM("UdpLite6RcvbufErrors", UDP_MIB_RCVBUFERRORS),
SNMP_MIB_ITEM("UdpLite6SndbufErrors", UDP_MIB_SNDBUFERRORS),
SNMP_MIB_SENTINEL SNMP_MIB_SENTINEL
}; };
......
...@@ -224,6 +224,9 @@ struct scatterlist *rds_message_alloc_sgs(struct rds_message *rm, int nents) ...@@ -224,6 +224,9 @@ struct scatterlist *rds_message_alloc_sgs(struct rds_message *rm, int nents)
WARN_ON(rm->m_used_sgs + nents > rm->m_total_sgs); WARN_ON(rm->m_used_sgs + nents > rm->m_total_sgs);
WARN_ON(!nents); WARN_ON(!nents);
if (rm->m_used_sgs + nents > rm->m_total_sgs)
return NULL;
sg_ret = &sg_first[rm->m_used_sgs]; sg_ret = &sg_first[rm->m_used_sgs];
sg_init_table(sg_ret, nents); sg_init_table(sg_ret, nents);
rm->m_used_sgs += nents; rm->m_used_sgs += nents;
...@@ -246,6 +249,8 @@ struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned in ...@@ -246,6 +249,8 @@ struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned in
rm->m_inc.i_hdr.h_len = cpu_to_be32(total_len); rm->m_inc.i_hdr.h_len = cpu_to_be32(total_len);
rm->data.op_nents = ceil(total_len, PAGE_SIZE); rm->data.op_nents = ceil(total_len, PAGE_SIZE);
rm->data.op_sg = rds_message_alloc_sgs(rm, num_sgs); rm->data.op_sg = rds_message_alloc_sgs(rm, num_sgs);
if (!rm->data.op_sg)
return ERR_PTR(-ENOMEM);
for (i = 0; i < rm->data.op_nents; ++i) { for (i = 0; i < rm->data.op_nents; ++i) {
sg_set_page(&rm->data.op_sg[i], sg_set_page(&rm->data.op_sg[i],
......
...@@ -479,13 +479,38 @@ void rds_atomic_free_op(struct rm_atomic_op *ao) ...@@ -479,13 +479,38 @@ void rds_atomic_free_op(struct rm_atomic_op *ao)
/* /*
* Count the number of pages needed to describe an incoming iovec. * Count the number of pages needed to describe an incoming iovec array.
*/ */
static int rds_rdma_pages(struct rds_rdma_args *args) static int rds_rdma_pages(struct rds_iovec iov[], int nr_iovecs)
{
int tot_pages = 0;
unsigned int nr_pages;
unsigned int i;
/* figure out the number of pages in the vector */
for (i = 0; i < nr_iovecs; i++) {
nr_pages = rds_pages_in_vec(&iov[i]);
if (nr_pages == 0)
return -EINVAL;
tot_pages += nr_pages;
/*
* nr_pages for one entry is limited to (UINT_MAX>>PAGE_SHIFT)+1,
* so tot_pages cannot overflow without first going negative.
*/
if (tot_pages < 0)
return -EINVAL;
}
return tot_pages;
}
int rds_rdma_extra_size(struct rds_rdma_args *args)
{ {
struct rds_iovec vec; struct rds_iovec vec;
struct rds_iovec __user *local_vec; struct rds_iovec __user *local_vec;
unsigned int tot_pages = 0; int tot_pages = 0;
unsigned int nr_pages; unsigned int nr_pages;
unsigned int i; unsigned int i;
...@@ -502,14 +527,16 @@ static int rds_rdma_pages(struct rds_rdma_args *args) ...@@ -502,14 +527,16 @@ static int rds_rdma_pages(struct rds_rdma_args *args)
return -EINVAL; return -EINVAL;
tot_pages += nr_pages; tot_pages += nr_pages;
}
return tot_pages; /*
} * nr_pages for one entry is limited to (UINT_MAX>>PAGE_SHIFT)+1,
* so tot_pages cannot overflow without first going negative.
*/
if (tot_pages < 0)
return -EINVAL;
}
int rds_rdma_extra_size(struct rds_rdma_args *args) return tot_pages * sizeof(struct scatterlist);
{
return rds_rdma_pages(args) * sizeof(struct scatterlist);
} }
/* /*
...@@ -520,13 +547,12 @@ int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm, ...@@ -520,13 +547,12 @@ int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
struct cmsghdr *cmsg) struct cmsghdr *cmsg)
{ {
struct rds_rdma_args *args; struct rds_rdma_args *args;
struct rds_iovec vec;
struct rm_rdma_op *op = &rm->rdma; struct rm_rdma_op *op = &rm->rdma;
int nr_pages; int nr_pages;
unsigned int nr_bytes; unsigned int nr_bytes;
struct page **pages = NULL; struct page **pages = NULL;
struct rds_iovec __user *local_vec; struct rds_iovec iovstack[UIO_FASTIOV], *iovs = iovstack;
unsigned int nr; int iov_size;
unsigned int i, j; unsigned int i, j;
int ret = 0; int ret = 0;
...@@ -546,9 +572,26 @@ int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm, ...@@ -546,9 +572,26 @@ int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
goto out; goto out;
} }
nr_pages = rds_rdma_pages(args); /* Check whether to allocate the iovec area */
if (nr_pages < 0) iov_size = args->nr_local * sizeof(struct rds_iovec);
if (args->nr_local > UIO_FASTIOV) {
iovs = sock_kmalloc(rds_rs_to_sk(rs), iov_size, GFP_KERNEL);
if (!iovs) {
ret = -ENOMEM;
goto out;
}
}
if (copy_from_user(iovs, (struct rds_iovec __user *)(unsigned long) args->local_vec_addr, iov_size)) {
ret = -EFAULT;
goto out;
}
nr_pages = rds_rdma_pages(iovs, args->nr_local);
if (nr_pages < 0) {
ret = -EINVAL;
goto out; goto out;
}
pages = kcalloc(nr_pages, sizeof(struct page *), GFP_KERNEL); pages = kcalloc(nr_pages, sizeof(struct page *), GFP_KERNEL);
if (!pages) { if (!pages) {
...@@ -564,6 +607,10 @@ int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm, ...@@ -564,6 +607,10 @@ int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
op->op_recverr = rs->rs_recverr; op->op_recverr = rs->rs_recverr;
WARN_ON(!nr_pages); WARN_ON(!nr_pages);
op->op_sg = rds_message_alloc_sgs(rm, nr_pages); op->op_sg = rds_message_alloc_sgs(rm, nr_pages);
if (!op->op_sg) {
ret = -ENOMEM;
goto out;
}
if (op->op_notify || op->op_recverr) { if (op->op_notify || op->op_recverr) {
/* We allocate an uninitialized notifier here, because /* We allocate an uninitialized notifier here, because
...@@ -597,50 +644,40 @@ int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm, ...@@ -597,50 +644,40 @@ int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
(unsigned long long)args->remote_vec.addr, (unsigned long long)args->remote_vec.addr,
op->op_rkey); op->op_rkey);
local_vec = (struct rds_iovec __user *)(unsigned long) args->local_vec_addr;
for (i = 0; i < args->nr_local; i++) { for (i = 0; i < args->nr_local; i++) {
if (copy_from_user(&vec, &local_vec[i], struct rds_iovec *iov = &iovs[i];
sizeof(struct rds_iovec))) { /* don't need to check, rds_rdma_pages() verified nr will be +nonzero */
ret = -EFAULT; unsigned int nr = rds_pages_in_vec(iov);
goto out;
}
nr = rds_pages_in_vec(&vec);
if (nr == 0) {
ret = -EINVAL;
goto out;
}
rs->rs_user_addr = vec.addr; rs->rs_user_addr = iov->addr;
rs->rs_user_bytes = vec.bytes; rs->rs_user_bytes = iov->bytes;
/* If it's a WRITE operation, we want to pin the pages for reading. /* If it's a WRITE operation, we want to pin the pages for reading.
* If it's a READ operation, we need to pin the pages for writing. * If it's a READ operation, we need to pin the pages for writing.
*/ */
ret = rds_pin_pages(vec.addr, nr, pages, !op->op_write); ret = rds_pin_pages(iov->addr, nr, pages, !op->op_write);
if (ret < 0) if (ret < 0)
goto out; goto out;
rdsdebug("RDS: nr_bytes %u nr %u vec.bytes %llu vec.addr %llx\n", rdsdebug("RDS: nr_bytes %u nr %u iov->bytes %llu iov->addr %llx\n",
nr_bytes, nr, vec.bytes, vec.addr); nr_bytes, nr, iov->bytes, iov->addr);
nr_bytes += vec.bytes; nr_bytes += iov->bytes;
for (j = 0; j < nr; j++) { for (j = 0; j < nr; j++) {
unsigned int offset = vec.addr & ~PAGE_MASK; unsigned int offset = iov->addr & ~PAGE_MASK;
struct scatterlist *sg; struct scatterlist *sg;
sg = &op->op_sg[op->op_nents + j]; sg = &op->op_sg[op->op_nents + j];
sg_set_page(sg, pages[j], sg_set_page(sg, pages[j],
min_t(unsigned int, vec.bytes, PAGE_SIZE - offset), min_t(unsigned int, iov->bytes, PAGE_SIZE - offset),
offset); offset);
rdsdebug("RDS: sg->offset %x sg->len %x vec.addr %llx vec.bytes %llu\n", rdsdebug("RDS: sg->offset %x sg->len %x iov->addr %llx iov->bytes %llu\n",
sg->offset, sg->length, vec.addr, vec.bytes); sg->offset, sg->length, iov->addr, iov->bytes);
vec.addr += sg->length; iov->addr += sg->length;
vec.bytes -= sg->length; iov->bytes -= sg->length;
} }
op->op_nents += nr; op->op_nents += nr;
...@@ -655,13 +692,14 @@ int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm, ...@@ -655,13 +692,14 @@ int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
} }
op->op_bytes = nr_bytes; op->op_bytes = nr_bytes;
ret = 0;
out: out:
if (iovs != iovstack)
sock_kfree_s(rds_rs_to_sk(rs), iovs, iov_size);
kfree(pages); kfree(pages);
if (ret) if (ret)
rds_rdma_free_op(op); rds_rdma_free_op(op);
else
rds_stats_inc(s_send_rdma); rds_stats_inc(s_send_rdma);
return ret; return ret;
} }
...@@ -773,6 +811,10 @@ int rds_cmsg_atomic(struct rds_sock *rs, struct rds_message *rm, ...@@ -773,6 +811,10 @@ int rds_cmsg_atomic(struct rds_sock *rs, struct rds_message *rm,
rm->atomic.op_active = 1; rm->atomic.op_active = 1;
rm->atomic.op_recverr = rs->rs_recverr; rm->atomic.op_recverr = rs->rs_recverr;
rm->atomic.op_sg = rds_message_alloc_sgs(rm, 1); rm->atomic.op_sg = rds_message_alloc_sgs(rm, 1);
if (!rm->atomic.op_sg) {
ret = -ENOMEM;
goto err;
}
/* verify 8 byte-aligned */ /* verify 8 byte-aligned */
if (args->local_addr & 0x7) { if (args->local_addr & 0x7) {
......
...@@ -973,6 +973,10 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, ...@@ -973,6 +973,10 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
/* Attach data to the rm */ /* Attach data to the rm */
if (payload_len) { if (payload_len) {
rm->data.op_sg = rds_message_alloc_sgs(rm, ceil(payload_len, PAGE_SIZE)); rm->data.op_sg = rds_message_alloc_sgs(rm, ceil(payload_len, PAGE_SIZE));
if (!rm->data.op_sg) {
ret = -ENOMEM;
goto out;
}
ret = rds_message_copy_from_user(rm, msg->msg_iov, payload_len); ret = rds_message_copy_from_user(rm, msg->msg_iov, payload_len);
if (ret) if (ret)
goto out; goto out;
......
...@@ -1652,6 +1652,8 @@ SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len, ...@@ -1652,6 +1652,8 @@ SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
struct iovec iov; struct iovec iov;
int fput_needed; int fput_needed;
if (len > INT_MAX)
len = INT_MAX;
sock = sockfd_lookup_light(fd, &err, &fput_needed); sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (!sock) if (!sock)
goto out; goto out;
...@@ -1709,6 +1711,8 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size, ...@@ -1709,6 +1711,8 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
int err, err2; int err, err2;
int fput_needed; int fput_needed;
if (size > INT_MAX)
size = INT_MAX;
sock = sockfd_lookup_light(fd, &err, &fput_needed); sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (!sock) if (!sock)
goto out; goto out;
......
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