fbdb5f9164
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
157 lines
5.1 KiB
Diff
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
|
|
|