Loading drivers/net/ethernet/msm/rndis_ipa.c +63 −2 Original line number Diff line number Diff line /* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -197,6 +197,7 @@ struct rndis_loopback_pipe { * This callback shall be called by the Netdev once the Netdev internal * state is changed to RNDIS_IPA_CONNECTED_AND_UP * @xmit_error_delayed_work: work item for cases where IPA driver Tx fails * @state_lock: used to protect the state variable. */ struct rndis_ipa_dev { struct net_device *net; Loading Loading @@ -228,6 +229,7 @@ struct rndis_ipa_dev { u8 device_ethaddr[ETH_ALEN]; void (*device_ready_notify)(void); struct delayed_work xmit_error_delayed_work; spinlock_t state_lock; /* Spinlock for the state variable.*/ }; /** Loading Loading @@ -560,6 +562,8 @@ int rndis_ipa_init(struct ipa_usb_init_params *params) memset(rndis_ipa_ctx, 0, sizeof(*rndis_ipa_ctx)); RNDIS_IPA_DEBUG("rndis_ipa_ctx (private)=%p\n", rndis_ipa_ctx); spin_lock_init(&rndis_ipa_ctx->state_lock); rndis_ipa_ctx->net = net; rndis_ipa_ctx->tx_filter = false; rndis_ipa_ctx->rx_filter = false; Loading Loading @@ -703,6 +707,7 @@ int rndis_ipa_pipe_connect_notify(u32 usb_to_ipa_hdl, struct rndis_ipa_dev *rndis_ipa_ctx = private; int next_state; int result; unsigned long flags; RNDIS_IPA_LOG_ENTRY(); Loading @@ -716,12 +721,15 @@ int rndis_ipa_pipe_connect_notify(u32 usb_to_ipa_hdl, RNDIS_IPA_DEBUG("max_xfer_sz_to_host=%d\n", max_xfer_size_bytes_to_host); spin_lock_irqsave(&rndis_ipa_ctx->state_lock, flags); next_state = rndis_ipa_next_state(rndis_ipa_ctx->state, RNDIS_IPA_CONNECT); if (next_state == RNDIS_IPA_INVALID) { spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); RNDIS_IPA_ERROR("use init()/disconnect() before connect()\n"); return -EPERM; } spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); if (usb_to_ipa_hdl >= IPA_CLIENT_MAX) { RNDIS_IPA_ERROR("usb_to_ipa_hdl(%d) - not valid ipa handle\n", Loading Loading @@ -770,7 +778,17 @@ int rndis_ipa_pipe_connect_notify(u32 usb_to_ipa_hdl, } RNDIS_IPA_DEBUG("netif_carrier_on() was called\n"); spin_lock_irqsave(&rndis_ipa_ctx->state_lock, flags); next_state = rndis_ipa_next_state(rndis_ipa_ctx->state, RNDIS_IPA_CONNECT); if (next_state == RNDIS_IPA_INVALID) { spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); RNDIS_IPA_ERROR("use init()/disconnect() before connect()\n"); return -EPERM; } rndis_ipa_ctx->state = next_state; spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); RNDIS_IPA_STATE_DEBUG(rndis_ipa_ctx); if (next_state == RNDIS_IPA_CONNECTED_AND_UP) Loading Loading @@ -807,18 +825,25 @@ static int rndis_ipa_open(struct net_device *net) { struct rndis_ipa_dev *rndis_ipa_ctx; int next_state; unsigned long flags; RNDIS_IPA_LOG_ENTRY(); rndis_ipa_ctx = netdev_priv(net); spin_lock_irqsave(&rndis_ipa_ctx->state_lock, flags); next_state = rndis_ipa_next_state(rndis_ipa_ctx->state, RNDIS_IPA_OPEN); if (next_state == RNDIS_IPA_INVALID) { spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); RNDIS_IPA_ERROR("can't bring driver up before initialize\n"); return -EPERM; } rndis_ipa_ctx->state = next_state; spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); RNDIS_IPA_STATE_DEBUG(rndis_ipa_ctx); Loading Loading @@ -1151,19 +1176,26 @@ static int rndis_ipa_stop(struct net_device *net) { struct rndis_ipa_dev *rndis_ipa_ctx = netdev_priv(net); int next_state; unsigned long flags; RNDIS_IPA_LOG_ENTRY(); spin_lock_irqsave(&rndis_ipa_ctx->state_lock, flags); next_state = rndis_ipa_next_state(rndis_ipa_ctx->state, RNDIS_IPA_STOP); if (next_state == RNDIS_IPA_INVALID) { spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); RNDIS_IPA_DEBUG("can't do network interface down without up\n"); return -EPERM; } rndis_ipa_ctx->state = next_state; spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); netif_stop_queue(net); pr_info("RNDIS_IPA NetDev queue is stopped\n"); rndis_ipa_ctx->state = next_state; RNDIS_IPA_STATE_DEBUG(rndis_ipa_ctx); RNDIS_IPA_LOG_EXIT(); Loading Loading @@ -1192,18 +1224,23 @@ int rndis_ipa_pipe_disconnect_notify(void *private) int next_state; int outstanding_dropped_pkts; int retval; unsigned long flags; RNDIS_IPA_LOG_ENTRY(); NULL_CHECK_RETVAL(rndis_ipa_ctx); RNDIS_IPA_DEBUG("private=0x%p\n", private); spin_lock_irqsave(&rndis_ipa_ctx->state_lock, flags); next_state = rndis_ipa_next_state(rndis_ipa_ctx->state, RNDIS_IPA_DISCONNECT); if (next_state == RNDIS_IPA_INVALID) { spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); RNDIS_IPA_ERROR("can't disconnect before connect\n"); return -EPERM; } spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); if (rndis_ipa_ctx->during_xmit_error) { RNDIS_IPA_DEBUG("canceling xmit-error delayed work\n"); Loading Loading @@ -1231,7 +1268,17 @@ int rndis_ipa_pipe_disconnect_notify(void *private) } RNDIS_IPA_DEBUG("RM was successfully destroyed\n"); spin_lock_irqsave(&rndis_ipa_ctx->state_lock, flags); next_state = rndis_ipa_next_state(rndis_ipa_ctx->state, RNDIS_IPA_DISCONNECT); if (next_state == RNDIS_IPA_INVALID) { spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); RNDIS_IPA_ERROR("can't disconnect before connect\n"); return -EPERM; } rndis_ipa_ctx->state = next_state; spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); RNDIS_IPA_STATE_DEBUG(rndis_ipa_ctx); pr_info("RNDIS_IPA NetDev pipes disconnected (%d outstanding clr)\n", Loading Loading @@ -1270,6 +1317,7 @@ void rndis_ipa_cleanup(void *private) struct rndis_ipa_dev *rndis_ipa_ctx = private; int next_state; int retval; unsigned long flags; RNDIS_IPA_LOG_ENTRY(); Loading @@ -1280,12 +1328,16 @@ void rndis_ipa_cleanup(void *private) return; } spin_lock_irqsave(&rndis_ipa_ctx->state_lock, flags); next_state = rndis_ipa_next_state(rndis_ipa_ctx->state, RNDIS_IPA_CLEANUP); if (next_state == RNDIS_IPA_INVALID) { spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); RNDIS_IPA_ERROR("use disconnect()before clean()\n"); return; } spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); RNDIS_IPA_STATE_DEBUG(rndis_ipa_ctx); retval = rndis_ipa_deregister_properties(rndis_ipa_ctx->net->name); Loading @@ -1308,7 +1360,16 @@ void rndis_ipa_cleanup(void *private) unregister_netdev(rndis_ipa_ctx->net); RNDIS_IPA_DEBUG("netdev unregistered\n"); spin_lock_irqsave(&rndis_ipa_ctx->state_lock, flags); next_state = rndis_ipa_next_state(rndis_ipa_ctx->state, RNDIS_IPA_CLEANUP); if (next_state == RNDIS_IPA_INVALID) { spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); RNDIS_IPA_ERROR("use disconnect()before clean()\n"); return; } rndis_ipa_ctx->state = next_state; spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); free_netdev(rndis_ipa_ctx->net); pr_info("RNDIS_IPA NetDev was cleaned\n"); Loading Loading
drivers/net/ethernet/msm/rndis_ipa.c +63 −2 Original line number Diff line number Diff line /* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -197,6 +197,7 @@ struct rndis_loopback_pipe { * This callback shall be called by the Netdev once the Netdev internal * state is changed to RNDIS_IPA_CONNECTED_AND_UP * @xmit_error_delayed_work: work item for cases where IPA driver Tx fails * @state_lock: used to protect the state variable. */ struct rndis_ipa_dev { struct net_device *net; Loading Loading @@ -228,6 +229,7 @@ struct rndis_ipa_dev { u8 device_ethaddr[ETH_ALEN]; void (*device_ready_notify)(void); struct delayed_work xmit_error_delayed_work; spinlock_t state_lock; /* Spinlock for the state variable.*/ }; /** Loading Loading @@ -560,6 +562,8 @@ int rndis_ipa_init(struct ipa_usb_init_params *params) memset(rndis_ipa_ctx, 0, sizeof(*rndis_ipa_ctx)); RNDIS_IPA_DEBUG("rndis_ipa_ctx (private)=%p\n", rndis_ipa_ctx); spin_lock_init(&rndis_ipa_ctx->state_lock); rndis_ipa_ctx->net = net; rndis_ipa_ctx->tx_filter = false; rndis_ipa_ctx->rx_filter = false; Loading Loading @@ -703,6 +707,7 @@ int rndis_ipa_pipe_connect_notify(u32 usb_to_ipa_hdl, struct rndis_ipa_dev *rndis_ipa_ctx = private; int next_state; int result; unsigned long flags; RNDIS_IPA_LOG_ENTRY(); Loading @@ -716,12 +721,15 @@ int rndis_ipa_pipe_connect_notify(u32 usb_to_ipa_hdl, RNDIS_IPA_DEBUG("max_xfer_sz_to_host=%d\n", max_xfer_size_bytes_to_host); spin_lock_irqsave(&rndis_ipa_ctx->state_lock, flags); next_state = rndis_ipa_next_state(rndis_ipa_ctx->state, RNDIS_IPA_CONNECT); if (next_state == RNDIS_IPA_INVALID) { spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); RNDIS_IPA_ERROR("use init()/disconnect() before connect()\n"); return -EPERM; } spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); if (usb_to_ipa_hdl >= IPA_CLIENT_MAX) { RNDIS_IPA_ERROR("usb_to_ipa_hdl(%d) - not valid ipa handle\n", Loading Loading @@ -770,7 +778,17 @@ int rndis_ipa_pipe_connect_notify(u32 usb_to_ipa_hdl, } RNDIS_IPA_DEBUG("netif_carrier_on() was called\n"); spin_lock_irqsave(&rndis_ipa_ctx->state_lock, flags); next_state = rndis_ipa_next_state(rndis_ipa_ctx->state, RNDIS_IPA_CONNECT); if (next_state == RNDIS_IPA_INVALID) { spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); RNDIS_IPA_ERROR("use init()/disconnect() before connect()\n"); return -EPERM; } rndis_ipa_ctx->state = next_state; spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); RNDIS_IPA_STATE_DEBUG(rndis_ipa_ctx); if (next_state == RNDIS_IPA_CONNECTED_AND_UP) Loading Loading @@ -807,18 +825,25 @@ static int rndis_ipa_open(struct net_device *net) { struct rndis_ipa_dev *rndis_ipa_ctx; int next_state; unsigned long flags; RNDIS_IPA_LOG_ENTRY(); rndis_ipa_ctx = netdev_priv(net); spin_lock_irqsave(&rndis_ipa_ctx->state_lock, flags); next_state = rndis_ipa_next_state(rndis_ipa_ctx->state, RNDIS_IPA_OPEN); if (next_state == RNDIS_IPA_INVALID) { spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); RNDIS_IPA_ERROR("can't bring driver up before initialize\n"); return -EPERM; } rndis_ipa_ctx->state = next_state; spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); RNDIS_IPA_STATE_DEBUG(rndis_ipa_ctx); Loading Loading @@ -1151,19 +1176,26 @@ static int rndis_ipa_stop(struct net_device *net) { struct rndis_ipa_dev *rndis_ipa_ctx = netdev_priv(net); int next_state; unsigned long flags; RNDIS_IPA_LOG_ENTRY(); spin_lock_irqsave(&rndis_ipa_ctx->state_lock, flags); next_state = rndis_ipa_next_state(rndis_ipa_ctx->state, RNDIS_IPA_STOP); if (next_state == RNDIS_IPA_INVALID) { spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); RNDIS_IPA_DEBUG("can't do network interface down without up\n"); return -EPERM; } rndis_ipa_ctx->state = next_state; spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); netif_stop_queue(net); pr_info("RNDIS_IPA NetDev queue is stopped\n"); rndis_ipa_ctx->state = next_state; RNDIS_IPA_STATE_DEBUG(rndis_ipa_ctx); RNDIS_IPA_LOG_EXIT(); Loading Loading @@ -1192,18 +1224,23 @@ int rndis_ipa_pipe_disconnect_notify(void *private) int next_state; int outstanding_dropped_pkts; int retval; unsigned long flags; RNDIS_IPA_LOG_ENTRY(); NULL_CHECK_RETVAL(rndis_ipa_ctx); RNDIS_IPA_DEBUG("private=0x%p\n", private); spin_lock_irqsave(&rndis_ipa_ctx->state_lock, flags); next_state = rndis_ipa_next_state(rndis_ipa_ctx->state, RNDIS_IPA_DISCONNECT); if (next_state == RNDIS_IPA_INVALID) { spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); RNDIS_IPA_ERROR("can't disconnect before connect\n"); return -EPERM; } spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); if (rndis_ipa_ctx->during_xmit_error) { RNDIS_IPA_DEBUG("canceling xmit-error delayed work\n"); Loading Loading @@ -1231,7 +1268,17 @@ int rndis_ipa_pipe_disconnect_notify(void *private) } RNDIS_IPA_DEBUG("RM was successfully destroyed\n"); spin_lock_irqsave(&rndis_ipa_ctx->state_lock, flags); next_state = rndis_ipa_next_state(rndis_ipa_ctx->state, RNDIS_IPA_DISCONNECT); if (next_state == RNDIS_IPA_INVALID) { spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); RNDIS_IPA_ERROR("can't disconnect before connect\n"); return -EPERM; } rndis_ipa_ctx->state = next_state; spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); RNDIS_IPA_STATE_DEBUG(rndis_ipa_ctx); pr_info("RNDIS_IPA NetDev pipes disconnected (%d outstanding clr)\n", Loading Loading @@ -1270,6 +1317,7 @@ void rndis_ipa_cleanup(void *private) struct rndis_ipa_dev *rndis_ipa_ctx = private; int next_state; int retval; unsigned long flags; RNDIS_IPA_LOG_ENTRY(); Loading @@ -1280,12 +1328,16 @@ void rndis_ipa_cleanup(void *private) return; } spin_lock_irqsave(&rndis_ipa_ctx->state_lock, flags); next_state = rndis_ipa_next_state(rndis_ipa_ctx->state, RNDIS_IPA_CLEANUP); if (next_state == RNDIS_IPA_INVALID) { spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); RNDIS_IPA_ERROR("use disconnect()before clean()\n"); return; } spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); RNDIS_IPA_STATE_DEBUG(rndis_ipa_ctx); retval = rndis_ipa_deregister_properties(rndis_ipa_ctx->net->name); Loading @@ -1308,7 +1360,16 @@ void rndis_ipa_cleanup(void *private) unregister_netdev(rndis_ipa_ctx->net); RNDIS_IPA_DEBUG("netdev unregistered\n"); spin_lock_irqsave(&rndis_ipa_ctx->state_lock, flags); next_state = rndis_ipa_next_state(rndis_ipa_ctx->state, RNDIS_IPA_CLEANUP); if (next_state == RNDIS_IPA_INVALID) { spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); RNDIS_IPA_ERROR("use disconnect()before clean()\n"); return; } rndis_ipa_ctx->state = next_state; spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags); free_netdev(rndis_ipa_ctx->net); pr_info("RNDIS_IPA NetDev was cleaned\n"); Loading