1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2020-21 Intel Corporation. 4 */ 5 6 #include <linux/etherdevice.h> 7 #include <linux/if_arp.h> 8 #include <linux/if_link.h> 9 #include <linux/rtnetlink.h> 10 #include <linux/wwan.h> 11 #include <net/pkt_sched.h> 12 13 #include "iosm_ipc_chnl_cfg.h" 14 #include "iosm_ipc_imem_ops.h" 15 #include "iosm_ipc_wwan.h" 16 17 #define IOSM_IP_TYPE_MASK 0xF0 18 #define IOSM_IP_TYPE_IPV4 0x40 19 #define IOSM_IP_TYPE_IPV6 0x60 20 21 #define IOSM_IF_ID_PAYLOAD 2 22 23 /** 24 * struct iosm_netdev_priv - netdev WWAN driver specific private data 25 * @ipc_wwan: Pointer to iosm_wwan struct 26 * @netdev: Pointer to network interface device structure 27 * @if_id: Interface id for device. 28 * @ch_id: IPC channel number for which interface device is created. 29 */ 30 struct iosm_netdev_priv { 31 struct iosm_wwan *ipc_wwan; 32 struct net_device *netdev; 33 int if_id; 34 int ch_id; 35 }; 36 37 /** 38 * struct iosm_wwan - This structure contains information about WWAN root device 39 * and interface to the IPC layer. 40 * @ipc_imem: Pointer to imem data-struct 41 * @sub_netlist: List of active netdevs 42 * @dev: Pointer device structure 43 */ 44 struct iosm_wwan { 45 struct iosm_imem *ipc_imem; 46 struct iosm_netdev_priv __rcu *sub_netlist[IP_MUX_SESSION_END + 1]; 47 struct device *dev; 48 }; 49 50 /* Bring-up the wwan net link */ 51 static int ipc_wwan_link_open(struct net_device *netdev) 52 { 53 struct iosm_netdev_priv *priv = wwan_netdev_drvpriv(netdev); 54 struct iosm_wwan *ipc_wwan = priv->ipc_wwan; 55 int if_id = priv->if_id; 56 57 if (if_id < IP_MUX_SESSION_START || 58 if_id >= ARRAY_SIZE(ipc_wwan->sub_netlist)) 59 return -EINVAL; 60 61 /* get channel id */ 62 priv->ch_id = ipc_imem_sys_wwan_open(ipc_wwan->ipc_imem, if_id); 63 64 if (priv->ch_id < 0) { 65 dev_err(ipc_wwan->dev, 66 "cannot connect wwan0 & id %d to the IPC mem layer", 67 if_id); 68 return -ENODEV; 69 } 70 71 /* enable tx path, DL data may follow */ 72 netif_start_queue(netdev); 73 74 dev_dbg(ipc_wwan->dev, "Channel id %d allocated to if_id %d", 75 priv->ch_id, priv->if_id); 76 77 return 0; 78 } 79 80 /* Bring-down the wwan net link */ 81 static int ipc_wwan_link_stop(struct net_device *netdev) 82 { 83 struct iosm_netdev_priv *priv = wwan_netdev_drvpriv(netdev); 84 85 netif_stop_queue(netdev); 86 87 ipc_imem_sys_wwan_close(priv->ipc_wwan->ipc_imem, priv->if_id, 88 priv->ch_id); 89 priv->ch_id = -1; 90 91 return 0; 92 } 93 94 /* Transmit a packet */ 95 static netdev_tx_t ipc_wwan_link_transmit(struct sk_buff *skb, 96 struct net_device *netdev) 97 { 98 struct iosm_netdev_priv *priv = wwan_netdev_drvpriv(netdev); 99 struct iosm_wwan *ipc_wwan = priv->ipc_wwan; 100 unsigned int len = skb->len; 101 int if_id = priv->if_id; 102 int ret; 103 104 /* Interface IDs from 1 to 8 are for IP data 105 * & from 257 to 261 are for non-IP data 106 */ 107 if (if_id < IP_MUX_SESSION_START || 108 if_id >= ARRAY_SIZE(ipc_wwan->sub_netlist)) 109 return -EINVAL; 110 111 /* Send the SKB to device for transmission */ 112 ret = ipc_imem_sys_wwan_transmit(ipc_wwan->ipc_imem, 113 if_id, priv->ch_id, skb); 114 115 /* Return code of zero is success */ 116 if (ret == 0) { 117 netdev->stats.tx_packets++; 118 netdev->stats.tx_bytes += len; 119 ret = NETDEV_TX_OK; 120 } else if (ret == -EBUSY) { 121 ret = NETDEV_TX_BUSY; 122 dev_err(ipc_wwan->dev, "unable to push packets"); 123 } else { 124 goto exit; 125 } 126 127 return ret; 128 129 exit: 130 /* Log any skb drop */ 131 if (if_id) 132 dev_dbg(ipc_wwan->dev, "skb dropped. IF_ID: %d, ret: %d", if_id, 133 ret); 134 135 dev_kfree_skb_any(skb); 136 netdev->stats.tx_dropped++; 137 return NETDEV_TX_OK; 138 } 139 140 /* Ops structure for wwan net link */ 141 static const struct net_device_ops ipc_inm_ops = { 142 .ndo_open = ipc_wwan_link_open, 143 .ndo_stop = ipc_wwan_link_stop, 144 .ndo_start_xmit = ipc_wwan_link_transmit, 145 }; 146 147 /* Setup function for creating new net link */ 148 static void ipc_wwan_setup(struct net_device *iosm_dev) 149 { 150 iosm_dev->header_ops = NULL; 151 iosm_dev->hard_header_len = 0; 152 iosm_dev->tx_queue_len = DEFAULT_TX_QUEUE_LEN; 153 154 iosm_dev->type = ARPHRD_NONE; 155 iosm_dev->mtu = ETH_DATA_LEN; 156 iosm_dev->min_mtu = ETH_MIN_MTU; 157 iosm_dev->max_mtu = ETH_MAX_MTU; 158 159 iosm_dev->flags = IFF_POINTOPOINT | IFF_NOARP; 160 iosm_dev->needs_free_netdev = true; 161 162 iosm_dev->netdev_ops = &ipc_inm_ops; 163 } 164 165 /* Create new wwan net link */ 166 static int ipc_wwan_newlink(void *ctxt, struct net_device *dev, 167 u32 if_id, struct netlink_ext_ack *extack) 168 { 169 struct iosm_wwan *ipc_wwan = ctxt; 170 struct iosm_netdev_priv *priv; 171 int err; 172 173 if (if_id < IP_MUX_SESSION_START || 174 if_id >= ARRAY_SIZE(ipc_wwan->sub_netlist)) 175 return -EINVAL; 176 177 priv = wwan_netdev_drvpriv(dev); 178 priv->if_id = if_id; 179 priv->netdev = dev; 180 priv->ipc_wwan = ipc_wwan; 181 182 if (rcu_access_pointer(ipc_wwan->sub_netlist[if_id])) 183 return -EBUSY; 184 185 err = register_netdevice(dev); 186 if (err) 187 return err; 188 189 rcu_assign_pointer(ipc_wwan->sub_netlist[if_id], priv); 190 netif_device_attach(dev); 191 192 return 0; 193 } 194 195 static void ipc_wwan_dellink(void *ctxt, struct net_device *dev, 196 struct list_head *head) 197 { 198 struct iosm_netdev_priv *priv = wwan_netdev_drvpriv(dev); 199 struct iosm_wwan *ipc_wwan = ctxt; 200 int if_id = priv->if_id; 201 202 if (WARN_ON(if_id < IP_MUX_SESSION_START || 203 if_id >= ARRAY_SIZE(ipc_wwan->sub_netlist))) 204 return; 205 206 if (WARN_ON(rcu_access_pointer(ipc_wwan->sub_netlist[if_id]) != priv)) 207 return; 208 209 RCU_INIT_POINTER(ipc_wwan->sub_netlist[if_id], NULL); 210 /* unregistering includes synchronize_net() */ 211 unregister_netdevice_queue(dev, head); 212 } 213 214 static const struct wwan_ops iosm_wwan_ops = { 215 .priv_size = sizeof(struct iosm_netdev_priv), 216 .setup = ipc_wwan_setup, 217 .newlink = ipc_wwan_newlink, 218 .dellink = ipc_wwan_dellink, 219 }; 220 221 int ipc_wwan_receive(struct iosm_wwan *ipc_wwan, struct sk_buff *skb_arg, 222 bool dss, int if_id) 223 { 224 struct sk_buff *skb = skb_arg; 225 struct net_device_stats *stats; 226 struct iosm_netdev_priv *priv; 227 int ret; 228 229 if ((skb->data[0] & IOSM_IP_TYPE_MASK) == IOSM_IP_TYPE_IPV4) 230 skb->protocol = htons(ETH_P_IP); 231 else if ((skb->data[0] & IOSM_IP_TYPE_MASK) == 232 IOSM_IP_TYPE_IPV6) 233 skb->protocol = htons(ETH_P_IPV6); 234 235 skb->pkt_type = PACKET_HOST; 236 237 if (if_id < IP_MUX_SESSION_START || 238 if_id > IP_MUX_SESSION_END) { 239 ret = -EINVAL; 240 goto free; 241 } 242 243 rcu_read_lock(); 244 priv = rcu_dereference(ipc_wwan->sub_netlist[if_id]); 245 if (!priv) { 246 ret = -EINVAL; 247 goto unlock; 248 } 249 skb->dev = priv->netdev; 250 stats = &priv->netdev->stats; 251 stats->rx_packets++; 252 stats->rx_bytes += skb->len; 253 254 ret = netif_rx(skb); 255 skb = NULL; 256 unlock: 257 rcu_read_unlock(); 258 free: 259 dev_kfree_skb(skb); 260 return ret; 261 } 262 263 void ipc_wwan_tx_flowctrl(struct iosm_wwan *ipc_wwan, int if_id, bool on) 264 { 265 struct net_device *netdev; 266 struct iosm_netdev_priv *priv; 267 bool is_tx_blk; 268 269 rcu_read_lock(); 270 priv = rcu_dereference(ipc_wwan->sub_netlist[if_id]); 271 if (!priv) { 272 rcu_read_unlock(); 273 return; 274 } 275 276 netdev = priv->netdev; 277 278 is_tx_blk = netif_queue_stopped(netdev); 279 280 if (on) 281 dev_dbg(ipc_wwan->dev, "session id[%d]: flowctrl enable", 282 if_id); 283 284 if (on && !is_tx_blk) 285 netif_stop_queue(netdev); 286 else if (!on && is_tx_blk) 287 netif_wake_queue(netdev); 288 rcu_read_unlock(); 289 } 290 291 struct iosm_wwan *ipc_wwan_init(struct iosm_imem *ipc_imem, struct device *dev) 292 { 293 struct iosm_wwan *ipc_wwan; 294 295 ipc_wwan = kzalloc(sizeof(*ipc_wwan), GFP_KERNEL); 296 if (!ipc_wwan) 297 return NULL; 298 299 ipc_wwan->dev = dev; 300 ipc_wwan->ipc_imem = ipc_imem; 301 302 /* WWAN core will create a netdev for the default IP MUX channel */ 303 if (wwan_register_ops(ipc_wwan->dev, &iosm_wwan_ops, ipc_wwan, 304 IP_MUX_SESSION_DEFAULT)) { 305 kfree(ipc_wwan); 306 return NULL; 307 } 308 309 return ipc_wwan; 310 } 311 312 void ipc_wwan_deinit(struct iosm_wwan *ipc_wwan) 313 { 314 /* This call will remove all child netdev(s) */ 315 wwan_unregister_ops(ipc_wwan->dev); 316 317 kfree(ipc_wwan); 318 } 319