From: Greg Kroah-Hartman Date: Thu, 15 Jun 2017 09:13:44 +0000 (+0200) Subject: 4.9-stable patches X-Git-Tag: v4.9.33~23 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=64759c2740ccc74e5b4731d703bf964ec9e6c467;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: i2c-piix4-fix-request_region-size.patch i2c-piix4-request-the-smbus-semaphore-inside-the-mutex.patch ibmvnic-call-napi_disable-instead-of-napi_enable-in-failure-path.patch ibmvnic-initialize-completion-variables-before-starting-work.patch net-fix-proc-net-arp-for-ax.25.patch net-hns-fix-the-device-being-used-for-dma-mapping-during-tx.patch net-mkiss-fix-panic.patch powerpc-powernv-properly-set-host-ipi-on-ipis.patch sierra_net-add-support-for-ipv6-and-dual-stack-link-sense-indications.patch sierra_net-skip-validating-irrelevant-fields-for-idle-lsis.patch --- diff --git a/queue-4.9/i2c-piix4-fix-request_region-size.patch b/queue-4.9/i2c-piix4-fix-request_region-size.patch new file mode 100644 index 00000000000..5074bd8d8a7 --- /dev/null +++ b/queue-4.9/i2c-piix4-fix-request_region-size.patch @@ -0,0 +1,34 @@ +From foo@baz Thu Jun 15 11:12:23 CEST 2017 +From: Ricardo Ribalda +Date: Tue, 23 May 2017 21:53:45 -0400 +Subject: i2c: piix4: Fix request_region size + +From: Ricardo Ribalda + + +[ Upstream commit f43128c75202f29ee71aa83e6c320a911137c189 ] + +Since '701dc207bf55 ("i2c: piix4: Avoid race conditions with IMC")' we +are using the SMBSLVCNT register at offset 0x8. We need to request it. + +Fixes: 701dc207bf55 ("i2c: piix4: Avoid race conditions with IMC") +Signed-off-by: Ricardo Ribalda Delgado +Signed-off-by: Jean Delvare +Signed-off-by: Wolfram Sang +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i2c/busses/i2c-piix4.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/i2c/busses/i2c-piix4.c ++++ b/drivers/i2c/busses/i2c-piix4.c +@@ -58,7 +58,7 @@ + #define SMBSLVDAT (0xC + piix4_smba) + + /* count for request_region */ +-#define SMBIOSIZE 8 ++#define SMBIOSIZE 9 + + /* PCI Address Constants */ + #define SMBBA 0x090 diff --git a/queue-4.9/i2c-piix4-request-the-smbus-semaphore-inside-the-mutex.patch b/queue-4.9/i2c-piix4-request-the-smbus-semaphore-inside-the-mutex.patch new file mode 100644 index 00000000000..c5fda90a2dc --- /dev/null +++ b/queue-4.9/i2c-piix4-request-the-smbus-semaphore-inside-the-mutex.patch @@ -0,0 +1,63 @@ +From foo@baz Thu Jun 15 11:12:23 CEST 2017 +From: Ricardo Ribalda +Date: Tue, 23 May 2017 21:53:44 -0400 +Subject: i2c: piix4: Request the SMBUS semaphore inside the mutex + +From: Ricardo Ribalda + + +[ Upstream commit bbb27fc33d44e7b8d96369810654df4ee1837566 ] + +SMBSLVCNT must be protected with the piix4_mutex_sb800 in order to avoid +multiple buses accessing to the semaphore at the same time. + +Fixes: 701dc207bf55 ("i2c: piix4: Avoid race conditions with IMC") +Reported-by: Jean Delvare +Signed-off-by: Ricardo Ribalda Delgado +Signed-off-by: Jean Delvare +Signed-off-by: Wolfram Sang +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i2c/busses/i2c-piix4.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +--- a/drivers/i2c/busses/i2c-piix4.c ++++ b/drivers/i2c/busses/i2c-piix4.c +@@ -592,6 +592,8 @@ static s32 piix4_access_sb800(struct i2c + u8 port; + int retval; + ++ mutex_lock(&piix4_mutex_sb800); ++ + /* Request the SMBUS semaphore, avoid conflicts with the IMC */ + smbslvcnt = inb_p(SMBSLVCNT); + do { +@@ -605,10 +607,10 @@ static s32 piix4_access_sb800(struct i2c + usleep_range(1000, 2000); + } while (--retries); + /* SMBus is still owned by the IMC, we give up */ +- if (!retries) ++ if (!retries) { ++ mutex_unlock(&piix4_mutex_sb800); + return -EBUSY; +- +- mutex_lock(&piix4_mutex_sb800); ++ } + + outb_p(piix4_port_sel_sb800, SB800_PIIX4_SMB_IDX); + smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1); +@@ -623,11 +625,11 @@ static s32 piix4_access_sb800(struct i2c + + outb_p(smba_en_lo, SB800_PIIX4_SMB_IDX + 1); + +- mutex_unlock(&piix4_mutex_sb800); +- + /* Release the semaphore */ + outb_p(smbslvcnt | 0x20, SMBSLVCNT); + ++ mutex_unlock(&piix4_mutex_sb800); ++ + return retval; + } + diff --git a/queue-4.9/ibmvnic-call-napi_disable-instead-of-napi_enable-in-failure-path.patch b/queue-4.9/ibmvnic-call-napi_disable-instead-of-napi_enable-in-failure-path.patch new file mode 100644 index 00000000000..9649097215b --- /dev/null +++ b/queue-4.9/ibmvnic-call-napi_disable-instead-of-napi_enable-in-failure-path.patch @@ -0,0 +1,34 @@ +From foo@baz Thu Jun 15 11:12:23 CEST 2017 +From: Nathan Fontenot +Date: Tue, 23 May 2017 21:53:38 -0400 +Subject: ibmvnic: Call napi_disable instead of napi_enable in failure path + +From: Nathan Fontenot + + +[ Upstream commit e722af6391949e8851310441bb0cec157d25611d ] + +The failure path in ibmvnic_open() mistakenly makes a second call +to napi_enable instead of calling napi_disable. This can result +in a BUG_ON for any queues that were enabled in the previous call +to napi_enable. + +Signed-off-by: Nathan Fontenot +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/ibm/ibmvnic.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/ibm/ibmvnic.c ++++ b/drivers/net/ethernet/ibm/ibmvnic.c +@@ -505,7 +505,7 @@ rx_pool_alloc_failed: + adapter->rx_pool = NULL; + rx_pool_arr_alloc_failed: + for (i = 0; i < adapter->req_rx_queues; i++) +- napi_enable(&adapter->napi[i]); ++ napi_disable(&adapter->napi[i]); + alloc_napi_failed: + return -ENOMEM; + } diff --git a/queue-4.9/ibmvnic-initialize-completion-variables-before-starting-work.patch b/queue-4.9/ibmvnic-initialize-completion-variables-before-starting-work.patch new file mode 100644 index 00000000000..e8bfc477d77 --- /dev/null +++ b/queue-4.9/ibmvnic-initialize-completion-variables-before-starting-work.patch @@ -0,0 +1,114 @@ +From foo@baz Thu Jun 15 11:12:23 CEST 2017 +From: Nathan Fontenot +Date: Tue, 23 May 2017 21:53:39 -0400 +Subject: ibmvnic: Initialize completion variables before starting work + +From: Nathan Fontenot + + +[ Upstream commit db5d0b597bc27bbddf40f2f8359a73be4eb77104 ] + +Initialize condition variables prior to invoking any work that can +mark them complete. This resolves a race in the ibmvnic driver where +the driver faults trying to complete an uninitialized condition +variable. + +Signed-off-by: Nathan Fontenot +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/ibm/ibmvnic.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +--- a/drivers/net/ethernet/ibm/ibmvnic.c ++++ b/drivers/net/ethernet/ibm/ibmvnic.c +@@ -189,9 +189,10 @@ static int alloc_long_term_buff(struct i + } + ltb->map_id = adapter->map_id; + adapter->map_id++; ++ ++ init_completion(&adapter->fw_done); + send_request_map(adapter, ltb->addr, + ltb->size, ltb->map_id); +- init_completion(&adapter->fw_done); + wait_for_completion(&adapter->fw_done); + return 0; + } +@@ -1133,10 +1134,10 @@ static void ibmvnic_get_ethtool_stats(st + crq.request_statistics.ioba = cpu_to_be32(adapter->stats_token); + crq.request_statistics.len = + cpu_to_be32(sizeof(struct ibmvnic_statistics)); +- ibmvnic_send_crq(adapter, &crq); + + /* Wait for data to be written */ + init_completion(&adapter->stats_done); ++ ibmvnic_send_crq(adapter, &crq); + wait_for_completion(&adapter->stats_done); + + for (i = 0; i < ARRAY_SIZE(ibmvnic_stats); i++) +@@ -2809,9 +2810,9 @@ static ssize_t trace_read(struct file *f + crq.collect_fw_trace.correlator = adapter->ras_comps[num].correlator; + crq.collect_fw_trace.ioba = cpu_to_be32(trace_tok); + crq.collect_fw_trace.len = adapter->ras_comps[num].trace_buff_size; +- ibmvnic_send_crq(adapter, &crq); + + init_completion(&adapter->fw_done); ++ ibmvnic_send_crq(adapter, &crq); + wait_for_completion(&adapter->fw_done); + + if (*ppos + len > be32_to_cpu(adapter->ras_comps[num].trace_buff_size)) +@@ -3591,9 +3592,9 @@ static int ibmvnic_dump_show(struct seq_ + memset(&crq, 0, sizeof(crq)); + crq.request_dump_size.first = IBMVNIC_CRQ_CMD; + crq.request_dump_size.cmd = REQUEST_DUMP_SIZE; +- ibmvnic_send_crq(adapter, &crq); + + init_completion(&adapter->fw_done); ++ ibmvnic_send_crq(adapter, &crq); + wait_for_completion(&adapter->fw_done); + + seq_write(seq, adapter->dump_data, adapter->dump_data_size); +@@ -3639,8 +3640,8 @@ static void handle_crq_init_rsp(struct w + } + } + +- send_version_xchg(adapter); + reinit_completion(&adapter->init_done); ++ send_version_xchg(adapter); + if (!wait_for_completion_timeout(&adapter->init_done, timeout)) { + dev_err(dev, "Passive init timeout\n"); + goto task_failed; +@@ -3650,9 +3651,9 @@ static void handle_crq_init_rsp(struct w + if (adapter->renegotiate) { + adapter->renegotiate = false; + release_sub_crqs_no_irqs(adapter); +- send_cap_queries(adapter); + + reinit_completion(&adapter->init_done); ++ send_cap_queries(adapter); + if (!wait_for_completion_timeout(&adapter->init_done, + timeout)) { + dev_err(dev, "Passive init timeout\n"); +@@ -3780,9 +3781,9 @@ static int ibmvnic_probe(struct vio_dev + adapter->debugfs_dump = ent; + } + } +- ibmvnic_send_crq_init(adapter); + + init_completion(&adapter->init_done); ++ ibmvnic_send_crq_init(adapter); + if (!wait_for_completion_timeout(&adapter->init_done, timeout)) + return 0; + +@@ -3790,9 +3791,9 @@ static int ibmvnic_probe(struct vio_dev + if (adapter->renegotiate) { + adapter->renegotiate = false; + release_sub_crqs_no_irqs(adapter); +- send_cap_queries(adapter); + + reinit_completion(&adapter->init_done); ++ send_cap_queries(adapter); + if (!wait_for_completion_timeout(&adapter->init_done, + timeout)) + return 0; diff --git a/queue-4.9/net-fix-proc-net-arp-for-ax.25.patch b/queue-4.9/net-fix-proc-net-arp-for-ax.25.patch new file mode 100644 index 00000000000..1399b8b0872 --- /dev/null +++ b/queue-4.9/net-fix-proc-net-arp-for-ax.25.patch @@ -0,0 +1,83 @@ +From foo@baz Thu Jun 15 11:12:23 CEST 2017 +From: Ralf Baechle +Date: Tue, 23 May 2017 21:53:37 -0400 +Subject: NET: Fix /proc/net/arp for AX.25 + +From: Ralf Baechle + + +[ Upstream commit 4872e57c812dd312bf8193b5933fa60585cda42f ] + +When sending ARP requests over AX.25 links the hwaddress in the neighbour +cache are not getting initialized. For such an incomplete arp entry +ax2asc2 will generate an empty string resulting in /proc/net/arp output +like the following: + +$ cat /proc/net/arp +IP address HW type Flags HW address Mask Device +192.168.122.1 0x1 0x2 52:54:00:00:5d:5f * ens3 +172.20.1.99 0x3 0x0 * bpq0 + +The missing field will confuse the procfs parsing of arp(8) resulting in +incorrect output for the device such as the following: + +$ arp +Address HWtype HWaddress Flags Mask Iface +gateway ether 52:54:00:00:5d:5f C ens3 +172.20.1.99 (incomplete) ens3 + +This changes the content of /proc/net/arp to: + +$ cat /proc/net/arp +IP address HW type Flags HW address Mask Device +172.20.1.99 0x3 0x0 * * bpq0 +192.168.122.1 0x1 0x2 52:54:00:00:5d:5f * ens3 + +To do so it change ax2asc to put the string "*" in buf for a NULL address +argument. Finally the HW address field is left aligned in a 17 character +field (the length of an ethernet HW address in the usual hex notation) for +readability. + +Signed-off-by: Ralf Baechle +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/arp.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/net/ipv4/arp.c ++++ b/net/ipv4/arp.c +@@ -1263,7 +1263,7 @@ void __init arp_init(void) + /* + * ax25 -> ASCII conversion + */ +-static char *ax2asc2(ax25_address *a, char *buf) ++static void ax2asc2(ax25_address *a, char *buf) + { + char c, *s; + int n; +@@ -1285,10 +1285,10 @@ static char *ax2asc2(ax25_address *a, ch + *s++ = n + '0'; + *s++ = '\0'; + +- if (*buf == '\0' || *buf == '-') +- return "*"; +- +- return buf; ++ if (*buf == '\0' || *buf == '-') { ++ buf[0] = '*'; ++ buf[1] = '\0'; ++ } + } + #endif /* CONFIG_AX25 */ + +@@ -1322,7 +1322,7 @@ static void arp_format_neigh_entry(struc + } + #endif + sprintf(tbuf, "%pI4", n->primary_key); +- seq_printf(seq, "%-16s 0x%-10x0x%-10x%s * %s\n", ++ seq_printf(seq, "%-16s 0x%-10x0x%-10x%-17s * %s\n", + tbuf, hatype, arp_state_to_flags(n), hbuffer, dev->name); + read_unlock(&n->lock); + } diff --git a/queue-4.9/net-hns-fix-the-device-being-used-for-dma-mapping-during-tx.patch b/queue-4.9/net-hns-fix-the-device-being-used-for-dma-mapping-during-tx.patch new file mode 100644 index 00000000000..17f3710ed53 --- /dev/null +++ b/queue-4.9/net-hns-fix-the-device-being-used-for-dma-mapping-during-tx.patch @@ -0,0 +1,38 @@ +From foo@baz Thu Jun 15 11:12:23 CEST 2017 +From: Kejian Yan +Date: Tue, 23 May 2017 21:53:41 -0400 +Subject: net: hns: Fix the device being used for dma mapping during TX + +From: Kejian Yan + + +[ Upstream commit b85ea006b6bebb692628f11882af41c3e12e1e09 ] + +This patch fixes the device being used to DMA map skb->data. +Erroneous device assignment causes the crash when SMMU is enabled. +This happens during TX since buffer gets DMA mapped with device +correspondign to net_device and gets unmapped using the device +related to DSAF. + +Signed-off-by: Kejian Yan +Reviewed-by: Yisen Zhuang +Signed-off-by: Salil Mehta +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/hisilicon/hns/hns_enet.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c ++++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c +@@ -304,8 +304,8 @@ int hns_nic_net_xmit_hw(struct net_devic + struct hns_nic_ring_data *ring_data) + { + struct hns_nic_priv *priv = netdev_priv(ndev); +- struct device *dev = priv->dev; + struct hnae_ring *ring = ring_data->ring; ++ struct device *dev = ring_to_dev(ring); + struct netdev_queue *dev_queue; + struct skb_frag_struct *frag; + int buf_num; diff --git a/queue-4.9/net-mkiss-fix-panic.patch b/queue-4.9/net-mkiss-fix-panic.patch new file mode 100644 index 00000000000..098051181f1 --- /dev/null +++ b/queue-4.9/net-mkiss-fix-panic.patch @@ -0,0 +1,54 @@ +From foo@baz Thu Jun 15 11:12:23 CEST 2017 +From: Ralf Baechle +Date: Tue, 23 May 2017 21:53:40 -0400 +Subject: NET: mkiss: Fix panic + +From: Ralf Baechle + + +[ Upstream commit 7ba1b689038726d34e3244c1ac9e2e18c2ea4787 ] + +If a USB-to-serial adapter is unplugged, the driver re-initializes, with +dev->hard_header_len and dev->addr_len set to zero, instead of the correct +values. If then a packet is sent through the half-dead interface, the +kernel will panic due to running out of headroom in the skb when pushing +for the AX.25 headers resulting in this panic: + +[] (skb_panic) from [] (skb_push+0x4c/0x50) +[] (skb_push) from [] (ax25_hard_header+0x34/0xf4 [ax25]) +[] (ax25_hard_header [ax25]) from [] (ax_header+0x38/0x40 [mkiss]) +[] (ax_header [mkiss]) from [] (neigh_compat_output+0x8c/0xd8) +[] (neigh_compat_output) from [] (ip_finish_output+0x2a0/0x914) +[] (ip_finish_output) from [] (ip_output+0xd8/0xf0) +[] (ip_output) from [] (ip_local_out_sk+0x44/0x48) + +This patch makes mkiss behave like the 6pack driver. 6pack does not +panic. In 6pack.c sp_setup() (same function name here) the values for +dev->hard_header_len and dev->addr_len are set to the same values as in +my mkiss patch. + +[ralf@linux-mips.org: Massages original submission to conform to the usual +standards for patch submissions.] + +Signed-off-by: Thomas Osterried +Signed-off-by: Ralf Baechle +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/hamradio/mkiss.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/hamradio/mkiss.c ++++ b/drivers/net/hamradio/mkiss.c +@@ -648,8 +648,8 @@ static void ax_setup(struct net_device * + { + /* Finish setting up the DEVICE info. */ + dev->mtu = AX_MTU; +- dev->hard_header_len = 0; +- dev->addr_len = 0; ++ dev->hard_header_len = AX25_MAX_HEADER_LEN; ++ dev->addr_len = AX25_ADDR_LEN; + dev->type = ARPHRD_AX25; + dev->tx_queue_len = 10; + dev->header_ops = &ax25_header_ops; diff --git a/queue-4.9/powerpc-powernv-properly-set-host-ipi-on-ipis.patch b/queue-4.9/powerpc-powernv-properly-set-host-ipi-on-ipis.patch new file mode 100644 index 00000000000..38f433d2fe5 --- /dev/null +++ b/queue-4.9/powerpc-powernv-properly-set-host-ipi-on-ipis.patch @@ -0,0 +1,41 @@ +From foo@baz Thu Jun 15 11:12:23 CEST 2017 +From: Benjamin Herrenschmidt +Date: Tue, 23 May 2017 21:53:46 -0400 +Subject: powerpc/powernv: Properly set "host-ipi" on IPIs + +From: Benjamin Herrenschmidt + + +[ Upstream commit f83e6862047e1e371bdc5d512dd6cabe8a3965b8 ] + +Otherwise KVM will fail to pass them through to the host + +Signed-off-by: Benjamin Herrenschmidt +Signed-off-by: Michael Ellerman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/sysdev/xics/icp-opal.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/arch/powerpc/sysdev/xics/icp-opal.c ++++ b/arch/powerpc/sysdev/xics/icp-opal.c +@@ -130,14 +130,16 @@ static void icp_opal_cause_ipi(int cpu, + { + int hw_cpu = get_hard_smp_processor_id(cpu); + ++ kvmppc_set_host_ipi(cpu, 1); + opal_int_set_mfrr(hw_cpu, IPI_PRIORITY); + } + + static irqreturn_t icp_opal_ipi_action(int irq, void *dev_id) + { +- int hw_cpu = hard_smp_processor_id(); ++ int cpu = smp_processor_id(); + +- opal_int_set_mfrr(hw_cpu, 0xff); ++ kvmppc_set_host_ipi(cpu, 0); ++ opal_int_set_mfrr(get_hard_smp_processor_id(cpu), 0xff); + + return smp_ipi_demux(); + } diff --git a/queue-4.9/series b/queue-4.9/series index 0fd339af336..9bb53491555 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -11,3 +11,13 @@ ipv6-handle-ipv4-mapped-src-to-in6addr_any-dst.patch ipv6-inhibit-ipv4-mapped-src-address-on-the-wire.patch tipc-fix-tipc_sk_reinit-race-conditions.patch gfs2-use-rhashtable-walk-interface-in-glock_hash_walk.patch +net-fix-proc-net-arp-for-ax.25.patch +ibmvnic-call-napi_disable-instead-of-napi_enable-in-failure-path.patch +ibmvnic-initialize-completion-variables-before-starting-work.patch +net-mkiss-fix-panic.patch +net-hns-fix-the-device-being-used-for-dma-mapping-during-tx.patch +sierra_net-skip-validating-irrelevant-fields-for-idle-lsis.patch +sierra_net-add-support-for-ipv6-and-dual-stack-link-sense-indications.patch +i2c-piix4-request-the-smbus-semaphore-inside-the-mutex.patch +i2c-piix4-fix-request_region-size.patch +powerpc-powernv-properly-set-host-ipi-on-ipis.patch diff --git a/queue-4.9/sierra_net-add-support-for-ipv6-and-dual-stack-link-sense-indications.patch b/queue-4.9/sierra_net-add-support-for-ipv6-and-dual-stack-link-sense-indications.patch new file mode 100644 index 00000000000..374570833fa --- /dev/null +++ b/queue-4.9/sierra_net-add-support-for-ipv6-and-dual-stack-link-sense-indications.patch @@ -0,0 +1,221 @@ +From foo@baz Thu Jun 15 11:12:23 CEST 2017 +From: Stefan Brüns +Date: Tue, 23 May 2017 21:53:43 -0400 +Subject: sierra_net: Add support for IPv6 and Dual-Stack Link Sense Indications + +From: Stefan Brüns + + +[ Upstream commit 5a70348e1187c5bf1cbd0ec51843f36befed1c2d ] + +If a context is configured as dualstack ("IPv4v6"), the modem indicates +the context activation with a slightly different indication message. +The dual-stack indication omits the link_type (IPv4/v6) and adds +additional address fields. +IPv6 LSIs are identical to IPv4 LSIs, but have a different link type. + +Signed-off-by: Stefan Brüns +Reviewed-by: Bjørn Mork +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/usb/sierra_net.c | 101 ++++++++++++++++++++++++++++--------------- + 1 file changed, 66 insertions(+), 35 deletions(-) + +--- a/drivers/net/usb/sierra_net.c ++++ b/drivers/net/usb/sierra_net.c +@@ -73,8 +73,6 @@ static atomic_t iface_counter = ATOMIC_I + /* Private data structure */ + struct sierra_net_data { + +- u8 ethr_hdr_tmpl[ETH_HLEN]; /* ethernet header template for rx'd pkts */ +- + u16 link_up; /* air link up or down */ + u8 tx_hdr_template[4]; /* part of HIP hdr for tx'd packets */ + +@@ -122,6 +120,7 @@ struct param { + + /* LSI Protocol types */ + #define SIERRA_NET_PROTOCOL_UMTS 0x01 ++#define SIERRA_NET_PROTOCOL_UMTS_DS 0x04 + /* LSI Coverage */ + #define SIERRA_NET_COVERAGE_NONE 0x00 + #define SIERRA_NET_COVERAGE_NOPACKET 0x01 +@@ -129,7 +128,8 @@ struct param { + /* LSI Session */ + #define SIERRA_NET_SESSION_IDLE 0x00 + /* LSI Link types */ +-#define SIERRA_NET_AS_LINK_TYPE_IPv4 0x00 ++#define SIERRA_NET_AS_LINK_TYPE_IPV4 0x00 ++#define SIERRA_NET_AS_LINK_TYPE_IPV6 0x02 + + struct lsi_umts { + u8 protocol; +@@ -137,9 +137,14 @@ struct lsi_umts { + __be16 length; + /* eventually use a union for the rest - assume umts for now */ + u8 coverage; +- u8 unused2[41]; ++ u8 network_len; /* network name len */ ++ u8 network[40]; /* network name (UCS2, bigendian) */ + u8 session_state; + u8 unused3[33]; ++} __packed; ++ ++struct lsi_umts_single { ++ struct lsi_umts lsi; + u8 link_type; + u8 pdp_addr_len; /* NW-supplied PDP address len */ + u8 pdp_addr[16]; /* NW-supplied PDP address (bigendian)) */ +@@ -158,10 +163,31 @@ struct lsi_umts { + u8 reserved[8]; + } __packed; + ++struct lsi_umts_dual { ++ struct lsi_umts lsi; ++ u8 pdp_addr4_len; /* NW-supplied PDP IPv4 address len */ ++ u8 pdp_addr4[4]; /* NW-supplied PDP IPv4 address (bigendian)) */ ++ u8 pdp_addr6_len; /* NW-supplied PDP IPv6 address len */ ++ u8 pdp_addr6[16]; /* NW-supplied PDP IPv6 address (bigendian)) */ ++ u8 unused4[23]; ++ u8 dns1_addr4_len; /* NW-supplied 1st DNS v4 address len (bigendian) */ ++ u8 dns1_addr4[4]; /* NW-supplied 1st DNS v4 address */ ++ u8 dns1_addr6_len; /* NW-supplied 1st DNS v6 address len */ ++ u8 dns1_addr6[16]; /* NW-supplied 1st DNS v6 address (bigendian)*/ ++ u8 dns2_addr4_len; /* NW-supplied 2nd DNS v4 address len (bigendian) */ ++ u8 dns2_addr4[4]; /* NW-supplied 2nd DNS v4 address */ ++ u8 dns2_addr6_len; /* NW-supplied 2nd DNS v6 address len */ ++ u8 dns2_addr6[16]; /* NW-supplied 2nd DNS v6 address (bigendian)*/ ++ u8 unused5[68]; ++} __packed; ++ + #define SIERRA_NET_LSI_COMMON_LEN 4 +-#define SIERRA_NET_LSI_UMTS_LEN (sizeof(struct lsi_umts)) ++#define SIERRA_NET_LSI_UMTS_LEN (sizeof(struct lsi_umts_single)) + #define SIERRA_NET_LSI_UMTS_STATUS_LEN \ + (SIERRA_NET_LSI_UMTS_LEN - SIERRA_NET_LSI_COMMON_LEN) ++#define SIERRA_NET_LSI_UMTS_DS_LEN (sizeof(struct lsi_umts_dual)) ++#define SIERRA_NET_LSI_UMTS_DS_STATUS_LEN \ ++ (SIERRA_NET_LSI_UMTS_DS_LEN - SIERRA_NET_LSI_COMMON_LEN) + + /* Forward definitions */ + static void sierra_sync_timer(unsigned long syncdata); +@@ -191,10 +217,11 @@ static inline void sierra_net_set_privat + dev->data[0] = (unsigned long)priv; + } + +-/* is packet IPv4 */ ++/* is packet IPv4/IPv6 */ + static inline int is_ip(struct sk_buff *skb) + { +- return skb->protocol == cpu_to_be16(ETH_P_IP); ++ return skb->protocol == cpu_to_be16(ETH_P_IP) || ++ skb->protocol == cpu_to_be16(ETH_P_IPV6); + } + + /* +@@ -350,18 +377,11 @@ static inline int sierra_net_is_valid_ad + static int sierra_net_parse_lsi(struct usbnet *dev, char *data, int datalen) + { + struct lsi_umts *lsi = (struct lsi_umts *)data; ++ u32 expected_length; + +- if (datalen < sizeof(struct lsi_umts)) { +- netdev_err(dev->net, "%s: Data length %d, exp %Zu\n", +- __func__, datalen, +- sizeof(struct lsi_umts)); +- return -1; +- } +- +- if (lsi->length != cpu_to_be16(SIERRA_NET_LSI_UMTS_STATUS_LEN)) { +- netdev_err(dev->net, "%s: LSI_UMTS_STATUS_LEN %d, exp %u\n", +- __func__, be16_to_cpu(lsi->length), +- (u32)SIERRA_NET_LSI_UMTS_STATUS_LEN); ++ if (datalen < sizeof(struct lsi_umts_single)) { ++ netdev_err(dev->net, "%s: Data length %d, exp >= %Zu\n", ++ __func__, datalen, sizeof(struct lsi_umts_single)); + return -1; + } + +@@ -373,22 +393,34 @@ static int sierra_net_parse_lsi(struct u + } + + /* Validate the protocol - only support UMTS for now */ +- if (lsi->protocol != SIERRA_NET_PROTOCOL_UMTS) { ++ if (lsi->protocol == SIERRA_NET_PROTOCOL_UMTS) { ++ struct lsi_umts_single *single = (struct lsi_umts_single *)lsi; ++ ++ /* Validate the link type */ ++ if (single->link_type != SIERRA_NET_AS_LINK_TYPE_IPV4 && ++ single->link_type != SIERRA_NET_AS_LINK_TYPE_IPV6) { ++ netdev_err(dev->net, "Link type unsupported: 0x%02x\n", ++ single->link_type); ++ return -1; ++ } ++ expected_length = SIERRA_NET_LSI_UMTS_STATUS_LEN; ++ } else if (lsi->protocol == SIERRA_NET_PROTOCOL_UMTS_DS) { ++ expected_length = SIERRA_NET_LSI_UMTS_DS_STATUS_LEN; ++ } else { + netdev_err(dev->net, "Protocol unsupported, 0x%02x\n", +- lsi->protocol); ++ lsi->protocol); + return -1; + } + +- /* Validate the link type */ +- if (lsi->link_type != SIERRA_NET_AS_LINK_TYPE_IPv4) { +- netdev_err(dev->net, "Link type unsupported: 0x%02x\n", +- lsi->link_type); ++ if (be16_to_cpu(lsi->length) != expected_length) { ++ netdev_err(dev->net, "%s: LSI_UMTS_STATUS_LEN %d, exp %u\n", ++ __func__, be16_to_cpu(lsi->length), expected_length); + return -1; + } + + /* Validate the coverage */ +- if (lsi->coverage == SIERRA_NET_COVERAGE_NONE +- || lsi->coverage == SIERRA_NET_COVERAGE_NOPACKET) { ++ if (lsi->coverage == SIERRA_NET_COVERAGE_NONE || ++ lsi->coverage == SIERRA_NET_COVERAGE_NOPACKET) { + netdev_err(dev->net, "No coverage, 0x%02x\n", lsi->coverage); + return 0; + } +@@ -662,7 +694,6 @@ static int sierra_net_bind(struct usbnet + u8 numendpoints; + u16 fwattr = 0; + int status; +- struct ethhdr *eth; + struct sierra_net_data *priv; + static const u8 sync_tmplate[sizeof(priv->sync_msg)] = { + 0x00, 0x00, SIERRA_NET_HIP_MSYNC_ID, 0x00}; +@@ -700,11 +731,6 @@ static int sierra_net_bind(struct usbnet + dev->net->dev_addr[ETH_ALEN-2] = atomic_inc_return(&iface_counter); + dev->net->dev_addr[ETH_ALEN-1] = ifacenum; + +- /* we will have to manufacture ethernet headers, prepare template */ +- eth = (struct ethhdr *)priv->ethr_hdr_tmpl; +- memcpy(ð->h_dest, dev->net->dev_addr, ETH_ALEN); +- eth->h_proto = cpu_to_be16(ETH_P_IP); +- + /* prepare shutdown message template */ + memcpy(priv->shdwn_msg, shdwn_tmplate, sizeof(priv->shdwn_msg)); + /* set context index initially to 0 - prepares tx hdr template */ +@@ -833,9 +859,14 @@ static int sierra_net_rx_fixup(struct us + + skb_pull(skb, hh.hdrlen); + +- /* We are going to accept this packet, prepare it */ +- memcpy(skb->data, sierra_net_get_private(dev)->ethr_hdr_tmpl, +- ETH_HLEN); ++ /* We are going to accept this packet, prepare it. ++ * In case protocol is IPv6, keep it, otherwise force IPv4. ++ */ ++ skb_reset_mac_header(skb); ++ if (eth_hdr(skb)->h_proto != cpu_to_be16(ETH_P_IPV6)) ++ eth_hdr(skb)->h_proto = cpu_to_be16(ETH_P_IP); ++ eth_zero_addr(eth_hdr(skb)->h_source); ++ memcpy(eth_hdr(skb)->h_dest, dev->net->dev_addr, ETH_ALEN); + + /* Last packet in batch handled by usbnet */ + if (hh.payload_len.word == skb->len) diff --git a/queue-4.9/sierra_net-skip-validating-irrelevant-fields-for-idle-lsis.patch b/queue-4.9/sierra_net-skip-validating-irrelevant-fields-for-idle-lsis.patch new file mode 100644 index 00000000000..14aec9acea2 --- /dev/null +++ b/queue-4.9/sierra_net-skip-validating-irrelevant-fields-for-idle-lsis.patch @@ -0,0 +1,52 @@ +From foo@baz Thu Jun 15 11:12:23 CEST 2017 +From: Stefan Brüns +Date: Tue, 23 May 2017 21:53:42 -0400 +Subject: sierra_net: Skip validating irrelevant fields for IDLE LSIs + +From: Stefan Brüns + + +[ Upstream commit 764895d3039e903dac3a70f219949efe43d036a0 ] + +When the context is deactivated, the link_type is set to 0xff, which +triggers a warning message, and results in a wrong link status, as +the LSI is ignored. + +Signed-off-by: Stefan Brüns +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/usb/sierra_net.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +--- a/drivers/net/usb/sierra_net.c ++++ b/drivers/net/usb/sierra_net.c +@@ -365,6 +365,13 @@ static int sierra_net_parse_lsi(struct u + return -1; + } + ++ /* Validate the session state */ ++ if (lsi->session_state == SIERRA_NET_SESSION_IDLE) { ++ netdev_err(dev->net, "Session idle, 0x%02x\n", ++ lsi->session_state); ++ return 0; ++ } ++ + /* Validate the protocol - only support UMTS for now */ + if (lsi->protocol != SIERRA_NET_PROTOCOL_UMTS) { + netdev_err(dev->net, "Protocol unsupported, 0x%02x\n", +@@ -386,13 +393,6 @@ static int sierra_net_parse_lsi(struct u + return 0; + } + +- /* Validate the session state */ +- if (lsi->session_state == SIERRA_NET_SESSION_IDLE) { +- netdev_err(dev->net, "Session idle, 0x%02x\n", +- lsi->session_state); +- return 0; +- } +- + /* Set link_sense true */ + return 1; + }