Commit 8b803841 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull networking fixes from David Miller:
 "A quick batch of fixes, including the annoying bad lock stack problem
  introduced by udp_sk_rx_dst_set() locking change:

   1) Use xchg() instead of sk_dst_lock() in udp_sk_rx_dst_set(), from
      Eric Dumazet.

   2) qlcnic bug fixes from Himanshu Madhani and Manish Chopra.

   3) Update IPSEC MAINTAINERS entry, from Steffen Klassert.

   4) Administrative neigh entry changes should generate netlink
      notifications the same as event generated ones.  From Bob
      Gilligan.

   5) Netfilter SYNPROXY fixes from Patrick McHardy.

   6) Netfilter nft_reject endianness fixes from Eric Leblond"

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net:
  qlcnic: Dump mailbox registers when mailbox command times out.
  qlcnic: Fix mailbox processing during diagnostic test
  qlcnic: Allow firmware dump collection when auto firmware recovery is disabled
  qlcnic: Fix memory allocation
  qlcnic: Fix TSS/RSS validation for 83xx/84xx series adapter.
  qlcnic: Fix TSS/RSS ring validation logic.
  qlcnic: Fix diagnostic test for all adapters.
  qlcnic: Fix usage of netif_tx_{wake, stop} api during link change.
  xen-netback: fix fragments error handling in checksum_setup_ip()
  neigh: Netlink notification for administrative NUD state change
  ipv4: improve documentation of ip_no_pmtu_disc
  net: unix: allow bind to fail on mutex lock
  MAINTAINERS: Update the IPsec maintainer entry
  udp: ipv4: do not use sk_dst_lock from softirq context
  netvsc: don't flush peers notifying work during setting mtu
  can: peak_usb: fix mem leak in pcan_usb_pro_init()
  can: ems_usb: fix urb leaks on failure paths
  sctp: loading sctp when load sctp_probe
  netfilter: nft_reject: fix endianness in dump function
  netfilter: SYNPROXY target: restrict to INPUT/FORWARD
parents b0031f22 78106927
......@@ -16,8 +16,12 @@ ip_default_ttl - INTEGER
Default: 64 (as recommended by RFC1700)
ip_no_pmtu_disc - BOOLEAN
Disable Path MTU Discovery.
default FALSE
Disable Path MTU Discovery. If enabled and a
fragmentation-required ICMP is received, the PMTU to this
destination will be set to min_pmtu (see below). You will need
to raise min_pmtu to the smallest interface MTU on your system
manually if you want to avoid locally generated fragments.
Default: FALSE
min_pmtu - INTEGER
default 552 - minimum discovered Path MTU
......
......@@ -5913,12 +5913,21 @@ M: Steffen Klassert <steffen.klassert@secunet.com>
M: Herbert Xu <herbert@gondor.apana.org.au>
M: "David S. Miller" <davem@davemloft.net>
L: netdev@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next.git
S: Maintained
F: net/xfrm/
F: net/key/
F: net/ipv4/xfrm*
F: net/ipv4/esp4.c
F: net/ipv4/ah4.c
F: net/ipv4/ipcomp.c
F: net/ipv4/ip_vti.c
F: net/ipv6/xfrm*
F: net/ipv6/esp6.c
F: net/ipv6/ah6.c
F: net/ipv6/ipcomp6.c
F: net/ipv6/ip6_vti.c
F: include/uapi/linux/xfrm.h
F: include/net/xfrm.h
......
......@@ -625,6 +625,7 @@ static int ems_usb_start(struct ems_usb *dev)
usb_unanchor_urb(urb);
usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf,
urb->transfer_dma);
usb_free_urb(urb);
break;
}
......@@ -798,8 +799,8 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne
* allowed (MAX_TX_URBS).
*/
if (!context) {
usb_unanchor_urb(urb);
usb_free_coherent(dev->udev, size, buf, urb->transfer_dma);
usb_free_urb(urb);
netdev_warn(netdev, "couldn't find free context\n");
......
......@@ -927,6 +927,9 @@ static int pcan_usb_pro_init(struct peak_usb_device *dev)
/* set LED in default state (end of init phase) */
pcan_usb_pro_set_led(dev, 0, 1);
kfree(bi);
kfree(fi);
return 0;
err_out:
......
......@@ -447,7 +447,8 @@ irqreturn_t qlcnic_83xx_intr(int irq, void *data)
qlcnic_83xx_poll_process_aen(adapter);
if (ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
if (ahw->diag_test) {
if (ahw->diag_test == QLCNIC_INTERRUPT_TEST)
ahw->diag_cnt++;
qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter);
return IRQ_HANDLED;
......@@ -1345,11 +1346,6 @@ static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test,
}
if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
/* disable and free mailbox interrupt */
if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
qlcnic_83xx_enable_mbx_poll(adapter);
qlcnic_83xx_free_mbx_intr(adapter);
}
adapter->ahw->loopback_state = 0;
adapter->ahw->hw_ops->setup_link_event(adapter, 1);
}
......@@ -1363,33 +1359,20 @@ static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_host_sds_ring *sds_ring;
int ring, err;
int ring;
clear_bit(__QLCNIC_DEV_UP, &adapter->state);
if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
sds_ring = &adapter->recv_ctx->sds_rings[ring];
if (adapter->flags & QLCNIC_MSIX_ENABLED)
qlcnic_83xx_disable_intr(adapter, sds_ring);
if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
qlcnic_83xx_enable_mbx_poll(adapter);
}
}
qlcnic_fw_destroy_ctx(adapter);
qlcnic_detach(adapter);
if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
err = qlcnic_83xx_setup_mbx_intr(adapter);
qlcnic_83xx_disable_mbx_poll(adapter);
if (err) {
dev_err(&adapter->pdev->dev,
"%s: failed to setup mbx interrupt\n",
__func__);
goto out;
}
}
}
adapter->ahw->diag_test = 0;
adapter->drv_sds_rings = drv_sds_rings;
......@@ -1399,9 +1382,6 @@ static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
if (netif_running(netdev))
__qlcnic_up(adapter, netdev);
if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST &&
!(adapter->flags & QLCNIC_MSIX_ENABLED))
qlcnic_83xx_disable_mbx_poll(adapter);
out:
netif_device_attach(netdev);
}
......@@ -3754,6 +3734,19 @@ static void qlcnic_83xx_decode_mbx_rsp(struct qlcnic_adapter *adapter,
return;
}
static inline void qlcnic_dump_mailbox_registers(struct qlcnic_adapter *adapter)
{
struct qlcnic_hardware_context *ahw = adapter->ahw;
u32 offset;
offset = QLCRDX(ahw, QLCNIC_DEF_INT_MASK);
dev_info(&adapter->pdev->dev, "Mbx interrupt mask=0x%x, Mbx interrupt enable=0x%x, Host mbx control=0x%x, Fw mbx control=0x%x",
readl(ahw->pci_base0 + offset),
QLCRDX(ahw, QLCNIC_MBX_INTR_ENBL),
QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL),
QLCRDX(ahw, QLCNIC_FW_MBX_CTRL));
}
static void qlcnic_83xx_mailbox_worker(struct work_struct *work)
{
struct qlcnic_mailbox *mbx = container_of(work, struct qlcnic_mailbox,
......@@ -3798,6 +3791,8 @@ static void qlcnic_83xx_mailbox_worker(struct work_struct *work)
__func__, cmd->cmd_op, cmd->type, ahw->pci_func,
ahw->op_mode);
clear_bit(QLC_83XX_MBX_READY, &mbx->status);
qlcnic_dump_mailbox_registers(adapter);
qlcnic_83xx_get_mbx_data(adapter, cmd);
qlcnic_dump_mbx(adapter, cmd);
qlcnic_83xx_idc_request_reset(adapter,
QLCNIC_FORCE_FW_DUMP_KEY);
......
......@@ -662,4 +662,5 @@ pci_ers_result_t qlcnic_83xx_io_error_detected(struct pci_dev *,
pci_channel_state_t);
pci_ers_result_t qlcnic_83xx_io_slot_reset(struct pci_dev *);
void qlcnic_83xx_io_resume(struct pci_dev *);
void qlcnic_83xx_stop_hw(struct qlcnic_adapter *);
#endif
......@@ -740,6 +740,7 @@ static int qlcnic_83xx_idc_unknown_state(struct qlcnic_adapter *adapter)
adapter->ahw->idc.err_code = -EIO;
dev_err(&adapter->pdev->dev,
"%s: Device in unknown state\n", __func__);
clear_bit(__QLCNIC_RESETTING, &adapter->state);
return 0;
}
......@@ -818,7 +819,6 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
struct qlcnic_hardware_context *ahw = adapter->ahw;
struct qlcnic_mailbox *mbx = ahw->mailbox;
int ret = 0;
u32 owner;
u32 val;
/* Perform NIC configuration based ready state entry actions */
......@@ -848,9 +848,9 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
set_bit(__QLCNIC_RESETTING, &adapter->state);
qlcnic_83xx_idc_enter_need_reset_state(adapter, 1);
} else {
owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);
if (ahw->pci_func == owner)
qlcnic_dump_fw(adapter);
netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",
__func__);
qlcnic_83xx_idc_enter_failed_state(adapter, 1);
}
return -EIO;
}
......@@ -948,13 +948,26 @@ static int qlcnic_83xx_idc_need_quiesce_state(struct qlcnic_adapter *adapter)
return 0;
}
static int qlcnic_83xx_idc_failed_state(struct qlcnic_adapter *adapter)
static void qlcnic_83xx_idc_failed_state(struct qlcnic_adapter *adapter)
{
dev_err(&adapter->pdev->dev, "%s: please restart!!\n", __func__);
struct qlcnic_hardware_context *ahw = adapter->ahw;
u32 val, owner;
val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {
owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);
if (ahw->pci_func == owner) {
qlcnic_83xx_stop_hw(adapter);
qlcnic_dump_fw(adapter);
}
}
netdev_warn(adapter->netdev, "%s: Reboot will be required to recover the adapter!!\n",
__func__);
clear_bit(__QLCNIC_RESETTING, &adapter->state);
adapter->ahw->idc.err_code = -EIO;
ahw->idc.err_code = -EIO;
return 0;
return;
}
static int qlcnic_83xx_idc_quiesce_state(struct qlcnic_adapter *adapter)
......@@ -1063,12 +1076,6 @@ void qlcnic_83xx_idc_poll_dev_state(struct work_struct *work)
adapter->ahw->idc.prev_state = adapter->ahw->idc.curr_state;
qlcnic_83xx_periodic_tasks(adapter);
/* Do not reschedule if firmaware is in hanged state and auto
* recovery is disabled
*/
if ((adapter->flags & QLCNIC_FW_HANG) && !qlcnic_auto_fw_reset)
return;
/* Re-schedule the function */
if (test_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status))
qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state,
......@@ -1219,10 +1226,10 @@ void qlcnic_83xx_idc_request_reset(struct qlcnic_adapter *adapter, u32 key)
}
val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
if ((val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) ||
!qlcnic_auto_fw_reset) {
dev_err(&adapter->pdev->dev,
"%s:failed, device in non reset mode\n", __func__);
if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {
netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",
__func__);
qlcnic_83xx_idc_enter_failed_state(adapter, 0);
qlcnic_83xx_unlock_driver(adapter);
return;
}
......@@ -1254,24 +1261,24 @@ static int qlcnic_83xx_copy_bootloader(struct qlcnic_adapter *adapter)
if (size & 0xF)
size = (size + 16) & ~0xF;
p_cache = kzalloc(size, GFP_KERNEL);
p_cache = vzalloc(size);
if (p_cache == NULL)
return -ENOMEM;
ret = qlcnic_83xx_lockless_flash_read32(adapter, src, p_cache,
size / sizeof(u32));
if (ret) {
kfree(p_cache);
vfree(p_cache);
return ret;
}
/* 16 byte write to MS memory */
ret = qlcnic_83xx_ms_mem_write128(adapter, dest, (u32 *)p_cache,
size / 16);
if (ret) {
kfree(p_cache);
vfree(p_cache);
return ret;
}
kfree(p_cache);
vfree(p_cache);
return ret;
}
......@@ -1939,7 +1946,7 @@ static void qlcnic_83xx_exec_template_cmd(struct qlcnic_adapter *p_dev,
p_dev->ahw->reset.seq_index = index;
}
static void qlcnic_83xx_stop_hw(struct qlcnic_adapter *p_dev)
void qlcnic_83xx_stop_hw(struct qlcnic_adapter *p_dev)
{
p_dev->ahw->reset.seq_index = 0;
......@@ -1994,6 +2001,14 @@ static int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter)
val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
if (!(val & QLC_83XX_IDC_GRACEFULL_RESET))
qlcnic_dump_fw(adapter);
if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {
netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",
__func__);
qlcnic_83xx_idc_enter_failed_state(adapter, 1);
return err;
}
qlcnic_83xx_init_hw(adapter);
if (qlcnic_83xx_copy_bootloader(adapter))
......@@ -2073,8 +2088,8 @@ int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter)
ahw->nic_mode = QLCNIC_DEFAULT_MODE;
adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver;
ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
adapter->max_sds_rings = ahw->max_rx_ques;
adapter->max_tx_rings = ahw->max_tx_ques;
adapter->max_sds_rings = QLCNIC_MAX_SDS_RINGS;
adapter->max_tx_rings = QLCNIC_MAX_TX_RINGS;
} else {
return -EIO;
}
......
......@@ -667,30 +667,25 @@ qlcnic_set_ringparam(struct net_device *dev,
static int qlcnic_validate_ring_count(struct qlcnic_adapter *adapter,
u8 rx_ring, u8 tx_ring)
{
if (rx_ring == 0 || tx_ring == 0)
return -EINVAL;
if (rx_ring != 0) {
if (rx_ring > adapter->max_sds_rings) {
netdev_err(adapter->netdev, "Invalid ring count, SDS ring count %d should not be greater than max %d driver sds rings.\n",
netdev_err(adapter->netdev,
"Invalid ring count, SDS ring count %d should not be greater than max %d driver sds rings.\n",
rx_ring, adapter->max_sds_rings);
return -EINVAL;
}
}
if (tx_ring != 0) {
if (qlcnic_82xx_check(adapter) &&
(tx_ring > adapter->max_tx_rings)) {
if (tx_ring > adapter->max_tx_rings) {
netdev_err(adapter->netdev,
"Invalid ring count, Tx ring count %d should not be greater than max %d driver Tx rings.\n",
tx_ring, adapter->max_tx_rings);
return -EINVAL;
}
if (qlcnic_83xx_check(adapter) &&
(tx_ring > QLCNIC_SINGLE_RING)) {
netdev_err(adapter->netdev,
"Invalid ring count, Tx ring count %d should not be greater than %d driver Tx rings.\n",
tx_ring, QLCNIC_SINGLE_RING);
return -EINVAL;
}
}
return 0;
......@@ -948,6 +943,7 @@ static int qlcnic_irq_test(struct net_device *netdev)
struct qlcnic_hardware_context *ahw = adapter->ahw;
struct qlcnic_cmd_args cmd;
int ret, drv_sds_rings = adapter->drv_sds_rings;
int drv_tx_rings = adapter->drv_tx_rings;
if (qlcnic_83xx_check(adapter))
return qlcnic_83xx_interrupt_test(netdev);
......@@ -980,6 +976,7 @@ static int qlcnic_irq_test(struct net_device *netdev)
clear_diag_irq:
adapter->drv_sds_rings = drv_sds_rings;
adapter->drv_tx_rings = drv_tx_rings;
clear_bit(__QLCNIC_RESETTING, &adapter->state);
return ret;
......
......@@ -687,17 +687,11 @@ void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup)
if (adapter->ahw->linkup && !linkup) {
netdev_info(netdev, "NIC Link is down\n");
adapter->ahw->linkup = 0;
if (netif_running(netdev)) {
netif_carrier_off(netdev);
netif_tx_stop_all_queues(netdev);
}
} else if (!adapter->ahw->linkup && linkup) {
netdev_info(netdev, "NIC Link is up\n");
adapter->ahw->linkup = 1;
if (netif_running(netdev)) {
netif_carrier_on(netdev);
netif_wake_queue(netdev);
}
}
}
......
......@@ -1178,6 +1178,7 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
} else {
adapter->ahw->nic_mode = QLCNIC_DEFAULT_MODE;
adapter->max_tx_rings = QLCNIC_MAX_HW_TX_RINGS;
adapter->max_sds_rings = QLCNIC_MAX_SDS_RINGS;
adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
}
......@@ -1940,7 +1941,6 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
qlcnic_detach(adapter);
adapter->drv_sds_rings = QLCNIC_SINGLE_RING;
adapter->drv_tx_rings = QLCNIC_SINGLE_RING;
adapter->ahw->diag_test = test;
adapter->ahw->linkup = 0;
......
......@@ -327,7 +327,6 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
return -EINVAL;
nvdev->start_remove = true;
cancel_delayed_work_sync(&ndevctx->dwork);
cancel_work_sync(&ndevctx->work);
netif_tx_disable(ndev);
rndis_filter_device_remove(hdev);
......
......@@ -1197,6 +1197,9 @@ static int checksum_setup_ip(struct xenvif *vif, struct sk_buff *skb,
err = -EPROTO;
if (fragment)
goto out;
switch (ip_hdr(skb)->protocol) {
case IPPROTO_TCP:
err = maybe_pull_tail(skb,
......
......@@ -1161,6 +1161,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
neigh->parms->reachable_time :
0)));
neigh->nud_state = new;
notify = 1;
}
if (lladdr != neigh->ha) {
......
......@@ -423,6 +423,7 @@ static void synproxy_tg4_destroy(const struct xt_tgdtor_param *par)
static struct xt_target synproxy_tg4_reg __read_mostly = {
.name = "SYNPROXY",
.family = NFPROTO_IPV4,
.hooks = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD),
.target = synproxy_tg4,
.targetsize = sizeof(struct xt_synproxy_info),
.checkentry = synproxy_tg4_check,
......
......@@ -72,7 +72,7 @@ static int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr)
{
const struct nft_reject *priv = nft_expr_priv(expr);
if (nla_put_be32(skb, NFTA_REJECT_TYPE, priv->type))
if (nla_put_be32(skb, NFTA_REJECT_TYPE, htonl(priv->type)))
goto nla_put_failure;
switch (priv->type) {
......
......@@ -1600,20 +1600,15 @@ static void flush_stack(struct sock **stack, unsigned int count,
}
/* For TCP sockets, sk_rx_dst is protected by socket lock
* For UDP, we use sk_dst_lock to guard against concurrent changes.
* For UDP, we use xchg() to guard against concurrent changes.
*/
static void udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst)
{
struct dst_entry *old;
spin_lock(&sk->sk_dst_lock);
old = sk->sk_rx_dst;
if (likely(old != dst)) {
dst_hold(dst);
sk->sk_rx_dst = dst;
old = xchg(&sk->sk_rx_dst, dst);
dst_release(old);
}
spin_unlock(&sk->sk_dst_lock);
}
/*
......
......@@ -446,6 +446,7 @@ static void synproxy_tg6_destroy(const struct xt_tgdtor_param *par)
static struct xt_target synproxy_tg6_reg __read_mostly = {
.name = "SYNPROXY",
.family = NFPROTO_IPV6,
.hooks = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD),
.target = synproxy_tg6,
.targetsize = sizeof(struct xt_synproxy_info),
.checkentry = synproxy_tg6_check,
......
......@@ -38,6 +38,7 @@
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
MODULE_SOFTDEP("pre: sctp");
MODULE_AUTHOR("Wei Yongjun <yjwei@cn.fujitsu.com>");
MODULE_DESCRIPTION("SCTP snooper");
MODULE_LICENSE("GPL");
......@@ -182,6 +183,20 @@ static struct jprobe sctp_recv_probe = {
.entry = jsctp_sf_eat_sack,
};
static __init int sctp_setup_jprobe(void)
{
int ret = register_jprobe(&sctp_recv_probe);
if (ret) {
if (request_module("sctp"))
goto out;
ret = register_jprobe(&sctp_recv_probe);
}
out:
return ret;
}
static __init int sctpprobe_init(void)
{
int ret = -ENOMEM;
......@@ -202,7 +217,7 @@ static __init int sctpprobe_init(void)
&sctpprobe_fops))
goto free_kfifo;
ret = register_jprobe(&sctp_recv_probe);
ret = sctp_setup_jprobe();
if (ret)
goto remove_proc;
......
......@@ -718,7 +718,9 @@ static int unix_autobind(struct socket *sock)
int err;
unsigned int retries = 0;
mutex_lock(&u->readlock);
err = mutex_lock_interruptible(&u->readlock);
if (err)
return err;
err = 0;
if (u->addr)
......@@ -877,7 +879,9 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
goto out;
addr_len = err;
mutex_lock(&u->readlock);
err = mutex_lock_interruptible(&u->readlock);
if (err)
goto out;
err = -EINVAL;
if (u->addr)
......
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