Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) }