^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) /* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2018-2020 Linaro Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/if_arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/if_rmnet.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/remoteproc/qcom_rproc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "ipa.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "ipa_data.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "ipa_endpoint.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "ipa_table.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "ipa_mem.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "ipa_modem.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "ipa_smp2p.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "ipa_qmi.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define IPA_NETDEV_NAME "rmnet_ipa%d"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define IPA_NETDEV_TAILROOM 0 /* for padding by mux layer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define IPA_NETDEV_TIMEOUT 10 /* seconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) enum ipa_modem_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) IPA_MODEM_STATE_STOPPED = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) IPA_MODEM_STATE_STARTING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) IPA_MODEM_STATE_RUNNING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) IPA_MODEM_STATE_STOPPING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /** struct ipa_priv - IPA network device private data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct ipa_priv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct ipa *ipa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /** ipa_open() - Opens the modem network interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static int ipa_open(struct net_device *netdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct ipa_priv *priv = netdev_priv(netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct ipa *ipa = priv->ipa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) ret = ipa_endpoint_enable_one(ipa->name_map[IPA_ENDPOINT_AP_MODEM_TX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) ret = ipa_endpoint_enable_one(ipa->name_map[IPA_ENDPOINT_AP_MODEM_RX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) goto err_disable_tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) netif_start_queue(netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) err_disable_tx:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) ipa_endpoint_disable_one(ipa->name_map[IPA_ENDPOINT_AP_MODEM_TX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /** ipa_stop() - Stops the modem network interface. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static int ipa_stop(struct net_device *netdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct ipa_priv *priv = netdev_priv(netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct ipa *ipa = priv->ipa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) netif_stop_queue(netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) ipa_endpoint_disable_one(ipa->name_map[IPA_ENDPOINT_AP_MODEM_RX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) ipa_endpoint_disable_one(ipa->name_map[IPA_ENDPOINT_AP_MODEM_TX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /** ipa_start_xmit() - Transmits an skb.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * @skb: skb to be transmitted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * @dev: network device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * Return codes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * NETDEV_TX_OK: Success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * NETDEV_TX_BUSY: Error while transmitting the skb. Try again later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static int ipa_start_xmit(struct sk_buff *skb, struct net_device *netdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct net_device_stats *stats = &netdev->stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) struct ipa_priv *priv = netdev_priv(netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct ipa_endpoint *endpoint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct ipa *ipa = priv->ipa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) u32 skb_len = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (!skb_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) goto err_drop_skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) endpoint = ipa->name_map[IPA_ENDPOINT_AP_MODEM_TX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (endpoint->data->qmap && skb->protocol != htons(ETH_P_MAP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) goto err_drop_skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) ret = ipa_endpoint_skb_tx(endpoint, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (ret != -E2BIG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return NETDEV_TX_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) goto err_drop_skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) stats->tx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) stats->tx_bytes += skb_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) err_drop_skb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) dev_kfree_skb_any(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) stats->tx_dropped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) void ipa_modem_skb_rx(struct net_device *netdev, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct net_device_stats *stats = &netdev->stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) skb->dev = netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) skb->protocol = htons(ETH_P_MAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) stats->rx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) stats->rx_bytes += skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) (void)netif_receive_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) stats->rx_dropped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static const struct net_device_ops ipa_modem_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) .ndo_open = ipa_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .ndo_stop = ipa_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .ndo_start_xmit = ipa_start_xmit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /** ipa_modem_netdev_setup() - netdev setup function for the modem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static void ipa_modem_netdev_setup(struct net_device *netdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) netdev->netdev_ops = &ipa_modem_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) ether_setup(netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /* No header ops (override value set by ether_setup()) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) netdev->header_ops = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) netdev->type = ARPHRD_RAWIP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) netdev->hard_header_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) netdev->max_mtu = IPA_MTU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) netdev->mtu = netdev->max_mtu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) netdev->addr_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) netdev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) /* The endpoint is configured for QMAP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) netdev->needed_headroom = sizeof(struct rmnet_map_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) netdev->needed_tailroom = IPA_NETDEV_TAILROOM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) netdev->watchdog_timeo = IPA_NETDEV_TIMEOUT * HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) netdev->hw_features = NETIF_F_SG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /** ipa_modem_suspend() - suspend callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * @netdev: Network device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * Suspend the modem's endpoints.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) void ipa_modem_suspend(struct net_device *netdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct ipa_priv *priv = netdev_priv(netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) struct ipa *ipa = priv->ipa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) netif_stop_queue(netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) ipa_endpoint_suspend_one(ipa->name_map[IPA_ENDPOINT_AP_MODEM_RX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) ipa_endpoint_suspend_one(ipa->name_map[IPA_ENDPOINT_AP_MODEM_TX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) /** ipa_modem_resume() - resume callback for runtime_pm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * @dev: pointer to device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * Resume the modem's endpoints.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) void ipa_modem_resume(struct net_device *netdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct ipa_priv *priv = netdev_priv(netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct ipa *ipa = priv->ipa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) ipa_endpoint_resume_one(ipa->name_map[IPA_ENDPOINT_AP_MODEM_TX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) ipa_endpoint_resume_one(ipa->name_map[IPA_ENDPOINT_AP_MODEM_RX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) netif_wake_queue(netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) int ipa_modem_start(struct ipa *ipa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) enum ipa_modem_state state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) struct net_device *netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct ipa_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) /* Only attempt to start the modem if it's stopped */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) state = atomic_cmpxchg(&ipa->modem_state, IPA_MODEM_STATE_STOPPED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) IPA_MODEM_STATE_STARTING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) /* Silently ignore attempts when running, or when changing state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (state != IPA_MODEM_STATE_STOPPED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) netdev = alloc_netdev(sizeof(struct ipa_priv), IPA_NETDEV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) NET_NAME_UNKNOWN, ipa_modem_netdev_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (!netdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) goto out_set_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) ipa->name_map[IPA_ENDPOINT_AP_MODEM_TX]->netdev = netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) ipa->name_map[IPA_ENDPOINT_AP_MODEM_RX]->netdev = netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) SET_NETDEV_DEV(netdev, &ipa->pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) priv = netdev_priv(netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) priv->ipa = ipa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) ret = register_netdev(netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) free_netdev(netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) ipa->modem_netdev = netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) out_set_state:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) atomic_set(&ipa->modem_state, IPA_MODEM_STATE_STOPPED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) atomic_set(&ipa->modem_state, IPA_MODEM_STATE_RUNNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) smp_mb__after_atomic();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) int ipa_modem_stop(struct ipa *ipa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) struct net_device *netdev = ipa->modem_netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) enum ipa_modem_state state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) /* Only attempt to stop the modem if it's running */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) state = atomic_cmpxchg(&ipa->modem_state, IPA_MODEM_STATE_RUNNING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) IPA_MODEM_STATE_STOPPING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /* Silently ignore attempts when already stopped */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (state == IPA_MODEM_STATE_STOPPED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) /* If we're somewhere between stopped and starting, we're busy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (state != IPA_MODEM_STATE_RUNNING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /* Prevent the modem from triggering a call to ipa_setup() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) ipa_smp2p_disable(ipa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (netdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) /* Stop the queue and disable the endpoints if it's open */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) ret = ipa_stop(netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) goto out_set_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) ipa->modem_netdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) unregister_netdev(netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) free_netdev(netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) out_set_state:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) atomic_set(&ipa->modem_state, IPA_MODEM_STATE_RUNNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) atomic_set(&ipa->modem_state, IPA_MODEM_STATE_STOPPED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) smp_mb__after_atomic();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /* Treat a "clean" modem stop the same as a crash */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static void ipa_modem_crashed(struct ipa *ipa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) struct device *dev = &ipa->pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) ipa_endpoint_modem_pause_all(ipa, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) ipa_endpoint_modem_hol_block_clear_all(ipa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) ipa_table_reset(ipa, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) ret = ipa_table_hash_flush(ipa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) dev_err(dev, "error %d flushing hash caches\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) ret = ipa_endpoint_modem_exception_reset_all(ipa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) dev_err(dev, "error %d resetting exception endpoint\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) ipa_endpoint_modem_pause_all(ipa, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) ret = ipa_modem_stop(ipa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) dev_err(dev, "error %d stopping modem\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) /* Now prepare for the next modem boot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) ret = ipa_mem_zero_modem(ipa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) dev_err(dev, "error %d zeroing modem memory regions\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) static int ipa_modem_notify(struct notifier_block *nb, unsigned long action,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) struct ipa *ipa = container_of(nb, struct ipa, nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) struct qcom_ssr_notify_data *notify_data = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) struct device *dev = &ipa->pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) switch (action) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) case QCOM_SSR_BEFORE_POWERUP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) dev_info(dev, "received modem starting event\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) ipa_smp2p_notify_reset(ipa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) case QCOM_SSR_AFTER_POWERUP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) dev_info(dev, "received modem running event\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) case QCOM_SSR_BEFORE_SHUTDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) dev_info(dev, "received modem %s event\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) notify_data->crashed ? "crashed" : "stopping");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (ipa->setup_complete)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) ipa_modem_crashed(ipa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) case QCOM_SSR_AFTER_SHUTDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) dev_info(dev, "received modem offline event\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) dev_err(dev, "received unrecognized event %lu\n", action);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return NOTIFY_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) int ipa_modem_init(struct ipa *ipa, bool modem_init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) return ipa_smp2p_init(ipa, modem_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) void ipa_modem_exit(struct ipa *ipa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) ipa_smp2p_exit(ipa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) int ipa_modem_config(struct ipa *ipa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) void *notifier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) ipa->nb.notifier_call = ipa_modem_notify;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) notifier = qcom_register_ssr_notifier("mpss", &ipa->nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (IS_ERR(notifier))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) return PTR_ERR(notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) ipa->notifier = notifier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) void ipa_modem_deconfig(struct ipa *ipa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) struct device *dev = &ipa->pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) ret = qcom_unregister_ssr_notifier(ipa->notifier, &ipa->nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) dev_err(dev, "error %d unregistering notifier", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) ipa->notifier = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) memset(&ipa->nb, 0, sizeof(ipa->nb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) int ipa_modem_setup(struct ipa *ipa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return ipa_qmi_setup(ipa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) void ipa_modem_teardown(struct ipa *ipa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) ipa_qmi_teardown(ipa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }