1 | // SPDX-License-Identifier: GPL-2.0 |
2 | |
3 | /* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. |
4 | * Copyright (C) 2018-2022 Linaro Ltd. |
5 | */ |
6 | |
7 | #include <linux/errno.h> |
8 | #include <linux/if_arp.h> |
9 | #include <linux/netdevice.h> |
10 | #include <linux/skbuff.h> |
11 | #include <linux/if_rmnet.h> |
12 | #include <linux/etherdevice.h> |
13 | #include <net/pkt_sched.h> |
14 | #include <linux/pm_runtime.h> |
15 | #include <linux/remoteproc/qcom_rproc.h> |
16 | |
17 | #include "ipa.h" |
18 | #include "ipa_data.h" |
19 | #include "ipa_endpoint.h" |
20 | #include "ipa_table.h" |
21 | #include "ipa_mem.h" |
22 | #include "ipa_modem.h" |
23 | #include "ipa_smp2p.h" |
24 | #include "ipa_qmi.h" |
25 | #include "ipa_uc.h" |
26 | #include "ipa_power.h" |
27 | |
28 | #define IPA_NETDEV_NAME "rmnet_ipa%d" |
29 | #define IPA_NETDEV_TAILROOM 0 /* for padding by mux layer */ |
30 | #define IPA_NETDEV_TIMEOUT 10 /* seconds */ |
31 | |
32 | enum ipa_modem_state { |
33 | IPA_MODEM_STATE_STOPPED = 0, |
34 | IPA_MODEM_STATE_STARTING, |
35 | IPA_MODEM_STATE_RUNNING, |
36 | IPA_MODEM_STATE_STOPPING, |
37 | }; |
38 | |
39 | /** |
40 | * struct ipa_priv - IPA network device private data |
41 | * @ipa: IPA pointer |
42 | * @tx: Transmit endpoint pointer |
43 | * @rx: Receive endpoint pointer |
44 | * @work: Work structure used to wake the modem netdev TX queue |
45 | */ |
46 | struct ipa_priv { |
47 | struct ipa *ipa; |
48 | struct ipa_endpoint *tx; |
49 | struct ipa_endpoint *rx; |
50 | struct work_struct work; |
51 | }; |
52 | |
53 | /** ipa_open() - Opens the modem network interface */ |
54 | static int ipa_open(struct net_device *netdev) |
55 | { |
56 | struct ipa_priv *priv = netdev_priv(dev: netdev); |
57 | struct ipa *ipa = priv->ipa; |
58 | struct device *dev; |
59 | int ret; |
60 | |
61 | dev = ipa->dev; |
62 | ret = pm_runtime_get_sync(dev); |
63 | if (ret < 0) |
64 | goto err_power_put; |
65 | |
66 | ret = ipa_endpoint_enable_one(endpoint: priv->tx); |
67 | if (ret) |
68 | goto err_power_put; |
69 | |
70 | ret = ipa_endpoint_enable_one(endpoint: priv->rx); |
71 | if (ret) |
72 | goto err_disable_tx; |
73 | |
74 | netif_start_queue(dev: netdev); |
75 | |
76 | pm_runtime_mark_last_busy(dev); |
77 | (void)pm_runtime_put_autosuspend(dev); |
78 | |
79 | return 0; |
80 | |
81 | err_disable_tx: |
82 | ipa_endpoint_disable_one(endpoint: priv->tx); |
83 | err_power_put: |
84 | pm_runtime_put_noidle(dev); |
85 | |
86 | return ret; |
87 | } |
88 | |
89 | /** ipa_stop() - Stops the modem network interface. */ |
90 | static int ipa_stop(struct net_device *netdev) |
91 | { |
92 | struct ipa_priv *priv = netdev_priv(dev: netdev); |
93 | struct ipa *ipa = priv->ipa; |
94 | struct device *dev; |
95 | int ret; |
96 | |
97 | dev = ipa->dev; |
98 | ret = pm_runtime_get_sync(dev); |
99 | if (ret < 0) |
100 | goto out_power_put; |
101 | |
102 | netif_stop_queue(dev: netdev); |
103 | |
104 | ipa_endpoint_disable_one(endpoint: priv->rx); |
105 | ipa_endpoint_disable_one(endpoint: priv->tx); |
106 | out_power_put: |
107 | pm_runtime_mark_last_busy(dev); |
108 | (void)pm_runtime_put_autosuspend(dev); |
109 | |
110 | return 0; |
111 | } |
112 | |
113 | /** ipa_start_xmit() - Transmit an skb |
114 | * @skb: Socket buffer to be transmitted |
115 | * @netdev: Network device |
116 | * |
117 | * Return: NETDEV_TX_OK if successful (or dropped), NETDEV_TX_BUSY otherwise |
118 | |
119 | * Normally NETDEV_TX_OK indicates the buffer was successfully transmitted. |
120 | * If the buffer has an unexpected protocol or its size is out of range it |
121 | * is quietly dropped, returning NETDEV_TX_OK. NETDEV_TX_BUSY indicates |
122 | * the buffer cannot be sent at this time and should retried later. |
123 | */ |
124 | static netdev_tx_t |
125 | ipa_start_xmit(struct sk_buff *skb, struct net_device *netdev) |
126 | { |
127 | struct net_device_stats *stats = &netdev->stats; |
128 | struct ipa_priv *priv = netdev_priv(dev: netdev); |
129 | struct ipa_endpoint *endpoint; |
130 | struct ipa *ipa = priv->ipa; |
131 | u32 skb_len = skb->len; |
132 | struct device *dev; |
133 | int ret; |
134 | |
135 | if (!skb_len) |
136 | goto err_drop_skb; |
137 | |
138 | endpoint = ipa->name_map[IPA_ENDPOINT_AP_MODEM_TX]; |
139 | if (endpoint->config.qmap && skb->protocol != htons(ETH_P_MAP)) |
140 | goto err_drop_skb; |
141 | |
142 | /* The hardware must be powered for us to transmit, so if we're not |
143 | * ready we want the network stack to stop queueing until power is |
144 | * ACTIVE. Once runtime resume has completed, we inform the network |
145 | * stack it's OK to try transmitting again. |
146 | * |
147 | * We learn from pm_runtime_get() whether the hardware is powered. |
148 | * If it was not, powering up is either started or already underway. |
149 | * And in that case we want to disable queueing, expecting it to be |
150 | * re-enabled once power is ACTIVE. But runtime PM and network |
151 | * transmit run concurrently, and if we're not careful the requests |
152 | * to stop and start queueing could occur in the wrong order. |
153 | * |
154 | * For that reason we *always* stop queueing here, *before* the call |
155 | * to pm_runtime_get(). If we determine here that power is ACTIVE, |
156 | * we restart queueing before transmitting the SKB. Otherwise |
157 | * queueing will eventually be enabled after resume completes. |
158 | */ |
159 | netif_stop_queue(dev: netdev); |
160 | |
161 | dev = ipa->dev; |
162 | ret = pm_runtime_get(dev); |
163 | if (ret < 1) { |
164 | /* If a resume won't happen, just drop the packet */ |
165 | if (ret < 0 && ret != -EINPROGRESS) { |
166 | netif_wake_queue(dev: netdev); |
167 | pm_runtime_put_noidle(dev); |
168 | goto err_drop_skb; |
169 | } |
170 | |
171 | pm_runtime_put_noidle(dev); |
172 | |
173 | return NETDEV_TX_BUSY; |
174 | } |
175 | |
176 | netif_wake_queue(dev: netdev); |
177 | |
178 | ret = ipa_endpoint_skb_tx(endpoint, skb); |
179 | |
180 | pm_runtime_mark_last_busy(dev); |
181 | (void)pm_runtime_put_autosuspend(dev); |
182 | |
183 | if (ret) { |
184 | if (ret != -E2BIG) |
185 | return NETDEV_TX_BUSY; |
186 | goto err_drop_skb; |
187 | } |
188 | |
189 | stats->tx_packets++; |
190 | stats->tx_bytes += skb_len; |
191 | |
192 | return NETDEV_TX_OK; |
193 | |
194 | err_drop_skb: |
195 | dev_kfree_skb_any(skb); |
196 | stats->tx_dropped++; |
197 | |
198 | return NETDEV_TX_OK; |
199 | } |
200 | |
201 | void ipa_modem_skb_rx(struct net_device *netdev, struct sk_buff *skb) |
202 | { |
203 | struct net_device_stats *stats = &netdev->stats; |
204 | |
205 | if (skb) { |
206 | skb->dev = netdev; |
207 | skb->protocol = htons(ETH_P_MAP); |
208 | stats->rx_packets++; |
209 | stats->rx_bytes += skb->len; |
210 | |
211 | (void)netif_receive_skb(skb); |
212 | } else { |
213 | stats->rx_dropped++; |
214 | } |
215 | } |
216 | |
217 | static const struct net_device_ops ipa_modem_ops = { |
218 | .ndo_open = ipa_open, |
219 | .ndo_stop = ipa_stop, |
220 | .ndo_start_xmit = ipa_start_xmit, |
221 | }; |
222 | |
223 | /** ipa_modem_netdev_setup() - netdev setup function for the modem */ |
224 | static void ipa_modem_netdev_setup(struct net_device *netdev) |
225 | { |
226 | netdev->netdev_ops = &ipa_modem_ops; |
227 | |
228 | netdev->header_ops = NULL; |
229 | netdev->type = ARPHRD_RAWIP; |
230 | netdev->hard_header_len = 0; |
231 | netdev->min_header_len = ETH_HLEN; |
232 | netdev->min_mtu = ETH_MIN_MTU; |
233 | netdev->max_mtu = IPA_MTU; |
234 | netdev->mtu = netdev->max_mtu; |
235 | netdev->addr_len = 0; |
236 | netdev->tx_queue_len = DEFAULT_TX_QUEUE_LEN; |
237 | netdev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST); |
238 | netdev->priv_flags |= IFF_TX_SKB_SHARING; |
239 | eth_broadcast_addr(addr: netdev->broadcast); |
240 | |
241 | /* The endpoint is configured for QMAP */ |
242 | netdev->needed_headroom = sizeof(struct rmnet_map_header); |
243 | netdev->needed_tailroom = IPA_NETDEV_TAILROOM; |
244 | netdev->watchdog_timeo = IPA_NETDEV_TIMEOUT * HZ; |
245 | netdev->hw_features = NETIF_F_SG; |
246 | } |
247 | |
248 | /** ipa_modem_suspend() - suspend callback |
249 | * @netdev: Network device |
250 | * |
251 | * Suspend the modem's endpoints. |
252 | */ |
253 | void ipa_modem_suspend(struct net_device *netdev) |
254 | { |
255 | struct ipa_priv *priv; |
256 | |
257 | if (!(netdev->flags & IFF_UP)) |
258 | return; |
259 | |
260 | priv = netdev_priv(dev: netdev); |
261 | ipa_endpoint_suspend_one(endpoint: priv->rx); |
262 | ipa_endpoint_suspend_one(endpoint: priv->tx); |
263 | } |
264 | |
265 | /** |
266 | * ipa_modem_wake_queue_work() - enable modem netdev queue |
267 | * @work: Work structure |
268 | * |
269 | * Re-enable transmit on the modem network device. This is called |
270 | * in (power management) work queue context, scheduled when resuming |
271 | * the modem. We can't enable the queue directly in ipa_modem_resume() |
272 | * because transmits restart the instant the queue is awakened; but the |
273 | * device power state won't be ACTIVE until *after* ipa_modem_resume() |
274 | * returns. |
275 | */ |
276 | static void ipa_modem_wake_queue_work(struct work_struct *work) |
277 | { |
278 | struct ipa_priv *priv = container_of(work, struct ipa_priv, work); |
279 | |
280 | netif_wake_queue(dev: priv->tx->netdev); |
281 | } |
282 | |
283 | /** ipa_modem_resume() - resume callback for runtime_pm |
284 | * @dev: pointer to device |
285 | * |
286 | * Resume the modem's endpoints. |
287 | */ |
288 | void ipa_modem_resume(struct net_device *netdev) |
289 | { |
290 | struct ipa_priv *priv; |
291 | |
292 | if (!(netdev->flags & IFF_UP)) |
293 | return; |
294 | |
295 | priv = netdev_priv(dev: netdev); |
296 | ipa_endpoint_resume_one(endpoint: priv->tx); |
297 | ipa_endpoint_resume_one(endpoint: priv->rx); |
298 | |
299 | /* Arrange for the TX queue to be restarted */ |
300 | (void)queue_pm_work(work: &priv->work); |
301 | } |
302 | |
303 | int ipa_modem_start(struct ipa *ipa) |
304 | { |
305 | enum ipa_modem_state state; |
306 | struct net_device *netdev; |
307 | struct ipa_priv *priv; |
308 | int ret; |
309 | |
310 | /* Only attempt to start the modem if it's stopped */ |
311 | state = atomic_cmpxchg(v: &ipa->modem_state, old: IPA_MODEM_STATE_STOPPED, |
312 | new: IPA_MODEM_STATE_STARTING); |
313 | |
314 | /* Silently ignore attempts when running, or when changing state */ |
315 | if (state != IPA_MODEM_STATE_STOPPED) |
316 | return 0; |
317 | |
318 | netdev = alloc_netdev(sizeof(struct ipa_priv), IPA_NETDEV_NAME, |
319 | NET_NAME_UNKNOWN, ipa_modem_netdev_setup); |
320 | if (!netdev) { |
321 | ret = -ENOMEM; |
322 | goto out_set_state; |
323 | } |
324 | |
325 | SET_NETDEV_DEV(netdev, ipa->dev); |
326 | priv = netdev_priv(dev: netdev); |
327 | priv->ipa = ipa; |
328 | priv->tx = ipa->name_map[IPA_ENDPOINT_AP_MODEM_TX]; |
329 | priv->rx = ipa->name_map[IPA_ENDPOINT_AP_MODEM_RX]; |
330 | INIT_WORK(&priv->work, ipa_modem_wake_queue_work); |
331 | |
332 | priv->tx->netdev = netdev; |
333 | priv->rx->netdev = netdev; |
334 | |
335 | ipa->modem_netdev = netdev; |
336 | |
337 | ret = register_netdev(dev: netdev); |
338 | if (ret) { |
339 | ipa->modem_netdev = NULL; |
340 | priv->rx->netdev = NULL; |
341 | priv->tx->netdev = NULL; |
342 | |
343 | free_netdev(dev: netdev); |
344 | } |
345 | |
346 | out_set_state: |
347 | if (ret) |
348 | atomic_set(v: &ipa->modem_state, i: IPA_MODEM_STATE_STOPPED); |
349 | else |
350 | atomic_set(v: &ipa->modem_state, i: IPA_MODEM_STATE_RUNNING); |
351 | smp_mb__after_atomic(); |
352 | |
353 | return ret; |
354 | } |
355 | |
356 | int ipa_modem_stop(struct ipa *ipa) |
357 | { |
358 | struct net_device *netdev = ipa->modem_netdev; |
359 | enum ipa_modem_state state; |
360 | |
361 | /* Only attempt to stop the modem if it's running */ |
362 | state = atomic_cmpxchg(v: &ipa->modem_state, old: IPA_MODEM_STATE_RUNNING, |
363 | new: IPA_MODEM_STATE_STOPPING); |
364 | |
365 | /* Silently ignore attempts when already stopped */ |
366 | if (state == IPA_MODEM_STATE_STOPPED) |
367 | return 0; |
368 | |
369 | /* If we're somewhere between stopped and starting, we're busy */ |
370 | if (state != IPA_MODEM_STATE_RUNNING) |
371 | return -EBUSY; |
372 | |
373 | /* Clean up the netdev and endpoints if it was started */ |
374 | if (netdev) { |
375 | struct ipa_priv *priv = netdev_priv(dev: netdev); |
376 | |
377 | cancel_work_sync(work: &priv->work); |
378 | /* If it was opened, stop it first */ |
379 | if (netdev->flags & IFF_UP) |
380 | (void)ipa_stop(netdev); |
381 | unregister_netdev(dev: netdev); |
382 | |
383 | ipa->modem_netdev = NULL; |
384 | priv->rx->netdev = NULL; |
385 | priv->tx->netdev = NULL; |
386 | |
387 | free_netdev(dev: netdev); |
388 | } |
389 | |
390 | atomic_set(v: &ipa->modem_state, i: IPA_MODEM_STATE_STOPPED); |
391 | smp_mb__after_atomic(); |
392 | |
393 | return 0; |
394 | } |
395 | |
396 | /* Treat a "clean" modem stop the same as a crash */ |
397 | static void ipa_modem_crashed(struct ipa *ipa) |
398 | { |
399 | struct device *dev = ipa->dev; |
400 | int ret; |
401 | |
402 | /* Prevent the modem from triggering a call to ipa_setup() */ |
403 | ipa_smp2p_irq_disable_setup(ipa); |
404 | |
405 | ret = pm_runtime_get_sync(dev); |
406 | if (ret < 0) { |
407 | dev_err(dev, "error %d getting power to handle crash\n" , ret); |
408 | goto out_power_put; |
409 | } |
410 | |
411 | ipa_endpoint_modem_pause_all(ipa, enable: true); |
412 | |
413 | ipa_endpoint_modem_hol_block_clear_all(ipa); |
414 | |
415 | ipa_table_reset(ipa, modem: true); |
416 | |
417 | ret = ipa_table_hash_flush(ipa); |
418 | if (ret) |
419 | dev_err(dev, "error %d flushing hash caches\n" , ret); |
420 | |
421 | ret = ipa_endpoint_modem_exception_reset_all(ipa); |
422 | if (ret) |
423 | dev_err(dev, "error %d resetting exception endpoint\n" , ret); |
424 | |
425 | ipa_endpoint_modem_pause_all(ipa, enable: false); |
426 | |
427 | ret = ipa_modem_stop(ipa); |
428 | if (ret) |
429 | dev_err(dev, "error %d stopping modem\n" , ret); |
430 | |
431 | /* Now prepare for the next modem boot */ |
432 | ret = ipa_mem_zero_modem(ipa); |
433 | if (ret) |
434 | dev_err(dev, "error %d zeroing modem memory regions\n" , ret); |
435 | |
436 | out_power_put: |
437 | pm_runtime_mark_last_busy(dev); |
438 | (void)pm_runtime_put_autosuspend(dev); |
439 | } |
440 | |
441 | static int ipa_modem_notify(struct notifier_block *nb, unsigned long action, |
442 | void *data) |
443 | { |
444 | struct ipa *ipa = container_of(nb, struct ipa, nb); |
445 | struct qcom_ssr_notify_data *notify_data = data; |
446 | struct device *dev = ipa->dev; |
447 | |
448 | switch (action) { |
449 | case QCOM_SSR_BEFORE_POWERUP: |
450 | dev_info(dev, "received modem starting event\n" ); |
451 | ipa_uc_power(ipa); |
452 | ipa_smp2p_notify_reset(ipa); |
453 | break; |
454 | |
455 | case QCOM_SSR_AFTER_POWERUP: |
456 | dev_info(dev, "received modem running event\n" ); |
457 | break; |
458 | |
459 | case QCOM_SSR_BEFORE_SHUTDOWN: |
460 | dev_info(dev, "received modem %s event\n" , |
461 | notify_data->crashed ? "crashed" : "stopping" ); |
462 | if (ipa->setup_complete) |
463 | ipa_modem_crashed(ipa); |
464 | break; |
465 | |
466 | case QCOM_SSR_AFTER_SHUTDOWN: |
467 | dev_info(dev, "received modem offline event\n" ); |
468 | break; |
469 | |
470 | default: |
471 | dev_err(dev, "received unrecognized event %lu\n" , action); |
472 | break; |
473 | } |
474 | |
475 | return NOTIFY_OK; |
476 | } |
477 | |
478 | int ipa_modem_config(struct ipa *ipa) |
479 | { |
480 | void *notifier; |
481 | |
482 | ipa->nb.notifier_call = ipa_modem_notify; |
483 | |
484 | notifier = qcom_register_ssr_notifier(name: "mpss" , nb: &ipa->nb); |
485 | if (IS_ERR(ptr: notifier)) |
486 | return PTR_ERR(ptr: notifier); |
487 | |
488 | ipa->notifier = notifier; |
489 | |
490 | return 0; |
491 | } |
492 | |
493 | void ipa_modem_deconfig(struct ipa *ipa) |
494 | { |
495 | struct device *dev = ipa->dev; |
496 | int ret; |
497 | |
498 | ret = qcom_unregister_ssr_notifier(notify: ipa->notifier, nb: &ipa->nb); |
499 | if (ret) |
500 | dev_err(dev, "error %d unregistering notifier" , ret); |
501 | |
502 | ipa->notifier = NULL; |
503 | memset(&ipa->nb, 0, sizeof(ipa->nb)); |
504 | } |
505 | |