From 1cde3fcb0f1b0b9a6bdc96a1843db4d6cbbc3539 Mon Sep 17 00:00:00 2001 From: Minecrell 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 #include #include +#include #include #include #include @@ -19,9 +20,11 @@ #include #include #include +#include #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