Merge 574686c807 ("ice: use DSN instead of PCI BDF for ice_adapter index") into android16-6.12-lts
Steps on the way to 6.12.29 Change-Id: Id846660f91db6f211ce79fc31186c6d8e78b0468 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -165,6 +165,19 @@
|
||||
startup-delay-us = <20000>;
|
||||
};
|
||||
|
||||
reg_usdhc2_vqmmc: regulator-usdhc2-vqmmc {
|
||||
compatible = "regulator-gpio";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_usdhc2_vsel>;
|
||||
gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-min-microvolt = <1800000>;
|
||||
states = <1800000 0x1>,
|
||||
<3300000 0x0>;
|
||||
regulator-name = "PMIC_USDHC_VSELECT";
|
||||
vin-supply = <®_nvcc_sd>;
|
||||
};
|
||||
|
||||
reserved-memory {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
@@ -290,7 +303,7 @@
|
||||
"SODIMM_19",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"PMIC_USDHC_VSELECT",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
@@ -801,6 +814,7 @@
|
||||
pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_cd>;
|
||||
pinctrl-3 = <&pinctrl_usdhc2_sleep>, <&pinctrl_usdhc2_cd_sleep>;
|
||||
vmmc-supply = <®_usdhc2_vmmc>;
|
||||
vqmmc-supply = <®_usdhc2_vqmmc>;
|
||||
};
|
||||
|
||||
&wdog1 {
|
||||
@@ -1222,13 +1236,17 @@
|
||||
<MX8MM_IOMUXC_NAND_CLE_GPIO3_IO5 0x6>; /* SODIMM 76 */
|
||||
};
|
||||
|
||||
pinctrl_usdhc2_vsel: usdhc2vselgrp {
|
||||
fsl,pins =
|
||||
<MX8MM_IOMUXC_GPIO1_IO04_GPIO1_IO4 0x10>; /* PMIC_USDHC_VSELECT */
|
||||
};
|
||||
|
||||
/*
|
||||
* Note: Due to ERR050080 we use discrete external on-module resistors pulling-up to the
|
||||
* on-module +V3.3_1.8_SD (LDO5) rail and explicitly disable the internal pull-ups here.
|
||||
*/
|
||||
pinctrl_usdhc2: usdhc2grp {
|
||||
fsl,pins =
|
||||
<MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x10>,
|
||||
<MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x90>, /* SODIMM 78 */
|
||||
<MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x90>, /* SODIMM 74 */
|
||||
<MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x90>, /* SODIMM 80 */
|
||||
@@ -1239,7 +1257,6 @@
|
||||
|
||||
pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
|
||||
fsl,pins =
|
||||
<MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x10>,
|
||||
<MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x94>,
|
||||
<MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x94>,
|
||||
<MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x94>,
|
||||
@@ -1250,7 +1267,6 @@
|
||||
|
||||
pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
|
||||
fsl,pins =
|
||||
<MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x10>,
|
||||
<MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x96>,
|
||||
<MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x96>,
|
||||
<MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x96>,
|
||||
@@ -1262,7 +1278,6 @@
|
||||
/* Avoid backfeeding with removed card power */
|
||||
pinctrl_usdhc2_sleep: usdhc2slpgrp {
|
||||
fsl,pins =
|
||||
<MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x0>,
|
||||
<MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x0>,
|
||||
<MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x0>,
|
||||
<MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x0>,
|
||||
|
||||
@@ -636,7 +636,8 @@ SYM_CODE_START(stack_overflow)
|
||||
stmg %r0,%r7,__PT_R0(%r11)
|
||||
stmg %r8,%r9,__PT_PSW(%r11)
|
||||
mvc __PT_R8(64,%r11),0(%r14)
|
||||
stg %r10,__PT_ORIG_GPR2(%r11) # store last break to orig_gpr2
|
||||
GET_LC %r2
|
||||
mvc __PT_ORIG_GPR2(8,%r11),__LC_PGM_LAST_BREAK(%r2)
|
||||
xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
|
||||
lgr %r2,%r11 # pass pointer to pt_regs
|
||||
jg kernel_stack_overflow
|
||||
|
||||
@@ -422,6 +422,8 @@ static void __clp_add(struct clp_fh_list_entry *entry, void *data)
|
||||
return;
|
||||
}
|
||||
zdev = zpci_create_device(entry->fid, entry->fh, entry->config_state);
|
||||
if (IS_ERR(zdev))
|
||||
return;
|
||||
list_add_tail(&zdev->entry, scan_list);
|
||||
}
|
||||
|
||||
|
||||
@@ -1219,7 +1219,8 @@ static void xfer_put(const struct scmi_protocol_handle *ph,
|
||||
}
|
||||
|
||||
static bool scmi_xfer_done_no_timeout(struct scmi_chan_info *cinfo,
|
||||
struct scmi_xfer *xfer, ktime_t stop)
|
||||
struct scmi_xfer *xfer, ktime_t stop,
|
||||
bool *ooo)
|
||||
{
|
||||
struct scmi_info *info = handle_to_scmi_info(cinfo->handle);
|
||||
|
||||
@@ -1228,7 +1229,7 @@ static bool scmi_xfer_done_no_timeout(struct scmi_chan_info *cinfo,
|
||||
* in case of out-of-order receptions of delayed responses
|
||||
*/
|
||||
return info->desc->ops->poll_done(cinfo, xfer) ||
|
||||
try_wait_for_completion(&xfer->done) ||
|
||||
(*ooo = try_wait_for_completion(&xfer->done)) ||
|
||||
ktime_after(ktime_get(), stop);
|
||||
}
|
||||
|
||||
@@ -1245,15 +1246,17 @@ static int scmi_wait_for_reply(struct device *dev, const struct scmi_desc *desc,
|
||||
* itself to support synchronous commands replies.
|
||||
*/
|
||||
if (!desc->sync_cmds_completed_on_ret) {
|
||||
bool ooo = false;
|
||||
|
||||
/*
|
||||
* Poll on xfer using transport provided .poll_done();
|
||||
* assumes no completion interrupt was available.
|
||||
*/
|
||||
ktime_t stop = ktime_add_ms(ktime_get(), timeout_ms);
|
||||
|
||||
spin_until_cond(scmi_xfer_done_no_timeout(cinfo,
|
||||
xfer, stop));
|
||||
if (ktime_after(ktime_get(), stop)) {
|
||||
spin_until_cond(scmi_xfer_done_no_timeout(cinfo, xfer,
|
||||
stop, &ooo));
|
||||
if (!ooo && !info->desc->ops->poll_done(cinfo, xfer)) {
|
||||
dev_err(dev,
|
||||
"timed out in resp(caller: %pS) - polling\n",
|
||||
(void *)_RET_IP_);
|
||||
|
||||
@@ -1183,7 +1183,7 @@ static int dm_keyslot_evict(struct blk_crypto_profile *profile,
|
||||
|
||||
t = dm_get_live_table(md, &srcu_idx);
|
||||
if (!t)
|
||||
return 0;
|
||||
goto put_live_table;
|
||||
|
||||
for (unsigned int i = 0; i < t->num_targets; i++) {
|
||||
struct dm_target *ti = dm_table_get_target(t, i);
|
||||
@@ -1194,6 +1194,7 @@ static int dm_keyslot_evict(struct blk_crypto_profile *profile,
|
||||
(void *)key);
|
||||
}
|
||||
|
||||
put_live_table:
|
||||
dm_put_live_table(md, srcu_idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2372,6 +2372,7 @@ struct m_can_classdev *m_can_class_allocate_dev(struct device *dev,
|
||||
SET_NETDEV_DEV(net_dev, dev);
|
||||
|
||||
m_can_of_parse_mram(class_dev, mram_config_vals);
|
||||
spin_lock_init(&class_dev->tx_handling_spinlock);
|
||||
out:
|
||||
return class_dev;
|
||||
}
|
||||
@@ -2456,9 +2457,9 @@ EXPORT_SYMBOL_GPL(m_can_class_register);
|
||||
|
||||
void m_can_class_unregister(struct m_can_classdev *cdev)
|
||||
{
|
||||
unregister_candev(cdev->net);
|
||||
if (cdev->is_peripheral)
|
||||
can_rx_offload_del(&cdev->offload);
|
||||
unregister_candev(cdev->net);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(m_can_class_unregister);
|
||||
|
||||
|
||||
@@ -942,8 +942,8 @@ static void rkcanfd_remove(struct platform_device *pdev)
|
||||
struct rkcanfd_priv *priv = platform_get_drvdata(pdev);
|
||||
struct net_device *ndev = priv->ndev;
|
||||
|
||||
can_rx_offload_del(&priv->offload);
|
||||
rkcanfd_unregister(priv);
|
||||
can_rx_offload_del(&priv->offload);
|
||||
free_candev(ndev);
|
||||
}
|
||||
|
||||
|
||||
@@ -75,6 +75,24 @@ static const struct can_bittiming_const mcp251xfd_data_bittiming_const = {
|
||||
.brp_inc = 1,
|
||||
};
|
||||
|
||||
/* The datasheet of the mcp2518fd (DS20006027B) specifies a range of
|
||||
* [-64,63] for TDCO, indicating a relative TDCO.
|
||||
*
|
||||
* Manual tests have shown, that using a relative TDCO configuration
|
||||
* results in bus off, while an absolute configuration works.
|
||||
*
|
||||
* For TDCO use the max value (63) from the data sheet, but 0 as the
|
||||
* minimum.
|
||||
*/
|
||||
static const struct can_tdc_const mcp251xfd_tdc_const = {
|
||||
.tdcv_min = 0,
|
||||
.tdcv_max = 63,
|
||||
.tdco_min = 0,
|
||||
.tdco_max = 63,
|
||||
.tdcf_min = 0,
|
||||
.tdcf_max = 0,
|
||||
};
|
||||
|
||||
static const char *__mcp251xfd_get_model_str(enum mcp251xfd_model model)
|
||||
{
|
||||
switch (model) {
|
||||
@@ -510,8 +528,7 @@ static int mcp251xfd_set_bittiming(const struct mcp251xfd_priv *priv)
|
||||
{
|
||||
const struct can_bittiming *bt = &priv->can.bittiming;
|
||||
const struct can_bittiming *dbt = &priv->can.data_bittiming;
|
||||
u32 val = 0;
|
||||
s8 tdco;
|
||||
u32 tdcmod, val = 0;
|
||||
int err;
|
||||
|
||||
/* CAN Control Register
|
||||
@@ -575,11 +592,16 @@ static int mcp251xfd_set_bittiming(const struct mcp251xfd_priv *priv)
|
||||
return err;
|
||||
|
||||
/* Transmitter Delay Compensation */
|
||||
tdco = clamp_t(int, dbt->brp * (dbt->prop_seg + dbt->phase_seg1),
|
||||
-64, 63);
|
||||
val = FIELD_PREP(MCP251XFD_REG_TDC_TDCMOD_MASK,
|
||||
MCP251XFD_REG_TDC_TDCMOD_AUTO) |
|
||||
FIELD_PREP(MCP251XFD_REG_TDC_TDCO_MASK, tdco);
|
||||
if (priv->can.ctrlmode & CAN_CTRLMODE_TDC_AUTO)
|
||||
tdcmod = MCP251XFD_REG_TDC_TDCMOD_AUTO;
|
||||
else if (priv->can.ctrlmode & CAN_CTRLMODE_TDC_MANUAL)
|
||||
tdcmod = MCP251XFD_REG_TDC_TDCMOD_MANUAL;
|
||||
else
|
||||
tdcmod = MCP251XFD_REG_TDC_TDCMOD_DISABLED;
|
||||
|
||||
val = FIELD_PREP(MCP251XFD_REG_TDC_TDCMOD_MASK, tdcmod) |
|
||||
FIELD_PREP(MCP251XFD_REG_TDC_TDCV_MASK, priv->can.tdc.tdcv) |
|
||||
FIELD_PREP(MCP251XFD_REG_TDC_TDCO_MASK, priv->can.tdc.tdco);
|
||||
|
||||
return regmap_write(priv->map_reg, MCP251XFD_REG_TDC, val);
|
||||
}
|
||||
@@ -2083,10 +2105,12 @@ static int mcp251xfd_probe(struct spi_device *spi)
|
||||
priv->can.do_get_berr_counter = mcp251xfd_get_berr_counter;
|
||||
priv->can.bittiming_const = &mcp251xfd_bittiming_const;
|
||||
priv->can.data_bittiming_const = &mcp251xfd_data_bittiming_const;
|
||||
priv->can.tdc_const = &mcp251xfd_tdc_const;
|
||||
priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
|
||||
CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_BERR_REPORTING |
|
||||
CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO |
|
||||
CAN_CTRLMODE_CC_LEN8_DLC;
|
||||
CAN_CTRLMODE_CC_LEN8_DLC | CAN_CTRLMODE_TDC_AUTO |
|
||||
CAN_CTRLMODE_TDC_MANUAL;
|
||||
set_bit(MCP251XFD_FLAGS_DOWN, priv->flags);
|
||||
priv->ndev = ndev;
|
||||
priv->spi = spi;
|
||||
@@ -2174,8 +2198,8 @@ static void mcp251xfd_remove(struct spi_device *spi)
|
||||
struct mcp251xfd_priv *priv = spi_get_drvdata(spi);
|
||||
struct net_device *ndev = priv->ndev;
|
||||
|
||||
can_rx_offload_del(&priv->offload);
|
||||
mcp251xfd_unregister(priv);
|
||||
can_rx_offload_del(&priv->offload);
|
||||
spi->max_speed_hz = priv->spi_max_speed_hz_orig;
|
||||
free_candev(ndev);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// SPDX-FileCopyrightText: Copyright Red Hat
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/pci.h>
|
||||
@@ -9,27 +8,21 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/xarray.h>
|
||||
#include "ice_adapter.h"
|
||||
#include "ice.h"
|
||||
|
||||
static DEFINE_XARRAY(ice_adapters);
|
||||
static DEFINE_MUTEX(ice_adapters_mutex);
|
||||
|
||||
/* PCI bus number is 8 bits. Slot is 5 bits. Domain can have the rest. */
|
||||
#define INDEX_FIELD_DOMAIN GENMASK(BITS_PER_LONG - 1, 13)
|
||||
#define INDEX_FIELD_BUS GENMASK(12, 5)
|
||||
#define INDEX_FIELD_SLOT GENMASK(4, 0)
|
||||
|
||||
static unsigned long ice_adapter_index(const struct pci_dev *pdev)
|
||||
static unsigned long ice_adapter_index(u64 dsn)
|
||||
{
|
||||
unsigned int domain = pci_domain_nr(pdev->bus);
|
||||
|
||||
WARN_ON(domain > FIELD_MAX(INDEX_FIELD_DOMAIN));
|
||||
|
||||
return FIELD_PREP(INDEX_FIELD_DOMAIN, domain) |
|
||||
FIELD_PREP(INDEX_FIELD_BUS, pdev->bus->number) |
|
||||
FIELD_PREP(INDEX_FIELD_SLOT, PCI_SLOT(pdev->devfn));
|
||||
#if BITS_PER_LONG == 64
|
||||
return dsn;
|
||||
#else
|
||||
return (u32)dsn ^ (u32)(dsn >> 32);
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct ice_adapter *ice_adapter_new(void)
|
||||
static struct ice_adapter *ice_adapter_new(u64 dsn)
|
||||
{
|
||||
struct ice_adapter *adapter;
|
||||
|
||||
@@ -37,6 +30,7 @@ static struct ice_adapter *ice_adapter_new(void)
|
||||
if (!adapter)
|
||||
return NULL;
|
||||
|
||||
adapter->device_serial_number = dsn;
|
||||
spin_lock_init(&adapter->ptp_gltsyn_time_lock);
|
||||
refcount_set(&adapter->refcount, 1);
|
||||
|
||||
@@ -67,23 +61,26 @@ static void ice_adapter_free(struct ice_adapter *adapter)
|
||||
* Return: Pointer to ice_adapter on success.
|
||||
* ERR_PTR() on error. -ENOMEM is the only possible error.
|
||||
*/
|
||||
struct ice_adapter *ice_adapter_get(const struct pci_dev *pdev)
|
||||
struct ice_adapter *ice_adapter_get(struct pci_dev *pdev)
|
||||
{
|
||||
unsigned long index = ice_adapter_index(pdev);
|
||||
u64 dsn = pci_get_dsn(pdev);
|
||||
struct ice_adapter *adapter;
|
||||
unsigned long index;
|
||||
int err;
|
||||
|
||||
index = ice_adapter_index(dsn);
|
||||
scoped_guard(mutex, &ice_adapters_mutex) {
|
||||
err = xa_insert(&ice_adapters, index, NULL, GFP_KERNEL);
|
||||
if (err == -EBUSY) {
|
||||
adapter = xa_load(&ice_adapters, index);
|
||||
refcount_inc(&adapter->refcount);
|
||||
WARN_ON_ONCE(adapter->device_serial_number != dsn);
|
||||
return adapter;
|
||||
}
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
|
||||
adapter = ice_adapter_new();
|
||||
adapter = ice_adapter_new(dsn);
|
||||
if (!adapter)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
xa_store(&ice_adapters, index, adapter, GFP_KERNEL);
|
||||
@@ -100,11 +97,13 @@ struct ice_adapter *ice_adapter_get(const struct pci_dev *pdev)
|
||||
*
|
||||
* Context: Process, may sleep.
|
||||
*/
|
||||
void ice_adapter_put(const struct pci_dev *pdev)
|
||||
void ice_adapter_put(struct pci_dev *pdev)
|
||||
{
|
||||
unsigned long index = ice_adapter_index(pdev);
|
||||
u64 dsn = pci_get_dsn(pdev);
|
||||
struct ice_adapter *adapter;
|
||||
unsigned long index;
|
||||
|
||||
index = ice_adapter_index(dsn);
|
||||
scoped_guard(mutex, &ice_adapters_mutex) {
|
||||
adapter = xa_load(&ice_adapters, index);
|
||||
if (WARN_ON(!adapter))
|
||||
|
||||
@@ -32,6 +32,7 @@ struct ice_port_list {
|
||||
* @refcount: Reference count. struct ice_pf objects hold the references.
|
||||
* @ctrl_pf: Control PF of the adapter
|
||||
* @ports: Ports list
|
||||
* @device_serial_number: DSN cached for collision detection on 32bit systems
|
||||
*/
|
||||
struct ice_adapter {
|
||||
refcount_t refcount;
|
||||
@@ -40,9 +41,10 @@ struct ice_adapter {
|
||||
|
||||
struct ice_pf *ctrl_pf;
|
||||
struct ice_port_list ports;
|
||||
u64 device_serial_number;
|
||||
};
|
||||
|
||||
struct ice_adapter *ice_adapter_get(const struct pci_dev *pdev);
|
||||
void ice_adapter_put(const struct pci_dev *pdev);
|
||||
struct ice_adapter *ice_adapter_get(struct pci_dev *pdev);
|
||||
void ice_adapter_put(struct pci_dev *pdev);
|
||||
|
||||
#endif /* _ICE_ADAPTER_H */
|
||||
|
||||
@@ -3140,11 +3140,19 @@ static int mtk_dma_init(struct mtk_eth *eth)
|
||||
static void mtk_dma_free(struct mtk_eth *eth)
|
||||
{
|
||||
const struct mtk_soc_data *soc = eth->soc;
|
||||
int i;
|
||||
int i, j, txqs = 1;
|
||||
|
||||
if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA))
|
||||
txqs = MTK_QDMA_NUM_QUEUES;
|
||||
|
||||
for (i = 0; i < MTK_MAX_DEVS; i++) {
|
||||
if (!eth->netdev[i])
|
||||
continue;
|
||||
|
||||
for (j = 0; j < txqs; j++)
|
||||
netdev_tx_reset_subqueue(eth->netdev[i], j);
|
||||
}
|
||||
|
||||
for (i = 0; i < MTK_MAX_DEVS; i++)
|
||||
if (eth->netdev[i])
|
||||
netdev_reset_queue(eth->netdev[i]);
|
||||
if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && eth->scratch_ring) {
|
||||
dma_free_coherent(eth->dma_dev,
|
||||
MTK_QDMA_RING_SIZE * soc->tx.desc_size,
|
||||
@@ -3419,9 +3427,6 @@ static int mtk_open(struct net_device *dev)
|
||||
}
|
||||
mtk_gdm_config(eth, target_mac->id, gdm_config);
|
||||
}
|
||||
/* Reset and enable PSE */
|
||||
mtk_w32(eth, RST_GL_PSE, MTK_RST_GL);
|
||||
mtk_w32(eth, 0, MTK_RST_GL);
|
||||
|
||||
napi_enable(ð->tx_napi);
|
||||
napi_enable(ð->rx_napi);
|
||||
|
||||
@@ -298,6 +298,10 @@ struct send_queue {
|
||||
|
||||
/* Record whether sq is in reset state. */
|
||||
bool reset;
|
||||
|
||||
struct xsk_buff_pool *xsk_pool;
|
||||
|
||||
dma_addr_t xsk_hdr_dma_addr;
|
||||
};
|
||||
|
||||
/* Internal representation of a receive virtqueue */
|
||||
@@ -501,6 +505,8 @@ struct virtio_net_common_hdr {
|
||||
};
|
||||
};
|
||||
|
||||
static struct virtio_net_common_hdr xsk_hdr;
|
||||
|
||||
static void virtnet_sq_free_unused_buf(struct virtqueue *vq, void *buf);
|
||||
static void virtnet_sq_free_unused_buf_done(struct virtqueue *vq);
|
||||
static int virtnet_xdp_handler(struct bpf_prog *xdp_prog, struct xdp_buff *xdp,
|
||||
@@ -5556,6 +5562,29 @@ unreg:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int virtnet_sq_bind_xsk_pool(struct virtnet_info *vi,
|
||||
struct send_queue *sq,
|
||||
struct xsk_buff_pool *pool)
|
||||
{
|
||||
int err, qindex;
|
||||
|
||||
qindex = sq - vi->sq;
|
||||
|
||||
virtnet_tx_pause(vi, sq);
|
||||
|
||||
err = virtqueue_reset(sq->vq, virtnet_sq_free_unused_buf);
|
||||
if (err) {
|
||||
netdev_err(vi->dev, "reset tx fail: tx queue index: %d err: %d\n", qindex, err);
|
||||
pool = NULL;
|
||||
}
|
||||
|
||||
sq->xsk_pool = pool;
|
||||
|
||||
virtnet_tx_resume(vi, sq);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int virtnet_xsk_pool_enable(struct net_device *dev,
|
||||
struct xsk_buff_pool *pool,
|
||||
u16 qid)
|
||||
@@ -5564,6 +5593,7 @@ static int virtnet_xsk_pool_enable(struct net_device *dev,
|
||||
struct receive_queue *rq;
|
||||
struct device *dma_dev;
|
||||
struct send_queue *sq;
|
||||
dma_addr_t hdr_dma;
|
||||
int err, size;
|
||||
|
||||
if (vi->hdr_len > xsk_pool_get_headroom(pool))
|
||||
@@ -5601,6 +5631,13 @@ static int virtnet_xsk_pool_enable(struct net_device *dev,
|
||||
if (!rq->xsk_buffs)
|
||||
return -ENOMEM;
|
||||
|
||||
hdr_dma = virtqueue_dma_map_single_attrs(sq->vq, &xsk_hdr, vi->hdr_len,
|
||||
DMA_TO_DEVICE, 0);
|
||||
if (virtqueue_dma_mapping_error(sq->vq, hdr_dma)) {
|
||||
err = -ENOMEM;
|
||||
goto err_free_buffs;
|
||||
}
|
||||
|
||||
err = xsk_pool_dma_map(pool, dma_dev, 0);
|
||||
if (err)
|
||||
goto err_xsk_map;
|
||||
@@ -5609,11 +5646,26 @@ static int virtnet_xsk_pool_enable(struct net_device *dev,
|
||||
if (err)
|
||||
goto err_rq;
|
||||
|
||||
err = virtnet_sq_bind_xsk_pool(vi, sq, pool);
|
||||
if (err)
|
||||
goto err_sq;
|
||||
|
||||
/* Now, we do not support tx offload(such as tx csum), so all the tx
|
||||
* virtnet hdr is zero. So all the tx packets can share a single hdr.
|
||||
*/
|
||||
sq->xsk_hdr_dma_addr = hdr_dma;
|
||||
|
||||
return 0;
|
||||
|
||||
err_sq:
|
||||
virtnet_rq_bind_xsk_pool(vi, rq, NULL);
|
||||
err_rq:
|
||||
xsk_pool_dma_unmap(pool, 0);
|
||||
err_xsk_map:
|
||||
virtqueue_dma_unmap_single_attrs(rq->vq, hdr_dma, vi->hdr_len,
|
||||
DMA_TO_DEVICE, 0);
|
||||
err_free_buffs:
|
||||
kvfree(rq->xsk_buffs);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -5622,19 +5674,24 @@ static int virtnet_xsk_pool_disable(struct net_device *dev, u16 qid)
|
||||
struct virtnet_info *vi = netdev_priv(dev);
|
||||
struct xsk_buff_pool *pool;
|
||||
struct receive_queue *rq;
|
||||
struct send_queue *sq;
|
||||
int err;
|
||||
|
||||
if (qid >= vi->curr_queue_pairs)
|
||||
return -EINVAL;
|
||||
|
||||
sq = &vi->sq[qid];
|
||||
rq = &vi->rq[qid];
|
||||
|
||||
pool = rq->xsk_pool;
|
||||
|
||||
err = virtnet_rq_bind_xsk_pool(vi, rq, NULL);
|
||||
err |= virtnet_sq_bind_xsk_pool(vi, sq, NULL);
|
||||
|
||||
xsk_pool_dma_unmap(pool, 0);
|
||||
|
||||
virtqueue_dma_unmap_single_attrs(sq->vq, sq->xsk_hdr_dma_addr,
|
||||
vi->hdr_len, DMA_TO_DEVICE, 0);
|
||||
kvfree(rq->xsk_buffs);
|
||||
|
||||
return err;
|
||||
|
||||
@@ -59,7 +59,6 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
|
||||
|
||||
pdev = pci_get_slot(zdev->zbus->bus, zdev->devfn);
|
||||
if (pdev && pci_num_vf(pdev)) {
|
||||
pci_dev_put(pdev);
|
||||
rc = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1658,14 +1658,14 @@ static vm_fault_t vfio_pci_mmap_huge_fault(struct vm_fault *vmf,
|
||||
{
|
||||
struct vm_area_struct *vma = vmf->vma;
|
||||
struct vfio_pci_core_device *vdev = vma->vm_private_data;
|
||||
unsigned long pfn, pgoff = vmf->pgoff - vma->vm_pgoff;
|
||||
unsigned long addr = vmf->address & ~((PAGE_SIZE << order) - 1);
|
||||
unsigned long pgoff = (addr - vma->vm_start) >> PAGE_SHIFT;
|
||||
unsigned long pfn = vma_to_pfn(vma) + pgoff;
|
||||
vm_fault_t ret = VM_FAULT_SIGBUS;
|
||||
|
||||
pfn = vma_to_pfn(vma) + pgoff;
|
||||
|
||||
if (order && (pfn & ((1 << order) - 1) ||
|
||||
vmf->address & ((PAGE_SIZE << order) - 1) ||
|
||||
vmf->address + (PAGE_SIZE << order) > vma->vm_end)) {
|
||||
if (order && (addr < vma->vm_start ||
|
||||
addr + (PAGE_SIZE << order) > vma->vm_end ||
|
||||
pfn & ((1 << order) - 1))) {
|
||||
ret = VM_FAULT_FALLBACK;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -732,82 +732,6 @@ const u8 *btrfs_sb_fsid_ptr(const struct btrfs_super_block *sb)
|
||||
return has_metadata_uuid ? sb->metadata_uuid : sb->fsid;
|
||||
}
|
||||
|
||||
/*
|
||||
* We can have very weird soft links passed in.
|
||||
* One example is "/proc/self/fd/<fd>", which can be a soft link to
|
||||
* a block device.
|
||||
*
|
||||
* But it's never a good idea to use those weird names.
|
||||
* Here we check if the path (not following symlinks) is a good one inside
|
||||
* "/dev/".
|
||||
*/
|
||||
static bool is_good_dev_path(const char *dev_path)
|
||||
{
|
||||
struct path path = { .mnt = NULL, .dentry = NULL };
|
||||
char *path_buf = NULL;
|
||||
char *resolved_path;
|
||||
bool is_good = false;
|
||||
int ret;
|
||||
|
||||
if (!dev_path)
|
||||
goto out;
|
||||
|
||||
path_buf = kmalloc(PATH_MAX, GFP_KERNEL);
|
||||
if (!path_buf)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Do not follow soft link, just check if the original path is inside
|
||||
* "/dev/".
|
||||
*/
|
||||
ret = kern_path(dev_path, 0, &path);
|
||||
if (ret)
|
||||
goto out;
|
||||
resolved_path = d_path(&path, path_buf, PATH_MAX);
|
||||
if (IS_ERR(resolved_path))
|
||||
goto out;
|
||||
if (strncmp(resolved_path, "/dev/", strlen("/dev/")))
|
||||
goto out;
|
||||
is_good = true;
|
||||
out:
|
||||
kfree(path_buf);
|
||||
path_put(&path);
|
||||
return is_good;
|
||||
}
|
||||
|
||||
static int get_canonical_dev_path(const char *dev_path, char *canonical)
|
||||
{
|
||||
struct path path = { .mnt = NULL, .dentry = NULL };
|
||||
char *path_buf = NULL;
|
||||
char *resolved_path;
|
||||
int ret;
|
||||
|
||||
if (!dev_path) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
path_buf = kmalloc(PATH_MAX, GFP_KERNEL);
|
||||
if (!path_buf) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = kern_path(dev_path, LOOKUP_FOLLOW, &path);
|
||||
if (ret)
|
||||
goto out;
|
||||
resolved_path = d_path(&path, path_buf, PATH_MAX);
|
||||
if (IS_ERR(resolved_path)) {
|
||||
ret = PTR_ERR(resolved_path);
|
||||
goto out;
|
||||
}
|
||||
ret = strscpy(canonical, resolved_path, PATH_MAX);
|
||||
out:
|
||||
kfree(path_buf);
|
||||
path_put(&path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool is_same_device(struct btrfs_device *device, const char *new_path)
|
||||
{
|
||||
struct path old = { .mnt = NULL, .dentry = NULL };
|
||||
@@ -1495,23 +1419,12 @@ struct btrfs_device *btrfs_scan_one_device(const char *path, blk_mode_t flags,
|
||||
bool new_device_added = false;
|
||||
struct btrfs_device *device = NULL;
|
||||
struct file *bdev_file;
|
||||
char *canonical_path = NULL;
|
||||
u64 bytenr;
|
||||
dev_t devt;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&uuid_mutex);
|
||||
|
||||
if (!is_good_dev_path(path)) {
|
||||
canonical_path = kmalloc(PATH_MAX, GFP_KERNEL);
|
||||
if (canonical_path) {
|
||||
ret = get_canonical_dev_path(path, canonical_path);
|
||||
if (ret < 0) {
|
||||
kfree(canonical_path);
|
||||
canonical_path = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Avoid an exclusive open here, as the systemd-udev may initiate the
|
||||
* device scan which may race with the user's mount or mkfs command,
|
||||
@@ -1556,8 +1469,7 @@ struct btrfs_device *btrfs_scan_one_device(const char *path, blk_mode_t flags,
|
||||
goto free_disk_super;
|
||||
}
|
||||
|
||||
device = device_list_add(canonical_path ? : path, disk_super,
|
||||
&new_device_added);
|
||||
device = device_list_add(path, disk_super, &new_device_added);
|
||||
if (!IS_ERR(device) && new_device_added)
|
||||
btrfs_free_stale_devices(device->devt, device);
|
||||
|
||||
@@ -1566,7 +1478,6 @@ free_disk_super:
|
||||
|
||||
error_bdev_put:
|
||||
fput(bdev_file);
|
||||
kfree(canonical_path);
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
@@ -150,10 +150,10 @@ io_retry:
|
||||
io->rq->bio.bi_iter.bi_sector = io->dev.m_pa >> 9;
|
||||
attached = 0;
|
||||
}
|
||||
if (!attached++)
|
||||
erofs_onlinefolio_split(folio);
|
||||
if (!bio_add_folio(&io->rq->bio, folio, len, cur))
|
||||
goto io_retry;
|
||||
if (!attached++)
|
||||
erofs_onlinefolio_split(folio);
|
||||
io->dev.m_pa += len;
|
||||
}
|
||||
cur += len;
|
||||
|
||||
@@ -1496,7 +1496,7 @@ struct lease_ctx_info *parse_lease_state(void *open_req)
|
||||
|
||||
if (le16_to_cpu(cc->DataOffset) + le32_to_cpu(cc->DataLength) <
|
||||
sizeof(struct create_lease_v2) - 4)
|
||||
return NULL;
|
||||
goto err_out;
|
||||
|
||||
memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
|
||||
lreq->req_state = lc->lcontext.LeaseState;
|
||||
@@ -1512,7 +1512,7 @@ struct lease_ctx_info *parse_lease_state(void *open_req)
|
||||
|
||||
if (le16_to_cpu(cc->DataOffset) + le32_to_cpu(cc->DataLength) <
|
||||
sizeof(struct create_lease))
|
||||
return NULL;
|
||||
goto err_out;
|
||||
|
||||
memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
|
||||
lreq->req_state = lc->lcontext.LeaseState;
|
||||
@@ -1521,6 +1521,9 @@ struct lease_ctx_info *parse_lease_state(void *open_req)
|
||||
lreq->version = 1;
|
||||
}
|
||||
return lreq;
|
||||
err_out:
|
||||
kfree(lreq);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -633,6 +633,11 @@ smb2_get_name(const char *src, const int maxlen, struct nls_table *local_nls)
|
||||
return name;
|
||||
}
|
||||
|
||||
if (*name == '\0') {
|
||||
kfree(name);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if (*name == '\\') {
|
||||
pr_err("not allow directory name included leading slash\n");
|
||||
kfree(name);
|
||||
|
||||
@@ -443,6 +443,13 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (v_len <= *pos) {
|
||||
pr_err("stream write position %lld is out of bounds (stream length: %zd)\n",
|
||||
*pos, v_len);
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (v_len < size) {
|
||||
wbuf = kvzalloc(size, KSMBD_DEFAULT_GFP);
|
||||
if (!wbuf) {
|
||||
|
||||
@@ -661,21 +661,40 @@ __close_file_table_ids(struct ksmbd_file_table *ft,
|
||||
bool (*skip)(struct ksmbd_tree_connect *tcon,
|
||||
struct ksmbd_file *fp))
|
||||
{
|
||||
unsigned int id;
|
||||
struct ksmbd_file *fp;
|
||||
int num = 0;
|
||||
struct ksmbd_file *fp;
|
||||
unsigned int id = 0;
|
||||
int num = 0;
|
||||
|
||||
idr_for_each_entry(ft->idr, fp, id) {
|
||||
if (skip(tcon, fp))
|
||||
while (1) {
|
||||
write_lock(&ft->lock);
|
||||
fp = idr_get_next(ft->idr, &id);
|
||||
if (!fp) {
|
||||
write_unlock(&ft->lock);
|
||||
break;
|
||||
}
|
||||
|
||||
if (skip(tcon, fp) ||
|
||||
!atomic_dec_and_test(&fp->refcount)) {
|
||||
id++;
|
||||
write_unlock(&ft->lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
set_close_state_blocked_works(fp);
|
||||
idr_remove(ft->idr, fp->volatile_id);
|
||||
fp->volatile_id = KSMBD_NO_FID;
|
||||
write_unlock(&ft->lock);
|
||||
|
||||
down_write(&fp->f_ci->m_lock);
|
||||
list_del_init(&fp->node);
|
||||
up_write(&fp->f_ci->m_lock);
|
||||
|
||||
if (!atomic_dec_and_test(&fp->refcount))
|
||||
continue;
|
||||
__ksmbd_close_fd(ft, fp);
|
||||
|
||||
num++;
|
||||
id++;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
@@ -1524,7 +1524,7 @@ struct ieee80211_mgmt {
|
||||
struct {
|
||||
u8 action_code;
|
||||
u8 dialog_token;
|
||||
u8 status_code;
|
||||
__le16 status_code;
|
||||
u8 variable[];
|
||||
} __packed ttlm_res;
|
||||
struct {
|
||||
|
||||
151
net/can/gw.c
151
net/can/gw.c
@@ -130,7 +130,7 @@ struct cgw_job {
|
||||
u32 handled_frames;
|
||||
u32 dropped_frames;
|
||||
u32 deleted_frames;
|
||||
struct cf_mod mod;
|
||||
struct cf_mod __rcu *cf_mod;
|
||||
union {
|
||||
/* CAN frame data source */
|
||||
struct net_device *dev;
|
||||
@@ -459,6 +459,7 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data)
|
||||
struct cgw_job *gwj = (struct cgw_job *)data;
|
||||
struct canfd_frame *cf;
|
||||
struct sk_buff *nskb;
|
||||
struct cf_mod *mod;
|
||||
int modidx = 0;
|
||||
|
||||
/* process strictly Classic CAN or CAN FD frames */
|
||||
@@ -506,7 +507,8 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data)
|
||||
* When there is at least one modification function activated,
|
||||
* we need to copy the skb as we want to modify skb->data.
|
||||
*/
|
||||
if (gwj->mod.modfunc[0])
|
||||
mod = rcu_dereference(gwj->cf_mod);
|
||||
if (mod->modfunc[0])
|
||||
nskb = skb_copy(skb, GFP_ATOMIC);
|
||||
else
|
||||
nskb = skb_clone(skb, GFP_ATOMIC);
|
||||
@@ -529,8 +531,8 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data)
|
||||
cf = (struct canfd_frame *)nskb->data;
|
||||
|
||||
/* perform preprocessed modification functions if there are any */
|
||||
while (modidx < MAX_MODFUNCTIONS && gwj->mod.modfunc[modidx])
|
||||
(*gwj->mod.modfunc[modidx++])(cf, &gwj->mod);
|
||||
while (modidx < MAX_MODFUNCTIONS && mod->modfunc[modidx])
|
||||
(*mod->modfunc[modidx++])(cf, mod);
|
||||
|
||||
/* Has the CAN frame been modified? */
|
||||
if (modidx) {
|
||||
@@ -546,11 +548,11 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data)
|
||||
}
|
||||
|
||||
/* check for checksum updates */
|
||||
if (gwj->mod.csumfunc.crc8)
|
||||
(*gwj->mod.csumfunc.crc8)(cf, &gwj->mod.csum.crc8);
|
||||
if (mod->csumfunc.crc8)
|
||||
(*mod->csumfunc.crc8)(cf, &mod->csum.crc8);
|
||||
|
||||
if (gwj->mod.csumfunc.xor)
|
||||
(*gwj->mod.csumfunc.xor)(cf, &gwj->mod.csum.xor);
|
||||
if (mod->csumfunc.xor)
|
||||
(*mod->csumfunc.xor)(cf, &mod->csum.xor);
|
||||
}
|
||||
|
||||
/* clear the skb timestamp if not configured the other way */
|
||||
@@ -581,9 +583,20 @@ static void cgw_job_free_rcu(struct rcu_head *rcu_head)
|
||||
{
|
||||
struct cgw_job *gwj = container_of(rcu_head, struct cgw_job, rcu);
|
||||
|
||||
/* cgw_job::cf_mod is always accessed from the same cgw_job object within
|
||||
* the same RCU read section. Once cgw_job is scheduled for removal,
|
||||
* cf_mod can also be removed without mandating an additional grace period.
|
||||
*/
|
||||
kfree(rcu_access_pointer(gwj->cf_mod));
|
||||
kmem_cache_free(cgw_cache, gwj);
|
||||
}
|
||||
|
||||
/* Return cgw_job::cf_mod with RTNL protected section */
|
||||
static struct cf_mod *cgw_job_cf_mod(struct cgw_job *gwj)
|
||||
{
|
||||
return rcu_dereference_protected(gwj->cf_mod, rtnl_is_locked());
|
||||
}
|
||||
|
||||
static int cgw_notifier(struct notifier_block *nb,
|
||||
unsigned long msg, void *ptr)
|
||||
{
|
||||
@@ -616,6 +629,7 @@ static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj, int type,
|
||||
{
|
||||
struct rtcanmsg *rtcan;
|
||||
struct nlmsghdr *nlh;
|
||||
struct cf_mod *mod;
|
||||
|
||||
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*rtcan), flags);
|
||||
if (!nlh)
|
||||
@@ -650,82 +664,83 @@ static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj, int type,
|
||||
goto cancel;
|
||||
}
|
||||
|
||||
mod = cgw_job_cf_mod(gwj);
|
||||
if (gwj->flags & CGW_FLAGS_CAN_FD) {
|
||||
struct cgw_fdframe_mod mb;
|
||||
|
||||
if (gwj->mod.modtype.and) {
|
||||
memcpy(&mb.cf, &gwj->mod.modframe.and, sizeof(mb.cf));
|
||||
mb.modtype = gwj->mod.modtype.and;
|
||||
if (mod->modtype.and) {
|
||||
memcpy(&mb.cf, &mod->modframe.and, sizeof(mb.cf));
|
||||
mb.modtype = mod->modtype.and;
|
||||
if (nla_put(skb, CGW_FDMOD_AND, sizeof(mb), &mb) < 0)
|
||||
goto cancel;
|
||||
}
|
||||
|
||||
if (gwj->mod.modtype.or) {
|
||||
memcpy(&mb.cf, &gwj->mod.modframe.or, sizeof(mb.cf));
|
||||
mb.modtype = gwj->mod.modtype.or;
|
||||
if (mod->modtype.or) {
|
||||
memcpy(&mb.cf, &mod->modframe.or, sizeof(mb.cf));
|
||||
mb.modtype = mod->modtype.or;
|
||||
if (nla_put(skb, CGW_FDMOD_OR, sizeof(mb), &mb) < 0)
|
||||
goto cancel;
|
||||
}
|
||||
|
||||
if (gwj->mod.modtype.xor) {
|
||||
memcpy(&mb.cf, &gwj->mod.modframe.xor, sizeof(mb.cf));
|
||||
mb.modtype = gwj->mod.modtype.xor;
|
||||
if (mod->modtype.xor) {
|
||||
memcpy(&mb.cf, &mod->modframe.xor, sizeof(mb.cf));
|
||||
mb.modtype = mod->modtype.xor;
|
||||
if (nla_put(skb, CGW_FDMOD_XOR, sizeof(mb), &mb) < 0)
|
||||
goto cancel;
|
||||
}
|
||||
|
||||
if (gwj->mod.modtype.set) {
|
||||
memcpy(&mb.cf, &gwj->mod.modframe.set, sizeof(mb.cf));
|
||||
mb.modtype = gwj->mod.modtype.set;
|
||||
if (mod->modtype.set) {
|
||||
memcpy(&mb.cf, &mod->modframe.set, sizeof(mb.cf));
|
||||
mb.modtype = mod->modtype.set;
|
||||
if (nla_put(skb, CGW_FDMOD_SET, sizeof(mb), &mb) < 0)
|
||||
goto cancel;
|
||||
}
|
||||
} else {
|
||||
struct cgw_frame_mod mb;
|
||||
|
||||
if (gwj->mod.modtype.and) {
|
||||
memcpy(&mb.cf, &gwj->mod.modframe.and, sizeof(mb.cf));
|
||||
mb.modtype = gwj->mod.modtype.and;
|
||||
if (mod->modtype.and) {
|
||||
memcpy(&mb.cf, &mod->modframe.and, sizeof(mb.cf));
|
||||
mb.modtype = mod->modtype.and;
|
||||
if (nla_put(skb, CGW_MOD_AND, sizeof(mb), &mb) < 0)
|
||||
goto cancel;
|
||||
}
|
||||
|
||||
if (gwj->mod.modtype.or) {
|
||||
memcpy(&mb.cf, &gwj->mod.modframe.or, sizeof(mb.cf));
|
||||
mb.modtype = gwj->mod.modtype.or;
|
||||
if (mod->modtype.or) {
|
||||
memcpy(&mb.cf, &mod->modframe.or, sizeof(mb.cf));
|
||||
mb.modtype = mod->modtype.or;
|
||||
if (nla_put(skb, CGW_MOD_OR, sizeof(mb), &mb) < 0)
|
||||
goto cancel;
|
||||
}
|
||||
|
||||
if (gwj->mod.modtype.xor) {
|
||||
memcpy(&mb.cf, &gwj->mod.modframe.xor, sizeof(mb.cf));
|
||||
mb.modtype = gwj->mod.modtype.xor;
|
||||
if (mod->modtype.xor) {
|
||||
memcpy(&mb.cf, &mod->modframe.xor, sizeof(mb.cf));
|
||||
mb.modtype = mod->modtype.xor;
|
||||
if (nla_put(skb, CGW_MOD_XOR, sizeof(mb), &mb) < 0)
|
||||
goto cancel;
|
||||
}
|
||||
|
||||
if (gwj->mod.modtype.set) {
|
||||
memcpy(&mb.cf, &gwj->mod.modframe.set, sizeof(mb.cf));
|
||||
mb.modtype = gwj->mod.modtype.set;
|
||||
if (mod->modtype.set) {
|
||||
memcpy(&mb.cf, &mod->modframe.set, sizeof(mb.cf));
|
||||
mb.modtype = mod->modtype.set;
|
||||
if (nla_put(skb, CGW_MOD_SET, sizeof(mb), &mb) < 0)
|
||||
goto cancel;
|
||||
}
|
||||
}
|
||||
|
||||
if (gwj->mod.uid) {
|
||||
if (nla_put_u32(skb, CGW_MOD_UID, gwj->mod.uid) < 0)
|
||||
if (mod->uid) {
|
||||
if (nla_put_u32(skb, CGW_MOD_UID, mod->uid) < 0)
|
||||
goto cancel;
|
||||
}
|
||||
|
||||
if (gwj->mod.csumfunc.crc8) {
|
||||
if (mod->csumfunc.crc8) {
|
||||
if (nla_put(skb, CGW_CS_CRC8, CGW_CS_CRC8_LEN,
|
||||
&gwj->mod.csum.crc8) < 0)
|
||||
&mod->csum.crc8) < 0)
|
||||
goto cancel;
|
||||
}
|
||||
|
||||
if (gwj->mod.csumfunc.xor) {
|
||||
if (mod->csumfunc.xor) {
|
||||
if (nla_put(skb, CGW_CS_XOR, CGW_CS_XOR_LEN,
|
||||
&gwj->mod.csum.xor) < 0)
|
||||
&mod->csum.xor) < 0)
|
||||
goto cancel;
|
||||
}
|
||||
|
||||
@@ -1059,7 +1074,7 @@ static int cgw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
struct net *net = sock_net(skb->sk);
|
||||
struct rtcanmsg *r;
|
||||
struct cgw_job *gwj;
|
||||
struct cf_mod mod;
|
||||
struct cf_mod *mod;
|
||||
struct can_can_gw ccgw;
|
||||
u8 limhops = 0;
|
||||
int err = 0;
|
||||
@@ -1078,37 +1093,48 @@ static int cgw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
if (r->gwtype != CGW_TYPE_CAN_CAN)
|
||||
return -EINVAL;
|
||||
|
||||
err = cgw_parse_attr(nlh, &mod, CGW_TYPE_CAN_CAN, &ccgw, &limhops);
|
||||
if (err < 0)
|
||||
return err;
|
||||
mod = kmalloc(sizeof(*mod), GFP_KERNEL);
|
||||
if (!mod)
|
||||
return -ENOMEM;
|
||||
|
||||
if (mod.uid) {
|
||||
err = cgw_parse_attr(nlh, mod, CGW_TYPE_CAN_CAN, &ccgw, &limhops);
|
||||
if (err < 0)
|
||||
goto out_free_cf;
|
||||
|
||||
if (mod->uid) {
|
||||
ASSERT_RTNL();
|
||||
|
||||
/* check for updating an existing job with identical uid */
|
||||
hlist_for_each_entry(gwj, &net->can.cgw_list, list) {
|
||||
if (gwj->mod.uid != mod.uid)
|
||||
struct cf_mod *old_cf;
|
||||
|
||||
old_cf = cgw_job_cf_mod(gwj);
|
||||
if (old_cf->uid != mod->uid)
|
||||
continue;
|
||||
|
||||
/* interfaces & filters must be identical */
|
||||
if (memcmp(&gwj->ccgw, &ccgw, sizeof(ccgw)))
|
||||
return -EINVAL;
|
||||
if (memcmp(&gwj->ccgw, &ccgw, sizeof(ccgw))) {
|
||||
err = -EINVAL;
|
||||
goto out_free_cf;
|
||||
}
|
||||
|
||||
/* update modifications with disabled softirq & quit */
|
||||
local_bh_disable();
|
||||
memcpy(&gwj->mod, &mod, sizeof(mod));
|
||||
local_bh_enable();
|
||||
rcu_assign_pointer(gwj->cf_mod, mod);
|
||||
kfree_rcu_mightsleep(old_cf);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ifindex == 0 is not allowed for job creation */
|
||||
if (!ccgw.src_idx || !ccgw.dst_idx)
|
||||
return -ENODEV;
|
||||
if (!ccgw.src_idx || !ccgw.dst_idx) {
|
||||
err = -ENODEV;
|
||||
goto out_free_cf;
|
||||
}
|
||||
|
||||
gwj = kmem_cache_alloc(cgw_cache, GFP_KERNEL);
|
||||
if (!gwj)
|
||||
return -ENOMEM;
|
||||
if (!gwj) {
|
||||
err = -ENOMEM;
|
||||
goto out_free_cf;
|
||||
}
|
||||
|
||||
gwj->handled_frames = 0;
|
||||
gwj->dropped_frames = 0;
|
||||
@@ -1118,7 +1144,7 @@ static int cgw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
gwj->limit_hops = limhops;
|
||||
|
||||
/* insert already parsed information */
|
||||
memcpy(&gwj->mod, &mod, sizeof(mod));
|
||||
RCU_INIT_POINTER(gwj->cf_mod, mod);
|
||||
memcpy(&gwj->ccgw, &ccgw, sizeof(ccgw));
|
||||
|
||||
err = -ENODEV;
|
||||
@@ -1152,9 +1178,11 @@ static int cgw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
if (!err)
|
||||
hlist_add_head_rcu(&gwj->list, &net->can.cgw_list);
|
||||
out:
|
||||
if (err)
|
||||
if (err) {
|
||||
kmem_cache_free(cgw_cache, gwj);
|
||||
|
||||
out_free_cf:
|
||||
kfree(mod);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1214,19 +1242,22 @@ static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
|
||||
/* remove only the first matching entry */
|
||||
hlist_for_each_entry_safe(gwj, nx, &net->can.cgw_list, list) {
|
||||
struct cf_mod *cf_mod;
|
||||
|
||||
if (gwj->flags != r->flags)
|
||||
continue;
|
||||
|
||||
if (gwj->limit_hops != limhops)
|
||||
continue;
|
||||
|
||||
cf_mod = cgw_job_cf_mod(gwj);
|
||||
/* we have a match when uid is enabled and identical */
|
||||
if (gwj->mod.uid || mod.uid) {
|
||||
if (gwj->mod.uid != mod.uid)
|
||||
if (cf_mod->uid || mod.uid) {
|
||||
if (cf_mod->uid != mod.uid)
|
||||
continue;
|
||||
} else {
|
||||
/* no uid => check for identical modifications */
|
||||
if (memcmp(&gwj->mod, &mod, sizeof(mod)))
|
||||
if (memcmp(cf_mod, &mod, sizeof(mod)))
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -3259,16 +3259,13 @@ static void add_v4_addrs(struct inet6_dev *idev)
|
||||
struct in6_addr addr;
|
||||
struct net_device *dev;
|
||||
struct net *net = dev_net(idev->dev);
|
||||
int scope, plen, offset = 0;
|
||||
int scope, plen;
|
||||
u32 pflags = 0;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
memset(&addr, 0, sizeof(struct in6_addr));
|
||||
/* in case of IP6GRE the dev_addr is an IPv6 and therefore we use only the last 4 bytes */
|
||||
if (idev->dev->addr_len == sizeof(struct in6_addr))
|
||||
offset = sizeof(struct in6_addr) - 4;
|
||||
memcpy(&addr.s6_addr32[3], idev->dev->dev_addr + offset, 4);
|
||||
memcpy(&addr.s6_addr32[3], idev->dev->dev_addr, 4);
|
||||
|
||||
if (!(idev->dev->flags & IFF_POINTOPOINT) && idev->dev->type == ARPHRD_SIT) {
|
||||
scope = IPV6_ADDR_COMPATv4;
|
||||
@@ -3579,7 +3576,13 @@ static void addrconf_gre_config(struct net_device *dev)
|
||||
return;
|
||||
}
|
||||
|
||||
if (dev->type == ARPHRD_ETHER) {
|
||||
/* Generate the IPv6 link-local address using addrconf_addr_gen(),
|
||||
* unless we have an IPv4 GRE device not bound to an IP address and
|
||||
* which is in EUI64 mode (as __ipv6_isatap_ifid() would fail in this
|
||||
* case). Such devices fall back to add_v4_addrs() instead.
|
||||
*/
|
||||
if (!(dev->type == ARPHRD_IPGRE && *(__be32 *)dev->dev_addr == 0 &&
|
||||
idev->cnf.addr_gen_mode == IN6_ADDR_GEN_MODE_EUI64)) {
|
||||
addrconf_addr_gen(idev, true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -7177,6 +7177,7 @@ ieee80211_send_neg_ttlm_res(struct ieee80211_sub_if_data *sdata,
|
||||
int hdr_len = offsetofend(struct ieee80211_mgmt, u.action.u.ttlm_res);
|
||||
int ttlm_max_len = 2 + 1 + sizeof(struct ieee80211_ttlm_elem) + 1 +
|
||||
2 * 2 * IEEE80211_TTLM_NUM_TIDS;
|
||||
u16 status_code;
|
||||
|
||||
skb = dev_alloc_skb(local->tx_headroom + hdr_len + ttlm_max_len);
|
||||
if (!skb)
|
||||
@@ -7199,19 +7200,18 @@ ieee80211_send_neg_ttlm_res(struct ieee80211_sub_if_data *sdata,
|
||||
WARN_ON(1);
|
||||
fallthrough;
|
||||
case NEG_TTLM_RES_REJECT:
|
||||
mgmt->u.action.u.ttlm_res.status_code =
|
||||
WLAN_STATUS_DENIED_TID_TO_LINK_MAPPING;
|
||||
status_code = WLAN_STATUS_DENIED_TID_TO_LINK_MAPPING;
|
||||
break;
|
||||
case NEG_TTLM_RES_ACCEPT:
|
||||
mgmt->u.action.u.ttlm_res.status_code = WLAN_STATUS_SUCCESS;
|
||||
status_code = WLAN_STATUS_SUCCESS;
|
||||
break;
|
||||
case NEG_TTLM_RES_SUGGEST_PREFERRED:
|
||||
mgmt->u.action.u.ttlm_res.status_code =
|
||||
WLAN_STATUS_PREF_TID_TO_LINK_MAPPING_SUGGESTED;
|
||||
status_code = WLAN_STATUS_PREF_TID_TO_LINK_MAPPING_SUGGESTED;
|
||||
ieee80211_neg_ttlm_add_suggested_map(skb, neg_ttlm);
|
||||
break;
|
||||
}
|
||||
|
||||
mgmt->u.action.u.ttlm_res.status_code = cpu_to_le16(status_code);
|
||||
ieee80211_tx_skb(sdata, skb);
|
||||
}
|
||||
|
||||
@@ -7377,7 +7377,7 @@ void ieee80211_process_neg_ttlm_res(struct ieee80211_sub_if_data *sdata,
|
||||
* This can be better implemented in the future, to handle request
|
||||
* rejections.
|
||||
*/
|
||||
if (mgmt->u.action.u.ttlm_res.status_code != WLAN_STATUS_SUCCESS)
|
||||
if (le16_to_cpu(mgmt->u.action.u.ttlm_res.status_code) != WLAN_STATUS_SUCCESS)
|
||||
__ieee80211_disconnect(sdata);
|
||||
}
|
||||
|
||||
|
||||
@@ -975,8 +975,7 @@ static int output_userspace(struct datapath *dp, struct sk_buff *skb,
|
||||
upcall.cmd = OVS_PACKET_CMD_ACTION;
|
||||
upcall.mru = OVS_CB(skb)->mru;
|
||||
|
||||
for (a = nla_data(attr), rem = nla_len(attr); rem > 0;
|
||||
a = nla_next(a, &rem)) {
|
||||
nla_for_each_nested(a, attr, rem) {
|
||||
switch (nla_type(a)) {
|
||||
case OVS_USERSPACE_ATTR_USERDATA:
|
||||
upcall.userdata = a;
|
||||
|
||||
@@ -348,7 +348,8 @@ static void htb_add_to_wait_tree(struct htb_sched *q,
|
||||
*/
|
||||
static inline void htb_next_rb_node(struct rb_node **n)
|
||||
{
|
||||
*n = rb_next(*n);
|
||||
if (*n)
|
||||
*n = rb_next(*n);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -609,8 +610,8 @@ static inline void htb_activate(struct htb_sched *q, struct htb_class *cl)
|
||||
*/
|
||||
static inline void htb_deactivate(struct htb_sched *q, struct htb_class *cl)
|
||||
{
|
||||
WARN_ON(!cl->prio_activity);
|
||||
|
||||
if (!cl->prio_activity)
|
||||
return;
|
||||
htb_deactivate_prios(q, cl);
|
||||
cl->prio_activity = 0;
|
||||
}
|
||||
@@ -1485,8 +1486,6 @@ static void htb_qlen_notify(struct Qdisc *sch, unsigned long arg)
|
||||
{
|
||||
struct htb_class *cl = (struct htb_class *)arg;
|
||||
|
||||
if (!cl->prio_activity)
|
||||
return;
|
||||
htb_deactivate(qdisc_priv(sch), cl);
|
||||
}
|
||||
|
||||
@@ -1740,8 +1739,7 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg,
|
||||
if (cl->parent)
|
||||
cl->parent->children--;
|
||||
|
||||
if (cl->prio_activity)
|
||||
htb_deactivate(q, cl);
|
||||
htb_deactivate(q, cl);
|
||||
|
||||
if (cl->cmode != HTB_CAN_SEND)
|
||||
htb_safe_rb_erase(&cl->pq_node,
|
||||
@@ -1949,8 +1947,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
|
||||
/* turn parent into inner node */
|
||||
qdisc_purge_queue(parent->leaf.q);
|
||||
parent_qdisc = parent->leaf.q;
|
||||
if (parent->prio_activity)
|
||||
htb_deactivate(q, parent);
|
||||
htb_deactivate(q, parent);
|
||||
|
||||
/* remove from evt list because of level change */
|
||||
if (parent->cmode != HTB_CAN_SEND) {
|
||||
|
||||
Reference in New Issue
Block a user