Merge "msm: ipa: Enable support for dynamic loading of clients"

tirimbino
qctecmdr 6 years ago committed by Gerrit - the friendly Code Review server
commit fd43ddb0c0
  1. 57
      drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth.c
  2. 8
      drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_gsi.c
  3. 2
      drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_offload.c
  4. 4
      drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_pm.c
  5. 2
      include/linux/ipa_eth.h

@ -27,6 +27,11 @@ enum ipa_eth_states {
IPA_ETH_ST_MAX,
};
enum ipa_eth_dev_states {
IPA_ETH_DEV_ST_UNPAIRING,
IPA_ETH_DEV_ST_MAX,
};
static unsigned long ipa_eth_state;
static struct dentry *ipa_eth_debugfs;
@ -56,12 +61,15 @@ static inline bool ipa_eth_ready(void)
static inline bool initable(struct ipa_eth_device *eth_dev)
{
return eth_dev->init;
return !test_bit(IPA_ETH_DEV_ST_UNPAIRING, &eth_dev->state) &&
eth_dev->init;
}
static inline bool startable(struct ipa_eth_device *eth_dev)
{
return eth_dev->init && eth_dev->start &&
return !test_bit(IPA_ETH_DEV_ST_UNPAIRING, &eth_dev->state) &&
eth_dev->init &&
eth_dev->start &&
test_bit(IPA_ETH_IF_ST_LOWER_UP, &eth_dev->if_state);
}
@ -148,9 +156,13 @@ static int ipa_eth_deinit_device(struct ipa_eth_device *eth_dev)
return 0;
}
static void ipa_eth_free_msg(void *buff, u32 len, u32 type) {}
static int ipa_eth_start_device(struct ipa_eth_device *eth_dev)
{
int rc;
struct ipa_msg_meta msg_meta;
struct ipa_ecm_msg ecm_msg;
if (eth_dev->of_state == IPA_ETH_OF_ST_STARTED)
return 0;
@ -180,6 +192,16 @@ static int ipa_eth_start_device(struct ipa_eth_device *eth_dev)
return rc;
}
memset(&msg_meta, 0, sizeof(msg_meta));
memset(&ecm_msg, 0, sizeof(ecm_msg));
ecm_msg.ifindex = eth_dev->net_dev->ifindex;
strlcpy(ecm_msg.name, eth_dev->net_dev->name, IPA_RESOURCE_NAME_MAX);
msg_meta.msg_type = ECM_CONNECT;
msg_meta.msg_len = sizeof(struct ipa_ecm_msg);
(void) ipa_send_msg(&msg_meta, &ecm_msg, ipa_eth_free_msg);
ipa_eth_dev_log(eth_dev, "Started device");
eth_dev->of_state = IPA_ETH_OF_ST_STARTED;
@ -190,6 +212,18 @@ static int ipa_eth_start_device(struct ipa_eth_device *eth_dev)
static int ipa_eth_stop_device(struct ipa_eth_device *eth_dev)
{
int rc;
struct ipa_msg_meta msg_meta;
struct ipa_ecm_msg ecm_msg;
memset(&msg_meta, 0, sizeof(msg_meta));
memset(&ecm_msg, 0, sizeof(ecm_msg));
ecm_msg.ifindex = eth_dev->net_dev->ifindex;
strlcpy(ecm_msg.name, eth_dev->net_dev->name, IPA_RESOURCE_NAME_MAX);
msg_meta.msg_type = ECM_DISCONNECT;
msg_meta.msg_len = sizeof(struct ipa_ecm_msg);
(void) ipa_send_msg(&msg_meta, &ecm_msg, ipa_eth_free_msg);
if (eth_dev->of_state == IPA_ETH_OF_ST_DEINITED)
return 0;
@ -342,7 +376,7 @@ static void ipa_eth_dev_start_timer_cb(unsigned long data)
ipa_eth_refresh_device(eth_dev);
}
static int ipa_eth_netdev_event_change(struct ipa_eth_device *eth_dev)
static int __ipa_eth_netdev_event(struct ipa_eth_device *eth_dev)
{
bool refresh_needed = netif_carrier_ok(eth_dev->net_dev) ?
!test_and_set_bit(IPA_ETH_IF_ST_LOWER_UP, &eth_dev->if_state) :
@ -365,17 +399,9 @@ static int ipa_eth_netdev_event(struct notifier_block *nb,
if (net_dev != eth_dev->net_dev)
return NOTIFY_DONE;
ipa_eth_dev_log(eth_dev, "Received netdev event %lu", event);
switch (event) {
case NETDEV_CHANGE:
return ipa_eth_netdev_event_change(eth_dev);
default:
/* Ignore other events */
break;
}
ipa_eth_dev_log(eth_dev, "Received netdev event 0x%04lx", event);
return NOTIFY_DONE;
return __ipa_eth_netdev_event(eth_dev);
}
static int ipa_eth_uc_ready_cb(struct notifier_block *nb,
@ -620,7 +646,7 @@ static void __ipa_eth_unpair_device(struct ipa_eth_device *eth_dev)
flush_work(&eth_dev->refresh);
eth_dev->init = eth_dev->start = false;
set_bit(IPA_ETH_DEV_ST_UNPAIRING, &eth_dev->state);
ipa_eth_refresh_device(eth_dev);
flush_work(&eth_dev->refresh);
@ -628,6 +654,8 @@ static void __ipa_eth_unpair_device(struct ipa_eth_device *eth_dev)
unregister_netdevice_notifier(&eth_dev->netdevice_nb);
ipa_eth_offload_unpair_device(eth_dev);
clear_bit(IPA_ETH_DEV_ST_UNPAIRING, &eth_dev->state);
}
static void ipa_eth_pair_devices(void)
@ -904,6 +932,7 @@ int ipa_eth_register_offload_driver(struct ipa_eth_offload_driver *od)
ipa_eth_log("Registered offload driver %s", od->name);
ipa_eth_pair_devices();
ipa_eth_refresh_devices();
return 0;
}

@ -242,6 +242,14 @@ int ipa_eth_gsi_dealloc(struct ipa_eth_channel *ch)
}
if (ep_ctx->gsi_evt_ring_hdl != ~0) {
gsi_rc = gsi_reset_evt_ring(ep_ctx->gsi_evt_ring_hdl);
if (gsi_rc != GSI_STATUS_SUCCESS) {
ipa_eth_dev_err(ch->eth_dev,
"Failed to reset event ring %lu",
ep_ctx->gsi_evt_ring_hdl);
return gsi_rc;
}
gsi_rc = gsi_dealloc_evt_ring(ep_ctx->gsi_evt_ring_hdl);
if (gsi_rc != GSI_STATUS_SUCCESS) {
ipa_eth_dev_err(ch->eth_dev,

@ -207,6 +207,8 @@ int ipa_eth_offload_register_driver(struct ipa_eth_offload_driver *od)
void ipa_eth_offload_unregister_driver(struct ipa_eth_offload_driver *od)
{
debugfs_remove_recursive(od->debugfs);
mutex_lock(&ipa_eth_offload_drivers_lock);
list_del(&od->driver_list);
mutex_unlock(&ipa_eth_offload_drivers_lock);

@ -11,6 +11,7 @@
*/
#include <linux/ethtool.h>
#include <linux/rtnetlink.h>
#include "ipa_eth_i.h"
@ -100,7 +101,10 @@ static u32 __fetch_ethtool_link_speed(struct ipa_eth_device *eth_dev)
int rc;
struct ethtool_link_ksettings link_ksettings;
rtnl_lock();
rc = __ethtool_get_link_ksettings(eth_dev->net_dev, &link_ksettings);
rtnl_unlock();
if (rc) {
ipa_eth_dev_err(eth_dev,
"Failed to obtain link settings via ethtool");

@ -440,6 +440,7 @@ struct ipa_eth_channel {
* @start_on_resume: Allow start upon driver resume
* @start_on_timeout: Timeout in milliseconds after which @start is enabled
* @start_timer: Timer associated with @start_on_timer
* @state: Device state
* @if_state: Interface state - one or more bit numbers IPA_ETH_IF_ST_*
* @pm_handle: IPA PM client handle for the device
* @bus_priv: Private field for use by offload subsystem bus layer
@ -478,6 +479,7 @@ struct ipa_eth_device {
u32 start_on_timeout;
struct timer_list start_timer;
unsigned long state;
unsigned long if_state;
u32 pm_handle;

Loading…
Cancel
Save