提交 78f9bbb5 编写于 作者: L 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:
  ariadne: remove redundant NULL check
  ip6ip6: autoload ip6 tunnel
  net: bridge builtin vs. ipv6 modular
  ipv6: Don't create clones of host routes.
  pktgen: fix errata in show results
  ipv4: Fix erroneous uses of ifa_address.
  vxge: update MAINTAINERS
  r6040: bump to version 0.27 and date 23Feb2011
  r6040: fix multicast operations
  rds: prevent BUG_ON triggering on congestion map updates
  bonding 802.3ad: Rename rx_machine_lock to state_machine_lock
  bonding 802.3ad: Fix the state machine locking v2
  drivers/net/macvtap: fix error check
  net: fix multithreaded signal handling in unix recv routines
  net: Enter net/ipv6/ even if CONFIG_IPV6=n
  net/smsc911x.c: Set the VLAN1 register to fix VLAN MTU problem
  bnx2x: fix MaxBW configuration
  bnx2x: (NPAR) prevent HW access in D3 state
  bnx2x: fix link notification
  bnx2x: fix non-pmf device load flow

Doing my first --no-ff merge here, to get the explicit merge commit.

David did a back-merge in order to get commit 8909c9ad ("net: don't
allow CAP_NET_ADMIN to load non-netdev kernel modules") so that we can
add Stephen Hemminger's fix to handle ip6 tunnels as well, which uses
the MODULE_ALIAS_NETDEV() macro created by that change.
......@@ -4292,10 +4292,7 @@ S: Maintained
F: net/sched/sch_netem.c
NETERION 10GbE DRIVERS (s2io/vxge)
M: Ramkrishna Vepa <ramkrishna.vepa@exar.com>
M: Sivakumar Subramani <sivakumar.subramani@exar.com>
M: Sreenivasa Honnur <sreenivasa.honnur@exar.com>
M: Jon Mason <jon.mason@exar.com>
M: Jon Mason <jdmason@kudzu.us>
L: netdev@vger.kernel.org
W: http://trac.neterion.com/cgi-bin/trac.cgi/wiki/Linux?Anonymous
W: http://trac.neterion.com/cgi-bin/trac.cgi/wiki/X3100Linux?Anonymous
......
......@@ -425,11 +425,6 @@ static irqreturn_t ariadne_interrupt(int irq, void *data)
int csr0, boguscnt;
int handled = 0;
if (dev == NULL) {
printk(KERN_WARNING "ariadne_interrupt(): irq for unknown device.\n");
return IRQ_NONE;
}
lance->RAP = CSR0; /* PCnet-ISA Controller Status */
if (!(lance->RDP & INTR)) /* Check if any interrupt has been */
......
......@@ -1211,6 +1211,7 @@ struct bnx2x {
/* DCBX Negotation results */
struct dcbx_features dcbx_local_feat;
u32 dcbx_error;
u32 pending_max;
};
/**
......@@ -1616,8 +1617,8 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
/* CMNG constants, as derived from system spec calculations */
/* default MIN rate in case VNIC min rate is configured to zero - 100Mbps */
#define DEF_MIN_RATE 100
/* resolution of the rate shaping timer - 100 usec */
#define RS_PERIODIC_TIMEOUT_USEC 100
/* resolution of the rate shaping timer - 400 usec */
#define RS_PERIODIC_TIMEOUT_USEC 400
/* number of bytes in single QM arbitration cycle -
* coefficient for calculating the fairness timer */
#define QM_ARB_BYTES 160000
......
......@@ -996,6 +996,23 @@ void bnx2x_free_skbs(struct bnx2x *bp)
bnx2x_free_rx_skbs(bp);
}
void bnx2x_update_max_mf_config(struct bnx2x *bp, u32 value)
{
/* load old values */
u32 mf_cfg = bp->mf_config[BP_VN(bp)];
if (value != bnx2x_extract_max_cfg(bp, mf_cfg)) {
/* leave all but MAX value */
mf_cfg &= ~FUNC_MF_CFG_MAX_BW_MASK;
/* set new MAX value */
mf_cfg |= (value << FUNC_MF_CFG_MAX_BW_SHIFT)
& FUNC_MF_CFG_MAX_BW_MASK;
bnx2x_fw_command(bp, DRV_MSG_CODE_SET_MF_BW, mf_cfg);
}
}
static void bnx2x_free_msix_irqs(struct bnx2x *bp)
{
int i, offset = 1;
......@@ -1464,6 +1481,11 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
bnx2x_set_eth_mac(bp, 1);
if (bp->pending_max) {
bnx2x_update_max_mf_config(bp, bp->pending_max);
bp->pending_max = 0;
}
if (bp->port.pmf)
bnx2x_initial_phy_init(bp, load_mode);
......
......@@ -341,6 +341,15 @@ void bnx2x_dcbx_init(struct bnx2x *bp);
*/
int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state);
/**
* Updates MAX part of MF configuration in HW
* (if required)
*
* @param bp
* @param value
*/
void bnx2x_update_max_mf_config(struct bnx2x *bp, u32 value);
/* dev_close main block */
int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode);
......
......@@ -238,7 +238,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
speed |= (cmd->speed_hi << 16);
if (IS_MF_SI(bp)) {
u32 param = 0, part;
u32 part;
u32 line_speed = bp->link_vars.line_speed;
/* use 10G if no link detected */
......@@ -251,24 +251,22 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
REQ_BC_VER_4_SET_MF_BW);
return -EINVAL;
}
part = (speed * 100) / line_speed;
if (line_speed < speed || !part) {
BNX2X_DEV_INFO("Speed setting should be in a range "
"from 1%% to 100%% "
"of actual line speed\n");
return -EINVAL;
}
/* load old values */
param = bp->mf_config[BP_VN(bp)];
/* leave only MIN value */
param &= FUNC_MF_CFG_MIN_BW_MASK;
/* set new MAX value */
param |= (part << FUNC_MF_CFG_MAX_BW_SHIFT)
& FUNC_MF_CFG_MAX_BW_MASK;
if (bp->state != BNX2X_STATE_OPEN)
/* store value for following "load" */
bp->pending_max = part;
else
bnx2x_update_max_mf_config(bp, part);
bnx2x_fw_command(bp, DRV_MSG_CODE_SET_MF_BW, param);
return 0;
}
......
......@@ -2092,6 +2092,7 @@ static void bnx2x_cmng_fns_init(struct bnx2x *bp, u8 read_cfg, u8 cmng_type)
bnx2x_calc_vn_weight_sum(bp);
/* calculate and set min-max rate for each vn */
if (bp->port.pmf)
for (vn = VN_0; vn < E1HVN_MAX; vn++)
bnx2x_init_vn_minmax(bp, vn);
......@@ -2162,13 +2163,6 @@ static void bnx2x_link_attn(struct bnx2x *bp)
bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP);
}
/* indicate link status only if link status actually changed */
if (prev_link_status != bp->link_vars.link_status)
bnx2x_link_report(bp);
if (IS_MF(bp))
bnx2x_link_sync_notify(bp);
if (bp->link_vars.link_up && bp->link_vars.line_speed) {
int cmng_fns = bnx2x_get_cmng_fns_mode(bp);
......@@ -2180,6 +2174,13 @@ static void bnx2x_link_attn(struct bnx2x *bp)
DP(NETIF_MSG_IFUP,
"single function mode without fairness\n");
}
if (IS_MF(bp))
bnx2x_link_sync_notify(bp);
/* indicate link status only if link status actually changed */
if (prev_link_status != bp->link_vars.link_status)
bnx2x_link_report(bp);
}
void bnx2x__link_status_update(struct bnx2x *bp)
......
......@@ -281,23 +281,23 @@ static inline int __check_agg_selection_timer(struct port *port)
}
/**
* __get_rx_machine_lock - lock the port's RX machine
* __get_state_machine_lock - lock the port's state machines
* @port: the port we're looking at
*
*/
static inline void __get_rx_machine_lock(struct port *port)
static inline void __get_state_machine_lock(struct port *port)
{
spin_lock_bh(&(SLAVE_AD_INFO(port->slave).rx_machine_lock));
spin_lock_bh(&(SLAVE_AD_INFO(port->slave).state_machine_lock));
}
/**
* __release_rx_machine_lock - unlock the port's RX machine
* __release_state_machine_lock - unlock the port's state machines
* @port: the port we're looking at
*
*/
static inline void __release_rx_machine_lock(struct port *port)
static inline void __release_state_machine_lock(struct port *port)
{
spin_unlock_bh(&(SLAVE_AD_INFO(port->slave).rx_machine_lock));
spin_unlock_bh(&(SLAVE_AD_INFO(port->slave).state_machine_lock));
}
/**
......@@ -388,14 +388,14 @@ static u8 __get_duplex(struct port *port)
}
/**
* __initialize_port_locks - initialize a port's RX machine spinlock
* __initialize_port_locks - initialize a port's STATE machine spinlock
* @port: the port we're looking at
*
*/
static inline void __initialize_port_locks(struct port *port)
{
// make sure it isn't called twice
spin_lock_init(&(SLAVE_AD_INFO(port->slave).rx_machine_lock));
spin_lock_init(&(SLAVE_AD_INFO(port->slave).state_machine_lock));
}
//conversions
......@@ -1025,9 +1025,6 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
{
rx_states_t last_state;
// Lock to prevent 2 instances of this function to run simultaneously(rx interrupt and periodic machine callback)
__get_rx_machine_lock(port);
// keep current State Machine state to compare later if it was changed
last_state = port->sm_rx_state;
......@@ -1133,7 +1130,6 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
pr_err("%s: An illegal loopback occurred on adapter (%s).\n"
"Check the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n",
port->slave->dev->master->name, port->slave->dev->name);
__release_rx_machine_lock(port);
return;
}
__update_selected(lacpdu, port);
......@@ -1153,7 +1149,6 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
break;
}
}
__release_rx_machine_lock(port);
}
/**
......@@ -2155,6 +2150,12 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
goto re_arm;
}
/* Lock around state machines to protect data accessed
* by all (e.g., port->sm_vars). ad_rx_machine may run
* concurrently due to incoming LACPDU.
*/
__get_state_machine_lock(port);
ad_rx_machine(NULL, port);
ad_periodic_machine(port);
ad_port_selection_logic(port);
......@@ -2164,6 +2165,8 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
// turn off the BEGIN bit, since we already handled it
if (port->sm_vars & AD_PORT_BEGIN)
port->sm_vars &= ~AD_PORT_BEGIN;
__release_state_machine_lock(port);
}
re_arm:
......@@ -2200,7 +2203,10 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
case AD_TYPE_LACPDU:
pr_debug("Received LACPDU on port %d\n",
port->actor_port_number);
/* Protect against concurrent state machines */
__get_state_machine_lock(port);
ad_rx_machine(lacpdu, port);
__release_state_machine_lock(port);
break;
case AD_TYPE_MARKER:
......
......@@ -264,7 +264,8 @@ struct ad_bond_info {
struct ad_slave_info {
struct aggregator aggregator; // 802.3ad aggregator structure
struct port port; // 802.3ad port structure
spinlock_t rx_machine_lock; // To avoid race condition between callback and receive interrupt
spinlock_t state_machine_lock; /* mutex state machines vs.
incoming LACPDU */
u16 id;
};
......
......@@ -528,8 +528,9 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q,
vnet_hdr_len = q->vnet_hdr_sz;
err = -EINVAL;
if ((len -= vnet_hdr_len) < 0)
if (len < vnet_hdr_len)
goto err;
len -= vnet_hdr_len;
err = memcpy_fromiovecend((void *)&vnet_hdr, iv, 0,
sizeof(vnet_hdr));
......
......@@ -49,8 +49,8 @@
#include <asm/processor.h>
#define DRV_NAME "r6040"
#define DRV_VERSION "0.26"
#define DRV_RELDATE "30May2010"
#define DRV_VERSION "0.27"
#define DRV_RELDATE "23Feb2011"
/* PHY CHIP Address */
#define PHY1_ADDR 1 /* For MAC1 */
......@@ -69,6 +69,8 @@
/* MAC registers */
#define MCR0 0x00 /* Control register 0 */
#define MCR0_PROMISC 0x0020 /* Promiscuous mode */
#define MCR0_HASH_EN 0x0100 /* Enable multicast hash table function */
#define MCR1 0x04 /* Control register 1 */
#define MAC_RST 0x0001 /* Reset the MAC */
#define MBCR 0x08 /* Bus control */
......@@ -851,77 +853,92 @@ static void r6040_multicast_list(struct net_device *dev)
{
struct r6040_private *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
u16 *adrp;
u16 reg;
unsigned long flags;
struct netdev_hw_addr *ha;
int i;
u16 *adrp;
u16 hash_table[4] = { 0 };
spin_lock_irqsave(&lp->lock, flags);
/* MAC Address */
/* Keep our MAC Address */
adrp = (u16 *)dev->dev_addr;
iowrite16(adrp[0], ioaddr + MID_0L);
iowrite16(adrp[1], ioaddr + MID_0M);
iowrite16(adrp[2], ioaddr + MID_0H);
/* Promiscous Mode */
spin_lock_irqsave(&lp->lock, flags);
/* Clear AMCP & PROM bits */
reg = ioread16(ioaddr) & ~0x0120;
if (dev->flags & IFF_PROMISC) {
reg |= 0x0020;
lp->mcr0 |= 0x0020;
}
/* Too many multicast addresses
* accept all traffic */
else if ((netdev_mc_count(dev) > MCAST_MAX) ||
(dev->flags & IFF_ALLMULTI))
reg |= 0x0020;
iowrite16(reg, ioaddr);
spin_unlock_irqrestore(&lp->lock, flags);
/* Build the hash table */
if (netdev_mc_count(dev) > MCAST_MAX) {
u16 hash_table[4];
u32 crc;
lp->mcr0 = ioread16(ioaddr + MCR0) & ~(MCR0_PROMISC | MCR0_HASH_EN);
for (i = 0; i < 4; i++)
hash_table[i] = 0;
netdev_for_each_mc_addr(ha, dev) {
char *addrs = ha->addr;
/* Promiscuous mode */
if (dev->flags & IFF_PROMISC)
lp->mcr0 |= MCR0_PROMISC;
if (!(*addrs & 1))
continue;
/* Enable multicast hash table function to
* receive all multicast packets. */
else if (dev->flags & IFF_ALLMULTI) {
lp->mcr0 |= MCR0_HASH_EN;
crc = ether_crc_le(6, addrs);
crc >>= 26;
hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf));
for (i = 0; i < MCAST_MAX ; i++) {
iowrite16(0, ioaddr + MID_1L + 8 * i);
iowrite16(0, ioaddr + MID_1M + 8 * i);
iowrite16(0, ioaddr + MID_1H + 8 * i);
}
/* Fill the MAC hash tables with their values */
iowrite16(hash_table[0], ioaddr + MAR0);
iowrite16(hash_table[1], ioaddr + MAR1);
iowrite16(hash_table[2], ioaddr + MAR2);
iowrite16(hash_table[3], ioaddr + MAR3);
for (i = 0; i < 4; i++)
hash_table[i] = 0xffff;
}
/* Multicast Address 1~4 case */
/* Use internal multicast address registers if the number of
* multicast addresses is not greater than MCAST_MAX. */
else if (netdev_mc_count(dev) <= MCAST_MAX) {
i = 0;
netdev_for_each_mc_addr(ha, dev) {
if (i >= MCAST_MAX)
break;
adrp = (u16 *) ha->addr;
u16 *adrp = (u16 *) ha->addr;
iowrite16(adrp[0], ioaddr + MID_1L + 8 * i);
iowrite16(adrp[1], ioaddr + MID_1M + 8 * i);
iowrite16(adrp[2], ioaddr + MID_1H + 8 * i);
i++;
}
while (i < MCAST_MAX) {
iowrite16(0xffff, ioaddr + MID_1L + 8 * i);
iowrite16(0xffff, ioaddr + MID_1M + 8 * i);
iowrite16(0xffff, ioaddr + MID_1H + 8 * i);
iowrite16(0, ioaddr + MID_1L + 8 * i);
iowrite16(0, ioaddr + MID_1M + 8 * i);
iowrite16(0, ioaddr + MID_1H + 8 * i);
i++;
}
}
/* Otherwise, Enable multicast hash table function. */
else {
u32 crc;
lp->mcr0 |= MCR0_HASH_EN;
for (i = 0; i < MCAST_MAX ; i++) {
iowrite16(0, ioaddr + MID_1L + 8 * i);
iowrite16(0, ioaddr + MID_1M + 8 * i);
iowrite16(0, ioaddr + MID_1H + 8 * i);
}
/* Build multicast hash table */
netdev_for_each_mc_addr(ha, dev) {
u8 *addrs = ha->addr;
crc = ether_crc(ETH_ALEN, addrs);
crc >>= 26;
hash_table[crc >> 4] |= 1 << (crc & 0xf);
}
}
iowrite16(lp->mcr0, ioaddr + MCR0);
/* Fill the MAC hash tables with their values */
if (lp->mcr0 && MCR0_HASH_EN) {
iowrite16(hash_table[0], ioaddr + MAR0);
iowrite16(hash_table[1], ioaddr + MAR1);
iowrite16(hash_table[2], ioaddr + MAR2);
iowrite16(hash_table[3], ioaddr + MAR3);
}
spin_unlock_irqrestore(&lp->lock, flags);
}
static void netdev_get_drvinfo(struct net_device *dev,
......
......@@ -1178,6 +1178,11 @@ static int smsc911x_open(struct net_device *dev)
smsc911x_reg_write(pdata, HW_CFG, 0x00050000);
smsc911x_reg_write(pdata, AFC_CFG, 0x006E3740);
/* Increase the legal frame size of VLAN tagged frames to 1522 bytes */
spin_lock_irq(&pdata->mac_lock);
smsc911x_mac_write(pdata, VLAN1, ETH_P_8021Q);
spin_unlock_irq(&pdata->mac_lock);
/* Make sure EEPROM has finished loading before setting GPIO_CFG */
timeout = 50;
while ((smsc911x_reg_read(pdata, E2P_CMD) & E2P_CMD_EPC_BUSY_) &&
......
......@@ -19,9 +19,7 @@ obj-$(CONFIG_NETFILTER) += netfilter/
obj-$(CONFIG_INET) += ipv4/
obj-$(CONFIG_XFRM) += xfrm/
obj-$(CONFIG_UNIX) += unix/
ifneq ($(CONFIG_IPV6),)
obj-y += ipv6/
endif
obj-$(CONFIG_NET) += ipv6/
obj-$(CONFIG_PACKET) += packet/
obj-$(CONFIG_NET_KEY) += key/
obj-$(CONFIG_BRIDGE) += bridge/
......
......@@ -6,6 +6,7 @@ config BRIDGE
tristate "802.1d Ethernet Bridging"
select LLC
select STP
depends on IPV6 || IPV6=n
---help---
If you say Y here, then your Linux box will be able to act as an
Ethernet bridge, which means that the different Ethernet segments it
......
......@@ -3321,7 +3321,7 @@ static void show_results(struct pktgen_dev *pkt_dev, int nr_frags)
pkt_dev->started_at);
ktime_t idle = ns_to_ktime(pkt_dev->idle_acc);
p += sprintf(p, "OK: %llu(c%llu+d%llu) nsec, %llu (%dbyte,%dfrags)\n",
p += sprintf(p, "OK: %llu(c%llu+d%llu) usec, %llu (%dbyte,%dfrags)\n",
(unsigned long long)ktime_to_us(elapsed),
(unsigned long long)ktime_to_us(ktime_sub(elapsed, idle)),
(unsigned long long)ktime_to_us(idle),
......
......@@ -670,7 +670,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
ifap = &ifa->ifa_next) {
if (!strcmp(ifr.ifr_name, ifa->ifa_label) &&
sin_orig.sin_addr.s_addr ==
ifa->ifa_address) {
ifa->ifa_local) {
break; /* found */
}
}
......@@ -1040,8 +1040,8 @@ static void inetdev_send_gratuitous_arp(struct net_device *dev,
return;
arp_send(ARPOP_REQUEST, ETH_P_ARP,
ifa->ifa_address, dev,
ifa->ifa_address, NULL,
ifa->ifa_local, dev,
ifa->ifa_local, NULL,
dev->dev_addr, NULL);
}
......
......@@ -57,6 +57,7 @@
MODULE_AUTHOR("Ville Nuorvala");
MODULE_DESCRIPTION("IPv6 tunneling device");
MODULE_LICENSE("GPL");
MODULE_ALIAS_NETDEV("ip6tnl0");
#ifdef IP6_TNL_DEBUG
#define IP6_TNL_TRACE(x...) printk(KERN_DEBUG "%s:" x "\n", __func__)
......
......@@ -739,8 +739,10 @@ static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP))
nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src);
else
else if (!(rt->dst.flags & DST_HOST))
nrt = rt6_alloc_clone(rt, &fl->fl6_dst);
else
goto out2;
dst_release(&rt->dst);
rt = nrt ? : net->ipv6.ip6_null_entry;
......
......@@ -551,7 +551,10 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm,
if (conn->c_loopback
&& rm->m_inc.i_hdr.h_flags & RDS_FLAG_CONG_BITMAP) {
rds_cong_map_updated(conn->c_fcong, ~(u64) 0);
return sizeof(struct rds_header) + RDS_CONG_MAP_BYTES;
scat = &rm->data.op_sg[sg];
ret = sizeof(struct rds_header) + RDS_CONG_MAP_BYTES;
ret = min_t(int, ret, scat->length - conn->c_xmit_data_off);
return ret;
}
/* FIXME we may overallocate here */
......
......@@ -61,10 +61,15 @@ static int rds_loop_xmit(struct rds_connection *conn, struct rds_message *rm,
unsigned int hdr_off, unsigned int sg,
unsigned int off)
{
struct scatterlist *sgp = &rm->data.op_sg[sg];
int ret = sizeof(struct rds_header) +
be32_to_cpu(rm->m_inc.i_hdr.h_len);
/* Do not send cong updates to loopback */
if (rm->m_inc.i_hdr.h_flags & RDS_FLAG_CONG_BITMAP) {
rds_cong_map_updated(conn->c_fcong, ~(u64) 0);
return sizeof(struct rds_header) + RDS_CONG_MAP_BYTES;
ret = min_t(int, ret, sgp->length - conn->c_xmit_data_off);
goto out;
}
BUG_ON(hdr_off || sg || off);
......@@ -80,8 +85,8 @@ static int rds_loop_xmit(struct rds_connection *conn, struct rds_message *rm,
NULL);
rds_inc_put(&rm->m_inc);
return sizeof(struct rds_header) + be32_to_cpu(rm->m_inc.i_hdr.h_len);
out:
return ret;
}
/*
......
......@@ -1724,7 +1724,11 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
msg->msg_namelen = 0;
mutex_lock(&u->readlock);
err = mutex_lock_interruptible(&u->readlock);
if (err) {
err = sock_intr_errno(sock_rcvtimeo(sk, noblock));
goto out;
}
skb = skb_recv_datagram(sk, flags, noblock, &err);
if (!skb) {
......@@ -1864,7 +1868,11 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
memset(&tmp_scm, 0, sizeof(tmp_scm));
}
mutex_lock(&u->readlock);
err = mutex_lock_interruptible(&u->readlock);
if (err) {
err = sock_intr_errno(timeo);
goto out;
}
do {
int chunk;
......@@ -1895,11 +1903,12 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
timeo = unix_stream_data_wait(sk, timeo);
if (signal_pending(current)) {
if (signal_pending(current)
|| mutex_lock_interruptible(&u->readlock)) {
err = sock_intr_errno(timeo);
goto out;
}
mutex_lock(&u->readlock);
continue;
unlock:
unix_state_unlock(sk);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册