Loading drivers/net/ethernet/msm/ecm_ipa.c +67 −18 Original line number Diff line number Diff line Loading @@ -34,6 +34,10 @@ pr_debug("ctx:%s: "\ fmt, current->comm, ## args) #define ECM_IPA_INFO(fmt, args...) \ pr_err(DRIVER_NAME "@%s@%d@ctx:%s: "\ fmt, __func__, __LINE__, current->comm, ## args) #define ECM_IPA_ERROR(fmt, args...) \ pr_err(DRIVER_NAME "@%s@%d@ctx:%s: "\ fmt, __func__, __LINE__, current->comm, ## args) Loading Loading @@ -94,7 +98,7 @@ enum ecm_ipa_operation { }; #define ECM_IPA_STATE_DEBUG(ecm_ipa_ctx) \ ECM_IPA_DEBUG("Driver state - %s",\ ECM_IPA_DEBUG("Driver state - %s\n",\ ecm_ipa_state_string(ecm_ipa_ctx->state)); /** Loading @@ -114,6 +118,9 @@ enum ecm_ipa_operation { * @outstanding_low: number of outstanding packets which shall cause * to netdev queue start (after stopped due to outstanding_high reached) * @state: current state of ecm_ipa driver * @device_ready_notify: callback supplied by USB core driver * This callback shall be called by the Netdev once the Netdev internal * state is changed to RNDIS_IPA_CONNECTED_AND_UP */ struct ecm_ipa_dev { struct net_device *net; Loading @@ -130,6 +137,7 @@ struct ecm_ipa_dev { u8 outstanding_high; u8 outstanding_low; enum ecm_ipa_state state; void (*device_ready_notify)(void); }; static int ecm_ipa_open(struct net_device *net); Loading @@ -138,6 +146,7 @@ static void ecm_ipa_packet_receive_notify(void *priv, static void ecm_ipa_tx_complete_notify(void *priv, enum ipa_dp_evt_type evt, unsigned long data); static int ecm_ipa_stop(struct net_device *net); static void ecm_ipa_enable_data_path(struct ecm_ipa_dev *ecm_ipa_ctx); static int ecm_ipa_rules_cfg(struct ecm_ipa_dev *ecm_ipa_ctx, const void *dst_mac, const void *src_mac); static void ecm_ipa_rules_destroy(struct ecm_ipa_dev *ecm_ipa_ctx); Loading Loading @@ -228,6 +237,7 @@ int ecm_ipa_init(struct ecm_ipa_params *params) struct ecm_ipa_dev *ecm_ipa_ctx; ECM_IPA_LOG_ENTRY(); ECM_IPA_DEBUG("%s initializing\n", DRIVER_NAME); NULL_CHECK(params); Loading @@ -250,7 +260,7 @@ int ecm_ipa_init(struct ecm_ipa_params *params) goto fail_netdev_priv; } memset(ecm_ipa_ctx, 0, sizeof(*ecm_ipa_ctx)); ECM_IPA_DEBUG("ecm_ipa_ctx (private) = %p", ecm_ipa_ctx); ECM_IPA_DEBUG("ecm_ipa_ctx (private) = %p\n", ecm_ipa_ctx); ecm_ipa_ctx->net = net; ecm_ipa_ctx->tx_enable = true; Loading @@ -263,6 +273,10 @@ int ecm_ipa_init(struct ecm_ipa_params *params) net->netdev_ops = &ecm_ipa_netdev_ops; ECM_IPA_DEBUG("internal data structures were intialized\n"); if (!params->device_ready_notify) ECM_IPA_DEBUG("device_ready_notify() was not supplied"); ecm_ipa_ctx->device_ready_notify = params->device_ready_notify; result = ecm_ipa_debugfs_init(ecm_ipa_ctx); if (result) goto fail_debugfs; Loading Loading @@ -315,6 +329,8 @@ int ecm_ipa_init(struct ecm_ipa_params *params) ecm_ipa_ctx->state = ECM_IPA_INITIALIZED; ECM_IPA_STATE_DEBUG(ecm_ipa_ctx); ECM_IPA_INFO("ECM_IPA was initialized successfully\n"); ECM_IPA_LOG_EXIT(); return 0; Loading Loading @@ -346,6 +362,8 @@ EXPORT_SYMBOL(ecm_ipa_init); * Once USB driver finishes the pipe connection between IPA core * and USB core this method shall be called in order to * allow ecm_ipa complete the data path configurations. * Caller should make sure that it is calling this function * from a context that allows it to handle device_ready_notify(). * Detailed description: * - configure the IPA end-points register * - notify the Linux kernel for "carrier_on" Loading Loading @@ -420,12 +438,14 @@ int ecm_ipa_connect(u32 usb_to_ipa_hdl, u32 ipa_to_usb_hdl, retval = -EBUSY; goto fail_carrier; } ECM_IPA_DEBUG("carrier_on notified, ecm_ipa is operational\n"); ECM_IPA_DEBUG("carrier_on notified\n"); if (ecm_ipa_ctx->state == ECM_IPA_CONNECTED_AND_UP) { netif_start_queue(ecm_ipa_ctx->net); ECM_IPA_DEBUG("queue started\n"); } if (ecm_ipa_ctx->state == ECM_IPA_CONNECTED_AND_UP) ecm_ipa_enable_data_path(ecm_ipa_ctx); else ECM_IPA_DEBUG("data path was not enabled yet\n"); ECM_IPA_INFO("ECM_IPA was connected successfully\n"); ECM_IPA_LOG_EXIT(); Loading Loading @@ -465,12 +485,10 @@ static int ecm_ipa_open(struct net_device *net) ecm_ipa_ctx->state = next_state; ECM_IPA_STATE_DEBUG(ecm_ipa_ctx); if (ecm_ipa_ctx->state == ECM_IPA_CONNECTED_AND_UP) { netif_start_queue(net); ECM_IPA_DEBUG("queue started\n"); } else { ECM_IPA_DEBUG("queue was not started, waiting for connect()\n"); } if (ecm_ipa_ctx->state == ECM_IPA_CONNECTED_AND_UP) ecm_ipa_enable_data_path(ecm_ipa_ctx); else ECM_IPA_DEBUG("data path was not enabled yet\n"); ECM_IPA_LOG_EXIT(); Loading Loading @@ -504,7 +522,8 @@ static netdev_tx_t ecm_ipa_start_xmit(struct sk_buff *skb, netdev_tx_t status = NETDEV_TX_BUSY; struct ecm_ipa_dev *ecm_ipa_ctx = netdev_priv(net); ECM_IPA_DEBUG("packet TX, len=%d", skb->len); ECM_IPA_DEBUG("packet Tx, len=%d, skb->protocol=%d\n", skb->len, skb->protocol); if (unlikely(netif_queue_stopped(net))) { ECM_IPA_ERROR("interface queue is stopped\n"); Loading Loading @@ -575,7 +594,12 @@ static void ecm_ipa_packet_receive_notify(void *priv, struct ecm_ipa_dev *ecm_ipa_ctx = priv; int result; ECM_IPA_DEBUG("packet RX, len=%d", skb->len); if (!skb) { ECM_IPA_ERROR("Bad SKB received from IPA driver\n"); return; } ECM_IPA_DEBUG("packet RX, len=%d\n", skb->len); if (unlikely(ecm_ipa_ctx->state != ECM_IPA_CONNECTED_AND_UP)) { ECM_IPA_DEBUG("Missing pipe connected and/or iface up\n"); Loading Loading @@ -697,6 +721,8 @@ int ecm_ipa_disconnect(void *priv) ecm_ipa_ctx->net->stats.tx_errors += outstanding_dropped_pkts; atomic_set(&ecm_ipa_ctx->outstanding_pkts, 0); ECM_IPA_INFO("ECM_IPA was disconnected successfully\n"); ECM_IPA_LOG_EXIT(); return 0; Loading Loading @@ -749,13 +775,27 @@ void ecm_ipa_cleanup(void *priv) unregister_netdev(ecm_ipa_ctx->net); free_netdev(ecm_ipa_ctx->net); ECM_IPA_DEBUG("cleanup done\n"); ECM_IPA_INFO("ECM_IPA was destroyed successfully\n"); ECM_IPA_LOG_EXIT(); return; } EXPORT_SYMBOL(ecm_ipa_cleanup); static void ecm_ipa_enable_data_path(struct ecm_ipa_dev *ecm_ipa_ctx) { if (ecm_ipa_ctx->device_ready_notify) { ecm_ipa_ctx->device_ready_notify(); ECM_IPA_DEBUG("USB device_ready_notify() was called\n"); } else { ECM_IPA_DEBUG("device_ready_notify() not supplied\n"); } netif_start_queue(ecm_ipa_ctx->net); ECM_IPA_DEBUG("queue started\n"); } /** * ecm_ipa_rules_cfg() - set header insertion and register Tx/Rx properties * Headers will be commited to HW Loading Loading @@ -851,7 +891,7 @@ static void ecm_ipa_rules_destroy(struct ecm_ipa_dev *ecm_ipa_ctx) ipv6->hdl = ecm_ipa_ctx->eth_ipv6_hdr_hdl; result = ipa_del_hdr(del_hdr); if (result || ipv4->status || ipv6->status) ECM_IPA_ERROR("ipa_del_hdr failed"); ECM_IPA_ERROR("ipa_del_hdr failed\n"); } /* ecm_ipa_register_properties() - set Tx/Rx properties for ipacm Loading Loading @@ -1076,6 +1116,15 @@ static void ecm_ipa_tx_complete_notify(void *priv, struct sk_buff *skb = (struct sk_buff *)data; struct ecm_ipa_dev *ecm_ipa_ctx = priv; if (!skb) { ECM_IPA_ERROR("Bad SKB received from IPA driver\n"); return; } ECM_IPA_DEBUG("packet Tx-complete, len=%d, skb->protocol=%d\n", skb->len, skb->protocol); if (!ecm_ipa_ctx) { ECM_IPA_ERROR("ecm_ipa_ctx is NULL pointer\n"); return; Loading Loading @@ -1176,7 +1225,7 @@ static ssize_t ecm_ipa_debugfs_enable_read(struct file *file, nbytes = scnprintf(enable_str, sizeof(enable_str), "%d\n", *enable); ret = simple_read_from_buffer(ubuf, count, ppos, enable_str, nbytes); if (ret < 0) { ECM_IPA_ERROR("simple_read_from_buffer problem"); ECM_IPA_ERROR("simple_read_from_buffer problem\n"); return ret; } size += ret; Loading include/linux/ecm_ipa.h +4 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,9 @@ typedef void (*ecm_ipa_callback)(void *priv, /* * struct ecm_ipa_params - parameters for ecm_ipa initialization API * * @device_ready_notify: callback supplied by USB core driver. * This callback shall be called by the Netdev once the device * is ready to recieve data from tethered PC. * @ecm_ipa_rx_dp_notify: ecm_ipa will set this callback (out parameter). * this callback shall be supplied for ipa_connect upon pipe * connection (USB->IPA), once IPA driver receive data packets Loading @@ -44,6 +47,7 @@ typedef void (*ecm_ipa_callback)(void *priv, * should or should not configure this end-point. */ struct ecm_ipa_params { void (*device_ready_notify)(void); ecm_ipa_callback ecm_ipa_rx_dp_notify; ecm_ipa_callback ecm_ipa_tx_dp_notify; u8 host_ethaddr[ETH_ALEN]; Loading Loading
drivers/net/ethernet/msm/ecm_ipa.c +67 −18 Original line number Diff line number Diff line Loading @@ -34,6 +34,10 @@ pr_debug("ctx:%s: "\ fmt, current->comm, ## args) #define ECM_IPA_INFO(fmt, args...) \ pr_err(DRIVER_NAME "@%s@%d@ctx:%s: "\ fmt, __func__, __LINE__, current->comm, ## args) #define ECM_IPA_ERROR(fmt, args...) \ pr_err(DRIVER_NAME "@%s@%d@ctx:%s: "\ fmt, __func__, __LINE__, current->comm, ## args) Loading Loading @@ -94,7 +98,7 @@ enum ecm_ipa_operation { }; #define ECM_IPA_STATE_DEBUG(ecm_ipa_ctx) \ ECM_IPA_DEBUG("Driver state - %s",\ ECM_IPA_DEBUG("Driver state - %s\n",\ ecm_ipa_state_string(ecm_ipa_ctx->state)); /** Loading @@ -114,6 +118,9 @@ enum ecm_ipa_operation { * @outstanding_low: number of outstanding packets which shall cause * to netdev queue start (after stopped due to outstanding_high reached) * @state: current state of ecm_ipa driver * @device_ready_notify: callback supplied by USB core driver * This callback shall be called by the Netdev once the Netdev internal * state is changed to RNDIS_IPA_CONNECTED_AND_UP */ struct ecm_ipa_dev { struct net_device *net; Loading @@ -130,6 +137,7 @@ struct ecm_ipa_dev { u8 outstanding_high; u8 outstanding_low; enum ecm_ipa_state state; void (*device_ready_notify)(void); }; static int ecm_ipa_open(struct net_device *net); Loading @@ -138,6 +146,7 @@ static void ecm_ipa_packet_receive_notify(void *priv, static void ecm_ipa_tx_complete_notify(void *priv, enum ipa_dp_evt_type evt, unsigned long data); static int ecm_ipa_stop(struct net_device *net); static void ecm_ipa_enable_data_path(struct ecm_ipa_dev *ecm_ipa_ctx); static int ecm_ipa_rules_cfg(struct ecm_ipa_dev *ecm_ipa_ctx, const void *dst_mac, const void *src_mac); static void ecm_ipa_rules_destroy(struct ecm_ipa_dev *ecm_ipa_ctx); Loading Loading @@ -228,6 +237,7 @@ int ecm_ipa_init(struct ecm_ipa_params *params) struct ecm_ipa_dev *ecm_ipa_ctx; ECM_IPA_LOG_ENTRY(); ECM_IPA_DEBUG("%s initializing\n", DRIVER_NAME); NULL_CHECK(params); Loading @@ -250,7 +260,7 @@ int ecm_ipa_init(struct ecm_ipa_params *params) goto fail_netdev_priv; } memset(ecm_ipa_ctx, 0, sizeof(*ecm_ipa_ctx)); ECM_IPA_DEBUG("ecm_ipa_ctx (private) = %p", ecm_ipa_ctx); ECM_IPA_DEBUG("ecm_ipa_ctx (private) = %p\n", ecm_ipa_ctx); ecm_ipa_ctx->net = net; ecm_ipa_ctx->tx_enable = true; Loading @@ -263,6 +273,10 @@ int ecm_ipa_init(struct ecm_ipa_params *params) net->netdev_ops = &ecm_ipa_netdev_ops; ECM_IPA_DEBUG("internal data structures were intialized\n"); if (!params->device_ready_notify) ECM_IPA_DEBUG("device_ready_notify() was not supplied"); ecm_ipa_ctx->device_ready_notify = params->device_ready_notify; result = ecm_ipa_debugfs_init(ecm_ipa_ctx); if (result) goto fail_debugfs; Loading Loading @@ -315,6 +329,8 @@ int ecm_ipa_init(struct ecm_ipa_params *params) ecm_ipa_ctx->state = ECM_IPA_INITIALIZED; ECM_IPA_STATE_DEBUG(ecm_ipa_ctx); ECM_IPA_INFO("ECM_IPA was initialized successfully\n"); ECM_IPA_LOG_EXIT(); return 0; Loading Loading @@ -346,6 +362,8 @@ EXPORT_SYMBOL(ecm_ipa_init); * Once USB driver finishes the pipe connection between IPA core * and USB core this method shall be called in order to * allow ecm_ipa complete the data path configurations. * Caller should make sure that it is calling this function * from a context that allows it to handle device_ready_notify(). * Detailed description: * - configure the IPA end-points register * - notify the Linux kernel for "carrier_on" Loading Loading @@ -420,12 +438,14 @@ int ecm_ipa_connect(u32 usb_to_ipa_hdl, u32 ipa_to_usb_hdl, retval = -EBUSY; goto fail_carrier; } ECM_IPA_DEBUG("carrier_on notified, ecm_ipa is operational\n"); ECM_IPA_DEBUG("carrier_on notified\n"); if (ecm_ipa_ctx->state == ECM_IPA_CONNECTED_AND_UP) { netif_start_queue(ecm_ipa_ctx->net); ECM_IPA_DEBUG("queue started\n"); } if (ecm_ipa_ctx->state == ECM_IPA_CONNECTED_AND_UP) ecm_ipa_enable_data_path(ecm_ipa_ctx); else ECM_IPA_DEBUG("data path was not enabled yet\n"); ECM_IPA_INFO("ECM_IPA was connected successfully\n"); ECM_IPA_LOG_EXIT(); Loading Loading @@ -465,12 +485,10 @@ static int ecm_ipa_open(struct net_device *net) ecm_ipa_ctx->state = next_state; ECM_IPA_STATE_DEBUG(ecm_ipa_ctx); if (ecm_ipa_ctx->state == ECM_IPA_CONNECTED_AND_UP) { netif_start_queue(net); ECM_IPA_DEBUG("queue started\n"); } else { ECM_IPA_DEBUG("queue was not started, waiting for connect()\n"); } if (ecm_ipa_ctx->state == ECM_IPA_CONNECTED_AND_UP) ecm_ipa_enable_data_path(ecm_ipa_ctx); else ECM_IPA_DEBUG("data path was not enabled yet\n"); ECM_IPA_LOG_EXIT(); Loading Loading @@ -504,7 +522,8 @@ static netdev_tx_t ecm_ipa_start_xmit(struct sk_buff *skb, netdev_tx_t status = NETDEV_TX_BUSY; struct ecm_ipa_dev *ecm_ipa_ctx = netdev_priv(net); ECM_IPA_DEBUG("packet TX, len=%d", skb->len); ECM_IPA_DEBUG("packet Tx, len=%d, skb->protocol=%d\n", skb->len, skb->protocol); if (unlikely(netif_queue_stopped(net))) { ECM_IPA_ERROR("interface queue is stopped\n"); Loading Loading @@ -575,7 +594,12 @@ static void ecm_ipa_packet_receive_notify(void *priv, struct ecm_ipa_dev *ecm_ipa_ctx = priv; int result; ECM_IPA_DEBUG("packet RX, len=%d", skb->len); if (!skb) { ECM_IPA_ERROR("Bad SKB received from IPA driver\n"); return; } ECM_IPA_DEBUG("packet RX, len=%d\n", skb->len); if (unlikely(ecm_ipa_ctx->state != ECM_IPA_CONNECTED_AND_UP)) { ECM_IPA_DEBUG("Missing pipe connected and/or iface up\n"); Loading Loading @@ -697,6 +721,8 @@ int ecm_ipa_disconnect(void *priv) ecm_ipa_ctx->net->stats.tx_errors += outstanding_dropped_pkts; atomic_set(&ecm_ipa_ctx->outstanding_pkts, 0); ECM_IPA_INFO("ECM_IPA was disconnected successfully\n"); ECM_IPA_LOG_EXIT(); return 0; Loading Loading @@ -749,13 +775,27 @@ void ecm_ipa_cleanup(void *priv) unregister_netdev(ecm_ipa_ctx->net); free_netdev(ecm_ipa_ctx->net); ECM_IPA_DEBUG("cleanup done\n"); ECM_IPA_INFO("ECM_IPA was destroyed successfully\n"); ECM_IPA_LOG_EXIT(); return; } EXPORT_SYMBOL(ecm_ipa_cleanup); static void ecm_ipa_enable_data_path(struct ecm_ipa_dev *ecm_ipa_ctx) { if (ecm_ipa_ctx->device_ready_notify) { ecm_ipa_ctx->device_ready_notify(); ECM_IPA_DEBUG("USB device_ready_notify() was called\n"); } else { ECM_IPA_DEBUG("device_ready_notify() not supplied\n"); } netif_start_queue(ecm_ipa_ctx->net); ECM_IPA_DEBUG("queue started\n"); } /** * ecm_ipa_rules_cfg() - set header insertion and register Tx/Rx properties * Headers will be commited to HW Loading Loading @@ -851,7 +891,7 @@ static void ecm_ipa_rules_destroy(struct ecm_ipa_dev *ecm_ipa_ctx) ipv6->hdl = ecm_ipa_ctx->eth_ipv6_hdr_hdl; result = ipa_del_hdr(del_hdr); if (result || ipv4->status || ipv6->status) ECM_IPA_ERROR("ipa_del_hdr failed"); ECM_IPA_ERROR("ipa_del_hdr failed\n"); } /* ecm_ipa_register_properties() - set Tx/Rx properties for ipacm Loading Loading @@ -1076,6 +1116,15 @@ static void ecm_ipa_tx_complete_notify(void *priv, struct sk_buff *skb = (struct sk_buff *)data; struct ecm_ipa_dev *ecm_ipa_ctx = priv; if (!skb) { ECM_IPA_ERROR("Bad SKB received from IPA driver\n"); return; } ECM_IPA_DEBUG("packet Tx-complete, len=%d, skb->protocol=%d\n", skb->len, skb->protocol); if (!ecm_ipa_ctx) { ECM_IPA_ERROR("ecm_ipa_ctx is NULL pointer\n"); return; Loading Loading @@ -1176,7 +1225,7 @@ static ssize_t ecm_ipa_debugfs_enable_read(struct file *file, nbytes = scnprintf(enable_str, sizeof(enable_str), "%d\n", *enable); ret = simple_read_from_buffer(ubuf, count, ppos, enable_str, nbytes); if (ret < 0) { ECM_IPA_ERROR("simple_read_from_buffer problem"); ECM_IPA_ERROR("simple_read_from_buffer problem\n"); return ret; } size += ret; Loading
include/linux/ecm_ipa.h +4 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,9 @@ typedef void (*ecm_ipa_callback)(void *priv, /* * struct ecm_ipa_params - parameters for ecm_ipa initialization API * * @device_ready_notify: callback supplied by USB core driver. * This callback shall be called by the Netdev once the device * is ready to recieve data from tethered PC. * @ecm_ipa_rx_dp_notify: ecm_ipa will set this callback (out parameter). * this callback shall be supplied for ipa_connect upon pipe * connection (USB->IPA), once IPA driver receive data packets Loading @@ -44,6 +47,7 @@ typedef void (*ecm_ipa_callback)(void *priv, * should or should not configure this end-point. */ struct ecm_ipa_params { void (*device_ready_notify)(void); ecm_ipa_callback ecm_ipa_rx_dp_notify; ecm_ipa_callback ecm_ipa_tx_dp_notify; u8 host_ethaddr[ETH_ALEN]; Loading