mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-07 14:32:23 +00:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Cross-merge networking fixes after downstream PR. Conflicts: drivers/net/ethernet/broadcom/bnxt/bnxt.cf7ce5eb2cb
("bnxt_en: Fix crash in bnxt_get_max_rss_ctx_ring()")20c8ad72eb
("eth: bnxt: use the RSS context XArray instead of the local list") Adjacent changes: net/ethtool/ioctl.c503757c809
("net: ethtool: Fix RSS setting")eac9122f0c
("net: ethtool: record custom RSS contexts in the XArray") Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
e5abd12f3d
@ -66,7 +66,6 @@ allOf:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,qdu1000-llcc
|
||||
- qcom,sc7180-llcc
|
||||
- qcom,sm6350-llcc
|
||||
then:
|
||||
@ -104,6 +103,7 @@ allOf:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,qdu1000-llcc
|
||||
- qcom,sc8180x-llcc
|
||||
- qcom,sc8280xp-llcc
|
||||
- qcom,x1e80100-llcc
|
||||
|
13
MAINTAINERS
13
MAINTAINERS
@ -2892,7 +2892,7 @@ F: drivers/edac/altera_edac.[ch]
|
||||
ARM/SPREADTRUM SoC SUPPORT
|
||||
M: Orson Zhai <orsonzhai@gmail.com>
|
||||
M: Baolin Wang <baolin.wang7@gmail.com>
|
||||
M: Chunyan Zhang <zhang.lyra@gmail.com>
|
||||
R: Chunyan Zhang <zhang.lyra@gmail.com>
|
||||
S: Maintained
|
||||
F: arch/arm64/boot/dts/sprd
|
||||
N: sprd
|
||||
@ -8833,6 +8833,7 @@ F: drivers/spi/spi-fsl-qspi.c
|
||||
|
||||
FREESCALE QUICC ENGINE LIBRARY
|
||||
M: Qiang Zhao <qiang.zhao@nxp.com>
|
||||
M: Christophe Leroy <christophe.leroy@csgroup.eu>
|
||||
L: linuxppc-dev@lists.ozlabs.org
|
||||
S: Maintained
|
||||
F: drivers/soc/fsl/qe/
|
||||
@ -8882,9 +8883,10 @@ S: Maintained
|
||||
F: drivers/tty/serial/ucc_uart.c
|
||||
|
||||
FREESCALE SOC DRIVERS
|
||||
M: Christophe Leroy <christophe.leroy@csgroup.eu>
|
||||
L: linuxppc-dev@lists.ozlabs.org
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Orphan
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/misc/fsl,dpaa2-console.yaml
|
||||
F: Documentation/devicetree/bindings/soc/fsl/
|
||||
F: drivers/soc/fsl/
|
||||
@ -16447,7 +16449,7 @@ F: arch/arm/boot/dts/ti/omap/am335x-nano.dts
|
||||
OMAP1 SUPPORT
|
||||
M: Aaro Koskinen <aaro.koskinen@iki.fi>
|
||||
M: Janusz Krzysztofik <jmkrzyszt@gmail.com>
|
||||
M: Tony Lindgren <tony@atomide.com>
|
||||
R: Tony Lindgren <tony@atomide.com>
|
||||
L: linux-omap@vger.kernel.org
|
||||
S: Maintained
|
||||
Q: http://patchwork.kernel.org/project/linux-omap/list/
|
||||
@ -16459,10 +16461,13 @@ F: include/linux/platform_data/ams-delta-fiq.h
|
||||
F: include/linux/platform_data/i2c-omap.h
|
||||
|
||||
OMAP2+ SUPPORT
|
||||
M: Aaro Koskinen <aaro.koskinen@iki.fi>
|
||||
M: Andreas Kemnade <andreas@kemnade.info>
|
||||
M: Kevin Hilman <khilman@baylibre.com>
|
||||
M: Roger Quadros <rogerq@kernel.org>
|
||||
M: Tony Lindgren <tony@atomide.com>
|
||||
L: linux-omap@vger.kernel.org
|
||||
S: Maintained
|
||||
W: http://www.muru.com/linux/omap/
|
||||
W: http://linux.omap.com/
|
||||
Q: http://patchwork.kernel.org/project/linux-omap/list/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git
|
||||
|
@ -61,7 +61,7 @@ static void davinci_pm_suspend(void)
|
||||
|
||||
/* Configure sleep count in deep sleep register */
|
||||
val = __raw_readl(pm_config.deepsleep_reg);
|
||||
val &= ~DEEPSLEEP_SLEEPCOUNT_MASK,
|
||||
val &= ~DEEPSLEEP_SLEEPCOUNT_MASK;
|
||||
val |= pm_config.sleepcount;
|
||||
__raw_writel(val, pm_config.deepsleep_reg);
|
||||
|
||||
|
@ -191,7 +191,7 @@ axp803: pmic@3a3 {
|
||||
compatible = "x-powers,axp803";
|
||||
reg = <0x3a3>;
|
||||
interrupt-parent = <&r_intc>;
|
||||
interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_LOW>;
|
||||
x-powers,drive-vbus-en;
|
||||
|
||||
vin1-supply = <®_vcc5v>;
|
||||
|
@ -1459,9 +1459,23 @@ gem_noc: interconnect@19100000 {
|
||||
|
||||
system-cache-controller@19200000 {
|
||||
compatible = "qcom,qdu1000-llcc";
|
||||
reg = <0 0x19200000 0 0xd80000>,
|
||||
reg = <0 0x19200000 0 0x80000>,
|
||||
<0 0x19300000 0 0x80000>,
|
||||
<0 0x19600000 0 0x80000>,
|
||||
<0 0x19700000 0 0x80000>,
|
||||
<0 0x19a00000 0 0x80000>,
|
||||
<0 0x19b00000 0 0x80000>,
|
||||
<0 0x19e00000 0 0x80000>,
|
||||
<0 0x19f00000 0 0x80000>,
|
||||
<0 0x1a200000 0 0x80000>;
|
||||
reg-names = "llcc0_base",
|
||||
"llcc1_base",
|
||||
"llcc2_base",
|
||||
"llcc3_base",
|
||||
"llcc4_base",
|
||||
"llcc5_base",
|
||||
"llcc6_base",
|
||||
"llcc7_base",
|
||||
"llcc_broadcast_base";
|
||||
interrupts = <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
|
@ -3605,7 +3605,7 @@ arch_timer: timer {
|
||||
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 12 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>;
|
||||
<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>;
|
||||
};
|
||||
|
||||
pcie0: pcie@1c00000 {
|
||||
|
@ -2647,11 +2647,14 @@ usb_sec_dpphy: dp-phy@88ef200 {
|
||||
|
||||
system-cache-controller@9200000 {
|
||||
compatible = "qcom,sc8180x-llcc";
|
||||
reg = <0 0x09200000 0 0x50000>, <0 0x09280000 0 0x50000>,
|
||||
<0 0x09300000 0 0x50000>, <0 0x09380000 0 0x50000>,
|
||||
<0 0x09600000 0 0x50000>;
|
||||
reg = <0 0x09200000 0 0x58000>, <0 0x09280000 0 0x58000>,
|
||||
<0 0x09300000 0 0x58000>, <0 0x09380000 0 0x58000>,
|
||||
<0 0x09400000 0 0x58000>, <0 0x09480000 0 0x58000>,
|
||||
<0 0x09500000 0 0x58000>, <0 0x09580000 0 0x58000>,
|
||||
<0 0x09600000 0 0x58000>;
|
||||
reg-names = "llcc0_base", "llcc1_base", "llcc2_base",
|
||||
"llcc3_base", "llcc_broadcast_base";
|
||||
"llcc3_base", "llcc4_base", "llcc5_base",
|
||||
"llcc6_base", "llcc7_base", "llcc_broadcast_base";
|
||||
interrupts = <GIC_SPI 582 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
|
||||
|
@ -977,8 +977,7 @@ int-n-pins {
|
||||
reset-n-pins {
|
||||
pins = "gpio99";
|
||||
function = "gpio";
|
||||
output-high;
|
||||
drive-strength = <16>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -655,15 +655,16 @@ &i2c4 {
|
||||
|
||||
status = "okay";
|
||||
|
||||
/* FIXME: verify */
|
||||
touchscreen@10 {
|
||||
compatible = "hid-over-i2c";
|
||||
compatible = "elan,ekth5015m", "elan,ekth6915";
|
||||
reg = <0x10>;
|
||||
|
||||
hid-descr-addr = <0x1>;
|
||||
interrupts-extended = <&tlmm 175 IRQ_TYPE_LEVEL_LOW>;
|
||||
vdd-supply = <&vreg_misc_3p3>;
|
||||
vddl-supply = <&vreg_s10b>;
|
||||
reset-gpios = <&tlmm 99 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>;
|
||||
no-reset-on-power-off;
|
||||
|
||||
vcc33-supply = <&vreg_misc_3p3>;
|
||||
vccio-supply = <&vreg_misc_3p3>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&ts0_default>;
|
||||
@ -1496,8 +1497,8 @@ int-n-pins {
|
||||
reset-n-pins {
|
||||
pins = "gpio99";
|
||||
function = "gpio";
|
||||
output-high;
|
||||
drive-strength = <16>;
|
||||
drive-strength = <2>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -4623,6 +4623,8 @@ tsens0: thermal-sensor@c263000 {
|
||||
restart@c264000 {
|
||||
compatible = "qcom,pshold";
|
||||
reg = <0 0x0c264000 0 0x4>;
|
||||
/* TZ seems to block access */
|
||||
status = "reserved";
|
||||
};
|
||||
|
||||
tsens1: thermal-sensor@c265000 {
|
||||
|
@ -1090,6 +1090,7 @@ sdhc_1: mmc@4744000 {
|
||||
|
||||
power-domains = <&rpmpd SM6115_VDDCX>;
|
||||
operating-points-v2 = <&sdhc1_opp_table>;
|
||||
iommus = <&apps_smmu 0x00c0 0x0>;
|
||||
interconnects = <&system_noc MASTER_SDCC_1 RPM_ALWAYS_TAG
|
||||
&bimc SLAVE_EBI_CH0 RPM_ALWAYS_TAG>,
|
||||
<&bimc MASTER_AMPSS_M0 RPM_ALWAYS_TAG
|
||||
|
@ -49,6 +49,15 @@ chosen {
|
||||
stdout-path = "serial0:115200n8";
|
||||
};
|
||||
|
||||
reserved-memory {
|
||||
linux,cma {
|
||||
compatible = "shared-dma-pool";
|
||||
size = <0x0 0x8000000>;
|
||||
reusable;
|
||||
linux,cma-default;
|
||||
};
|
||||
};
|
||||
|
||||
sound {
|
||||
compatible = "qcom,x1e80100-sndcard";
|
||||
model = "X1E80100-CRD";
|
||||
@ -93,7 +102,7 @@ cpu {
|
||||
};
|
||||
|
||||
codec {
|
||||
sound-dai = <&wcd938x 1>, <&swr2 0>, <&lpass_txmacro 0>;
|
||||
sound-dai = <&wcd938x 1>, <&swr2 1>, <&lpass_txmacro 0>;
|
||||
};
|
||||
|
||||
platform {
|
||||
@ -744,7 +753,7 @@ &swr2 {
|
||||
wcd_tx: codec@0,3 {
|
||||
compatible = "sdw20217010d00";
|
||||
reg = <0 3>;
|
||||
qcom,tx-port-mapping = <1 1 2 3>;
|
||||
qcom,tx-port-mapping = <2 2 3 4>;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -23,6 +23,15 @@ chosen {
|
||||
stdout-path = "serial0:115200n8";
|
||||
};
|
||||
|
||||
reserved-memory {
|
||||
linux,cma {
|
||||
compatible = "shared-dma-pool";
|
||||
size = <0x0 0x8000000>;
|
||||
reusable;
|
||||
linux,cma-default;
|
||||
};
|
||||
};
|
||||
|
||||
vph_pwr: vph-pwr-regulator {
|
||||
compatible = "regulator-fixed";
|
||||
|
||||
|
@ -2737,15 +2737,17 @@ pcie6a: pci@1bf8000 {
|
||||
device_type = "pci";
|
||||
compatible = "qcom,pcie-x1e80100";
|
||||
reg = <0 0x01bf8000 0 0x3000>,
|
||||
<0 0x70000000 0 0xf1d>,
|
||||
<0 0x70000f20 0 0xa8>,
|
||||
<0 0x70000000 0 0xf20>,
|
||||
<0 0x70000f40 0 0xa8>,
|
||||
<0 0x70001000 0 0x1000>,
|
||||
<0 0x70100000 0 0x100000>;
|
||||
<0 0x70100000 0 0x100000>,
|
||||
<0 0x01bfb000 0 0x1000>;
|
||||
reg-names = "parf",
|
||||
"dbi",
|
||||
"elbi",
|
||||
"atu",
|
||||
"config";
|
||||
"config",
|
||||
"mhi";
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
ranges = <0x01000000 0 0x00000000 0 0x70200000 0 0x100000>,
|
||||
|
@ -1036,6 +1036,7 @@ CONFIG_SND_AUDIO_GRAPH_CARD2=m
|
||||
CONFIG_HID_MULTITOUCH=m
|
||||
CONFIG_I2C_HID_ACPI=m
|
||||
CONFIG_I2C_HID_OF=m
|
||||
CONFIG_I2C_HID_OF_ELAN=m
|
||||
CONFIG_USB=y
|
||||
CONFIG_USB_OTG=y
|
||||
CONFIG_USB_XHCI_HCD=y
|
||||
|
@ -269,8 +269,13 @@ hpet_read(struct file *file, char __user *buf, size_t count, loff_t * ppos)
|
||||
if (!devp->hd_ireqfreq)
|
||||
return -EIO;
|
||||
|
||||
if (count < sizeof(unsigned long))
|
||||
return -EINVAL;
|
||||
if (in_compat_syscall()) {
|
||||
if (count < sizeof(compat_ulong_t))
|
||||
return -EINVAL;
|
||||
} else {
|
||||
if (count < sizeof(unsigned long))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
add_wait_queue(&devp->hd_waitqueue, &wait);
|
||||
|
||||
@ -294,9 +299,16 @@ hpet_read(struct file *file, char __user *buf, size_t count, loff_t * ppos)
|
||||
schedule();
|
||||
}
|
||||
|
||||
retval = put_user(data, (unsigned long __user *)buf);
|
||||
if (!retval)
|
||||
retval = sizeof(unsigned long);
|
||||
if (in_compat_syscall()) {
|
||||
retval = put_user(data, (compat_ulong_t __user *)buf);
|
||||
if (!retval)
|
||||
retval = sizeof(compat_ulong_t);
|
||||
} else {
|
||||
retval = put_user(data, (unsigned long __user *)buf);
|
||||
if (!retval)
|
||||
retval = sizeof(unsigned long);
|
||||
}
|
||||
|
||||
out:
|
||||
__set_current_state(TASK_RUNNING);
|
||||
remove_wait_queue(&devp->hd_waitqueue, &wait);
|
||||
@ -651,12 +663,24 @@ struct compat_hpet_info {
|
||||
unsigned short hi_timer;
|
||||
};
|
||||
|
||||
/* 32-bit types would lead to different command codes which should be
|
||||
* translated into 64-bit ones before passed to hpet_ioctl_common
|
||||
*/
|
||||
#define COMPAT_HPET_INFO _IOR('h', 0x03, struct compat_hpet_info)
|
||||
#define COMPAT_HPET_IRQFREQ _IOW('h', 0x6, compat_ulong_t)
|
||||
|
||||
static long
|
||||
hpet_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct hpet_info info;
|
||||
int err;
|
||||
|
||||
if (cmd == COMPAT_HPET_INFO)
|
||||
cmd = HPET_INFO;
|
||||
|
||||
if (cmd == COMPAT_HPET_IRQFREQ)
|
||||
cmd = HPET_IRQFREQ;
|
||||
|
||||
mutex_lock(&hpet_mutex);
|
||||
err = hpet_ioctl_common(file->private_data, cmd, arg, &info);
|
||||
mutex_unlock(&hpet_mutex);
|
||||
|
@ -1107,9 +1107,16 @@ struct cs_dsp_coeff_parsed_coeff {
|
||||
int len;
|
||||
};
|
||||
|
||||
static int cs_dsp_coeff_parse_string(int bytes, const u8 **pos, const u8 **str)
|
||||
static int cs_dsp_coeff_parse_string(int bytes, const u8 **pos, unsigned int avail,
|
||||
const u8 **str)
|
||||
{
|
||||
int length;
|
||||
int length, total_field_len;
|
||||
|
||||
/* String fields are at least one __le32 */
|
||||
if (sizeof(__le32) > avail) {
|
||||
*pos = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (bytes) {
|
||||
case 1:
|
||||
@ -1122,10 +1129,16 @@ static int cs_dsp_coeff_parse_string(int bytes, const u8 **pos, const u8 **str)
|
||||
return 0;
|
||||
}
|
||||
|
||||
total_field_len = ((length + bytes) + 3) & ~0x03;
|
||||
if ((unsigned int)total_field_len > avail) {
|
||||
*pos = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (str)
|
||||
*str = *pos + bytes;
|
||||
|
||||
*pos += ((length + bytes) + 3) & ~0x03;
|
||||
*pos += total_field_len;
|
||||
|
||||
return length;
|
||||
}
|
||||
@ -1150,71 +1163,134 @@ static int cs_dsp_coeff_parse_int(int bytes, const u8 **pos)
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline void cs_dsp_coeff_parse_alg(struct cs_dsp *dsp, const u8 **data,
|
||||
struct cs_dsp_coeff_parsed_alg *blk)
|
||||
static int cs_dsp_coeff_parse_alg(struct cs_dsp *dsp,
|
||||
const struct wmfw_region *region,
|
||||
struct cs_dsp_coeff_parsed_alg *blk)
|
||||
{
|
||||
const struct wmfw_adsp_alg_data *raw;
|
||||
unsigned int data_len = le32_to_cpu(region->len);
|
||||
unsigned int pos;
|
||||
const u8 *tmp;
|
||||
|
||||
raw = (const struct wmfw_adsp_alg_data *)region->data;
|
||||
|
||||
switch (dsp->fw_ver) {
|
||||
case 0:
|
||||
case 1:
|
||||
raw = (const struct wmfw_adsp_alg_data *)*data;
|
||||
*data = raw->data;
|
||||
if (sizeof(*raw) > data_len)
|
||||
return -EOVERFLOW;
|
||||
|
||||
blk->id = le32_to_cpu(raw->id);
|
||||
blk->name = raw->name;
|
||||
blk->name_len = strlen(raw->name);
|
||||
blk->name_len = strnlen(raw->name, ARRAY_SIZE(raw->name));
|
||||
blk->ncoeff = le32_to_cpu(raw->ncoeff);
|
||||
|
||||
pos = sizeof(*raw);
|
||||
break;
|
||||
default:
|
||||
blk->id = cs_dsp_coeff_parse_int(sizeof(raw->id), data);
|
||||
blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), data,
|
||||
if (sizeof(raw->id) > data_len)
|
||||
return -EOVERFLOW;
|
||||
|
||||
tmp = region->data;
|
||||
blk->id = cs_dsp_coeff_parse_int(sizeof(raw->id), &tmp);
|
||||
pos = tmp - region->data;
|
||||
|
||||
tmp = ®ion->data[pos];
|
||||
blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), &tmp, data_len - pos,
|
||||
&blk->name);
|
||||
cs_dsp_coeff_parse_string(sizeof(u16), data, NULL);
|
||||
blk->ncoeff = cs_dsp_coeff_parse_int(sizeof(raw->ncoeff), data);
|
||||
if (!tmp)
|
||||
return -EOVERFLOW;
|
||||
|
||||
pos = tmp - region->data;
|
||||
cs_dsp_coeff_parse_string(sizeof(u16), &tmp, data_len - pos, NULL);
|
||||
if (!tmp)
|
||||
return -EOVERFLOW;
|
||||
|
||||
pos = tmp - region->data;
|
||||
if (sizeof(raw->ncoeff) > (data_len - pos))
|
||||
return -EOVERFLOW;
|
||||
|
||||
blk->ncoeff = cs_dsp_coeff_parse_int(sizeof(raw->ncoeff), &tmp);
|
||||
pos += sizeof(raw->ncoeff);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((int)blk->ncoeff < 0)
|
||||
return -EOVERFLOW;
|
||||
|
||||
cs_dsp_dbg(dsp, "Algorithm ID: %#x\n", blk->id);
|
||||
cs_dsp_dbg(dsp, "Algorithm name: %.*s\n", blk->name_len, blk->name);
|
||||
cs_dsp_dbg(dsp, "# of coefficient descriptors: %#x\n", blk->ncoeff);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
static inline void cs_dsp_coeff_parse_coeff(struct cs_dsp *dsp, const u8 **data,
|
||||
struct cs_dsp_coeff_parsed_coeff *blk)
|
||||
static int cs_dsp_coeff_parse_coeff(struct cs_dsp *dsp,
|
||||
const struct wmfw_region *region,
|
||||
unsigned int pos,
|
||||
struct cs_dsp_coeff_parsed_coeff *blk)
|
||||
{
|
||||
const struct wmfw_adsp_coeff_data *raw;
|
||||
unsigned int data_len = le32_to_cpu(region->len);
|
||||
unsigned int blk_len, blk_end_pos;
|
||||
const u8 *tmp;
|
||||
int length;
|
||||
|
||||
raw = (const struct wmfw_adsp_coeff_data *)®ion->data[pos];
|
||||
if (sizeof(raw->hdr) > (data_len - pos))
|
||||
return -EOVERFLOW;
|
||||
|
||||
blk_len = le32_to_cpu(raw->hdr.size);
|
||||
if (blk_len > S32_MAX)
|
||||
return -EOVERFLOW;
|
||||
|
||||
if (blk_len > (data_len - pos - sizeof(raw->hdr)))
|
||||
return -EOVERFLOW;
|
||||
|
||||
blk_end_pos = pos + sizeof(raw->hdr) + blk_len;
|
||||
|
||||
blk->offset = le16_to_cpu(raw->hdr.offset);
|
||||
blk->mem_type = le16_to_cpu(raw->hdr.type);
|
||||
|
||||
switch (dsp->fw_ver) {
|
||||
case 0:
|
||||
case 1:
|
||||
raw = (const struct wmfw_adsp_coeff_data *)*data;
|
||||
*data = *data + sizeof(raw->hdr) + le32_to_cpu(raw->hdr.size);
|
||||
if (sizeof(*raw) > (data_len - pos))
|
||||
return -EOVERFLOW;
|
||||
|
||||
blk->offset = le16_to_cpu(raw->hdr.offset);
|
||||
blk->mem_type = le16_to_cpu(raw->hdr.type);
|
||||
blk->name = raw->name;
|
||||
blk->name_len = strlen(raw->name);
|
||||
blk->name_len = strnlen(raw->name, ARRAY_SIZE(raw->name));
|
||||
blk->ctl_type = le16_to_cpu(raw->ctl_type);
|
||||
blk->flags = le16_to_cpu(raw->flags);
|
||||
blk->len = le32_to_cpu(raw->len);
|
||||
break;
|
||||
default:
|
||||
tmp = *data;
|
||||
blk->offset = cs_dsp_coeff_parse_int(sizeof(raw->hdr.offset), &tmp);
|
||||
blk->mem_type = cs_dsp_coeff_parse_int(sizeof(raw->hdr.type), &tmp);
|
||||
length = cs_dsp_coeff_parse_int(sizeof(raw->hdr.size), &tmp);
|
||||
blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), &tmp,
|
||||
pos += sizeof(raw->hdr);
|
||||
tmp = ®ion->data[pos];
|
||||
blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), &tmp, data_len - pos,
|
||||
&blk->name);
|
||||
cs_dsp_coeff_parse_string(sizeof(u8), &tmp, NULL);
|
||||
cs_dsp_coeff_parse_string(sizeof(u16), &tmp, NULL);
|
||||
blk->ctl_type = cs_dsp_coeff_parse_int(sizeof(raw->ctl_type), &tmp);
|
||||
blk->flags = cs_dsp_coeff_parse_int(sizeof(raw->flags), &tmp);
|
||||
blk->len = cs_dsp_coeff_parse_int(sizeof(raw->len), &tmp);
|
||||
if (!tmp)
|
||||
return -EOVERFLOW;
|
||||
|
||||
*data = *data + sizeof(raw->hdr) + length;
|
||||
pos = tmp - region->data;
|
||||
cs_dsp_coeff_parse_string(sizeof(u8), &tmp, data_len - pos, NULL);
|
||||
if (!tmp)
|
||||
return -EOVERFLOW;
|
||||
|
||||
pos = tmp - region->data;
|
||||
cs_dsp_coeff_parse_string(sizeof(u16), &tmp, data_len - pos, NULL);
|
||||
if (!tmp)
|
||||
return -EOVERFLOW;
|
||||
|
||||
pos = tmp - region->data;
|
||||
if (sizeof(raw->ctl_type) + sizeof(raw->flags) + sizeof(raw->len) >
|
||||
(data_len - pos))
|
||||
return -EOVERFLOW;
|
||||
|
||||
blk->ctl_type = cs_dsp_coeff_parse_int(sizeof(raw->ctl_type), &tmp);
|
||||
pos += sizeof(raw->ctl_type);
|
||||
blk->flags = cs_dsp_coeff_parse_int(sizeof(raw->flags), &tmp);
|
||||
pos += sizeof(raw->flags);
|
||||
blk->len = cs_dsp_coeff_parse_int(sizeof(raw->len), &tmp);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1224,6 +1300,8 @@ static inline void cs_dsp_coeff_parse_coeff(struct cs_dsp *dsp, const u8 **data,
|
||||
cs_dsp_dbg(dsp, "\tCoefficient flags: %#x\n", blk->flags);
|
||||
cs_dsp_dbg(dsp, "\tALSA control type: %#x\n", blk->ctl_type);
|
||||
cs_dsp_dbg(dsp, "\tALSA control len: %#x\n", blk->len);
|
||||
|
||||
return blk_end_pos;
|
||||
}
|
||||
|
||||
static int cs_dsp_check_coeff_flags(struct cs_dsp *dsp,
|
||||
@ -1247,12 +1325,16 @@ static int cs_dsp_parse_coeff(struct cs_dsp *dsp,
|
||||
struct cs_dsp_alg_region alg_region = {};
|
||||
struct cs_dsp_coeff_parsed_alg alg_blk;
|
||||
struct cs_dsp_coeff_parsed_coeff coeff_blk;
|
||||
const u8 *data = region->data;
|
||||
int i, ret;
|
||||
int i, pos, ret;
|
||||
|
||||
pos = cs_dsp_coeff_parse_alg(dsp, region, &alg_blk);
|
||||
if (pos < 0)
|
||||
return pos;
|
||||
|
||||
cs_dsp_coeff_parse_alg(dsp, &data, &alg_blk);
|
||||
for (i = 0; i < alg_blk.ncoeff; i++) {
|
||||
cs_dsp_coeff_parse_coeff(dsp, &data, &coeff_blk);
|
||||
pos = cs_dsp_coeff_parse_coeff(dsp, region, pos, &coeff_blk);
|
||||
if (pos < 0)
|
||||
return pos;
|
||||
|
||||
switch (coeff_blk.ctl_type) {
|
||||
case WMFW_CTL_TYPE_BYTES:
|
||||
@ -1321,6 +1403,10 @@ static unsigned int cs_dsp_adsp1_parse_sizes(struct cs_dsp *dsp,
|
||||
const struct wmfw_adsp1_sizes *adsp1_sizes;
|
||||
|
||||
adsp1_sizes = (void *)&firmware->data[pos];
|
||||
if (sizeof(*adsp1_sizes) > firmware->size - pos) {
|
||||
cs_dsp_err(dsp, "%s: file truncated\n", file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cs_dsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n", file,
|
||||
le32_to_cpu(adsp1_sizes->dm), le32_to_cpu(adsp1_sizes->pm),
|
||||
@ -1337,6 +1423,10 @@ static unsigned int cs_dsp_adsp2_parse_sizes(struct cs_dsp *dsp,
|
||||
const struct wmfw_adsp2_sizes *adsp2_sizes;
|
||||
|
||||
adsp2_sizes = (void *)&firmware->data[pos];
|
||||
if (sizeof(*adsp2_sizes) > firmware->size - pos) {
|
||||
cs_dsp_err(dsp, "%s: file truncated\n", file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cs_dsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n", file,
|
||||
le32_to_cpu(adsp2_sizes->xm), le32_to_cpu(adsp2_sizes->ym),
|
||||
@ -1376,7 +1466,6 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
|
||||
struct regmap *regmap = dsp->regmap;
|
||||
unsigned int pos = 0;
|
||||
const struct wmfw_header *header;
|
||||
const struct wmfw_adsp1_sizes *adsp1_sizes;
|
||||
const struct wmfw_footer *footer;
|
||||
const struct wmfw_region *region;
|
||||
const struct cs_dsp_region *mem;
|
||||
@ -1392,10 +1481,8 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
|
||||
|
||||
ret = -EINVAL;
|
||||
|
||||
pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
|
||||
if (pos >= firmware->size) {
|
||||
cs_dsp_err(dsp, "%s: file too short, %zu bytes\n",
|
||||
file, firmware->size);
|
||||
if (sizeof(*header) >= firmware->size) {
|
||||
ret = -EOVERFLOW;
|
||||
goto out_fw;
|
||||
}
|
||||
|
||||
@ -1423,22 +1510,36 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
|
||||
|
||||
pos = sizeof(*header);
|
||||
pos = dsp->ops->parse_sizes(dsp, file, pos, firmware);
|
||||
if ((pos == 0) || (sizeof(*footer) > firmware->size - pos)) {
|
||||
ret = -EOVERFLOW;
|
||||
goto out_fw;
|
||||
}
|
||||
|
||||
footer = (void *)&firmware->data[pos];
|
||||
pos += sizeof(*footer);
|
||||
|
||||
if (le32_to_cpu(header->len) != pos) {
|
||||
cs_dsp_err(dsp, "%s: unexpected header length %d\n",
|
||||
file, le32_to_cpu(header->len));
|
||||
ret = -EOVERFLOW;
|
||||
goto out_fw;
|
||||
}
|
||||
|
||||
cs_dsp_dbg(dsp, "%s: timestamp %llu\n", file,
|
||||
le64_to_cpu(footer->timestamp));
|
||||
|
||||
while (pos < firmware->size &&
|
||||
sizeof(*region) < firmware->size - pos) {
|
||||
while (pos < firmware->size) {
|
||||
/* Is there enough data for a complete block header? */
|
||||
if (sizeof(*region) > firmware->size - pos) {
|
||||
ret = -EOVERFLOW;
|
||||
goto out_fw;
|
||||
}
|
||||
|
||||
region = (void *)&(firmware->data[pos]);
|
||||
|
||||
if (le32_to_cpu(region->len) > firmware->size - pos - sizeof(*region)) {
|
||||
ret = -EOVERFLOW;
|
||||
goto out_fw;
|
||||
}
|
||||
|
||||
region_name = "Unknown";
|
||||
reg = 0;
|
||||
text = NULL;
|
||||
@ -1495,16 +1596,6 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
|
||||
regions, le32_to_cpu(region->len), offset,
|
||||
region_name);
|
||||
|
||||
if (le32_to_cpu(region->len) >
|
||||
firmware->size - pos - sizeof(*region)) {
|
||||
cs_dsp_err(dsp,
|
||||
"%s.%d: %s region len %d bytes exceeds file length %zu\n",
|
||||
file, regions, region_name,
|
||||
le32_to_cpu(region->len), firmware->size);
|
||||
ret = -EINVAL;
|
||||
goto out_fw;
|
||||
}
|
||||
|
||||
if (text) {
|
||||
memcpy(text, region->data, le32_to_cpu(region->len));
|
||||
cs_dsp_info(dsp, "%s: %s\n", file, text);
|
||||
@ -1555,6 +1646,9 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
|
||||
cs_dsp_buf_free(&buf_list);
|
||||
kfree(text);
|
||||
|
||||
if (ret == -EOVERFLOW)
|
||||
cs_dsp_err(dsp, "%s: file content overflows file data\n", file);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2122,10 +2216,20 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
|
||||
pos = le32_to_cpu(hdr->len);
|
||||
|
||||
blocks = 0;
|
||||
while (pos < firmware->size &&
|
||||
sizeof(*blk) < firmware->size - pos) {
|
||||
while (pos < firmware->size) {
|
||||
/* Is there enough data for a complete block header? */
|
||||
if (sizeof(*blk) > firmware->size - pos) {
|
||||
ret = -EOVERFLOW;
|
||||
goto out_fw;
|
||||
}
|
||||
|
||||
blk = (void *)(&firmware->data[pos]);
|
||||
|
||||
if (le32_to_cpu(blk->len) > firmware->size - pos - sizeof(*blk)) {
|
||||
ret = -EOVERFLOW;
|
||||
goto out_fw;
|
||||
}
|
||||
|
||||
type = le16_to_cpu(blk->type);
|
||||
offset = le16_to_cpu(blk->offset);
|
||||
version = le32_to_cpu(blk->ver) >> 8;
|
||||
@ -2222,17 +2326,6 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
|
||||
}
|
||||
|
||||
if (reg) {
|
||||
if (le32_to_cpu(blk->len) >
|
||||
firmware->size - pos - sizeof(*blk)) {
|
||||
cs_dsp_err(dsp,
|
||||
"%s.%d: %s region len %d bytes exceeds file length %zu\n",
|
||||
file, blocks, region_name,
|
||||
le32_to_cpu(blk->len),
|
||||
firmware->size);
|
||||
ret = -EINVAL;
|
||||
goto out_fw;
|
||||
}
|
||||
|
||||
buf = cs_dsp_buf_alloc(blk->data,
|
||||
le32_to_cpu(blk->len),
|
||||
&buf_list);
|
||||
@ -2272,6 +2365,10 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
|
||||
regmap_async_complete(regmap);
|
||||
cs_dsp_buf_free(&buf_list);
|
||||
kfree(text);
|
||||
|
||||
if (ret == -EOVERFLOW)
|
||||
cs_dsp_err(dsp, "%s: file content overflows file data\n", file);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -315,7 +315,7 @@ int iio_trigger_attach_poll_func(struct iio_trigger *trig,
|
||||
* this is the case if the IIO device and the trigger device share the
|
||||
* same parent device.
|
||||
*/
|
||||
if (iio_validate_own_trigger(pf->indio_dev, trig))
|
||||
if (!iio_validate_own_trigger(pf->indio_dev, trig))
|
||||
trig->attached_own_device = true;
|
||||
|
||||
return ret;
|
||||
|
@ -583,8 +583,8 @@ static int apds9306_intg_time_set(struct apds9306_data *data, int val2)
|
||||
return ret;
|
||||
|
||||
intg_old = iio_gts_find_int_time_by_sel(&data->gts, intg_time_idx);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (intg_old < 0)
|
||||
return intg_old;
|
||||
|
||||
if (intg_old == val2)
|
||||
return 0;
|
||||
|
@ -945,7 +945,7 @@ static void vdo_io_hints(struct dm_target *ti, struct queue_limits *limits)
|
||||
* The value is used by dm-thin to determine whether to pass down discards. The block layer
|
||||
* splits large discards on this boundary when this is set.
|
||||
*/
|
||||
limits->max_discard_sectors =
|
||||
limits->max_hw_discard_sectors =
|
||||
(vdo->device_config->max_discard_blocks * VDO_SECTORS_PER_BLOCK);
|
||||
|
||||
/*
|
||||
|
@ -1238,6 +1238,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
|
||||
struct fastrpc_phy_page pages[1];
|
||||
char *name;
|
||||
int err;
|
||||
bool scm_done = false;
|
||||
struct {
|
||||
int pgid;
|
||||
u32 namelen;
|
||||
@ -1289,6 +1290,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
|
||||
fl->cctx->remote_heap->phys, fl->cctx->remote_heap->size, err);
|
||||
goto err_map;
|
||||
}
|
||||
scm_done = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1320,10 +1322,11 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
|
||||
goto err_invoke;
|
||||
|
||||
kfree(args);
|
||||
kfree(name);
|
||||
|
||||
return 0;
|
||||
err_invoke:
|
||||
if (fl->cctx->vmcount) {
|
||||
if (fl->cctx->vmcount && scm_done) {
|
||||
u64 src_perms = 0;
|
||||
struct qcom_scm_vmperm dst_perms;
|
||||
u32 i;
|
||||
@ -1693,16 +1696,20 @@ static int fastrpc_get_info_from_dsp(struct fastrpc_user *fl, uint32_t *dsp_attr
|
||||
{
|
||||
struct fastrpc_invoke_args args[2] = { 0 };
|
||||
|
||||
/* Capability filled in userspace */
|
||||
/*
|
||||
* Capability filled in userspace. This carries the information
|
||||
* about the remoteproc support which is fetched from the remoteproc
|
||||
* sysfs node by userspace.
|
||||
*/
|
||||
dsp_attr_buf[0] = 0;
|
||||
dsp_attr_buf_len -= 1;
|
||||
|
||||
args[0].ptr = (u64)(uintptr_t)&dsp_attr_buf_len;
|
||||
args[0].length = sizeof(dsp_attr_buf_len);
|
||||
args[0].fd = -1;
|
||||
args[1].ptr = (u64)(uintptr_t)&dsp_attr_buf[1];
|
||||
args[1].length = dsp_attr_buf_len;
|
||||
args[1].length = dsp_attr_buf_len * sizeof(u32);
|
||||
args[1].fd = -1;
|
||||
fl->pd = USER_PD;
|
||||
|
||||
return fastrpc_internal_invoke(fl, true, FASTRPC_DSP_UTILITIES_HANDLE,
|
||||
FASTRPC_SCALARS(0, 1, 1), args);
|
||||
@ -1730,7 +1737,7 @@ static int fastrpc_get_info_from_kernel(struct fastrpc_ioctl_capability *cap,
|
||||
if (!dsp_attributes)
|
||||
return -ENOMEM;
|
||||
|
||||
err = fastrpc_get_info_from_dsp(fl, dsp_attributes, FASTRPC_MAX_DSP_ATTRIBUTES_LEN);
|
||||
err = fastrpc_get_info_from_dsp(fl, dsp_attributes, FASTRPC_MAX_DSP_ATTRIBUTES);
|
||||
if (err == DSP_UNSUPPORTED_API) {
|
||||
dev_info(&cctx->rpdev->dev,
|
||||
"Warning: DSP capabilities not supported on domain: %d\n", domain);
|
||||
@ -1783,7 +1790,7 @@ static int fastrpc_get_dsp_info(struct fastrpc_user *fl, char __user *argp)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (copy_to_user(argp, &cap.capability, sizeof(cap.capability)))
|
||||
if (copy_to_user(argp, &cap, sizeof(cap)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
@ -2080,6 +2087,16 @@ static int fastrpc_req_mem_map(struct fastrpc_user *fl, char __user *argp)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int is_attach_rejected(struct fastrpc_user *fl)
|
||||
{
|
||||
/* Check if the device node is non-secure */
|
||||
if (!fl->is_secure_dev) {
|
||||
dev_dbg(&fl->cctx->rpdev->dev, "untrusted app trying to attach to privileged DSP PD\n");
|
||||
return -EACCES;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long fastrpc_device_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
@ -2092,13 +2109,19 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int cmd,
|
||||
err = fastrpc_invoke(fl, argp);
|
||||
break;
|
||||
case FASTRPC_IOCTL_INIT_ATTACH:
|
||||
err = fastrpc_init_attach(fl, ROOT_PD);
|
||||
err = is_attach_rejected(fl);
|
||||
if (!err)
|
||||
err = fastrpc_init_attach(fl, ROOT_PD);
|
||||
break;
|
||||
case FASTRPC_IOCTL_INIT_ATTACH_SNS:
|
||||
err = fastrpc_init_attach(fl, SENSORS_PD);
|
||||
err = is_attach_rejected(fl);
|
||||
if (!err)
|
||||
err = fastrpc_init_attach(fl, SENSORS_PD);
|
||||
break;
|
||||
case FASTRPC_IOCTL_INIT_CREATE_STATIC:
|
||||
err = fastrpc_init_create_static_process(fl, argp);
|
||||
err = is_attach_rejected(fl);
|
||||
if (!err)
|
||||
err = fastrpc_init_create_static_process(fl, argp);
|
||||
break;
|
||||
case FASTRPC_IOCTL_INIT_CREATE:
|
||||
err = fastrpc_init_create_process(fl, argp);
|
||||
|
@ -153,7 +153,6 @@ static int pci1xxxx_eeprom_read(void *priv_t, unsigned int off,
|
||||
|
||||
buf[byte] = readl(rb + MMAP_EEPROM_OFFSET(EEPROM_DATA_REG));
|
||||
}
|
||||
ret = byte;
|
||||
error:
|
||||
release_sys_lock(priv);
|
||||
return ret;
|
||||
@ -197,7 +196,6 @@ static int pci1xxxx_eeprom_write(void *priv_t, unsigned int off,
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
ret = byte;
|
||||
error:
|
||||
release_sys_lock(priv);
|
||||
return ret;
|
||||
@ -258,7 +256,6 @@ static int pci1xxxx_otp_read(void *priv_t, unsigned int off,
|
||||
|
||||
buf[byte] = readl(rb + MMAP_OTP_OFFSET(OTP_RD_DATA_OFFSET));
|
||||
}
|
||||
ret = byte;
|
||||
error:
|
||||
release_sys_lock(priv);
|
||||
return ret;
|
||||
@ -315,7 +312,6 @@ static int pci1xxxx_otp_write(void *priv_t, unsigned int off,
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
ret = byte;
|
||||
error:
|
||||
release_sys_lock(priv);
|
||||
return ret;
|
||||
|
@ -28,8 +28,8 @@
|
||||
|
||||
#define MEI_VSC_MAX_MSG_SIZE 512
|
||||
|
||||
#define MEI_VSC_POLL_DELAY_US (50 * USEC_PER_MSEC)
|
||||
#define MEI_VSC_POLL_TIMEOUT_US (200 * USEC_PER_MSEC)
|
||||
#define MEI_VSC_POLL_DELAY_US (100 * USEC_PER_MSEC)
|
||||
#define MEI_VSC_POLL_TIMEOUT_US (400 * USEC_PER_MSEC)
|
||||
|
||||
#define mei_dev_to_vsc_hw(dev) ((struct mei_vsc_hw *)((dev)->hw))
|
||||
|
||||
|
@ -204,7 +204,7 @@ struct vsc_img_frag {
|
||||
|
||||
/**
|
||||
* struct vsc_fw_loader - represent vsc firmware loader
|
||||
* @dev: device used to request fimware
|
||||
* @dev: device used to request firmware
|
||||
* @tp: transport layer used with the firmware loader
|
||||
* @csi: CSI image
|
||||
* @ace: ACE image
|
||||
|
@ -331,12 +331,12 @@ int vsc_tp_rom_xfer(struct vsc_tp *tp, const void *obuf, void *ibuf, size_t len)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = vsc_tp_dev_xfer(tp, tp->tx_buf, tp->rx_buf, len);
|
||||
ret = vsc_tp_dev_xfer(tp, tp->tx_buf, ibuf ? tp->rx_buf : NULL, len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (ibuf)
|
||||
cpu_to_be32_array(ibuf, tp->rx_buf, words);
|
||||
be32_to_cpu_array(ibuf, tp->rx_buf, words);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -568,6 +568,19 @@ static void vsc_tp_remove(struct spi_device *spi)
|
||||
free_irq(spi->irq, tp);
|
||||
}
|
||||
|
||||
static void vsc_tp_shutdown(struct spi_device *spi)
|
||||
{
|
||||
struct vsc_tp *tp = spi_get_drvdata(spi);
|
||||
|
||||
platform_device_unregister(tp->pdev);
|
||||
|
||||
mutex_destroy(&tp->mutex);
|
||||
|
||||
vsc_tp_reset(tp);
|
||||
|
||||
free_irq(spi->irq, tp);
|
||||
}
|
||||
|
||||
static const struct acpi_device_id vsc_tp_acpi_ids[] = {
|
||||
{ "INTC1009" }, /* Raptor Lake */
|
||||
{ "INTC1058" }, /* Tiger Lake */
|
||||
@ -580,6 +593,7 @@ MODULE_DEVICE_TABLE(acpi, vsc_tp_acpi_ids);
|
||||
static struct spi_driver vsc_tp_driver = {
|
||||
.probe = vsc_tp_probe,
|
||||
.remove = vsc_tp_remove,
|
||||
.shutdown = vsc_tp_shutdown,
|
||||
.driver = {
|
||||
.name = "vsc-tp",
|
||||
.acpi_match_table = vsc_tp_acpi_ids,
|
||||
|
@ -224,6 +224,9 @@ static void davinci_fifo_data_trans(struct mmc_davinci_host *host,
|
||||
}
|
||||
p = sgm->addr;
|
||||
|
||||
if (n > sgm->length)
|
||||
n = sgm->length;
|
||||
|
||||
/* NOTE: we never transfer more than rw_threshold bytes
|
||||
* to/from the fifo here; there's no I/O overlap.
|
||||
* This also assumes that access width( i.e. ACCWD) is 4 bytes
|
||||
|
@ -4727,6 +4727,21 @@ int sdhci_setup_host(struct sdhci_host *host)
|
||||
if (host->quirks & SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC) {
|
||||
host->max_adma = 65532; /* 32-bit alignment */
|
||||
mmc->max_seg_size = 65535;
|
||||
/*
|
||||
* sdhci_adma_table_pre() expects to define 1 DMA
|
||||
* descriptor per segment, so the maximum segment size
|
||||
* is set accordingly. SDHCI allows up to 64KiB per DMA
|
||||
* descriptor (16-bit field), but some controllers do
|
||||
* not support "zero means 65536" reducing the maximum
|
||||
* for them to 65535. That is a problem if PAGE_SIZE is
|
||||
* 64KiB because the block layer does not support
|
||||
* max_seg_size < PAGE_SIZE, however
|
||||
* sdhci_adma_table_pre() has a workaround to handle
|
||||
* that case, and split the descriptor. Refer also
|
||||
* comment in sdhci_adma_table_pre().
|
||||
*/
|
||||
if (mmc->max_seg_size < PAGE_SIZE)
|
||||
mmc->max_seg_size = PAGE_SIZE;
|
||||
} else {
|
||||
mmc->max_seg_size = 65536;
|
||||
}
|
||||
|
@ -109,10 +109,6 @@ static inline int i40e_aq_rc_to_posix(int aq_ret, int aq_rc)
|
||||
-EFBIG, /* I40E_AQ_RC_EFBIG */
|
||||
};
|
||||
|
||||
/* aq_rc is invalid if AQ timed out */
|
||||
if (aq_ret == -EIO)
|
||||
return -EAGAIN;
|
||||
|
||||
if (!((u32)aq_rc < (sizeof(aq_to_posix) / sizeof((aq_to_posix)[0]))))
|
||||
return -ERANGE;
|
||||
|
||||
|
@ -1753,7 +1753,7 @@ struct cpt_lf_alloc_req_msg {
|
||||
u16 nix_pf_func;
|
||||
u16 sso_pf_func;
|
||||
u16 eng_grpmsk;
|
||||
int blkaddr;
|
||||
u8 blkaddr;
|
||||
u8 ctx_ilen_valid : 1;
|
||||
u8 ctx_ilen : 7;
|
||||
};
|
||||
|
@ -63,8 +63,13 @@ enum npc_kpu_lb_ltype {
|
||||
NPC_LT_LB_CUSTOM1 = 0xF,
|
||||
};
|
||||
|
||||
/* Don't modify ltypes up to IP6_EXT, otherwise length and checksum of IP
|
||||
* headers may not be checked correctly. IPv4 ltypes and IPv6 ltypes must
|
||||
* differ only at bit 0 so mask 0xE can be used to detect extended headers.
|
||||
*/
|
||||
enum npc_kpu_lc_ltype {
|
||||
NPC_LT_LC_IP = 1,
|
||||
NPC_LT_LC_PTP = 1,
|
||||
NPC_LT_LC_IP,
|
||||
NPC_LT_LC_IP_OPT,
|
||||
NPC_LT_LC_IP6,
|
||||
NPC_LT_LC_IP6_EXT,
|
||||
@ -72,7 +77,6 @@ enum npc_kpu_lc_ltype {
|
||||
NPC_LT_LC_RARP,
|
||||
NPC_LT_LC_MPLS,
|
||||
NPC_LT_LC_NSH,
|
||||
NPC_LT_LC_PTP,
|
||||
NPC_LT_LC_FCOE,
|
||||
NPC_LT_LC_NGIO,
|
||||
NPC_LT_LC_CUSTOM0 = 0xE,
|
||||
|
@ -696,7 +696,8 @@ int rvu_mbox_handler_cpt_rd_wr_register(struct rvu *rvu,
|
||||
struct cpt_rd_wr_reg_msg *req,
|
||||
struct cpt_rd_wr_reg_msg *rsp)
|
||||
{
|
||||
int blkaddr;
|
||||
u64 offset = req->reg_offset;
|
||||
int blkaddr, lf;
|
||||
|
||||
blkaddr = validate_and_get_cpt_blkaddr(req->blkaddr);
|
||||
if (blkaddr < 0)
|
||||
@ -707,17 +708,25 @@ int rvu_mbox_handler_cpt_rd_wr_register(struct rvu *rvu,
|
||||
!is_cpt_vf(rvu, req->hdr.pcifunc))
|
||||
return CPT_AF_ERR_ACCESS_DENIED;
|
||||
|
||||
rsp->reg_offset = req->reg_offset;
|
||||
rsp->ret_val = req->ret_val;
|
||||
rsp->is_write = req->is_write;
|
||||
|
||||
if (!is_valid_offset(rvu, req))
|
||||
return CPT_AF_ERR_ACCESS_DENIED;
|
||||
|
||||
/* Translate local LF used by VFs to global CPT LF */
|
||||
lf = rvu_get_lf(rvu, &rvu->hw->block[blkaddr], req->hdr.pcifunc,
|
||||
(offset & 0xFFF) >> 3);
|
||||
|
||||
/* Translate local LF's offset to global CPT LF's offset */
|
||||
offset &= 0xFF000;
|
||||
offset += lf << 3;
|
||||
|
||||
rsp->reg_offset = offset;
|
||||
rsp->ret_val = req->ret_val;
|
||||
rsp->is_write = req->is_write;
|
||||
|
||||
if (req->is_write)
|
||||
rvu_write64(rvu, blkaddr, req->reg_offset, req->val);
|
||||
rvu_write64(rvu, blkaddr, offset, req->val);
|
||||
else
|
||||
rsp->val = rvu_read64(rvu, blkaddr, req->reg_offset);
|
||||
rsp->val = rvu_read64(rvu, blkaddr, offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -3862,6 +3862,11 @@ static int get_flowkey_alg_idx(struct nix_hw *nix_hw, u32 flow_cfg)
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
/* Mask to match ipv6(NPC_LT_LC_IP6) and ipv6 ext(NPC_LT_LC_IP6_EXT) */
|
||||
#define NPC_LT_LC_IP6_MATCH_MSK ((~(NPC_LT_LC_IP6 ^ NPC_LT_LC_IP6_EXT)) & 0xf)
|
||||
/* Mask to match both ipv4(NPC_LT_LC_IP) and ipv4 ext(NPC_LT_LC_IP_OPT) */
|
||||
#define NPC_LT_LC_IP_MATCH_MSK ((~(NPC_LT_LC_IP ^ NPC_LT_LC_IP_OPT)) & 0xf)
|
||||
|
||||
static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
|
||||
{
|
||||
int idx, nr_field, key_off, field_marker, keyoff_marker;
|
||||
@ -3931,7 +3936,7 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
|
||||
field->hdr_offset = 9; /* offset */
|
||||
field->bytesm1 = 0; /* 1 byte */
|
||||
field->ltype_match = NPC_LT_LC_IP;
|
||||
field->ltype_mask = 0xF;
|
||||
field->ltype_mask = NPC_LT_LC_IP_MATCH_MSK;
|
||||
break;
|
||||
case NIX_FLOW_KEY_TYPE_IPV4:
|
||||
case NIX_FLOW_KEY_TYPE_INNR_IPV4:
|
||||
@ -3958,8 +3963,7 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
|
||||
field->bytesm1 = 3; /* DIP, 4 bytes */
|
||||
}
|
||||
}
|
||||
|
||||
field->ltype_mask = 0xF; /* Match only IPv4 */
|
||||
field->ltype_mask = NPC_LT_LC_IP_MATCH_MSK;
|
||||
keyoff_marker = false;
|
||||
break;
|
||||
case NIX_FLOW_KEY_TYPE_IPV6:
|
||||
@ -3988,7 +3992,7 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
|
||||
field->bytesm1 = 15; /* DIP,16 bytes */
|
||||
}
|
||||
}
|
||||
field->ltype_mask = 0xF; /* Match only IPv6 */
|
||||
field->ltype_mask = NPC_LT_LC_IP6_MATCH_MSK;
|
||||
break;
|
||||
case NIX_FLOW_KEY_TYPE_TCP:
|
||||
case NIX_FLOW_KEY_TYPE_UDP:
|
||||
|
@ -396,10 +396,9 @@ static int nvmem_sysfs_setup_compat(struct nvmem_device *nvmem,
|
||||
if (!config->base_dev)
|
||||
return -EINVAL;
|
||||
|
||||
if (config->type == NVMEM_TYPE_FRAM)
|
||||
bin_attr_nvmem_eeprom_compat.attr.name = "fram";
|
||||
|
||||
nvmem->eeprom = bin_attr_nvmem_eeprom_compat;
|
||||
if (config->type == NVMEM_TYPE_FRAM)
|
||||
nvmem->eeprom.attr.name = "fram";
|
||||
nvmem->eeprom.attr.mode = nvmem_bin_attr_get_umode(nvmem);
|
||||
nvmem->eeprom.size = nvmem->size;
|
||||
#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
||||
@ -463,7 +462,7 @@ static int nvmem_populate_sysfs_cells(struct nvmem_device *nvmem)
|
||||
"%s@%x,%x", entry->name,
|
||||
entry->offset,
|
||||
entry->bit_offset);
|
||||
attrs[i].attr.mode = 0444;
|
||||
attrs[i].attr.mode = 0444 & nvmem_bin_attr_get_umode(nvmem);
|
||||
attrs[i].size = entry->bytes;
|
||||
attrs[i].read = &nvmem_cell_attr_read;
|
||||
attrs[i].private = entry;
|
||||
|
@ -18,18 +18,24 @@ static int meson_efuse_read(void *context, unsigned int offset,
|
||||
void *val, size_t bytes)
|
||||
{
|
||||
struct meson_sm_firmware *fw = context;
|
||||
int ret;
|
||||
|
||||
return meson_sm_call_read(fw, (u8 *)val, bytes, SM_EFUSE_READ, offset,
|
||||
bytes, 0, 0, 0);
|
||||
ret = meson_sm_call_read(fw, (u8 *)val, bytes, SM_EFUSE_READ, offset,
|
||||
bytes, 0, 0, 0);
|
||||
|
||||
return ret < 0 ? ret : 0;
|
||||
}
|
||||
|
||||
static int meson_efuse_write(void *context, unsigned int offset,
|
||||
void *val, size_t bytes)
|
||||
{
|
||||
struct meson_sm_firmware *fw = context;
|
||||
int ret;
|
||||
|
||||
return meson_sm_call_write(fw, (u8 *)val, bytes, SM_EFUSE_WRITE, offset,
|
||||
bytes, 0, 0, 0);
|
||||
ret = meson_sm_call_write(fw, (u8 *)val, bytes, SM_EFUSE_WRITE, offset,
|
||||
bytes, 0, 0, 0);
|
||||
|
||||
return ret < 0 ? ret : 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id meson_efuse_match[] = {
|
||||
|
@ -46,7 +46,10 @@ static int rmem_read(void *context, unsigned int offset,
|
||||
|
||||
memunmap(addr);
|
||||
|
||||
return count;
|
||||
if (count < 0)
|
||||
return count;
|
||||
|
||||
return count == bytes ? 0 : -EIO;
|
||||
}
|
||||
|
||||
static int rmem_probe(struct platform_device *pdev)
|
||||
|
@ -40,6 +40,7 @@
|
||||
* @addr: Resource address as looped up using resource name from
|
||||
* cmd-db
|
||||
* @state_synced: Indicator that sync_state has been invoked for the rpmhpd resource
|
||||
* @skip_retention_level: Indicate that retention level should not be used for the power domain
|
||||
*/
|
||||
struct rpmhpd {
|
||||
struct device *dev;
|
||||
@ -56,6 +57,7 @@ struct rpmhpd {
|
||||
const char *res_name;
|
||||
u32 addr;
|
||||
bool state_synced;
|
||||
bool skip_retention_level;
|
||||
};
|
||||
|
||||
struct rpmhpd_desc {
|
||||
@ -173,6 +175,7 @@ static struct rpmhpd mxc = {
|
||||
.pd = { .name = "mxc", },
|
||||
.peer = &mxc_ao,
|
||||
.res_name = "mxc.lvl",
|
||||
.skip_retention_level = true,
|
||||
};
|
||||
|
||||
static struct rpmhpd mxc_ao = {
|
||||
@ -180,6 +183,7 @@ static struct rpmhpd mxc_ao = {
|
||||
.active_only = true,
|
||||
.peer = &mxc,
|
||||
.res_name = "mxc.lvl",
|
||||
.skip_retention_level = true,
|
||||
};
|
||||
|
||||
static struct rpmhpd nsp = {
|
||||
@ -819,6 +823,9 @@ static int rpmhpd_update_level_mapping(struct rpmhpd *rpmhpd)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < rpmhpd->level_count; i++) {
|
||||
if (rpmhpd->skip_retention_level && buf[i] == RPMH_REGULATOR_LEVEL_RETENTION)
|
||||
continue;
|
||||
|
||||
rpmhpd->level[i] = buf[i];
|
||||
|
||||
/* Remember the first corner with non-zero level */
|
||||
|
@ -348,11 +348,15 @@ static void pmic_glink_remove(struct platform_device *pdev)
|
||||
mutex_unlock(&__pmic_glink_lock);
|
||||
}
|
||||
|
||||
static const unsigned long pmic_glink_sc8280xp_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) |
|
||||
BIT(PMIC_GLINK_CLIENT_ALTMODE);
|
||||
|
||||
static const unsigned long pmic_glink_sm8450_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) |
|
||||
BIT(PMIC_GLINK_CLIENT_ALTMODE) |
|
||||
BIT(PMIC_GLINK_CLIENT_UCSI);
|
||||
|
||||
static const struct of_device_id pmic_glink_of_match[] = {
|
||||
{ .compatible = "qcom,sc8280xp-pmic-glink", .data = &pmic_glink_sc8280xp_client_mask },
|
||||
{ .compatible = "qcom,pmic-glink", .data = &pmic_glink_sm8450_client_mask },
|
||||
{}
|
||||
};
|
||||
|
@ -164,16 +164,20 @@ static void spi_engine_gen_xfer(struct spi_engine_program *p, bool dry,
|
||||
}
|
||||
|
||||
static void spi_engine_gen_sleep(struct spi_engine_program *p, bool dry,
|
||||
int delay_ns, u32 sclk_hz)
|
||||
int delay_ns, int inst_ns, u32 sclk_hz)
|
||||
{
|
||||
unsigned int t;
|
||||
|
||||
/* negative delay indicates error, e.g. from spi_delay_to_ns() */
|
||||
if (delay_ns <= 0)
|
||||
/*
|
||||
* Negative delay indicates error, e.g. from spi_delay_to_ns(). And if
|
||||
* delay is less that the instruction execution time, there is no need
|
||||
* for an extra sleep instruction since the instruction execution time
|
||||
* will already cover the required delay.
|
||||
*/
|
||||
if (delay_ns < 0 || delay_ns <= inst_ns)
|
||||
return;
|
||||
|
||||
/* rounding down since executing the instruction adds a couple of ticks delay */
|
||||
t = DIV_ROUND_DOWN_ULL((u64)delay_ns * sclk_hz, NSEC_PER_SEC);
|
||||
t = DIV_ROUND_UP_ULL((u64)(delay_ns - inst_ns) * sclk_hz, NSEC_PER_SEC);
|
||||
while (t) {
|
||||
unsigned int n = min(t, 256U);
|
||||
|
||||
@ -220,10 +224,16 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry,
|
||||
struct spi_device *spi = msg->spi;
|
||||
struct spi_controller *host = spi->controller;
|
||||
struct spi_transfer *xfer;
|
||||
int clk_div, new_clk_div;
|
||||
int clk_div, new_clk_div, inst_ns;
|
||||
bool keep_cs = false;
|
||||
u8 bits_per_word = 0;
|
||||
|
||||
/*
|
||||
* Take into account instruction execution time for more accurate sleep
|
||||
* times, especially when the delay is small.
|
||||
*/
|
||||
inst_ns = DIV_ROUND_UP(NSEC_PER_SEC, host->max_speed_hz);
|
||||
|
||||
clk_div = 1;
|
||||
|
||||
spi_engine_program_add_cmd(p, dry,
|
||||
@ -252,7 +262,7 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry,
|
||||
|
||||
spi_engine_gen_xfer(p, dry, xfer);
|
||||
spi_engine_gen_sleep(p, dry, spi_delay_to_ns(&xfer->delay, xfer),
|
||||
xfer->effective_speed_hz);
|
||||
inst_ns, xfer->effective_speed_hz);
|
||||
|
||||
if (xfer->cs_change) {
|
||||
if (list_is_last(&xfer->transfer_list, &msg->transfers)) {
|
||||
@ -262,7 +272,7 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry,
|
||||
spi_engine_gen_cs(p, dry, spi, false);
|
||||
|
||||
spi_engine_gen_sleep(p, dry, spi_delay_to_ns(
|
||||
&xfer->cs_change_delay, xfer),
|
||||
&xfer->cs_change_delay, xfer), inst_ns,
|
||||
xfer->effective_speed_hz);
|
||||
|
||||
if (!list_next_entry(xfer, transfer_list)->cs_off)
|
||||
|
@ -984,6 +984,9 @@ static int davinci_spi_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
|
||||
free_dma:
|
||||
/* This bit needs to be cleared to disable dpsi->clk */
|
||||
clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK);
|
||||
|
||||
if (dspi->dma_rx) {
|
||||
dma_release_channel(dspi->dma_rx);
|
||||
dma_release_channel(dspi->dma_tx);
|
||||
@ -1013,6 +1016,9 @@ static void davinci_spi_remove(struct platform_device *pdev)
|
||||
|
||||
spi_bitbang_stop(&dspi->bitbang);
|
||||
|
||||
/* This bit needs to be cleared to disable dpsi->clk */
|
||||
clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK);
|
||||
|
||||
if (dspi->dma_rx) {
|
||||
dma_release_channel(dspi->dma_rx);
|
||||
dma_release_channel(dspi->dma_tx);
|
||||
|
@ -1050,7 +1050,7 @@ static struct spi_imx_devtype_data imx35_cspi_devtype_data = {
|
||||
.rx_available = mx31_rx_available,
|
||||
.reset = mx31_reset,
|
||||
.fifo_size = 8,
|
||||
.has_dmamode = true,
|
||||
.has_dmamode = false,
|
||||
.dynamic_burst = false,
|
||||
.has_targetmode = false,
|
||||
.devtype = IMX35_CSPI,
|
||||
|
@ -158,12 +158,14 @@ static int spi_mux_probe(struct spi_device *spi)
|
||||
/* supported modes are the same as our parent's */
|
||||
ctlr->mode_bits = spi->controller->mode_bits;
|
||||
ctlr->flags = spi->controller->flags;
|
||||
ctlr->bits_per_word_mask = spi->controller->bits_per_word_mask;
|
||||
ctlr->transfer_one_message = spi_mux_transfer_one_message;
|
||||
ctlr->setup = spi_mux_setup;
|
||||
ctlr->num_chipselect = mux_control_states(priv->mux);
|
||||
ctlr->bus_num = -1;
|
||||
ctlr->dev.of_node = spi->dev.of_node;
|
||||
ctlr->must_async = true;
|
||||
ctlr->defer_optimize_message = true;
|
||||
|
||||
ret = devm_spi_register_controller(&spi->dev, ctlr);
|
||||
if (ret)
|
||||
|
@ -1277,24 +1277,11 @@ static int omap2_mcspi_prepare_message(struct spi_controller *ctlr,
|
||||
|
||||
/*
|
||||
* Check if this transfer contains only one word;
|
||||
* OR contains 1 to 4 words, with bits_per_word == 8 and no delay between each word
|
||||
* OR contains 1 to 2 words, with bits_per_word == 16 and no delay between each word
|
||||
*
|
||||
* If one of the two last case is true, this also change the bits_per_word of this
|
||||
* transfer to make it a bit faster.
|
||||
* It's not an issue to change the bits_per_word here even if the multi-mode is not
|
||||
* applicable for this message, the signal on the wire will be the same.
|
||||
*/
|
||||
if (bits_per_word < 8 && tr->len == 1) {
|
||||
/* multi-mode is applicable, only one word (1..7 bits) */
|
||||
} else if (tr->word_delay.value == 0 && bits_per_word == 8 && tr->len <= 4) {
|
||||
/* multi-mode is applicable, only one "bigger" word (8,16,24,32 bits) */
|
||||
tr->bits_per_word = tr->len * bits_per_word;
|
||||
} else if (tr->word_delay.value == 0 && bits_per_word == 16 && tr->len <= 2) {
|
||||
/* multi-mode is applicable, only one "bigger" word (16,32 bits) */
|
||||
tr->bits_per_word = tr->len * bits_per_word / 2;
|
||||
} else if (bits_per_word >= 8 && tr->len == bits_per_word / 8) {
|
||||
/* multi-mode is applicable, only one word (9..15,17..32 bits) */
|
||||
/* multi-mode is applicable, only one word (8..32 bits) */
|
||||
} else {
|
||||
/* multi-mode is not applicable: more than one word in the transfer */
|
||||
mcspi->use_multi_mode = false;
|
||||
|
@ -2151,7 +2151,8 @@ static void __spi_unoptimize_message(struct spi_message *msg)
|
||||
*/
|
||||
static void spi_maybe_unoptimize_message(struct spi_message *msg)
|
||||
{
|
||||
if (!msg->pre_optimized && msg->optimized)
|
||||
if (!msg->pre_optimized && msg->optimized &&
|
||||
!msg->spi->controller->defer_optimize_message)
|
||||
__spi_unoptimize_message(msg);
|
||||
}
|
||||
|
||||
@ -4294,6 +4295,11 @@ static int __spi_optimize_message(struct spi_device *spi,
|
||||
static int spi_maybe_optimize_message(struct spi_device *spi,
|
||||
struct spi_message *msg)
|
||||
{
|
||||
if (spi->controller->defer_optimize_message) {
|
||||
msg->spi = spi;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (msg->pre_optimized)
|
||||
return 0;
|
||||
|
||||
@ -4324,6 +4330,13 @@ int spi_optimize_message(struct spi_device *spi, struct spi_message *msg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Pre-optimization is not supported and optimization is deferred e.g.
|
||||
* when using spi-mux.
|
||||
*/
|
||||
if (spi->controller->defer_optimize_message)
|
||||
return 0;
|
||||
|
||||
ret = __spi_optimize_message(spi, msg);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -4350,6 +4363,9 @@ EXPORT_SYMBOL_GPL(spi_optimize_message);
|
||||
*/
|
||||
void spi_unoptimize_message(struct spi_message *msg)
|
||||
{
|
||||
if (msg->spi->controller->defer_optimize_message)
|
||||
return;
|
||||
|
||||
__spi_unoptimize_message(msg);
|
||||
msg->pre_optimized = false;
|
||||
}
|
||||
@ -4432,8 +4448,6 @@ int spi_async(struct spi_device *spi, struct spi_message *message)
|
||||
|
||||
spin_unlock_irqrestore(&ctlr->bus_lock_spinlock, flags);
|
||||
|
||||
spi_maybe_unoptimize_message(message);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(spi_async);
|
||||
|
@ -672,7 +672,8 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id)
|
||||
* https://www.ti.com/lit/pdf/sprz536
|
||||
*/
|
||||
if (priv->habit & UART_RX_TIMEOUT_QUIRK &&
|
||||
(iir & UART_IIR_RX_TIMEOUT) == UART_IIR_RX_TIMEOUT) {
|
||||
(iir & UART_IIR_RX_TIMEOUT) == UART_IIR_RX_TIMEOUT &&
|
||||
serial_port_in(port, UART_OMAP_RX_LVL) == 0) {
|
||||
unsigned char efr2, timeout_h, timeout_l;
|
||||
|
||||
efr2 = serial_in(up, UART_OMAP_EFR2);
|
||||
|
@ -120,6 +120,7 @@
|
||||
#define UCR4_OREN (1<<1) /* Receiver overrun interrupt enable */
|
||||
#define UCR4_DREN (1<<0) /* Recv data ready interrupt enable */
|
||||
#define UFCR_RXTL_SHF 0 /* Receiver trigger level shift */
|
||||
#define UFCR_RXTL_MASK 0x3F /* Receiver trigger 6 bits wide */
|
||||
#define UFCR_DCEDTE (1<<6) /* DCE/DTE mode select */
|
||||
#define UFCR_RFDIV (7<<7) /* Reference freq divider mask */
|
||||
#define UFCR_RFDIV_REG(x) (((x) < 7 ? 6 - (x) : 6) << 7)
|
||||
@ -1551,6 +1552,7 @@ static void imx_uart_shutdown(struct uart_port *port)
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
unsigned long flags;
|
||||
u32 ucr1, ucr2, ucr4, uts;
|
||||
int loops;
|
||||
|
||||
if (sport->dma_is_enabled) {
|
||||
dmaengine_terminate_sync(sport->dma_chan_tx);
|
||||
@ -1613,6 +1615,56 @@ static void imx_uart_shutdown(struct uart_port *port)
|
||||
ucr4 &= ~UCR4_TCEN;
|
||||
imx_uart_writel(sport, ucr4, UCR4);
|
||||
|
||||
/*
|
||||
* We have to ensure the tx state machine ends up in OFF. This
|
||||
* is especially important for rs485 where we must not leave
|
||||
* the RTS signal high, blocking the bus indefinitely.
|
||||
*
|
||||
* All interrupts are now disabled, so imx_uart_stop_tx() will
|
||||
* no longer be called from imx_uart_transmit_buffer(). It may
|
||||
* still be called via the hrtimers, and if those are in play,
|
||||
* we have to honour the delays.
|
||||
*/
|
||||
if (sport->tx_state == WAIT_AFTER_RTS || sport->tx_state == SEND)
|
||||
imx_uart_stop_tx(port);
|
||||
|
||||
/*
|
||||
* In many cases (rs232 mode, or if tx_state was
|
||||
* WAIT_AFTER_RTS, or if tx_state was SEND and there is no
|
||||
* delay_rts_after_send), this will have moved directly to
|
||||
* OFF. In rs485 mode, tx_state might already have been
|
||||
* WAIT_AFTER_SEND and the hrtimer thus already started, or
|
||||
* the above imx_uart_stop_tx() call could have started it. In
|
||||
* those cases, we have to wait for the hrtimer to fire and
|
||||
* complete the transition to OFF.
|
||||
*/
|
||||
loops = port->rs485.flags & SER_RS485_ENABLED ?
|
||||
port->rs485.delay_rts_after_send : 0;
|
||||
while (sport->tx_state != OFF && loops--) {
|
||||
uart_port_unlock_irqrestore(&sport->port, flags);
|
||||
msleep(1);
|
||||
uart_port_lock_irqsave(&sport->port, &flags);
|
||||
}
|
||||
|
||||
if (sport->tx_state != OFF) {
|
||||
dev_warn(sport->port.dev, "unexpected tx_state %d\n",
|
||||
sport->tx_state);
|
||||
/*
|
||||
* This machine may be busted, but ensure the RTS
|
||||
* signal is inactive in order not to block other
|
||||
* devices.
|
||||
*/
|
||||
if (port->rs485.flags & SER_RS485_ENABLED) {
|
||||
ucr2 = imx_uart_readl(sport, UCR2);
|
||||
if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
|
||||
imx_uart_rts_active(sport, &ucr2);
|
||||
else
|
||||
imx_uart_rts_inactive(sport, &ucr2);
|
||||
imx_uart_writel(sport, ucr2, UCR2);
|
||||
}
|
||||
sport->tx_state = OFF;
|
||||
}
|
||||
|
||||
uart_port_unlock_irqrestore(&sport->port, flags);
|
||||
|
||||
clk_disable_unprepare(sport->clk_per);
|
||||
@ -1933,7 +1985,7 @@ static int imx_uart_rs485_config(struct uart_port *port, struct ktermios *termio
|
||||
struct serial_rs485 *rs485conf)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
u32 ucr2;
|
||||
u32 ucr2, ufcr;
|
||||
|
||||
if (rs485conf->flags & SER_RS485_ENABLED) {
|
||||
/* Enable receiver if low-active RTS signal is requested */
|
||||
@ -1953,7 +2005,10 @@ static int imx_uart_rs485_config(struct uart_port *port, struct ktermios *termio
|
||||
/* Make sure Rx is enabled in case Tx is active with Rx disabled */
|
||||
if (!(rs485conf->flags & SER_RS485_ENABLED) ||
|
||||
rs485conf->flags & SER_RS485_RX_DURING_TX) {
|
||||
imx_uart_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
|
||||
/* If the receiver trigger is 0, set it to a default value */
|
||||
ufcr = imx_uart_readl(sport, UFCR);
|
||||
if ((ufcr & UFCR_RXTL_MASK) == 0)
|
||||
imx_uart_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
|
||||
imx_uart_start_rx(port);
|
||||
}
|
||||
|
||||
|
@ -688,12 +688,13 @@ static int ma35d1serial_probe(struct platform_device *pdev)
|
||||
struct uart_ma35d1_port *up;
|
||||
int ret = 0;
|
||||
|
||||
if (pdev->dev.of_node) {
|
||||
ret = of_alias_get_id(pdev->dev.of_node, "serial");
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed to get alias/pdev id, errno %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (!pdev->dev.of_node)
|
||||
return -ENODEV;
|
||||
|
||||
ret = of_alias_get_id(pdev->dev.of_node, "serial");
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed to get alias/pdev id, errno %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
up = &ma35d1serial_ports[ret];
|
||||
up->port.line = ret;
|
||||
|
@ -649,15 +649,25 @@ static void qcom_geni_serial_start_tx_dma(struct uart_port *uport)
|
||||
|
||||
static void qcom_geni_serial_start_tx_fifo(struct uart_port *uport)
|
||||
{
|
||||
unsigned char c;
|
||||
u32 irq_en;
|
||||
|
||||
if (qcom_geni_serial_main_active(uport) ||
|
||||
!qcom_geni_serial_tx_empty(uport))
|
||||
return;
|
||||
/*
|
||||
* Start a new transfer in case the previous command was cancelled and
|
||||
* left data in the FIFO which may prevent the watermark interrupt
|
||||
* from triggering. Note that the stale data is discarded.
|
||||
*/
|
||||
if (!qcom_geni_serial_main_active(uport) &&
|
||||
!qcom_geni_serial_tx_empty(uport)) {
|
||||
if (uart_fifo_out(uport, &c, 1) == 1) {
|
||||
writel(M_CMD_DONE_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
|
||||
qcom_geni_serial_setup_tx(uport, 1);
|
||||
writel(c, uport->membase + SE_GENI_TX_FIFOn);
|
||||
}
|
||||
}
|
||||
|
||||
irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
|
||||
irq_en |= M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN;
|
||||
|
||||
writel(DEF_TX_WM, uport->membase + SE_GENI_TX_WATERMARK_REG);
|
||||
writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN);
|
||||
}
|
||||
@ -665,13 +675,17 @@ static void qcom_geni_serial_start_tx_fifo(struct uart_port *uport)
|
||||
static void qcom_geni_serial_stop_tx_fifo(struct uart_port *uport)
|
||||
{
|
||||
u32 irq_en;
|
||||
struct qcom_geni_serial_port *port = to_dev_port(uport);
|
||||
|
||||
irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
|
||||
irq_en &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN);
|
||||
writel(0, uport->membase + SE_GENI_TX_WATERMARK_REG);
|
||||
writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN);
|
||||
/* Possible stop tx is called multiple times. */
|
||||
}
|
||||
|
||||
static void qcom_geni_serial_cancel_tx_cmd(struct uart_port *uport)
|
||||
{
|
||||
struct qcom_geni_serial_port *port = to_dev_port(uport);
|
||||
|
||||
if (!qcom_geni_serial_main_active(uport))
|
||||
return;
|
||||
|
||||
@ -684,6 +698,8 @@ static void qcom_geni_serial_stop_tx_fifo(struct uart_port *uport)
|
||||
writel(M_CMD_ABORT_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
|
||||
}
|
||||
writel(M_CMD_CANCEL_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
|
||||
|
||||
port->tx_remaining = 0;
|
||||
}
|
||||
|
||||
static void qcom_geni_serial_handle_rx_fifo(struct uart_port *uport, bool drop)
|
||||
@ -862,7 +878,7 @@ static void qcom_geni_serial_send_chunk_fifo(struct uart_port *uport,
|
||||
memset(buf, 0, sizeof(buf));
|
||||
tx_bytes = min(remaining, BYTES_PER_FIFO_WORD);
|
||||
|
||||
tx_bytes = uart_fifo_out(uport, buf, tx_bytes);
|
||||
uart_fifo_out(uport, buf, tx_bytes);
|
||||
|
||||
iowrite32_rep(uport->membase + SE_GENI_TX_FIFOn, buf, 1);
|
||||
|
||||
@ -890,13 +906,17 @@ static void qcom_geni_serial_handle_tx_fifo(struct uart_port *uport,
|
||||
else
|
||||
pending = kfifo_len(&tport->xmit_fifo);
|
||||
|
||||
/* All data has been transmitted and acknowledged as received */
|
||||
if (!pending && !status && done) {
|
||||
/* All data has been transmitted or command has been cancelled */
|
||||
if (!pending && done) {
|
||||
qcom_geni_serial_stop_tx_fifo(uport);
|
||||
goto out_write_wakeup;
|
||||
}
|
||||
|
||||
avail = port->tx_fifo_depth - (status & TX_FIFO_WC);
|
||||
if (active)
|
||||
avail = port->tx_fifo_depth - (status & TX_FIFO_WC);
|
||||
else
|
||||
avail = port->tx_fifo_depth;
|
||||
|
||||
avail *= BYTES_PER_FIFO_WORD;
|
||||
|
||||
chunk = min(avail, pending);
|
||||
@ -1069,11 +1089,15 @@ static void qcom_geni_serial_shutdown(struct uart_port *uport)
|
||||
{
|
||||
disable_irq(uport->irq);
|
||||
|
||||
if (uart_console(uport))
|
||||
return;
|
||||
|
||||
qcom_geni_serial_stop_tx(uport);
|
||||
qcom_geni_serial_stop_rx(uport);
|
||||
|
||||
qcom_geni_serial_cancel_tx_cmd(uport);
|
||||
}
|
||||
|
||||
static void qcom_geni_serial_flush_buffer(struct uart_port *uport)
|
||||
{
|
||||
qcom_geni_serial_cancel_tx_cmd(uport);
|
||||
}
|
||||
|
||||
static int qcom_geni_serial_port_setup(struct uart_port *uport)
|
||||
@ -1532,6 +1556,7 @@ static const struct uart_ops qcom_geni_console_pops = {
|
||||
.request_port = qcom_geni_serial_request_port,
|
||||
.config_port = qcom_geni_serial_config_port,
|
||||
.shutdown = qcom_geni_serial_shutdown,
|
||||
.flush_buffer = qcom_geni_serial_flush_buffer,
|
||||
.type = qcom_geni_serial_get_type,
|
||||
.set_mctrl = qcom_geni_serial_set_mctrl,
|
||||
.get_mctrl = qcom_geni_serial_get_mctrl,
|
||||
|
@ -291,6 +291,20 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
|
||||
if (ifp->desc.bNumEndpoints >= num_ep)
|
||||
goto skip_to_next_endpoint_or_interface_descriptor;
|
||||
|
||||
/* Save a copy of the descriptor and use it instead of the original */
|
||||
endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints];
|
||||
memcpy(&endpoint->desc, d, n);
|
||||
d = &endpoint->desc;
|
||||
|
||||
/* Clear the reserved bits in bEndpointAddress */
|
||||
i = d->bEndpointAddress &
|
||||
(USB_ENDPOINT_DIR_MASK | USB_ENDPOINT_NUMBER_MASK);
|
||||
if (i != d->bEndpointAddress) {
|
||||
dev_notice(ddev, "config %d interface %d altsetting %d has an endpoint descriptor with address 0x%X, changing to 0x%X\n",
|
||||
cfgno, inum, asnum, d->bEndpointAddress, i);
|
||||
endpoint->desc.bEndpointAddress = i;
|
||||
}
|
||||
|
||||
/* Check for duplicate endpoint addresses */
|
||||
if (config_endpoint_is_duplicate(config, inum, asnum, d)) {
|
||||
dev_notice(ddev, "config %d interface %d altsetting %d has a duplicate endpoint with address 0x%X, skipping\n",
|
||||
@ -308,10 +322,8 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
|
||||
}
|
||||
}
|
||||
|
||||
endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints];
|
||||
/* Accept this endpoint */
|
||||
++ifp->desc.bNumEndpoints;
|
||||
|
||||
memcpy(&endpoint->desc, d, n);
|
||||
INIT_LIST_HEAD(&endpoint->urb_list);
|
||||
|
||||
/*
|
||||
|
@ -84,9 +84,12 @@ static bool usb_of_has_devices_or_graph(const struct usb_device *hub)
|
||||
if (of_graph_is_present(np))
|
||||
return true;
|
||||
|
||||
for_each_child_of_node(np, child)
|
||||
if (of_property_present(child, "reg"))
|
||||
for_each_child_of_node(np, child) {
|
||||
if (of_property_present(child, "reg")) {
|
||||
of_node_put(child);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -506,6 +506,9 @@ static const struct usb_device_id usb_quirk_list[] = {
|
||||
{ USB_DEVICE(0x1b1c, 0x1b38), .driver_info = USB_QUIRK_DELAY_INIT |
|
||||
USB_QUIRK_DELAY_CTRL_MSG },
|
||||
|
||||
/* START BP-850k Printer */
|
||||
{ USB_DEVICE(0x1bc3, 0x0003), .driver_info = USB_QUIRK_NO_SET_INTF },
|
||||
|
||||
/* MIDI keyboard WORLDE MINI */
|
||||
{ USB_DEVICE(0x1c75, 0x0204), .driver_info =
|
||||
USB_QUIRK_CONFIG_INTF_STRINGS },
|
||||
|
@ -54,6 +54,10 @@
|
||||
#define PCI_DEVICE_ID_INTEL_MTL 0x7e7e
|
||||
#define PCI_DEVICE_ID_INTEL_ARLH_PCH 0x777e
|
||||
#define PCI_DEVICE_ID_INTEL_TGL 0x9a15
|
||||
#define PCI_DEVICE_ID_INTEL_PTLH 0xe332
|
||||
#define PCI_DEVICE_ID_INTEL_PTLH_PCH 0xe37e
|
||||
#define PCI_DEVICE_ID_INTEL_PTLU 0xe432
|
||||
#define PCI_DEVICE_ID_INTEL_PTLU_PCH 0xe47e
|
||||
#define PCI_DEVICE_ID_AMD_MR 0x163a
|
||||
|
||||
#define PCI_INTEL_BXT_DSM_GUID "732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511"
|
||||
@ -430,6 +434,10 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
|
||||
{ PCI_DEVICE_DATA(INTEL, MTLS, &dwc3_pci_intel_swnode) },
|
||||
{ PCI_DEVICE_DATA(INTEL, ARLH_PCH, &dwc3_pci_intel_swnode) },
|
||||
{ PCI_DEVICE_DATA(INTEL, TGL, &dwc3_pci_intel_swnode) },
|
||||
{ PCI_DEVICE_DATA(INTEL, PTLH, &dwc3_pci_intel_swnode) },
|
||||
{ PCI_DEVICE_DATA(INTEL, PTLH_PCH, &dwc3_pci_intel_swnode) },
|
||||
{ PCI_DEVICE_DATA(INTEL, PTLU, &dwc3_pci_intel_swnode) },
|
||||
{ PCI_DEVICE_DATA(INTEL, PTLU_PCH, &dwc3_pci_intel_swnode) },
|
||||
|
||||
{ PCI_DEVICE_DATA(AMD, NL_USB, &dwc3_pci_amd_swnode) },
|
||||
{ PCI_DEVICE_DATA(AMD, MR, &dwc3_pci_amd_mr_swnode) },
|
||||
|
@ -115,9 +115,12 @@ static int usb_string_copy(const char *s, char **s_copy)
|
||||
int ret;
|
||||
char *str;
|
||||
char *copy = *s_copy;
|
||||
|
||||
ret = strlen(s);
|
||||
if (ret > USB_MAX_STRING_LEN)
|
||||
return -EOVERFLOW;
|
||||
if (ret < 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (copy) {
|
||||
str = copy;
|
||||
|
@ -1125,10 +1125,20 @@ int xhci_resume(struct xhci_hcd *xhci, pm_message_t msg)
|
||||
xhci_dbg(xhci, "Start the secondary HCD\n");
|
||||
retval = xhci_run(xhci->shared_hcd);
|
||||
}
|
||||
|
||||
if (retval)
|
||||
return retval;
|
||||
/*
|
||||
* Resume roothubs unconditionally as PORTSC change bits are not
|
||||
* immediately visible after xHC reset
|
||||
*/
|
||||
hcd->state = HC_STATE_SUSPENDED;
|
||||
if (xhci->shared_hcd)
|
||||
|
||||
if (xhci->shared_hcd) {
|
||||
xhci->shared_hcd->state = HC_STATE_SUSPENDED;
|
||||
usb_hcd_resume_root_hub(xhci->shared_hcd);
|
||||
}
|
||||
usb_hcd_resume_root_hub(hcd);
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -1152,7 +1162,6 @@ int xhci_resume(struct xhci_hcd *xhci, pm_message_t msg)
|
||||
|
||||
xhci_dbc_resume(xhci);
|
||||
|
||||
done:
|
||||
if (retval == 0) {
|
||||
/*
|
||||
* Resume roothubs only if there are pending events.
|
||||
@ -1178,6 +1187,7 @@ int xhci_resume(struct xhci_hcd *xhci, pm_message_t msg)
|
||||
usb_hcd_resume_root_hub(hcd);
|
||||
}
|
||||
}
|
||||
done:
|
||||
/*
|
||||
* If system is subject to the Quirk, Compliance Mode Timer needs to
|
||||
* be re-initialized Always after a system resume. Ports are subject
|
||||
|
@ -1737,6 +1737,49 @@ static void mos7840_port_remove(struct usb_serial_port *port)
|
||||
kfree(mos7840_port);
|
||||
}
|
||||
|
||||
static int mos7840_suspend(struct usb_serial *serial, pm_message_t message)
|
||||
{
|
||||
struct moschip_port *mos7840_port;
|
||||
struct usb_serial_port *port;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < serial->num_ports; ++i) {
|
||||
port = serial->port[i];
|
||||
if (!tty_port_initialized(&port->port))
|
||||
continue;
|
||||
|
||||
mos7840_port = usb_get_serial_port_data(port);
|
||||
|
||||
usb_kill_urb(mos7840_port->read_urb);
|
||||
mos7840_port->read_urb_busy = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mos7840_resume(struct usb_serial *serial)
|
||||
{
|
||||
struct moschip_port *mos7840_port;
|
||||
struct usb_serial_port *port;
|
||||
int res;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < serial->num_ports; ++i) {
|
||||
port = serial->port[i];
|
||||
if (!tty_port_initialized(&port->port))
|
||||
continue;
|
||||
|
||||
mos7840_port = usb_get_serial_port_data(port);
|
||||
|
||||
mos7840_port->read_urb_busy = true;
|
||||
res = usb_submit_urb(mos7840_port->read_urb, GFP_NOIO);
|
||||
if (res)
|
||||
mos7840_port->read_urb_busy = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct usb_serial_driver moschip7840_4port_device = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
@ -1764,6 +1807,8 @@ static struct usb_serial_driver moschip7840_4port_device = {
|
||||
.port_probe = mos7840_port_probe,
|
||||
.port_remove = mos7840_port_remove,
|
||||
.read_bulk_callback = mos7840_bulk_in_callback,
|
||||
.suspend = mos7840_suspend,
|
||||
.resume = mos7840_resume,
|
||||
};
|
||||
|
||||
static struct usb_serial_driver * const serial_drivers[] = {
|
||||
|
@ -1425,6 +1425,10 @@ static const struct usb_device_id option_ids[] = {
|
||||
.driver_info = NCTRL(0) | RSVD(1) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1901, 0xff), /* Telit LN940 (MBIM) */
|
||||
.driver_info = NCTRL(0) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x3000, 0xff), /* Telit FN912 */
|
||||
.driver_info = RSVD(0) | NCTRL(3) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x3001, 0xff), /* Telit FN912 */
|
||||
.driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x7010, 0xff), /* Telit LE910-S1 (RNDIS) */
|
||||
.driver_info = NCTRL(2) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x7011, 0xff), /* Telit LE910-S1 (ECM) */
|
||||
@ -1433,6 +1437,8 @@ static const struct usb_device_id option_ids[] = {
|
||||
.driver_info = NCTRL(2) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x701b, 0xff), /* Telit LE910R1 (ECM) */
|
||||
.driver_info = NCTRL(2) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x9000, 0xff), /* Telit generic core-dump device */
|
||||
.driver_info = NCTRL(0) },
|
||||
{ USB_DEVICE(TELIT_VENDOR_ID, 0x9010), /* Telit SBL FN980 flashing device */
|
||||
.driver_info = NCTRL(0) | ZLP },
|
||||
{ USB_DEVICE(TELIT_VENDOR_ID, 0x9200), /* Telit LE910S1 flashing device */
|
||||
@ -2224,6 +2230,10 @@ static const struct usb_device_id option_ids[] = {
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7106_2COM, 0x02, 0x02, 0x01) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x02, 0x01) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x00, 0x00) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x7126, 0xff, 0x00, 0x00),
|
||||
.driver_info = NCTRL(2) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x7127, 0xff, 0x00, 0x00),
|
||||
.driver_info = NCTRL(2) | NCTRL(3) | NCTRL(4) },
|
||||
{ USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) },
|
||||
{ USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MPL200),
|
||||
.driver_info = RSVD(1) | RSVD(4) },
|
||||
@ -2284,6 +2294,8 @@ static const struct usb_device_id option_ids[] = {
|
||||
.driver_info = RSVD(3) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x0489, 0xe0f0, 0xff), /* Foxconn T99W373 MBIM */
|
||||
.driver_info = RSVD(3) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x0489, 0xe145, 0xff), /* Foxconn T99W651 RNDIS */
|
||||
.driver_info = RSVD(5) | RSVD(6) },
|
||||
{ USB_DEVICE(0x1508, 0x1001), /* Fibocom NL668 (IOT version) */
|
||||
.driver_info = RSVD(4) | RSVD(5) | RSVD(6) },
|
||||
{ USB_DEVICE(0x1782, 0x4d10) }, /* Fibocom L610 (AT mode) */
|
||||
@ -2321,6 +2333,32 @@ static const struct usb_device_id option_ids[] = {
|
||||
.driver_info = RSVD(4) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x0115, 0xff), /* Rolling RW135-GL (laptop MBIM) */
|
||||
.driver_info = RSVD(5) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x0802, 0xff), /* Rolling RW350-GL (laptop MBIM) */
|
||||
.driver_info = RSVD(5) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0100, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WWD for Global */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0100, 0xff, 0x00, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0100, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0101, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WRD for Global SKU */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0101, 0xff, 0x00, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0101, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0106, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WRD for China SKU */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0106, 0xff, 0x00, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0106, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0111, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WWD for SA */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0111, 0xff, 0x00, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0111, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0112, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WWD for EU */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0112, 0xff, 0x00, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0112, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0113, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WWD for NA */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0113, 0xff, 0x00, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0113, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0115, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WWD for China EDU */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0115, 0xff, 0x00, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0115, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0116, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WWD for Golbal EDU */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0116, 0xff, 0x00, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0116, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(OPPO_VENDOR_ID, OPPO_PRODUCT_R11, 0xff, 0xff, 0x30) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x30) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x40) },
|
||||
|
@ -641,16 +641,30 @@ static int bch2_gc_btree(struct btree_trans *trans, enum btree_id btree, bool in
|
||||
target_depth = 0;
|
||||
|
||||
/* root */
|
||||
mutex_lock(&c->btree_root_lock);
|
||||
struct btree *b = bch2_btree_id_root(c, btree)->b;
|
||||
if (!btree_node_fake(b)) {
|
||||
do {
|
||||
retry_root:
|
||||
bch2_trans_begin(trans);
|
||||
|
||||
struct btree_iter iter;
|
||||
bch2_trans_node_iter_init(trans, &iter, btree, POS_MIN,
|
||||
0, bch2_btree_id_root(c, btree)->b->c.level, 0);
|
||||
struct btree *b = bch2_btree_iter_peek_node(&iter);
|
||||
ret = PTR_ERR_OR_ZERO(b);
|
||||
if (ret)
|
||||
goto err_root;
|
||||
|
||||
if (b != btree_node_root(c, b)) {
|
||||
bch2_trans_iter_exit(trans, &iter);
|
||||
goto retry_root;
|
||||
}
|
||||
|
||||
gc_pos_set(c, gc_pos_btree(btree, b->c.level + 1, SPOS_MAX));
|
||||
ret = lockrestart_do(trans,
|
||||
bch2_gc_mark_key(trans, b->c.btree_id, b->c.level + 1,
|
||||
NULL, NULL, bkey_i_to_s_c(&b->key), initial));
|
||||
struct bkey_s_c k = bkey_i_to_s_c(&b->key);
|
||||
ret = bch2_gc_mark_key(trans, btree, b->c.level + 1, NULL, NULL, k, initial);
|
||||
level = b->c.level;
|
||||
}
|
||||
mutex_unlock(&c->btree_root_lock);
|
||||
err_root:
|
||||
bch2_trans_iter_exit(trans, &iter);
|
||||
} while (bch2_err_matches(ret, BCH_ERR_transaction_restart));
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -996,7 +996,7 @@ static int bch2_btree_path_traverse_all(struct btree_trans *trans)
|
||||
|
||||
bch2_trans_unlock(trans);
|
||||
cond_resched();
|
||||
trans->locked = true;
|
||||
trans_set_locked(trans);
|
||||
|
||||
if (unlikely(trans->memory_allocation_failure)) {
|
||||
struct closure cl;
|
||||
@ -3089,7 +3089,8 @@ u32 bch2_trans_begin(struct btree_trans *trans)
|
||||
bch2_trans_srcu_unlock(trans);
|
||||
|
||||
trans->last_begin_ip = _RET_IP_;
|
||||
trans->locked = true;
|
||||
|
||||
trans_set_locked(trans);
|
||||
|
||||
if (trans->restarted) {
|
||||
bch2_btree_path_traverse_all(trans);
|
||||
@ -3159,7 +3160,6 @@ struct btree_trans *__bch2_trans_get(struct bch_fs *c, unsigned fn_idx)
|
||||
trans->last_begin_time = local_clock();
|
||||
trans->fn_idx = fn_idx;
|
||||
trans->locking_wait.task = current;
|
||||
trans->locked = true;
|
||||
trans->journal_replay_not_finished =
|
||||
unlikely(!test_bit(JOURNAL_replay_done, &c->journal.flags)) &&
|
||||
atomic_inc_not_zero(&c->journal_keys.ref);
|
||||
@ -3193,6 +3193,7 @@ struct btree_trans *__bch2_trans_get(struct bch_fs *c, unsigned fn_idx)
|
||||
trans->srcu_idx = srcu_read_lock(&c->btree_trans_barrier);
|
||||
trans->srcu_lock_time = jiffies;
|
||||
trans->srcu_held = true;
|
||||
trans_set_locked(trans);
|
||||
|
||||
closure_init_stack_release(&trans->ref);
|
||||
return trans;
|
||||
|
@ -231,7 +231,7 @@ static noinline int break_cycle(struct lock_graph *g, struct printbuf *cycle)
|
||||
prt_newline(&buf);
|
||||
}
|
||||
|
||||
bch2_print_string_as_lines(KERN_ERR, buf.buf);
|
||||
bch2_print_string_as_lines_nonblocking(KERN_ERR, buf.buf);
|
||||
printbuf_exit(&buf);
|
||||
BUG();
|
||||
}
|
||||
@ -792,7 +792,7 @@ static inline int __bch2_trans_relock(struct btree_trans *trans, bool trace)
|
||||
return bch2_trans_relock_fail(trans, path, &f, trace);
|
||||
}
|
||||
|
||||
trans->locked = true;
|
||||
trans_set_locked(trans);
|
||||
out:
|
||||
bch2_trans_verify_locks(trans);
|
||||
return 0;
|
||||
@ -812,16 +812,14 @@ void bch2_trans_unlock_noassert(struct btree_trans *trans)
|
||||
{
|
||||
__bch2_trans_unlock(trans);
|
||||
|
||||
trans->locked = false;
|
||||
trans->last_unlock_ip = _RET_IP_;
|
||||
trans_set_unlocked(trans);
|
||||
}
|
||||
|
||||
void bch2_trans_unlock(struct btree_trans *trans)
|
||||
{
|
||||
__bch2_trans_unlock(trans);
|
||||
|
||||
trans->locked = false;
|
||||
trans->last_unlock_ip = _RET_IP_;
|
||||
trans_set_unlocked(trans);
|
||||
}
|
||||
|
||||
void bch2_trans_unlock_long(struct btree_trans *trans)
|
||||
|
@ -193,6 +193,28 @@ int bch2_six_check_for_deadlock(struct six_lock *lock, void *p);
|
||||
|
||||
/* lock: */
|
||||
|
||||
static inline void trans_set_locked(struct btree_trans *trans)
|
||||
{
|
||||
if (!trans->locked) {
|
||||
trans->locked = true;
|
||||
trans->last_unlock_ip = 0;
|
||||
|
||||
trans->pf_memalloc_nofs = (current->flags & PF_MEMALLOC_NOFS) != 0;
|
||||
current->flags |= PF_MEMALLOC_NOFS;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void trans_set_unlocked(struct btree_trans *trans)
|
||||
{
|
||||
if (trans->locked) {
|
||||
trans->locked = false;
|
||||
trans->last_unlock_ip = _RET_IP_;
|
||||
|
||||
if (!trans->pf_memalloc_nofs)
|
||||
current->flags &= ~PF_MEMALLOC_NOFS;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int __btree_node_lock_nopath(struct btree_trans *trans,
|
||||
struct btree_bkey_cached_common *b,
|
||||
enum six_lock_type type,
|
||||
|
@ -484,6 +484,7 @@ struct btree_trans {
|
||||
bool lock_may_not_fail:1;
|
||||
bool srcu_held:1;
|
||||
bool locked:1;
|
||||
bool pf_memalloc_nofs:1;
|
||||
bool write_locked:1;
|
||||
bool used_mempool:1;
|
||||
bool in_traverse_all:1;
|
||||
|
@ -805,7 +805,7 @@ int bch2_bucket_ref_update(struct btree_trans *trans, struct bch_dev *ca,
|
||||
"bucket %u:%zu gen %u (mem gen %u) data type %s: stale dirty ptr (gen %u)\n"
|
||||
"while marking %s",
|
||||
ptr->dev, bucket_nr, b_gen,
|
||||
*bucket_gen(ca, bucket_nr),
|
||||
bucket_gen_get(ca, bucket_nr),
|
||||
bch2_data_type_str(bucket_data_type ?: ptr_data_type),
|
||||
ptr->gen,
|
||||
(printbuf_reset(&buf),
|
||||
|
@ -116,6 +116,14 @@ static inline u8 *bucket_gen(struct bch_dev *ca, size_t b)
|
||||
return gens->b + b;
|
||||
}
|
||||
|
||||
static inline u8 bucket_gen_get(struct bch_dev *ca, size_t b)
|
||||
{
|
||||
rcu_read_lock();
|
||||
u8 gen = *bucket_gen(ca, b);
|
||||
rcu_read_unlock();
|
||||
return gen;
|
||||
}
|
||||
|
||||
static inline size_t PTR_BUCKET_NR(const struct bch_dev *ca,
|
||||
const struct bch_extent_ptr *ptr)
|
||||
{
|
||||
|
@ -2073,8 +2073,7 @@ int __init bch2_vfs_init(void)
|
||||
{
|
||||
int ret = -ENOMEM;
|
||||
|
||||
bch2_inode_cache = KMEM_CACHE(bch_inode_info, SLAB_RECLAIM_ACCOUNT |
|
||||
SLAB_ACCOUNT);
|
||||
bch2_inode_cache = KMEM_CACHE(bch_inode_info, SLAB_RECLAIM_ACCOUNT);
|
||||
if (!bch2_inode_cache)
|
||||
goto err;
|
||||
|
||||
|
@ -125,7 +125,7 @@ int bch2_extent_fallocate(struct btree_trans *trans,
|
||||
bch2_bkey_buf_exit(&old, c);
|
||||
|
||||
if (closure_nr_remaining(&cl) != 1) {
|
||||
bch2_trans_unlock(trans);
|
||||
bch2_trans_unlock_long(trans);
|
||||
closure_sync(&cl);
|
||||
}
|
||||
|
||||
|
@ -252,8 +252,10 @@ void bch2_prt_u64_base2(struct printbuf *out, u64 v)
|
||||
bch2_prt_u64_base2_nbits(out, v, fls64(v) ?: 1);
|
||||
}
|
||||
|
||||
void bch2_print_string_as_lines(const char *prefix, const char *lines)
|
||||
static void __bch2_print_string_as_lines(const char *prefix, const char *lines,
|
||||
bool nonblocking)
|
||||
{
|
||||
bool locked = false;
|
||||
const char *p;
|
||||
|
||||
if (!lines) {
|
||||
@ -261,7 +263,13 @@ void bch2_print_string_as_lines(const char *prefix, const char *lines)
|
||||
return;
|
||||
}
|
||||
|
||||
console_lock();
|
||||
if (!nonblocking) {
|
||||
console_lock();
|
||||
locked = true;
|
||||
} else {
|
||||
locked = console_trylock();
|
||||
}
|
||||
|
||||
while (1) {
|
||||
p = strchrnul(lines, '\n');
|
||||
printk("%s%.*s\n", prefix, (int) (p - lines), lines);
|
||||
@ -269,7 +277,18 @@ void bch2_print_string_as_lines(const char *prefix, const char *lines)
|
||||
break;
|
||||
lines = p + 1;
|
||||
}
|
||||
console_unlock();
|
||||
if (locked)
|
||||
console_unlock();
|
||||
}
|
||||
|
||||
void bch2_print_string_as_lines(const char *prefix, const char *lines)
|
||||
{
|
||||
return __bch2_print_string_as_lines(prefix, lines, false);
|
||||
}
|
||||
|
||||
void bch2_print_string_as_lines_nonblocking(const char *prefix, const char *lines)
|
||||
{
|
||||
return __bch2_print_string_as_lines(prefix, lines, true);
|
||||
}
|
||||
|
||||
int bch2_save_backtrace(bch_stacktrace *stack, struct task_struct *task, unsigned skipnr,
|
||||
|
@ -315,6 +315,7 @@ void bch2_prt_u64_base2_nbits(struct printbuf *, u64, unsigned);
|
||||
void bch2_prt_u64_base2(struct printbuf *, u64);
|
||||
|
||||
void bch2_print_string_as_lines(const char *prefix, const char *lines);
|
||||
void bch2_print_string_as_lines_nonblocking(const char *prefix, const char *lines);
|
||||
|
||||
typedef DARRAY(unsigned long) bch_stacktrace;
|
||||
int bch2_save_backtrace(bch_stacktrace *stack, struct task_struct *, unsigned, gfp_t);
|
||||
|
@ -2856,6 +2856,8 @@ static int init_mount_fs_info(struct btrfs_fs_info *fs_info, struct super_block
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
spin_lock_init(&fs_info->extent_map_shrinker_lock);
|
||||
|
||||
ret = percpu_counter_init(&fs_info->dirty_metadata_bytes, 0, GFP_KERNEL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -1028,7 +1028,14 @@ int split_extent_map(struct btrfs_inode *inode, u64 start, u64 len, u64 pre,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long btrfs_scan_inode(struct btrfs_inode *inode, long *scanned, long nr_to_scan)
|
||||
struct btrfs_em_shrink_ctx {
|
||||
long nr_to_scan;
|
||||
long scanned;
|
||||
u64 last_ino;
|
||||
u64 last_root;
|
||||
};
|
||||
|
||||
static long btrfs_scan_inode(struct btrfs_inode *inode, struct btrfs_em_shrink_ctx *ctx)
|
||||
{
|
||||
const u64 cur_fs_gen = btrfs_get_fs_generation(inode->root->fs_info);
|
||||
struct extent_map_tree *tree = &inode->extent_tree;
|
||||
@ -1057,14 +1064,25 @@ static long btrfs_scan_inode(struct btrfs_inode *inode, long *scanned, long nr_t
|
||||
if (!down_read_trylock(&inode->i_mmap_lock))
|
||||
return 0;
|
||||
|
||||
write_lock(&tree->lock);
|
||||
/*
|
||||
* We want to be fast because we can be called from any path trying to
|
||||
* allocate memory, so if the lock is busy we don't want to spend time
|
||||
* waiting for it - either some task is about to do IO for the inode or
|
||||
* we may have another task shrinking extent maps, here in this code, so
|
||||
* skip this inode.
|
||||
*/
|
||||
if (!write_trylock(&tree->lock)) {
|
||||
up_read(&inode->i_mmap_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
node = rb_first_cached(&tree->map);
|
||||
while (node) {
|
||||
struct extent_map *em;
|
||||
|
||||
em = rb_entry(node, struct extent_map, rb_node);
|
||||
node = rb_next(node);
|
||||
(*scanned)++;
|
||||
ctx->scanned++;
|
||||
|
||||
if (em->flags & EXTENT_FLAG_PINNED)
|
||||
goto next;
|
||||
@ -1085,16 +1103,18 @@ static long btrfs_scan_inode(struct btrfs_inode *inode, long *scanned, long nr_t
|
||||
free_extent_map(em);
|
||||
nr_dropped++;
|
||||
next:
|
||||
if (*scanned >= nr_to_scan)
|
||||
if (ctx->scanned >= ctx->nr_to_scan)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Restart if we had to reschedule, and any extent maps that were
|
||||
* pinned before may have become unpinned after we released the
|
||||
* lock and took it again.
|
||||
* Stop if we need to reschedule or there's contention on the
|
||||
* lock. This is to avoid slowing other tasks trying to take the
|
||||
* lock and because the shrinker might be called during a memory
|
||||
* allocation path and we want to avoid taking a very long time
|
||||
* and slowing down all sorts of tasks.
|
||||
*/
|
||||
if (cond_resched_rwlock_write(&tree->lock))
|
||||
node = rb_first_cached(&tree->map);
|
||||
if (need_resched() || rwlock_needbreak(&tree->lock))
|
||||
break;
|
||||
}
|
||||
write_unlock(&tree->lock);
|
||||
up_read(&inode->i_mmap_lock);
|
||||
@ -1102,25 +1122,30 @@ static long btrfs_scan_inode(struct btrfs_inode *inode, long *scanned, long nr_t
|
||||
return nr_dropped;
|
||||
}
|
||||
|
||||
static long btrfs_scan_root(struct btrfs_root *root, long *scanned, long nr_to_scan)
|
||||
static long btrfs_scan_root(struct btrfs_root *root, struct btrfs_em_shrink_ctx *ctx)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = root->fs_info;
|
||||
struct btrfs_inode *inode;
|
||||
long nr_dropped = 0;
|
||||
u64 min_ino = fs_info->extent_map_shrinker_last_ino + 1;
|
||||
u64 min_ino = ctx->last_ino + 1;
|
||||
|
||||
inode = btrfs_find_first_inode(root, min_ino);
|
||||
while (inode) {
|
||||
nr_dropped += btrfs_scan_inode(inode, scanned, nr_to_scan);
|
||||
nr_dropped += btrfs_scan_inode(inode, ctx);
|
||||
|
||||
min_ino = btrfs_ino(inode) + 1;
|
||||
fs_info->extent_map_shrinker_last_ino = btrfs_ino(inode);
|
||||
iput(&inode->vfs_inode);
|
||||
ctx->last_ino = btrfs_ino(inode);
|
||||
btrfs_add_delayed_iput(inode);
|
||||
|
||||
if (*scanned >= nr_to_scan)
|
||||
if (ctx->scanned >= ctx->nr_to_scan)
|
||||
break;
|
||||
|
||||
/*
|
||||
* We may be called from memory allocation paths, so we don't
|
||||
* want to take too much time and slowdown tasks.
|
||||
*/
|
||||
if (need_resched())
|
||||
break;
|
||||
|
||||
cond_resched();
|
||||
inode = btrfs_find_first_inode(root, min_ino);
|
||||
}
|
||||
|
||||
@ -1132,14 +1157,14 @@ static long btrfs_scan_root(struct btrfs_root *root, long *scanned, long nr_to_s
|
||||
* inode if there is one or we will find out this was the last
|
||||
* one and move to the next root.
|
||||
*/
|
||||
fs_info->extent_map_shrinker_last_root = btrfs_root_id(root);
|
||||
ctx->last_root = btrfs_root_id(root);
|
||||
} else {
|
||||
/*
|
||||
* No more inodes in this root, set extent_map_shrinker_last_ino to 0 so
|
||||
* that when processing the next root we start from its first inode.
|
||||
*/
|
||||
fs_info->extent_map_shrinker_last_ino = 0;
|
||||
fs_info->extent_map_shrinker_last_root = btrfs_root_id(root) + 1;
|
||||
ctx->last_ino = 0;
|
||||
ctx->last_root = btrfs_root_id(root) + 1;
|
||||
}
|
||||
|
||||
return nr_dropped;
|
||||
@ -1147,19 +1172,41 @@ static long btrfs_scan_root(struct btrfs_root *root, long *scanned, long nr_to_s
|
||||
|
||||
long btrfs_free_extent_maps(struct btrfs_fs_info *fs_info, long nr_to_scan)
|
||||
{
|
||||
const u64 start_root_id = fs_info->extent_map_shrinker_last_root;
|
||||
u64 next_root_id = start_root_id;
|
||||
struct btrfs_em_shrink_ctx ctx;
|
||||
u64 start_root_id;
|
||||
u64 next_root_id;
|
||||
bool cycled = false;
|
||||
long nr_dropped = 0;
|
||||
long scanned = 0;
|
||||
|
||||
ctx.scanned = 0;
|
||||
ctx.nr_to_scan = nr_to_scan;
|
||||
|
||||
/*
|
||||
* In case we have multiple tasks running this shrinker, make the next
|
||||
* one start from the next inode in case it starts before we finish.
|
||||
*/
|
||||
spin_lock(&fs_info->extent_map_shrinker_lock);
|
||||
ctx.last_ino = fs_info->extent_map_shrinker_last_ino;
|
||||
fs_info->extent_map_shrinker_last_ino++;
|
||||
ctx.last_root = fs_info->extent_map_shrinker_last_root;
|
||||
spin_unlock(&fs_info->extent_map_shrinker_lock);
|
||||
|
||||
start_root_id = ctx.last_root;
|
||||
next_root_id = ctx.last_root;
|
||||
|
||||
if (trace_btrfs_extent_map_shrinker_scan_enter_enabled()) {
|
||||
s64 nr = percpu_counter_sum_positive(&fs_info->evictable_extent_maps);
|
||||
|
||||
trace_btrfs_extent_map_shrinker_scan_enter(fs_info, nr_to_scan, nr);
|
||||
trace_btrfs_extent_map_shrinker_scan_enter(fs_info, nr_to_scan,
|
||||
nr, ctx.last_root,
|
||||
ctx.last_ino);
|
||||
}
|
||||
|
||||
while (scanned < nr_to_scan) {
|
||||
/*
|
||||
* We may be called from memory allocation paths, so we don't want to
|
||||
* take too much time and slowdown tasks, so stop if we need reschedule.
|
||||
*/
|
||||
while (ctx.scanned < ctx.nr_to_scan && !need_resched()) {
|
||||
struct btrfs_root *root;
|
||||
unsigned long count;
|
||||
|
||||
@ -1171,8 +1218,8 @@ long btrfs_free_extent_maps(struct btrfs_fs_info *fs_info, long nr_to_scan)
|
||||
spin_unlock(&fs_info->fs_roots_radix_lock);
|
||||
if (start_root_id > 0 && !cycled) {
|
||||
next_root_id = 0;
|
||||
fs_info->extent_map_shrinker_last_root = 0;
|
||||
fs_info->extent_map_shrinker_last_ino = 0;
|
||||
ctx.last_root = 0;
|
||||
ctx.last_ino = 0;
|
||||
cycled = true;
|
||||
continue;
|
||||
}
|
||||
@ -1186,15 +1233,33 @@ long btrfs_free_extent_maps(struct btrfs_fs_info *fs_info, long nr_to_scan)
|
||||
continue;
|
||||
|
||||
if (is_fstree(btrfs_root_id(root)))
|
||||
nr_dropped += btrfs_scan_root(root, &scanned, nr_to_scan);
|
||||
nr_dropped += btrfs_scan_root(root, &ctx);
|
||||
|
||||
btrfs_put_root(root);
|
||||
}
|
||||
|
||||
/*
|
||||
* In case of multiple tasks running this extent map shrinking code this
|
||||
* isn't perfect but it's simple and silences things like KCSAN. It's
|
||||
* not possible to know which task made more progress because we can
|
||||
* cycle back to the first root and first inode if it's not the first
|
||||
* time the shrinker ran, see the above logic. Also a task that started
|
||||
* later may finish ealier than another task and made less progress. So
|
||||
* make this simple and update to the progress of the last task that
|
||||
* finished, with the occasional possiblity of having two consecutive
|
||||
* runs of the shrinker process the same inodes.
|
||||
*/
|
||||
spin_lock(&fs_info->extent_map_shrinker_lock);
|
||||
fs_info->extent_map_shrinker_last_ino = ctx.last_ino;
|
||||
fs_info->extent_map_shrinker_last_root = ctx.last_root;
|
||||
spin_unlock(&fs_info->extent_map_shrinker_lock);
|
||||
|
||||
if (trace_btrfs_extent_map_shrinker_scan_exit_enabled()) {
|
||||
s64 nr = percpu_counter_sum_positive(&fs_info->evictable_extent_maps);
|
||||
|
||||
trace_btrfs_extent_map_shrinker_scan_exit(fs_info, nr_dropped, nr);
|
||||
trace_btrfs_extent_map_shrinker_scan_exit(fs_info, nr_dropped,
|
||||
nr, ctx.last_root,
|
||||
ctx.last_ino);
|
||||
}
|
||||
|
||||
return nr_dropped;
|
||||
|
@ -630,6 +630,7 @@ struct btrfs_fs_info {
|
||||
s32 delalloc_batch;
|
||||
|
||||
struct percpu_counter evictable_extent_maps;
|
||||
spinlock_t extent_map_shrinker_lock;
|
||||
u64 extent_map_shrinker_last_root;
|
||||
u64 extent_map_shrinker_last_ino;
|
||||
|
||||
|
@ -533,6 +533,9 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch
|
||||
* @queue_empty: signal green light for opportunistically skipping the queue
|
||||
* for spi_sync transfers.
|
||||
* @must_async: disable all fast paths in the core
|
||||
* @defer_optimize_message: set to true if controller cannot pre-optimize messages
|
||||
* and needs to defer the optimization step until the message is actually
|
||||
* being transferred
|
||||
*
|
||||
* Each SPI controller can communicate with one or more @spi_device
|
||||
* children. These make a small bus, sharing MOSI, MISO and SCK signals
|
||||
@ -776,6 +779,7 @@ struct spi_controller {
|
||||
/* Flag for enabling opportunistic skipping of the queue in spi_sync */
|
||||
bool queue_empty;
|
||||
bool must_async;
|
||||
bool defer_optimize_message;
|
||||
};
|
||||
|
||||
static inline void *spi_controller_get_devdata(struct spi_controller *ctlr)
|
||||
|
@ -2556,9 +2556,10 @@ TRACE_EVENT(btrfs_extent_map_shrinker_count,
|
||||
|
||||
TRACE_EVENT(btrfs_extent_map_shrinker_scan_enter,
|
||||
|
||||
TP_PROTO(const struct btrfs_fs_info *fs_info, long nr_to_scan, long nr),
|
||||
TP_PROTO(const struct btrfs_fs_info *fs_info, long nr_to_scan, long nr,
|
||||
u64 last_root_id, u64 last_ino),
|
||||
|
||||
TP_ARGS(fs_info, nr_to_scan, nr),
|
||||
TP_ARGS(fs_info, nr_to_scan, nr, last_root_id, last_ino),
|
||||
|
||||
TP_STRUCT__entry_btrfs(
|
||||
__field( long, nr_to_scan )
|
||||
@ -2570,8 +2571,8 @@ TRACE_EVENT(btrfs_extent_map_shrinker_scan_enter,
|
||||
TP_fast_assign_btrfs(fs_info,
|
||||
__entry->nr_to_scan = nr_to_scan;
|
||||
__entry->nr = nr;
|
||||
__entry->last_root_id = fs_info->extent_map_shrinker_last_root;
|
||||
__entry->last_ino = fs_info->extent_map_shrinker_last_ino;
|
||||
__entry->last_root_id = last_root_id;
|
||||
__entry->last_ino = last_ino;
|
||||
),
|
||||
|
||||
TP_printk_btrfs("nr_to_scan=%ld nr=%ld last_root=%llu(%s) last_ino=%llu",
|
||||
@ -2581,9 +2582,10 @@ TRACE_EVENT(btrfs_extent_map_shrinker_scan_enter,
|
||||
|
||||
TRACE_EVENT(btrfs_extent_map_shrinker_scan_exit,
|
||||
|
||||
TP_PROTO(const struct btrfs_fs_info *fs_info, long nr_dropped, long nr),
|
||||
TP_PROTO(const struct btrfs_fs_info *fs_info, long nr_dropped, long nr,
|
||||
u64 last_root_id, u64 last_ino),
|
||||
|
||||
TP_ARGS(fs_info, nr_dropped, nr),
|
||||
TP_ARGS(fs_info, nr_dropped, nr, last_root_id, last_ino),
|
||||
|
||||
TP_STRUCT__entry_btrfs(
|
||||
__field( long, nr_dropped )
|
||||
@ -2595,8 +2597,8 @@ TRACE_EVENT(btrfs_extent_map_shrinker_scan_exit,
|
||||
TP_fast_assign_btrfs(fs_info,
|
||||
__entry->nr_dropped = nr_dropped;
|
||||
__entry->nr = nr;
|
||||
__entry->last_root_id = fs_info->extent_map_shrinker_last_root;
|
||||
__entry->last_ino = fs_info->extent_map_shrinker_last_ino;
|
||||
__entry->last_root_id = last_root_id;
|
||||
__entry->last_ino = last_ino;
|
||||
),
|
||||
|
||||
TP_printk_btrfs("nr_dropped=%ld nr=%ld last_root=%llu(%s) last_ino=%llu",
|
||||
|
@ -8,11 +8,14 @@
|
||||
#define FASTRPC_IOCTL_ALLOC_DMA_BUFF _IOWR('R', 1, struct fastrpc_alloc_dma_buf)
|
||||
#define FASTRPC_IOCTL_FREE_DMA_BUFF _IOWR('R', 2, __u32)
|
||||
#define FASTRPC_IOCTL_INVOKE _IOWR('R', 3, struct fastrpc_invoke)
|
||||
/* This ioctl is only supported with secure device nodes */
|
||||
#define FASTRPC_IOCTL_INIT_ATTACH _IO('R', 4)
|
||||
#define FASTRPC_IOCTL_INIT_CREATE _IOWR('R', 5, struct fastrpc_init_create)
|
||||
#define FASTRPC_IOCTL_MMAP _IOWR('R', 6, struct fastrpc_req_mmap)
|
||||
#define FASTRPC_IOCTL_MUNMAP _IOWR('R', 7, struct fastrpc_req_munmap)
|
||||
/* This ioctl is only supported with secure device nodes */
|
||||
#define FASTRPC_IOCTL_INIT_ATTACH_SNS _IO('R', 8)
|
||||
/* This ioctl is only supported with secure device nodes */
|
||||
#define FASTRPC_IOCTL_INIT_CREATE_STATIC _IOWR('R', 9, struct fastrpc_init_create_static)
|
||||
#define FASTRPC_IOCTL_MEM_MAP _IOWR('R', 10, struct fastrpc_mem_map)
|
||||
#define FASTRPC_IOCTL_MEM_UNMAP _IOWR('R', 11, struct fastrpc_mem_unmap)
|
||||
|
@ -429,7 +429,10 @@ static int is_out(const struct crush_map *map,
|
||||
/**
|
||||
* crush_choose_firstn - choose numrep distinct items of given type
|
||||
* @map: the crush_map
|
||||
* @work: working space initialized by crush_init_workspace()
|
||||
* @bucket: the bucket we are choose an item from
|
||||
* @weight: weight vector (for map leaves)
|
||||
* @weight_max: size of weight vector
|
||||
* @x: crush input value
|
||||
* @numrep: the number of items to choose
|
||||
* @type: the type of item to choose
|
||||
@ -445,6 +448,7 @@ static int is_out(const struct crush_map *map,
|
||||
* @vary_r: pass r to recursive calls
|
||||
* @out2: second output vector for leaf items (if @recurse_to_leaf)
|
||||
* @parent_r: r value passed from the parent
|
||||
* @choose_args: weights and ids for each known bucket
|
||||
*/
|
||||
static int crush_choose_firstn(const struct crush_map *map,
|
||||
struct crush_work *work,
|
||||
@ -636,9 +640,8 @@ static int crush_choose_firstn(const struct crush_map *map,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
/*
|
||||
* crush_choose_indep: alternative breadth-first positionally stable mapping
|
||||
*
|
||||
*/
|
||||
static void crush_choose_indep(const struct crush_map *map,
|
||||
struct crush_work *work,
|
||||
|
@ -1085,13 +1085,19 @@ static void delayed_work(struct work_struct *work)
|
||||
struct ceph_mon_client *monc =
|
||||
container_of(work, struct ceph_mon_client, delayed_work.work);
|
||||
|
||||
dout("monc delayed_work\n");
|
||||
mutex_lock(&monc->mutex);
|
||||
dout("%s mon%d\n", __func__, monc->cur_mon);
|
||||
if (monc->cur_mon < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (monc->hunting) {
|
||||
dout("%s continuing hunt\n", __func__);
|
||||
reopen_session(monc);
|
||||
} else {
|
||||
int is_auth = ceph_auth_is_authenticated(monc->auth);
|
||||
|
||||
dout("%s is_authed %d\n", __func__, is_auth);
|
||||
if (ceph_con_keepalive_expired(&monc->con,
|
||||
CEPH_MONC_PING_TIMEOUT)) {
|
||||
dout("monc keepalive timeout\n");
|
||||
@ -1116,6 +1122,8 @@ static void delayed_work(struct work_struct *work)
|
||||
}
|
||||
}
|
||||
__schedule_delayed(monc);
|
||||
|
||||
out:
|
||||
mutex_unlock(&monc->mutex);
|
||||
}
|
||||
|
||||
@ -1232,13 +1240,15 @@ EXPORT_SYMBOL(ceph_monc_init);
|
||||
void ceph_monc_stop(struct ceph_mon_client *monc)
|
||||
{
|
||||
dout("stop\n");
|
||||
cancel_delayed_work_sync(&monc->delayed_work);
|
||||
|
||||
mutex_lock(&monc->mutex);
|
||||
__close_session(monc);
|
||||
monc->hunting = false;
|
||||
monc->cur_mon = -1;
|
||||
mutex_unlock(&monc->mutex);
|
||||
|
||||
cancel_delayed_work_sync(&monc->delayed_work);
|
||||
|
||||
/*
|
||||
* flush msgr queue before we destroy ourselves to ensure that:
|
||||
* - any work that references our embedded con is finished.
|
||||
|
@ -1362,7 +1362,8 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
|
||||
if (rxfh.input_xfrm && rxfh.input_xfrm != RXH_XFRM_SYM_XOR &&
|
||||
rxfh.input_xfrm != RXH_XFRM_NO_CHANGE)
|
||||
return -EINVAL;
|
||||
if ((rxfh.input_xfrm & RXH_XFRM_SYM_XOR) &&
|
||||
if (rxfh.input_xfrm != RXH_XFRM_NO_CHANGE &&
|
||||
(rxfh.input_xfrm & RXH_XFRM_SYM_XOR) &&
|
||||
!ops->cap_rss_sym_xor_supported)
|
||||
return -EOPNOTSUPP;
|
||||
create = rxfh.rss_context == ETH_RXFH_CONTEXT_ALLOC;
|
||||
|
@ -128,8 +128,8 @@ static const struct cs35l41_config cs35l41_config_table[] = {
|
||||
{ "17AA38B5", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
|
||||
{ "17AA38B6", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
|
||||
{ "17AA38B7", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
|
||||
{ "17AA38C7", 4, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, CS35L41_LEFT, CS35L41_RIGHT }, 0, 2, -1, 1000, 4500, 24 },
|
||||
{ "17AA38C8", 4, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, CS35L41_LEFT, CS35L41_RIGHT }, 0, 2, -1, 1000, 4500, 24 },
|
||||
{ "17AA38C7", 4, INTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, CS35L41_RIGHT, CS35L41_LEFT }, 0, 2, -1, 1000, 4500, 24 },
|
||||
{ "17AA38C8", 4, INTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, CS35L41_RIGHT, CS35L41_LEFT }, 0, 2, -1, 1000, 4500, 24 },
|
||||
{ "17AA38F9", 2, EXTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, 0, 0 }, 0, 2, -1, 0, 0, 0 },
|
||||
{ "17AA38FA", 2, EXTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, 0, 0 }, 0, 2, -1, 0, 0, 0 },
|
||||
{}
|
||||
|
@ -10053,6 +10053,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x103c, 0x83b9, "HP Spectre x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
|
||||
SND_PCI_QUIRK(0x103c, 0x841c, "HP Pavilion 15-CK0xx", ALC269_FIXUP_HP_MUTE_LED_MIC3),
|
||||
SND_PCI_QUIRK(0x103c, 0x8497, "HP Envy x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
|
||||
SND_PCI_QUIRK(0x103c, 0x84a6, "HP 250 G7 Notebook PC", ALC269_FIXUP_HP_LINE1_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x84ae, "HP 15-db0403ng", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
|
||||
SND_PCI_QUIRK(0x103c, 0x84da, "HP OMEN dc0019-ur", ALC295_FIXUP_HP_OMEN),
|
||||
SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
|
||||
@ -10383,6 +10384,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC),
|
||||
SND_PCI_QUIRK(0x10ec, 0x10f2, "Intel Reference board", ALC700_FIXUP_INTEL_REFERENCE),
|
||||
SND_PCI_QUIRK(0x10ec, 0x118c, "Medion EE4254 MD62100", ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x10ec, 0x11bc, "VAIO VJFE-IL", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x10ec, 0x1230, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
|
||||
SND_PCI_QUIRK(0x10ec, 0x124c, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
|
||||
SND_PCI_QUIRK(0x10ec, 0x1252, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
|
||||
@ -10480,6 +10482,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1558, 0xa600, "Clevo NL50NU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1558, 0xa650, "Clevo NP[567]0SN[CD]", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1558, 0xa671, "Clevo NP70SN[CDE]", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1558, 0xa763, "Clevo V54x_6x_TU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1558, 0xb018, "Clevo NP50D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1558, 0xb019, "Clevo NH77D[BE]Q", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1558, 0xb022, "Clevo NH77D[DC][QW]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
|
||||
@ -10655,6 +10658,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1d72, 0x1945, "Redmi G", ALC256_FIXUP_ASUS_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1d72, 0x1947, "RedmiBook Air", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x2782, 0x0214, "VAIO VJFE-CL", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x2782, 0x0232, "CHUWI CoreBook XPro", ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO),
|
||||
SND_PCI_QUIRK(0x2782, 0x1707, "Vaio VJFE-ADL", ALC298_FIXUP_SPK_VOLUME),
|
||||
SND_PCI_QUIRK(0x8086, 0x2074, "Intel NUC 8", ALC233_FIXUP_INTEL_NUC8_DMIC),
|
||||
|
@ -38,7 +38,9 @@ static bool rt711_readable_register(struct device *dev, unsigned int reg)
|
||||
case 0x8300 ... 0x83ff:
|
||||
case 0x9c00 ... 0x9cff:
|
||||
case 0xb900 ... 0xb9ff:
|
||||
case 0x752008:
|
||||
case 0x752009:
|
||||
case 0x75200b:
|
||||
case 0x752011:
|
||||
case 0x75201a:
|
||||
case 0x752045:
|
||||
|
@ -617,12 +617,6 @@ static int hda_dai_suspend(struct hdac_bus *bus)
|
||||
sdai = swidget->private;
|
||||
ops = sdai->platform_private;
|
||||
|
||||
ret = hda_link_dma_cleanup(hext_stream->link_substream,
|
||||
hext_stream,
|
||||
cpu_dai);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* for consistency with TRIGGER_SUSPEND */
|
||||
if (ops->post_trigger) {
|
||||
ret = ops->post_trigger(sdev, cpu_dai,
|
||||
@ -631,6 +625,12 @@ static int hda_dai_suspend(struct hdac_bus *bus)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = hda_link_dma_cleanup(hext_stream->link_substream,
|
||||
hext_stream,
|
||||
cpu_dai);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -258,6 +258,12 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
|
||||
snd_pcm_hw_constraint_integer(substream->runtime,
|
||||
SNDRV_PCM_HW_PARAM_PERIODS);
|
||||
|
||||
/* Limit the maximum number of periods to not exceed the BDL entries count */
|
||||
if (runtime->hw.periods_max > HDA_DSP_MAX_BDL_ENTRIES)
|
||||
snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIODS,
|
||||
runtime->hw.periods_min,
|
||||
HDA_DSP_MAX_BDL_ENTRIES);
|
||||
|
||||
/* Only S16 and S32 supported by HDA hardware when used without DSP */
|
||||
if (sdev->dspless_mode_selected)
|
||||
snd_pcm_hw_constraint_mask64(substream->runtime, SNDRV_PCM_HW_PARAM_FORMAT,
|
||||
|
Loading…
Reference in New Issue
Block a user