mirror of
https://github.com/torvalds/linux.git
synced 2026-01-25 07:47:50 +00:00
Merge tag 'net-6.17-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Pull networking fixes from Paolo Abeni:
"Including fixes from Bluetooth, IPsec and CAN.
No known regressions at this point.
Current release - regressions:
- xfrm: xfrm_alloc_spi shouldn't use 0 as SPI
Previous releases - regressions:
- xfrm: fix offloading of cross-family tunnels
- bluetooth: fix several races leading to UaFs
- dsa: lantiq_gswip: fix FDB entries creation for the CPU port
- eth:
- tun: update napi->skb after XDP process
- mlx: fix UAF in flow counter release
Previous releases - always broken:
- core: forbid FDB status change while nexthop is in a group
- smc: fix warning in smc_rx_splice() when calling get_page()
- can: provide missing ndo_change_mtu(), to prevent buffer overflow.
- eth:
- i40e: fix VF config validation
- broadcom: fix support for PTP_EXTTS_REQUEST2 ioctl"
* tag 'net-6.17-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (40 commits)
octeontx2-pf: Fix potential use after free in otx2_tc_add_flow()
net: dsa: lantiq_gswip: suppress -EINVAL errors for bridge FDB entries added to the CPU port
net: dsa: lantiq_gswip: move gswip_add_single_port_br() call to port_setup()
libie: fix string names for AQ error codes
net/mlx5e: Fix missing FEC RS stats for RS_544_514_INTERLEAVED_QUAD
net/mlx5: HWS, ignore flow level for multi-dest table
net/mlx5: fs, fix UAF in flow counter release
selftests: fib_nexthops: Add test cases for FDB status change
selftests: fib_nexthops: Fix creation of non-FDB nexthops
nexthop: Forbid FDB status change while nexthop is in a group
net: allow alloc_skb_with_frags() to use MAX_SKB_FRAGS
bnxt_en: correct offset handling for IPv6 destination address
ptp: document behavior of PTP_STRICT_FLAGS
broadcom: fix support for PTP_EXTTS_REQUEST2 ioctl
broadcom: fix support for PTP_PEROUT_DUTY_CYCLE
Bluetooth: MGMT: Fix possible UAFs
Bluetooth: hci_event: Fix UAF in hci_acl_create_conn_sync
Bluetooth: hci_event: Fix UAF in hci_conn_tx_dequeue
Bluetooth: hci_sync: Fix hci_resume_advertising_sync
Bluetooth: Fix build after header cleanup
...
This commit is contained in:
@@ -312,7 +312,9 @@ config BT_HCIBCM4377
|
||||
|
||||
config BT_HCIBPA10X
|
||||
tristate "HCI BPA10x USB driver"
|
||||
depends on BT_HCIUART
|
||||
depends on USB
|
||||
select BT_HCIUART_H4
|
||||
help
|
||||
Bluetooth HCI BPA10x USB driver.
|
||||
This driver provides support for the Digianswer BPA 100/105 Bluetooth
|
||||
@@ -437,8 +439,10 @@ config BT_MTKSDIO
|
||||
|
||||
config BT_MTKUART
|
||||
tristate "MediaTek HCI UART driver"
|
||||
depends on BT_HCIUART
|
||||
depends on SERIAL_DEV_BUS
|
||||
depends on USB || !BT_HCIBTUSB_MTK
|
||||
select BT_HCIUART_H4
|
||||
select BT_MTK
|
||||
help
|
||||
MediaTek Bluetooth HCI UART driver.
|
||||
@@ -483,7 +487,9 @@ config BT_VIRTIO
|
||||
|
||||
config BT_NXPUART
|
||||
tristate "NXP protocol support"
|
||||
depends on BT_HCIUART
|
||||
depends on SERIAL_DEV_BUS
|
||||
select BT_HCIUART_H4
|
||||
select CRC32
|
||||
select CRC8
|
||||
help
|
||||
|
||||
@@ -121,10 +121,6 @@ void hci_uart_set_flow_control(struct hci_uart *hu, bool enable);
|
||||
void hci_uart_set_speeds(struct hci_uart *hu, unsigned int init_speed,
|
||||
unsigned int oper_speed);
|
||||
|
||||
#ifdef CONFIG_BT_HCIUART_H4
|
||||
int h4_init(void);
|
||||
int h4_deinit(void);
|
||||
|
||||
struct h4_recv_pkt {
|
||||
u8 type; /* Packet type */
|
||||
u8 hlen; /* Header length */
|
||||
@@ -162,6 +158,10 @@ struct h4_recv_pkt {
|
||||
.lsize = 2, \
|
||||
.maxlen = HCI_MAX_FRAME_SIZE \
|
||||
|
||||
#ifdef CONFIG_BT_HCIUART_H4
|
||||
int h4_init(void);
|
||||
int h4_deinit(void);
|
||||
|
||||
struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb,
|
||||
const unsigned char *buffer, int count,
|
||||
const struct h4_recv_pkt *pkts, int pkts_count);
|
||||
|
||||
@@ -823,9 +823,6 @@ static int rcar_canfd_reset_controller(struct rcar_canfd_global *gpriv)
|
||||
/* Reset Global error flags */
|
||||
rcar_canfd_write(gpriv->base, RCANFD_GERFL, 0x0);
|
||||
|
||||
/* Set the controller into appropriate mode */
|
||||
rcar_canfd_set_mode(gpriv);
|
||||
|
||||
/* Transition all Channels to reset mode */
|
||||
for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) {
|
||||
rcar_canfd_clear_bit(gpriv->base,
|
||||
@@ -844,6 +841,10 @@ static int rcar_canfd_reset_controller(struct rcar_canfd_global *gpriv)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the controller into appropriate mode */
|
||||
rcar_canfd_set_mode(gpriv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -545,8 +545,6 @@ static int hi3110_stop(struct net_device *net)
|
||||
|
||||
priv->force_quit = 1;
|
||||
free_irq(spi->irq, priv);
|
||||
destroy_workqueue(priv->wq);
|
||||
priv->wq = NULL;
|
||||
|
||||
mutex_lock(&priv->hi3110_lock);
|
||||
|
||||
@@ -770,34 +768,23 @@ static int hi3110_open(struct net_device *net)
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
priv->wq = alloc_workqueue("hi3110_wq", WQ_FREEZABLE | WQ_MEM_RECLAIM,
|
||||
0);
|
||||
if (!priv->wq) {
|
||||
ret = -ENOMEM;
|
||||
goto out_free_irq;
|
||||
}
|
||||
INIT_WORK(&priv->tx_work, hi3110_tx_work_handler);
|
||||
INIT_WORK(&priv->restart_work, hi3110_restart_work_handler);
|
||||
|
||||
ret = hi3110_hw_reset(spi);
|
||||
if (ret)
|
||||
goto out_free_wq;
|
||||
goto out_free_irq;
|
||||
|
||||
ret = hi3110_setup(net);
|
||||
if (ret)
|
||||
goto out_free_wq;
|
||||
goto out_free_irq;
|
||||
|
||||
ret = hi3110_set_normal_mode(spi);
|
||||
if (ret)
|
||||
goto out_free_wq;
|
||||
goto out_free_irq;
|
||||
|
||||
netif_wake_queue(net);
|
||||
mutex_unlock(&priv->hi3110_lock);
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_wq:
|
||||
destroy_workqueue(priv->wq);
|
||||
out_free_irq:
|
||||
free_irq(spi->irq, priv);
|
||||
hi3110_hw_sleep(spi);
|
||||
@@ -812,6 +799,7 @@ static const struct net_device_ops hi3110_netdev_ops = {
|
||||
.ndo_open = hi3110_open,
|
||||
.ndo_stop = hi3110_stop,
|
||||
.ndo_start_xmit = hi3110_hard_start_xmit,
|
||||
.ndo_change_mtu = can_change_mtu,
|
||||
};
|
||||
|
||||
static const struct ethtool_ops hi3110_ethtool_ops = {
|
||||
@@ -908,6 +896,15 @@ static int hi3110_can_probe(struct spi_device *spi)
|
||||
if (ret)
|
||||
goto out_clk;
|
||||
|
||||
priv->wq = alloc_workqueue("hi3110_wq", WQ_FREEZABLE | WQ_MEM_RECLAIM,
|
||||
0);
|
||||
if (!priv->wq) {
|
||||
ret = -ENOMEM;
|
||||
goto out_clk;
|
||||
}
|
||||
INIT_WORK(&priv->tx_work, hi3110_tx_work_handler);
|
||||
INIT_WORK(&priv->restart_work, hi3110_restart_work_handler);
|
||||
|
||||
priv->spi = spi;
|
||||
mutex_init(&priv->hi3110_lock);
|
||||
|
||||
@@ -943,6 +940,8 @@ static int hi3110_can_probe(struct spi_device *spi)
|
||||
return 0;
|
||||
|
||||
error_probe:
|
||||
destroy_workqueue(priv->wq);
|
||||
priv->wq = NULL;
|
||||
hi3110_power_enable(priv->power, 0);
|
||||
|
||||
out_clk:
|
||||
@@ -963,6 +962,9 @@ static void hi3110_can_remove(struct spi_device *spi)
|
||||
|
||||
hi3110_power_enable(priv->power, 0);
|
||||
|
||||
destroy_workqueue(priv->wq);
|
||||
priv->wq = NULL;
|
||||
|
||||
clk_disable_unprepare(priv->clk);
|
||||
|
||||
free_candev(net);
|
||||
|
||||
@@ -768,6 +768,7 @@ static const struct net_device_ops sun4ican_netdev_ops = {
|
||||
.ndo_open = sun4ican_open,
|
||||
.ndo_stop = sun4ican_close,
|
||||
.ndo_start_xmit = sun4ican_start_xmit,
|
||||
.ndo_change_mtu = can_change_mtu,
|
||||
};
|
||||
|
||||
static const struct ethtool_ops sun4ican_ethtool_ops = {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* Copyright (c) 2019 Robert Bosch Engineering and Business Solutions. All rights reserved.
|
||||
* Copyright (c) 2020 ETAS K.K.. All rights reserved.
|
||||
* Copyright (c) 2020-2022 Vincent Mailhol <mailhol.vincent@wanadoo.fr>
|
||||
* Copyright (c) 2020-2025 Vincent Mailhol <mailhol@kernel.org>
|
||||
*/
|
||||
|
||||
#include <linux/unaligned.h>
|
||||
@@ -1977,6 +1977,7 @@ static const struct net_device_ops es58x_netdev_ops = {
|
||||
.ndo_stop = es58x_stop,
|
||||
.ndo_start_xmit = es58x_start_xmit,
|
||||
.ndo_eth_ioctl = can_eth_ioctl_hwts,
|
||||
.ndo_change_mtu = can_change_mtu,
|
||||
};
|
||||
|
||||
static const struct ethtool_ops es58x_ethtool_ops = {
|
||||
|
||||
@@ -761,6 +761,7 @@ static const struct net_device_ops mcba_netdev_ops = {
|
||||
.ndo_open = mcba_usb_open,
|
||||
.ndo_stop = mcba_usb_close,
|
||||
.ndo_start_xmit = mcba_usb_start_xmit,
|
||||
.ndo_change_mtu = can_change_mtu,
|
||||
};
|
||||
|
||||
static const struct ethtool_ops mcba_ethtool_ops = {
|
||||
|
||||
@@ -111,7 +111,7 @@ void peak_usb_update_ts_now(struct peak_time_ref *time_ref, u32 ts_now)
|
||||
u32 delta_ts = time_ref->ts_dev_2 - time_ref->ts_dev_1;
|
||||
|
||||
if (time_ref->ts_dev_2 < time_ref->ts_dev_1)
|
||||
delta_ts &= (1 << time_ref->adapter->ts_used_bits) - 1;
|
||||
delta_ts &= (1ULL << time_ref->adapter->ts_used_bits) - 1;
|
||||
|
||||
time_ref->ts_total += delta_ts;
|
||||
}
|
||||
|
||||
@@ -685,18 +685,27 @@ static int gswip_add_single_port_br(struct gswip_priv *priv, int port, bool add)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gswip_port_enable(struct dsa_switch *ds, int port,
|
||||
struct phy_device *phydev)
|
||||
static int gswip_port_setup(struct dsa_switch *ds, int port)
|
||||
{
|
||||
struct gswip_priv *priv = ds->priv;
|
||||
int err;
|
||||
|
||||
if (!dsa_is_cpu_port(ds, port)) {
|
||||
u32 mdio_phy = 0;
|
||||
|
||||
err = gswip_add_single_port_br(priv, port, true);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gswip_port_enable(struct dsa_switch *ds, int port,
|
||||
struct phy_device *phydev)
|
||||
{
|
||||
struct gswip_priv *priv = ds->priv;
|
||||
|
||||
if (!dsa_is_cpu_port(ds, port)) {
|
||||
u32 mdio_phy = 0;
|
||||
|
||||
if (phydev)
|
||||
mdio_phy = phydev->mdio.addr & GSWIP_MDIO_PHY_ADDR_MASK;
|
||||
@@ -1359,8 +1368,9 @@ static int gswip_port_fdb(struct dsa_switch *ds, int port,
|
||||
int i;
|
||||
int err;
|
||||
|
||||
/* Operation not supported on the CPU port, don't throw errors */
|
||||
if (!bridge)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
|
||||
for (i = max_ports; i < ARRAY_SIZE(priv->vlans); i++) {
|
||||
if (priv->vlans[i].bridge == bridge) {
|
||||
@@ -1829,6 +1839,7 @@ static const struct phylink_mac_ops gswip_phylink_mac_ops = {
|
||||
static const struct dsa_switch_ops gswip_xrx200_switch_ops = {
|
||||
.get_tag_protocol = gswip_get_tag_protocol,
|
||||
.setup = gswip_setup,
|
||||
.port_setup = gswip_port_setup,
|
||||
.port_enable = gswip_port_enable,
|
||||
.port_disable = gswip_port_disable,
|
||||
.port_bridge_join = gswip_port_bridge_join,
|
||||
|
||||
@@ -244,7 +244,7 @@ bnxt_tc_parse_pedit(struct bnxt *bp, struct bnxt_tc_actions *actions,
|
||||
offset < offset_of_ip6_daddr + 16) {
|
||||
actions->nat.src_xlate = false;
|
||||
idx = (offset - offset_of_ip6_daddr) / 4;
|
||||
actions->nat.l3.ipv6.saddr.s6_addr32[idx] = htonl(val);
|
||||
actions->nat.l3.ipv6.daddr.s6_addr32[idx] = htonl(val);
|
||||
} else {
|
||||
netdev_err(bp->dev,
|
||||
"%s: IPv6_hdr: Invalid pedit field\n",
|
||||
|
||||
@@ -1278,7 +1278,8 @@ struct i40e_mac_filter *i40e_add_mac_filter(struct i40e_vsi *vsi,
|
||||
const u8 *macaddr);
|
||||
int i40e_del_mac_filter(struct i40e_vsi *vsi, const u8 *macaddr);
|
||||
bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi);
|
||||
int i40e_count_filters(struct i40e_vsi *vsi);
|
||||
int i40e_count_all_filters(struct i40e_vsi *vsi);
|
||||
int i40e_count_active_filters(struct i40e_vsi *vsi);
|
||||
struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, const u8 *macaddr);
|
||||
void i40e_vlan_stripping_enable(struct i40e_vsi *vsi);
|
||||
static inline bool i40e_is_sw_dcb(struct i40e_pf *pf)
|
||||
|
||||
@@ -1243,12 +1243,30 @@ void i40e_update_stats(struct i40e_vsi *vsi)
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_count_filters - counts VSI mac filters
|
||||
* i40e_count_all_filters - counts VSI MAC filters
|
||||
* @vsi: the VSI to be searched
|
||||
*
|
||||
* Returns count of mac filters
|
||||
**/
|
||||
int i40e_count_filters(struct i40e_vsi *vsi)
|
||||
* Return: count of MAC filters in any state.
|
||||
*/
|
||||
int i40e_count_all_filters(struct i40e_vsi *vsi)
|
||||
{
|
||||
struct i40e_mac_filter *f;
|
||||
struct hlist_node *h;
|
||||
int bkt, cnt = 0;
|
||||
|
||||
hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist)
|
||||
cnt++;
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_count_active_filters - counts VSI MAC filters
|
||||
* @vsi: the VSI to be searched
|
||||
*
|
||||
* Return: count of active MAC filters.
|
||||
*/
|
||||
int i40e_count_active_filters(struct i40e_vsi *vsi)
|
||||
{
|
||||
struct i40e_mac_filter *f;
|
||||
struct hlist_node *h;
|
||||
|
||||
@@ -448,7 +448,7 @@ static void i40e_config_irq_link_list(struct i40e_vf *vf, u16 vsi_id,
|
||||
(qtype << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT) |
|
||||
(pf_queue_id << I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) |
|
||||
BIT(I40E_QINT_RQCTL_CAUSE_ENA_SHIFT) |
|
||||
(itr_idx << I40E_QINT_RQCTL_ITR_INDX_SHIFT);
|
||||
FIELD_PREP(I40E_QINT_RQCTL_ITR_INDX_MASK, itr_idx);
|
||||
wr32(hw, reg_idx, reg);
|
||||
}
|
||||
|
||||
@@ -653,6 +653,13 @@ static int i40e_config_vsi_tx_queue(struct i40e_vf *vf, u16 vsi_id,
|
||||
|
||||
/* only set the required fields */
|
||||
tx_ctx.base = info->dma_ring_addr / 128;
|
||||
|
||||
/* ring_len has to be multiple of 8 */
|
||||
if (!IS_ALIGNED(info->ring_len, 8) ||
|
||||
info->ring_len > I40E_MAX_NUM_DESCRIPTORS_XL710) {
|
||||
ret = -EINVAL;
|
||||
goto error_context;
|
||||
}
|
||||
tx_ctx.qlen = info->ring_len;
|
||||
tx_ctx.rdylist = le16_to_cpu(vsi->info.qs_handle[0]);
|
||||
tx_ctx.rdylist_act = 0;
|
||||
@@ -716,6 +723,13 @@ static int i40e_config_vsi_rx_queue(struct i40e_vf *vf, u16 vsi_id,
|
||||
|
||||
/* only set the required fields */
|
||||
rx_ctx.base = info->dma_ring_addr / 128;
|
||||
|
||||
/* ring_len has to be multiple of 32 */
|
||||
if (!IS_ALIGNED(info->ring_len, 32) ||
|
||||
info->ring_len > I40E_MAX_NUM_DESCRIPTORS_XL710) {
|
||||
ret = -EINVAL;
|
||||
goto error_param;
|
||||
}
|
||||
rx_ctx.qlen = info->ring_len;
|
||||
|
||||
if (info->splithdr_enabled) {
|
||||
@@ -1450,6 +1464,7 @@ static void i40e_trigger_vf_reset(struct i40e_vf *vf, bool flr)
|
||||
* functions that may still be running at this point.
|
||||
*/
|
||||
clear_bit(I40E_VF_STATE_INIT, &vf->vf_states);
|
||||
clear_bit(I40E_VF_STATE_RESOURCES_LOADED, &vf->vf_states);
|
||||
|
||||
/* In the case of a VFLR, the HW has already reset the VF and we
|
||||
* just need to clean up, so don't hit the VFRTRIG register.
|
||||
@@ -2116,7 +2131,10 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg)
|
||||
size_t len = 0;
|
||||
int ret;
|
||||
|
||||
if (!i40e_sync_vf_state(vf, I40E_VF_STATE_INIT)) {
|
||||
i40e_sync_vf_state(vf, I40E_VF_STATE_INIT);
|
||||
|
||||
if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states) ||
|
||||
test_bit(I40E_VF_STATE_RESOURCES_LOADED, &vf->vf_states)) {
|
||||
aq_ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
@@ -2219,6 +2237,7 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg)
|
||||
vf->default_lan_addr.addr);
|
||||
}
|
||||
set_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states);
|
||||
set_bit(I40E_VF_STATE_RESOURCES_LOADED, &vf->vf_states);
|
||||
|
||||
err:
|
||||
/* send the response back to the VF */
|
||||
@@ -2381,7 +2400,7 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg)
|
||||
}
|
||||
|
||||
if (vf->adq_enabled) {
|
||||
if (idx >= ARRAY_SIZE(vf->ch)) {
|
||||
if (idx >= vf->num_tc) {
|
||||
aq_ret = -ENODEV;
|
||||
goto error_param;
|
||||
}
|
||||
@@ -2402,7 +2421,7 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg)
|
||||
* to its appropriate VSIs based on TC mapping
|
||||
*/
|
||||
if (vf->adq_enabled) {
|
||||
if (idx >= ARRAY_SIZE(vf->ch)) {
|
||||
if (idx >= vf->num_tc) {
|
||||
aq_ret = -ENODEV;
|
||||
goto error_param;
|
||||
}
|
||||
@@ -2452,8 +2471,10 @@ static int i40e_validate_queue_map(struct i40e_vf *vf, u16 vsi_id,
|
||||
u16 vsi_queue_id, queue_id;
|
||||
|
||||
for_each_set_bit(vsi_queue_id, &queuemap, I40E_MAX_VSI_QP) {
|
||||
if (vf->adq_enabled) {
|
||||
vsi_id = vf->ch[vsi_queue_id / I40E_MAX_VF_VSI].vsi_id;
|
||||
u16 idx = vsi_queue_id / I40E_MAX_VF_VSI;
|
||||
|
||||
if (vf->adq_enabled && idx < vf->num_tc) {
|
||||
vsi_id = vf->ch[idx].vsi_id;
|
||||
queue_id = (vsi_queue_id % I40E_DEFAULT_QUEUES_PER_VF);
|
||||
} else {
|
||||
queue_id = vsi_queue_id;
|
||||
@@ -2841,24 +2862,6 @@ error_param:
|
||||
(u8 *)&stats, sizeof(stats));
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_can_vf_change_mac
|
||||
* @vf: pointer to the VF info
|
||||
*
|
||||
* Return true if the VF is allowed to change its MAC filters, false otherwise
|
||||
*/
|
||||
static bool i40e_can_vf_change_mac(struct i40e_vf *vf)
|
||||
{
|
||||
/* If the VF MAC address has been set administratively (via the
|
||||
* ndo_set_vf_mac command), then deny permission to the VF to
|
||||
* add/delete unicast MAC addresses, unless the VF is trusted
|
||||
*/
|
||||
if (vf->pf_set_mac && !vf->trusted)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define I40E_MAX_MACVLAN_PER_HW 3072
|
||||
#define I40E_MAX_MACVLAN_PER_PF(num_ports) (I40E_MAX_MACVLAN_PER_HW / \
|
||||
(num_ports))
|
||||
@@ -2897,8 +2900,10 @@ static inline int i40e_check_vf_permission(struct i40e_vf *vf,
|
||||
struct i40e_pf *pf = vf->pf;
|
||||
struct i40e_vsi *vsi = pf->vsi[vf->lan_vsi_idx];
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
int mac2add_cnt = 0;
|
||||
int i;
|
||||
int i, mac_add_max, mac_add_cnt = 0;
|
||||
bool vf_trusted;
|
||||
|
||||
vf_trusted = test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps);
|
||||
|
||||
for (i = 0; i < al->num_elements; i++) {
|
||||
struct i40e_mac_filter *f;
|
||||
@@ -2918,9 +2923,8 @@ static inline int i40e_check_vf_permission(struct i40e_vf *vf,
|
||||
* The VF may request to set the MAC address filter already
|
||||
* assigned to it so do not return an error in that case.
|
||||
*/
|
||||
if (!i40e_can_vf_change_mac(vf) &&
|
||||
!is_multicast_ether_addr(addr) &&
|
||||
!ether_addr_equal(addr, vf->default_lan_addr.addr)) {
|
||||
if (!vf_trusted && !is_multicast_ether_addr(addr) &&
|
||||
vf->pf_set_mac && !ether_addr_equal(addr, vf->default_lan_addr.addr)) {
|
||||
dev_err(&pf->pdev->dev,
|
||||
"VF attempting to override administratively set MAC address, bring down and up the VF interface to resume normal operation\n");
|
||||
return -EPERM;
|
||||
@@ -2929,29 +2933,33 @@ static inline int i40e_check_vf_permission(struct i40e_vf *vf,
|
||||
/*count filters that really will be added*/
|
||||
f = i40e_find_mac(vsi, addr);
|
||||
if (!f)
|
||||
++mac2add_cnt;
|
||||
++mac_add_cnt;
|
||||
}
|
||||
|
||||
/* If this VF is not privileged, then we can't add more than a limited
|
||||
* number of addresses. Check to make sure that the additions do not
|
||||
* push us over the limit.
|
||||
*/
|
||||
if (!test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps)) {
|
||||
if ((i40e_count_filters(vsi) + mac2add_cnt) >
|
||||
I40E_VC_MAX_MAC_ADDR_PER_VF) {
|
||||
dev_err(&pf->pdev->dev,
|
||||
"Cannot add more MAC addresses, VF is not trusted, switch the VF to trusted to add more functionality\n");
|
||||
return -EPERM;
|
||||
}
|
||||
/* If this VF is trusted, it can use more resources than untrusted.
|
||||
* number of addresses.
|
||||
*
|
||||
* If this VF is trusted, it can use more resources than untrusted.
|
||||
* However to ensure that every trusted VF has appropriate number of
|
||||
* resources, divide whole pool of resources per port and then across
|
||||
* all VFs.
|
||||
*/
|
||||
} else {
|
||||
if ((i40e_count_filters(vsi) + mac2add_cnt) >
|
||||
I40E_VC_MAX_MACVLAN_PER_TRUSTED_VF(pf->num_alloc_vfs,
|
||||
hw->num_ports)) {
|
||||
if (!vf_trusted)
|
||||
mac_add_max = I40E_VC_MAX_MAC_ADDR_PER_VF;
|
||||
else
|
||||
mac_add_max = I40E_VC_MAX_MACVLAN_PER_TRUSTED_VF(pf->num_alloc_vfs, hw->num_ports);
|
||||
|
||||
/* VF can replace all its filters in one step, in this case mac_add_max
|
||||
* will be added as active and another mac_add_max will be in
|
||||
* a to-be-removed state. Account for that.
|
||||
*/
|
||||
if ((i40e_count_active_filters(vsi) + mac_add_cnt) > mac_add_max ||
|
||||
(i40e_count_all_filters(vsi) + mac_add_cnt) > 2 * mac_add_max) {
|
||||
if (!vf_trusted) {
|
||||
dev_err(&pf->pdev->dev,
|
||||
"Cannot add more MAC addresses, VF is not trusted, switch the VF to trusted to add more functionality\n");
|
||||
return -EPERM;
|
||||
} else {
|
||||
dev_err(&pf->pdev->dev,
|
||||
"Cannot add more MAC addresses, trusted VF exhausted it's resources\n");
|
||||
return -EPERM;
|
||||
@@ -3587,7 +3595,7 @@ static int i40e_validate_cloud_filter(struct i40e_vf *vf,
|
||||
|
||||
/* action_meta is TC number here to which the filter is applied */
|
||||
if (!tc_filter->action_meta ||
|
||||
tc_filter->action_meta > vf->num_tc) {
|
||||
tc_filter->action_meta >= vf->num_tc) {
|
||||
dev_info(&pf->pdev->dev, "VF %d: Invalid TC number %u\n",
|
||||
vf->vf_id, tc_filter->action_meta);
|
||||
goto err;
|
||||
@@ -3884,6 +3892,8 @@ err:
|
||||
aq_ret);
|
||||
}
|
||||
|
||||
#define I40E_MAX_VF_CLOUD_FILTER 0xFF00
|
||||
|
||||
/**
|
||||
* i40e_vc_add_cloud_filter
|
||||
* @vf: pointer to the VF info
|
||||
@@ -3923,6 +3933,14 @@ static int i40e_vc_add_cloud_filter(struct i40e_vf *vf, u8 *msg)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (vf->num_cloud_filters >= I40E_MAX_VF_CLOUD_FILTER) {
|
||||
dev_warn(&pf->pdev->dev,
|
||||
"VF %d: Max number of filters reached, can't apply cloud filter\n",
|
||||
vf->vf_id);
|
||||
aq_ret = -ENOSPC;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
cfilter = kzalloc(sizeof(*cfilter), GFP_KERNEL);
|
||||
if (!cfilter) {
|
||||
aq_ret = -ENOMEM;
|
||||
|
||||
@@ -41,7 +41,8 @@ enum i40e_vf_states {
|
||||
I40E_VF_STATE_MC_PROMISC,
|
||||
I40E_VF_STATE_UC_PROMISC,
|
||||
I40E_VF_STATE_PRE_ENABLE,
|
||||
I40E_VF_STATE_RESETTING
|
||||
I40E_VF_STATE_RESETTING,
|
||||
I40E_VF_STATE_RESOURCES_LOADED,
|
||||
};
|
||||
|
||||
/* VF capabilities */
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
static const char * const libie_aq_str_arr[] = {
|
||||
#define LIBIE_AQ_STR(x) \
|
||||
[LIBIE_AQ_RC_##x] = "LIBIE_AQ_RC" #x
|
||||
[LIBIE_AQ_RC_##x] = "LIBIE_AQ_RC_" #x
|
||||
LIBIE_AQ_STR(OK),
|
||||
LIBIE_AQ_STR(EPERM),
|
||||
LIBIE_AQ_STR(ENOENT),
|
||||
|
||||
@@ -21,8 +21,7 @@
|
||||
#include "rvu.h"
|
||||
#include "lmac_common.h"
|
||||
|
||||
#define DRV_NAME "Marvell-CGX/RPM"
|
||||
#define DRV_STRING "Marvell CGX/RPM Driver"
|
||||
#define DRV_NAME "Marvell-CGX-RPM"
|
||||
|
||||
#define CGX_RX_STAT_GLOBAL_INDEX 9
|
||||
|
||||
|
||||
@@ -1326,7 +1326,6 @@ static int otx2_tc_add_flow(struct otx2_nic *nic,
|
||||
|
||||
free_leaf:
|
||||
otx2_tc_del_from_flow_list(flow_cfg, new_node);
|
||||
kfree_rcu(new_node, rcu);
|
||||
if (new_node->is_act_police) {
|
||||
mutex_lock(&nic->mbox.lock);
|
||||
|
||||
@@ -1346,6 +1345,7 @@ free_leaf:
|
||||
|
||||
mutex_unlock(&nic->mbox.lock);
|
||||
}
|
||||
kfree_rcu(new_node, rcu);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1466,6 +1466,7 @@ static void fec_set_block_stats(struct mlx5e_priv *priv,
|
||||
case MLX5E_FEC_RS_528_514:
|
||||
case MLX5E_FEC_RS_544_514:
|
||||
case MLX5E_FEC_LLRS_272_257_1:
|
||||
case MLX5E_FEC_RS_544_514_INTERLEAVED_QUAD:
|
||||
fec_set_rs_stats(fec_stats, out);
|
||||
return;
|
||||
case MLX5E_FEC_FIRECODE:
|
||||
|
||||
@@ -663,7 +663,7 @@ static void del_sw_hw_rule(struct fs_node *node)
|
||||
BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_ACTION) |
|
||||
BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_FLOW_COUNTERS);
|
||||
fte->act_dests.action.action &= ~MLX5_FLOW_CONTEXT_ACTION_COUNT;
|
||||
mlx5_fc_local_destroy(rule->dest_attr.counter);
|
||||
mlx5_fc_local_put(rule->dest_attr.counter);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
@@ -343,6 +343,7 @@ struct mlx5_fc {
|
||||
enum mlx5_fc_type type;
|
||||
struct mlx5_fc_bulk *bulk;
|
||||
struct mlx5_fc_cache cache;
|
||||
refcount_t fc_local_refcount;
|
||||
/* last{packets,bytes} are used for calculating deltas since last reading. */
|
||||
u64 lastpackets;
|
||||
u64 lastbytes;
|
||||
|
||||
@@ -562,17 +562,36 @@ mlx5_fc_local_create(u32 counter_id, u32 offset, u32 bulk_size)
|
||||
counter->id = counter_id;
|
||||
fc_bulk->base_id = counter_id - offset;
|
||||
fc_bulk->fs_bulk.bulk_len = bulk_size;
|
||||
refcount_set(&fc_bulk->hws_data.hws_action_refcount, 0);
|
||||
mutex_init(&fc_bulk->hws_data.lock);
|
||||
counter->bulk = fc_bulk;
|
||||
refcount_set(&counter->fc_local_refcount, 1);
|
||||
return counter;
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_fc_local_create);
|
||||
|
||||
void mlx5_fc_local_destroy(struct mlx5_fc *counter)
|
||||
{
|
||||
if (!counter || counter->type != MLX5_FC_TYPE_LOCAL)
|
||||
return;
|
||||
|
||||
kfree(counter->bulk);
|
||||
kfree(counter);
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_fc_local_destroy);
|
||||
|
||||
void mlx5_fc_local_get(struct mlx5_fc *counter)
|
||||
{
|
||||
if (!counter || counter->type != MLX5_FC_TYPE_LOCAL)
|
||||
return;
|
||||
|
||||
refcount_inc(&counter->fc_local_refcount);
|
||||
}
|
||||
|
||||
void mlx5_fc_local_put(struct mlx5_fc *counter)
|
||||
{
|
||||
if (!counter || counter->type != MLX5_FC_TYPE_LOCAL)
|
||||
return;
|
||||
|
||||
if (!refcount_dec_and_test(&counter->fc_local_refcount))
|
||||
return;
|
||||
|
||||
mlx5_fc_local_destroy(counter);
|
||||
}
|
||||
|
||||
@@ -1360,7 +1360,7 @@ free_action:
|
||||
struct mlx5hws_action *
|
||||
mlx5hws_action_create_dest_array(struct mlx5hws_context *ctx, size_t num_dest,
|
||||
struct mlx5hws_action_dest_attr *dests,
|
||||
bool ignore_flow_level, u32 flags)
|
||||
u32 flags)
|
||||
{
|
||||
struct mlx5hws_cmd_set_fte_dest *dest_list = NULL;
|
||||
struct mlx5hws_cmd_ft_create_attr ft_attr = {0};
|
||||
@@ -1397,7 +1397,7 @@ mlx5hws_action_create_dest_array(struct mlx5hws_context *ctx, size_t num_dest,
|
||||
MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
|
||||
dest_list[i].destination_id = dests[i].dest->dest_obj.obj_id;
|
||||
fte_attr.action_flags |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
|
||||
fte_attr.ignore_flow_level = ignore_flow_level;
|
||||
fte_attr.ignore_flow_level = 1;
|
||||
if (dests[i].is_wire_ft)
|
||||
last_dest_idx = i;
|
||||
break;
|
||||
|
||||
@@ -572,12 +572,12 @@ static void mlx5_fs_put_dest_action_sampler(struct mlx5_fs_hws_context *fs_ctx,
|
||||
static struct mlx5hws_action *
|
||||
mlx5_fs_create_action_dest_array(struct mlx5hws_context *ctx,
|
||||
struct mlx5hws_action_dest_attr *dests,
|
||||
u32 num_of_dests, bool ignore_flow_level)
|
||||
u32 num_of_dests)
|
||||
{
|
||||
u32 flags = MLX5HWS_ACTION_FLAG_HWS_FDB | MLX5HWS_ACTION_FLAG_SHARED;
|
||||
|
||||
return mlx5hws_action_create_dest_array(ctx, num_of_dests, dests,
|
||||
ignore_flow_level, flags);
|
||||
flags);
|
||||
}
|
||||
|
||||
static struct mlx5hws_action *
|
||||
@@ -1014,19 +1014,14 @@ static int mlx5_fs_fte_get_hws_actions(struct mlx5_flow_root_namespace *ns,
|
||||
}
|
||||
(*ractions)[num_actions++].action = dest_actions->dest;
|
||||
} else if (num_dest_actions > 1) {
|
||||
bool ignore_flow_level;
|
||||
|
||||
if (num_actions == MLX5_FLOW_CONTEXT_ACTION_MAX ||
|
||||
num_fs_actions == MLX5_FLOW_CONTEXT_ACTION_MAX) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto free_actions;
|
||||
}
|
||||
ignore_flow_level =
|
||||
!!(fte_action->flags & FLOW_ACT_IGNORE_FLOW_LEVEL);
|
||||
tmp_action =
|
||||
mlx5_fs_create_action_dest_array(ctx, dest_actions,
|
||||
num_dest_actions,
|
||||
ignore_flow_level);
|
||||
num_dest_actions);
|
||||
if (!tmp_action) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto free_actions;
|
||||
|
||||
@@ -407,15 +407,21 @@ struct mlx5hws_action *mlx5_fc_get_hws_action(struct mlx5hws_context *ctx,
|
||||
{
|
||||
struct mlx5_fs_hws_create_action_ctx create_ctx;
|
||||
struct mlx5_fc_bulk *fc_bulk = counter->bulk;
|
||||
struct mlx5hws_action *hws_action;
|
||||
|
||||
create_ctx.hws_ctx = ctx;
|
||||
create_ctx.id = fc_bulk->base_id;
|
||||
create_ctx.actions_type = MLX5HWS_ACTION_TYP_CTR;
|
||||
|
||||
return mlx5_fs_get_hws_action(&fc_bulk->hws_data, &create_ctx);
|
||||
mlx5_fc_local_get(counter);
|
||||
hws_action = mlx5_fs_get_hws_action(&fc_bulk->hws_data, &create_ctx);
|
||||
if (!hws_action)
|
||||
mlx5_fc_local_put(counter);
|
||||
return hws_action;
|
||||
}
|
||||
|
||||
void mlx5_fc_put_hws_action(struct mlx5_fc *counter)
|
||||
{
|
||||
mlx5_fs_put_hws_action(&counter->bulk->hws_data);
|
||||
mlx5_fc_local_put(counter);
|
||||
}
|
||||
|
||||
@@ -735,7 +735,6 @@ mlx5hws_action_create_push_vlan(struct mlx5hws_context *ctx, u32 flags);
|
||||
* @num_dest: The number of dests attributes.
|
||||
* @dests: The destination array. Each contains a destination action and can
|
||||
* have additional actions.
|
||||
* @ignore_flow_level: Whether to turn on 'ignore_flow_level' for this dest.
|
||||
* @flags: Action creation flags (enum mlx5hws_action_flags).
|
||||
*
|
||||
* Return: pointer to mlx5hws_action on success NULL otherwise.
|
||||
@@ -743,7 +742,7 @@ mlx5hws_action_create_push_vlan(struct mlx5hws_context *ctx, u32 flags);
|
||||
struct mlx5hws_action *
|
||||
mlx5hws_action_create_dest_array(struct mlx5hws_context *ctx, size_t num_dest,
|
||||
struct mlx5hws_action_dest_attr *dests,
|
||||
bool ignore_flow_level, u32 flags);
|
||||
u32 flags);
|
||||
|
||||
/**
|
||||
* mlx5hws_action_create_insert_header - Create insert header action.
|
||||
|
||||
@@ -597,10 +597,6 @@ static int bcm_ptp_perout_locked(struct bcm_ptp_private *priv,
|
||||
|
||||
period = BCM_MAX_PERIOD_8NS; /* write nonzero value */
|
||||
|
||||
/* Reject unsupported flags */
|
||||
if (req->flags & ~PTP_PEROUT_DUTY_CYCLE)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (req->flags & PTP_PEROUT_DUTY_CYCLE)
|
||||
pulse = ktime_to_ns(ktime_set(req->on.sec, req->on.nsec));
|
||||
else
|
||||
@@ -741,6 +737,8 @@ static const struct ptp_clock_info bcm_ptp_clock_info = {
|
||||
.n_pins = 1,
|
||||
.n_per_out = 1,
|
||||
.n_ext_ts = 1,
|
||||
.supported_perout_flags = PTP_PEROUT_DUTY_CYCLE,
|
||||
.supported_extts_flags = PTP_STRICT_FLAGS | PTP_RISING_EDGE,
|
||||
};
|
||||
|
||||
static void bcm_ptp_txtstamp(struct mii_timestamper *mii_ts,
|
||||
|
||||
@@ -1875,6 +1875,9 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
|
||||
local_bh_enable();
|
||||
goto unlock_frags;
|
||||
}
|
||||
|
||||
if (frags && skb != tfile->napi.skb)
|
||||
tfile->napi.skb = skb;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
local_bh_enable();
|
||||
|
||||
@@ -308,6 +308,8 @@ struct mlx5_fc *mlx5_fc_create(struct mlx5_core_dev *dev, bool aging);
|
||||
void mlx5_fc_destroy(struct mlx5_core_dev *dev, struct mlx5_fc *counter);
|
||||
struct mlx5_fc *mlx5_fc_local_create(u32 counter_id, u32 offset, u32 bulk_size);
|
||||
void mlx5_fc_local_destroy(struct mlx5_fc *counter);
|
||||
void mlx5_fc_local_get(struct mlx5_fc *counter);
|
||||
void mlx5_fc_local_put(struct mlx5_fc *counter);
|
||||
u64 mlx5_fc_query_lastuse(struct mlx5_fc *counter);
|
||||
void mlx5_fc_query_cached(struct mlx5_fc *counter,
|
||||
u64 *bytes, u64 *packets, u64 *lastuse);
|
||||
|
||||
@@ -1245,6 +1245,27 @@ static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct hci_conn *hci_conn_hash_lookup_role(struct hci_dev *hdev,
|
||||
__u8 type, __u8 role,
|
||||
bdaddr_t *ba)
|
||||
{
|
||||
struct hci_conn_hash *h = &hdev->conn_hash;
|
||||
struct hci_conn *c;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
list_for_each_entry_rcu(c, &h->list, list) {
|
||||
if (c->type == type && c->role == role && !bacmp(&c->dst, ba)) {
|
||||
rcu_read_unlock();
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct hci_conn *hci_conn_hash_lookup_le(struct hci_dev *hdev,
|
||||
bdaddr_t *ba,
|
||||
__u8 ba_type)
|
||||
|
||||
@@ -37,6 +37,9 @@
|
||||
|
||||
/*
|
||||
* flag fields valid for the new PTP_EXTTS_REQUEST2 ioctl.
|
||||
*
|
||||
* Note: PTP_STRICT_FLAGS is always enabled by the kernel for
|
||||
* PTP_EXTTS_REQUEST2 regardless of whether it is set by userspace.
|
||||
*/
|
||||
#define PTP_EXTTS_VALID_FLAGS (PTP_ENABLE_FEATURE | \
|
||||
PTP_RISING_EDGE | \
|
||||
|
||||
@@ -3087,8 +3087,18 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
/* Check for existing connection:
|
||||
*
|
||||
* 1. If it doesn't exist then it must be receiver/slave role.
|
||||
* 2. If it does exist confirm that it is connecting/BT_CONNECT in case
|
||||
* of initiator/master role since there could be a collision where
|
||||
* either side is attempting to connect or something like a fuzzing
|
||||
* testing is trying to play tricks to destroy the hcon object before
|
||||
* it even attempts to connect (e.g. hcon->state == BT_OPEN).
|
||||
*/
|
||||
conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
|
||||
if (!conn) {
|
||||
if (!conn ||
|
||||
(conn->role == HCI_ROLE_MASTER && conn->state != BT_CONNECT)) {
|
||||
/* In case of error status and there is no connection pending
|
||||
* just unlock as there is nothing to cleanup.
|
||||
*/
|
||||
@@ -4391,6 +4401,8 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data,
|
||||
|
||||
bt_dev_dbg(hdev, "num %d", ev->num);
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
for (i = 0; i < ev->num; i++) {
|
||||
struct hci_comp_pkts_info *info = &ev->handles[i];
|
||||
struct hci_conn *conn;
|
||||
@@ -4472,6 +4484,8 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data,
|
||||
}
|
||||
|
||||
queue_work(hdev->workqueue, &hdev->tx_work);
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
}
|
||||
|
||||
static void hci_mode_change_evt(struct hci_dev *hdev, void *data,
|
||||
@@ -5634,8 +5648,18 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
|
||||
*/
|
||||
hci_dev_clear_flag(hdev, HCI_LE_ADV);
|
||||
|
||||
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, bdaddr);
|
||||
if (!conn) {
|
||||
/* Check for existing connection:
|
||||
*
|
||||
* 1. If it doesn't exist then use the role to create a new object.
|
||||
* 2. If it does exist confirm that it is connecting/BT_CONNECT in case
|
||||
* of initiator/master role since there could be a collision where
|
||||
* either side is attempting to connect or something like a fuzzing
|
||||
* testing is trying to play tricks to destroy the hcon object before
|
||||
* it even attempts to connect (e.g. hcon->state == BT_OPEN).
|
||||
*/
|
||||
conn = hci_conn_hash_lookup_role(hdev, LE_LINK, role, bdaddr);
|
||||
if (!conn ||
|
||||
(conn->role == HCI_ROLE_MASTER && conn->state != BT_CONNECT)) {
|
||||
/* In case of error status and there is no connection pending
|
||||
* just unlock as there is nothing to cleanup.
|
||||
*/
|
||||
|
||||
@@ -2594,6 +2594,13 @@ static int hci_resume_advertising_sync(struct hci_dev *hdev)
|
||||
hci_remove_ext_adv_instance_sync(hdev, adv->instance,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* If current advertising instance is set to instance 0x00
|
||||
* then we need to re-enable it.
|
||||
*/
|
||||
if (!hdev->cur_adv_instance)
|
||||
err = hci_enable_ext_advertising_sync(hdev,
|
||||
hdev->cur_adv_instance);
|
||||
} else {
|
||||
/* Schedule for most recent instance to be restarted and begin
|
||||
* the software rotation loop
|
||||
|
||||
@@ -1323,8 +1323,7 @@ static void mgmt_set_powered_complete(struct hci_dev *hdev, void *data, int err)
|
||||
struct mgmt_mode *cp;
|
||||
|
||||
/* Make sure cmd still outstanding. */
|
||||
if (err == -ECANCELED ||
|
||||
cmd != pending_find(MGMT_OP_SET_POWERED, hdev))
|
||||
if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd))
|
||||
return;
|
||||
|
||||
cp = cmd->param;
|
||||
@@ -1351,23 +1350,29 @@ static void mgmt_set_powered_complete(struct hci_dev *hdev, void *data, int err)
|
||||
mgmt_status(err));
|
||||
}
|
||||
|
||||
mgmt_pending_remove(cmd);
|
||||
mgmt_pending_free(cmd);
|
||||
}
|
||||
|
||||
static int set_powered_sync(struct hci_dev *hdev, void *data)
|
||||
{
|
||||
struct mgmt_pending_cmd *cmd = data;
|
||||
struct mgmt_mode *cp;
|
||||
struct mgmt_mode cp;
|
||||
|
||||
mutex_lock(&hdev->mgmt_pending_lock);
|
||||
|
||||
/* Make sure cmd still outstanding. */
|
||||
if (cmd != pending_find(MGMT_OP_SET_POWERED, hdev))
|
||||
if (!__mgmt_pending_listed(hdev, cmd)) {
|
||||
mutex_unlock(&hdev->mgmt_pending_lock);
|
||||
return -ECANCELED;
|
||||
}
|
||||
|
||||
cp = cmd->param;
|
||||
memcpy(&cp, cmd->param, sizeof(cp));
|
||||
|
||||
mutex_unlock(&hdev->mgmt_pending_lock);
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
return hci_set_powered_sync(hdev, cp->val);
|
||||
return hci_set_powered_sync(hdev, cp.val);
|
||||
}
|
||||
|
||||
static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
|
||||
@@ -1516,8 +1521,7 @@ static void mgmt_set_discoverable_complete(struct hci_dev *hdev, void *data,
|
||||
bt_dev_dbg(hdev, "err %d", err);
|
||||
|
||||
/* Make sure cmd still outstanding. */
|
||||
if (err == -ECANCELED ||
|
||||
cmd != pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
|
||||
if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd))
|
||||
return;
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
@@ -1539,12 +1543,15 @@ static void mgmt_set_discoverable_complete(struct hci_dev *hdev, void *data,
|
||||
new_settings(hdev, cmd->sk);
|
||||
|
||||
done:
|
||||
mgmt_pending_remove(cmd);
|
||||
mgmt_pending_free(cmd);
|
||||
hci_dev_unlock(hdev);
|
||||
}
|
||||
|
||||
static int set_discoverable_sync(struct hci_dev *hdev, void *data)
|
||||
{
|
||||
if (!mgmt_pending_listed(hdev, data))
|
||||
return -ECANCELED;
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
return hci_update_discoverable_sync(hdev);
|
||||
@@ -1691,8 +1698,7 @@ static void mgmt_set_connectable_complete(struct hci_dev *hdev, void *data,
|
||||
bt_dev_dbg(hdev, "err %d", err);
|
||||
|
||||
/* Make sure cmd still outstanding. */
|
||||
if (err == -ECANCELED ||
|
||||
cmd != pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
|
||||
if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd))
|
||||
return;
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
@@ -1707,7 +1713,7 @@ static void mgmt_set_connectable_complete(struct hci_dev *hdev, void *data,
|
||||
new_settings(hdev, cmd->sk);
|
||||
|
||||
done:
|
||||
mgmt_pending_remove(cmd);
|
||||
mgmt_pending_free(cmd);
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
}
|
||||
@@ -1743,6 +1749,9 @@ static int set_connectable_update_settings(struct hci_dev *hdev,
|
||||
|
||||
static int set_connectable_sync(struct hci_dev *hdev, void *data)
|
||||
{
|
||||
if (!mgmt_pending_listed(hdev, data))
|
||||
return -ECANCELED;
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
return hci_update_connectable_sync(hdev);
|
||||
@@ -1919,14 +1928,17 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err)
|
||||
{
|
||||
struct cmd_lookup match = { NULL, hdev };
|
||||
struct mgmt_pending_cmd *cmd = data;
|
||||
struct mgmt_mode *cp = cmd->param;
|
||||
u8 enable = cp->val;
|
||||
struct mgmt_mode *cp;
|
||||
u8 enable;
|
||||
bool changed;
|
||||
|
||||
/* Make sure cmd still outstanding. */
|
||||
if (err == -ECANCELED || cmd != pending_find(MGMT_OP_SET_SSP, hdev))
|
||||
if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd))
|
||||
return;
|
||||
|
||||
cp = cmd->param;
|
||||
enable = cp->val;
|
||||
|
||||
if (err) {
|
||||
u8 mgmt_err = mgmt_status(err);
|
||||
|
||||
@@ -1935,8 +1947,7 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err)
|
||||
new_settings(hdev, NULL);
|
||||
}
|
||||
|
||||
mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, true,
|
||||
cmd_status_rsp, &mgmt_err);
|
||||
mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_err);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1946,7 +1957,7 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err)
|
||||
changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED);
|
||||
}
|
||||
|
||||
mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, true, settings_rsp, &match);
|
||||
settings_rsp(cmd, &match);
|
||||
|
||||
if (changed)
|
||||
new_settings(hdev, match.sk);
|
||||
@@ -1960,14 +1971,25 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err)
|
||||
static int set_ssp_sync(struct hci_dev *hdev, void *data)
|
||||
{
|
||||
struct mgmt_pending_cmd *cmd = data;
|
||||
struct mgmt_mode *cp = cmd->param;
|
||||
struct mgmt_mode cp;
|
||||
bool changed = false;
|
||||
int err;
|
||||
|
||||
if (cp->val)
|
||||
mutex_lock(&hdev->mgmt_pending_lock);
|
||||
|
||||
if (!__mgmt_pending_listed(hdev, cmd)) {
|
||||
mutex_unlock(&hdev->mgmt_pending_lock);
|
||||
return -ECANCELED;
|
||||
}
|
||||
|
||||
memcpy(&cp, cmd->param, sizeof(cp));
|
||||
|
||||
mutex_unlock(&hdev->mgmt_pending_lock);
|
||||
|
||||
if (cp.val)
|
||||
changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED);
|
||||
|
||||
err = hci_write_ssp_mode_sync(hdev, cp->val);
|
||||
err = hci_write_ssp_mode_sync(hdev, cp.val);
|
||||
|
||||
if (!err && changed)
|
||||
hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
|
||||
@@ -2060,32 +2082,50 @@ static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
|
||||
|
||||
static void set_le_complete(struct hci_dev *hdev, void *data, int err)
|
||||
{
|
||||
struct mgmt_pending_cmd *cmd = data;
|
||||
struct cmd_lookup match = { NULL, hdev };
|
||||
u8 status = mgmt_status(err);
|
||||
|
||||
bt_dev_dbg(hdev, "err %d", err);
|
||||
|
||||
if (status) {
|
||||
mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, true, cmd_status_rsp,
|
||||
&status);
|
||||
if (err == -ECANCELED || !mgmt_pending_valid(hdev, data))
|
||||
return;
|
||||
|
||||
if (status) {
|
||||
mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, status);
|
||||
goto done;
|
||||
}
|
||||
|
||||
mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, true, settings_rsp, &match);
|
||||
settings_rsp(cmd, &match);
|
||||
|
||||
new_settings(hdev, match.sk);
|
||||
|
||||
if (match.sk)
|
||||
sock_put(match.sk);
|
||||
|
||||
done:
|
||||
mgmt_pending_free(cmd);
|
||||
}
|
||||
|
||||
static int set_le_sync(struct hci_dev *hdev, void *data)
|
||||
{
|
||||
struct mgmt_pending_cmd *cmd = data;
|
||||
struct mgmt_mode *cp = cmd->param;
|
||||
u8 val = !!cp->val;
|
||||
struct mgmt_mode cp;
|
||||
u8 val;
|
||||
int err;
|
||||
|
||||
mutex_lock(&hdev->mgmt_pending_lock);
|
||||
|
||||
if (!__mgmt_pending_listed(hdev, cmd)) {
|
||||
mutex_unlock(&hdev->mgmt_pending_lock);
|
||||
return -ECANCELED;
|
||||
}
|
||||
|
||||
memcpy(&cp, cmd->param, sizeof(cp));
|
||||
val = !!cp.val;
|
||||
|
||||
mutex_unlock(&hdev->mgmt_pending_lock);
|
||||
|
||||
if (!val) {
|
||||
hci_clear_adv_instance_sync(hdev, NULL, 0x00, true);
|
||||
|
||||
@@ -2127,7 +2167,12 @@ static void set_mesh_complete(struct hci_dev *hdev, void *data, int err)
|
||||
{
|
||||
struct mgmt_pending_cmd *cmd = data;
|
||||
u8 status = mgmt_status(err);
|
||||
struct sock *sk = cmd->sk;
|
||||
struct sock *sk;
|
||||
|
||||
if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd))
|
||||
return;
|
||||
|
||||
sk = cmd->sk;
|
||||
|
||||
if (status) {
|
||||
mgmt_pending_foreach(MGMT_OP_SET_MESH_RECEIVER, hdev, true,
|
||||
@@ -2142,24 +2187,37 @@ static void set_mesh_complete(struct hci_dev *hdev, void *data, int err)
|
||||
static int set_mesh_sync(struct hci_dev *hdev, void *data)
|
||||
{
|
||||
struct mgmt_pending_cmd *cmd = data;
|
||||
struct mgmt_cp_set_mesh *cp = cmd->param;
|
||||
size_t len = cmd->param_len;
|
||||
struct mgmt_cp_set_mesh cp;
|
||||
size_t len;
|
||||
|
||||
mutex_lock(&hdev->mgmt_pending_lock);
|
||||
|
||||
if (!__mgmt_pending_listed(hdev, cmd)) {
|
||||
mutex_unlock(&hdev->mgmt_pending_lock);
|
||||
return -ECANCELED;
|
||||
}
|
||||
|
||||
memcpy(&cp, cmd->param, sizeof(cp));
|
||||
|
||||
mutex_unlock(&hdev->mgmt_pending_lock);
|
||||
|
||||
len = cmd->param_len;
|
||||
|
||||
memset(hdev->mesh_ad_types, 0, sizeof(hdev->mesh_ad_types));
|
||||
|
||||
if (cp->enable)
|
||||
if (cp.enable)
|
||||
hci_dev_set_flag(hdev, HCI_MESH);
|
||||
else
|
||||
hci_dev_clear_flag(hdev, HCI_MESH);
|
||||
|
||||
hdev->le_scan_interval = __le16_to_cpu(cp->period);
|
||||
hdev->le_scan_window = __le16_to_cpu(cp->window);
|
||||
hdev->le_scan_interval = __le16_to_cpu(cp.period);
|
||||
hdev->le_scan_window = __le16_to_cpu(cp.window);
|
||||
|
||||
len -= sizeof(*cp);
|
||||
len -= sizeof(cp);
|
||||
|
||||
/* If filters don't fit, forward all adv pkts */
|
||||
if (len <= sizeof(hdev->mesh_ad_types))
|
||||
memcpy(hdev->mesh_ad_types, cp->ad_types, len);
|
||||
memcpy(hdev->mesh_ad_types, cp.ad_types, len);
|
||||
|
||||
hci_update_passive_scan_sync(hdev);
|
||||
return 0;
|
||||
@@ -3867,15 +3925,16 @@ static int name_changed_sync(struct hci_dev *hdev, void *data)
|
||||
static void set_name_complete(struct hci_dev *hdev, void *data, int err)
|
||||
{
|
||||
struct mgmt_pending_cmd *cmd = data;
|
||||
struct mgmt_cp_set_local_name *cp = cmd->param;
|
||||
struct mgmt_cp_set_local_name *cp;
|
||||
u8 status = mgmt_status(err);
|
||||
|
||||
bt_dev_dbg(hdev, "err %d", err);
|
||||
|
||||
if (err == -ECANCELED ||
|
||||
cmd != pending_find(MGMT_OP_SET_LOCAL_NAME, hdev))
|
||||
if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd))
|
||||
return;
|
||||
|
||||
cp = cmd->param;
|
||||
|
||||
if (status) {
|
||||
mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
|
||||
status);
|
||||
@@ -3887,16 +3946,27 @@ static void set_name_complete(struct hci_dev *hdev, void *data, int err)
|
||||
hci_cmd_sync_queue(hdev, name_changed_sync, NULL, NULL);
|
||||
}
|
||||
|
||||
mgmt_pending_remove(cmd);
|
||||
mgmt_pending_free(cmd);
|
||||
}
|
||||
|
||||
static int set_name_sync(struct hci_dev *hdev, void *data)
|
||||
{
|
||||
struct mgmt_pending_cmd *cmd = data;
|
||||
struct mgmt_cp_set_local_name *cp = cmd->param;
|
||||
struct mgmt_cp_set_local_name cp;
|
||||
|
||||
mutex_lock(&hdev->mgmt_pending_lock);
|
||||
|
||||
if (!__mgmt_pending_listed(hdev, cmd)) {
|
||||
mutex_unlock(&hdev->mgmt_pending_lock);
|
||||
return -ECANCELED;
|
||||
}
|
||||
|
||||
memcpy(&cp, cmd->param, sizeof(cp));
|
||||
|
||||
mutex_unlock(&hdev->mgmt_pending_lock);
|
||||
|
||||
if (lmp_bredr_capable(hdev)) {
|
||||
hci_update_name_sync(hdev, cp->name);
|
||||
hci_update_name_sync(hdev, cp.name);
|
||||
hci_update_eir_sync(hdev);
|
||||
}
|
||||
|
||||
@@ -4048,12 +4118,10 @@ int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *skip)
|
||||
static void set_default_phy_complete(struct hci_dev *hdev, void *data, int err)
|
||||
{
|
||||
struct mgmt_pending_cmd *cmd = data;
|
||||
struct sk_buff *skb = cmd->skb;
|
||||
struct sk_buff *skb;
|
||||
u8 status = mgmt_status(err);
|
||||
|
||||
if (err == -ECANCELED ||
|
||||
cmd != pending_find(MGMT_OP_SET_PHY_CONFIGURATION, hdev))
|
||||
return;
|
||||
skb = cmd->skb;
|
||||
|
||||
if (!status) {
|
||||
if (!skb)
|
||||
@@ -4080,7 +4148,7 @@ static void set_default_phy_complete(struct hci_dev *hdev, void *data, int err)
|
||||
if (skb && !IS_ERR(skb))
|
||||
kfree_skb(skb);
|
||||
|
||||
mgmt_pending_remove(cmd);
|
||||
mgmt_pending_free(cmd);
|
||||
}
|
||||
|
||||
static int set_default_phy_sync(struct hci_dev *hdev, void *data)
|
||||
@@ -4088,7 +4156,9 @@ static int set_default_phy_sync(struct hci_dev *hdev, void *data)
|
||||
struct mgmt_pending_cmd *cmd = data;
|
||||
struct mgmt_cp_set_phy_configuration *cp = cmd->param;
|
||||
struct hci_cp_le_set_default_phy cp_phy;
|
||||
u32 selected_phys = __le32_to_cpu(cp->selected_phys);
|
||||
u32 selected_phys;
|
||||
|
||||
selected_phys = __le32_to_cpu(cp->selected_phys);
|
||||
|
||||
memset(&cp_phy, 0, sizeof(cp_phy));
|
||||
|
||||
@@ -4228,7 +4298,7 @@ static int set_phy_configuration(struct sock *sk, struct hci_dev *hdev,
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
cmd = mgmt_pending_add(sk, MGMT_OP_SET_PHY_CONFIGURATION, hdev, data,
|
||||
cmd = mgmt_pending_new(sk, MGMT_OP_SET_PHY_CONFIGURATION, hdev, data,
|
||||
len);
|
||||
if (!cmd)
|
||||
err = -ENOMEM;
|
||||
@@ -5189,7 +5259,17 @@ static void mgmt_add_adv_patterns_monitor_complete(struct hci_dev *hdev,
|
||||
{
|
||||
struct mgmt_rp_add_adv_patterns_monitor rp;
|
||||
struct mgmt_pending_cmd *cmd = data;
|
||||
struct adv_monitor *monitor = cmd->user_data;
|
||||
struct adv_monitor *monitor;
|
||||
|
||||
/* This is likely the result of hdev being closed and mgmt_index_removed
|
||||
* is attempting to clean up any pending command so
|
||||
* hci_adv_monitors_clear is about to be called which will take care of
|
||||
* freeing the adv_monitor instances.
|
||||
*/
|
||||
if (status == -ECANCELED && !mgmt_pending_valid(hdev, cmd))
|
||||
return;
|
||||
|
||||
monitor = cmd->user_data;
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
@@ -5215,9 +5295,20 @@ static void mgmt_add_adv_patterns_monitor_complete(struct hci_dev *hdev,
|
||||
static int mgmt_add_adv_patterns_monitor_sync(struct hci_dev *hdev, void *data)
|
||||
{
|
||||
struct mgmt_pending_cmd *cmd = data;
|
||||
struct adv_monitor *monitor = cmd->user_data;
|
||||
struct adv_monitor *mon;
|
||||
|
||||
return hci_add_adv_monitor(hdev, monitor);
|
||||
mutex_lock(&hdev->mgmt_pending_lock);
|
||||
|
||||
if (!__mgmt_pending_listed(hdev, cmd)) {
|
||||
mutex_unlock(&hdev->mgmt_pending_lock);
|
||||
return -ECANCELED;
|
||||
}
|
||||
|
||||
mon = cmd->user_data;
|
||||
|
||||
mutex_unlock(&hdev->mgmt_pending_lock);
|
||||
|
||||
return hci_add_adv_monitor(hdev, mon);
|
||||
}
|
||||
|
||||
static int __add_adv_patterns_monitor(struct sock *sk, struct hci_dev *hdev,
|
||||
@@ -5484,7 +5575,8 @@ unlock:
|
||||
status);
|
||||
}
|
||||
|
||||
static void read_local_oob_data_complete(struct hci_dev *hdev, void *data, int err)
|
||||
static void read_local_oob_data_complete(struct hci_dev *hdev, void *data,
|
||||
int err)
|
||||
{
|
||||
struct mgmt_rp_read_local_oob_data mgmt_rp;
|
||||
size_t rp_size = sizeof(mgmt_rp);
|
||||
@@ -5504,7 +5596,8 @@ static void read_local_oob_data_complete(struct hci_dev *hdev, void *data, int e
|
||||
bt_dev_dbg(hdev, "status %d", status);
|
||||
|
||||
if (status) {
|
||||
mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, status);
|
||||
mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
|
||||
status);
|
||||
goto remove;
|
||||
}
|
||||
|
||||
@@ -5786,17 +5879,12 @@ static void start_discovery_complete(struct hci_dev *hdev, void *data, int err)
|
||||
|
||||
bt_dev_dbg(hdev, "err %d", err);
|
||||
|
||||
if (err == -ECANCELED)
|
||||
return;
|
||||
|
||||
if (cmd != pending_find(MGMT_OP_START_DISCOVERY, hdev) &&
|
||||
cmd != pending_find(MGMT_OP_START_LIMITED_DISCOVERY, hdev) &&
|
||||
cmd != pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev))
|
||||
if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd))
|
||||
return;
|
||||
|
||||
mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err),
|
||||
cmd->param, 1);
|
||||
mgmt_pending_remove(cmd);
|
||||
mgmt_pending_free(cmd);
|
||||
|
||||
hci_discovery_set_state(hdev, err ? DISCOVERY_STOPPED:
|
||||
DISCOVERY_FINDING);
|
||||
@@ -5804,6 +5892,9 @@ static void start_discovery_complete(struct hci_dev *hdev, void *data, int err)
|
||||
|
||||
static int start_discovery_sync(struct hci_dev *hdev, void *data)
|
||||
{
|
||||
if (!mgmt_pending_listed(hdev, data))
|
||||
return -ECANCELED;
|
||||
|
||||
return hci_start_discovery_sync(hdev);
|
||||
}
|
||||
|
||||
@@ -6009,15 +6100,14 @@ static void stop_discovery_complete(struct hci_dev *hdev, void *data, int err)
|
||||
{
|
||||
struct mgmt_pending_cmd *cmd = data;
|
||||
|
||||
if (err == -ECANCELED ||
|
||||
cmd != pending_find(MGMT_OP_STOP_DISCOVERY, hdev))
|
||||
if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd))
|
||||
return;
|
||||
|
||||
bt_dev_dbg(hdev, "err %d", err);
|
||||
|
||||
mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err),
|
||||
cmd->param, 1);
|
||||
mgmt_pending_remove(cmd);
|
||||
mgmt_pending_free(cmd);
|
||||
|
||||
if (!err)
|
||||
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
|
||||
@@ -6025,6 +6115,9 @@ static void stop_discovery_complete(struct hci_dev *hdev, void *data, int err)
|
||||
|
||||
static int stop_discovery_sync(struct hci_dev *hdev, void *data)
|
||||
{
|
||||
if (!mgmt_pending_listed(hdev, data))
|
||||
return -ECANCELED;
|
||||
|
||||
return hci_stop_discovery_sync(hdev);
|
||||
}
|
||||
|
||||
@@ -6234,14 +6327,18 @@ static void enable_advertising_instance(struct hci_dev *hdev, int err)
|
||||
|
||||
static void set_advertising_complete(struct hci_dev *hdev, void *data, int err)
|
||||
{
|
||||
struct mgmt_pending_cmd *cmd = data;
|
||||
struct cmd_lookup match = { NULL, hdev };
|
||||
u8 instance;
|
||||
struct adv_info *adv_instance;
|
||||
u8 status = mgmt_status(err);
|
||||
|
||||
if (err == -ECANCELED || !mgmt_pending_valid(hdev, data))
|
||||
return;
|
||||
|
||||
if (status) {
|
||||
mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, true,
|
||||
cmd_status_rsp, &status);
|
||||
mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, status);
|
||||
mgmt_pending_free(cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -6250,8 +6347,7 @@ static void set_advertising_complete(struct hci_dev *hdev, void *data, int err)
|
||||
else
|
||||
hci_dev_clear_flag(hdev, HCI_ADVERTISING);
|
||||
|
||||
mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, true, settings_rsp,
|
||||
&match);
|
||||
settings_rsp(cmd, &match);
|
||||
|
||||
new_settings(hdev, match.sk);
|
||||
|
||||
@@ -6283,10 +6379,23 @@ static void set_advertising_complete(struct hci_dev *hdev, void *data, int err)
|
||||
static int set_adv_sync(struct hci_dev *hdev, void *data)
|
||||
{
|
||||
struct mgmt_pending_cmd *cmd = data;
|
||||
struct mgmt_mode *cp = cmd->param;
|
||||
u8 val = !!cp->val;
|
||||
struct mgmt_mode cp;
|
||||
u8 val;
|
||||
|
||||
if (cp->val == 0x02)
|
||||
mutex_lock(&hdev->mgmt_pending_lock);
|
||||
|
||||
if (!__mgmt_pending_listed(hdev, cmd)) {
|
||||
mutex_unlock(&hdev->mgmt_pending_lock);
|
||||
return -ECANCELED;
|
||||
}
|
||||
|
||||
memcpy(&cp, cmd->param, sizeof(cp));
|
||||
|
||||
mutex_unlock(&hdev->mgmt_pending_lock);
|
||||
|
||||
val = !!cp.val;
|
||||
|
||||
if (cp.val == 0x02)
|
||||
hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
|
||||
else
|
||||
hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
|
||||
@@ -8039,10 +8148,6 @@ static void read_local_oob_ext_data_complete(struct hci_dev *hdev, void *data,
|
||||
u8 status = mgmt_status(err);
|
||||
u16 eir_len;
|
||||
|
||||
if (err == -ECANCELED ||
|
||||
cmd != pending_find(MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev))
|
||||
return;
|
||||
|
||||
if (!status) {
|
||||
if (!skb)
|
||||
status = MGMT_STATUS_FAILED;
|
||||
@@ -8149,7 +8254,7 @@ done:
|
||||
kfree_skb(skb);
|
||||
|
||||
kfree(mgmt_rp);
|
||||
mgmt_pending_remove(cmd);
|
||||
mgmt_pending_free(cmd);
|
||||
}
|
||||
|
||||
static int read_local_ssp_oob_req(struct hci_dev *hdev, struct sock *sk,
|
||||
@@ -8158,7 +8263,7 @@ static int read_local_ssp_oob_req(struct hci_dev *hdev, struct sock *sk,
|
||||
struct mgmt_pending_cmd *cmd;
|
||||
int err;
|
||||
|
||||
cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev,
|
||||
cmd = mgmt_pending_new(sk, MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev,
|
||||
cp, sizeof(*cp));
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -320,6 +320,52 @@ void mgmt_pending_remove(struct mgmt_pending_cmd *cmd)
|
||||
mgmt_pending_free(cmd);
|
||||
}
|
||||
|
||||
bool __mgmt_pending_listed(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd)
|
||||
{
|
||||
struct mgmt_pending_cmd *tmp;
|
||||
|
||||
lockdep_assert_held(&hdev->mgmt_pending_lock);
|
||||
|
||||
if (!cmd)
|
||||
return false;
|
||||
|
||||
list_for_each_entry(tmp, &hdev->mgmt_pending, list) {
|
||||
if (cmd == tmp)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool mgmt_pending_listed(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd)
|
||||
{
|
||||
bool listed;
|
||||
|
||||
mutex_lock(&hdev->mgmt_pending_lock);
|
||||
listed = __mgmt_pending_listed(hdev, cmd);
|
||||
mutex_unlock(&hdev->mgmt_pending_lock);
|
||||
|
||||
return listed;
|
||||
}
|
||||
|
||||
bool mgmt_pending_valid(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd)
|
||||
{
|
||||
bool listed;
|
||||
|
||||
if (!cmd)
|
||||
return false;
|
||||
|
||||
mutex_lock(&hdev->mgmt_pending_lock);
|
||||
|
||||
listed = __mgmt_pending_listed(hdev, cmd);
|
||||
if (listed)
|
||||
list_del(&cmd->list);
|
||||
|
||||
mutex_unlock(&hdev->mgmt_pending_lock);
|
||||
|
||||
return listed;
|
||||
}
|
||||
|
||||
void mgmt_mesh_foreach(struct hci_dev *hdev,
|
||||
void (*cb)(struct mgmt_mesh_tx *mesh_tx, void *data),
|
||||
void *data, struct sock *sk)
|
||||
|
||||
@@ -65,6 +65,9 @@ struct mgmt_pending_cmd *mgmt_pending_new(struct sock *sk, u16 opcode,
|
||||
void *data, u16 len);
|
||||
void mgmt_pending_free(struct mgmt_pending_cmd *cmd);
|
||||
void mgmt_pending_remove(struct mgmt_pending_cmd *cmd);
|
||||
bool __mgmt_pending_listed(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd);
|
||||
bool mgmt_pending_listed(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd);
|
||||
bool mgmt_pending_valid(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd);
|
||||
void mgmt_mesh_foreach(struct hci_dev *hdev,
|
||||
void (*cb)(struct mgmt_mesh_tx *mesh_tx, void *data),
|
||||
void *data, struct sock *sk);
|
||||
|
||||
@@ -6667,7 +6667,7 @@ struct sk_buff *alloc_skb_with_frags(unsigned long header_len,
|
||||
return NULL;
|
||||
|
||||
while (data_len) {
|
||||
if (nr_frags == MAX_SKB_FRAGS - 1)
|
||||
if (nr_frags == MAX_SKB_FRAGS)
|
||||
goto failure;
|
||||
while (order && PAGE_ALIGN(data_len) < (PAGE_SIZE << order))
|
||||
order--;
|
||||
|
||||
@@ -2399,6 +2399,13 @@ static int replace_nexthop_single(struct net *net, struct nexthop *old,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!list_empty(&old->grp_list) &&
|
||||
rtnl_dereference(new->nh_info)->fdb_nh !=
|
||||
rtnl_dereference(old->nh_info)->fdb_nh) {
|
||||
NL_SET_ERR_MSG(extack, "Cannot change nexthop FDB status while in a group");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = call_nexthop_notifiers(net, NEXTHOP_EVENT_REPLACE, new, extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -56,6 +56,7 @@ static int smc_lo_register_dmb(struct smcd_dev *smcd, struct smcd_dmb *dmb,
|
||||
{
|
||||
struct smc_lo_dmb_node *dmb_node, *tmp_node;
|
||||
struct smc_lo_dev *ldev = smcd->priv;
|
||||
struct folio *folio;
|
||||
int sba_idx, rc;
|
||||
|
||||
/* check space for new dmb */
|
||||
@@ -74,13 +75,16 @@ static int smc_lo_register_dmb(struct smcd_dev *smcd, struct smcd_dmb *dmb,
|
||||
|
||||
dmb_node->sba_idx = sba_idx;
|
||||
dmb_node->len = dmb->dmb_len;
|
||||
dmb_node->cpu_addr = kzalloc(dmb_node->len, GFP_KERNEL |
|
||||
__GFP_NOWARN | __GFP_NORETRY |
|
||||
__GFP_NOMEMALLOC);
|
||||
if (!dmb_node->cpu_addr) {
|
||||
|
||||
/* not critical; fail under memory pressure and fallback to TCP */
|
||||
folio = folio_alloc(GFP_KERNEL | __GFP_NOWARN | __GFP_NOMEMALLOC |
|
||||
__GFP_NORETRY | __GFP_ZERO,
|
||||
get_order(dmb_node->len));
|
||||
if (!folio) {
|
||||
rc = -ENOMEM;
|
||||
goto err_node;
|
||||
}
|
||||
dmb_node->cpu_addr = folio_address(folio);
|
||||
dmb_node->dma_addr = SMC_DMA_ADDR_INVALID;
|
||||
refcount_set(&dmb_node->refcnt, 1);
|
||||
|
||||
@@ -122,7 +126,7 @@ static void __smc_lo_unregister_dmb(struct smc_lo_dev *ldev,
|
||||
write_unlock_bh(&ldev->dmb_ht_lock);
|
||||
|
||||
clear_bit(dmb_node->sba_idx, ldev->sba_idx_mask);
|
||||
kvfree(dmb_node->cpu_addr);
|
||||
folio_put(virt_to_folio(dmb_node->cpu_addr));
|
||||
kfree(dmb_node);
|
||||
|
||||
if (atomic_dec_and_test(&ldev->dmb_cnt))
|
||||
|
||||
@@ -438,7 +438,7 @@ ok:
|
||||
|
||||
check_tunnel_size = x->xso.type == XFRM_DEV_OFFLOAD_PACKET &&
|
||||
x->props.mode == XFRM_MODE_TUNNEL;
|
||||
switch (x->props.family) {
|
||||
switch (x->inner_mode.family) {
|
||||
case AF_INET:
|
||||
/* Check for IPv4 options */
|
||||
if (ip_hdr(skb)->ihl != 5)
|
||||
|
||||
@@ -2583,6 +2583,8 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high,
|
||||
|
||||
for (h = 0; h < range; h++) {
|
||||
u32 spi = (low == high) ? low : get_random_u32_inclusive(low, high);
|
||||
if (spi == 0)
|
||||
goto next;
|
||||
newspi = htonl(spi);
|
||||
|
||||
spin_lock_bh(&net->xfrm.xfrm_state_lock);
|
||||
@@ -2598,6 +2600,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high,
|
||||
xfrm_state_put(x0);
|
||||
spin_unlock_bh(&net->xfrm.xfrm_state_lock);
|
||||
|
||||
next:
|
||||
if (signal_pending(current)) {
|
||||
err = -ERESTARTSYS;
|
||||
goto unlock;
|
||||
|
||||
@@ -467,8 +467,8 @@ ipv6_fdb_grp_fcnal()
|
||||
log_test $? 0 "Get Fdb nexthop group by id"
|
||||
|
||||
# fdb nexthop group can only contain fdb nexthops
|
||||
run_cmd "$IP nexthop add id 63 via 2001:db8:91::4"
|
||||
run_cmd "$IP nexthop add id 64 via 2001:db8:91::5"
|
||||
run_cmd "$IP nexthop add id 63 via 2001:db8:91::4 dev veth1"
|
||||
run_cmd "$IP nexthop add id 64 via 2001:db8:91::5 dev veth1"
|
||||
run_cmd "$IP nexthop add id 103 group 63/64 fdb"
|
||||
log_test $? 2 "Fdb Nexthop group with non-fdb nexthops"
|
||||
|
||||
@@ -494,6 +494,26 @@ ipv6_fdb_grp_fcnal()
|
||||
run_cmd "$IP nexthop add id 69 encap mpls 101 via 2001:db8:91::8 dev veth1 fdb"
|
||||
log_test $? 2 "Fdb Nexthop with encap"
|
||||
|
||||
# Replace FDB nexthop to non-FDB and vice versa
|
||||
run_cmd "$IP nexthop add id 70 via 2001:db8:91::2 fdb"
|
||||
run_cmd "$IP nexthop replace id 70 via 2001:db8:91::2 dev veth1"
|
||||
log_test $? 0 "Replace FDB nexthop to non-FDB nexthop"
|
||||
run_cmd "$IP nexthop replace id 70 via 2001:db8:91::2 fdb"
|
||||
log_test $? 0 "Replace non-FDB nexthop to FDB nexthop"
|
||||
|
||||
# Replace FDB nexthop address while in a group
|
||||
run_cmd "$IP nexthop add id 71 group 70 fdb"
|
||||
run_cmd "$IP nexthop replace id 70 via 2001:db8:91::3 fdb"
|
||||
log_test $? 0 "Replace FDB nexthop address while in a group"
|
||||
|
||||
# Cannot replace FDB nexthop to non-FDB and vice versa while in a group
|
||||
run_cmd "$IP nexthop replace id 70 via 2001:db8:91::2 dev veth1"
|
||||
log_test $? 2 "Replace FDB nexthop to non-FDB nexthop while in a group"
|
||||
run_cmd "$IP nexthop add id 72 via 2001:db8:91::2 dev veth1"
|
||||
run_cmd "$IP nexthop add id 73 group 72"
|
||||
run_cmd "$IP nexthop replace id 72 via 2001:db8:91::2 fdb"
|
||||
log_test $? 2 "Replace non-FDB nexthop to FDB nexthop while in a group"
|
||||
|
||||
run_cmd "$IP link add name vx10 type vxlan id 1010 local 2001:db8:91::9 remote 2001:db8:91::10 dstport 4789 nolearning noudpcsum tos inherit ttl 100"
|
||||
run_cmd "$BRIDGE fdb add 02:02:00:00:00:13 dev vx10 nhid 102 self"
|
||||
log_test $? 0 "Fdb mac add with nexthop group"
|
||||
@@ -547,15 +567,15 @@ ipv4_fdb_grp_fcnal()
|
||||
log_test $? 0 "Get Fdb nexthop group by id"
|
||||
|
||||
# fdb nexthop group can only contain fdb nexthops
|
||||
run_cmd "$IP nexthop add id 14 via 172.16.1.2"
|
||||
run_cmd "$IP nexthop add id 15 via 172.16.1.3"
|
||||
run_cmd "$IP nexthop add id 14 via 172.16.1.2 dev veth1"
|
||||
run_cmd "$IP nexthop add id 15 via 172.16.1.3 dev veth1"
|
||||
run_cmd "$IP nexthop add id 103 group 14/15 fdb"
|
||||
log_test $? 2 "Fdb Nexthop group with non-fdb nexthops"
|
||||
|
||||
# Non fdb nexthop group can not contain fdb nexthops
|
||||
run_cmd "$IP nexthop add id 16 via 172.16.1.2 fdb"
|
||||
run_cmd "$IP nexthop add id 17 via 172.16.1.3 fdb"
|
||||
run_cmd "$IP nexthop add id 104 group 14/15"
|
||||
run_cmd "$IP nexthop add id 104 group 16/17"
|
||||
log_test $? 2 "Non-Fdb Nexthop group with fdb nexthops"
|
||||
|
||||
# fdb nexthop cannot have blackhole
|
||||
@@ -574,6 +594,26 @@ ipv4_fdb_grp_fcnal()
|
||||
run_cmd "$IP nexthop add id 17 encap mpls 101 via 172.16.1.2 dev veth1 fdb"
|
||||
log_test $? 2 "Fdb Nexthop with encap"
|
||||
|
||||
# Replace FDB nexthop to non-FDB and vice versa
|
||||
run_cmd "$IP nexthop add id 18 via 172.16.1.2 fdb"
|
||||
run_cmd "$IP nexthop replace id 18 via 172.16.1.2 dev veth1"
|
||||
log_test $? 0 "Replace FDB nexthop to non-FDB nexthop"
|
||||
run_cmd "$IP nexthop replace id 18 via 172.16.1.2 fdb"
|
||||
log_test $? 0 "Replace non-FDB nexthop to FDB nexthop"
|
||||
|
||||
# Replace FDB nexthop address while in a group
|
||||
run_cmd "$IP nexthop add id 19 group 18 fdb"
|
||||
run_cmd "$IP nexthop replace id 18 via 172.16.1.3 fdb"
|
||||
log_test $? 0 "Replace FDB nexthop address while in a group"
|
||||
|
||||
# Cannot replace FDB nexthop to non-FDB and vice versa while in a group
|
||||
run_cmd "$IP nexthop replace id 18 via 172.16.1.2 dev veth1"
|
||||
log_test $? 2 "Replace FDB nexthop to non-FDB nexthop while in a group"
|
||||
run_cmd "$IP nexthop add id 20 via 172.16.1.2 dev veth1"
|
||||
run_cmd "$IP nexthop add id 21 group 20"
|
||||
run_cmd "$IP nexthop replace id 20 via 172.16.1.2 fdb"
|
||||
log_test $? 2 "Replace non-FDB nexthop to FDB nexthop while in a group"
|
||||
|
||||
run_cmd "$IP link add name vx10 type vxlan id 1010 local 10.0.0.1 remote 10.0.0.2 dstport 4789 nolearning noudpcsum tos inherit ttl 100"
|
||||
run_cmd "$BRIDGE fdb add 02:02:00:00:00:13 dev vx10 nhid 102 self"
|
||||
log_test $? 0 "Fdb mac add with nexthop group"
|
||||
@@ -582,7 +622,7 @@ ipv4_fdb_grp_fcnal()
|
||||
run_cmd "$BRIDGE fdb add 02:02:00:00:00:14 dev vx10 nhid 12 self"
|
||||
log_test $? 255 "Fdb mac add with nexthop"
|
||||
|
||||
run_cmd "$IP ro add 172.16.0.0/22 nhid 15"
|
||||
run_cmd "$IP ro add 172.16.0.0/22 nhid 16"
|
||||
log_test $? 2 "Route add with fdb nexthop"
|
||||
|
||||
run_cmd "$IP ro add 172.16.0.0/22 nhid 103"
|
||||
|
||||
Reference in New Issue
Block a user