Feat: update quectel_QMI_WWAN from 1.2.2 to 1.2.9
This commit is contained in:
parent
cdad1e4075
commit
9e4386988d
@ -8,8 +8,8 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=qmi_wwan_q
|
||||
PKG_VERSION:=3.0
|
||||
PKG_RELEASE:=2
|
||||
PKG_VERSION:=1.2.9
|
||||
PKG_RELEASE:=1
|
||||
|
||||
include $(INCLUDE_DIR)/kernel.mk
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
@ -1,13 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Bjørn Mork <bjorn@mork.no>
|
||||
*
|
||||
* The probing code is heavily inspired by cdc_ether, which is:
|
||||
* Copyright (C) 2003-2005 by David Brownell
|
||||
* Copyright (C) 2006 by Ole Andre Vadla Ravnas (ActiveSync)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
Copyright (c) Bjørn Mork of author <bjorn@mork.no>
|
||||
|
||||
This program is free software; you can redistribute it and/ormodify it under the terms of the GNU General
|
||||
Public licenseas published byFree Software Foundation; either version 2theof the License,(at your option)
|
||||
any later version.O1
|
||||
This program isdistributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the
|
||||
implied warranty ofOr FITNESS FOR A PARTICULAR PURPOSE.MERCHANTABILITYSee theGNU General Public License
|
||||
for more details.
|
||||
You should have received a copy of the GNU General Public licensealong withthis program; if not, write to
|
||||
the Free SoftwareFoundation, Inc.r51 Franklin Street, Fifth Floor,Boston,MA 02110-1301,USA.
|
||||
|
||||
Based on version modification, the author is Quectel <fae-support@quectel.com>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
@ -62,8 +65,10 @@ static struct rmnet_nss_cb __read_mostly *nss_cb = NULL;
|
||||
#if defined(CONFIG_PINCTRL_IPQ807x) || defined(CONFIG_PINCTRL_IPQ5018)
|
||||
#ifdef CONFIG_RMNET_DATA
|
||||
#define CONFIG_QCA_NSS_DRV
|
||||
/* define at qsdk/qca/src/linux-4.4/net/rmnet_data/rmnet_data_main.c */
|
||||
/* define at qsdk/qca/src/linux-4.4/net/rmnet_data/rmnet_data_main.c */ //for spf11.x
|
||||
/* define at qsdk/qca/src/datarmnet/core/rmnet_config.c */ //for spf12.x
|
||||
/* set at qsdk/qca/src/data-kernel/drivers/rmnet-nss/rmnet_nss.c */
|
||||
/* need add DEPENDS:= kmod-rmnet-core in feeds/makefile */
|
||||
extern struct rmnet_nss_cb *rmnet_nss_callbacks __rcu __read_mostly;
|
||||
#endif
|
||||
#endif
|
||||
@ -91,7 +96,7 @@ extern struct rmnet_nss_cb *rmnet_nss_callbacks __rcu __read_mostly;
|
||||
* These devices may alternatively/additionally be configured using AT
|
||||
* commands on a serial interface
|
||||
*/
|
||||
#define VERSION_NUMBER "V1.2.2"
|
||||
#define VERSION_NUMBER "V1.2.9"
|
||||
#define QUECTEL_WWAN_VERSION "Quectel_Linux&Android_QMI_WWAN_Driver_"VERSION_NUMBER
|
||||
static const char driver_name[] = "qmi_wwan_q";
|
||||
|
||||
@ -115,6 +120,7 @@ static const u8 default_modem_addr[ETH_ALEN] = {0x02, 0x50, 0xf3};
|
||||
1 - QMAP (Aggregation protocol)
|
||||
X - QMAP (Multiplexing and Aggregation protocol)
|
||||
*/
|
||||
//#define CONFIG_CLEAR_HALT
|
||||
#define QUECTEL_WWAN_QMAP 4 //MAX is 7
|
||||
|
||||
#if defined(QUECTEL_WWAN_QMAP)
|
||||
@ -216,7 +222,7 @@ struct qmap_priv {
|
||||
struct timespec64 agg_time;
|
||||
struct hrtimer agg_hrtimer;
|
||||
struct work_struct agg_wq;
|
||||
|
||||
|
||||
#ifdef QUECTEL_BRIDGE_MODE
|
||||
uint bridge_mode;
|
||||
uint bridge_ipv4;
|
||||
@ -225,7 +231,7 @@ struct qmap_priv {
|
||||
unsigned char bridge_self_mac[ETH_ALEN];
|
||||
#endif
|
||||
#endif
|
||||
uint use_qca_nss;
|
||||
uint use_qca_nss;
|
||||
};
|
||||
|
||||
struct qmap_hdr {
|
||||
@ -319,10 +325,10 @@ static int bridge_arp_reply(struct net_device *net, struct sk_buff *skb, uint br
|
||||
reply->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
reply->pkt_type = PACKET_HOST;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)
|
||||
netif_rx_ni(reply);
|
||||
#else
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION( 5,18,0 ))
|
||||
netif_rx(reply);
|
||||
#else
|
||||
netif_rx_ni(reply);
|
||||
#endif
|
||||
}
|
||||
return 1;
|
||||
@ -357,14 +363,14 @@ static struct sk_buff *bridge_mode_tx_fixup(struct net_device *net, struct sk_bu
|
||||
bridge_mac[0], bridge_mac[1], bridge_mac[2], bridge_mac[3], bridge_mac[4], bridge_mac[5]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_BRIDGE_LAN
|
||||
//bridge Lan IP 192.168.0.0
|
||||
if (ehdr->h_proto == htons(ETH_P_IP) && (iph->daddr & 0xFFFF) == 0xA8C0)
|
||||
{
|
||||
struct sk_buff *reply = skb_copy(skb, GFP_ATOMIC);
|
||||
ehdr = eth_hdr(reply);
|
||||
|
||||
|
||||
memcpy(ehdr->h_source, default_modem_addr, ETH_ALEN);
|
||||
if(is_qmap_netdev(net))
|
||||
{
|
||||
@ -378,20 +384,16 @@ static struct sk_buff *bridge_mode_tx_fixup(struct net_device *net, struct sk_bu
|
||||
sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused;
|
||||
memcpy(ehdr->h_dest, pQmapDev->bridge_self_mac, ETH_ALEN);
|
||||
}
|
||||
|
||||
|
||||
//pr_info("%s br rx pkt addr: %02x:%02x:%02x:%02x:%02x:%02x -> %02x:%02x:%02x:%02x:%02x:%02x\n", netdev_name(net),
|
||||
// ehdr->h_source[0], ehdr->h_source[1], ehdr->h_source[2], ehdr->h_source[3], ehdr->h_source[4], ehdr->h_source[5],
|
||||
// ehdr->h_dest[0], ehdr->h_dest[1], ehdr->h_dest[2], ehdr->h_dest[3], ehdr->h_dest[4], ehdr->h_dest[5]);
|
||||
|
||||
|
||||
skb_reset_mac_header(reply);
|
||||
__skb_pull(reply, skb_network_offset(reply));
|
||||
reply->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
reply->pkt_type = PACKET_HOST;
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)
|
||||
netif_rx_ni(reply);
|
||||
#else
|
||||
netif_rx(reply);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
@ -407,7 +409,7 @@ static void bridge_mode_rx_fixup(sQmiWwanQmap *pQmapDev, struct net_device *net,
|
||||
uint bridge_mode = 0;
|
||||
unsigned char *bridge_mac;
|
||||
|
||||
if (pQmapDev->qmap_mode > 1 || pQmapDev->use_rmnet_usb == 1) {
|
||||
if (pQmapDev->qmap_mode > 1 || ((pQmapDev->use_rmnet_usb == 1) && !one_card_mode)) {
|
||||
struct qmap_priv *priv = netdev_priv(net);
|
||||
bridge_mode = priv->bridge_mode;
|
||||
bridge_mac = priv->bridge_mac;
|
||||
@ -510,7 +512,7 @@ static ssize_t link_state_store(struct device *dev, struct device_attribute *att
|
||||
}
|
||||
}
|
||||
|
||||
if (usbnetdev->net->flags & IFF_UP) {
|
||||
if (usbnetdev->net->flags & IFF_UP) {
|
||||
if (!pQmapDev->link_state) {
|
||||
netif_carrier_off(usbnetdev->net);
|
||||
}
|
||||
@ -683,7 +685,7 @@ static void qmap_wake_queue(sQmiWwanQmap *pQmapDev)
|
||||
|
||||
if (!pQmapDev || !pQmapDev->use_rmnet_usb)
|
||||
return;
|
||||
|
||||
|
||||
for (i = 0; i < pQmapDev->qmap_mode; i++) {
|
||||
struct net_device *qmap_net = pQmapDev->mpQmapNetDev[i];
|
||||
|
||||
@ -693,7 +695,7 @@ static void qmap_wake_queue(sQmiWwanQmap *pQmapDev)
|
||||
}
|
||||
}
|
||||
|
||||
static struct sk_buff * add_qhdr(struct sk_buff *skb, u8 mux_id) {
|
||||
static struct sk_buff * add_qhdr(struct sk_buff *skb, u8 mux_id, int *hdr_data, int ip_offset) {
|
||||
struct qmap_hdr *qhdr;
|
||||
int pad = 0;
|
||||
|
||||
@ -701,44 +703,55 @@ static struct sk_buff * add_qhdr(struct sk_buff *skb, u8 mux_id) {
|
||||
if (pad) {
|
||||
pad = 4 - pad;
|
||||
if (skb_tailroom(skb) < pad) {
|
||||
printk("skb_tailroom small!\n");
|
||||
//printk("skb_tailroom small!\n");
|
||||
pad = 0;
|
||||
}
|
||||
if (pad)
|
||||
__skb_put(skb, pad);
|
||||
}
|
||||
|
||||
qhdr = (struct qmap_hdr *)skb_push(skb, sizeof(struct qmap_hdr));
|
||||
|
||||
if (hdr_data) {
|
||||
qhdr = (struct qmap_hdr *)hdr_data;
|
||||
qhdr->pkt_len = cpu_to_be16(skb->len - ip_offset);
|
||||
}
|
||||
else {
|
||||
qhdr = (struct qmap_hdr *)skb_push(skb, sizeof(struct qmap_hdr));
|
||||
qhdr->pkt_len = cpu_to_be16(skb->len - sizeof(struct qmap_hdr));
|
||||
}
|
||||
qhdr->cd_rsvd_pad = pad;
|
||||
qhdr->mux_id = mux_id;
|
||||
qhdr->pkt_len = cpu_to_be16(skb->len - sizeof(struct qmap_hdr));
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
static struct sk_buff * add_qhdr_v5(struct sk_buff *skb, u8 mux_id) {
|
||||
static struct sk_buff * add_qhdr_v5(struct sk_buff *skb, u8 mux_id, int *hdr_data, int ip_offset) {
|
||||
struct rmnet_map_header *map_header;
|
||||
struct rmnet_map_v5_csum_header *ul_header;
|
||||
u32 padding, map_datalen;
|
||||
int pad = 0;
|
||||
|
||||
map_datalen = skb->len;
|
||||
padding = map_datalen%4;
|
||||
if (padding) {
|
||||
padding = 4 - padding;
|
||||
if (skb_tailroom(skb) < padding) {
|
||||
printk("skb_tailroom small!\n");
|
||||
padding = 0;
|
||||
pad = (skb->len - ip_offset) %4;
|
||||
if (pad) {
|
||||
pad = 4 - pad;
|
||||
if (skb_tailroom(skb) < pad) {
|
||||
//printk("skb_tailroom small!\n");
|
||||
pad = 0;
|
||||
}
|
||||
if (padding)
|
||||
__skb_put(skb, padding);
|
||||
if (pad)
|
||||
__skb_put(skb, pad);
|
||||
}
|
||||
|
||||
if (hdr_data) {
|
||||
map_header = (struct rmnet_map_header *)hdr_data;
|
||||
map_header->pkt_len = htons(skb->len - ip_offset);
|
||||
}
|
||||
else {
|
||||
map_header = (struct rmnet_map_header *)skb_push(skb, (sizeof(struct rmnet_map_header) + sizeof(struct rmnet_map_v5_csum_header)));
|
||||
map_header->pkt_len = htons(skb->len - (sizeof(struct rmnet_map_header) + sizeof(struct rmnet_map_v5_csum_header)));
|
||||
}
|
||||
|
||||
map_header = (struct rmnet_map_header *)skb_push(skb, (sizeof(struct rmnet_map_header) + sizeof(struct rmnet_map_v5_csum_header)));
|
||||
map_header->cd_bit = 0;
|
||||
map_header->next_hdr = 1;
|
||||
map_header->pad_len = padding;
|
||||
map_header->pad_len = pad;
|
||||
map_header->mux_id = mux_id;
|
||||
map_header->pkt_len = htons(map_datalen + padding);
|
||||
|
||||
ul_header = (struct rmnet_map_v5_csum_header *)(map_header + 1);
|
||||
memset(ul_header, 0, sizeof(*ul_header));
|
||||
@ -761,48 +774,38 @@ static void rmnet_vnd_update_rx_stats(struct net_device *net,
|
||||
struct pcpu_sw_netstats *stats64 = this_cpu_ptr(dev->stats64);
|
||||
|
||||
u64_stats_update_begin(&stats64->syncp);
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION( 6,0,0 ))
|
||||
stats64->rx_packets += rx_packets;
|
||||
stats64->rx_bytes += rx_bytes;
|
||||
#else
|
||||
u64_stats_add(&stats64->rx_packets, rx_packets);
|
||||
u64_stats_add(&stats64->rx_bytes, rx_bytes);
|
||||
u64_stats_add(&stats64->rx_packets, rx_packets);
|
||||
u64_stats_add(&stats64->rx_bytes, rx_bytes);
|
||||
#endif
|
||||
u64_stats_update_end(&stats64->syncp);
|
||||
#else
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)
|
||||
net->stats.rx_packets += rx_packets;
|
||||
net->stats.rx_bytes += rx_bytes;
|
||||
#else
|
||||
u64_stats_add(&net->stats.rx_packets, rx_packets);
|
||||
u64_stats_add(&net->stats.rx_bytes, rx_bytes);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static void rmnet_vnd_update_tx_stats(struct net_device *net,
|
||||
unsigned tx_packets, unsigned tx_bytes) {
|
||||
unsigned tx_packets, unsigned tx_bytes) {
|
||||
#if defined(MHI_NETDEV_STATUS64)
|
||||
struct qmap_priv *dev = netdev_priv(net);
|
||||
struct pcpu_sw_netstats *stats64 = this_cpu_ptr(dev->stats64);
|
||||
|
||||
u64_stats_update_begin(&stats64->syncp);
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION( 6,0,0 ))
|
||||
stats64->tx_packets += tx_packets;
|
||||
stats64->tx_bytes += tx_bytes;
|
||||
#else
|
||||
u64_stats_add(&stats64->tx_packets, tx_packets);
|
||||
u64_stats_add(&stats64->tx_bytes, tx_bytes);
|
||||
u64_stats_add(&stats64->tx_packets, tx_packets);
|
||||
u64_stats_add(&stats64->tx_bytes, tx_bytes);
|
||||
#endif
|
||||
u64_stats_update_end(&stats64->syncp);
|
||||
#else
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)
|
||||
net->stats.tx_packets += tx_packets;
|
||||
net->stats.tx_bytes += tx_bytes;
|
||||
#else
|
||||
u64_stats_add(&net->stats.tx_packets, tx_packets);
|
||||
u64_stats_add(&net->tx_bytes, tx_bytes);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -822,6 +825,7 @@ static struct rtnl_link_stats64 *_rmnet_vnd_get_stats64(struct net_device *net,
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
struct pcpu_sw_netstats *stats64;
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION( 6,1,0 ))
|
||||
u64 rx_packets, rx_bytes;
|
||||
u64 tx_packets, tx_bytes;
|
||||
|
||||
@ -829,25 +833,35 @@ static struct rtnl_link_stats64 *_rmnet_vnd_get_stats64(struct net_device *net,
|
||||
|
||||
do {
|
||||
start = u64_stats_fetch_begin_irq(&stats64->syncp);
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)
|
||||
rx_packets = stats64->rx_packets;
|
||||
rx_bytes = stats64->rx_bytes;
|
||||
tx_packets = stats64->tx_packets;
|
||||
tx_bytes = stats64->tx_bytes;
|
||||
#else
|
||||
rx_packets = u64_stats_read(&stats64->rx_packets);
|
||||
rx_bytes = u64_stats_read(&stats64->rx_bytes);
|
||||
tx_packets = u64_stats_read(&stats64->tx_packets);
|
||||
tx_bytes = u64_stats_read(&stats64->tx_bytes);
|
||||
#endif
|
||||
} while (u64_stats_fetch_retry_irq(&stats64->syncp, start));
|
||||
|
||||
|
||||
stats->rx_packets += rx_packets;
|
||||
stats->rx_bytes += rx_bytes;
|
||||
stats->tx_packets += tx_packets;
|
||||
stats->tx_bytes += tx_bytes;
|
||||
#else
|
||||
u64_stats_t rx_packets, rx_bytes;
|
||||
u64_stats_t tx_packets, tx_bytes;
|
||||
|
||||
stats64 = per_cpu_ptr(dev->stats64, cpu);
|
||||
|
||||
do {
|
||||
start = u64_stats_fetch_begin_irq(&stats64->syncp);
|
||||
rx_packets = stats64->rx_packets;
|
||||
rx_bytes = stats64->rx_bytes;
|
||||
tx_packets = stats64->tx_packets;
|
||||
tx_bytes = stats64->tx_bytes;
|
||||
} while (u64_stats_fetch_retry_irq(&stats64->syncp, start));
|
||||
|
||||
stats->rx_packets += u64_stats_read(&rx_packets);
|
||||
stats->rx_bytes += u64_stats_read(&rx_bytes);
|
||||
stats->tx_packets += u64_stats_read(&tx_packets);
|
||||
stats->tx_bytes += u64_stats_read(&tx_bytes);
|
||||
#endif
|
||||
}
|
||||
|
||||
return stats;
|
||||
@ -897,7 +911,7 @@ static void rmnet_usb_tx_skb_destructor(struct sk_buff *skb) {
|
||||
|
||||
if (pQmapDev && pQmapDev->use_rmnet_usb) {
|
||||
int i;
|
||||
|
||||
|
||||
for (i = 0; i < pQmapDev->qmap_mode; i++) {
|
||||
struct net_device *qmap_net = pQmapDev->mpQmapNetDev[i];
|
||||
|
||||
@ -967,7 +981,7 @@ static void rmnet_usb_tx_agg_work(struct work_struct *work)
|
||||
ktime_get_ts64(&priv->agg_time);
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->agg_lock, flags);
|
||||
|
||||
|
||||
if (skb) {
|
||||
int err;
|
||||
#if 0
|
||||
@ -998,7 +1012,7 @@ static long agg_bypass_time __read_mostly = 10000000L;
|
||||
module_param(agg_bypass_time, long, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(agg_bypass_time, "Skip agg when apart spaced more than this");
|
||||
|
||||
static int rmnet_usb_tx_agg(struct sk_buff *skb, struct qmap_priv *priv) {
|
||||
static int rmnet_usb_tx_agg(struct sk_buff *skb, struct qmap_priv *priv, int *hdr_data, int hdr_len, int ip_offset) {
|
||||
struct qmi_wwan_state *info = (void *)&priv->dev->data;
|
||||
sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused;
|
||||
struct tx_agg_ctx *ctx = &pQmapDev->tx_ctx;
|
||||
@ -1021,15 +1035,22 @@ static int rmnet_usb_tx_agg(struct sk_buff *skb, struct qmap_priv *priv) {
|
||||
rmnet_vnd_update_tx_stats(pNet, 1, skb->len);
|
||||
|
||||
if (ctx->ul_data_aggregation_max_datagrams == 1) {
|
||||
skb->protocol = htons(ETH_P_MAP);
|
||||
skb->dev = priv->real_dev;
|
||||
agg_skb = alloc_skb(skb->len + hdr_len, GFP_ATOMIC);
|
||||
if (agg_skb) {
|
||||
memcpy(skb_put(agg_skb, hdr_len), hdr_data, hdr_len);
|
||||
memcpy(skb_put(agg_skb, skb->len - ip_offset), skb->data + ip_offset, skb->len - ip_offset);
|
||||
agg_skb->protocol = htons(ETH_P_MAP);
|
||||
agg_skb->dev = priv->real_dev;
|
||||
#if 0
|
||||
if (!skb->destructor)
|
||||
skb->destructor = rmnet_usb_tx_skb_destructor;
|
||||
if (!agg_skb->destructor)
|
||||
agg_skb->destructor = rmnet_usb_tx_skb_destructor;
|
||||
#endif
|
||||
err = dev_queue_xmit(skb);
|
||||
if (err != NET_XMIT_SUCCESS)
|
||||
err = dev_queue_xmit(agg_skb);
|
||||
if (err != NET_XMIT_SUCCESS)
|
||||
pNet->stats.tx_errors++;
|
||||
}
|
||||
dev_kfree_skb_any(skb);
|
||||
skb = NULL;
|
||||
return NET_XMIT_SUCCESS;
|
||||
}
|
||||
|
||||
@ -1041,8 +1062,9 @@ new_packet:
|
||||
diff = timespec64_sub(now, priv->agg_time);
|
||||
|
||||
if (priv->agg_skb) {
|
||||
if ((priv->agg_skb->len + skb->len) < ctx->ul_data_aggregation_max_size) {
|
||||
memcpy(skb_put(priv->agg_skb, skb->len), skb->data, skb->len);
|
||||
if ((priv->agg_skb->len + skb->len + hdr_len) < ctx->ul_data_aggregation_max_size) {
|
||||
memcpy(skb_put(priv->agg_skb, hdr_len), hdr_data, hdr_len);
|
||||
memcpy(skb_put(priv->agg_skb, skb->len - ip_offset), skb->data + ip_offset, skb->len - ip_offset);
|
||||
priv->agg_count++;
|
||||
|
||||
if (diff.tv_sec > 0 || diff.tv_nsec > agg_time_limit) {
|
||||
@ -1052,14 +1074,14 @@ new_packet:
|
||||
ready2send = 1;
|
||||
}
|
||||
else if (xmit_more == 0) {
|
||||
struct rmnet_map_header *map_header = (struct rmnet_map_header *)skb->data;
|
||||
struct rmnet_map_header *map_header = (struct rmnet_map_header *)hdr_data;
|
||||
size_t offset = sizeof(struct rmnet_map_header);
|
||||
if (map_header->next_hdr)
|
||||
offset += sizeof(struct rmnet_map_v5_csum_header);
|
||||
|
||||
ready2send = rmnet_usb_tx_agg_skip(skb, offset);
|
||||
}
|
||||
|
||||
|
||||
dev_kfree_skb_any(skb);
|
||||
skb = NULL;
|
||||
}
|
||||
@ -1078,7 +1100,7 @@ new_packet:
|
||||
ready2send = 1;
|
||||
}
|
||||
else if (xmit_more == 0) {
|
||||
struct rmnet_map_header *map_header = (struct rmnet_map_header *)skb->data;
|
||||
struct rmnet_map_header *map_header = (struct rmnet_map_header *)hdr_data;
|
||||
size_t offset = sizeof(struct rmnet_map_header);
|
||||
if (map_header->next_hdr)
|
||||
offset += sizeof(struct rmnet_map_v5_csum_header);
|
||||
@ -1090,7 +1112,8 @@ new_packet:
|
||||
priv->agg_skb = alloc_skb(ctx->ul_data_aggregation_max_size, GFP_ATOMIC);
|
||||
if (priv->agg_skb) {
|
||||
skb_reset_network_header(priv->agg_skb); //protocol da1a is buggy, dev wwan0
|
||||
memcpy(skb_put(priv->agg_skb, skb->len), skb->data, skb->len);
|
||||
memcpy(skb_put(priv->agg_skb, hdr_len), hdr_data, hdr_len);
|
||||
memcpy(skb_put(priv->agg_skb, skb->len - ip_offset), skb->data + ip_offset, skb->len - ip_offset);
|
||||
priv->agg_count++;
|
||||
dev_kfree_skb_any(skb);
|
||||
skb = NULL;
|
||||
@ -1101,7 +1124,12 @@ new_packet:
|
||||
}
|
||||
|
||||
if (ready2send) {
|
||||
agg_skb = skb;
|
||||
agg_skb = alloc_skb(skb->len + hdr_len, GFP_ATOMIC);
|
||||
if (agg_skb) {
|
||||
memcpy(skb_put(agg_skb, hdr_len), hdr_data, hdr_len);
|
||||
memcpy(skb_put(agg_skb, skb->len - ip_offset), skb->data + ip_offset, skb->len - ip_offset);
|
||||
}
|
||||
dev_kfree_skb_any(skb);
|
||||
skb = NULL;
|
||||
}
|
||||
}
|
||||
@ -1142,6 +1170,9 @@ static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb,
|
||||
{
|
||||
int err;
|
||||
struct qmap_priv *priv = netdev_priv(pNet);
|
||||
int qmap_hdr[2];
|
||||
int hdr_len = 0;
|
||||
int ip_offset = 0;
|
||||
|
||||
if (netif_queue_stopped(priv->real_dev)) {
|
||||
netif_stop_queue(pNet);
|
||||
@ -1159,18 +1190,24 @@ static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb,
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
ip_offset = ETH_HLEN;
|
||||
#else
|
||||
if (skb_pull(skb, ETH_HLEN) == NULL) {
|
||||
dev_kfree_skb_any (skb);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
//printk("%s 2 skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len);
|
||||
|
||||
if (priv->qmap_version == 5) {
|
||||
add_qhdr(skb, priv->mux_id);
|
||||
add_qhdr(skb, priv->mux_id, qmap_hdr, ip_offset);
|
||||
hdr_len = 4;
|
||||
}
|
||||
else if (priv->qmap_version == 9) {
|
||||
add_qhdr_v5(skb, priv->mux_id);
|
||||
add_qhdr_v5(skb, priv->mux_id, qmap_hdr, ip_offset);
|
||||
hdr_len = 8;
|
||||
}
|
||||
else {
|
||||
dev_kfree_skb_any (skb);
|
||||
@ -1178,7 +1215,7 @@ static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb,
|
||||
}
|
||||
//printk("%s skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len);
|
||||
|
||||
err = rmnet_usb_tx_agg(skb, priv);
|
||||
err = rmnet_usb_tx_agg(skb, priv, qmap_hdr, hdr_len, ip_offset);
|
||||
|
||||
return err;
|
||||
}
|
||||
@ -1246,7 +1283,7 @@ static rx_handler_result_t qca_nss_rx_handler(struct sk_buff **pskb)
|
||||
|
||||
if (!skb)
|
||||
return RX_HANDLER_CONSUMED;
|
||||
|
||||
|
||||
//printk("%s skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len);
|
||||
|
||||
if (skb->pkt_type == PACKET_LOOPBACK)
|
||||
@ -1295,10 +1332,10 @@ static int qmap_register_device(sQmiWwanQmap * pDev, u8 offset_id)
|
||||
priv->dev = pDev->mpNetDev;
|
||||
priv->qmap_version = pDev->qmap_version;
|
||||
priv->mux_id = QUECTEL_QMAP_MUX_ID + offset_id;
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 17, 0)
|
||||
memcpy (qmap_net->dev_addr, real_dev->dev_addr, ETH_ALEN);
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,17,0)
|
||||
__dev_addr_set(qmap_net, real_dev->dev_addr, ETH_ALEN);
|
||||
#else
|
||||
eth_hw_addr_set (real_dev, qmap_net->dev_addr);
|
||||
memcpy (qmap_net->dev_addr, real_dev->dev_addr, ETH_ALEN);
|
||||
#endif
|
||||
|
||||
#ifdef QUECTEL_BRIDGE_MODE
|
||||
@ -1314,7 +1351,9 @@ static int qmap_register_device(sQmiWwanQmap * pDev, u8 offset_id)
|
||||
if (nss_cb && use_qca_nss) {
|
||||
rmnet_usb_rawip_setup(qmap_net);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PINCTRL_IPQ9574
|
||||
rmnet_usb_rawip_setup(qmap_net);
|
||||
#endif
|
||||
priv->agg_skb = NULL;
|
||||
priv->agg_count = 0;
|
||||
hrtimer_init(&priv->agg_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
@ -1350,7 +1389,7 @@ static int qmap_register_device(sQmiWwanQmap * pDev, u8 offset_id)
|
||||
netdev_info(qmap_net, "NSS context created\n");
|
||||
rtnl_lock();
|
||||
netdev_rx_handler_register(qmap_net, qca_nss_rx_handler, NULL);
|
||||
rtnl_unlock();
|
||||
rtnl_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1379,7 +1418,7 @@ static void qmap_unregister_device(sQmiWwanQmap * pDev, u8 offset_id) {
|
||||
pDev->mpQmapNetDev[offset_id] = NULL;
|
||||
netif_carrier_off( qmap_net );
|
||||
netif_stop_queue( qmap_net );
|
||||
|
||||
|
||||
hrtimer_cancel(&priv->agg_hrtimer);
|
||||
cancel_work_sync(&priv->agg_wq);
|
||||
spin_lock_irqsave(&priv->agg_lock, flags);
|
||||
@ -1421,6 +1460,8 @@ typedef struct {
|
||||
} BRMAC_SETTING;
|
||||
#endif
|
||||
|
||||
static int qma_setting_store(struct device *dev, QMAP_SETTING *qmap_settings, size_t size);
|
||||
|
||||
int qma_setting_store(struct device *dev, QMAP_SETTING *qmap_settings, size_t size) {
|
||||
struct net_device *netdev = to_net_dev(dev);
|
||||
struct usbnet * usbnetdev = netdev_priv( netdev );
|
||||
@ -1460,7 +1501,11 @@ static int qmap_ndo_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||
#ifdef CONFIG_BRIDGE_LAN
|
||||
BRMAC_SETTING brmac_settings = {0};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CLEAR_HALT
|
||||
uint clear_halt = 0;
|
||||
#endif
|
||||
|
||||
|
||||
switch (cmd) {
|
||||
case 0x89F1: //SIOCDEVPRIVATE
|
||||
rc = copy_from_user(&link_state, ifr->ifr_ifru.ifru_data, sizeof(link_state));
|
||||
@ -1493,7 +1538,7 @@ static int qmap_ndo_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||
rc = copy_to_user(ifr->ifr_ifru.ifru_data, &pQmapDev->rmnet_info, sizeof(pQmapDev->rmnet_info));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
#ifdef CONFIG_BRIDGE_LAN
|
||||
case 0x89F4: //SIOCDEVPRIVATE
|
||||
rc = copy_from_user(&brmac_settings, ifr->ifr_ifru.ifru_data, sizeof(brmac_settings));
|
||||
@ -1515,6 +1560,16 @@ static int qmap_ndo_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_CLEAR_HALT
|
||||
case 0x89F5: //SIOCDEVPRIVATE
|
||||
rc = copy_from_user(&clear_halt, ifr->ifr_ifru.ifru_data, sizeof(clear_halt));
|
||||
if (rc == 0 && clear_halt == 1) {
|
||||
usb_clear_halt(usbnetdev->udev,usbnetdev->in);
|
||||
usb_clear_halt(usbnetdev->udev,usbnetdev->out);
|
||||
pr_info("usb_clear_halt EPIN EPOUT\n");
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
@ -1657,9 +1712,9 @@ static struct sk_buff *qmap_qmi_wwan_tx_fixup(struct usbnet *dev, struct sk_buff
|
||||
|
||||
if (skb) {
|
||||
if(pQmapDev->qmap_version == 5)
|
||||
add_qhdr(skb, QUECTEL_QMAP_MUX_ID);
|
||||
add_qhdr(skb, QUECTEL_QMAP_MUX_ID, NULL, 0);
|
||||
else
|
||||
add_qhdr_v5(skb, QUECTEL_QMAP_MUX_ID);
|
||||
add_qhdr_v5(skb, QUECTEL_QMAP_MUX_ID, NULL, 0);
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
@ -1690,7 +1745,7 @@ static void qmap_packet_decode(sQmiWwanQmap *pQmapDev,
|
||||
while (skb_in->len > sizeof(struct qmap_hdr)) {
|
||||
struct rmnet_map_header *map_header = (struct rmnet_map_header *)skb_in->data;
|
||||
struct rmnet_map_v5_csum_header *ul_header = NULL;
|
||||
size_t hdr_size = sizeof(struct rmnet_map_header);
|
||||
size_t hdr_size = sizeof(struct rmnet_map_header);
|
||||
struct net_device *qmap_net;
|
||||
int pkt_len = ntohs(map_header->pkt_len);
|
||||
int skb_len;
|
||||
@ -1702,7 +1757,7 @@ static void qmap_packet_decode(sQmiWwanQmap *pQmapDev,
|
||||
ul_header = (struct rmnet_map_v5_csum_header *)(map_header + 1);
|
||||
hdr_size += sizeof(struct rmnet_map_v5_csum_header);
|
||||
}
|
||||
|
||||
|
||||
skb_len = pkt_len - (map_header->pad_len&0x3F);
|
||||
skb_len -= dl_minimum_padding;
|
||||
|
||||
@ -1717,7 +1772,7 @@ static void qmap_packet_decode(sQmiWwanQmap *pQmapDev,
|
||||
dev_info(dev, "drop qmap unknow mux_id %x\n", map_header->mux_id);
|
||||
goto skip_pkt;
|
||||
}
|
||||
|
||||
|
||||
if (skb_len > qmap_net->mtu) {
|
||||
dev_info(dev, "drop skb_len=%x larger than mtu=%d\n", skb_len, qmap_net->mtu);
|
||||
goto error_pkt;
|
||||
@ -1760,7 +1815,7 @@ static void qmap_packet_decode(sQmiWwanQmap *pQmapDev,
|
||||
dev_info(dev, "unknow skb->protocol %02x\n", skb_in->data[hdr_size]);
|
||||
goto error_pkt;
|
||||
}
|
||||
|
||||
|
||||
qmap_skb = netdev_alloc_skb(qmap_net, skb_len);
|
||||
if (qmap_skb) {
|
||||
skb_put(qmap_skb, skb_len);
|
||||
@ -1815,7 +1870,7 @@ static int qmap_qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
|
||||
sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused;
|
||||
struct sk_buff *qmap_skb;
|
||||
struct sk_buff_head skb_chain;
|
||||
|
||||
|
||||
if (pQmapDev->qmap_mode == 0)
|
||||
return qmi_wwan_rx_fixup(dev, skb_in);
|
||||
|
||||
@ -1862,7 +1917,7 @@ static void (*_usbnet_get_stats64)(struct net_device *net, struct rtnl_link_stat
|
||||
static void qmi_wwan_get_stats64(struct net_device *net, struct rtnl_link_stats64 *stats) {
|
||||
if (_usbnet_get_stats64) ////c8b5d129ee293bcf972e7279ac996bb8a138505c
|
||||
return _usbnet_get_stats64(net, stats);
|
||||
|
||||
|
||||
netdev_stats_to_stats64(stats, &net->stats);
|
||||
}
|
||||
#else
|
||||
@ -1871,7 +1926,7 @@ static struct rtnl_link_stats64 * (*_usbnet_get_stats64)(struct net_device *net,
|
||||
static struct rtnl_link_stats64 * qmi_wwan_get_stats64(struct net_device *net, struct rtnl_link_stats64 *stats) {
|
||||
if (_usbnet_get_stats64)
|
||||
return _usbnet_get_stats64(net, stats);
|
||||
|
||||
|
||||
netdev_stats_to_stats64(stats, &net->stats);
|
||||
return stats;
|
||||
}
|
||||
@ -1896,7 +1951,7 @@ static int qmi_wwan_open (struct net_device *net) {
|
||||
}
|
||||
|
||||
static netdev_tx_t qmi_wwan_start_xmit (struct sk_buff *skb,
|
||||
struct net_device *net)
|
||||
struct net_device *net)
|
||||
{
|
||||
struct usbnet * usbnetdev = netdev_priv( net );
|
||||
struct qmi_wwan_state *info = (void *)&usbnetdev->data;
|
||||
@ -1907,7 +1962,7 @@ static netdev_tx_t qmi_wwan_start_xmit (struct sk_buff *skb,
|
||||
|
||||
if (netif_queue_stopped(net) && pQmapDev && pQmapDev->use_rmnet_usb) {
|
||||
int i;
|
||||
|
||||
|
||||
for (i = 0; i < pQmapDev->qmap_mode; i++) {
|
||||
struct net_device *qmap_net = pQmapDev->mpQmapNetDev[i];
|
||||
if (qmap_net) {
|
||||
@ -1949,7 +2004,7 @@ static void ql_net_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *i
|
||||
{
|
||||
/* Inherit standard device info */
|
||||
usbnet_get_drvinfo(net, info);
|
||||
/* strlcpy() is deprecated in kernel 6.8.0+, using strscpy instead */
|
||||
/* strlcpy() is deprecated in kernel 6.8.0+, using strscpy instead */
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6,8,0))
|
||||
strlcpy(info->driver, driver_name, sizeof(info->driver));
|
||||
strlcpy(info->version, VERSION_NUMBER, sizeof(info->version));
|
||||
@ -2021,7 +2076,7 @@ static int qmi_wwan_register_subdriver(struct usbnet *dev)
|
||||
atomic_set(&info->pmcount, 0);
|
||||
|
||||
/* register subdriver */
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION( 5,12,0 )) //cac6fb015f719104e60b1c68c15ca5b734f57b9c
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION( 5,14,0 )) //cac6fb015f719104e60b1c68c15ca5b734f57b9c
|
||||
subdriver = usb_cdc_wdm_register(info->control, &dev->status->desc,
|
||||
4096, WWAN_PORT_QMI, &qmi_wwan_cdc_wdm_manage_power);
|
||||
#else
|
||||
@ -2072,17 +2127,17 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
|
||||
|
||||
/* make MAC addr easily distinguishable from an IP header */
|
||||
if (possibly_iphdr(dev->net->dev_addr)) {
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,17,0)
|
||||
u8 temp_addr[ETH_ALEN];
|
||||
memcpy(temp_addr, dev->net->dev_addr, ETH_ALEN);
|
||||
temp_addr[0] |= 0x02; /* set local assignment bit */
|
||||
temp_addr[0] &= 0xbf; /* clear "IP" bit */
|
||||
__dev_addr_set(dev->net, temp_addr, ETH_ALEN);
|
||||
#else
|
||||
dev->net->dev_addr[0] |= 0x02; /* set local assignment bit */
|
||||
dev->net->dev_addr[0] &= 0xbf; /* clear "IP" bit */
|
||||
#else
|
||||
u8 addr = dev->net->dev_addr[0];
|
||||
|
||||
addr |= 0x02; /* set local assignment bit */
|
||||
addr &= 0xbf; /* clear "IP" bit */
|
||||
dev_addr_mod(dev->net, 0, &addr, 1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (!_usbnet_get_stats64)
|
||||
_usbnet_get_stats64 = dev->net->netdev_ops->ndo_get_stats64;
|
||||
dev->net->netdev_ops = &qmi_wwan_netdev_ops;
|
||||
@ -2115,6 +2170,9 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
|
||||
NULL, 0, 100);
|
||||
}
|
||||
|
||||
usb_clear_halt(dev->udev,dev->in);
|
||||
usb_clear_halt(dev->udev,dev->out);
|
||||
|
||||
//to advoid module report mtu 1460, but rx 1500 bytes IP packets, and cause the customer's system crash
|
||||
//next setting can make usbnet.c:usbnet_change_mtu() do not modify rx_urb_size according to hard mtu
|
||||
dev->rx_urb_size = ETH_DATA_LEN + ETH_HLEN + 6;
|
||||
@ -2146,12 +2204,13 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
|
||||
int qmap_version = (dev->driver_info->data>>8)&0xFF;
|
||||
int qmap_size = (dev->driver_info->data)&0xFF;
|
||||
int idProduct = le16_to_cpu(dev->udev->descriptor.idProduct);
|
||||
int lte_a = (idProduct == 0x0306 || idProduct == 0x030B || idProduct == 0x0512 || idProduct == 0x0620 || idProduct == 0x0800 || idProduct == 0x0801);
|
||||
int lte_a = (idProduct == 0x0306 || idProduct == 0x030B || idProduct == 0x0512 || idProduct == 0x0620 ||
|
||||
idProduct == 0x0800 || idProduct == 0x0801 || idProduct == 0x0122 || idProduct == 0x0316);
|
||||
|
||||
if (qmap_size > 4096 || dev->udev->speed >= USB_SPEED_SUPER) { //if meet this requirements, must be LTE-A or 5G
|
||||
lte_a = 1;
|
||||
}
|
||||
|
||||
|
||||
pQmapDev->qmap_mode = qmap_mode;
|
||||
if (lte_a && pQmapDev->qmap_mode == 0) {
|
||||
pQmapDev->qmap_mode = 1; //force use QMAP
|
||||
@ -2168,17 +2227,19 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
|
||||
|
||||
if (pQmapDev->qmap_mode > 1)
|
||||
pQmapDev->use_rmnet_usb = 1;
|
||||
else if (idProduct == 0x0800 || idProduct == 0x0801)
|
||||
else if (idProduct == 0x0800 || idProduct == 0x0801 || idProduct == 0x0122)
|
||||
pQmapDev->use_rmnet_usb = 1; //benefit for ul data agg
|
||||
#ifdef QMI_NETDEV_ONE_CARD_MODE
|
||||
if(pQmapDev->use_rmnet_usb == 1 && pQmapDev->qmap_mode == 1)
|
||||
one_card_mode = 1;
|
||||
pQmapDev->rmnet_info.mux_id[0] = QUECTEL_QMAP_MUX_ID;
|
||||
#endif
|
||||
#endif
|
||||
pQmapDev->rmnet_info.size = sizeof(RMNET_INFO);
|
||||
pQmapDev->rmnet_info.rx_urb_size = pQmapDev->qmap_size;
|
||||
pQmapDev->rmnet_info.ep_type = 2; //DATA_EP_TYPE_HSUSB
|
||||
pQmapDev->rmnet_info.iface_id = 4;
|
||||
pQmapDev->rmnet_info.iface_id = 4;//Interface ID
|
||||
if(idProduct == 0x0316)
|
||||
pQmapDev->rmnet_info.iface_id = 3;// SDX35 Interface ID
|
||||
pQmapDev->rmnet_info.qmap_mode = pQmapDev->qmap_mode;
|
||||
pQmapDev->rmnet_info.qmap_version = pQmapDev->qmap_version;
|
||||
pQmapDev->rmnet_info.dl_minimum_padding = 0;
|
||||
@ -2188,7 +2249,7 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
|
||||
pQmapDev->tx_ctx.ul_data_aggregation_max_size = 1500;
|
||||
#endif
|
||||
|
||||
if (pQmapDev->use_rmnet_usb && !one_card_mode) {
|
||||
if (pQmapDev->use_rmnet_usb && !one_card_mode) {
|
||||
pQmapDev->driver_info = rmnet_usb_info;
|
||||
pQmapDev->driver_info.data = dev->driver_info->data;
|
||||
dev->driver_info = &pQmapDev->driver_info;
|
||||
@ -2356,7 +2417,7 @@ static int rmnet_usb_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2417,7 +2478,7 @@ static const struct driver_info qmi_wwan_info = {
|
||||
};
|
||||
|
||||
#define qmi_wwan_raw_ip_info \
|
||||
.description = "WWAN/QMI device", \
|
||||
.description = "WWAN/QMI Raw IP device", \
|
||||
.flags = FLAG_WWAN | FLAG_RX_ASSEMBLE | FLAG_NOARP | FLAG_SEND_ZLP, \
|
||||
.bind = qmi_wwan_bind, \
|
||||
.unbind = qmi_wwan_unbind, \
|
||||
@ -2465,6 +2526,7 @@ static const struct usb_device_id products[] = {
|
||||
{ QMI_FIXED_INTF(0x05C6, 0x9215, 4) }, /* Quectel EC20 (MDM9215) */
|
||||
{ QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0125, 4, mdm9x07) }, /* Quectel EC20 (MDM9X07)/EC25/EG25 */
|
||||
{ QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0121, 4, mdm9x07) }, /* Quectel EC21 */
|
||||
{ QMI_FIXED_RAWIP_INTF(0x2C7C, 0x030E, 4, mdm9x07) }, /* Quectel EM05G */
|
||||
{ QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0191, 4, mdm9x07) }, /* Quectel EG91 */
|
||||
{ QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0195, 4, mdm9x07) }, /* Quectel EG95 */
|
||||
{ QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0700, 3, mdm9x07) }, /* Quectel BG95 (at+qcfgext="usbnet","rmnet") */
|
||||
@ -2474,8 +2536,10 @@ static const struct usb_device_id products[] = {
|
||||
{ QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0296, 4, mdm9x07) }, /* Quectel BG96 */
|
||||
{ QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0435, 4, mdm9x07) }, /* Quectel AG35 */
|
||||
{ QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0620, 4, mdm9x40) }, /* Quectel EG20 */
|
||||
{ QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0316, 3, mdm9x40) }, /* Quectel RG255 */
|
||||
{ QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0800, 4, sdx55) }, /* Quectel RG500 */
|
||||
{ QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0801, 4, sdx55) }, /* Quectel RG520 */
|
||||
{ QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0122, 4, sdx55) }, /* Quectel RG650 */
|
||||
{ } /* END */
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, products);
|
||||
@ -2582,11 +2646,11 @@ static void qmap_qmi_wwan_disconnect(struct usb_interface *intf)
|
||||
}
|
||||
|
||||
tasklet_kill(&pQmapDev->txq);
|
||||
|
||||
|
||||
usbnet_disconnect(intf);
|
||||
/* struct usbnet *dev had free by usbnet_disconnect()->free_netdev().
|
||||
so we should access info. */
|
||||
//info->unused = 0;
|
||||
//info->unused = 0;
|
||||
kfree(pQmapDev);
|
||||
}
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user