pmaports/main/linux-postmarketos-qcom-msm8974/0001-net-qualcomm-bam-dmux-Switch-to-Raw-IP-mode.patch
Minecrell fbdb5f9164
main/linux-postmarketos-qcom-msm8974: add BAM-DMUX patches (MR 2053)
These are required to make it work with the latest ModemManager patches,
especially the patch that switches BAM-DMUX to Raw-IP mode.

[ci:skip-build]: already built successfully in CI
2021-03-22 21:43:26 +01:00

157 lines
5.1 KiB
Diff

From 1cde3fcb0f1b0b9a6bdc96a1843db4d6cbbc3539 Mon Sep 17 00:00:00 2001
From: Minecrell <minecrell@minecrell.net>
Date: Thu, 15 Oct 2020 11:31:16 +0200
Subject: [PATCH 1/6] net: qualcomm: bam-dmux: Switch to Raw IP mode
---
drivers/net/ethernet/qualcomm/bam-dmux.c | 92 +++++++++++-------------
1 file changed, 43 insertions(+), 49 deletions(-)
diff --git a/drivers/net/ethernet/qualcomm/bam-dmux.c b/drivers/net/ethernet/qualcomm/bam-dmux.c
index c1346452c9d4..75b3f3932b4f 100644
--- a/drivers/net/ethernet/qualcomm/bam-dmux.c
+++ b/drivers/net/ethernet/qualcomm/bam-dmux.c
@@ -9,6 +9,7 @@
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/netdevice.h>
@@ -19,9 +20,11 @@
#include <linux/soc/qcom/smem_state.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
+#include <net/pkt_sched.h>
#define BAM_DMUX_BUFFER_SIZE SZ_2K
#define BAM_DMUX_MAX_DATA_SIZE (BAM_DMUX_BUFFER_SIZE - sizeof(struct bam_dmux_hdr))
+#define BAM_DMUX_DEFAULT_MTU 2000
#define BAM_DMUX_NUM_SKB 32
#define BAM_DMUX_AUTOSUSPEND_DELAY 1000
@@ -442,25 +445,27 @@ static void bam_dmux_tx_wakeup_work(struct work_struct *work)
pm_runtime_put_autosuspend(dmux->dev);
}
-static const struct net_device_ops bam_dmux_ops_ether = {
- .ndo_open = bam_dmux_netdev_open,
- .ndo_stop = bam_dmux_netdev_stop,
- .ndo_start_xmit = bam_dmux_netdev_start_xmit,
- .ndo_set_mac_address = eth_mac_addr,
- .ndo_validate_addr = eth_validate_addr,
+static const struct net_device_ops bam_dmux_ops = {
+ .ndo_open = bam_dmux_netdev_open,
+ .ndo_stop = bam_dmux_netdev_stop,
+ .ndo_start_xmit = bam_dmux_netdev_start_xmit,
};
-static void bam_dmux_netdev_setup(struct net_device *netdev)
+static void bam_dmux_netdev_setup(struct net_device *dev)
{
- /* Hardcode ethernet mode for now */
- ether_setup(netdev);
- random_ether_addr(netdev->dev_addr);
- netdev->netdev_ops = &bam_dmux_ops_ether;
+ dev->netdev_ops = &bam_dmux_ops;
- netdev->needed_headroom = sizeof(struct bam_dmux_hdr);
- netdev->needed_tailroom = sizeof(u32); /* word-aligned */
- netdev->max_mtu = 2000;
- netdev->mtu = netdev->max_mtu;
+ dev->type = ARPHRD_RAWIP;
+ dev->mtu = BAM_DMUX_DEFAULT_MTU;
+ dev->max_mtu = BAM_DMUX_MAX_DATA_SIZE;
+ dev->needed_headroom = sizeof(struct bam_dmux_hdr);
+ dev->needed_tailroom = sizeof(u32); /* word-aligned */
+
+ /* This perm addr will be used as interface identifier by IPv6 */
+ dev->addr_assign_type = NET_ADDR_RANDOM;
+ eth_random_addr(dev->perm_addr);
+
+ dev->tx_queue_len = DEFAULT_TX_QUEUE_LEN;
}
static void bam_dmux_register_netdev_work(struct work_struct *work)
@@ -523,7 +528,7 @@ static bool bam_dmux_skb_dma_submit_rx(struct bam_dmux_skb_dma *skb_dma)
static bool bam_dmux_skb_dma_queue_rx(struct bam_dmux_skb_dma *skb_dma, gfp_t gfp)
{
- skb_dma->skb = __netdev_alloc_skb_ip_align(NULL, BAM_DMUX_BUFFER_SIZE, gfp);
+ skb_dma->skb = __netdev_alloc_skb(NULL, BAM_DMUX_BUFFER_SIZE, gfp);
if (!skb_dma->skb)
return false;
skb_put(skb_dma->skb, BAM_DMUX_BUFFER_SIZE);
@@ -532,38 +537,6 @@ static bool bam_dmux_skb_dma_queue_rx(struct bam_dmux_skb_dma *skb_dma, gfp_t gf
bam_dmux_skb_dma_submit_rx(skb_dma);
}
-/* FIXME: For some reason the modem send raw-ip packets even in ethernet mode.
- * The qmi_wwan driver mentions a similar problem due to a "firmware bug",
- * and uses code similar to the one below to generate an ethernet header
- * in case of such weird packets.
- */
-static __be16 bam_dmux_eth_type_trans(struct sk_buff *skb, struct net_device *dev)
-{
- __be16 protocol;
-
- /* Determine L3 protocol */
- switch (skb->data[0] & 0xf0) {
- case 0x40:
- protocol = htons(ETH_P_IP);
- break;
- case 0x60:
- protocol = htons(ETH_P_IPV6);
- break;
- default:
- /* Seems to be valid */
- return eth_type_trans(skb, dev);
- }
-
- /* Generate a dummy ethernet header */
- skb_push(skb, ETH_HLEN);
- skb_reset_mac_header(skb);
- eth_hdr(skb)->h_proto = protocol;
- eth_zero_addr(eth_hdr(skb)->h_source);
- memcpy(eth_hdr(skb)->h_dest, dev->dev_addr, ETH_ALEN);
-
- return eth_type_trans(skb, dev);
-}
-
static bool bam_dmux_cmd_data(struct bam_dmux_skb_dma *skb_dma)
{
struct bam_dmux *dmux = skb_dma->dmux;
@@ -587,7 +560,28 @@ static bool bam_dmux_cmd_data(struct bam_dmux_skb_dma *skb_dma)
skb_trim(skb, hdr->len);
skb->dev = netdev;
- skb->protocol = bam_dmux_eth_type_trans(skb, netdev);
+
+ /* There are several different configurations possible for the modem.
+ * - Ethernet / Raw-IP mode
+ * - Additional "QMI" QoS header
+ * - QMAP/rmnet MAP header (another muxing layer)
+ *
+ * Ethernet mode seems to be broken, Ethernet headers are only sent for
+ * DHCP replies, all other packets are Raw-IP. Therefore, only Raw-IP
+ * or QMAP mode are supported in this driver.
+ */
+ switch (skb->data[0] & 0xf0) {
+ case 0x40:
+ skb->protocol = htons(ETH_P_IP);
+ break;
+ case 0x60:
+ skb->protocol = htons(ETH_P_IPV6);
+ break;
+ default:
+ skb->protocol = htons(ETH_P_MAP);
+ break;
+ }
+
netif_rx_ni(skb);
if (bam_dmux_skb_dma_queue_rx(skb_dma, GFP_ATOMIC))
--
2.30.1