Including fixes from bluetooth and IPsec.
The bridge patch is actually a follow-up to a recent fix in the same area. We have a pending v6.8 AF_UNIX regression; it should be solved soon, but not in time for this PR. Current release - regressions: - eth: ks8851: Queue RX packets in IRQ handler instead of disabling BHs - net: bridge: fix corrupted ethernet header on multicast-to-unicast Current release - new code bugs: - xfrm: fix possible bad pointer derferencing in error path Previous releases - regressionis: - core: fix out-of-bounds access in ops_init - ipv6: - fix potential uninit-value access in __ip6_make_skb() - fib6_rules: avoid possible NULL dereference in fib6_rule_action() - tcp: use refcount_inc_not_zero() in tcp_twsk_unique(). - rtnetlink: correct nested IFLA_VF_VLAN_LIST attribute validation - rxrpc: fix congestion control algorithm - bluetooth: - l2cap: fix slab-use-after-free in l2cap_connect() - msft: fix slab-use-after-free in msft_do_close() - eth: hns3: fix kernel crash when devlink reload during initialization - eth: dsa: mv88e6xxx: add phylink_get_caps for the mv88e6320/21 family Previous releases - always broken: - xfrm: preserve vlan tags for transport mode software GRO - tcp: defer shutdown(SEND_SHUTDOWN) for TCP_SYN_RECV sockets - eth: hns3: keep using user config after hardware reset Signed-off-by: Paolo Abeni <pabeni@redhat.com> -----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEEg1AjqC77wbdLX2LbKSR5jcyPE6QFAmY8uHASHHBhYmVuaUBy ZWRoYXQuY29tAAoJECkkeY3MjxOkedQQAJ4qDwzqUvo+4Ixnn8xQOEeoaqDAfLGR TBVFgpG72Hd8sT6C92AO2FPOiBkn5D6VL6QsCsOHmoCBmx9opxdM6K+WIuAldlju 0IZ/Z2tML5xE7hdrtpI54iqU4OCbf8M9mJrabHaNetWRwLZruLagvyvpdNNtEoup nhoVetUYBYmxb3MQ0ez6/zTxvbO1ry7H1xVwbe21hOJszoxuYhLQRx7GBMBm2xn3 g6m0T7H8EhPKaY/eGoPONcRQ3v29PEuqgVWg0imNy3P4KkTOhshW0jg11mXfaZQA 32zwLKecdv1gU8Q3Si0ALMtzL3ZC1Iqo4GOEfpr6Bj5Gu+Jd+enPsRDA2hEtMggD uh6d9FU4XULZzX5CFEXCoZs0f9N/FNjkDIWUFdHG+0I8pybw+Fbifub76uN1YC5Y /02WrtlieOy38UG2FW/zTDRqXMwdwY+VhnVVjK42VnVVFCOM3ucXI/wj5uvytk0B iZIWLKtKrVKuUdSdcFvh+Y4z1rK3SFqT5qJEsjzHkLsoap9sbyJrS+MEDeCxv8c4 RDycwqWdlf1csZFDJ/sIxU9+DvpYY+Zh/ZQgTaU86etWYN7GngSYKFgHSD5F+81X kQJgmYInUafzButoL3Kc6JYzfjXYVX9MKAWAjtGdhr7wHOzQHF2U4BUTS4TopjYV BQx1t4dZ4n1F =qYKQ -----END PGP SIGNATURE----- Merge tag 'net-6.9-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net Pull networking fixes from Paolo Abeni: "Including fixes from bluetooth and IPsec. The bridge patch is actually a follow-up to a recent fix in the same area. We have a pending v6.8 AF_UNIX regression; it should be solved soon, but not in time for this PR. Current release - regressions: - eth: ks8851: Queue RX packets in IRQ handler instead of disabling BHs - net: bridge: fix corrupted ethernet header on multicast-to-unicast Current release - new code bugs: - xfrm: fix possible bad pointer derferencing in error path Previous releases - regressionis: - core: fix out-of-bounds access in ops_init - ipv6: - fix potential uninit-value access in __ip6_make_skb() - fib6_rules: avoid possible NULL dereference in fib6_rule_action() - tcp: use refcount_inc_not_zero() in tcp_twsk_unique(). - rtnetlink: correct nested IFLA_VF_VLAN_LIST attribute validation - rxrpc: fix congestion control algorithm - bluetooth: - l2cap: fix slab-use-after-free in l2cap_connect() - msft: fix slab-use-after-free in msft_do_close() - eth: hns3: fix kernel crash when devlink reload during initialization - eth: dsa: mv88e6xxx: add phylink_get_caps for the mv88e6320/21 family Previous releases - always broken: - xfrm: preserve vlan tags for transport mode software GRO - tcp: defer shutdown(SEND_SHUTDOWN) for TCP_SYN_RECV sockets - eth: hns3: keep using user config after hardware reset" * tag 'net-6.9-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (47 commits) net: dsa: mv88e6xxx: read cmode on mv88e6320/21 serdes only ports net: dsa: mv88e6xxx: add phylink_get_caps for the mv88e6320/21 family net: hns3: fix kernel crash when devlink reload during initialization net: hns3: fix port vlan filter not disabled issue net: hns3: use appropriate barrier function after setting a bit value net: hns3: release PTP resources if pf initialization failed net: hns3: change type of numa_node_mask as nodemask_t net: hns3: direct return when receive a unknown mailbox message net: hns3: using user configure after hardware reset net/smc: fix neighbour and rtable leak in smc_ib_find_route() ipv6: prevent NULL dereference in ip6_output() hsr: Simplify code for announcing HSR nodes timer setup ipv6: fib6_rules: avoid possible NULL dereference in fib6_rule_action() dt-bindings: net: mediatek: remove wrongly added clocks and SerDes rxrpc: Only transmit one ACK per jumbo packet received rxrpc: Fix congestion control algorithm selftests: test_bridge_neigh_suppress.sh: Fix failures due to duplicate MAC ipv6: Fix potential uninit-value access in __ip6_make_skb() net: phy: marvell-88q2xxx: add support for Rev B1 and B2 appletalk: Improve handling of broadcast packets ...
This commit is contained in:
commit
8c3b7565f8
|
@ -337,8 +337,8 @@ allOf:
|
||||||
minItems: 4
|
minItems: 4
|
||||||
|
|
||||||
clocks:
|
clocks:
|
||||||
minItems: 34
|
minItems: 24
|
||||||
maxItems: 34
|
maxItems: 24
|
||||||
|
|
||||||
clock-names:
|
clock-names:
|
||||||
items:
|
items:
|
||||||
|
@ -351,18 +351,6 @@ allOf:
|
||||||
- const: ethwarp_wocpu1
|
- const: ethwarp_wocpu1
|
||||||
- const: ethwarp_wocpu0
|
- const: ethwarp_wocpu0
|
||||||
- const: esw
|
- const: esw
|
||||||
- const: netsys0
|
|
||||||
- const: netsys1
|
|
||||||
- const: sgmii_tx250m
|
|
||||||
- const: sgmii_rx250m
|
|
||||||
- const: sgmii2_tx250m
|
|
||||||
- const: sgmii2_rx250m
|
|
||||||
- const: top_usxgmii0_sel
|
|
||||||
- const: top_usxgmii1_sel
|
|
||||||
- const: top_sgm0_sel
|
|
||||||
- const: top_sgm1_sel
|
|
||||||
- const: top_xfi_phy0_xtal_sel
|
|
||||||
- const: top_xfi_phy1_xtal_sel
|
|
||||||
- const: top_eth_gmii_sel
|
- const: top_eth_gmii_sel
|
||||||
- const: top_eth_refck_50m_sel
|
- const: top_eth_refck_50m_sel
|
||||||
- const: top_eth_sys_200m_sel
|
- const: top_eth_sys_200m_sel
|
||||||
|
@ -375,16 +363,10 @@ allOf:
|
||||||
- const: top_netsys_sync_250m_sel
|
- const: top_netsys_sync_250m_sel
|
||||||
- const: top_netsys_ppefb_250m_sel
|
- const: top_netsys_ppefb_250m_sel
|
||||||
- const: top_netsys_warp_sel
|
- const: top_netsys_warp_sel
|
||||||
- const: wocpu1
|
|
||||||
- const: wocpu0
|
|
||||||
- const: xgp1
|
- const: xgp1
|
||||||
- const: xgp2
|
- const: xgp2
|
||||||
- const: xgp3
|
- const: xgp3
|
||||||
|
|
||||||
mediatek,sgmiisys:
|
|
||||||
minItems: 2
|
|
||||||
maxItems: 2
|
|
||||||
|
|
||||||
patternProperties:
|
patternProperties:
|
||||||
"^mac@[0-1]$":
|
"^mac@[0-1]$":
|
||||||
type: object
|
type: object
|
||||||
|
|
|
@ -1144,6 +1144,12 @@ attribute-sets:
|
||||||
-
|
-
|
||||||
name: mcast-querier-state
|
name: mcast-querier-state
|
||||||
type: binary
|
type: binary
|
||||||
|
-
|
||||||
|
name: fdb-n-learned
|
||||||
|
type: u32
|
||||||
|
-
|
||||||
|
name: fdb-max-learned
|
||||||
|
type: u32
|
||||||
-
|
-
|
||||||
name: linkinfo-brport-attrs
|
name: linkinfo-brport-attrs
|
||||||
name-prefix: ifla-brport-
|
name-prefix: ifla-brport-
|
||||||
|
|
|
@ -5709,7 +5709,7 @@ Q: http://patchwork.linuxtv.org/project/linux-media/list/
|
||||||
F: drivers/media/dvb-frontends/cxd2820r*
|
F: drivers/media/dvb-frontends/cxd2820r*
|
||||||
|
|
||||||
CXGB3 ETHERNET DRIVER (CXGB3)
|
CXGB3 ETHERNET DRIVER (CXGB3)
|
||||||
M: Raju Rangoju <rajur@chelsio.com>
|
M: Potnuri Bharat Teja <bharat@chelsio.com>
|
||||||
L: netdev@vger.kernel.org
|
L: netdev@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
W: http://www.chelsio.com
|
W: http://www.chelsio.com
|
||||||
|
@ -5730,7 +5730,7 @@ W: http://www.chelsio.com
|
||||||
F: drivers/crypto/chelsio
|
F: drivers/crypto/chelsio
|
||||||
|
|
||||||
CXGB4 ETHERNET DRIVER (CXGB4)
|
CXGB4 ETHERNET DRIVER (CXGB4)
|
||||||
M: Raju Rangoju <rajur@chelsio.com>
|
M: Potnuri Bharat Teja <bharat@chelsio.com>
|
||||||
L: netdev@vger.kernel.org
|
L: netdev@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
W: http://www.chelsio.com
|
W: http://www.chelsio.com
|
||||||
|
@ -5759,7 +5759,7 @@ F: drivers/infiniband/hw/cxgb4/
|
||||||
F: include/uapi/rdma/cxgb4-abi.h
|
F: include/uapi/rdma/cxgb4-abi.h
|
||||||
|
|
||||||
CXGB4VF ETHERNET DRIVER (CXGB4VF)
|
CXGB4VF ETHERNET DRIVER (CXGB4VF)
|
||||||
M: Raju Rangoju <rajur@chelsio.com>
|
M: Potnuri Bharat Teja <bharat@chelsio.com>
|
||||||
L: netdev@vger.kernel.org
|
L: netdev@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
W: http://www.chelsio.com
|
W: http://www.chelsio.com
|
||||||
|
|
|
@ -82,7 +82,8 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
&mmc1 {
|
&mmc1 {
|
||||||
bt_reset: bt-reset {
|
bluetooth@2 {
|
||||||
|
reg = <2>;
|
||||||
compatible = "mediatek,mt7921s-bluetooth";
|
compatible = "mediatek,mt7921s-bluetooth";
|
||||||
pinctrl-names = "default";
|
pinctrl-names = "default";
|
||||||
pinctrl-0 = <&bt_pins_reset>;
|
pinctrl-0 = <&bt_pins_reset>;
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
|
|
||||||
#define VERSION "0.1"
|
#define VERSION "0.1"
|
||||||
|
|
||||||
#define QCA_BDADDR_DEFAULT (&(bdaddr_t) {{ 0xad, 0x5a, 0x00, 0x00, 0x00, 0x00 }})
|
|
||||||
|
|
||||||
int qca_read_soc_version(struct hci_dev *hdev, struct qca_btsoc_version *ver,
|
int qca_read_soc_version(struct hci_dev *hdev, struct qca_btsoc_version *ver,
|
||||||
enum qca_btsoc_type soc_type)
|
enum qca_btsoc_type soc_type)
|
||||||
{
|
{
|
||||||
|
@ -101,7 +99,8 @@ static int qca_read_fw_build_info(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
struct edl_event_hdr *edl;
|
struct edl_event_hdr *edl;
|
||||||
char cmd, build_label[QCA_FW_BUILD_VER_LEN];
|
char *build_label;
|
||||||
|
char cmd;
|
||||||
int build_lbl_len, err = 0;
|
int build_lbl_len, err = 0;
|
||||||
|
|
||||||
bt_dev_dbg(hdev, "QCA read fw build info");
|
bt_dev_dbg(hdev, "QCA read fw build info");
|
||||||
|
@ -116,6 +115,11 @@ static int qca_read_fw_build_info(struct hci_dev *hdev)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (skb->len < sizeof(*edl)) {
|
||||||
|
err = -EILSEQ;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
edl = (struct edl_event_hdr *)(skb->data);
|
edl = (struct edl_event_hdr *)(skb->data);
|
||||||
if (!edl) {
|
if (!edl) {
|
||||||
bt_dev_err(hdev, "QCA read fw build info with no header");
|
bt_dev_err(hdev, "QCA read fw build info with no header");
|
||||||
|
@ -131,14 +135,25 @@ static int qca_read_fw_build_info(struct hci_dev *hdev)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
build_lbl_len = edl->data[0];
|
if (skb->len < sizeof(*edl) + 1) {
|
||||||
if (build_lbl_len <= QCA_FW_BUILD_VER_LEN - 1) {
|
err = -EILSEQ;
|
||||||
memcpy(build_label, edl->data + 1, build_lbl_len);
|
goto out;
|
||||||
*(build_label + build_lbl_len) = '\0';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
build_lbl_len = edl->data[0];
|
||||||
|
|
||||||
|
if (skb->len < sizeof(*edl) + 1 + build_lbl_len) {
|
||||||
|
err = -EILSEQ;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
build_label = kstrndup(&edl->data[1], build_lbl_len, GFP_KERNEL);
|
||||||
|
if (!build_label)
|
||||||
|
goto out;
|
||||||
|
|
||||||
hci_set_fw_info(hdev, "%s", build_label);
|
hci_set_fw_info(hdev, "%s", build_label);
|
||||||
|
|
||||||
|
kfree(build_label);
|
||||||
out:
|
out:
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
return err;
|
return err;
|
||||||
|
@ -237,6 +252,11 @@ static int qca_read_fw_board_id(struct hci_dev *hdev, u16 *bid)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (skb->len < 3) {
|
||||||
|
err = -EILSEQ;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
*bid = (edl->data[1] << 8) + edl->data[2];
|
*bid = (edl->data[1] << 8) + edl->data[2];
|
||||||
bt_dev_dbg(hdev, "%s: bid = %x", __func__, *bid);
|
bt_dev_dbg(hdev, "%s: bid = %x", __func__, *bid);
|
||||||
|
|
||||||
|
@ -267,9 +287,10 @@ int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(qca_send_pre_shutdown_cmd);
|
EXPORT_SYMBOL_GPL(qca_send_pre_shutdown_cmd);
|
||||||
|
|
||||||
static void qca_tlv_check_data(struct hci_dev *hdev,
|
static int qca_tlv_check_data(struct hci_dev *hdev,
|
||||||
struct qca_fw_config *config,
|
struct qca_fw_config *config,
|
||||||
u8 *fw_data, enum qca_btsoc_type soc_type)
|
u8 *fw_data, size_t fw_size,
|
||||||
|
enum qca_btsoc_type soc_type)
|
||||||
{
|
{
|
||||||
const u8 *data;
|
const u8 *data;
|
||||||
u32 type_len;
|
u32 type_len;
|
||||||
|
@ -279,12 +300,16 @@ static void qca_tlv_check_data(struct hci_dev *hdev,
|
||||||
struct tlv_type_patch *tlv_patch;
|
struct tlv_type_patch *tlv_patch;
|
||||||
struct tlv_type_nvm *tlv_nvm;
|
struct tlv_type_nvm *tlv_nvm;
|
||||||
uint8_t nvm_baud_rate = config->user_baud_rate;
|
uint8_t nvm_baud_rate = config->user_baud_rate;
|
||||||
|
u8 type;
|
||||||
|
|
||||||
config->dnld_mode = QCA_SKIP_EVT_NONE;
|
config->dnld_mode = QCA_SKIP_EVT_NONE;
|
||||||
config->dnld_type = QCA_SKIP_EVT_NONE;
|
config->dnld_type = QCA_SKIP_EVT_NONE;
|
||||||
|
|
||||||
switch (config->type) {
|
switch (config->type) {
|
||||||
case ELF_TYPE_PATCH:
|
case ELF_TYPE_PATCH:
|
||||||
|
if (fw_size < 7)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
config->dnld_mode = QCA_SKIP_EVT_VSE_CC;
|
config->dnld_mode = QCA_SKIP_EVT_VSE_CC;
|
||||||
config->dnld_type = QCA_SKIP_EVT_VSE_CC;
|
config->dnld_type = QCA_SKIP_EVT_VSE_CC;
|
||||||
|
|
||||||
|
@ -293,6 +318,9 @@ static void qca_tlv_check_data(struct hci_dev *hdev,
|
||||||
bt_dev_dbg(hdev, "File version : 0x%x", fw_data[6]);
|
bt_dev_dbg(hdev, "File version : 0x%x", fw_data[6]);
|
||||||
break;
|
break;
|
||||||
case TLV_TYPE_PATCH:
|
case TLV_TYPE_PATCH:
|
||||||
|
if (fw_size < sizeof(struct tlv_type_hdr) + sizeof(struct tlv_type_patch))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
tlv = (struct tlv_type_hdr *)fw_data;
|
tlv = (struct tlv_type_hdr *)fw_data;
|
||||||
type_len = le32_to_cpu(tlv->type_len);
|
type_len = le32_to_cpu(tlv->type_len);
|
||||||
tlv_patch = (struct tlv_type_patch *)tlv->data;
|
tlv_patch = (struct tlv_type_patch *)tlv->data;
|
||||||
|
@ -332,25 +360,64 @@ static void qca_tlv_check_data(struct hci_dev *hdev,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TLV_TYPE_NVM:
|
case TLV_TYPE_NVM:
|
||||||
|
if (fw_size < sizeof(struct tlv_type_hdr))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
tlv = (struct tlv_type_hdr *)fw_data;
|
tlv = (struct tlv_type_hdr *)fw_data;
|
||||||
|
|
||||||
type_len = le32_to_cpu(tlv->type_len);
|
type_len = le32_to_cpu(tlv->type_len);
|
||||||
length = (type_len >> 8) & 0x00ffffff;
|
length = type_len >> 8;
|
||||||
|
type = type_len & 0xff;
|
||||||
|
|
||||||
BT_DBG("TLV Type\t\t : 0x%x", type_len & 0x000000ff);
|
/* Some NVM files have more than one set of tags, only parse
|
||||||
|
* the first set when it has type 2 for now. When there is
|
||||||
|
* more than one set there is an enclosing header of type 4.
|
||||||
|
*/
|
||||||
|
if (type == 4) {
|
||||||
|
if (fw_size < 2 * sizeof(struct tlv_type_hdr))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
tlv++;
|
||||||
|
|
||||||
|
type_len = le32_to_cpu(tlv->type_len);
|
||||||
|
length = type_len >> 8;
|
||||||
|
type = type_len & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
BT_DBG("TLV Type\t\t : 0x%x", type);
|
||||||
BT_DBG("Length\t\t : %d bytes", length);
|
BT_DBG("Length\t\t : %d bytes", length);
|
||||||
|
|
||||||
|
if (type != 2)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (fw_size < length + (tlv->data - fw_data))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
idx = 0;
|
idx = 0;
|
||||||
data = tlv->data;
|
data = tlv->data;
|
||||||
while (idx < length) {
|
while (idx < length - sizeof(struct tlv_type_nvm)) {
|
||||||
tlv_nvm = (struct tlv_type_nvm *)(data + idx);
|
tlv_nvm = (struct tlv_type_nvm *)(data + idx);
|
||||||
|
|
||||||
tag_id = le16_to_cpu(tlv_nvm->tag_id);
|
tag_id = le16_to_cpu(tlv_nvm->tag_id);
|
||||||
tag_len = le16_to_cpu(tlv_nvm->tag_len);
|
tag_len = le16_to_cpu(tlv_nvm->tag_len);
|
||||||
|
|
||||||
|
if (length < idx + sizeof(struct tlv_type_nvm) + tag_len)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
/* Update NVM tags as needed */
|
/* Update NVM tags as needed */
|
||||||
switch (tag_id) {
|
switch (tag_id) {
|
||||||
|
case EDL_TAG_ID_BD_ADDR:
|
||||||
|
if (tag_len != sizeof(bdaddr_t))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
memcpy(&config->bdaddr, tlv_nvm->data, sizeof(bdaddr_t));
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
case EDL_TAG_ID_HCI:
|
case EDL_TAG_ID_HCI:
|
||||||
|
if (tag_len < 3)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
/* HCI transport layer parameters
|
/* HCI transport layer parameters
|
||||||
* enabling software inband sleep
|
* enabling software inband sleep
|
||||||
* onto controller side.
|
* onto controller side.
|
||||||
|
@ -366,6 +433,9 @@ static void qca_tlv_check_data(struct hci_dev *hdev,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EDL_TAG_ID_DEEP_SLEEP:
|
case EDL_TAG_ID_DEEP_SLEEP:
|
||||||
|
if (tag_len < 1)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
/* Sleep enable mask
|
/* Sleep enable mask
|
||||||
* enabling deep sleep feature on controller.
|
* enabling deep sleep feature on controller.
|
||||||
*/
|
*/
|
||||||
|
@ -374,14 +444,16 @@ static void qca_tlv_check_data(struct hci_dev *hdev,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
idx += (sizeof(u16) + sizeof(u16) + 8 + tag_len);
|
idx += sizeof(struct tlv_type_nvm) + tag_len;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
BT_ERR("Unknown TLV type %d", config->type);
|
BT_ERR("Unknown TLV type %d", config->type);
|
||||||
break;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qca_tlv_send_segment(struct hci_dev *hdev, int seg_size,
|
static int qca_tlv_send_segment(struct hci_dev *hdev, int seg_size,
|
||||||
|
@ -531,7 +603,9 @@ static int qca_download_firmware(struct hci_dev *hdev,
|
||||||
memcpy(data, fw->data, size);
|
memcpy(data, fw->data, size);
|
||||||
release_firmware(fw);
|
release_firmware(fw);
|
||||||
|
|
||||||
qca_tlv_check_data(hdev, config, data, soc_type);
|
ret = qca_tlv_check_data(hdev, config, data, size, soc_type);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
segment = data;
|
segment = data;
|
||||||
remain = size;
|
remain = size;
|
||||||
|
@ -614,7 +688,7 @@ int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(qca_set_bdaddr_rome);
|
EXPORT_SYMBOL_GPL(qca_set_bdaddr_rome);
|
||||||
|
|
||||||
static int qca_check_bdaddr(struct hci_dev *hdev)
|
static int qca_check_bdaddr(struct hci_dev *hdev, const struct qca_fw_config *config)
|
||||||
{
|
{
|
||||||
struct hci_rp_read_bd_addr *bda;
|
struct hci_rp_read_bd_addr *bda;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
|
@ -638,7 +712,7 @@ static int qca_check_bdaddr(struct hci_dev *hdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
bda = (struct hci_rp_read_bd_addr *)skb->data;
|
bda = (struct hci_rp_read_bd_addr *)skb->data;
|
||||||
if (!bacmp(&bda->bdaddr, QCA_BDADDR_DEFAULT))
|
if (!bacmp(&bda->bdaddr, &config->bdaddr))
|
||||||
set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
|
set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
|
||||||
|
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
|
@ -667,7 +741,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
|
||||||
enum qca_btsoc_type soc_type, struct qca_btsoc_version ver,
|
enum qca_btsoc_type soc_type, struct qca_btsoc_version ver,
|
||||||
const char *firmware_name)
|
const char *firmware_name)
|
||||||
{
|
{
|
||||||
struct qca_fw_config config;
|
struct qca_fw_config config = {};
|
||||||
int err;
|
int err;
|
||||||
u8 rom_ver = 0;
|
u8 rom_ver = 0;
|
||||||
u32 soc_ver;
|
u32 soc_ver;
|
||||||
|
@ -852,7 +926,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = qca_check_bdaddr(hdev);
|
err = qca_check_bdaddr(hdev, &config);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#define EDL_PATCH_CONFIG_RES_EVT (0x00)
|
#define EDL_PATCH_CONFIG_RES_EVT (0x00)
|
||||||
#define QCA_DISABLE_LOGGING_SUB_OP (0x14)
|
#define QCA_DISABLE_LOGGING_SUB_OP (0x14)
|
||||||
|
|
||||||
|
#define EDL_TAG_ID_BD_ADDR 2
|
||||||
#define EDL_TAG_ID_HCI (17)
|
#define EDL_TAG_ID_HCI (17)
|
||||||
#define EDL_TAG_ID_DEEP_SLEEP (27)
|
#define EDL_TAG_ID_DEEP_SLEEP (27)
|
||||||
|
|
||||||
|
@ -47,7 +48,6 @@
|
||||||
#define get_soc_ver(soc_id, rom_ver) \
|
#define get_soc_ver(soc_id, rom_ver) \
|
||||||
((le32_to_cpu(soc_id) << 16) | (le16_to_cpu(rom_ver)))
|
((le32_to_cpu(soc_id) << 16) | (le16_to_cpu(rom_ver)))
|
||||||
|
|
||||||
#define QCA_FW_BUILD_VER_LEN 255
|
|
||||||
#define QCA_HSP_GF_SOC_ID 0x1200
|
#define QCA_HSP_GF_SOC_ID 0x1200
|
||||||
#define QCA_HSP_GF_SOC_MASK 0x0000ff00
|
#define QCA_HSP_GF_SOC_MASK 0x0000ff00
|
||||||
|
|
||||||
|
@ -94,6 +94,7 @@ struct qca_fw_config {
|
||||||
uint8_t user_baud_rate;
|
uint8_t user_baud_rate;
|
||||||
enum qca_tlv_dnld_mode dnld_mode;
|
enum qca_tlv_dnld_mode dnld_mode;
|
||||||
enum qca_tlv_dnld_mode dnld_type;
|
enum qca_tlv_dnld_mode dnld_type;
|
||||||
|
bdaddr_t bdaddr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct edl_event_hdr {
|
struct edl_event_hdr {
|
||||||
|
|
|
@ -637,12 +637,12 @@ static void mv88e6351_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
|
||||||
MAC_1000FD;
|
MAC_1000FD;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mv88e6352_get_port4_serdes_cmode(struct mv88e6xxx_chip *chip)
|
static int mv88e63xx_get_port_serdes_cmode(struct mv88e6xxx_chip *chip, int port)
|
||||||
{
|
{
|
||||||
u16 reg, val;
|
u16 reg, val;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = mv88e6xxx_port_read(chip, 4, MV88E6XXX_PORT_STS, ®);
|
err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, ®);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -651,16 +651,16 @@ static int mv88e6352_get_port4_serdes_cmode(struct mv88e6xxx_chip *chip)
|
||||||
return 0xf;
|
return 0xf;
|
||||||
|
|
||||||
val = reg & ~MV88E6XXX_PORT_STS_PHY_DETECT;
|
val = reg & ~MV88E6XXX_PORT_STS_PHY_DETECT;
|
||||||
err = mv88e6xxx_port_write(chip, 4, MV88E6XXX_PORT_STS, val);
|
err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_STS, val);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = mv88e6xxx_port_read(chip, 4, MV88E6XXX_PORT_STS, &val);
|
err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &val);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
/* Restore PHY_DETECT value */
|
/* Restore PHY_DETECT value */
|
||||||
err = mv88e6xxx_port_write(chip, 4, MV88E6XXX_PORT_STS, reg);
|
err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_STS, reg);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -688,7 +688,30 @@ static void mv88e6352_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
|
||||||
if (err <= 0)
|
if (err <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cmode = mv88e6352_get_port4_serdes_cmode(chip);
|
cmode = mv88e63xx_get_port_serdes_cmode(chip, port);
|
||||||
|
if (cmode < 0)
|
||||||
|
dev_err(chip->dev, "p%d: failed to read serdes cmode\n",
|
||||||
|
port);
|
||||||
|
else
|
||||||
|
mv88e6xxx_translate_cmode(cmode, supported);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mv88e632x_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
|
||||||
|
struct phylink_config *config)
|
||||||
|
{
|
||||||
|
unsigned long *supported = config->supported_interfaces;
|
||||||
|
int cmode;
|
||||||
|
|
||||||
|
/* Translate the default cmode */
|
||||||
|
mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported);
|
||||||
|
|
||||||
|
config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 |
|
||||||
|
MAC_1000FD;
|
||||||
|
|
||||||
|
/* Port 0/1 are serdes only ports */
|
||||||
|
if (port == 0 || port == 1) {
|
||||||
|
cmode = mv88e63xx_get_port_serdes_cmode(chip, port);
|
||||||
if (cmode < 0)
|
if (cmode < 0)
|
||||||
dev_err(chip->dev, "p%d: failed to read serdes cmode\n",
|
dev_err(chip->dev, "p%d: failed to read serdes cmode\n",
|
||||||
port);
|
port);
|
||||||
|
@ -5093,7 +5116,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = {
|
||||||
.gpio_ops = &mv88e6352_gpio_ops,
|
.gpio_ops = &mv88e6352_gpio_ops,
|
||||||
.avb_ops = &mv88e6352_avb_ops,
|
.avb_ops = &mv88e6352_avb_ops,
|
||||||
.ptp_ops = &mv88e6352_ptp_ops,
|
.ptp_ops = &mv88e6352_ptp_ops,
|
||||||
.phylink_get_caps = mv88e6185_phylink_get_caps,
|
.phylink_get_caps = mv88e632x_phylink_get_caps,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct mv88e6xxx_ops mv88e6321_ops = {
|
static const struct mv88e6xxx_ops mv88e6321_ops = {
|
||||||
|
@ -5139,7 +5162,7 @@ static const struct mv88e6xxx_ops mv88e6321_ops = {
|
||||||
.gpio_ops = &mv88e6352_gpio_ops,
|
.gpio_ops = &mv88e6352_gpio_ops,
|
||||||
.avb_ops = &mv88e6352_avb_ops,
|
.avb_ops = &mv88e6352_avb_ops,
|
||||||
.ptp_ops = &mv88e6352_ptp_ops,
|
.ptp_ops = &mv88e6352_ptp_ops,
|
||||||
.phylink_get_caps = mv88e6185_phylink_get_caps,
|
.phylink_get_caps = mv88e632x_phylink_get_caps,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct mv88e6xxx_ops mv88e6341_ops = {
|
static const struct mv88e6xxx_ops mv88e6341_ops = {
|
||||||
|
|
|
@ -897,7 +897,7 @@ struct hnae3_handle {
|
||||||
struct hnae3_roce_private_info rinfo;
|
struct hnae3_roce_private_info rinfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
u32 numa_node_mask; /* for multi-chip support */
|
nodemask_t numa_node_mask; /* for multi-chip support */
|
||||||
|
|
||||||
enum hnae3_port_base_vlan_state port_base_vlan_state;
|
enum hnae3_port_base_vlan_state port_base_vlan_state;
|
||||||
|
|
||||||
|
|
|
@ -1537,6 +1537,9 @@ static int hclge_configure(struct hclge_dev *hdev)
|
||||||
cfg.default_speed, ret);
|
cfg.default_speed, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
hdev->hw.mac.req_speed = hdev->hw.mac.speed;
|
||||||
|
hdev->hw.mac.req_autoneg = AUTONEG_ENABLE;
|
||||||
|
hdev->hw.mac.req_duplex = DUPLEX_FULL;
|
||||||
|
|
||||||
hclge_parse_link_mode(hdev, cfg.speed_ability);
|
hclge_parse_link_mode(hdev, cfg.speed_ability);
|
||||||
|
|
||||||
|
@ -1766,7 +1769,8 @@ static int hclge_vport_setup(struct hclge_vport *vport, u16 num_tqps)
|
||||||
|
|
||||||
nic->pdev = hdev->pdev;
|
nic->pdev = hdev->pdev;
|
||||||
nic->ae_algo = &ae_algo;
|
nic->ae_algo = &ae_algo;
|
||||||
nic->numa_node_mask = hdev->numa_node_mask;
|
bitmap_copy(nic->numa_node_mask.bits, hdev->numa_node_mask.bits,
|
||||||
|
MAX_NUMNODES);
|
||||||
nic->kinfo.io_base = hdev->hw.hw.io_base;
|
nic->kinfo.io_base = hdev->hw.hw.io_base;
|
||||||
|
|
||||||
ret = hclge_knic_setup(vport, num_tqps,
|
ret = hclge_knic_setup(vport, num_tqps,
|
||||||
|
@ -2458,7 +2462,8 @@ static int hclge_init_roce_base_info(struct hclge_vport *vport)
|
||||||
|
|
||||||
roce->pdev = nic->pdev;
|
roce->pdev = nic->pdev;
|
||||||
roce->ae_algo = nic->ae_algo;
|
roce->ae_algo = nic->ae_algo;
|
||||||
roce->numa_node_mask = nic->numa_node_mask;
|
bitmap_copy(roce->numa_node_mask.bits, nic->numa_node_mask.bits,
|
||||||
|
MAX_NUMNODES);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -3342,9 +3347,9 @@ hclge_set_phy_link_ksettings(struct hnae3_handle *handle,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
hdev->hw.mac.autoneg = cmd->base.autoneg;
|
hdev->hw.mac.req_autoneg = cmd->base.autoneg;
|
||||||
hdev->hw.mac.speed = cmd->base.speed;
|
hdev->hw.mac.req_speed = cmd->base.speed;
|
||||||
hdev->hw.mac.duplex = cmd->base.duplex;
|
hdev->hw.mac.req_duplex = cmd->base.duplex;
|
||||||
linkmode_copy(hdev->hw.mac.advertising, cmd->link_modes.advertising);
|
linkmode_copy(hdev->hw.mac.advertising, cmd->link_modes.advertising);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -3377,9 +3382,9 @@ static int hclge_tp_port_init(struct hclge_dev *hdev)
|
||||||
if (!hnae3_dev_phy_imp_supported(hdev))
|
if (!hnae3_dev_phy_imp_supported(hdev))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
cmd.base.autoneg = hdev->hw.mac.autoneg;
|
cmd.base.autoneg = hdev->hw.mac.req_autoneg;
|
||||||
cmd.base.speed = hdev->hw.mac.speed;
|
cmd.base.speed = hdev->hw.mac.req_speed;
|
||||||
cmd.base.duplex = hdev->hw.mac.duplex;
|
cmd.base.duplex = hdev->hw.mac.req_duplex;
|
||||||
linkmode_copy(cmd.link_modes.advertising, hdev->hw.mac.advertising);
|
linkmode_copy(cmd.link_modes.advertising, hdev->hw.mac.advertising);
|
||||||
|
|
||||||
return hclge_set_phy_link_ksettings(&hdev->vport->nic, &cmd);
|
return hclge_set_phy_link_ksettings(&hdev->vport->nic, &cmd);
|
||||||
|
@ -7952,8 +7957,7 @@ static void hclge_set_timer_task(struct hnae3_handle *handle, bool enable)
|
||||||
/* Set the DOWN flag here to disable link updating */
|
/* Set the DOWN flag here to disable link updating */
|
||||||
set_bit(HCLGE_STATE_DOWN, &hdev->state);
|
set_bit(HCLGE_STATE_DOWN, &hdev->state);
|
||||||
|
|
||||||
/* flush memory to make sure DOWN is seen by service task */
|
smp_mb__after_atomic(); /* flush memory to make sure DOWN is seen by service task */
|
||||||
smp_mb__before_atomic();
|
|
||||||
hclge_flush_link_update(hdev);
|
hclge_flush_link_update(hdev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9906,6 +9910,7 @@ static int hclge_set_vlan_protocol_type(struct hclge_dev *hdev)
|
||||||
static int hclge_init_vlan_filter(struct hclge_dev *hdev)
|
static int hclge_init_vlan_filter(struct hclge_dev *hdev)
|
||||||
{
|
{
|
||||||
struct hclge_vport *vport;
|
struct hclge_vport *vport;
|
||||||
|
bool enable = true;
|
||||||
int ret;
|
int ret;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -9925,8 +9930,12 @@ static int hclge_init_vlan_filter(struct hclge_dev *hdev)
|
||||||
vport->cur_vlan_fltr_en = true;
|
vport->cur_vlan_fltr_en = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (test_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, hdev->ae_dev->caps) &&
|
||||||
|
!test_bit(HNAE3_DEV_SUPPORT_PORT_VLAN_BYPASS_B, hdev->ae_dev->caps))
|
||||||
|
enable = false;
|
||||||
|
|
||||||
return hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_PORT,
|
return hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_PORT,
|
||||||
HCLGE_FILTER_FE_INGRESS, true, 0);
|
HCLGE_FILTER_FE_INGRESS, enable, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hclge_init_vlan_type(struct hclge_dev *hdev)
|
static int hclge_init_vlan_type(struct hclge_dev *hdev)
|
||||||
|
@ -11622,16 +11631,10 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret = hclge_devlink_init(hdev);
|
|
||||||
if (ret)
|
|
||||||
goto err_pci_uninit;
|
|
||||||
|
|
||||||
devl_lock(hdev->devlink);
|
|
||||||
|
|
||||||
/* Firmware command queue initialize */
|
/* Firmware command queue initialize */
|
||||||
ret = hclge_comm_cmd_queue_init(hdev->pdev, &hdev->hw.hw);
|
ret = hclge_comm_cmd_queue_init(hdev->pdev, &hdev->hw.hw);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_devlink_uninit;
|
goto err_pci_uninit;
|
||||||
|
|
||||||
/* Firmware command initialize */
|
/* Firmware command initialize */
|
||||||
ret = hclge_comm_cmd_init(hdev->ae_dev, &hdev->hw.hw, &hdev->fw_version,
|
ret = hclge_comm_cmd_init(hdev->ae_dev, &hdev->hw.hw, &hdev->fw_version,
|
||||||
|
@ -11759,7 +11762,7 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
|
||||||
|
|
||||||
ret = hclge_update_port_info(hdev);
|
ret = hclge_update_port_info(hdev);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_mdiobus_unreg;
|
goto err_ptp_uninit;
|
||||||
|
|
||||||
INIT_KFIFO(hdev->mac_tnl_log);
|
INIT_KFIFO(hdev->mac_tnl_log);
|
||||||
|
|
||||||
|
@ -11799,6 +11802,10 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
|
||||||
dev_warn(&pdev->dev,
|
dev_warn(&pdev->dev,
|
||||||
"failed to wake on lan init, ret = %d\n", ret);
|
"failed to wake on lan init, ret = %d\n", ret);
|
||||||
|
|
||||||
|
ret = hclge_devlink_init(hdev);
|
||||||
|
if (ret)
|
||||||
|
goto err_ptp_uninit;
|
||||||
|
|
||||||
hclge_state_init(hdev);
|
hclge_state_init(hdev);
|
||||||
hdev->last_reset_time = jiffies;
|
hdev->last_reset_time = jiffies;
|
||||||
|
|
||||||
|
@ -11806,10 +11813,10 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
|
||||||
HCLGE_DRIVER_NAME);
|
HCLGE_DRIVER_NAME);
|
||||||
|
|
||||||
hclge_task_schedule(hdev, round_jiffies_relative(HZ));
|
hclge_task_schedule(hdev, round_jiffies_relative(HZ));
|
||||||
|
|
||||||
devl_unlock(hdev->devlink);
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_ptp_uninit:
|
||||||
|
hclge_ptp_uninit(hdev);
|
||||||
err_mdiobus_unreg:
|
err_mdiobus_unreg:
|
||||||
if (hdev->hw.mac.phydev)
|
if (hdev->hw.mac.phydev)
|
||||||
mdiobus_unregister(hdev->hw.mac.mdio_bus);
|
mdiobus_unregister(hdev->hw.mac.mdio_bus);
|
||||||
|
@ -11819,9 +11826,6 @@ err_msi_uninit:
|
||||||
pci_free_irq_vectors(pdev);
|
pci_free_irq_vectors(pdev);
|
||||||
err_cmd_uninit:
|
err_cmd_uninit:
|
||||||
hclge_comm_cmd_uninit(hdev->ae_dev, &hdev->hw.hw);
|
hclge_comm_cmd_uninit(hdev->ae_dev, &hdev->hw.hw);
|
||||||
err_devlink_uninit:
|
|
||||||
devl_unlock(hdev->devlink);
|
|
||||||
hclge_devlink_uninit(hdev);
|
|
||||||
err_pci_uninit:
|
err_pci_uninit:
|
||||||
pcim_iounmap(pdev, hdev->hw.hw.io_base);
|
pcim_iounmap(pdev, hdev->hw.hw.io_base);
|
||||||
pci_release_regions(pdev);
|
pci_release_regions(pdev);
|
||||||
|
|
|
@ -279,11 +279,14 @@ struct hclge_mac {
|
||||||
u8 media_type; /* port media type, e.g. fibre/copper/backplane */
|
u8 media_type; /* port media type, e.g. fibre/copper/backplane */
|
||||||
u8 mac_addr[ETH_ALEN];
|
u8 mac_addr[ETH_ALEN];
|
||||||
u8 autoneg;
|
u8 autoneg;
|
||||||
|
u8 req_autoneg;
|
||||||
u8 duplex;
|
u8 duplex;
|
||||||
|
u8 req_duplex;
|
||||||
u8 support_autoneg;
|
u8 support_autoneg;
|
||||||
u8 speed_type; /* 0: sfp speed, 1: active speed */
|
u8 speed_type; /* 0: sfp speed, 1: active speed */
|
||||||
u8 lane_num;
|
u8 lane_num;
|
||||||
u32 speed;
|
u32 speed;
|
||||||
|
u32 req_speed;
|
||||||
u32 max_speed;
|
u32 max_speed;
|
||||||
u32 speed_ability; /* speed ability supported by current media */
|
u32 speed_ability; /* speed ability supported by current media */
|
||||||
u32 module_type; /* sub media type, e.g. kr/cr/sr/lr */
|
u32 module_type; /* sub media type, e.g. kr/cr/sr/lr */
|
||||||
|
@ -891,7 +894,7 @@ struct hclge_dev {
|
||||||
|
|
||||||
u16 fdir_pf_filter_count; /* Num of guaranteed filters for this PF */
|
u16 fdir_pf_filter_count; /* Num of guaranteed filters for this PF */
|
||||||
u16 num_alloc_vport; /* Num vports this driver supports */
|
u16 num_alloc_vport; /* Num vports this driver supports */
|
||||||
u32 numa_node_mask;
|
nodemask_t numa_node_mask;
|
||||||
u16 rx_buf_len;
|
u16 rx_buf_len;
|
||||||
u16 num_tx_desc; /* desc num of per tx queue */
|
u16 num_tx_desc; /* desc num of per tx queue */
|
||||||
u16 num_rx_desc; /* desc num of per rx queue */
|
u16 num_rx_desc; /* desc num of per rx queue */
|
||||||
|
|
|
@ -1077,12 +1077,13 @@ static void hclge_mbx_request_handling(struct hclge_mbx_ops_param *param)
|
||||||
|
|
||||||
hdev = param->vport->back;
|
hdev = param->vport->back;
|
||||||
cmd_func = hclge_mbx_ops_list[param->req->msg.code];
|
cmd_func = hclge_mbx_ops_list[param->req->msg.code];
|
||||||
if (cmd_func)
|
if (!cmd_func) {
|
||||||
ret = cmd_func(param);
|
|
||||||
else
|
|
||||||
dev_err(&hdev->pdev->dev,
|
dev_err(&hdev->pdev->dev,
|
||||||
"un-supported mailbox message, code = %u\n",
|
"un-supported mailbox message, code = %u\n",
|
||||||
param->req->msg.code);
|
param->req->msg.code);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ret = cmd_func(param);
|
||||||
|
|
||||||
/* PF driver should not reply IMP */
|
/* PF driver should not reply IMP */
|
||||||
if (hnae3_get_bit(param->req->mbx_need_resp, HCLGE_MBX_NEED_RESP_B) &&
|
if (hnae3_get_bit(param->req->mbx_need_resp, HCLGE_MBX_NEED_RESP_B) &&
|
||||||
|
|
|
@ -412,7 +412,8 @@ static int hclgevf_set_handle_info(struct hclgevf_dev *hdev)
|
||||||
|
|
||||||
nic->ae_algo = &ae_algovf;
|
nic->ae_algo = &ae_algovf;
|
||||||
nic->pdev = hdev->pdev;
|
nic->pdev = hdev->pdev;
|
||||||
nic->numa_node_mask = hdev->numa_node_mask;
|
bitmap_copy(nic->numa_node_mask.bits, hdev->numa_node_mask.bits,
|
||||||
|
MAX_NUMNODES);
|
||||||
nic->flags |= HNAE3_SUPPORT_VF;
|
nic->flags |= HNAE3_SUPPORT_VF;
|
||||||
nic->kinfo.io_base = hdev->hw.hw.io_base;
|
nic->kinfo.io_base = hdev->hw.hw.io_base;
|
||||||
|
|
||||||
|
@ -2082,8 +2083,8 @@ static int hclgevf_init_roce_base_info(struct hclgevf_dev *hdev)
|
||||||
|
|
||||||
roce->pdev = nic->pdev;
|
roce->pdev = nic->pdev;
|
||||||
roce->ae_algo = nic->ae_algo;
|
roce->ae_algo = nic->ae_algo;
|
||||||
roce->numa_node_mask = nic->numa_node_mask;
|
bitmap_copy(roce->numa_node_mask.bits, nic->numa_node_mask.bits,
|
||||||
|
MAX_NUMNODES);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2180,8 +2181,7 @@ static void hclgevf_set_timer_task(struct hnae3_handle *handle, bool enable)
|
||||||
} else {
|
} else {
|
||||||
set_bit(HCLGEVF_STATE_DOWN, &hdev->state);
|
set_bit(HCLGEVF_STATE_DOWN, &hdev->state);
|
||||||
|
|
||||||
/* flush memory to make sure DOWN is seen by service task */
|
smp_mb__after_atomic(); /* flush memory to make sure DOWN is seen by service task */
|
||||||
smp_mb__before_atomic();
|
|
||||||
hclgevf_flush_link_update(hdev);
|
hclgevf_flush_link_update(hdev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2845,10 +2845,6 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev)
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = hclgevf_devlink_init(hdev);
|
|
||||||
if (ret)
|
|
||||||
goto err_devlink_init;
|
|
||||||
|
|
||||||
ret = hclge_comm_cmd_queue_init(hdev->pdev, &hdev->hw.hw);
|
ret = hclge_comm_cmd_queue_init(hdev->pdev, &hdev->hw.hw);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_cmd_queue_init;
|
goto err_cmd_queue_init;
|
||||||
|
@ -2941,6 +2937,10 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev)
|
||||||
|
|
||||||
hclgevf_init_rxd_adv_layout(hdev);
|
hclgevf_init_rxd_adv_layout(hdev);
|
||||||
|
|
||||||
|
ret = hclgevf_devlink_init(hdev);
|
||||||
|
if (ret)
|
||||||
|
goto err_config;
|
||||||
|
|
||||||
set_bit(HCLGEVF_STATE_SERVICE_INITED, &hdev->state);
|
set_bit(HCLGEVF_STATE_SERVICE_INITED, &hdev->state);
|
||||||
|
|
||||||
hdev->last_reset_time = jiffies;
|
hdev->last_reset_time = jiffies;
|
||||||
|
@ -2960,8 +2960,6 @@ err_misc_irq_init:
|
||||||
err_cmd_init:
|
err_cmd_init:
|
||||||
hclge_comm_cmd_uninit(hdev->ae_dev, &hdev->hw.hw);
|
hclge_comm_cmd_uninit(hdev->ae_dev, &hdev->hw.hw);
|
||||||
err_cmd_queue_init:
|
err_cmd_queue_init:
|
||||||
hclgevf_devlink_uninit(hdev);
|
|
||||||
err_devlink_init:
|
|
||||||
hclgevf_pci_uninit(hdev);
|
hclgevf_pci_uninit(hdev);
|
||||||
clear_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state);
|
clear_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -236,7 +236,7 @@ struct hclgevf_dev {
|
||||||
u16 rss_size_max; /* HW defined max RSS task queue */
|
u16 rss_size_max; /* HW defined max RSS task queue */
|
||||||
|
|
||||||
u16 num_alloc_vport; /* num vports this driver supports */
|
u16 num_alloc_vport; /* num vports this driver supports */
|
||||||
u32 numa_node_mask;
|
nodemask_t numa_node_mask;
|
||||||
u16 rx_buf_len;
|
u16 rx_buf_len;
|
||||||
u16 num_tx_desc; /* desc num of per tx queue */
|
u16 num_tx_desc; /* desc num of per tx queue */
|
||||||
u16 num_rx_desc; /* desc num of per rx queue */
|
u16 num_rx_desc; /* desc num of per rx queue */
|
||||||
|
|
|
@ -234,12 +234,13 @@ static void ks8851_dbg_dumpkkt(struct ks8851_net *ks, u8 *rxpkt)
|
||||||
/**
|
/**
|
||||||
* ks8851_rx_pkts - receive packets from the host
|
* ks8851_rx_pkts - receive packets from the host
|
||||||
* @ks: The device information.
|
* @ks: The device information.
|
||||||
|
* @rxq: Queue of packets received in this function.
|
||||||
*
|
*
|
||||||
* This is called from the IRQ work queue when the system detects that there
|
* This is called from the IRQ work queue when the system detects that there
|
||||||
* are packets in the receive queue. Find out how many packets there are and
|
* are packets in the receive queue. Find out how many packets there are and
|
||||||
* read them from the FIFO.
|
* read them from the FIFO.
|
||||||
*/
|
*/
|
||||||
static void ks8851_rx_pkts(struct ks8851_net *ks)
|
static void ks8851_rx_pkts(struct ks8851_net *ks, struct sk_buff_head *rxq)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
unsigned rxfc;
|
unsigned rxfc;
|
||||||
|
@ -299,7 +300,7 @@ static void ks8851_rx_pkts(struct ks8851_net *ks)
|
||||||
ks8851_dbg_dumpkkt(ks, rxpkt);
|
ks8851_dbg_dumpkkt(ks, rxpkt);
|
||||||
|
|
||||||
skb->protocol = eth_type_trans(skb, ks->netdev);
|
skb->protocol = eth_type_trans(skb, ks->netdev);
|
||||||
__netif_rx(skb);
|
__skb_queue_tail(rxq, skb);
|
||||||
|
|
||||||
ks->netdev->stats.rx_packets++;
|
ks->netdev->stats.rx_packets++;
|
||||||
ks->netdev->stats.rx_bytes += rxlen;
|
ks->netdev->stats.rx_bytes += rxlen;
|
||||||
|
@ -326,11 +327,11 @@ static void ks8851_rx_pkts(struct ks8851_net *ks)
|
||||||
static irqreturn_t ks8851_irq(int irq, void *_ks)
|
static irqreturn_t ks8851_irq(int irq, void *_ks)
|
||||||
{
|
{
|
||||||
struct ks8851_net *ks = _ks;
|
struct ks8851_net *ks = _ks;
|
||||||
|
struct sk_buff_head rxq;
|
||||||
unsigned handled = 0;
|
unsigned handled = 0;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned int status;
|
unsigned int status;
|
||||||
|
struct sk_buff *skb;
|
||||||
local_bh_disable();
|
|
||||||
|
|
||||||
ks8851_lock(ks, &flags);
|
ks8851_lock(ks, &flags);
|
||||||
|
|
||||||
|
@ -384,7 +385,8 @@ static irqreturn_t ks8851_irq(int irq, void *_ks)
|
||||||
* from the device so do not bother masking just the RX
|
* from the device so do not bother masking just the RX
|
||||||
* from the device. */
|
* from the device. */
|
||||||
|
|
||||||
ks8851_rx_pkts(ks);
|
__skb_queue_head_init(&rxq);
|
||||||
|
ks8851_rx_pkts(ks, &rxq);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if something stopped the rx process, probably due to wanting
|
/* if something stopped the rx process, probably due to wanting
|
||||||
|
@ -408,7 +410,9 @@ static irqreturn_t ks8851_irq(int irq, void *_ks)
|
||||||
if (status & IRQ_LCI)
|
if (status & IRQ_LCI)
|
||||||
mii_check_link(&ks->mii);
|
mii_check_link(&ks->mii);
|
||||||
|
|
||||||
local_bh_enable();
|
if (status & IRQ_RXI)
|
||||||
|
while ((skb = __skb_dequeue(&rxq)))
|
||||||
|
netif_rx(skb);
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#include <linux/hwmon.h>
|
#include <linux/hwmon.h>
|
||||||
|
|
||||||
#define PHY_ID_88Q2220_REVB0 (MARVELL_PHY_ID_88Q2220 | 0x1)
|
#define PHY_ID_88Q2220_REVB0 (MARVELL_PHY_ID_88Q2220 | 0x1)
|
||||||
|
#define PHY_ID_88Q2220_REVB1 (MARVELL_PHY_ID_88Q2220 | 0x2)
|
||||||
|
#define PHY_ID_88Q2220_REVB2 (MARVELL_PHY_ID_88Q2220 | 0x3)
|
||||||
|
|
||||||
#define MDIO_MMD_AN_MV_STAT 32769
|
#define MDIO_MMD_AN_MV_STAT 32769
|
||||||
#define MDIO_MMD_AN_MV_STAT_ANEG 0x0100
|
#define MDIO_MMD_AN_MV_STAT_ANEG 0x0100
|
||||||
|
@ -129,6 +131,49 @@ static const struct mmd_val mv88q222x_revb0_init_seq1[] = {
|
||||||
{ MDIO_MMD_PCS, 0xfe05, 0x755c },
|
{ MDIO_MMD_PCS, 0xfe05, 0x755c },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct mmd_val mv88q222x_revb1_init_seq0[] = {
|
||||||
|
{ MDIO_MMD_PCS, 0xffe4, 0x0007 },
|
||||||
|
{ MDIO_MMD_AN, MDIO_AN_T1_CTRL, 0x0 },
|
||||||
|
{ MDIO_MMD_PCS, 0xffe3, 0x7000 },
|
||||||
|
{ MDIO_MMD_PMAPMD, MDIO_CTRL1, 0x0840 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct mmd_val mv88q222x_revb2_init_seq0[] = {
|
||||||
|
{ MDIO_MMD_PCS, 0xffe4, 0x0007 },
|
||||||
|
{ MDIO_MMD_AN, MDIO_AN_T1_CTRL, 0x0 },
|
||||||
|
{ MDIO_MMD_PMAPMD, MDIO_CTRL1, 0x0840 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct mmd_val mv88q222x_revb1_revb2_init_seq1[] = {
|
||||||
|
{ MDIO_MMD_PCS, 0xfe07, 0x125a },
|
||||||
|
{ MDIO_MMD_PCS, 0xfe09, 0x1288 },
|
||||||
|
{ MDIO_MMD_PCS, 0xfe08, 0x2588 },
|
||||||
|
{ MDIO_MMD_PCS, 0xfe72, 0x042c },
|
||||||
|
{ MDIO_MMD_PCS, 0xffe4, 0x0071 },
|
||||||
|
{ MDIO_MMD_PCS, 0xffe4, 0x0001 },
|
||||||
|
{ MDIO_MMD_PCS, 0xfe1b, 0x0048 },
|
||||||
|
{ MDIO_MMD_PMAPMD, 0x0000, 0x0000 },
|
||||||
|
{ MDIO_MMD_PCS, 0x0000, 0x0000 },
|
||||||
|
{ MDIO_MMD_PCS, 0xffdb, 0xfc10 },
|
||||||
|
{ MDIO_MMD_PCS, 0xfe1b, 0x58 },
|
||||||
|
{ MDIO_MMD_PCS, 0xfcad, 0x030c },
|
||||||
|
{ MDIO_MMD_PCS, 0x8032, 0x6001 },
|
||||||
|
{ MDIO_MMD_PCS, 0xfdff, 0x05a5 },
|
||||||
|
{ MDIO_MMD_PCS, 0xfdec, 0xdbaf },
|
||||||
|
{ MDIO_MMD_PCS, 0xfcab, 0x1054 },
|
||||||
|
{ MDIO_MMD_PCS, 0xfcac, 0x1483 },
|
||||||
|
{ MDIO_MMD_PCS, 0x8033, 0xc801 },
|
||||||
|
{ MDIO_MMD_AN, 0x8032, 0x2020 },
|
||||||
|
{ MDIO_MMD_AN, 0x8031, 0xa28 },
|
||||||
|
{ MDIO_MMD_AN, 0x8031, 0xc28 },
|
||||||
|
{ MDIO_MMD_PCS, 0xfbba, 0x0cb2 },
|
||||||
|
{ MDIO_MMD_PCS, 0xfbbb, 0x0c4a },
|
||||||
|
{ MDIO_MMD_PCS, 0xfe5f, 0xe8 },
|
||||||
|
{ MDIO_MMD_PCS, 0xfe05, 0x755c },
|
||||||
|
{ MDIO_MMD_PCS, 0xfa20, 0x002a },
|
||||||
|
{ MDIO_MMD_PCS, 0xfe11, 0x1105 },
|
||||||
|
};
|
||||||
|
|
||||||
static int mv88q2xxx_soft_reset(struct phy_device *phydev)
|
static int mv88q2xxx_soft_reset(struct phy_device *phydev)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -687,31 +732,72 @@ static int mv88q222x_soft_reset(struct phy_device *phydev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mv88q222x_revb0_config_init(struct phy_device *phydev)
|
static int mv88q222x_write_mmd_vals(struct phy_device *phydev,
|
||||||
|
const struct mmd_val *vals, size_t len)
|
||||||
{
|
{
|
||||||
int ret, i;
|
int ret;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(mv88q222x_revb0_init_seq0); i++) {
|
for (; len; vals++, len--) {
|
||||||
ret = phy_write_mmd(phydev, mv88q222x_revb0_init_seq0[i].devad,
|
ret = phy_write_mmd(phydev, vals->devad, vals->regnum,
|
||||||
mv88q222x_revb0_init_seq0[i].regnum,
|
vals->val);
|
||||||
mv88q222x_revb0_init_seq0[i].val);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mv88q222x_revb0_config_init(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = mv88q222x_write_mmd_vals(phydev, mv88q222x_revb0_init_seq0,
|
||||||
|
ARRAY_SIZE(mv88q222x_revb0_init_seq0));
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
usleep_range(5000, 10000);
|
usleep_range(5000, 10000);
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(mv88q222x_revb0_init_seq1); i++) {
|
ret = mv88q222x_write_mmd_vals(phydev, mv88q222x_revb0_init_seq1,
|
||||||
ret = phy_write_mmd(phydev, mv88q222x_revb0_init_seq1[i].devad,
|
ARRAY_SIZE(mv88q222x_revb0_init_seq1));
|
||||||
mv88q222x_revb0_init_seq1[i].regnum,
|
if (ret < 0)
|
||||||
mv88q222x_revb0_init_seq1[i].val);
|
return ret;
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mv88q2xxx_config_init(phydev);
|
return mv88q2xxx_config_init(phydev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mv88q222x_revb1_revb2_config_init(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
bool is_rev_b1 = phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] == PHY_ID_88Q2220_REVB1;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (is_rev_b1)
|
||||||
|
ret = mv88q222x_write_mmd_vals(phydev, mv88q222x_revb1_init_seq0,
|
||||||
|
ARRAY_SIZE(mv88q222x_revb1_init_seq0));
|
||||||
|
else
|
||||||
|
ret = mv88q222x_write_mmd_vals(phydev, mv88q222x_revb2_init_seq0,
|
||||||
|
ARRAY_SIZE(mv88q222x_revb2_init_seq0));
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
usleep_range(3000, 5000);
|
||||||
|
|
||||||
|
ret = mv88q222x_write_mmd_vals(phydev, mv88q222x_revb1_revb2_init_seq1,
|
||||||
|
ARRAY_SIZE(mv88q222x_revb1_revb2_init_seq1));
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return mv88q2xxx_config_init(phydev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mv88q222x_config_init(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
if (phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] == PHY_ID_88Q2220_REVB0)
|
||||||
|
return mv88q222x_revb0_config_init(phydev);
|
||||||
|
else
|
||||||
|
return mv88q222x_revb1_revb2_config_init(phydev);
|
||||||
|
}
|
||||||
|
|
||||||
static int mv88q222x_cable_test_start(struct phy_device *phydev)
|
static int mv88q222x_cable_test_start(struct phy_device *phydev)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -810,14 +896,15 @@ static struct phy_driver mv88q2xxx_driver[] = {
|
||||||
.get_sqi_max = mv88q2xxx_get_sqi_max,
|
.get_sqi_max = mv88q2xxx_get_sqi_max,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
PHY_ID_MATCH_EXACT(PHY_ID_88Q2220_REVB0),
|
.phy_id = MARVELL_PHY_ID_88Q2220,
|
||||||
|
.phy_id_mask = MARVELL_PHY_ID_MASK,
|
||||||
.name = "mv88q2220",
|
.name = "mv88q2220",
|
||||||
.flags = PHY_POLL_CABLE_TEST,
|
.flags = PHY_POLL_CABLE_TEST,
|
||||||
.probe = mv88q2xxx_probe,
|
.probe = mv88q2xxx_probe,
|
||||||
.get_features = mv88q2xxx_get_features,
|
.get_features = mv88q2xxx_get_features,
|
||||||
.config_aneg = mv88q2xxx_config_aneg,
|
.config_aneg = mv88q2xxx_config_aneg,
|
||||||
.aneg_done = genphy_c45_aneg_done,
|
.aneg_done = genphy_c45_aneg_done,
|
||||||
.config_init = mv88q222x_revb0_config_init,
|
.config_init = mv88q222x_config_init,
|
||||||
.read_status = mv88q2xxx_read_status,
|
.read_status = mv88q2xxx_read_status,
|
||||||
.soft_reset = mv88q222x_soft_reset,
|
.soft_reset = mv88q222x_soft_reset,
|
||||||
.config_intr = mv88q2xxx_config_intr,
|
.config_intr = mv88q2xxx_config_intr,
|
||||||
|
@ -836,7 +923,7 @@ module_phy_driver(mv88q2xxx_driver);
|
||||||
|
|
||||||
static struct mdio_device_id __maybe_unused mv88q2xxx_tbl[] = {
|
static struct mdio_device_id __maybe_unused mv88q2xxx_tbl[] = {
|
||||||
{ MARVELL_PHY_ID_88Q2110, MARVELL_PHY_ID_MASK },
|
{ MARVELL_PHY_ID_88Q2110, MARVELL_PHY_ID_MASK },
|
||||||
{ PHY_ID_MATCH_EXACT(PHY_ID_88Q2220_REVB0), },
|
{ MARVELL_PHY_ID_88Q2220, MARVELL_PHY_ID_MASK },
|
||||||
{ /*sentinel*/ }
|
{ /*sentinel*/ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(mdio, mv88q2xxx_tbl);
|
MODULE_DEVICE_TABLE(mdio, mv88q2xxx_tbl);
|
||||||
|
|
|
@ -3031,6 +3031,21 @@ static inline void skb_mac_header_rebuild(struct sk_buff *skb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Move the full mac header up to current network_header.
|
||||||
|
* Leaves skb->data pointing at offset skb->mac_len into the mac_header.
|
||||||
|
* Must be provided the complete mac header length.
|
||||||
|
*/
|
||||||
|
static inline void skb_mac_header_rebuild_full(struct sk_buff *skb, u32 full_mac_len)
|
||||||
|
{
|
||||||
|
if (skb_mac_header_was_set(skb)) {
|
||||||
|
const unsigned char *old_mac = skb_mac_header(skb);
|
||||||
|
|
||||||
|
skb_set_mac_header(skb, -full_mac_len);
|
||||||
|
memmove(skb_mac_header(skb), old_mac, full_mac_len);
|
||||||
|
__skb_push(skb, full_mac_len - skb->mac_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline int skb_checksum_start_offset(const struct sk_buff *skb)
|
static inline int skb_checksum_start_offset(const struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
return skb->csum_start - skb_headroom(skb);
|
return skb->csum_start - skb_headroom(skb);
|
||||||
|
|
|
@ -1049,6 +1049,9 @@ struct xfrm_offload {
|
||||||
#define CRYPTO_INVALID_PACKET_SYNTAX 64
|
#define CRYPTO_INVALID_PACKET_SYNTAX 64
|
||||||
#define CRYPTO_INVALID_PROTOCOL 128
|
#define CRYPTO_INVALID_PROTOCOL 128
|
||||||
|
|
||||||
|
/* Used to keep whole l2 header for transport mode GRO */
|
||||||
|
__u32 orig_mac_len;
|
||||||
|
|
||||||
__u8 proto;
|
__u8 proto;
|
||||||
__u8 inner_ipproto;
|
__u8 inner_ipproto;
|
||||||
};
|
};
|
||||||
|
|
|
@ -228,7 +228,7 @@ enum {
|
||||||
#define XFRM_NR_MSGTYPES (XFRM_MSG_MAX + 1 - XFRM_MSG_BASE)
|
#define XFRM_NR_MSGTYPES (XFRM_MSG_MAX + 1 - XFRM_MSG_BASE)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generic LSM security context for comunicating to user space
|
* Generic LSM security context for communicating to user space
|
||||||
* NOTE: Same format as sadb_x_sec_ctx
|
* NOTE: Same format as sadb_x_sec_ctx
|
||||||
*/
|
*/
|
||||||
struct xfrm_user_sec_ctx {
|
struct xfrm_user_sec_ctx {
|
||||||
|
|
|
@ -88,6 +88,7 @@ static inline void atalk_remove_socket(struct sock *sk)
|
||||||
static struct sock *atalk_search_socket(struct sockaddr_at *to,
|
static struct sock *atalk_search_socket(struct sockaddr_at *to,
|
||||||
struct atalk_iface *atif)
|
struct atalk_iface *atif)
|
||||||
{
|
{
|
||||||
|
struct sock *def_socket = NULL;
|
||||||
struct sock *s;
|
struct sock *s;
|
||||||
|
|
||||||
read_lock_bh(&atalk_sockets_lock);
|
read_lock_bh(&atalk_sockets_lock);
|
||||||
|
@ -98,8 +99,20 @@ static struct sock *atalk_search_socket(struct sockaddr_at *to,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (to->sat_addr.s_net == ATADDR_ANYNET &&
|
if (to->sat_addr.s_net == ATADDR_ANYNET &&
|
||||||
to->sat_addr.s_node == ATADDR_BCAST)
|
to->sat_addr.s_node == ATADDR_BCAST) {
|
||||||
goto found;
|
if (atif->address.s_node == at->src_node &&
|
||||||
|
atif->address.s_net == at->src_net) {
|
||||||
|
/* This socket's address matches the address of the interface
|
||||||
|
* that received the packet -- use it
|
||||||
|
*/
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Continue searching for a socket matching the interface address,
|
||||||
|
* but use this socket by default if no other one is found
|
||||||
|
*/
|
||||||
|
def_socket = s;
|
||||||
|
}
|
||||||
|
|
||||||
if (to->sat_addr.s_net == at->src_net &&
|
if (to->sat_addr.s_net == at->src_net &&
|
||||||
(to->sat_addr.s_node == at->src_node ||
|
(to->sat_addr.s_node == at->src_node ||
|
||||||
|
@ -116,7 +129,7 @@ static struct sock *atalk_search_socket(struct sockaddr_at *to,
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s = NULL;
|
s = def_socket;
|
||||||
found:
|
found:
|
||||||
read_unlock_bh(&atalk_sockets_lock);
|
read_unlock_bh(&atalk_sockets_lock);
|
||||||
return s;
|
return s;
|
||||||
|
|
|
@ -2768,8 +2768,6 @@ void hci_unregister_dev(struct hci_dev *hdev)
|
||||||
|
|
||||||
hci_unregister_suspend_notifier(hdev);
|
hci_unregister_suspend_notifier(hdev);
|
||||||
|
|
||||||
msft_unregister(hdev);
|
|
||||||
|
|
||||||
hci_dev_do_close(hdev);
|
hci_dev_do_close(hdev);
|
||||||
|
|
||||||
if (!test_bit(HCI_INIT, &hdev->flags) &&
|
if (!test_bit(HCI_INIT, &hdev->flags) &&
|
||||||
|
@ -2823,6 +2821,7 @@ void hci_release_dev(struct hci_dev *hdev)
|
||||||
hci_discovery_filter_clear(hdev);
|
hci_discovery_filter_clear(hdev);
|
||||||
hci_blocked_keys_clear(hdev);
|
hci_blocked_keys_clear(hdev);
|
||||||
hci_codec_list_clear(&hdev->local_codecs);
|
hci_codec_list_clear(&hdev->local_codecs);
|
||||||
|
msft_release(hdev);
|
||||||
hci_dev_unlock(hdev);
|
hci_dev_unlock(hdev);
|
||||||
|
|
||||||
ida_destroy(&hdev->unset_handle_ida);
|
ida_destroy(&hdev->unset_handle_ida);
|
||||||
|
|
|
@ -7037,6 +7037,8 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
|
||||||
u16 handle = le16_to_cpu(ev->bis[i]);
|
u16 handle = le16_to_cpu(ev->bis[i]);
|
||||||
|
|
||||||
bis = hci_conn_hash_lookup_handle(hdev, handle);
|
bis = hci_conn_hash_lookup_handle(hdev, handle);
|
||||||
|
if (!bis)
|
||||||
|
continue;
|
||||||
|
|
||||||
set_bit(HCI_CONN_BIG_SYNC_FAILED, &bis->flags);
|
set_bit(HCI_CONN_BIG_SYNC_FAILED, &bis->flags);
|
||||||
hci_connect_cfm(bis, ev->status);
|
hci_connect_cfm(bis, ev->status);
|
||||||
|
|
|
@ -415,6 +415,9 @@ static void l2cap_chan_timeout(struct work_struct *work)
|
||||||
|
|
||||||
BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
|
BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
|
||||||
|
|
||||||
|
if (!conn)
|
||||||
|
return;
|
||||||
|
|
||||||
mutex_lock(&conn->chan_lock);
|
mutex_lock(&conn->chan_lock);
|
||||||
/* __set_chan_timer() calls l2cap_chan_hold(chan) while scheduling
|
/* __set_chan_timer() calls l2cap_chan_hold(chan) while scheduling
|
||||||
* this work. No need to call l2cap_chan_hold(chan) here again.
|
* this work. No need to call l2cap_chan_hold(chan) here again.
|
||||||
|
@ -3902,13 +3905,12 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
|
static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd,
|
||||||
struct l2cap_cmd_hdr *cmd,
|
u8 *data, u8 rsp_code, u8 amp_id)
|
||||||
u8 *data, u8 rsp_code, u8 amp_id)
|
|
||||||
{
|
{
|
||||||
struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
|
struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
|
||||||
struct l2cap_conn_rsp rsp;
|
struct l2cap_conn_rsp rsp;
|
||||||
struct l2cap_chan *chan = NULL, *pchan;
|
struct l2cap_chan *chan = NULL, *pchan = NULL;
|
||||||
int result, status = L2CAP_CS_NO_INFO;
|
int result, status = L2CAP_CS_NO_INFO;
|
||||||
|
|
||||||
u16 dcid = 0, scid = __le16_to_cpu(req->scid);
|
u16 dcid = 0, scid = __le16_to_cpu(req->scid);
|
||||||
|
@ -3921,7 +3923,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
|
||||||
&conn->hcon->dst, ACL_LINK);
|
&conn->hcon->dst, ACL_LINK);
|
||||||
if (!pchan) {
|
if (!pchan) {
|
||||||
result = L2CAP_CR_BAD_PSM;
|
result = L2CAP_CR_BAD_PSM;
|
||||||
goto sendresp;
|
goto response;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&conn->chan_lock);
|
mutex_lock(&conn->chan_lock);
|
||||||
|
@ -4008,17 +4010,15 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
|
||||||
}
|
}
|
||||||
|
|
||||||
response:
|
response:
|
||||||
l2cap_chan_unlock(pchan);
|
|
||||||
mutex_unlock(&conn->chan_lock);
|
|
||||||
l2cap_chan_put(pchan);
|
|
||||||
|
|
||||||
sendresp:
|
|
||||||
rsp.scid = cpu_to_le16(scid);
|
rsp.scid = cpu_to_le16(scid);
|
||||||
rsp.dcid = cpu_to_le16(dcid);
|
rsp.dcid = cpu_to_le16(dcid);
|
||||||
rsp.result = cpu_to_le16(result);
|
rsp.result = cpu_to_le16(result);
|
||||||
rsp.status = cpu_to_le16(status);
|
rsp.status = cpu_to_le16(status);
|
||||||
l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp);
|
l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp);
|
||||||
|
|
||||||
|
if (!pchan)
|
||||||
|
return;
|
||||||
|
|
||||||
if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
|
if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
|
||||||
struct l2cap_info_req info;
|
struct l2cap_info_req info;
|
||||||
info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
|
info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
|
||||||
|
@ -4041,7 +4041,9 @@ sendresp:
|
||||||
chan->num_conf_req++;
|
chan->num_conf_req++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return chan;
|
l2cap_chan_unlock(pchan);
|
||||||
|
mutex_unlock(&conn->chan_lock);
|
||||||
|
l2cap_chan_put(pchan);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l2cap_connect_req(struct l2cap_conn *conn,
|
static int l2cap_connect_req(struct l2cap_conn *conn,
|
||||||
|
|
|
@ -769,7 +769,7 @@ void msft_register(struct hci_dev *hdev)
|
||||||
mutex_init(&msft->filter_lock);
|
mutex_init(&msft->filter_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void msft_unregister(struct hci_dev *hdev)
|
void msft_release(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct msft_data *msft = hdev->msft_data;
|
struct msft_data *msft = hdev->msft_data;
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
bool msft_monitor_supported(struct hci_dev *hdev);
|
bool msft_monitor_supported(struct hci_dev *hdev);
|
||||||
void msft_register(struct hci_dev *hdev);
|
void msft_register(struct hci_dev *hdev);
|
||||||
void msft_unregister(struct hci_dev *hdev);
|
void msft_release(struct hci_dev *hdev);
|
||||||
void msft_do_open(struct hci_dev *hdev);
|
void msft_do_open(struct hci_dev *hdev);
|
||||||
void msft_do_close(struct hci_dev *hdev);
|
void msft_do_close(struct hci_dev *hdev);
|
||||||
void msft_vendor_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb);
|
void msft_vendor_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb);
|
||||||
|
@ -35,7 +35,7 @@ static inline bool msft_monitor_supported(struct hci_dev *hdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void msft_register(struct hci_dev *hdev) {}
|
static inline void msft_register(struct hci_dev *hdev) {}
|
||||||
static inline void msft_unregister(struct hci_dev *hdev) {}
|
static inline void msft_release(struct hci_dev *hdev) {}
|
||||||
static inline void msft_do_open(struct hci_dev *hdev) {}
|
static inline void msft_do_open(struct hci_dev *hdev) {}
|
||||||
static inline void msft_do_close(struct hci_dev *hdev) {}
|
static inline void msft_do_close(struct hci_dev *hdev) {}
|
||||||
static inline void msft_vendor_evt(struct hci_dev *hdev, void *data,
|
static inline void msft_vendor_evt(struct hci_dev *hdev, void *data,
|
||||||
|
|
|
@ -83,6 +83,10 @@ static void sco_sock_timeout(struct work_struct *work)
|
||||||
struct sock *sk;
|
struct sock *sk;
|
||||||
|
|
||||||
sco_conn_lock(conn);
|
sco_conn_lock(conn);
|
||||||
|
if (!conn->hcon) {
|
||||||
|
sco_conn_unlock(conn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
sk = conn->sk;
|
sk = conn->sk;
|
||||||
if (sk)
|
if (sk)
|
||||||
sock_hold(sk);
|
sock_hold(sk);
|
||||||
|
|
|
@ -258,6 +258,7 @@ static void maybe_deliver_addr(struct net_bridge_port *p, struct sk_buff *skb,
|
||||||
{
|
{
|
||||||
struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
|
struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
|
||||||
const unsigned char *src = eth_hdr(skb)->h_source;
|
const unsigned char *src = eth_hdr(skb)->h_source;
|
||||||
|
struct sk_buff *nskb;
|
||||||
|
|
||||||
if (!should_deliver(p, skb))
|
if (!should_deliver(p, skb))
|
||||||
return;
|
return;
|
||||||
|
@ -266,12 +267,16 @@ static void maybe_deliver_addr(struct net_bridge_port *p, struct sk_buff *skb,
|
||||||
if (skb->dev == p->dev && ether_addr_equal(src, addr))
|
if (skb->dev == p->dev && ether_addr_equal(src, addr))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
skb = pskb_copy(skb, GFP_ATOMIC);
|
__skb_push(skb, ETH_HLEN);
|
||||||
if (!skb) {
|
nskb = pskb_copy(skb, GFP_ATOMIC);
|
||||||
|
__skb_pull(skb, ETH_HLEN);
|
||||||
|
if (!nskb) {
|
||||||
DEV_STATS_INC(dev, tx_dropped);
|
DEV_STATS_INC(dev, tx_dropped);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skb = nskb;
|
||||||
|
__skb_pull(skb, ETH_HLEN);
|
||||||
if (!is_broadcast_ether_addr(addr))
|
if (!is_broadcast_ether_addr(addr))
|
||||||
memcpy(eth_hdr(skb)->h_dest, addr, ETH_ALEN);
|
memcpy(eth_hdr(skb)->h_dest, addr, ETH_ALEN);
|
||||||
|
|
||||||
|
|
|
@ -69,12 +69,15 @@ DEFINE_COOKIE(net_cookie);
|
||||||
|
|
||||||
static struct net_generic *net_alloc_generic(void)
|
static struct net_generic *net_alloc_generic(void)
|
||||||
{
|
{
|
||||||
|
unsigned int gen_ptrs = READ_ONCE(max_gen_ptrs);
|
||||||
|
unsigned int generic_size;
|
||||||
struct net_generic *ng;
|
struct net_generic *ng;
|
||||||
unsigned int generic_size = offsetof(struct net_generic, ptr[max_gen_ptrs]);
|
|
||||||
|
generic_size = offsetof(struct net_generic, ptr[gen_ptrs]);
|
||||||
|
|
||||||
ng = kzalloc(generic_size, GFP_KERNEL);
|
ng = kzalloc(generic_size, GFP_KERNEL);
|
||||||
if (ng)
|
if (ng)
|
||||||
ng->s.len = max_gen_ptrs;
|
ng->s.len = gen_ptrs;
|
||||||
|
|
||||||
return ng;
|
return ng;
|
||||||
}
|
}
|
||||||
|
@ -1307,7 +1310,11 @@ static int register_pernet_operations(struct list_head *list,
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
return error;
|
return error;
|
||||||
*ops->id = error;
|
*ops->id = error;
|
||||||
max_gen_ptrs = max(max_gen_ptrs, *ops->id + 1);
|
/* This does not require READ_ONCE as writers already hold
|
||||||
|
* pernet_ops_rwsem. But WRITE_ONCE is needed to protect
|
||||||
|
* net_alloc_generic.
|
||||||
|
*/
|
||||||
|
WRITE_ONCE(max_gen_ptrs, max(max_gen_ptrs, *ops->id + 1));
|
||||||
}
|
}
|
||||||
error = __register_pernet_operations(list, ops);
|
error = __register_pernet_operations(list, ops);
|
||||||
if (error) {
|
if (error) {
|
||||||
|
|
|
@ -2530,7 +2530,7 @@ static int do_setvfinfo(struct net_device *dev, struct nlattr **tb)
|
||||||
|
|
||||||
nla_for_each_nested(attr, tb[IFLA_VF_VLAN_LIST], rem) {
|
nla_for_each_nested(attr, tb[IFLA_VF_VLAN_LIST], rem) {
|
||||||
if (nla_type(attr) != IFLA_VF_VLAN_INFO ||
|
if (nla_type(attr) != IFLA_VF_VLAN_INFO ||
|
||||||
nla_len(attr) < NLA_HDRLEN) {
|
nla_len(attr) < sizeof(struct ifla_vf_vlan_info)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (len >= MAX_VLAN_LIST_LEN)
|
if (len >= MAX_VLAN_LIST_LEN)
|
||||||
|
|
|
@ -61,39 +61,36 @@ static bool hsr_check_carrier(struct hsr_port *master)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hsr_check_announce(struct net_device *hsr_dev,
|
static void hsr_check_announce(struct net_device *hsr_dev)
|
||||||
unsigned char old_operstate)
|
|
||||||
{
|
{
|
||||||
struct hsr_priv *hsr;
|
struct hsr_priv *hsr;
|
||||||
|
|
||||||
hsr = netdev_priv(hsr_dev);
|
hsr = netdev_priv(hsr_dev);
|
||||||
|
if (netif_running(hsr_dev) && netif_oper_up(hsr_dev)) {
|
||||||
if (READ_ONCE(hsr_dev->operstate) == IF_OPER_UP && old_operstate != IF_OPER_UP) {
|
/* Enable announce timer and start sending supervisory frames */
|
||||||
/* Went up */
|
if (!timer_pending(&hsr->announce_timer)) {
|
||||||
hsr->announce_count = 0;
|
hsr->announce_count = 0;
|
||||||
mod_timer(&hsr->announce_timer,
|
mod_timer(&hsr->announce_timer, jiffies +
|
||||||
jiffies + msecs_to_jiffies(HSR_ANNOUNCE_INTERVAL));
|
msecs_to_jiffies(HSR_ANNOUNCE_INTERVAL));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Deactivate the announce timer */
|
||||||
|
timer_delete(&hsr->announce_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (READ_ONCE(hsr_dev->operstate) != IF_OPER_UP && old_operstate == IF_OPER_UP)
|
|
||||||
/* Went down */
|
|
||||||
del_timer(&hsr->announce_timer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void hsr_check_carrier_and_operstate(struct hsr_priv *hsr)
|
void hsr_check_carrier_and_operstate(struct hsr_priv *hsr)
|
||||||
{
|
{
|
||||||
struct hsr_port *master;
|
struct hsr_port *master;
|
||||||
unsigned char old_operstate;
|
|
||||||
bool has_carrier;
|
bool has_carrier;
|
||||||
|
|
||||||
master = hsr_port_get_hsr(hsr, HSR_PT_MASTER);
|
master = hsr_port_get_hsr(hsr, HSR_PT_MASTER);
|
||||||
/* netif_stacked_transfer_operstate() cannot be used here since
|
/* netif_stacked_transfer_operstate() cannot be used here since
|
||||||
* it doesn't set IF_OPER_LOWERLAYERDOWN (?)
|
* it doesn't set IF_OPER_LOWERLAYERDOWN (?)
|
||||||
*/
|
*/
|
||||||
old_operstate = READ_ONCE(master->dev->operstate);
|
|
||||||
has_carrier = hsr_check_carrier(master);
|
has_carrier = hsr_check_carrier(master);
|
||||||
hsr_set_operstate(master, has_carrier);
|
hsr_set_operstate(master, has_carrier);
|
||||||
hsr_check_announce(master->dev, old_operstate);
|
hsr_check_announce(master->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
int hsr_get_max_mtu(struct hsr_priv *hsr)
|
int hsr_get_max_mtu(struct hsr_priv *hsr)
|
||||||
|
|
|
@ -2710,7 +2710,7 @@ void tcp_shutdown(struct sock *sk, int how)
|
||||||
/* If we've already sent a FIN, or it's a closed state, skip this. */
|
/* If we've already sent a FIN, or it's a closed state, skip this. */
|
||||||
if ((1 << sk->sk_state) &
|
if ((1 << sk->sk_state) &
|
||||||
(TCPF_ESTABLISHED | TCPF_SYN_SENT |
|
(TCPF_ESTABLISHED | TCPF_SYN_SENT |
|
||||||
TCPF_SYN_RECV | TCPF_CLOSE_WAIT)) {
|
TCPF_CLOSE_WAIT)) {
|
||||||
/* Clear out any half completed packets. FIN if needed. */
|
/* Clear out any half completed packets. FIN if needed. */
|
||||||
if (tcp_close_state(sk))
|
if (tcp_close_state(sk))
|
||||||
tcp_send_fin(sk);
|
tcp_send_fin(sk);
|
||||||
|
@ -2819,7 +2819,7 @@ void __tcp_close(struct sock *sk, long timeout)
|
||||||
* machine. State transitions:
|
* machine. State transitions:
|
||||||
*
|
*
|
||||||
* TCP_ESTABLISHED -> TCP_FIN_WAIT1
|
* TCP_ESTABLISHED -> TCP_FIN_WAIT1
|
||||||
* TCP_SYN_RECV -> TCP_FIN_WAIT1 (forget it, it's impossible)
|
* TCP_SYN_RECV -> TCP_FIN_WAIT1 (it is difficult)
|
||||||
* TCP_CLOSE_WAIT -> TCP_LAST_ACK
|
* TCP_CLOSE_WAIT -> TCP_LAST_ACK
|
||||||
*
|
*
|
||||||
* are legal only when FIN has been sent (i.e. in window),
|
* are legal only when FIN has been sent (i.e. in window),
|
||||||
|
|
|
@ -6761,6 +6761,8 @@ tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
|
||||||
|
|
||||||
tcp_initialize_rcv_mss(sk);
|
tcp_initialize_rcv_mss(sk);
|
||||||
tcp_fast_path_on(tp);
|
tcp_fast_path_on(tp);
|
||||||
|
if (sk->sk_shutdown & SEND_SHUTDOWN)
|
||||||
|
tcp_shutdown(sk, SEND_SHUTDOWN);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TCP_FIN_WAIT1: {
|
case TCP_FIN_WAIT1: {
|
||||||
|
|
|
@ -154,6 +154,12 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
|
||||||
if (tcptw->tw_ts_recent_stamp &&
|
if (tcptw->tw_ts_recent_stamp &&
|
||||||
(!twp || (reuse && time_after32(ktime_get_seconds(),
|
(!twp || (reuse && time_after32(ktime_get_seconds(),
|
||||||
tcptw->tw_ts_recent_stamp)))) {
|
tcptw->tw_ts_recent_stamp)))) {
|
||||||
|
/* inet_twsk_hashdance() sets sk_refcnt after putting twsk
|
||||||
|
* and releasing the bucket lock.
|
||||||
|
*/
|
||||||
|
if (unlikely(!refcount_inc_not_zero(&sktw->sk_refcnt)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* In case of repair and re-using TIME-WAIT sockets we still
|
/* In case of repair and re-using TIME-WAIT sockets we still
|
||||||
* want to be sure that it is safe as above but honor the
|
* want to be sure that it is safe as above but honor the
|
||||||
* sequence numbers and time stamps set as part of the repair
|
* sequence numbers and time stamps set as part of the repair
|
||||||
|
@ -174,7 +180,7 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
|
||||||
tp->rx_opt.ts_recent = tcptw->tw_ts_recent;
|
tp->rx_opt.ts_recent = tcptw->tw_ts_recent;
|
||||||
tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp;
|
tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp;
|
||||||
}
|
}
|
||||||
sock_hold(sktw);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3563,7 +3563,9 @@ void tcp_send_fin(struct sock *sk)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
skb = alloc_skb_fclone(MAX_TCP_HEADER, sk->sk_allocation);
|
skb = alloc_skb_fclone(MAX_TCP_HEADER,
|
||||||
|
sk_gfp_mask(sk, GFP_ATOMIC |
|
||||||
|
__GFP_NOWARN));
|
||||||
if (unlikely(!skb))
|
if (unlikely(!skb))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,11 @@ int xfrm4_transport_finish(struct sk_buff *skb, int async)
|
||||||
ip_send_check(iph);
|
ip_send_check(iph);
|
||||||
|
|
||||||
if (xo && (xo->flags & XFRM_GRO)) {
|
if (xo && (xo->flags & XFRM_GRO)) {
|
||||||
skb_mac_header_rebuild(skb);
|
/* The full l2 header needs to be preserved so that re-injecting the packet at l2
|
||||||
|
* works correctly in the presence of vlan tags.
|
||||||
|
*/
|
||||||
|
skb_mac_header_rebuild_full(skb, xo->orig_mac_len);
|
||||||
|
skb_reset_network_header(skb);
|
||||||
skb_reset_transport_header(skb);
|
skb_reset_transport_header(skb);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -233,8 +233,12 @@ static int __fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
|
||||||
rt = pol_lookup_func(lookup,
|
rt = pol_lookup_func(lookup,
|
||||||
net, table, flp6, arg->lookup_data, flags);
|
net, table, flp6, arg->lookup_data, flags);
|
||||||
if (rt != net->ipv6.ip6_null_entry) {
|
if (rt != net->ipv6.ip6_null_entry) {
|
||||||
|
struct inet6_dev *idev = ip6_dst_idev(&rt->dst);
|
||||||
|
|
||||||
|
if (!idev)
|
||||||
|
goto again;
|
||||||
err = fib6_rule_saddr(net, rule, flags, flp6,
|
err = fib6_rule_saddr(net, rule, flags, flp6,
|
||||||
ip6_dst_idev(&rt->dst)->dev);
|
idev->dev);
|
||||||
|
|
||||||
if (err == -EAGAIN)
|
if (err == -EAGAIN)
|
||||||
goto again;
|
goto again;
|
||||||
|
|
|
@ -234,7 +234,7 @@ int ip6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||||
skb->protocol = htons(ETH_P_IPV6);
|
skb->protocol = htons(ETH_P_IPV6);
|
||||||
skb->dev = dev;
|
skb->dev = dev;
|
||||||
|
|
||||||
if (unlikely(READ_ONCE(idev->cnf.disable_ipv6))) {
|
if (unlikely(!idev || READ_ONCE(idev->cnf.disable_ipv6))) {
|
||||||
IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
|
IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
|
||||||
kfree_skb_reason(skb, SKB_DROP_REASON_IPV6DISABLED);
|
kfree_skb_reason(skb, SKB_DROP_REASON_IPV6DISABLED);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1933,7 +1933,7 @@ struct sk_buff *__ip6_make_skb(struct sock *sk,
|
||||||
u8 icmp6_type;
|
u8 icmp6_type;
|
||||||
|
|
||||||
if (sk->sk_socket->type == SOCK_RAW &&
|
if (sk->sk_socket->type == SOCK_RAW &&
|
||||||
!inet_test_bit(HDRINCL, sk))
|
!(fl6->flowi6_flags & FLOWI_FLAG_KNOWN_NH))
|
||||||
icmp6_type = fl6->fl6_icmp_type;
|
icmp6_type = fl6->fl6_icmp_type;
|
||||||
else
|
else
|
||||||
icmp6_type = icmp6_hdr(skb)->icmp6_type;
|
icmp6_type = icmp6_hdr(skb)->icmp6_type;
|
||||||
|
|
|
@ -58,7 +58,11 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async)
|
||||||
skb_postpush_rcsum(skb, skb_network_header(skb), nhlen);
|
skb_postpush_rcsum(skb, skb_network_header(skb), nhlen);
|
||||||
|
|
||||||
if (xo && (xo->flags & XFRM_GRO)) {
|
if (xo && (xo->flags & XFRM_GRO)) {
|
||||||
skb_mac_header_rebuild(skb);
|
/* The full l2 header needs to be preserved so that re-injecting the packet at l2
|
||||||
|
* works correctly in the presence of vlan tags.
|
||||||
|
*/
|
||||||
|
skb_mac_header_rebuild_full(skb, xo->orig_mac_len);
|
||||||
|
skb_reset_network_header(skb);
|
||||||
skb_reset_transport_header(skb);
|
skb_reset_transport_header(skb);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,43 @@ static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SYSCTL
|
#ifdef CONFIG_SYSCTL
|
||||||
|
static int mptcp_set_scheduler(const struct net *net, const char *name)
|
||||||
|
{
|
||||||
|
struct mptcp_pernet *pernet = mptcp_get_pernet(net);
|
||||||
|
struct mptcp_sched_ops *sched;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
sched = mptcp_sched_find(name);
|
||||||
|
if (sched)
|
||||||
|
strscpy(pernet->scheduler, name, MPTCP_SCHED_NAME_MAX);
|
||||||
|
else
|
||||||
|
ret = -ENOENT;
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int proc_scheduler(struct ctl_table *ctl, int write,
|
||||||
|
void *buffer, size_t *lenp, loff_t *ppos)
|
||||||
|
{
|
||||||
|
const struct net *net = current->nsproxy->net_ns;
|
||||||
|
char val[MPTCP_SCHED_NAME_MAX];
|
||||||
|
struct ctl_table tbl = {
|
||||||
|
.data = val,
|
||||||
|
.maxlen = MPTCP_SCHED_NAME_MAX,
|
||||||
|
};
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
strscpy(val, mptcp_get_scheduler(net), MPTCP_SCHED_NAME_MAX);
|
||||||
|
|
||||||
|
ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
|
||||||
|
if (write && ret == 0)
|
||||||
|
ret = mptcp_set_scheduler(net, val);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static struct ctl_table mptcp_sysctl_table[] = {
|
static struct ctl_table mptcp_sysctl_table[] = {
|
||||||
{
|
{
|
||||||
.procname = "enabled",
|
.procname = "enabled",
|
||||||
|
@ -148,7 +185,7 @@ static struct ctl_table mptcp_sysctl_table[] = {
|
||||||
.procname = "scheduler",
|
.procname = "scheduler",
|
||||||
.maxlen = MPTCP_SCHED_NAME_MAX,
|
.maxlen = MPTCP_SCHED_NAME_MAX,
|
||||||
.mode = 0644,
|
.mode = 0644,
|
||||||
.proc_handler = proc_dostring,
|
.proc_handler = proc_scheduler,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.procname = "close_timeout",
|
.procname = "close_timeout",
|
||||||
|
|
|
@ -1518,6 +1518,7 @@ static void nci_rx_work(struct work_struct *work)
|
||||||
|
|
||||||
if (!nci_plen(skb->data)) {
|
if (!nci_plen(skb->data)) {
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
|
kcov_remote_stop();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -193,7 +193,7 @@ void rtm_phonet_notify(int event, struct net_device *dev, u8 dst)
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
int err = -ENOBUFS;
|
int err = -ENOBUFS;
|
||||||
|
|
||||||
skb = nlmsg_new(NLMSG_ALIGN(sizeof(struct ifaddrmsg)) +
|
skb = nlmsg_new(NLMSG_ALIGN(sizeof(struct rtmsg)) +
|
||||||
nla_total_size(1) + nla_total_size(4), GFP_KERNEL);
|
nla_total_size(1) + nla_total_size(4), GFP_KERNEL);
|
||||||
if (skb == NULL)
|
if (skb == NULL)
|
||||||
goto errout;
|
goto errout;
|
||||||
|
|
|
@ -697,7 +697,7 @@ struct rxrpc_call {
|
||||||
* packets) rather than bytes.
|
* packets) rather than bytes.
|
||||||
*/
|
*/
|
||||||
#define RXRPC_TX_SMSS RXRPC_JUMBO_DATALEN
|
#define RXRPC_TX_SMSS RXRPC_JUMBO_DATALEN
|
||||||
#define RXRPC_MIN_CWND (RXRPC_TX_SMSS > 2190 ? 2 : RXRPC_TX_SMSS > 1095 ? 3 : 4)
|
#define RXRPC_MIN_CWND 4
|
||||||
u8 cong_cwnd; /* Congestion window size */
|
u8 cong_cwnd; /* Congestion window size */
|
||||||
u8 cong_extra; /* Extra to send for congestion management */
|
u8 cong_extra; /* Extra to send for congestion management */
|
||||||
u8 cong_ssthresh; /* Slow-start threshold */
|
u8 cong_ssthresh; /* Slow-start threshold */
|
||||||
|
|
|
@ -174,12 +174,7 @@ struct rxrpc_call *rxrpc_alloc_call(struct rxrpc_sock *rx, gfp_t gfp,
|
||||||
call->rx_winsize = rxrpc_rx_window_size;
|
call->rx_winsize = rxrpc_rx_window_size;
|
||||||
call->tx_winsize = 16;
|
call->tx_winsize = 16;
|
||||||
|
|
||||||
if (RXRPC_TX_SMSS > 2190)
|
call->cong_cwnd = RXRPC_MIN_CWND;
|
||||||
call->cong_cwnd = 2;
|
|
||||||
else if (RXRPC_TX_SMSS > 1095)
|
|
||||||
call->cong_cwnd = 3;
|
|
||||||
else
|
|
||||||
call->cong_cwnd = 4;
|
|
||||||
call->cong_ssthresh = RXRPC_TX_MAX_WINDOW;
|
call->cong_ssthresh = RXRPC_TX_MAX_WINDOW;
|
||||||
|
|
||||||
call->rxnet = rxnet;
|
call->rxnet = rxnet;
|
||||||
|
|
|
@ -9,6 +9,17 @@
|
||||||
|
|
||||||
#include "ar-internal.h"
|
#include "ar-internal.h"
|
||||||
|
|
||||||
|
/* Override priority when generating ACKs for received DATA */
|
||||||
|
static const u8 rxrpc_ack_priority[RXRPC_ACK__INVALID] = {
|
||||||
|
[RXRPC_ACK_IDLE] = 1,
|
||||||
|
[RXRPC_ACK_DELAY] = 2,
|
||||||
|
[RXRPC_ACK_REQUESTED] = 3,
|
||||||
|
[RXRPC_ACK_DUPLICATE] = 4,
|
||||||
|
[RXRPC_ACK_EXCEEDS_WINDOW] = 5,
|
||||||
|
[RXRPC_ACK_NOSPACE] = 6,
|
||||||
|
[RXRPC_ACK_OUT_OF_SEQUENCE] = 7,
|
||||||
|
};
|
||||||
|
|
||||||
static void rxrpc_proto_abort(struct rxrpc_call *call, rxrpc_seq_t seq,
|
static void rxrpc_proto_abort(struct rxrpc_call *call, rxrpc_seq_t seq,
|
||||||
enum rxrpc_abort_reason why)
|
enum rxrpc_abort_reason why)
|
||||||
{
|
{
|
||||||
|
@ -365,7 +376,7 @@ static void rxrpc_input_queue_data(struct rxrpc_call *call, struct sk_buff *skb,
|
||||||
* Process a DATA packet.
|
* Process a DATA packet.
|
||||||
*/
|
*/
|
||||||
static void rxrpc_input_data_one(struct rxrpc_call *call, struct sk_buff *skb,
|
static void rxrpc_input_data_one(struct rxrpc_call *call, struct sk_buff *skb,
|
||||||
bool *_notify)
|
bool *_notify, rxrpc_serial_t *_ack_serial, int *_ack_reason)
|
||||||
{
|
{
|
||||||
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
|
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
|
||||||
struct sk_buff *oos;
|
struct sk_buff *oos;
|
||||||
|
@ -418,8 +429,6 @@ static void rxrpc_input_data_one(struct rxrpc_call *call, struct sk_buff *skb,
|
||||||
/* Send an immediate ACK if we fill in a hole */
|
/* Send an immediate ACK if we fill in a hole */
|
||||||
else if (!skb_queue_empty(&call->rx_oos_queue))
|
else if (!skb_queue_empty(&call->rx_oos_queue))
|
||||||
ack_reason = RXRPC_ACK_DELAY;
|
ack_reason = RXRPC_ACK_DELAY;
|
||||||
else
|
|
||||||
call->ackr_nr_unacked++;
|
|
||||||
|
|
||||||
window++;
|
window++;
|
||||||
if (after(window, wtop)) {
|
if (after(window, wtop)) {
|
||||||
|
@ -497,12 +506,16 @@ static void rxrpc_input_data_one(struct rxrpc_call *call, struct sk_buff *skb,
|
||||||
}
|
}
|
||||||
|
|
||||||
send_ack:
|
send_ack:
|
||||||
if (ack_reason >= 0)
|
if (ack_reason >= 0) {
|
||||||
rxrpc_send_ACK(call, ack_reason, serial,
|
if (rxrpc_ack_priority[ack_reason] > rxrpc_ack_priority[*_ack_reason]) {
|
||||||
rxrpc_propose_ack_input_data);
|
*_ack_serial = serial;
|
||||||
else
|
*_ack_reason = ack_reason;
|
||||||
rxrpc_propose_delay_ACK(call, serial,
|
} else if (rxrpc_ack_priority[ack_reason] == rxrpc_ack_priority[*_ack_reason] &&
|
||||||
rxrpc_propose_ack_input_data);
|
ack_reason == RXRPC_ACK_REQUESTED) {
|
||||||
|
*_ack_serial = serial;
|
||||||
|
*_ack_reason = ack_reason;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -513,9 +526,11 @@ static bool rxrpc_input_split_jumbo(struct rxrpc_call *call, struct sk_buff *skb
|
||||||
struct rxrpc_jumbo_header jhdr;
|
struct rxrpc_jumbo_header jhdr;
|
||||||
struct rxrpc_skb_priv *sp = rxrpc_skb(skb), *jsp;
|
struct rxrpc_skb_priv *sp = rxrpc_skb(skb), *jsp;
|
||||||
struct sk_buff *jskb;
|
struct sk_buff *jskb;
|
||||||
|
rxrpc_serial_t ack_serial = 0;
|
||||||
unsigned int offset = sizeof(struct rxrpc_wire_header);
|
unsigned int offset = sizeof(struct rxrpc_wire_header);
|
||||||
unsigned int len = skb->len - offset;
|
unsigned int len = skb->len - offset;
|
||||||
bool notify = false;
|
bool notify = false;
|
||||||
|
int ack_reason = 0;
|
||||||
|
|
||||||
while (sp->hdr.flags & RXRPC_JUMBO_PACKET) {
|
while (sp->hdr.flags & RXRPC_JUMBO_PACKET) {
|
||||||
if (len < RXRPC_JUMBO_SUBPKTLEN)
|
if (len < RXRPC_JUMBO_SUBPKTLEN)
|
||||||
|
@ -535,7 +550,7 @@ static bool rxrpc_input_split_jumbo(struct rxrpc_call *call, struct sk_buff *skb
|
||||||
jsp = rxrpc_skb(jskb);
|
jsp = rxrpc_skb(jskb);
|
||||||
jsp->offset = offset;
|
jsp->offset = offset;
|
||||||
jsp->len = RXRPC_JUMBO_DATALEN;
|
jsp->len = RXRPC_JUMBO_DATALEN;
|
||||||
rxrpc_input_data_one(call, jskb, ¬ify);
|
rxrpc_input_data_one(call, jskb, ¬ify, &ack_serial, &ack_reason);
|
||||||
rxrpc_free_skb(jskb, rxrpc_skb_put_jumbo_subpacket);
|
rxrpc_free_skb(jskb, rxrpc_skb_put_jumbo_subpacket);
|
||||||
|
|
||||||
sp->hdr.flags = jhdr.flags;
|
sp->hdr.flags = jhdr.flags;
|
||||||
|
@ -548,7 +563,16 @@ static bool rxrpc_input_split_jumbo(struct rxrpc_call *call, struct sk_buff *skb
|
||||||
|
|
||||||
sp->offset = offset;
|
sp->offset = offset;
|
||||||
sp->len = len;
|
sp->len = len;
|
||||||
rxrpc_input_data_one(call, skb, ¬ify);
|
rxrpc_input_data_one(call, skb, ¬ify, &ack_serial, &ack_reason);
|
||||||
|
|
||||||
|
if (ack_reason > 0) {
|
||||||
|
rxrpc_send_ACK(call, ack_reason, ack_serial,
|
||||||
|
rxrpc_propose_ack_input_data);
|
||||||
|
} else {
|
||||||
|
call->ackr_nr_unacked++;
|
||||||
|
rxrpc_propose_delay_ACK(call, sp->hdr.serial,
|
||||||
|
rxrpc_propose_ack_input_data);
|
||||||
|
}
|
||||||
if (notify) {
|
if (notify) {
|
||||||
trace_rxrpc_notify_socket(call->debug_id, sp->hdr.serial);
|
trace_rxrpc_notify_socket(call->debug_id, sp->hdr.serial);
|
||||||
rxrpc_notify_socket(call);
|
rxrpc_notify_socket(call);
|
||||||
|
@ -685,9 +709,6 @@ static void rxrpc_input_ack_trailer(struct rxrpc_call *call, struct sk_buff *skb
|
||||||
call->tx_winsize = rwind;
|
call->tx_winsize = rwind;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (call->cong_ssthresh > rwind)
|
|
||||||
call->cong_ssthresh = rwind;
|
|
||||||
|
|
||||||
mtu = min(ntohl(trailer->maxMTU), ntohl(trailer->ifMTU));
|
mtu = min(ntohl(trailer->maxMTU), ntohl(trailer->ifMTU));
|
||||||
|
|
||||||
peer = call->peer;
|
peer = call->peer;
|
||||||
|
|
|
@ -209,13 +209,18 @@ int smc_ib_find_route(struct net *net, __be32 saddr, __be32 daddr,
|
||||||
if (IS_ERR(rt))
|
if (IS_ERR(rt))
|
||||||
goto out;
|
goto out;
|
||||||
if (rt->rt_uses_gateway && rt->rt_gw_family != AF_INET)
|
if (rt->rt_uses_gateway && rt->rt_gw_family != AF_INET)
|
||||||
goto out;
|
goto out_rt;
|
||||||
neigh = rt->dst.ops->neigh_lookup(&rt->dst, NULL, &fl4.daddr);
|
neigh = dst_neigh_lookup(&rt->dst, &fl4.daddr);
|
||||||
if (neigh) {
|
if (!neigh)
|
||||||
memcpy(nexthop_mac, neigh->ha, ETH_ALEN);
|
goto out_rt;
|
||||||
*uses_gateway = rt->rt_uses_gateway;
|
memcpy(nexthop_mac, neigh->ha, ETH_ALEN);
|
||||||
return 0;
|
*uses_gateway = rt->rt_uses_gateway;
|
||||||
}
|
neigh_release(neigh);
|
||||||
|
ip_rt_put(rt);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
out_rt:
|
||||||
|
ip_rt_put(rt);
|
||||||
out:
|
out:
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -389,11 +389,15 @@ static int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb)
|
||||||
*/
|
*/
|
||||||
static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb)
|
static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
|
struct xfrm_offload *xo = xfrm_offload(skb);
|
||||||
int ihl = skb->data - skb_transport_header(skb);
|
int ihl = skb->data - skb_transport_header(skb);
|
||||||
|
|
||||||
if (skb->transport_header != skb->network_header) {
|
if (skb->transport_header != skb->network_header) {
|
||||||
memmove(skb_transport_header(skb),
|
memmove(skb_transport_header(skb),
|
||||||
skb_network_header(skb), ihl);
|
skb_network_header(skb), ihl);
|
||||||
|
if (xo)
|
||||||
|
xo->orig_mac_len =
|
||||||
|
skb_mac_header_was_set(skb) ? skb_mac_header_len(skb) : 0;
|
||||||
skb->network_header = skb->transport_header;
|
skb->network_header = skb->transport_header;
|
||||||
}
|
}
|
||||||
ip_hdr(skb)->tot_len = htons(skb->len + ihl);
|
ip_hdr(skb)->tot_len = htons(skb->len + ihl);
|
||||||
|
@ -404,11 +408,15 @@ static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb)
|
||||||
static int xfrm6_transport_input(struct xfrm_state *x, struct sk_buff *skb)
|
static int xfrm6_transport_input(struct xfrm_state *x, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
#if IS_ENABLED(CONFIG_IPV6)
|
#if IS_ENABLED(CONFIG_IPV6)
|
||||||
|
struct xfrm_offload *xo = xfrm_offload(skb);
|
||||||
int ihl = skb->data - skb_transport_header(skb);
|
int ihl = skb->data - skb_transport_header(skb);
|
||||||
|
|
||||||
if (skb->transport_header != skb->network_header) {
|
if (skb->transport_header != skb->network_header) {
|
||||||
memmove(skb_transport_header(skb),
|
memmove(skb_transport_header(skb),
|
||||||
skb_network_header(skb), ihl);
|
skb_network_header(skb), ihl);
|
||||||
|
if (xo)
|
||||||
|
xo->orig_mac_len =
|
||||||
|
skb_mac_header_was_set(skb) ? skb_mac_header_len(skb) : 0;
|
||||||
skb->network_header = skb->transport_header;
|
skb->network_header = skb->transport_header;
|
||||||
}
|
}
|
||||||
ipv6_hdr(skb)->payload_len = htons(skb->len + ihl -
|
ipv6_hdr(skb)->payload_len = htons(skb->len + ihl -
|
||||||
|
|
|
@ -3593,6 +3593,8 @@ xfrm_policy *xfrm_in_fwd_icmp(struct sk_buff *skb,
|
||||||
return pol;
|
return pol;
|
||||||
|
|
||||||
pol = xfrm_policy_lookup(net, &fl1, family, XFRM_POLICY_FWD, if_id);
|
pol = xfrm_policy_lookup(net, &fl1, family, XFRM_POLICY_FWD, if_id);
|
||||||
|
if (IS_ERR(pol))
|
||||||
|
pol = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pol;
|
return pol;
|
||||||
|
|
|
@ -154,17 +154,9 @@ setup_topo()
|
||||||
setup_topo_ns $ns
|
setup_topo_ns $ns
|
||||||
done
|
done
|
||||||
|
|
||||||
ip link add name veth0 type veth peer name veth1
|
ip -n $h1 link add name eth0 type veth peer name swp1 netns $sw1
|
||||||
ip link set dev veth0 netns $h1 name eth0
|
ip -n $sw1 link add name veth0 type veth peer name veth0 netns $sw2
|
||||||
ip link set dev veth1 netns $sw1 name swp1
|
ip -n $h2 link add name eth0 type veth peer name swp1 netns $sw2
|
||||||
|
|
||||||
ip link add name veth0 type veth peer name veth1
|
|
||||||
ip link set dev veth0 netns $sw1 name veth0
|
|
||||||
ip link set dev veth1 netns $sw2 name veth0
|
|
||||||
|
|
||||||
ip link add name veth0 type veth peer name veth1
|
|
||||||
ip link set dev veth0 netns $h2 name eth0
|
|
||||||
ip link set dev veth1 netns $sw2 name swp1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_host_common()
|
setup_host_common()
|
||||||
|
|
Loading…
Reference in New Issue