Merge remote-tracking branch 'sm8250/lineage-20' into lineage-21
* sm8250/lineage-20: msm/sde: prevent double register of input handler scsi: ufs: Use WQ_HIGHPRI for gating work. scsi: ufs: disable clock scaling scsi: ufs: atomic update for clkgating_enable scsi: ufs: call single_release to avoid memory leak scsi: ufs: Disable interrupt in reset path cpuidle: Do not select menu and ladder governors msm: ipa3: Changes to fix memory leak issue msm: ipa: avoid OOM Killer for temp allocations msm: ipa: use lower order pages UPSTREAM: HID: playstation: support updated DualSense rumble mode. UPSTREAM: HID: playstation: add initial DualSense Edge controller support UPSTREAM: HID: playstation: add DualSense player LED support. UPSTREAM: HID: playstation: add microphone mute support for DualSense. UPSTREAM: HID: playstation: add initial DualSense lightbar support. UPSTREAM: HID: playstation: fix array size comparison (off-by-one) UPSTREAM: HID: playstation: fix unused variable in ps_battery_get_property. BACKPORT: HID: playstation: report DualSense hardware and firmware version. BACKPORT: HID: playstation: add DualSense classic rumble support. UPSTREAM: HID: playstation: add DualSense Bluetooth support. ... Change-Id: I8299aa7e799947d78ec126259d58aa956f49ca72
This commit is contained in:
159 files changed
+2254
-1230
No files matched your search
@@ -94,7 +94,6 @@ class KernelInclude(Include):
|
|||||||
# HINT: this is the only line I had to change / commented out:
|
# HINT: this is the only line I had to change / commented out:
|
||||||
#path = utils.relative_path(None, path)
|
#path = utils.relative_path(None, path)
|
||||||
|
|
||||||
path = nodes.reprunicode(path)
|
|
||||||
encoding = self.options.get(
|
encoding = self.options.get(
|
||||||
'encoding', self.state.document.settings.input_encoding)
|
'encoding', self.state.document.settings.input_encoding)
|
||||||
e_handler=self.state.document.settings.input_encoding_error_handler
|
e_handler=self.state.document.settings.input_encoding_error_handler
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
VERSION = 4
|
VERSION = 4
|
||||||
PATCHLEVEL = 19
|
PATCHLEVEL = 19
|
||||||
SUBLEVEL = 312
|
SUBLEVEL = 315
|
||||||
EXTRAVERSION =
|
EXTRAVERSION =
|
||||||
NAME = "People's Front"
|
NAME = "People's Front"
|
||||||
|
|
||||||
|
|||||||
@@ -964,7 +964,7 @@ put_tv32(struct timeval32 __user *o, struct timespec64 *i)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline long
|
static inline long
|
||||||
put_tv_to_tv32(struct timeval32 __user *o, struct __kernel_old_timeval *i)
|
put_tv_to_tv32(struct timeval32 __user *o, struct timeval *i)
|
||||||
{
|
{
|
||||||
return copy_to_user(o, &(struct timeval32){
|
return copy_to_user(o, &(struct timeval32){
|
||||||
.tv_sec = i->tv_sec,
|
.tv_sec = i->tv_sec,
|
||||||
|
|||||||
@@ -170,7 +170,6 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
gmac: ethernet@8000 {
|
gmac: ethernet@8000 {
|
||||||
#interrupt-cells = <1>;
|
|
||||||
compatible = "snps,dwmac";
|
compatible = "snps,dwmac";
|
||||||
reg = <0x8000 0x2000>;
|
reg = <0x8000 0x2000>;
|
||||||
interrupts = <10>;
|
interrupts = <10>;
|
||||||
|
|||||||
@@ -232,7 +232,7 @@
|
|||||||
clock-names = "hif_sel";
|
clock-names = "hif_sel";
|
||||||
};
|
};
|
||||||
|
|
||||||
cir: cir@10009000 {
|
cir: ir-receiver@10009000 {
|
||||||
compatible = "mediatek,mt7622-cir";
|
compatible = "mediatek,mt7622-cir";
|
||||||
reg = <0 0x10009000 0 0x1000>;
|
reg = <0 0x10009000 0 0x1000>;
|
||||||
interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_LOW>;
|
interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_LOW>;
|
||||||
@@ -459,7 +459,6 @@
|
|||||||
<&pericfg CLK_PERI_AUXADC_PD>;
|
<&pericfg CLK_PERI_AUXADC_PD>;
|
||||||
clock-names = "therm", "auxadc";
|
clock-names = "therm", "auxadc";
|
||||||
resets = <&pericfg MT7622_PERI_THERM_SW_RST>;
|
resets = <&pericfg MT7622_PERI_THERM_SW_RST>;
|
||||||
reset-names = "therm";
|
|
||||||
mediatek,auxadc = <&auxadc>;
|
mediatek,auxadc = <&auxadc>;
|
||||||
mediatek,apmixedsys = <&apmixedsys>;
|
mediatek,apmixedsys = <&apmixedsys>;
|
||||||
nvmem-cells = <&thermal_calibration>;
|
nvmem-cells = <&thermal_calibration>;
|
||||||
@@ -846,9 +845,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
eth: ethernet@1b100000 {
|
eth: ethernet@1b100000 {
|
||||||
compatible = "mediatek,mt7622-eth",
|
compatible = "mediatek,mt7622-eth";
|
||||||
"mediatek,mt2701-eth",
|
|
||||||
"syscon";
|
|
||||||
reg = <0 0x1b100000 0 0x20000>;
|
reg = <0 0x1b100000 0 0x20000>;
|
||||||
interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_LOW>,
|
interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_LOW>,
|
||||||
<GIC_SPI 224 IRQ_TYPE_LEVEL_LOW>,
|
<GIC_SPI 224 IRQ_TYPE_LEVEL_LOW>,
|
||||||
|
|||||||
@@ -426,16 +426,22 @@
|
|||||||
gpio1830-supply = <&vcc_1v8>;
|
gpio1830-supply = <&vcc_1v8>;
|
||||||
};
|
};
|
||||||
|
|
||||||
&pmu_io_domains {
|
&pcie_clkreqn_cpm {
|
||||||
status = "okay";
|
rockchip,pins =
|
||||||
pmu1830-supply = <&vcc_1v8>;
|
<2 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up>;
|
||||||
};
|
|
||||||
|
|
||||||
&pwm2 {
|
|
||||||
status = "okay";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
&pinctrl {
|
&pinctrl {
|
||||||
|
pinctrl-names = "default";
|
||||||
|
pinctrl-0 = <&q7_thermal_pin>;
|
||||||
|
|
||||||
|
gpios {
|
||||||
|
q7_thermal_pin: q7-thermal-pin {
|
||||||
|
rockchip,pins =
|
||||||
|
<0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
i2c8 {
|
i2c8 {
|
||||||
i2c8_xfer_a: i2c8-xfer {
|
i2c8_xfer_a: i2c8-xfer {
|
||||||
rockchip,pins =
|
rockchip,pins =
|
||||||
@@ -466,6 +472,15 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&pmu_io_domains {
|
||||||
|
status = "okay";
|
||||||
|
pmu1830-supply = <&vcc_1v8>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&pwm2 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
&sdhci {
|
&sdhci {
|
||||||
/*
|
/*
|
||||||
* Signal integrity isn't great at 200MHz but 100MHz has proven stable
|
* Signal integrity isn't great at 200MHz but 100MHz has proven stable
|
||||||
|
|||||||
+1
-1
@@ -2583,7 +2583,7 @@ static int __s390_enable_skey_hugetlb(pte_t *pte, unsigned long addr,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
start = pmd_val(*pmd) & HPAGE_MASK;
|
start = pmd_val(*pmd) & HPAGE_MASK;
|
||||||
end = start + HPAGE_SIZE - 1;
|
end = start + HPAGE_SIZE;
|
||||||
__storage_key_init_range(start, end);
|
__storage_key_init_range(start, end);
|
||||||
set_bit(PG_arch_1, &page->flags);
|
set_bit(PG_arch_1, &page->flags);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ static void clear_huge_pte_skeys(struct mm_struct *mm, unsigned long rste)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!test_and_set_bit(PG_arch_1, &page->flags))
|
if (!test_and_set_bit(PG_arch_1, &page->flags))
|
||||||
__storage_key_init_range(paddr, paddr + size - 1);
|
__storage_key_init_range(paddr, paddr + size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <asm/mpspec.h>
|
#include <asm/mpspec.h>
|
||||||
#include <asm/msr.h>
|
#include <asm/msr.h>
|
||||||
#include <asm/hardirq.h>
|
#include <asm/hardirq.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
|
||||||
#define ARCH_APICTIMER_STOPS_ON_C3 1
|
#define ARCH_APICTIMER_STOPS_ON_C3 1
|
||||||
|
|
||||||
@@ -110,7 +111,7 @@ static inline void native_apic_mem_write(u32 reg, u32 v)
|
|||||||
|
|
||||||
static inline u32 native_apic_mem_read(u32 reg)
|
static inline u32 native_apic_mem_read(u32 reg)
|
||||||
{
|
{
|
||||||
return *((volatile u32 *)(APIC_BASE + reg));
|
return readl((void __iomem *)(APIC_BASE + reg));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void native_apic_wait_icr_idle(void);
|
extern void native_apic_wait_icr_idle(void);
|
||||||
|
|||||||
@@ -236,7 +236,6 @@ static struct crypto_larval *__crypto_register_alg(struct crypto_alg *alg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(q->cra_driver_name, alg->cra_name) ||
|
if (!strcmp(q->cra_driver_name, alg->cra_name) ||
|
||||||
!strcmp(q->cra_driver_name, alg->cra_driver_name) ||
|
|
||||||
!strcmp(q->cra_name, alg->cra_driver_name))
|
!strcmp(q->cra_name, alg->cra_driver_name))
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,7 +200,10 @@ int gemini_sata_start_bridge(struct sata_gemini *sg, unsigned int bridge)
|
|||||||
pclk = sg->sata0_pclk;
|
pclk = sg->sata0_pclk;
|
||||||
else
|
else
|
||||||
pclk = sg->sata1_pclk;
|
pclk = sg->sata1_pclk;
|
||||||
clk_enable(pclk);
|
ret = clk_enable(pclk);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
msleep(10);
|
msleep(10);
|
||||||
|
|
||||||
/* Do not keep clocking a bridge that is not online */
|
/* Do not keep clocking a bridge that is not online */
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ menu "CPU Idle"
|
|||||||
config CPU_IDLE
|
config CPU_IDLE
|
||||||
bool "CPU idle PM support"
|
bool "CPU idle PM support"
|
||||||
default y if ACPI || PPC_PSERIES
|
default y if ACPI || PPC_PSERIES
|
||||||
select CPU_IDLE_GOV_LADDER if (!NO_HZ && !NO_HZ_IDLE)
|
|
||||||
select CPU_IDLE_GOV_MENU if (NO_HZ || NO_HZ_IDLE)
|
|
||||||
help
|
help
|
||||||
CPU idle is a generic framework for supporting software-controlled
|
CPU idle is a generic framework for supporting software-controlled
|
||||||
idle processor power management. It includes modular cross-platform
|
idle processor power management. It includes modular cross-platform
|
||||||
|
|||||||
@@ -172,6 +172,10 @@ static irqreturn_t idma64_irq(int irq, void *dev)
|
|||||||
u32 status_err;
|
u32 status_err;
|
||||||
unsigned short i;
|
unsigned short i;
|
||||||
|
|
||||||
|
/* Since IRQ may be shared, check if DMA controller is powered on */
|
||||||
|
if (status == GENMASK(31, 0))
|
||||||
|
return IRQ_NONE;
|
||||||
|
|
||||||
dev_vdbg(idma64->dma.dev, "%s: status=%#x\n", __func__, status);
|
dev_vdbg(idma64->dma.dev, "%s: status=%#x\n", __func__, status);
|
||||||
|
|
||||||
/* Check if we have any interrupt from the DMA controller */
|
/* Check if we have any interrupt from the DMA controller */
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ static void pchan_update(struct owl_dma_pchan *pchan, u32 reg,
|
|||||||
else
|
else
|
||||||
regval &= ~val;
|
regval &= ~val;
|
||||||
|
|
||||||
writel(val, pchan->base + reg);
|
writel(regval, pchan->base + reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pchan_writel(struct owl_dma_pchan *pchan, u32 reg, u32 data)
|
static void pchan_writel(struct owl_dma_pchan *pchan, u32 reg, u32 data)
|
||||||
@@ -254,7 +254,7 @@ static void dma_update(struct owl_dma *od, u32 reg, u32 val, bool state)
|
|||||||
else
|
else
|
||||||
regval &= ~val;
|
regval &= ~val;
|
||||||
|
|
||||||
writel(val, od->base + reg);
|
writel(regval, od->base + reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dma_writel(struct owl_dma *od, u32 reg, u32 data)
|
static void dma_writel(struct owl_dma *od, u32 reg, u32 data)
|
||||||
|
|||||||
@@ -161,10 +161,12 @@ packet_buffer_get(struct client *client, char __user *data, size_t user_length)
|
|||||||
if (atomic_read(&buffer->size) == 0)
|
if (atomic_read(&buffer->size) == 0)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/* FIXME: Check length <= user_length. */
|
length = buffer->head->length;
|
||||||
|
|
||||||
|
if (length > user_length)
|
||||||
|
return 0;
|
||||||
|
|
||||||
end = buffer->data + buffer->capacity;
|
end = buffer->data + buffer->capacity;
|
||||||
length = buffer->head->length;
|
|
||||||
|
|
||||||
if (&buffer->head->data[length] < end) {
|
if (&buffer->head->data[length] < end) {
|
||||||
if (copy_to_user(data, buffer->head->data, length))
|
if (copy_to_user(data, buffer->head->data, length))
|
||||||
|
|||||||
@@ -2066,6 +2066,8 @@ static void bus_reset_work(struct work_struct *work)
|
|||||||
|
|
||||||
ohci->generation = generation;
|
ohci->generation = generation;
|
||||||
reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
|
reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
|
||||||
|
if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS)
|
||||||
|
reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset);
|
||||||
|
|
||||||
if (ohci->quirks & QUIRK_RESET_PACKET)
|
if (ohci->quirks & QUIRK_RESET_PACKET)
|
||||||
ohci->request_generation = generation;
|
ohci->request_generation = generation;
|
||||||
@@ -2132,12 +2134,14 @@ static irqreturn_t irq_handler(int irq, void *data)
|
|||||||
return IRQ_NONE;
|
return IRQ_NONE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* busReset and postedWriteErr must not be cleared yet
|
* busReset and postedWriteErr events must not be cleared yet
|
||||||
* (OHCI 1.1 clauses 7.2.3.2 and 13.2.8.1)
|
* (OHCI 1.1 clauses 7.2.3.2 and 13.2.8.1)
|
||||||
*/
|
*/
|
||||||
reg_write(ohci, OHCI1394_IntEventClear,
|
reg_write(ohci, OHCI1394_IntEventClear,
|
||||||
event & ~(OHCI1394_busReset | OHCI1394_postedWriteErr));
|
event & ~(OHCI1394_busReset | OHCI1394_postedWriteErr));
|
||||||
log_irqs(ohci, event);
|
log_irqs(ohci, event);
|
||||||
|
if (event & OHCI1394_busReset)
|
||||||
|
reg_write(ohci, OHCI1394_IntMaskClear, OHCI1394_busReset);
|
||||||
|
|
||||||
if (event & OHCI1394_selfIDComplete)
|
if (event & OHCI1394_selfIDComplete)
|
||||||
queue_work(selfid_workqueue, &ohci->bus_reset_work);
|
queue_work(selfid_workqueue, &ohci->bus_reset_work);
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ static inline int to_reg(int gpio, enum ctrl_register reg_type)
|
|||||||
case 0x5e:
|
case 0x5e:
|
||||||
return GPIOPANELCTL;
|
return GPIOPANELCTL;
|
||||||
default:
|
default:
|
||||||
return -EOPNOTSUPP;
|
return -ENOTSUPP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ static inline unsigned int to_reg(int gpio, enum ctrl_register reg_type)
|
|||||||
unsigned int reg;
|
unsigned int reg;
|
||||||
|
|
||||||
if (gpio >= WCOVE_GPIO_NUM)
|
if (gpio >= WCOVE_GPIO_NUM)
|
||||||
return -EOPNOTSUPP;
|
return -ENOTSUPP;
|
||||||
|
|
||||||
if (reg_type == CTRL_IN)
|
if (reg_type == CTRL_IN)
|
||||||
reg = GPIO_IN_CTRL_BASE + gpio;
|
reg = GPIO_IN_CTRL_BASE + gpio;
|
||||||
|
|||||||
@@ -46,9 +46,9 @@
|
|||||||
/* Impose limit on how much memory KFD can use */
|
/* Impose limit on how much memory KFD can use */
|
||||||
static struct {
|
static struct {
|
||||||
uint64_t max_system_mem_limit;
|
uint64_t max_system_mem_limit;
|
||||||
uint64_t max_userptr_mem_limit;
|
uint64_t max_ttm_mem_limit;
|
||||||
int64_t system_mem_used;
|
int64_t system_mem_used;
|
||||||
int64_t userptr_mem_used;
|
int64_t ttm_mem_used;
|
||||||
spinlock_t mem_limit_lock;
|
spinlock_t mem_limit_lock;
|
||||||
} kfd_mem_limit;
|
} kfd_mem_limit;
|
||||||
|
|
||||||
@@ -90,8 +90,8 @@ static bool check_if_add_bo_to_vm(struct amdgpu_vm *avm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Set memory usage limits. Current, limits are
|
/* Set memory usage limits. Current, limits are
|
||||||
* System (kernel) memory - 3/8th System RAM
|
* System (TTM + userptr) memory - 3/4th System RAM
|
||||||
* Userptr memory - 3/4th System RAM
|
* TTM memory - 3/8th System RAM
|
||||||
*/
|
*/
|
||||||
void amdgpu_amdkfd_gpuvm_init_mem_limits(void)
|
void amdgpu_amdkfd_gpuvm_init_mem_limits(void)
|
||||||
{
|
{
|
||||||
@@ -103,48 +103,54 @@ void amdgpu_amdkfd_gpuvm_init_mem_limits(void)
|
|||||||
mem *= si.mem_unit;
|
mem *= si.mem_unit;
|
||||||
|
|
||||||
spin_lock_init(&kfd_mem_limit.mem_limit_lock);
|
spin_lock_init(&kfd_mem_limit.mem_limit_lock);
|
||||||
kfd_mem_limit.max_system_mem_limit = (mem >> 1) - (mem >> 3);
|
kfd_mem_limit.max_system_mem_limit = (mem >> 1) + (mem >> 2);
|
||||||
kfd_mem_limit.max_userptr_mem_limit = mem - (mem >> 2);
|
kfd_mem_limit.max_ttm_mem_limit = (mem >> 1) - (mem >> 3);
|
||||||
pr_debug("Kernel memory limit %lluM, userptr limit %lluM\n",
|
pr_debug("Kernel memory limit %lluM, TTM limit %lluM\n",
|
||||||
(kfd_mem_limit.max_system_mem_limit >> 20),
|
(kfd_mem_limit.max_system_mem_limit >> 20),
|
||||||
(kfd_mem_limit.max_userptr_mem_limit >> 20));
|
(kfd_mem_limit.max_ttm_mem_limit >> 20));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int amdgpu_amdkfd_reserve_system_mem_limit(struct amdgpu_device *adev,
|
static int amdgpu_amdkfd_reserve_system_mem_limit(struct amdgpu_device *adev,
|
||||||
uint64_t size, u32 domain)
|
uint64_t size, u32 domain, bool sg)
|
||||||
{
|
{
|
||||||
size_t acc_size;
|
size_t acc_size, system_mem_needed, ttm_mem_needed;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
acc_size = ttm_bo_dma_acc_size(&adev->mman.bdev, size,
|
acc_size = ttm_bo_dma_acc_size(&adev->mman.bdev, size,
|
||||||
sizeof(struct amdgpu_bo));
|
sizeof(struct amdgpu_bo));
|
||||||
|
|
||||||
spin_lock(&kfd_mem_limit.mem_limit_lock);
|
spin_lock(&kfd_mem_limit.mem_limit_lock);
|
||||||
|
|
||||||
if (domain == AMDGPU_GEM_DOMAIN_GTT) {
|
if (domain == AMDGPU_GEM_DOMAIN_GTT) {
|
||||||
if (kfd_mem_limit.system_mem_used + (acc_size + size) >
|
/* TTM GTT memory */
|
||||||
kfd_mem_limit.max_system_mem_limit) {
|
system_mem_needed = acc_size + size;
|
||||||
ret = -ENOMEM;
|
ttm_mem_needed = acc_size + size;
|
||||||
goto err_no_mem;
|
} else if (domain == AMDGPU_GEM_DOMAIN_CPU && !sg) {
|
||||||
}
|
/* Userptr */
|
||||||
kfd_mem_limit.system_mem_used += (acc_size + size);
|
system_mem_needed = acc_size + size;
|
||||||
} else if (domain == AMDGPU_GEM_DOMAIN_CPU) {
|
ttm_mem_needed = acc_size;
|
||||||
if ((kfd_mem_limit.system_mem_used + acc_size >
|
} else {
|
||||||
kfd_mem_limit.max_system_mem_limit) ||
|
/* VRAM and SG */
|
||||||
(kfd_mem_limit.userptr_mem_used + (size + acc_size) >
|
system_mem_needed = acc_size;
|
||||||
kfd_mem_limit.max_userptr_mem_limit)) {
|
ttm_mem_needed = acc_size;
|
||||||
ret = -ENOMEM;
|
|
||||||
goto err_no_mem;
|
|
||||||
}
|
|
||||||
kfd_mem_limit.system_mem_used += acc_size;
|
|
||||||
kfd_mem_limit.userptr_mem_used += size;
|
|
||||||
}
|
}
|
||||||
err_no_mem:
|
|
||||||
|
if ((kfd_mem_limit.system_mem_used + system_mem_needed >
|
||||||
|
kfd_mem_limit.max_system_mem_limit) ||
|
||||||
|
(kfd_mem_limit.ttm_mem_used + ttm_mem_needed >
|
||||||
|
kfd_mem_limit.max_ttm_mem_limit))
|
||||||
|
ret = -ENOMEM;
|
||||||
|
else {
|
||||||
|
kfd_mem_limit.system_mem_used += system_mem_needed;
|
||||||
|
kfd_mem_limit.ttm_mem_used += ttm_mem_needed;
|
||||||
|
}
|
||||||
|
|
||||||
spin_unlock(&kfd_mem_limit.mem_limit_lock);
|
spin_unlock(&kfd_mem_limit.mem_limit_lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unreserve_system_mem_limit(struct amdgpu_device *adev,
|
static void unreserve_system_mem_limit(struct amdgpu_device *adev,
|
||||||
uint64_t size, u32 domain)
|
uint64_t size, u32 domain, bool sg)
|
||||||
{
|
{
|
||||||
size_t acc_size;
|
size_t acc_size;
|
||||||
|
|
||||||
@@ -154,14 +160,18 @@ static void unreserve_system_mem_limit(struct amdgpu_device *adev,
|
|||||||
spin_lock(&kfd_mem_limit.mem_limit_lock);
|
spin_lock(&kfd_mem_limit.mem_limit_lock);
|
||||||
if (domain == AMDGPU_GEM_DOMAIN_GTT) {
|
if (domain == AMDGPU_GEM_DOMAIN_GTT) {
|
||||||
kfd_mem_limit.system_mem_used -= (acc_size + size);
|
kfd_mem_limit.system_mem_used -= (acc_size + size);
|
||||||
} else if (domain == AMDGPU_GEM_DOMAIN_CPU) {
|
kfd_mem_limit.ttm_mem_used -= (acc_size + size);
|
||||||
|
} else if (domain == AMDGPU_GEM_DOMAIN_CPU && !sg) {
|
||||||
|
kfd_mem_limit.system_mem_used -= (acc_size + size);
|
||||||
|
kfd_mem_limit.ttm_mem_used -= acc_size;
|
||||||
|
} else {
|
||||||
kfd_mem_limit.system_mem_used -= acc_size;
|
kfd_mem_limit.system_mem_used -= acc_size;
|
||||||
kfd_mem_limit.userptr_mem_used -= size;
|
kfd_mem_limit.ttm_mem_used -= acc_size;
|
||||||
}
|
}
|
||||||
WARN_ONCE(kfd_mem_limit.system_mem_used < 0,
|
WARN_ONCE(kfd_mem_limit.system_mem_used < 0,
|
||||||
"kfd system memory accounting unbalanced");
|
"kfd system memory accounting unbalanced");
|
||||||
WARN_ONCE(kfd_mem_limit.userptr_mem_used < 0,
|
WARN_ONCE(kfd_mem_limit.ttm_mem_used < 0,
|
||||||
"kfd userptr memory accounting unbalanced");
|
"kfd TTM memory accounting unbalanced");
|
||||||
|
|
||||||
spin_unlock(&kfd_mem_limit.mem_limit_lock);
|
spin_unlock(&kfd_mem_limit.mem_limit_lock);
|
||||||
}
|
}
|
||||||
@@ -171,16 +181,22 @@ void amdgpu_amdkfd_unreserve_system_memory_limit(struct amdgpu_bo *bo)
|
|||||||
spin_lock(&kfd_mem_limit.mem_limit_lock);
|
spin_lock(&kfd_mem_limit.mem_limit_lock);
|
||||||
|
|
||||||
if (bo->flags & AMDGPU_AMDKFD_USERPTR_BO) {
|
if (bo->flags & AMDGPU_AMDKFD_USERPTR_BO) {
|
||||||
kfd_mem_limit.system_mem_used -= bo->tbo.acc_size;
|
kfd_mem_limit.system_mem_used -=
|
||||||
kfd_mem_limit.userptr_mem_used -= amdgpu_bo_size(bo);
|
(bo->tbo.acc_size + amdgpu_bo_size(bo));
|
||||||
|
kfd_mem_limit.ttm_mem_used -= bo->tbo.acc_size;
|
||||||
} else if (bo->preferred_domains == AMDGPU_GEM_DOMAIN_GTT) {
|
} else if (bo->preferred_domains == AMDGPU_GEM_DOMAIN_GTT) {
|
||||||
kfd_mem_limit.system_mem_used -=
|
kfd_mem_limit.system_mem_used -=
|
||||||
(bo->tbo.acc_size + amdgpu_bo_size(bo));
|
(bo->tbo.acc_size + amdgpu_bo_size(bo));
|
||||||
|
kfd_mem_limit.ttm_mem_used -=
|
||||||
|
(bo->tbo.acc_size + amdgpu_bo_size(bo));
|
||||||
|
} else {
|
||||||
|
kfd_mem_limit.system_mem_used -= bo->tbo.acc_size;
|
||||||
|
kfd_mem_limit.ttm_mem_used -= bo->tbo.acc_size;
|
||||||
}
|
}
|
||||||
WARN_ONCE(kfd_mem_limit.system_mem_used < 0,
|
WARN_ONCE(kfd_mem_limit.system_mem_used < 0,
|
||||||
"kfd system memory accounting unbalanced");
|
"kfd system memory accounting unbalanced");
|
||||||
WARN_ONCE(kfd_mem_limit.userptr_mem_used < 0,
|
WARN_ONCE(kfd_mem_limit.ttm_mem_used < 0,
|
||||||
"kfd userptr memory accounting unbalanced");
|
"kfd TTM memory accounting unbalanced");
|
||||||
|
|
||||||
spin_unlock(&kfd_mem_limit.mem_limit_lock);
|
spin_unlock(&kfd_mem_limit.mem_limit_lock);
|
||||||
}
|
}
|
||||||
@@ -1201,10 +1217,11 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
|||||||
|
|
||||||
amdgpu_sync_create(&(*mem)->sync);
|
amdgpu_sync_create(&(*mem)->sync);
|
||||||
|
|
||||||
ret = amdgpu_amdkfd_reserve_system_mem_limit(adev, size, alloc_domain);
|
ret = amdgpu_amdkfd_reserve_system_mem_limit(adev, size,
|
||||||
|
alloc_domain, false);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_debug("Insufficient system memory\n");
|
pr_debug("Insufficient system memory\n");
|
||||||
goto err_reserve_system_mem;
|
goto err_reserve_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_debug("\tcreate BO VA 0x%llx size 0x%llx domain %s\n",
|
pr_debug("\tcreate BO VA 0x%llx size 0x%llx domain %s\n",
|
||||||
@@ -1252,10 +1269,11 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
|||||||
allocate_init_user_pages_failed:
|
allocate_init_user_pages_failed:
|
||||||
amdgpu_bo_unref(&bo);
|
amdgpu_bo_unref(&bo);
|
||||||
/* Don't unreserve system mem limit twice */
|
/* Don't unreserve system mem limit twice */
|
||||||
goto err_reserve_system_mem;
|
goto err_reserve_limit;
|
||||||
err_bo_create:
|
err_bo_create:
|
||||||
unreserve_system_mem_limit(adev, size, alloc_domain);
|
unreserve_system_mem_limit(adev, size, alloc_domain, false);
|
||||||
err_reserve_system_mem:
|
err_reserve_limit:
|
||||||
|
amdgpu_sync_free(&(*mem)->sync);
|
||||||
mutex_destroy(&(*mem)->lock);
|
mutex_destroy(&(*mem)->lock);
|
||||||
kfree(*mem);
|
kfree(*mem);
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@@ -2048,6 +2048,37 @@ static void amdgpu_vm_bo_insert_map(struct amdgpu_device *adev,
|
|||||||
trace_amdgpu_vm_bo_map(bo_va, mapping);
|
trace_amdgpu_vm_bo_map(bo_va, mapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Validate operation parameters to prevent potential abuse */
|
||||||
|
static int amdgpu_vm_verify_parameters(struct amdgpu_device *adev,
|
||||||
|
struct amdgpu_bo *bo,
|
||||||
|
uint64_t saddr,
|
||||||
|
uint64_t offset,
|
||||||
|
uint64_t size)
|
||||||
|
{
|
||||||
|
uint64_t tmp, lpfn;
|
||||||
|
|
||||||
|
if (saddr & AMDGPU_GPU_PAGE_MASK
|
||||||
|
|| offset & AMDGPU_GPU_PAGE_MASK
|
||||||
|
|| size & AMDGPU_GPU_PAGE_MASK)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (check_add_overflow(saddr, size, &tmp)
|
||||||
|
|| check_add_overflow(offset, size, &tmp)
|
||||||
|
|| size == 0 /* which also leads to end < begin */)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* make sure object fit at this offset */
|
||||||
|
if (bo && offset + size > amdgpu_bo_size(bo))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Ensure last pfn not exceed max_pfn */
|
||||||
|
lpfn = (saddr + size - 1) >> AMDGPU_GPU_PAGE_SHIFT;
|
||||||
|
if (lpfn >= adev->vm_manager.max_pfn)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* amdgpu_vm_bo_map - map bo inside a vm
|
* amdgpu_vm_bo_map - map bo inside a vm
|
||||||
*
|
*
|
||||||
@@ -2074,20 +2105,14 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
|
|||||||
struct amdgpu_bo *bo = bo_va->base.bo;
|
struct amdgpu_bo *bo = bo_va->base.bo;
|
||||||
struct amdgpu_vm *vm = bo_va->base.vm;
|
struct amdgpu_vm *vm = bo_va->base.vm;
|
||||||
uint64_t eaddr;
|
uint64_t eaddr;
|
||||||
|
int r;
|
||||||
|
|
||||||
/* validate the parameters */
|
r = amdgpu_vm_verify_parameters(adev, bo, saddr, offset, size);
|
||||||
if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK ||
|
if (r)
|
||||||
size == 0 || size & ~PAGE_MASK)
|
return r;
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/* make sure object fit at this offset */
|
|
||||||
eaddr = saddr + size - 1;
|
|
||||||
if (saddr >= eaddr ||
|
|
||||||
(bo && offset + size > amdgpu_bo_size(bo)))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
saddr /= AMDGPU_GPU_PAGE_SIZE;
|
saddr /= AMDGPU_GPU_PAGE_SIZE;
|
||||||
eaddr /= AMDGPU_GPU_PAGE_SIZE;
|
eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE;
|
||||||
|
|
||||||
tmp = amdgpu_vm_it_iter_first(&vm->va, saddr, eaddr);
|
tmp = amdgpu_vm_it_iter_first(&vm->va, saddr, eaddr);
|
||||||
if (tmp) {
|
if (tmp) {
|
||||||
@@ -2140,16 +2165,9 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev,
|
|||||||
uint64_t eaddr;
|
uint64_t eaddr;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* validate the parameters */
|
r = amdgpu_vm_verify_parameters(adev, bo, saddr, offset, size);
|
||||||
if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK ||
|
if (r)
|
||||||
size == 0 || size & ~PAGE_MASK)
|
return r;
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/* make sure object fit at this offset */
|
|
||||||
eaddr = saddr + size - 1;
|
|
||||||
if (saddr >= eaddr ||
|
|
||||||
(bo && offset + size > amdgpu_bo_size(bo)))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/* Allocate all the needed memory */
|
/* Allocate all the needed memory */
|
||||||
mapping = kmalloc(sizeof(*mapping), GFP_KERNEL);
|
mapping = kmalloc(sizeof(*mapping), GFP_KERNEL);
|
||||||
@@ -2163,7 +2181,7 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
saddr /= AMDGPU_GPU_PAGE_SIZE;
|
saddr /= AMDGPU_GPU_PAGE_SIZE;
|
||||||
eaddr /= AMDGPU_GPU_PAGE_SIZE;
|
eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE;
|
||||||
|
|
||||||
mapping->start = saddr;
|
mapping->start = saddr;
|
||||||
mapping->last = eaddr;
|
mapping->last = eaddr;
|
||||||
@@ -2250,10 +2268,14 @@ int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev,
|
|||||||
struct amdgpu_bo_va_mapping *before, *after, *tmp, *next;
|
struct amdgpu_bo_va_mapping *before, *after, *tmp, *next;
|
||||||
LIST_HEAD(removed);
|
LIST_HEAD(removed);
|
||||||
uint64_t eaddr;
|
uint64_t eaddr;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = amdgpu_vm_verify_parameters(adev, NULL, saddr, 0, size);
|
||||||
|
if (r)
|
||||||
|
return r;
|
||||||
|
|
||||||
eaddr = saddr + size - 1;
|
|
||||||
saddr /= AMDGPU_GPU_PAGE_SIZE;
|
saddr /= AMDGPU_GPU_PAGE_SIZE;
|
||||||
eaddr /= AMDGPU_GPU_PAGE_SIZE;
|
eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE;
|
||||||
|
|
||||||
/* Allocate all the needed memory */
|
/* Allocate all the needed memory */
|
||||||
before = kzalloc(sizeof(*before), GFP_KERNEL);
|
before = kzalloc(sizeof(*before), GFP_KERNEL);
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include <drm/drmP.h>
|
#include <drm/drmP.h>
|
||||||
|
|
||||||
#include "nouveau_drv.h"
|
#include "nouveau_drv.h"
|
||||||
|
#include "nouveau_bios.h"
|
||||||
#include "nouveau_reg.h"
|
#include "nouveau_reg.h"
|
||||||
#include "dispnv04/hw.h"
|
#include "dispnv04/hw.h"
|
||||||
#include "nouveau_encoder.h"
|
#include "nouveau_encoder.h"
|
||||||
@@ -1674,7 +1675,7 @@ apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf)
|
|||||||
*/
|
*/
|
||||||
if (nv_match_device(dev, 0x0201, 0x1462, 0x8851)) {
|
if (nv_match_device(dev, 0x0201, 0x1462, 0x8851)) {
|
||||||
if (*conn == 0xf2005014 && *conf == 0xffffffff) {
|
if (*conn == 0xf2005014 && *conf == 0xffffffff) {
|
||||||
fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 1, 1, 1);
|
fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 1, 1, DCB_OUTPUT_B);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1760,26 +1761,26 @@ fabricate_dcb_encoder_table(struct drm_device *dev, struct nvbios *bios)
|
|||||||
#ifdef __powerpc__
|
#ifdef __powerpc__
|
||||||
/* Apple iMac G4 NV17 */
|
/* Apple iMac G4 NV17 */
|
||||||
if (of_machine_is_compatible("PowerMac4,5")) {
|
if (of_machine_is_compatible("PowerMac4,5")) {
|
||||||
fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 0, all_heads, 1);
|
fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 0, all_heads, DCB_OUTPUT_B);
|
||||||
fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG, 1, all_heads, 2);
|
fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG, 1, all_heads, DCB_OUTPUT_C);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Make up some sane defaults */
|
/* Make up some sane defaults */
|
||||||
fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG,
|
fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG,
|
||||||
bios->legacy.i2c_indices.crt, 1, 1);
|
bios->legacy.i2c_indices.crt, 1, DCB_OUTPUT_B);
|
||||||
|
|
||||||
if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0)
|
if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0)
|
||||||
fabricate_dcb_output(dcb, DCB_OUTPUT_TV,
|
fabricate_dcb_output(dcb, DCB_OUTPUT_TV,
|
||||||
bios->legacy.i2c_indices.tv,
|
bios->legacy.i2c_indices.tv,
|
||||||
all_heads, 0);
|
all_heads, DCB_OUTPUT_A);
|
||||||
|
|
||||||
else if (bios->tmds.output0_script_ptr ||
|
else if (bios->tmds.output0_script_ptr ||
|
||||||
bios->tmds.output1_script_ptr)
|
bios->tmds.output1_script_ptr)
|
||||||
fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS,
|
fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS,
|
||||||
bios->legacy.i2c_indices.panel,
|
bios->legacy.i2c_indices.panel,
|
||||||
all_heads, 1);
|
all_heads, DCB_OUTPUT_B);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|||||||
@@ -66,11 +66,16 @@ of_init(struct nvkm_bios *bios, const char *name)
|
|||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void of_fini(void *p)
|
||||||
|
{
|
||||||
|
kfree(p);
|
||||||
|
}
|
||||||
|
|
||||||
const struct nvbios_source
|
const struct nvbios_source
|
||||||
nvbios_of = {
|
nvbios_of = {
|
||||||
.name = "OpenFirmware",
|
.name = "OpenFirmware",
|
||||||
.init = of_init,
|
.init = of_init,
|
||||||
.fini = (void(*)(void *))kfree,
|
.fini = of_fini,
|
||||||
.read = of_read,
|
.read = of_read,
|
||||||
.size = of_size,
|
.size = of_size,
|
||||||
.rw = false,
|
.rw = false,
|
||||||
|
|||||||
@@ -221,8 +221,11 @@ nv50_instobj_acquire(struct nvkm_memory *memory)
|
|||||||
void __iomem *map = NULL;
|
void __iomem *map = NULL;
|
||||||
|
|
||||||
/* Already mapped? */
|
/* Already mapped? */
|
||||||
if (refcount_inc_not_zero(&iobj->maps))
|
if (refcount_inc_not_zero(&iobj->maps)) {
|
||||||
|
/* read barrier match the wmb on refcount set */
|
||||||
|
smp_rmb();
|
||||||
return iobj->map;
|
return iobj->map;
|
||||||
|
}
|
||||||
|
|
||||||
/* Take the lock, and re-check that another thread hasn't
|
/* Take the lock, and re-check that another thread hasn't
|
||||||
* already mapped the object in the meantime.
|
* already mapped the object in the meantime.
|
||||||
@@ -249,6 +252,8 @@ nv50_instobj_acquire(struct nvkm_memory *memory)
|
|||||||
iobj->base.memory.ptrs = &nv50_instobj_fast;
|
iobj->base.memory.ptrs = &nv50_instobj_fast;
|
||||||
else
|
else
|
||||||
iobj->base.memory.ptrs = &nv50_instobj_slow;
|
iobj->base.memory.ptrs = &nv50_instobj_slow;
|
||||||
|
/* barrier to ensure the ptrs are written before refcount is set */
|
||||||
|
smp_wmb();
|
||||||
refcount_set(&iobj->maps, 1);
|
refcount_set(&iobj->maps, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1064,7 +1064,7 @@ static int vmw_event_fence_action_create(struct drm_file *file_priv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
event->event.base.type = DRM_VMW_EVENT_FENCE_SIGNALED;
|
event->event.base.type = DRM_VMW_EVENT_FENCE_SIGNALED;
|
||||||
event->event.base.length = sizeof(*event);
|
event->event.base.length = sizeof(event->event);
|
||||||
event->event.user_data = user_data;
|
event->event.user_data = user_data;
|
||||||
|
|
||||||
ret = drm_event_reserve_init(dev, file_priv, &event->base, &event->event.base);
|
ret = drm_event_reserve_init(dev, file_priv, &event->base, &event->event.base);
|
||||||
|
|||||||
+6
-9
@@ -803,21 +803,18 @@ config HID_PLAYSTATION
|
|||||||
depends on HID
|
depends on HID
|
||||||
select CRC32
|
select CRC32
|
||||||
select POWER_SUPPLY
|
select POWER_SUPPLY
|
||||||
---help---
|
help
|
||||||
Provides support for Sony PS5 controllers including support for
|
Provides support for Sony PS5 controllers including support for
|
||||||
its special functionalities e.g. touchpad, lights and motion
|
its special functionalities e.g. touchpad, lights and motion
|
||||||
sensors.
|
sensors.
|
||||||
|
|
||||||
config PLAYSTATION_FF
|
config PLAYSTATION_FF
|
||||||
bool "PlayStation force feedback support"
|
bool "PlayStation force feedback support"
|
||||||
depends on HID_PLAYSTATION
|
depends on HID_PLAYSTATION
|
||||||
select INPUT_FF_MEMLESS
|
select INPUT_FF_MEMLESS
|
||||||
help
|
help
|
||||||
Provides the force feedback support for Playstation game
|
Say Y here if you would like to enable force feedback support for
|
||||||
controllers.
|
PlayStation game controllers.
|
||||||
|
|
||||||
Say Y here if you would like to enable force feedback support for
|
|
||||||
PlayStation game controllers.
|
|
||||||
|
|
||||||
config HID_PRIMAX
|
config HID_PRIMAX
|
||||||
tristate "Primax non-fully HID-compliant devices"
|
tristate "Primax non-fully HID-compliant devices"
|
||||||
|
|||||||
@@ -1056,6 +1056,7 @@
|
|||||||
#define USB_DEVICE_ID_SONY_PS4_CONTROLLER_2 0x09cc
|
#define USB_DEVICE_ID_SONY_PS4_CONTROLLER_2 0x09cc
|
||||||
#define USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE 0x0ba0
|
#define USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE 0x0ba0
|
||||||
#define USB_DEVICE_ID_SONY_PS5_CONTROLLER 0x0ce6
|
#define USB_DEVICE_ID_SONY_PS5_CONTROLLER 0x0ce6
|
||||||
|
#define USB_DEVICE_ID_SONY_PS5_CONTROLLER_2 0x0df2
|
||||||
#define USB_DEVICE_ID_SONY_MOTION_CONTROLLER 0x03d5
|
#define USB_DEVICE_ID_SONY_MOTION_CONTROLLER 0x03d5
|
||||||
#define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f
|
#define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f
|
||||||
#define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER 0x0002
|
#define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER 0x0002
|
||||||
|
|||||||
+160
-147
@@ -4,6 +4,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2020 Sony Interactive Entertainment
|
* Copyright (c) 2020 Sony Interactive Entertainment
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/bits.h>
|
#include <linux/bits.h>
|
||||||
#include <linux/crc32.h>
|
#include <linux/crc32.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
@@ -36,17 +37,15 @@ struct ps_device {
|
|||||||
struct power_supply *battery;
|
struct power_supply *battery;
|
||||||
uint8_t battery_capacity;
|
uint8_t battery_capacity;
|
||||||
int battery_status;
|
int battery_status;
|
||||||
|
|
||||||
uint8_t mac_address[6]; /* Note: stored in little endian order. */
|
uint8_t mac_address[6]; /* Note: stored in little endian order. */
|
||||||
int32_t hw_version;
|
uint32_t hw_version;
|
||||||
int32_t fw_version;
|
uint32_t fw_version;
|
||||||
|
|
||||||
int (*parse_report)(struct ps_device *dev, struct hid_report *report, u8 *data, int size);
|
int (*parse_report)(struct ps_device *dev, struct hid_report *report, u8 *data, int size);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Seed values for DualShock4 / DualSense CRC32 for different report types. */
|
/* Calibration data for playstation motion sensors. */
|
||||||
#define PS_INPUT_CRC32_SEED 0xA1
|
|
||||||
#define PS_OUTPUT_CRC32_SEED 0xA2
|
|
||||||
#define PS_FEATURE_CRC32_SEED 0xA3
|
|
||||||
|
|
||||||
struct ps_calibration_data {
|
struct ps_calibration_data {
|
||||||
int abs_code;
|
int abs_code;
|
||||||
short bias;
|
short bias;
|
||||||
@@ -54,24 +53,26 @@ struct ps_calibration_data {
|
|||||||
int sens_denom;
|
int sens_denom;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Seed values for DualShock4 / DualSense CRC32 for different report types. */
|
||||||
|
#define PS_INPUT_CRC32_SEED 0xA1
|
||||||
|
#define PS_OUTPUT_CRC32_SEED 0xA2
|
||||||
|
#define PS_FEATURE_CRC32_SEED 0xA3
|
||||||
|
|
||||||
#define DS_INPUT_REPORT_USB 0x01
|
#define DS_INPUT_REPORT_USB 0x01
|
||||||
#define DS_INPUT_REPORT_USB_SIZE 64
|
#define DS_INPUT_REPORT_USB_SIZE 64
|
||||||
|
#define DS_INPUT_REPORT_BT 0x31
|
||||||
|
#define DS_INPUT_REPORT_BT_SIZE 78
|
||||||
|
#define DS_OUTPUT_REPORT_USB 0x02
|
||||||
|
#define DS_OUTPUT_REPORT_USB_SIZE 63
|
||||||
|
#define DS_OUTPUT_REPORT_BT 0x31
|
||||||
|
#define DS_OUTPUT_REPORT_BT_SIZE 78
|
||||||
|
|
||||||
#define DS_FEATURE_REPORT_CALIBRATION 0x05
|
#define DS_FEATURE_REPORT_CALIBRATION 0x05
|
||||||
#define DS_FEATURE_REPORT_CALIBRATION_SIZE 41
|
#define DS_FEATURE_REPORT_CALIBRATION_SIZE 41
|
||||||
|
#define DS_FEATURE_REPORT_PAIRING_INFO 0x09
|
||||||
#define DS_INPUT_REPORT_BT 0x31
|
#define DS_FEATURE_REPORT_PAIRING_INFO_SIZE 20
|
||||||
#define DS_INPUT_REPORT_BT_SIZE 78
|
#define DS_FEATURE_REPORT_FIRMWARE_INFO 0x20
|
||||||
#define DS_OUTPUT_REPORT_USB 0x02
|
#define DS_FEATURE_REPORT_FIRMWARE_INFO_SIZE 64
|
||||||
#define DS_OUTPUT_REPORT_USB_SIZE 63
|
|
||||||
#define DS_OUTPUT_REPORT_BT 0x31
|
|
||||||
#define DS_OUTPUT_REPORT_BT_SIZE 78
|
|
||||||
|
|
||||||
#define DS_FEATURE_REPORT_PAIRING_INFO 0x09
|
|
||||||
#define DS_FEATURE_REPORT_PAIRING_INFO_SIZE 20
|
|
||||||
|
|
||||||
#define DS_FEATURE_REPORT_FIRMWARE_INFO 0x20
|
|
||||||
#define DS_FEATURE_REPORT_FIRMWARE_INFO_SIZE 64
|
|
||||||
|
|
||||||
/* Button masks for DualSense input report. */
|
/* Button masks for DualSense input report. */
|
||||||
#define DS_BUTTONS0_HAT_SWITCH GENMASK(3, 0)
|
#define DS_BUTTONS0_HAT_SWITCH GENMASK(3, 0)
|
||||||
@@ -96,14 +97,17 @@ struct ps_calibration_data {
|
|||||||
#define DS_STATUS_CHARGING GENMASK(7, 4)
|
#define DS_STATUS_CHARGING GENMASK(7, 4)
|
||||||
#define DS_STATUS_CHARGING_SHIFT 4
|
#define DS_STATUS_CHARGING_SHIFT 4
|
||||||
|
|
||||||
|
/* Feature version from DualSense Firmware Info report. */
|
||||||
|
#define DS_FEATURE_VERSION(major, minor) ((major & 0xff) << 8 | (minor & 0xff))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
+ * Status of a DualSense touch point contact.
|
* Status of a DualSense touch point contact.
|
||||||
+ * Contact IDs, with highest bit set are 'inactive'
|
* Contact IDs, with highest bit set are 'inactive'
|
||||||
+ * and any associated data is then invalid.
|
* and any associated data is then invalid.
|
||||||
+ */
|
*/
|
||||||
#define DS_TOUCH_POINT_INACTIVE BIT(7)
|
#define DS_TOUCH_POINT_INACTIVE BIT(7)
|
||||||
|
|
||||||
/* Magic value required in tag field of Bluetooth output report. */
|
/* Magic value required in tag field of Bluetooth output report. */
|
||||||
#define DS_OUTPUT_TAG 0x10
|
#define DS_OUTPUT_TAG 0x10
|
||||||
/* Flags for DualSense output report. */
|
/* Flags for DualSense output report. */
|
||||||
#define DS_OUTPUT_VALID_FLAG0_COMPATIBLE_VIBRATION BIT(0)
|
#define DS_OUTPUT_VALID_FLAG0_COMPATIBLE_VIBRATION BIT(0)
|
||||||
@@ -114,17 +118,17 @@ struct ps_calibration_data {
|
|||||||
#define DS_OUTPUT_VALID_FLAG1_RELEASE_LEDS BIT(3)
|
#define DS_OUTPUT_VALID_FLAG1_RELEASE_LEDS BIT(3)
|
||||||
#define DS_OUTPUT_VALID_FLAG1_PLAYER_INDICATOR_CONTROL_ENABLE BIT(4)
|
#define DS_OUTPUT_VALID_FLAG1_PLAYER_INDICATOR_CONTROL_ENABLE BIT(4)
|
||||||
#define DS_OUTPUT_VALID_FLAG2_LIGHTBAR_SETUP_CONTROL_ENABLE BIT(1)
|
#define DS_OUTPUT_VALID_FLAG2_LIGHTBAR_SETUP_CONTROL_ENABLE BIT(1)
|
||||||
|
#define DS_OUTPUT_VALID_FLAG2_COMPATIBLE_VIBRATION2 BIT(2)
|
||||||
#define DS_OUTPUT_POWER_SAVE_CONTROL_MIC_MUTE BIT(4)
|
#define DS_OUTPUT_POWER_SAVE_CONTROL_MIC_MUTE BIT(4)
|
||||||
#define DS_OUTPUT_LIGHTBAR_SETUP_LIGHT_OUT BIT(1)
|
#define DS_OUTPUT_LIGHTBAR_SETUP_LIGHT_OUT BIT(1)
|
||||||
|
|
||||||
#define DS_ACC_RES_PER_G 8192
|
|
||||||
#define DS_ACC_RANGE (4*DS_ACC_RES_PER_G)
|
|
||||||
#define DS_GYRO_RES_PER_DEG_S 1024
|
|
||||||
#define DS_GYRO_RANGE (2048*DS_GYRO_RES_PER_DEG_S)
|
|
||||||
|
|
||||||
/* DualSense hardware limits */
|
/* DualSense hardware limits */
|
||||||
#define DS_TOUCHPAD_WIDTH 1920
|
#define DS_ACC_RES_PER_G 8192
|
||||||
#define DS_TOUCHPAD_HEIGHT 1080
|
#define DS_ACC_RANGE (4*DS_ACC_RES_PER_G)
|
||||||
|
#define DS_GYRO_RES_PER_DEG_S 1024
|
||||||
|
#define DS_GYRO_RANGE (2048*DS_GYRO_RES_PER_DEG_S)
|
||||||
|
#define DS_TOUCHPAD_WIDTH 1920
|
||||||
|
#define DS_TOUCHPAD_HEIGHT 1080
|
||||||
|
|
||||||
struct dualsense {
|
struct dualsense {
|
||||||
struct ps_device base;
|
struct ps_device base;
|
||||||
@@ -132,15 +136,20 @@ struct dualsense {
|
|||||||
struct input_dev *sensors;
|
struct input_dev *sensors;
|
||||||
struct input_dev *touchpad;
|
struct input_dev *touchpad;
|
||||||
|
|
||||||
|
/* Update version is used as a feature/capability version. */
|
||||||
|
uint16_t update_version;
|
||||||
|
|
||||||
/* Calibration data for accelerometer and gyroscope. */
|
/* Calibration data for accelerometer and gyroscope. */
|
||||||
struct ps_calibration_data accel_calib_data[3];
|
struct ps_calibration_data accel_calib_data[3];
|
||||||
struct ps_calibration_data gyro_calib_data[3];
|
struct ps_calibration_data gyro_calib_data[3];
|
||||||
|
|
||||||
/* Timestamp for sensor data */
|
/* Timestamp for sensor data */
|
||||||
bool sensor_timestamp_initialized;
|
bool sensor_timestamp_initialized;
|
||||||
uint32_t prev_sensor_timestamp;
|
uint32_t prev_sensor_timestamp;
|
||||||
uint32_t sensor_timestamp_us;
|
uint32_t sensor_timestamp_us;
|
||||||
|
|
||||||
/* Compatible rumble state */
|
/* Compatible rumble state */
|
||||||
|
bool use_vibration_v2;
|
||||||
bool update_rumble;
|
bool update_rumble;
|
||||||
uint8_t motor_left;
|
uint8_t motor_left;
|
||||||
uint8_t motor_right;
|
uint8_t motor_right;
|
||||||
@@ -173,6 +182,29 @@ struct dualsense_touch_point {
|
|||||||
uint8_t y_hi;
|
uint8_t y_hi;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
/* Main DualSense input report excluding any BT/USB specific headers. */
|
||||||
|
struct dualsense_input_report {
|
||||||
|
uint8_t x, y;
|
||||||
|
uint8_t rx, ry;
|
||||||
|
uint8_t z, rz;
|
||||||
|
uint8_t seq_number;
|
||||||
|
uint8_t buttons[4];
|
||||||
|
uint8_t reserved[4];
|
||||||
|
|
||||||
|
/* Motion sensors */
|
||||||
|
__le16 gyro[3]; /* x, y, z */
|
||||||
|
__le16 accel[3]; /* x, y, z */
|
||||||
|
__le32 sensor_timestamp;
|
||||||
|
uint8_t reserved2;
|
||||||
|
|
||||||
|
/* Touchpad */
|
||||||
|
struct dualsense_touch_point points[2];
|
||||||
|
|
||||||
|
uint8_t reserved3[12];
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t reserved4[10];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
/* Common data between DualSense BT/USB main output report. */
|
/* Common data between DualSense BT/USB main output report. */
|
||||||
struct dualsense_output_report_common {
|
struct dualsense_output_report_common {
|
||||||
uint8_t valid_flag0;
|
uint8_t valid_flag0;
|
||||||
@@ -216,18 +248,15 @@ struct dualsense_output_report_usb {
|
|||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The DualSense has a main output report used to control most features.
|
* The DualSense has a main output report used to control most features. It is
|
||||||
* It is largely the same between Bluetooth and USB except for different
|
* largely the same between Bluetooth and USB except for different headers and CRC.
|
||||||
* headers and CRC. This structure hide the differences between the two to
|
* This structure hide the differences between the two to simplify sending output reports.
|
||||||
* simplify sending output reports.
|
|
||||||
*/
|
*/
|
||||||
struct dualsense_output_report {
|
struct dualsense_output_report {
|
||||||
uint8_t *data; /* Start of data */
|
uint8_t *data; /* Start of data */
|
||||||
uint8_t len; /* Size of output report */
|
uint8_t len; /* Size of output report */
|
||||||
|
|
||||||
/* Points to Bluetooth data payload
|
/* Points to Bluetooth data payload in case for a Bluetooth report else NULL. */
|
||||||
* in case for a Bluetooth report else NULL.
|
|
||||||
*/
|
|
||||||
struct dualsense_output_report_bt *bt;
|
struct dualsense_output_report_bt *bt;
|
||||||
/* Points to USB data payload in case for a USB report else NULL. */
|
/* Points to USB data payload in case for a USB report else NULL. */
|
||||||
struct dualsense_output_report_usb *usb;
|
struct dualsense_output_report_usb *usb;
|
||||||
@@ -235,29 +264,6 @@ struct dualsense_output_report {
|
|||||||
struct dualsense_output_report_common *common;
|
struct dualsense_output_report_common *common;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Main DualSense input report excluding any BT/USB specific headers. */
|
|
||||||
struct dualsense_input_report {
|
|
||||||
uint8_t x, y;
|
|
||||||
uint8_t rx, ry;
|
|
||||||
uint8_t z, rz;
|
|
||||||
uint8_t seq_number;
|
|
||||||
uint8_t buttons[4];
|
|
||||||
uint8_t reserved[4];
|
|
||||||
|
|
||||||
/* Motion sensors */
|
|
||||||
__le16 gyro[3]; /* x, y, z */
|
|
||||||
__le16 accel[3]; /* x, y, z */
|
|
||||||
__le32 sensor_timestamp;
|
|
||||||
uint8_t reserved2;
|
|
||||||
|
|
||||||
/* Touchpad */
|
|
||||||
struct dualsense_touch_point points[2];
|
|
||||||
|
|
||||||
uint8_t reserved3[12];
|
|
||||||
uint8_t status;
|
|
||||||
uint8_t reserved4[10];
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Common gamepad buttons across DualShock 3 / 4 and DualSense.
|
* Common gamepad buttons across DualShock 3 / 4 and DualSense.
|
||||||
* Note: for device with a touchpad, touchpad button is not included
|
* Note: for device with a touchpad, touchpad button is not included
|
||||||
@@ -362,17 +368,6 @@ static struct input_dev *ps_allocate_input_dev(struct hid_device *hdev, const ch
|
|||||||
return input_dev;
|
return input_dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute crc32 of HID data and compare against expected CRC. */
|
|
||||||
static bool ps_check_crc32(uint8_t seed, uint8_t *data, size_t len, uint32_t report_crc)
|
|
||||||
{
|
|
||||||
uint32_t crc;
|
|
||||||
|
|
||||||
crc = crc32_le(0xFFFFFFFF, &seed, 1);
|
|
||||||
crc = ~crc32_le(crc, data, len);
|
|
||||||
|
|
||||||
return crc == report_crc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum power_supply_property ps_power_supply_props[] = {
|
static enum power_supply_property ps_power_supply_props[] = {
|
||||||
POWER_SUPPLY_PROP_STATUS,
|
POWER_SUPPLY_PROP_STATUS,
|
||||||
POWER_SUPPLY_PROP_PRESENT,
|
POWER_SUPPLY_PROP_PRESENT,
|
||||||
@@ -381,8 +376,8 @@ static enum power_supply_property ps_power_supply_props[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static int ps_battery_get_property(struct power_supply *psy,
|
static int ps_battery_get_property(struct power_supply *psy,
|
||||||
enum power_supply_property psp,
|
enum power_supply_property psp,
|
||||||
union power_supply_propval *val)
|
union power_supply_propval *val)
|
||||||
{
|
{
|
||||||
struct ps_device *dev = power_supply_get_drvdata(psy);
|
struct ps_device *dev = power_supply_get_drvdata(psy);
|
||||||
uint8_t battery_capacity;
|
uint8_t battery_capacity;
|
||||||
@@ -427,7 +422,7 @@ static int ps_device_register_battery(struct ps_device *dev)
|
|||||||
dev->battery_desc.num_properties = ARRAY_SIZE(ps_power_supply_props);
|
dev->battery_desc.num_properties = ARRAY_SIZE(ps_power_supply_props);
|
||||||
dev->battery_desc.get_property = ps_battery_get_property;
|
dev->battery_desc.get_property = ps_battery_get_property;
|
||||||
dev->battery_desc.name = devm_kasprintf(&dev->hdev->dev, GFP_KERNEL,
|
dev->battery_desc.name = devm_kasprintf(&dev->hdev->dev, GFP_KERNEL,
|
||||||
"ps-controller-battery-%pMR", dev->mac_address);
|
"ps-controller-battery-%pMR", dev->mac_address);
|
||||||
if (!dev->battery_desc.name)
|
if (!dev->battery_desc.name)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@@ -448,8 +443,19 @@ static int ps_device_register_battery(struct ps_device *dev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Compute crc32 of HID data and compare against expected CRC. */
|
||||||
|
static bool ps_check_crc32(uint8_t seed, uint8_t *data, size_t len, uint32_t report_crc)
|
||||||
|
{
|
||||||
|
uint32_t crc;
|
||||||
|
|
||||||
|
crc = crc32_le(0xFFFFFFFF, &seed, 1);
|
||||||
|
crc = ~crc32_le(crc, data, len);
|
||||||
|
|
||||||
|
return crc == report_crc;
|
||||||
|
}
|
||||||
|
|
||||||
static struct input_dev *ps_gamepad_create(struct hid_device *hdev,
|
static struct input_dev *ps_gamepad_create(struct hid_device *hdev,
|
||||||
int (*play_effect)(struct input_dev *, void *, struct ff_effect *))
|
int (*play_effect)(struct input_dev *, void *, struct ff_effect *))
|
||||||
{
|
{
|
||||||
struct input_dev *gamepad;
|
struct input_dev *gamepad;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
@@ -486,25 +492,24 @@ static struct input_dev *ps_gamepad_create(struct hid_device *hdev,
|
|||||||
return gamepad;
|
return gamepad;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ps_get_report(struct hid_device *hdev, uint8_t report_id,
|
static int ps_get_report(struct hid_device *hdev, uint8_t report_id, uint8_t *buf, size_t size)
|
||||||
uint8_t *buf, size_t size)
|
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = hid_hw_raw_request(hdev, report_id, buf, size, HID_FEATURE_REPORT,
|
ret = hid_hw_raw_request(hdev, report_id, buf, size, HID_FEATURE_REPORT,
|
||||||
HID_REQ_GET_REPORT);
|
HID_REQ_GET_REPORT);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
hid_err(hdev, "Failed to retrieve: reportID %d: %d\n", report_id, ret);
|
hid_err(hdev, "Failed to retrieve feature with reportID %d: %d\n", report_id, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret != size) {
|
if (ret != size) {
|
||||||
hid_err(hdev, "Invalid byte count, expected %zu got %d\n", size, ret);
|
hid_err(hdev, "Invalid byte count transferred, expected %zu got %d\n", size, ret);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf[0] != report_id) {
|
if (buf[0] != report_id) {
|
||||||
hid_err(hdev, "Invalid reportID: expected %d got %d\n", report_id, buf[0]);
|
hid_err(hdev, "Invalid reportID received, expected %d got %d\n", report_id, buf[0]);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -522,8 +527,8 @@ static int ps_get_report(struct hid_device *hdev, uint8_t report_id,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct input_dev *ps_sensors_create(struct hid_device *hdev,
|
static struct input_dev *ps_sensors_create(struct hid_device *hdev, int accel_range, int accel_res,
|
||||||
int accel_range, int accel_res, int gyro_range, int gyro_res)
|
int gyro_range, int gyro_res)
|
||||||
{
|
{
|
||||||
struct input_dev *sensors;
|
struct input_dev *sensors;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -594,7 +599,7 @@ static ssize_t firmware_version_show(struct device *dev,
|
|||||||
struct hid_device *hdev = to_hid_device(dev);
|
struct hid_device *hdev = to_hid_device(dev);
|
||||||
struct ps_device *ps_dev = hid_get_drvdata(hdev);
|
struct ps_device *ps_dev = hid_get_drvdata(hdev);
|
||||||
|
|
||||||
return scnprintf(buf, PAGE_SIZE, "0x%08x\n", ps_dev->fw_version);
|
return snprintf(buf, PAGE_SIZE, "0x%08x\n", ps_dev->fw_version);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEVICE_ATTR_RO(firmware_version);
|
static DEVICE_ATTR_RO(firmware_version);
|
||||||
@@ -606,7 +611,7 @@ static ssize_t hardware_version_show(struct device *dev,
|
|||||||
struct hid_device *hdev = to_hid_device(dev);
|
struct hid_device *hdev = to_hid_device(dev);
|
||||||
struct ps_device *ps_dev = hid_get_drvdata(hdev);
|
struct ps_device *ps_dev = hid_get_drvdata(hdev);
|
||||||
|
|
||||||
return scnprintf(buf, PAGE_SIZE, "0x%08x\n", ps_dev->hw_version);
|
return snprintf(buf, PAGE_SIZE, "0x%08x\n", ps_dev->hw_version);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEVICE_ATTR_RO(hardware_version);
|
static DEVICE_ATTR_RO(hardware_version);
|
||||||
@@ -642,7 +647,7 @@ static int dualsense_get_calibration_data(struct dualsense *ds)
|
|||||||
ret = ps_get_report(ds->base.hdev, DS_FEATURE_REPORT_CALIBRATION, buf,
|
ret = ps_get_report(ds->base.hdev, DS_FEATURE_REPORT_CALIBRATION, buf,
|
||||||
DS_FEATURE_REPORT_CALIBRATION_SIZE);
|
DS_FEATURE_REPORT_CALIBRATION_SIZE);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
hid_err(ds->base.hdev, "Failed: DualSense cal info: %d\n", ret);
|
hid_err(ds->base.hdev, "Failed to retrieve DualSense calibration info: %d\n", ret);
|
||||||
goto err_free;
|
goto err_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -730,6 +735,15 @@ static int dualsense_get_firmware_info(struct dualsense *ds)
|
|||||||
ds->base.hw_version = get_unaligned_le32(&buf[24]);
|
ds->base.hw_version = get_unaligned_le32(&buf[24]);
|
||||||
ds->base.fw_version = get_unaligned_le32(&buf[28]);
|
ds->base.fw_version = get_unaligned_le32(&buf[28]);
|
||||||
|
|
||||||
|
/* Update version is some kind of feature version. It is distinct from
|
||||||
|
* the firmware version as there can be many different variations of a
|
||||||
|
* controller over time with the same physical shell, but with different
|
||||||
|
* PCBs and other internal changes. The update version (internal name) is
|
||||||
|
* used as a means to detect what features are available and change behavior.
|
||||||
|
* Note: the version is different between DualSense and DualSense Edge.
|
||||||
|
*/
|
||||||
|
ds->update_version = get_unaligned_le16(&buf[44]);
|
||||||
|
|
||||||
err_free:
|
err_free:
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -747,7 +761,7 @@ static int dualsense_get_mac_address(struct dualsense *ds)
|
|||||||
ret = ps_get_report(ds->base.hdev, DS_FEATURE_REPORT_PAIRING_INFO, buf,
|
ret = ps_get_report(ds->base.hdev, DS_FEATURE_REPORT_PAIRING_INFO, buf,
|
||||||
DS_FEATURE_REPORT_PAIRING_INFO_SIZE);
|
DS_FEATURE_REPORT_PAIRING_INFO_SIZE);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
hid_err(ds->base.hdev, "Failed to retrieve DualSense pair: %d\n", ret);
|
hid_err(ds->base.hdev, "Failed to retrieve DualSense pairing info: %d\n", ret);
|
||||||
goto err_free;
|
goto err_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -758,8 +772,8 @@ err_free:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dualsense_init_output_report(struct dualsense *ds,
|
static void dualsense_init_output_report(struct dualsense *ds, struct dualsense_output_report *rp,
|
||||||
struct dualsense_output_report *rp, void *buf)
|
void *buf)
|
||||||
{
|
{
|
||||||
struct hid_device *hdev = ds->base.hdev;
|
struct hid_device *hdev = ds->base.hdev;
|
||||||
|
|
||||||
@@ -768,12 +782,11 @@ static void dualsense_init_output_report(struct dualsense *ds,
|
|||||||
|
|
||||||
memset(bt, 0, sizeof(*bt));
|
memset(bt, 0, sizeof(*bt));
|
||||||
bt->report_id = DS_OUTPUT_REPORT_BT;
|
bt->report_id = DS_OUTPUT_REPORT_BT;
|
||||||
bt->tag = DS_OUTPUT_TAG; /* Tag to be set. It is unclear. */
|
bt->tag = DS_OUTPUT_TAG; /* Tag must be set. Exact meaning is unclear. */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Highest 4-bit is a sequence number, which needs to be
|
* Highest 4-bit is a sequence number, which needs to be increased
|
||||||
* increased every report. Lowest 4-bit is tag and can be
|
* every report. Lowest 4-bit is tag and can be zero for now.
|
||||||
* zero for now.
|
|
||||||
*/
|
*/
|
||||||
bt->seq_tag = (ds->output_seq << 4) | 0x0;
|
bt->seq_tag = (ds->output_seq << 4) | 0x0;
|
||||||
if (++ds->output_seq == 16)
|
if (++ds->output_seq == 16)
|
||||||
@@ -799,17 +812,15 @@ static void dualsense_init_output_report(struct dualsense *ds,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helper function to send DualSense output reports. Applies a CRC
|
* Helper function to send DualSense output reports. Applies a CRC at the end of a report
|
||||||
* at the end of a report for Bluetooth reports.
|
* for Bluetooth reports.
|
||||||
*/
|
*/
|
||||||
static void dualsense_send_output_report(struct dualsense *ds,
|
static void dualsense_send_output_report(struct dualsense *ds,
|
||||||
struct dualsense_output_report *report)
|
struct dualsense_output_report *report)
|
||||||
{
|
{
|
||||||
struct hid_device *hdev = ds->base.hdev;
|
struct hid_device *hdev = ds->base.hdev;
|
||||||
|
|
||||||
/* Bluetooth packets need to be signed
|
/* Bluetooth packets need to be signed with a CRC in the last 4 bytes. */
|
||||||
* with a CRC in the last 4 bytes.
|
|
||||||
*/
|
|
||||||
if (report->bt) {
|
if (report->bt) {
|
||||||
uint32_t crc;
|
uint32_t crc;
|
||||||
uint8_t seed = PS_OUTPUT_CRC32_SEED;
|
uint8_t seed = PS_OUTPUT_CRC32_SEED;
|
||||||
@@ -825,8 +836,7 @@ static void dualsense_send_output_report(struct dualsense *ds,
|
|||||||
|
|
||||||
static void dualsense_output_worker(struct work_struct *work)
|
static void dualsense_output_worker(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct dualsense *ds = container_of(work, struct dualsense,
|
struct dualsense *ds = container_of(work, struct dualsense, output_worker);
|
||||||
output_worker);
|
|
||||||
struct dualsense_output_report report;
|
struct dualsense_output_report report;
|
||||||
struct dualsense_output_report_common *common;
|
struct dualsense_output_report_common *common;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
@@ -839,8 +849,10 @@ static void dualsense_output_worker(struct work_struct *work)
|
|||||||
if (ds->update_rumble) {
|
if (ds->update_rumble) {
|
||||||
/* Select classic rumble style haptics and enable it. */
|
/* Select classic rumble style haptics and enable it. */
|
||||||
common->valid_flag0 |= DS_OUTPUT_VALID_FLAG0_HAPTICS_SELECT;
|
common->valid_flag0 |= DS_OUTPUT_VALID_FLAG0_HAPTICS_SELECT;
|
||||||
common->valid_flag0 |=
|
if (ds->use_vibration_v2)
|
||||||
DS_OUTPUT_VALID_FLAG0_COMPATIBLE_VIBRATION;
|
common->valid_flag2 |= DS_OUTPUT_VALID_FLAG2_COMPATIBLE_VIBRATION2;
|
||||||
|
else
|
||||||
|
common->valid_flag0 |= DS_OUTPUT_VALID_FLAG0_COMPATIBLE_VIBRATION;
|
||||||
common->motor_left = ds->motor_left;
|
common->motor_left = ds->motor_left;
|
||||||
common->motor_right = ds->motor_right;
|
common->motor_right = ds->motor_right;
|
||||||
ds->update_rumble = false;
|
ds->update_rumble = false;
|
||||||
@@ -863,22 +875,17 @@ static void dualsense_output_worker(struct work_struct *work)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ds->update_mic_mute) {
|
if (ds->update_mic_mute) {
|
||||||
common->valid_flag1 |=
|
common->valid_flag1 |= DS_OUTPUT_VALID_FLAG1_MIC_MUTE_LED_CONTROL_ENABLE;
|
||||||
DS_OUTPUT_VALID_FLAG1_MIC_MUTE_LED_CONTROL_ENABLE;
|
|
||||||
common->mute_button_led = ds->mic_muted;
|
common->mute_button_led = ds->mic_muted;
|
||||||
|
|
||||||
if (ds->mic_muted) {
|
if (ds->mic_muted) {
|
||||||
/* Disable microphone */
|
/* Disable microphone */
|
||||||
common->valid_flag1 |=
|
common->valid_flag1 |= DS_OUTPUT_VALID_FLAG1_POWER_SAVE_CONTROL_ENABLE;
|
||||||
DS_OUTPUT_VALID_FLAG1_POWER_SAVE_CONTROL_ENABLE;
|
common->power_save_control |= DS_OUTPUT_POWER_SAVE_CONTROL_MIC_MUTE;
|
||||||
common->power_save_control |=
|
|
||||||
DS_OUTPUT_POWER_SAVE_CONTROL_MIC_MUTE;
|
|
||||||
} else {
|
} else {
|
||||||
/* Enable microphone */
|
/* Enable microphone */
|
||||||
common->valid_flag1 |=
|
common->valid_flag1 |= DS_OUTPUT_VALID_FLAG1_POWER_SAVE_CONTROL_ENABLE;
|
||||||
DS_OUTPUT_VALID_FLAG1_POWER_SAVE_CONTROL_ENABLE;
|
common->power_save_control &= ~DS_OUTPUT_POWER_SAVE_CONTROL_MIC_MUTE;
|
||||||
common->power_save_control &=
|
|
||||||
~DS_OUTPUT_POWER_SAVE_CONTROL_MIC_MUTE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ds->update_mic_mute = false;
|
ds->update_mic_mute = false;
|
||||||
@@ -889,17 +896,17 @@ static void dualsense_output_worker(struct work_struct *work)
|
|||||||
dualsense_send_output_report(ds, &report);
|
dualsense_send_output_report(ds, &report);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dualsense_parse_report(struct ps_device *ps_dev,
|
static int dualsense_parse_report(struct ps_device *ps_dev, struct hid_report *report,
|
||||||
struct hid_report *report, u8 *data, int size)
|
u8 *data, int size)
|
||||||
{
|
{
|
||||||
struct hid_device *hdev = ps_dev->hdev;
|
struct hid_device *hdev = ps_dev->hdev;
|
||||||
struct dualsense *ds = container_of(ps_dev, struct dualsense, base);
|
struct dualsense *ds = container_of(ps_dev, struct dualsense, base);
|
||||||
struct dualsense_input_report *ds_report;
|
struct dualsense_input_report *ds_report;
|
||||||
uint8_t battery_data, battery_capacity, charging_status, value;
|
uint8_t battery_data, battery_capacity, charging_status, value;
|
||||||
int battery_status;
|
int battery_status;
|
||||||
unsigned long flags;
|
|
||||||
bool btn_mic_state;
|
|
||||||
uint32_t sensor_timestamp;
|
uint32_t sensor_timestamp;
|
||||||
|
bool btn_mic_state;
|
||||||
|
unsigned long flags;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -910,14 +917,12 @@ static int dualsense_parse_report(struct ps_device *ps_dev,
|
|||||||
if (hdev->bus == BUS_USB && report->id == DS_INPUT_REPORT_USB &&
|
if (hdev->bus == BUS_USB && report->id == DS_INPUT_REPORT_USB &&
|
||||||
size == DS_INPUT_REPORT_USB_SIZE) {
|
size == DS_INPUT_REPORT_USB_SIZE) {
|
||||||
ds_report = (struct dualsense_input_report *)&data[1];
|
ds_report = (struct dualsense_input_report *)&data[1];
|
||||||
} else if (hdev->bus == BUS_BLUETOOTH &&
|
} else if (hdev->bus == BUS_BLUETOOTH && report->id == DS_INPUT_REPORT_BT &&
|
||||||
report->id == DS_INPUT_REPORT_BT &&
|
|
||||||
size == DS_INPUT_REPORT_BT_SIZE) {
|
size == DS_INPUT_REPORT_BT_SIZE) {
|
||||||
/* Last 4 bytes of input report contain crc32 */
|
/* Last 4 bytes of input report contain crc32 */
|
||||||
uint32_t report_crc = get_unaligned_le32(&data[size - 4]);
|
uint32_t report_crc = get_unaligned_le32(&data[size - 4]);
|
||||||
|
|
||||||
if (!ps_check_crc32(PS_INPUT_CRC32_SEED, data, size - 4,
|
if (!ps_check_crc32(PS_INPUT_CRC32_SEED, data, size - 4, report_crc)) {
|
||||||
report_crc)) {
|
|
||||||
hid_err(hdev, "DualSense input CRC's check failed\n");
|
hid_err(hdev, "DualSense input CRC's check failed\n");
|
||||||
return -EILSEQ;
|
return -EILSEQ;
|
||||||
}
|
}
|
||||||
@@ -957,9 +962,8 @@ static int dualsense_parse_report(struct ps_device *ps_dev,
|
|||||||
input_sync(ds->gamepad);
|
input_sync(ds->gamepad);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The DualSense has an internal microphone, which can bemuted
|
* The DualSense has an internal microphone, which can be muted through a mute button
|
||||||
* through a mute button on the device. The driver is expected
|
* on the device. The driver is expected to read the button state and program the device
|
||||||
* to read the button state and program the device
|
|
||||||
* to mute/unmute audio at the hardware level.
|
* to mute/unmute audio at the hardware level.
|
||||||
*/
|
*/
|
||||||
btn_mic_state = !!(ds_report->buttons[2] & DS_BUTTONS2_MIC_MUTE);
|
btn_mic_state = !!(ds_report->buttons[2] & DS_BUTTONS2_MIC_MUTE);
|
||||||
@@ -981,8 +985,7 @@ static int dualsense_parse_report(struct ps_device *ps_dev,
|
|||||||
raw_data - ds->gyro_calib_data[i].bias,
|
raw_data - ds->gyro_calib_data[i].bias,
|
||||||
ds->gyro_calib_data[i].sens_denom);
|
ds->gyro_calib_data[i].sens_denom);
|
||||||
|
|
||||||
input_report_abs(ds->sensors, ds->gyro_calib_data[i].abs_code,
|
input_report_abs(ds->sensors, ds->gyro_calib_data[i].abs_code, calib_data);
|
||||||
calib_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse and calibrate accelerometer data. */
|
/* Parse and calibrate accelerometer data. */
|
||||||
@@ -992,35 +995,30 @@ static int dualsense_parse_report(struct ps_device *ps_dev,
|
|||||||
raw_data - ds->accel_calib_data[i].bias,
|
raw_data - ds->accel_calib_data[i].bias,
|
||||||
ds->accel_calib_data[i].sens_denom);
|
ds->accel_calib_data[i].sens_denom);
|
||||||
|
|
||||||
input_report_abs(ds->sensors, ds->accel_calib_data[i].abs_code,
|
input_report_abs(ds->sensors, ds->accel_calib_data[i].abs_code, calib_data);
|
||||||
calib_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert timestamp (in 0.33us unit) to timestamp_us */
|
/* Convert timestamp (in 0.33us unit) to timestamp_us */
|
||||||
sensor_timestamp = le32_to_cpu(ds_report->sensor_timestamp);
|
sensor_timestamp = le32_to_cpu(ds_report->sensor_timestamp);
|
||||||
if (!ds->sensor_timestamp_initialized) {
|
if (!ds->sensor_timestamp_initialized) {
|
||||||
ds->sensor_timestamp_us =
|
ds->sensor_timestamp_us = DIV_ROUND_CLOSEST(sensor_timestamp, 3);
|
||||||
DIV_ROUND_CLOSEST(sensor_timestamp, 3);
|
|
||||||
ds->sensor_timestamp_initialized = true;
|
ds->sensor_timestamp_initialized = true;
|
||||||
} else {
|
} else {
|
||||||
uint32_t delta;
|
uint32_t delta;
|
||||||
|
|
||||||
if (ds->prev_sensor_timestamp > sensor_timestamp)
|
if (ds->prev_sensor_timestamp > sensor_timestamp)
|
||||||
delta = (U32_MAX - ds->prev_sensor_timestamp +
|
delta = (U32_MAX - ds->prev_sensor_timestamp + sensor_timestamp + 1);
|
||||||
sensor_timestamp + 1);
|
|
||||||
else
|
else
|
||||||
delta = sensor_timestamp - ds->prev_sensor_timestamp;
|
delta = sensor_timestamp - ds->prev_sensor_timestamp;
|
||||||
ds->sensor_timestamp_us += DIV_ROUND_CLOSEST(delta, 3);
|
ds->sensor_timestamp_us += DIV_ROUND_CLOSEST(delta, 3);
|
||||||
}
|
}
|
||||||
ds->prev_sensor_timestamp = sensor_timestamp;
|
ds->prev_sensor_timestamp = sensor_timestamp;
|
||||||
input_event(ds->sensors, EV_MSC, MSC_TIMESTAMP,
|
input_event(ds->sensors, EV_MSC, MSC_TIMESTAMP, ds->sensor_timestamp_us);
|
||||||
ds->sensor_timestamp_us);
|
|
||||||
input_sync(ds->sensors);
|
input_sync(ds->sensors);
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(ds_report->points); i++) {
|
for (i = 0; i < ARRAY_SIZE(ds_report->points); i++) {
|
||||||
struct dualsense_touch_point *point = &ds_report->points[i];
|
struct dualsense_touch_point *point = &ds_report->points[i];
|
||||||
bool active = (point->contact &
|
bool active = (point->contact & DS_TOUCH_POINT_INACTIVE) ? false : true;
|
||||||
DS_TOUCH_POINT_INACTIVE) ? false : true;
|
|
||||||
|
|
||||||
input_mt_slot(ds->touchpad, i);
|
input_mt_slot(ds->touchpad, i);
|
||||||
input_mt_report_slot_state(ds->touchpad, MT_TOOL_FINGER, active);
|
input_mt_report_slot_state(ds->touchpad, MT_TOOL_FINGER, active);
|
||||||
@@ -1076,8 +1074,7 @@ static int dualsense_parse_report(struct ps_device *ps_dev,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dualsense_play_effect(struct input_dev *dev,
|
static int dualsense_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect)
|
||||||
void *data, struct ff_effect *effect)
|
|
||||||
{
|
{
|
||||||
struct hid_device *hdev = input_get_drvdata(dev);
|
struct hid_device *hdev = input_get_drvdata(dev);
|
||||||
struct dualsense *ds = hid_get_drvdata(hdev);
|
struct dualsense *ds = hid_get_drvdata(hdev);
|
||||||
@@ -1181,8 +1178,7 @@ static struct ps_device *dualsense_create(struct hid_device *hdev)
|
|||||||
hid_set_drvdata(hdev, ds);
|
hid_set_drvdata(hdev, ds);
|
||||||
|
|
||||||
max_output_report_size = sizeof(struct dualsense_output_report_bt);
|
max_output_report_size = sizeof(struct dualsense_output_report_bt);
|
||||||
ds->output_report_dmabuf = devm_kzalloc(&hdev->dev,
|
ds->output_report_dmabuf = devm_kzalloc(&hdev->dev, max_output_report_size, GFP_KERNEL);
|
||||||
max_output_report_size, GFP_KERNEL);
|
|
||||||
if (!ds->output_report_dmabuf)
|
if (!ds->output_report_dmabuf)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
@@ -1199,6 +1195,21 @@ static struct ps_device *dualsense_create(struct hid_device *hdev)
|
|||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Original DualSense firmware simulated classic controller rumble through
|
||||||
|
* its new haptics hardware. It felt different from classic rumble users
|
||||||
|
* were used to. Since then new firmwares were introduced to change behavior
|
||||||
|
* and make this new 'v2' behavior default on PlayStation and other platforms.
|
||||||
|
* The original DualSense requires a new enough firmware as bundled with PS5
|
||||||
|
* software released in 2021. DualSense edge supports it out of the box.
|
||||||
|
* Both devices also support the old mode, but it is not really used.
|
||||||
|
*/
|
||||||
|
if (hdev->product == USB_DEVICE_ID_SONY_PS5_CONTROLLER) {
|
||||||
|
/* Feature version 2.21 introduced new vibration method. */
|
||||||
|
ds->use_vibration_v2 = ds->update_version >= DS_FEATURE_VERSION(2, 21);
|
||||||
|
} else if (hdev->product == USB_DEVICE_ID_SONY_PS5_CONTROLLER_2) {
|
||||||
|
ds->use_vibration_v2 = true;
|
||||||
|
}
|
||||||
|
|
||||||
ret = ps_devices_list_add(ps_dev);
|
ret = ps_devices_list_add(ps_dev);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
@@ -1222,8 +1233,7 @@ static struct ps_device *dualsense_create(struct hid_device *hdev)
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ds->touchpad = ps_touchpad_create(hdev, DS_TOUCHPAD_WIDTH,
|
ds->touchpad = ps_touchpad_create(hdev, DS_TOUCHPAD_WIDTH, DS_TOUCHPAD_HEIGHT, 2);
|
||||||
DS_TOUCHPAD_HEIGHT, 2);
|
|
||||||
if (IS_ERR(ds->touchpad)) {
|
if (IS_ERR(ds->touchpad)) {
|
||||||
ret = PTR_ERR(ds->touchpad);
|
ret = PTR_ERR(ds->touchpad);
|
||||||
goto err;
|
goto err;
|
||||||
@@ -1301,7 +1311,8 @@ static int ps_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||||||
goto err_stop;
|
goto err_stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hdev->product == USB_DEVICE_ID_SONY_PS5_CONTROLLER) {
|
if (hdev->product == USB_DEVICE_ID_SONY_PS5_CONTROLLER ||
|
||||||
|
hdev->product == USB_DEVICE_ID_SONY_PS5_CONTROLLER_2) {
|
||||||
dev = dualsense_create(hdev);
|
dev = dualsense_create(hdev);
|
||||||
if (IS_ERR(dev)) {
|
if (IS_ERR(dev)) {
|
||||||
hid_err(hdev, "Failed to create dualsense.\n");
|
hid_err(hdev, "Failed to create dualsense.\n");
|
||||||
@@ -1339,6 +1350,8 @@ static void ps_remove(struct hid_device *hdev)
|
|||||||
static const struct hid_device_id ps_devices[] = {
|
static const struct hid_device_id ps_devices[] = {
|
||||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER) },
|
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER) },
|
||||||
|
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER_2) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER_2) },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(hid, ps_devices);
|
MODULE_DEVICE_TABLE(hid, ps_devices);
|
||||||
@@ -1367,4 +1380,4 @@ module_exit(ps_exit);
|
|||||||
|
|
||||||
MODULE_AUTHOR("Sony Interactive Entertainment");
|
MODULE_AUTHOR("Sony Interactive Entertainment");
|
||||||
MODULE_DESCRIPTION("HID Driver for PlayStation peripherals.");
|
MODULE_DESCRIPTION("HID Driver for PlayStation peripherals.");
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL");
|
||||||
@@ -58,7 +58,6 @@
|
|||||||
/* flags */
|
/* flags */
|
||||||
#define I2C_HID_STARTED 0
|
#define I2C_HID_STARTED 0
|
||||||
#define I2C_HID_RESET_PENDING 1
|
#define I2C_HID_RESET_PENDING 1
|
||||||
#define I2C_HID_READ_PENDING 2
|
|
||||||
|
|
||||||
#define I2C_HID_PWR_ON 0x00
|
#define I2C_HID_PWR_ON 0x00
|
||||||
#define I2C_HID_PWR_SLEEP 0x01
|
#define I2C_HID_PWR_SLEEP 0x01
|
||||||
@@ -259,7 +258,6 @@ static int __i2c_hid_command(struct i2c_client *client,
|
|||||||
msg[1].len = data_len;
|
msg[1].len = data_len;
|
||||||
msg[1].buf = buf_recv;
|
msg[1].buf = buf_recv;
|
||||||
msg_num = 2;
|
msg_num = 2;
|
||||||
set_bit(I2C_HID_READ_PENDING, &ihid->flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wait)
|
if (wait)
|
||||||
@@ -267,9 +265,6 @@ static int __i2c_hid_command(struct i2c_client *client,
|
|||||||
|
|
||||||
ret = i2c_transfer(client->adapter, msg, msg_num);
|
ret = i2c_transfer(client->adapter, msg, msg_num);
|
||||||
|
|
||||||
if (data_len > 0)
|
|
||||||
clear_bit(I2C_HID_READ_PENDING, &ihid->flags);
|
|
||||||
|
|
||||||
if (ret != msg_num)
|
if (ret != msg_num)
|
||||||
return ret < 0 ? ret : -EIO;
|
return ret < 0 ? ret : -EIO;
|
||||||
|
|
||||||
@@ -550,9 +545,6 @@ static irqreturn_t i2c_hid_irq(int irq, void *dev_id)
|
|||||||
{
|
{
|
||||||
struct i2c_hid *ihid = dev_id;
|
struct i2c_hid *ihid = dev_id;
|
||||||
|
|
||||||
if (test_bit(I2C_HID_READ_PENDING, &ihid->flags))
|
|
||||||
return IRQ_HANDLED;
|
|
||||||
|
|
||||||
i2c_hid_get_input(ihid);
|
i2c_hid_get_input(ihid);
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
|
|||||||
@@ -1872,13 +1872,18 @@ static int i2c_check_for_quirks(struct i2c_adapter *adap, struct i2c_msg *msgs,
|
|||||||
* Returns negative errno, else the number of messages executed.
|
* Returns negative errno, else the number of messages executed.
|
||||||
*
|
*
|
||||||
* Adapter lock must be held when calling this function. No debug logging
|
* Adapter lock must be held when calling this function. No debug logging
|
||||||
* takes place. adap->algo->master_xfer existence isn't checked.
|
* takes place.
|
||||||
*/
|
*/
|
||||||
int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
||||||
{
|
{
|
||||||
unsigned long orig_jiffies;
|
unsigned long orig_jiffies;
|
||||||
int ret, try;
|
int ret, try;
|
||||||
|
|
||||||
|
if (!adap->algo->master_xfer) {
|
||||||
|
dev_dbg(&adap->dev, "I2C level transfers not supported\n");
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
if (WARN_ON(!msgs || num < 1))
|
if (WARN_ON(!msgs || num < 1))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
|||||||
@@ -216,7 +216,8 @@ static int process_pma_cmd(struct mlx5_ib_dev *dev, u8 port_num,
|
|||||||
mdev = dev->mdev;
|
mdev = dev->mdev;
|
||||||
mdev_port_num = 1;
|
mdev_port_num = 1;
|
||||||
}
|
}
|
||||||
if (MLX5_CAP_GEN(dev->mdev, num_ports) == 1) {
|
if (MLX5_CAP_GEN(dev->mdev, num_ports) == 1 &&
|
||||||
|
!mlx5_core_mp_enabled(mdev)) {
|
||||||
/* set local port to one for Function-Per-Port HCA. */
|
/* set local port to one for Function-Per-Port HCA. */
|
||||||
mdev = dev->mdev;
|
mdev = dev->mdev;
|
||||||
mdev_port_num = 1;
|
mdev_port_num = 1;
|
||||||
|
|||||||
@@ -2994,13 +2994,8 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq
|
|||||||
set_bit(i, bitmap);
|
set_bit(i, bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err) {
|
if (err)
|
||||||
if (i > 0)
|
its_vpe_irq_domain_free(domain, virq, i);
|
||||||
its_vpe_irq_domain_free(domain, virq, i);
|
|
||||||
|
|
||||||
its_lpi_free(bitmap, base, nr_ids);
|
|
||||||
its_free_prop_table(vprop_page);
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
#include "dm.h"
|
#include "dm.h"
|
||||||
|
|
||||||
#define DM_RESERVED_MAX_IOS 1024
|
#define DM_RESERVED_MAX_IOS 1024
|
||||||
|
#define DM_MAX_TARGETS 1048576
|
||||||
|
#define DM_MAX_TARGET_PARAMS 1024
|
||||||
|
|
||||||
struct dm_kobject_holder {
|
struct dm_kobject_holder {
|
||||||
struct kobject kobj;
|
struct kobject kobj;
|
||||||
|
|||||||
@@ -1734,7 +1734,8 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern
|
|||||||
if (copy_from_user(param_kernel, user, minimum_data_size))
|
if (copy_from_user(param_kernel, user, minimum_data_size))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
if (param_kernel->data_size < minimum_data_size)
|
if (unlikely(param_kernel->data_size < minimum_data_size) ||
|
||||||
|
unlikely(param_kernel->data_size > DM_MAX_TARGETS * DM_MAX_TARGET_PARAMS))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
secure_data = param_kernel->flags & DM_SECURE_DATA_FLAG;
|
secure_data = param_kernel->flags & DM_SECURE_DATA_FLAG;
|
||||||
|
|||||||
@@ -190,7 +190,12 @@ static int alloc_targets(struct dm_table *t, unsigned int num)
|
|||||||
int dm_table_create(struct dm_table **result, fmode_t mode,
|
int dm_table_create(struct dm_table **result, fmode_t mode,
|
||||||
unsigned num_targets, struct mapped_device *md)
|
unsigned num_targets, struct mapped_device *md)
|
||||||
{
|
{
|
||||||
struct dm_table *t = kzalloc(sizeof(*t), GFP_KERNEL);
|
struct dm_table *t;
|
||||||
|
|
||||||
|
if (num_targets > DM_MAX_TARGETS)
|
||||||
|
return -EOVERFLOW;
|
||||||
|
|
||||||
|
t = kzalloc(sizeof(*t), GFP_KERNEL);
|
||||||
|
|
||||||
if (!t)
|
if (!t)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@@ -205,7 +210,7 @@ int dm_table_create(struct dm_table **result, fmode_t mode,
|
|||||||
|
|
||||||
if (!num_targets) {
|
if (!num_targets) {
|
||||||
kfree(t);
|
kfree(t);
|
||||||
return -ENOMEM;
|
return -EOVERFLOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (alloc_targets(t, num_targets)) {
|
if (alloc_targets(t, num_targets)) {
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ static unsigned long doc_locations[] __initdata = {
|
|||||||
0xe8000, 0xea000, 0xec000, 0xee000,
|
0xe8000, 0xea000, 0xec000, 0xee000,
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
0xffffffff };
|
};
|
||||||
|
|
||||||
static struct mtd_info *doclist = NULL;
|
static struct mtd_info *doclist = NULL;
|
||||||
|
|
||||||
@@ -1678,7 +1678,7 @@ static int __init init_nanddoc(void)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; (doc_locations[i] != 0xffffffff); i++) {
|
for (i = 0; i < ARRAY_SIZE(doc_locations); i++) {
|
||||||
doc_probe(doc_locations[i]);
|
doc_probe(doc_locations[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3933,6 +3933,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||||||
.family = MV88E6XXX_FAMILY_6097,
|
.family = MV88E6XXX_FAMILY_6097,
|
||||||
.name = "Marvell 88E6085",
|
.name = "Marvell 88E6085",
|
||||||
.num_databases = 4096,
|
.num_databases = 4096,
|
||||||
|
.num_macs = 8192,
|
||||||
.num_ports = 10,
|
.num_ports = 10,
|
||||||
.num_internal_phys = 5,
|
.num_internal_phys = 5,
|
||||||
.max_vid = 4095,
|
.max_vid = 4095,
|
||||||
@@ -3955,6 +3956,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||||||
.family = MV88E6XXX_FAMILY_6095,
|
.family = MV88E6XXX_FAMILY_6095,
|
||||||
.name = "Marvell 88E6095/88E6095F",
|
.name = "Marvell 88E6095/88E6095F",
|
||||||
.num_databases = 256,
|
.num_databases = 256,
|
||||||
|
.num_macs = 8192,
|
||||||
.num_ports = 11,
|
.num_ports = 11,
|
||||||
.num_internal_phys = 0,
|
.num_internal_phys = 0,
|
||||||
.max_vid = 4095,
|
.max_vid = 4095,
|
||||||
@@ -3975,6 +3977,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||||||
.family = MV88E6XXX_FAMILY_6097,
|
.family = MV88E6XXX_FAMILY_6097,
|
||||||
.name = "Marvell 88E6097/88E6097F",
|
.name = "Marvell 88E6097/88E6097F",
|
||||||
.num_databases = 4096,
|
.num_databases = 4096,
|
||||||
|
.num_macs = 8192,
|
||||||
.num_ports = 11,
|
.num_ports = 11,
|
||||||
.num_internal_phys = 8,
|
.num_internal_phys = 8,
|
||||||
.max_vid = 4095,
|
.max_vid = 4095,
|
||||||
@@ -3997,6 +4000,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||||||
.family = MV88E6XXX_FAMILY_6165,
|
.family = MV88E6XXX_FAMILY_6165,
|
||||||
.name = "Marvell 88E6123",
|
.name = "Marvell 88E6123",
|
||||||
.num_databases = 4096,
|
.num_databases = 4096,
|
||||||
|
.num_macs = 1024,
|
||||||
.num_ports = 3,
|
.num_ports = 3,
|
||||||
.num_internal_phys = 5,
|
.num_internal_phys = 5,
|
||||||
.max_vid = 4095,
|
.max_vid = 4095,
|
||||||
@@ -4019,6 +4023,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||||||
.family = MV88E6XXX_FAMILY_6185,
|
.family = MV88E6XXX_FAMILY_6185,
|
||||||
.name = "Marvell 88E6131",
|
.name = "Marvell 88E6131",
|
||||||
.num_databases = 256,
|
.num_databases = 256,
|
||||||
|
.num_macs = 8192,
|
||||||
.num_ports = 8,
|
.num_ports = 8,
|
||||||
.num_internal_phys = 0,
|
.num_internal_phys = 0,
|
||||||
.max_vid = 4095,
|
.max_vid = 4095,
|
||||||
@@ -4038,7 +4043,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||||||
.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6141,
|
.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6141,
|
||||||
.family = MV88E6XXX_FAMILY_6341,
|
.family = MV88E6XXX_FAMILY_6341,
|
||||||
.name = "Marvell 88E6141",
|
.name = "Marvell 88E6141",
|
||||||
.num_databases = 4096,
|
.num_databases = 256,
|
||||||
|
.num_macs = 2048,
|
||||||
.num_ports = 6,
|
.num_ports = 6,
|
||||||
.num_internal_phys = 5,
|
.num_internal_phys = 5,
|
||||||
.num_gpio = 11,
|
.num_gpio = 11,
|
||||||
@@ -4062,6 +4068,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||||||
.family = MV88E6XXX_FAMILY_6165,
|
.family = MV88E6XXX_FAMILY_6165,
|
||||||
.name = "Marvell 88E6161",
|
.name = "Marvell 88E6161",
|
||||||
.num_databases = 4096,
|
.num_databases = 4096,
|
||||||
|
.num_macs = 1024,
|
||||||
.num_ports = 6,
|
.num_ports = 6,
|
||||||
.num_internal_phys = 5,
|
.num_internal_phys = 5,
|
||||||
.max_vid = 4095,
|
.max_vid = 4095,
|
||||||
@@ -4085,6 +4092,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||||||
.family = MV88E6XXX_FAMILY_6165,
|
.family = MV88E6XXX_FAMILY_6165,
|
||||||
.name = "Marvell 88E6165",
|
.name = "Marvell 88E6165",
|
||||||
.num_databases = 4096,
|
.num_databases = 4096,
|
||||||
|
.num_macs = 8192,
|
||||||
.num_ports = 6,
|
.num_ports = 6,
|
||||||
.num_internal_phys = 0,
|
.num_internal_phys = 0,
|
||||||
.max_vid = 4095,
|
.max_vid = 4095,
|
||||||
@@ -4108,6 +4116,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||||||
.family = MV88E6XXX_FAMILY_6351,
|
.family = MV88E6XXX_FAMILY_6351,
|
||||||
.name = "Marvell 88E6171",
|
.name = "Marvell 88E6171",
|
||||||
.num_databases = 4096,
|
.num_databases = 4096,
|
||||||
|
.num_macs = 8192,
|
||||||
.num_ports = 7,
|
.num_ports = 7,
|
||||||
.num_internal_phys = 5,
|
.num_internal_phys = 5,
|
||||||
.max_vid = 4095,
|
.max_vid = 4095,
|
||||||
@@ -4130,6 +4139,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||||||
.family = MV88E6XXX_FAMILY_6352,
|
.family = MV88E6XXX_FAMILY_6352,
|
||||||
.name = "Marvell 88E6172",
|
.name = "Marvell 88E6172",
|
||||||
.num_databases = 4096,
|
.num_databases = 4096,
|
||||||
|
.num_macs = 8192,
|
||||||
.num_ports = 7,
|
.num_ports = 7,
|
||||||
.num_internal_phys = 5,
|
.num_internal_phys = 5,
|
||||||
.num_gpio = 15,
|
.num_gpio = 15,
|
||||||
@@ -4153,6 +4163,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||||||
.family = MV88E6XXX_FAMILY_6351,
|
.family = MV88E6XXX_FAMILY_6351,
|
||||||
.name = "Marvell 88E6175",
|
.name = "Marvell 88E6175",
|
||||||
.num_databases = 4096,
|
.num_databases = 4096,
|
||||||
|
.num_macs = 8192,
|
||||||
.num_ports = 7,
|
.num_ports = 7,
|
||||||
.num_internal_phys = 5,
|
.num_internal_phys = 5,
|
||||||
.max_vid = 4095,
|
.max_vid = 4095,
|
||||||
@@ -4175,6 +4186,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||||||
.family = MV88E6XXX_FAMILY_6352,
|
.family = MV88E6XXX_FAMILY_6352,
|
||||||
.name = "Marvell 88E6176",
|
.name = "Marvell 88E6176",
|
||||||
.num_databases = 4096,
|
.num_databases = 4096,
|
||||||
|
.num_macs = 8192,
|
||||||
.num_ports = 7,
|
.num_ports = 7,
|
||||||
.num_internal_phys = 5,
|
.num_internal_phys = 5,
|
||||||
.num_gpio = 15,
|
.num_gpio = 15,
|
||||||
@@ -4198,6 +4210,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||||||
.family = MV88E6XXX_FAMILY_6185,
|
.family = MV88E6XXX_FAMILY_6185,
|
||||||
.name = "Marvell 88E6185",
|
.name = "Marvell 88E6185",
|
||||||
.num_databases = 256,
|
.num_databases = 256,
|
||||||
|
.num_macs = 8192,
|
||||||
.num_ports = 10,
|
.num_ports = 10,
|
||||||
.num_internal_phys = 0,
|
.num_internal_phys = 0,
|
||||||
.max_vid = 4095,
|
.max_vid = 4095,
|
||||||
@@ -4218,6 +4231,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||||||
.family = MV88E6XXX_FAMILY_6390,
|
.family = MV88E6XXX_FAMILY_6390,
|
||||||
.name = "Marvell 88E6190",
|
.name = "Marvell 88E6190",
|
||||||
.num_databases = 4096,
|
.num_databases = 4096,
|
||||||
|
.num_macs = 16384,
|
||||||
.num_ports = 11, /* 10 + Z80 */
|
.num_ports = 11, /* 10 + Z80 */
|
||||||
.num_internal_phys = 9,
|
.num_internal_phys = 9,
|
||||||
.num_gpio = 16,
|
.num_gpio = 16,
|
||||||
@@ -4241,6 +4255,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||||||
.family = MV88E6XXX_FAMILY_6390,
|
.family = MV88E6XXX_FAMILY_6390,
|
||||||
.name = "Marvell 88E6190X",
|
.name = "Marvell 88E6190X",
|
||||||
.num_databases = 4096,
|
.num_databases = 4096,
|
||||||
|
.num_macs = 16384,
|
||||||
.num_ports = 11, /* 10 + Z80 */
|
.num_ports = 11, /* 10 + Z80 */
|
||||||
.num_internal_phys = 9,
|
.num_internal_phys = 9,
|
||||||
.num_gpio = 16,
|
.num_gpio = 16,
|
||||||
@@ -4264,6 +4279,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||||||
.family = MV88E6XXX_FAMILY_6390,
|
.family = MV88E6XXX_FAMILY_6390,
|
||||||
.name = "Marvell 88E6191",
|
.name = "Marvell 88E6191",
|
||||||
.num_databases = 4096,
|
.num_databases = 4096,
|
||||||
|
.num_macs = 16384,
|
||||||
.num_ports = 11, /* 10 + Z80 */
|
.num_ports = 11, /* 10 + Z80 */
|
||||||
.num_internal_phys = 9,
|
.num_internal_phys = 9,
|
||||||
.max_vid = 8191,
|
.max_vid = 8191,
|
||||||
@@ -4287,6 +4303,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||||||
.family = MV88E6XXX_FAMILY_6352,
|
.family = MV88E6XXX_FAMILY_6352,
|
||||||
.name = "Marvell 88E6240",
|
.name = "Marvell 88E6240",
|
||||||
.num_databases = 4096,
|
.num_databases = 4096,
|
||||||
|
.num_macs = 8192,
|
||||||
.num_ports = 7,
|
.num_ports = 7,
|
||||||
.num_internal_phys = 5,
|
.num_internal_phys = 5,
|
||||||
.num_gpio = 15,
|
.num_gpio = 15,
|
||||||
@@ -4335,6 +4352,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||||||
.family = MV88E6XXX_FAMILY_6320,
|
.family = MV88E6XXX_FAMILY_6320,
|
||||||
.name = "Marvell 88E6320",
|
.name = "Marvell 88E6320",
|
||||||
.num_databases = 4096,
|
.num_databases = 4096,
|
||||||
|
.num_macs = 8192,
|
||||||
.num_ports = 7,
|
.num_ports = 7,
|
||||||
.num_internal_phys = 5,
|
.num_internal_phys = 5,
|
||||||
.num_gpio = 15,
|
.num_gpio = 15,
|
||||||
@@ -4359,6 +4377,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||||||
.family = MV88E6XXX_FAMILY_6320,
|
.family = MV88E6XXX_FAMILY_6320,
|
||||||
.name = "Marvell 88E6321",
|
.name = "Marvell 88E6321",
|
||||||
.num_databases = 4096,
|
.num_databases = 4096,
|
||||||
|
.num_macs = 8192,
|
||||||
.num_ports = 7,
|
.num_ports = 7,
|
||||||
.num_internal_phys = 5,
|
.num_internal_phys = 5,
|
||||||
.num_gpio = 15,
|
.num_gpio = 15,
|
||||||
@@ -4381,7 +4400,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||||||
.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6341,
|
.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6341,
|
||||||
.family = MV88E6XXX_FAMILY_6341,
|
.family = MV88E6XXX_FAMILY_6341,
|
||||||
.name = "Marvell 88E6341",
|
.name = "Marvell 88E6341",
|
||||||
.num_databases = 4096,
|
.num_databases = 256,
|
||||||
|
.num_macs = 2048,
|
||||||
.num_internal_phys = 5,
|
.num_internal_phys = 5,
|
||||||
.num_ports = 6,
|
.num_ports = 6,
|
||||||
.num_gpio = 11,
|
.num_gpio = 11,
|
||||||
@@ -4406,6 +4426,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||||||
.family = MV88E6XXX_FAMILY_6351,
|
.family = MV88E6XXX_FAMILY_6351,
|
||||||
.name = "Marvell 88E6350",
|
.name = "Marvell 88E6350",
|
||||||
.num_databases = 4096,
|
.num_databases = 4096,
|
||||||
|
.num_macs = 8192,
|
||||||
.num_ports = 7,
|
.num_ports = 7,
|
||||||
.num_internal_phys = 5,
|
.num_internal_phys = 5,
|
||||||
.max_vid = 4095,
|
.max_vid = 4095,
|
||||||
@@ -4428,6 +4449,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||||||
.family = MV88E6XXX_FAMILY_6351,
|
.family = MV88E6XXX_FAMILY_6351,
|
||||||
.name = "Marvell 88E6351",
|
.name = "Marvell 88E6351",
|
||||||
.num_databases = 4096,
|
.num_databases = 4096,
|
||||||
|
.num_macs = 8192,
|
||||||
.num_ports = 7,
|
.num_ports = 7,
|
||||||
.num_internal_phys = 5,
|
.num_internal_phys = 5,
|
||||||
.max_vid = 4095,
|
.max_vid = 4095,
|
||||||
@@ -4450,6 +4472,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||||||
.family = MV88E6XXX_FAMILY_6352,
|
.family = MV88E6XXX_FAMILY_6352,
|
||||||
.name = "Marvell 88E6352",
|
.name = "Marvell 88E6352",
|
||||||
.num_databases = 4096,
|
.num_databases = 4096,
|
||||||
|
.num_macs = 8192,
|
||||||
.num_ports = 7,
|
.num_ports = 7,
|
||||||
.num_internal_phys = 5,
|
.num_internal_phys = 5,
|
||||||
.num_gpio = 15,
|
.num_gpio = 15,
|
||||||
@@ -4473,6 +4496,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||||||
.family = MV88E6XXX_FAMILY_6390,
|
.family = MV88E6XXX_FAMILY_6390,
|
||||||
.name = "Marvell 88E6390",
|
.name = "Marvell 88E6390",
|
||||||
.num_databases = 4096,
|
.num_databases = 4096,
|
||||||
|
.num_macs = 16384,
|
||||||
.num_ports = 11, /* 10 + Z80 */
|
.num_ports = 11, /* 10 + Z80 */
|
||||||
.num_internal_phys = 9,
|
.num_internal_phys = 9,
|
||||||
.num_gpio = 16,
|
.num_gpio = 16,
|
||||||
@@ -4496,6 +4520,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||||||
.family = MV88E6XXX_FAMILY_6390,
|
.family = MV88E6XXX_FAMILY_6390,
|
||||||
.name = "Marvell 88E6390X",
|
.name = "Marvell 88E6390X",
|
||||||
.num_databases = 4096,
|
.num_databases = 4096,
|
||||||
|
.num_macs = 16384,
|
||||||
.num_ports = 11, /* 10 + Z80 */
|
.num_ports = 11, /* 10 + Z80 */
|
||||||
.num_internal_phys = 9,
|
.num_internal_phys = 9,
|
||||||
.num_gpio = 16,
|
.num_gpio = 16,
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ struct mv88e6xxx_info {
|
|||||||
u16 prod_num;
|
u16 prod_num;
|
||||||
const char *name;
|
const char *name;
|
||||||
unsigned int num_databases;
|
unsigned int num_databases;
|
||||||
|
unsigned int num_macs;
|
||||||
unsigned int num_ports;
|
unsigned int num_ports;
|
||||||
unsigned int num_internal_phys;
|
unsigned int num_internal_phys;
|
||||||
unsigned int num_gpio;
|
unsigned int num_gpio;
|
||||||
@@ -559,6 +560,11 @@ static inline unsigned int mv88e6xxx_num_databases(struct mv88e6xxx_chip *chip)
|
|||||||
return chip->info->num_databases;
|
return chip->info->num_databases;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline unsigned int mv88e6xxx_num_macs(struct mv88e6xxx_chip *chip)
|
||||||
|
{
|
||||||
|
return chip->info->num_macs;
|
||||||
|
}
|
||||||
|
|
||||||
static inline unsigned int mv88e6xxx_num_ports(struct mv88e6xxx_chip *chip)
|
static inline unsigned int mv88e6xxx_num_ports(struct mv88e6xxx_chip *chip)
|
||||||
{
|
{
|
||||||
return chip->info->num_ports;
|
return chip->info->num_ports;
|
||||||
|
|||||||
@@ -2033,12 +2033,14 @@ static int b44_set_pauseparam(struct net_device *dev,
|
|||||||
bp->flags |= B44_FLAG_TX_PAUSE;
|
bp->flags |= B44_FLAG_TX_PAUSE;
|
||||||
else
|
else
|
||||||
bp->flags &= ~B44_FLAG_TX_PAUSE;
|
bp->flags &= ~B44_FLAG_TX_PAUSE;
|
||||||
if (bp->flags & B44_FLAG_PAUSE_AUTO) {
|
if (netif_running(dev)) {
|
||||||
b44_halt(bp);
|
if (bp->flags & B44_FLAG_PAUSE_AUTO) {
|
||||||
b44_init_rings(bp);
|
b44_halt(bp);
|
||||||
b44_init_hw(bp, B44_FULL_RESET);
|
b44_init_rings(bp);
|
||||||
} else {
|
b44_init_hw(bp, B44_FULL_RESET);
|
||||||
__b44_set_flow_ctrl(bp, bp->flags);
|
} else {
|
||||||
|
__b44_set_flow_ctrl(bp, bp->flags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
spin_unlock_irq(&bp->lock);
|
spin_unlock_irq(&bp->lock);
|
||||||
|
|
||||||
|
|||||||
@@ -2806,7 +2806,7 @@ static void bcmgenet_set_hw_addr(struct bcmgenet_priv *priv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Returns a reusable dma control register value */
|
/* Returns a reusable dma control register value */
|
||||||
static u32 bcmgenet_dma_disable(struct bcmgenet_priv *priv)
|
static u32 bcmgenet_dma_disable(struct bcmgenet_priv *priv, bool flush_rx)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
u32 reg;
|
u32 reg;
|
||||||
@@ -2831,6 +2831,14 @@ static u32 bcmgenet_dma_disable(struct bcmgenet_priv *priv)
|
|||||||
udelay(10);
|
udelay(10);
|
||||||
bcmgenet_umac_writel(priv, 0, UMAC_TX_FLUSH);
|
bcmgenet_umac_writel(priv, 0, UMAC_TX_FLUSH);
|
||||||
|
|
||||||
|
if (flush_rx) {
|
||||||
|
reg = bcmgenet_rbuf_ctrl_get(priv);
|
||||||
|
bcmgenet_rbuf_ctrl_set(priv, reg | BIT(0));
|
||||||
|
udelay(10);
|
||||||
|
bcmgenet_rbuf_ctrl_set(priv, reg);
|
||||||
|
udelay(10);
|
||||||
|
}
|
||||||
|
|
||||||
return dma_ctrl;
|
return dma_ctrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2926,8 +2934,8 @@ static int bcmgenet_open(struct net_device *dev)
|
|||||||
|
|
||||||
bcmgenet_set_hw_addr(priv, dev->dev_addr);
|
bcmgenet_set_hw_addr(priv, dev->dev_addr);
|
||||||
|
|
||||||
/* Disable RX/TX DMA and flush TX queues */
|
/* Disable RX/TX DMA and flush TX and RX queues */
|
||||||
dma_ctrl = bcmgenet_dma_disable(priv);
|
dma_ctrl = bcmgenet_dma_disable(priv, true);
|
||||||
|
|
||||||
/* Reinitialize TDMA and RDMA and SW housekeeping */
|
/* Reinitialize TDMA and RDMA and SW housekeeping */
|
||||||
ret = bcmgenet_init_dma(priv);
|
ret = bcmgenet_init_dma(priv);
|
||||||
@@ -3682,7 +3690,7 @@ static int bcmgenet_resume(struct device *d)
|
|||||||
bcmgenet_power_up(priv, GENET_POWER_WOL_MAGIC);
|
bcmgenet_power_up(priv, GENET_POWER_WOL_MAGIC);
|
||||||
|
|
||||||
/* Disable RX/TX DMA and flush TX queues */
|
/* Disable RX/TX DMA and flush TX queues */
|
||||||
dma_ctrl = bcmgenet_dma_disable(priv);
|
dma_ctrl = bcmgenet_dma_disable(priv, false);
|
||||||
|
|
||||||
/* Reinitialize TDMA and RDMA and SW housekeeping */
|
/* Reinitialize TDMA and RDMA and SW housekeeping */
|
||||||
ret = bcmgenet_init_dma(priv);
|
ret = bcmgenet_init_dma(priv);
|
||||||
|
|||||||
@@ -320,7 +320,7 @@ bnad_debugfs_write_regrd(struct file *file, const char __user *buf,
|
|||||||
void *kern_buf;
|
void *kern_buf;
|
||||||
|
|
||||||
/* Copy the user space buf */
|
/* Copy the user space buf */
|
||||||
kern_buf = memdup_user(buf, nbytes);
|
kern_buf = memdup_user_nul(buf, nbytes);
|
||||||
if (IS_ERR(kern_buf))
|
if (IS_ERR(kern_buf))
|
||||||
return PTR_ERR(kern_buf);
|
return PTR_ERR(kern_buf);
|
||||||
|
|
||||||
@@ -380,7 +380,7 @@ bnad_debugfs_write_regwr(struct file *file, const char __user *buf,
|
|||||||
void *kern_buf;
|
void *kern_buf;
|
||||||
|
|
||||||
/* Copy the user space buf */
|
/* Copy the user space buf */
|
||||||
kern_buf = memdup_user(buf, nbytes);
|
kern_buf = memdup_user_nul(buf, nbytes);
|
||||||
if (IS_ERR(kern_buf))
|
if (IS_ERR(kern_buf))
|
||||||
return PTR_ERR(kern_buf);
|
return PTR_ERR(kern_buf);
|
||||||
|
|
||||||
|
|||||||
@@ -14728,7 +14728,7 @@ static int __init i40e_init_module(void)
|
|||||||
* since we need to be able to guarantee forward progress even under
|
* since we need to be able to guarantee forward progress even under
|
||||||
* memory pressure.
|
* memory pressure.
|
||||||
*/
|
*/
|
||||||
i40e_wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 0, i40e_driver_name);
|
i40e_wq = alloc_workqueue("%s", 0, 0, i40e_driver_name);
|
||||||
if (!i40e_wq) {
|
if (!i40e_wq) {
|
||||||
pr_err("%s: Failed to create workqueue\n", i40e_driver_name);
|
pr_err("%s: Failed to create workqueue\n", i40e_driver_name);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|||||||
@@ -1452,8 +1452,9 @@ static struct mlx5_flow_handle *add_rule_fg(struct mlx5_flow_group *fg,
|
|||||||
}
|
}
|
||||||
trace_mlx5_fs_set_fte(fte, false);
|
trace_mlx5_fs_set_fte(fte, false);
|
||||||
|
|
||||||
|
/* Link newly added rules into the tree. */
|
||||||
for (i = 0; i < handle->num_rules; i++) {
|
for (i = 0; i < handle->num_rules; i++) {
|
||||||
if (refcount_read(&handle->rule[i]->node.refcount) == 1) {
|
if (!handle->rule[i]->node.parent) {
|
||||||
tree_add_node(&handle->rule[i]->node, &fte->node);
|
tree_add_node(&handle->rule[i]->node, &fte->node);
|
||||||
trace_mlx5_fs_add_rule(handle->rule[i]);
|
trace_mlx5_fs_add_rule(handle->rule[i]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -561,7 +561,7 @@ free_skb:
|
|||||||
|
|
||||||
static const struct mlxsw_listener mlxsw_emad_rx_listener =
|
static const struct mlxsw_listener mlxsw_emad_rx_listener =
|
||||||
MLXSW_RXL(mlxsw_emad_rx_listener_func, ETHEMAD, TRAP_TO_CPU, false,
|
MLXSW_RXL(mlxsw_emad_rx_listener_func, ETHEMAD, TRAP_TO_CPU, false,
|
||||||
EMAD, DISCARD);
|
EMAD, FORWARD);
|
||||||
|
|
||||||
static int mlxsw_emad_init(struct mlxsw_core *mlxsw_core)
|
static int mlxsw_emad_init(struct mlxsw_core *mlxsw_core)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -838,7 +838,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
|
|||||||
__be16 df;
|
__be16 df;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!pskb_inet_may_pull(skb))
|
if (!skb_vlan_inet_prepare(skb))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
|
sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
|
||||||
@@ -884,7 +884,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
|
|||||||
__be16 sport;
|
__be16 sport;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!pskb_inet_may_pull(skb))
|
if (!skb_vlan_inet_prepare(skb))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
|
sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
|
||||||
|
|||||||
+2
-1
@@ -710,11 +710,12 @@ out_hashtable:
|
|||||||
static void gtp_dellink(struct net_device *dev, struct list_head *head)
|
static void gtp_dellink(struct net_device *dev, struct list_head *head)
|
||||||
{
|
{
|
||||||
struct gtp_dev *gtp = netdev_priv(dev);
|
struct gtp_dev *gtp = netdev_priv(dev);
|
||||||
|
struct hlist_node *next;
|
||||||
struct pdp_ctx *pctx;
|
struct pdp_ctx *pctx;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < gtp->hash_size; i++)
|
for (i = 0; i < gtp->hash_size; i++)
|
||||||
hlist_for_each_entry_rcu(pctx, >p->tid_hash[i], hlist_tid)
|
hlist_for_each_entry_safe(pctx, next, >p->tid_hash[i], hlist_tid)
|
||||||
pdp_context_delete(pctx);
|
pdp_context_delete(pctx);
|
||||||
|
|
||||||
gtp_encap_disable(gtp);
|
gtp_encap_disable(gtp);
|
||||||
|
|||||||
+10
-8
@@ -2172,14 +2172,16 @@ static ssize_t tun_put_user(struct tun_struct *tun,
|
|||||||
tun_is_little_endian(tun), true,
|
tun_is_little_endian(tun), true,
|
||||||
vlan_hlen)) {
|
vlan_hlen)) {
|
||||||
struct skb_shared_info *sinfo = skb_shinfo(skb);
|
struct skb_shared_info *sinfo = skb_shinfo(skb);
|
||||||
pr_err("unexpected GSO type: "
|
|
||||||
"0x%x, gso_size %d, hdr_len %d\n",
|
if (net_ratelimit()) {
|
||||||
sinfo->gso_type, tun16_to_cpu(tun, gso.gso_size),
|
netdev_err(tun->dev, "unexpected GSO type: 0x%x, gso_size %d, hdr_len %d\n",
|
||||||
tun16_to_cpu(tun, gso.hdr_len));
|
sinfo->gso_type, tun16_to_cpu(tun, gso.gso_size),
|
||||||
print_hex_dump(KERN_ERR, "tun: ",
|
tun16_to_cpu(tun, gso.hdr_len));
|
||||||
DUMP_PREFIX_NONE,
|
print_hex_dump(KERN_ERR, "tun: ",
|
||||||
16, 1, skb->head,
|
DUMP_PREFIX_NONE,
|
||||||
min((int)tun16_to_cpu(tun, gso.hdr_len), 64), true);
|
16, 1, skb->head,
|
||||||
|
min((int)tun16_to_cpu(tun, gso.hdr_len), 64), true);
|
||||||
|
}
|
||||||
WARN_ON_ONCE(1);
|
WARN_ON_ONCE(1);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1383,6 +1383,7 @@ static const struct usb_device_id products[] = {
|
|||||||
{QMI_FIXED_INTF(0x0489, 0xe0b5, 0)}, /* Foxconn T77W968 LTE with eSIM support*/
|
{QMI_FIXED_INTF(0x0489, 0xe0b5, 0)}, /* Foxconn T77W968 LTE with eSIM support*/
|
||||||
{QMI_FIXED_INTF(0x2692, 0x9025, 4)}, /* Cellient MPL200 (rebranded Qualcomm 05c6:9025) */
|
{QMI_FIXED_INTF(0x2692, 0x9025, 4)}, /* Cellient MPL200 (rebranded Qualcomm 05c6:9025) */
|
||||||
{QMI_QUIRK_SET_DTR(0x1546, 0x1342, 4)}, /* u-blox LARA-L6 */
|
{QMI_QUIRK_SET_DTR(0x1546, 0x1342, 4)}, /* u-blox LARA-L6 */
|
||||||
|
{QMI_QUIRK_SET_DTR(0x33f8, 0x0104, 4)}, /* Rolling RW101 RMNET */
|
||||||
|
|
||||||
/* 4. Gobi 1000 devices */
|
/* 4. Gobi 1000 devices */
|
||||||
{QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
|
{QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
|
||||||
|
|||||||
@@ -1320,6 +1320,10 @@ static bool vxlan_set_mac(struct vxlan_dev *vxlan,
|
|||||||
if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr))
|
if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
/* Ignore packets from invalid src-address */
|
||||||
|
if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
|
||||||
|
return false;
|
||||||
|
|
||||||
/* Get address from the outer IP header */
|
/* Get address from the outer IP header */
|
||||||
if (vxlan_get_sk_family(vs) == AF_INET) {
|
if (vxlan_get_sk_family(vs) == AF_INET) {
|
||||||
saddr.sin.sin_addr.s_addr = ip_hdr(skb)->saddr;
|
saddr.sin.sin_addr.s_addr = ip_hdr(skb)->saddr;
|
||||||
|
|||||||
+23
-19
@@ -427,7 +427,8 @@ struct trf7970a {
|
|||||||
enum trf7970a_state state;
|
enum trf7970a_state state;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct spi_device *spi;
|
struct spi_device *spi;
|
||||||
struct regulator *regulator;
|
struct regulator *vin_regulator;
|
||||||
|
struct regulator *vddio_regulator;
|
||||||
struct nfc_digital_dev *ddev;
|
struct nfc_digital_dev *ddev;
|
||||||
u32 quirks;
|
u32 quirks;
|
||||||
bool is_initiator;
|
bool is_initiator;
|
||||||
@@ -1886,7 +1887,7 @@ static int trf7970a_power_up(struct trf7970a *trf)
|
|||||||
if (trf->state != TRF7970A_ST_PWR_OFF)
|
if (trf->state != TRF7970A_ST_PWR_OFF)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = regulator_enable(trf->regulator);
|
ret = regulator_enable(trf->vin_regulator);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(trf->dev, "%s - Can't enable VIN: %d\n", __func__, ret);
|
dev_err(trf->dev, "%s - Can't enable VIN: %d\n", __func__, ret);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -1929,7 +1930,7 @@ static int trf7970a_power_down(struct trf7970a *trf)
|
|||||||
if (trf->en2_gpiod && !(trf->quirks & TRF7970A_QUIRK_EN2_MUST_STAY_LOW))
|
if (trf->en2_gpiod && !(trf->quirks & TRF7970A_QUIRK_EN2_MUST_STAY_LOW))
|
||||||
gpiod_set_value_cansleep(trf->en2_gpiod, 0);
|
gpiod_set_value_cansleep(trf->en2_gpiod, 0);
|
||||||
|
|
||||||
ret = regulator_disable(trf->regulator);
|
ret = regulator_disable(trf->vin_regulator);
|
||||||
if (ret)
|
if (ret)
|
||||||
dev_err(trf->dev, "%s - Can't disable VIN: %d\n", __func__,
|
dev_err(trf->dev, "%s - Can't disable VIN: %d\n", __func__,
|
||||||
ret);
|
ret);
|
||||||
@@ -2068,37 +2069,37 @@ static int trf7970a_probe(struct spi_device *spi)
|
|||||||
mutex_init(&trf->lock);
|
mutex_init(&trf->lock);
|
||||||
INIT_DELAYED_WORK(&trf->timeout_work, trf7970a_timeout_work_handler);
|
INIT_DELAYED_WORK(&trf->timeout_work, trf7970a_timeout_work_handler);
|
||||||
|
|
||||||
trf->regulator = devm_regulator_get(&spi->dev, "vin");
|
trf->vin_regulator = devm_regulator_get(&spi->dev, "vin");
|
||||||
if (IS_ERR(trf->regulator)) {
|
if (IS_ERR(trf->vin_regulator)) {
|
||||||
ret = PTR_ERR(trf->regulator);
|
ret = PTR_ERR(trf->vin_regulator);
|
||||||
dev_err(trf->dev, "Can't get VIN regulator: %d\n", ret);
|
dev_err(trf->dev, "Can't get VIN regulator: %d\n", ret);
|
||||||
goto err_destroy_lock;
|
goto err_destroy_lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = regulator_enable(trf->regulator);
|
ret = regulator_enable(trf->vin_regulator);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(trf->dev, "Can't enable VIN: %d\n", ret);
|
dev_err(trf->dev, "Can't enable VIN: %d\n", ret);
|
||||||
goto err_destroy_lock;
|
goto err_destroy_lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
uvolts = regulator_get_voltage(trf->regulator);
|
uvolts = regulator_get_voltage(trf->vin_regulator);
|
||||||
if (uvolts > 4000000)
|
if (uvolts > 4000000)
|
||||||
trf->chip_status_ctrl = TRF7970A_CHIP_STATUS_VRS5_3;
|
trf->chip_status_ctrl = TRF7970A_CHIP_STATUS_VRS5_3;
|
||||||
|
|
||||||
trf->regulator = devm_regulator_get(&spi->dev, "vdd-io");
|
trf->vddio_regulator = devm_regulator_get(&spi->dev, "vdd-io");
|
||||||
if (IS_ERR(trf->regulator)) {
|
if (IS_ERR(trf->vddio_regulator)) {
|
||||||
ret = PTR_ERR(trf->regulator);
|
ret = PTR_ERR(trf->vddio_regulator);
|
||||||
dev_err(trf->dev, "Can't get VDD_IO regulator: %d\n", ret);
|
dev_err(trf->dev, "Can't get VDD_IO regulator: %d\n", ret);
|
||||||
goto err_destroy_lock;
|
goto err_disable_vin_regulator;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = regulator_enable(trf->regulator);
|
ret = regulator_enable(trf->vddio_regulator);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(trf->dev, "Can't enable VDD_IO: %d\n", ret);
|
dev_err(trf->dev, "Can't enable VDD_IO: %d\n", ret);
|
||||||
goto err_destroy_lock;
|
goto err_disable_vin_regulator;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (regulator_get_voltage(trf->regulator) == 1800000) {
|
if (regulator_get_voltage(trf->vddio_regulator) == 1800000) {
|
||||||
trf->io_ctrl = TRF7970A_REG_IO_CTRL_IO_LOW;
|
trf->io_ctrl = TRF7970A_REG_IO_CTRL_IO_LOW;
|
||||||
dev_dbg(trf->dev, "trf7970a config vdd_io to 1.8V\n");
|
dev_dbg(trf->dev, "trf7970a config vdd_io to 1.8V\n");
|
||||||
}
|
}
|
||||||
@@ -2111,7 +2112,7 @@ static int trf7970a_probe(struct spi_device *spi)
|
|||||||
if (!trf->ddev) {
|
if (!trf->ddev) {
|
||||||
dev_err(trf->dev, "Can't allocate NFC digital device\n");
|
dev_err(trf->dev, "Can't allocate NFC digital device\n");
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto err_disable_regulator;
|
goto err_disable_vddio_regulator;
|
||||||
}
|
}
|
||||||
|
|
||||||
nfc_digital_set_parent_dev(trf->ddev, trf->dev);
|
nfc_digital_set_parent_dev(trf->ddev, trf->dev);
|
||||||
@@ -2140,8 +2141,10 @@ err_shutdown:
|
|||||||
trf7970a_shutdown(trf);
|
trf7970a_shutdown(trf);
|
||||||
err_free_ddev:
|
err_free_ddev:
|
||||||
nfc_digital_free_device(trf->ddev);
|
nfc_digital_free_device(trf->ddev);
|
||||||
err_disable_regulator:
|
err_disable_vddio_regulator:
|
||||||
regulator_disable(trf->regulator);
|
regulator_disable(trf->vddio_regulator);
|
||||||
|
err_disable_vin_regulator:
|
||||||
|
regulator_disable(trf->vin_regulator);
|
||||||
err_destroy_lock:
|
err_destroy_lock:
|
||||||
mutex_destroy(&trf->lock);
|
mutex_destroy(&trf->lock);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -2160,7 +2163,8 @@ static int trf7970a_remove(struct spi_device *spi)
|
|||||||
nfc_digital_unregister_device(trf->ddev);
|
nfc_digital_unregister_device(trf->ddev);
|
||||||
nfc_digital_free_device(trf->ddev);
|
nfc_digital_free_device(trf->ddev);
|
||||||
|
|
||||||
regulator_disable(trf->regulator);
|
regulator_disable(trf->vddio_regulator);
|
||||||
|
regulator_disable(trf->vin_regulator);
|
||||||
|
|
||||||
mutex_destroy(&trf->lock);
|
mutex_destroy(&trf->lock);
|
||||||
|
|
||||||
|
|||||||
@@ -2036,13 +2036,7 @@ int pinctrl_enable(struct pinctrl_dev *pctldev)
|
|||||||
|
|
||||||
error = pinctrl_claim_hogs(pctldev);
|
error = pinctrl_claim_hogs(pctldev);
|
||||||
if (error) {
|
if (error) {
|
||||||
dev_err(pctldev->dev, "could not claim hogs: %i\n",
|
dev_err(pctldev->dev, "could not claim hogs: %i\n", error);
|
||||||
error);
|
|
||||||
pinctrl_free_pindescs(pctldev, pctldev->desc->pins,
|
|
||||||
pctldev->desc->npins);
|
|
||||||
mutex_destroy(&pctldev->mutex);
|
|
||||||
kfree(pctldev);
|
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -235,14 +235,16 @@ int pinctrl_dt_to_map(struct pinctrl *p, struct pinctrl_dev *pctldev)
|
|||||||
for (state = 0; ; state++) {
|
for (state = 0; ; state++) {
|
||||||
/* Retrieve the pinctrl-* property */
|
/* Retrieve the pinctrl-* property */
|
||||||
propname = kasprintf(GFP_KERNEL, "pinctrl-%d", state);
|
propname = kasprintf(GFP_KERNEL, "pinctrl-%d", state);
|
||||||
if (!propname)
|
if (!propname) {
|
||||||
return -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
prop = of_find_property(np, propname, &size);
|
prop = of_find_property(np, propname, &size);
|
||||||
kfree(propname);
|
kfree(propname);
|
||||||
if (!prop) {
|
if (!prop) {
|
||||||
if (state == 0) {
|
if (state == 0) {
|
||||||
of_node_put(np);
|
ret = -ENODEV;
|
||||||
return -ENODEV;
|
goto err;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1252,6 +1252,7 @@ static ssize_t ipa3_read_stats(struct file *file, char __user *ubuf,
|
|||||||
"flow_disable=%u\n"
|
"flow_disable=%u\n"
|
||||||
"rx_page_drop_cnt=%u\n"
|
"rx_page_drop_cnt=%u\n"
|
||||||
"zero_len_frag_pkt_cnt=%u\n",
|
"zero_len_frag_pkt_cnt=%u\n",
|
||||||
|
"lower_order=%u\n",
|
||||||
ipa3_ctx->stats.tx_sw_pkts,
|
ipa3_ctx->stats.tx_sw_pkts,
|
||||||
ipa3_ctx->stats.tx_hw_pkts,
|
ipa3_ctx->stats.tx_hw_pkts,
|
||||||
ipa3_ctx->stats.tx_non_linear,
|
ipa3_ctx->stats.tx_non_linear,
|
||||||
@@ -1269,7 +1270,8 @@ static ssize_t ipa3_read_stats(struct file *file, char __user *ubuf,
|
|||||||
ipa3_ctx->stats.flow_enable,
|
ipa3_ctx->stats.flow_enable,
|
||||||
ipa3_ctx->stats.flow_disable,
|
ipa3_ctx->stats.flow_disable,
|
||||||
ipa3_ctx->stats.rx_page_drop_cnt,
|
ipa3_ctx->stats.rx_page_drop_cnt,
|
||||||
ipa3_ctx->stats.zero_len_frag_pkt_cnt);
|
ipa3_ctx->stats.zero_len_frag_pkt_cnt,
|
||||||
|
ipa3_ctx->stats.lower_order);
|
||||||
cnt += nbytes;
|
cnt += nbytes;
|
||||||
|
|
||||||
for (i = 0; i < IPAHAL_PKT_STATUS_EXCEPTION_MAX; i++) {
|
for (i = 0; i < IPAHAL_PKT_STATUS_EXCEPTION_MAX; i++) {
|
||||||
|
|||||||
@@ -1923,6 +1923,26 @@ fail_kmem_cache_alloc:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct page *ipa3_alloc_page(
|
||||||
|
gfp_t flag, u32 *page_order, bool try_lower)
|
||||||
|
{
|
||||||
|
struct page *page = NULL;
|
||||||
|
u32 p_order = *page_order;
|
||||||
|
|
||||||
|
page = __dev_alloc_pages(flag, p_order);
|
||||||
|
/* We will only try 1 page order lower. */
|
||||||
|
if (unlikely(!page)) {
|
||||||
|
if (try_lower && p_order > 0) {
|
||||||
|
p_order = p_order - 1;
|
||||||
|
page = __dev_alloc_pages(flag, p_order);
|
||||||
|
if (likely(page))
|
||||||
|
ipa3_ctx->stats.lower_order++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*page_order = p_order;
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
static struct ipa3_rx_pkt_wrapper *ipa3_alloc_rx_pkt_page(
|
static struct ipa3_rx_pkt_wrapper *ipa3_alloc_rx_pkt_page(
|
||||||
gfp_t flag, bool is_tmp_alloc)
|
gfp_t flag, bool is_tmp_alloc)
|
||||||
{
|
{
|
||||||
@@ -1933,12 +1953,21 @@ static struct ipa3_rx_pkt_wrapper *ipa3_alloc_rx_pkt_page(
|
|||||||
flag);
|
flag);
|
||||||
if (unlikely(!rx_pkt))
|
if (unlikely(!rx_pkt))
|
||||||
return NULL;
|
return NULL;
|
||||||
rx_pkt->len = PAGE_SIZE << IPA_WAN_PAGE_ORDER;
|
|
||||||
rx_pkt->page_data.page = __dev_alloc_pages(flag,
|
rx_pkt->page_data.page_order = IPA_WAN_PAGE_ORDER;
|
||||||
IPA_WAN_PAGE_ORDER);
|
/* For temporary allocations, avoid triggering OOM Killer. */
|
||||||
|
if (is_tmp_alloc)
|
||||||
|
flag |= __GFP_RETRY_MAYFAIL | __GFP_NOWARN;
|
||||||
|
/* Try a lower order page for order 3 pages in case allocation fails. */
|
||||||
|
rx_pkt->page_data.page = ipa3_alloc_page(flag,
|
||||||
|
&rx_pkt->page_data.page_order,
|
||||||
|
(is_tmp_alloc && rx_pkt->page_data.page_order == 3));
|
||||||
|
|
||||||
if (unlikely(!rx_pkt->page_data.page))
|
if (unlikely(!rx_pkt->page_data.page))
|
||||||
goto fail_page_alloc;
|
goto fail_page_alloc;
|
||||||
|
|
||||||
|
rx_pkt->len = PAGE_SIZE << rx_pkt->page_data.page_order;
|
||||||
|
|
||||||
rx_pkt->page_data.dma_addr = dma_map_page(ipa3_ctx->pdev,
|
rx_pkt->page_data.dma_addr = dma_map_page(ipa3_ctx->pdev,
|
||||||
rx_pkt->page_data.page, 0,
|
rx_pkt->page_data.page, 0,
|
||||||
rx_pkt->len, DMA_FROM_DEVICE);
|
rx_pkt->len, DMA_FROM_DEVICE);
|
||||||
@@ -1956,7 +1985,7 @@ static struct ipa3_rx_pkt_wrapper *ipa3_alloc_rx_pkt_page(
|
|||||||
return rx_pkt;
|
return rx_pkt;
|
||||||
|
|
||||||
fail_dma_mapping:
|
fail_dma_mapping:
|
||||||
__free_pages(rx_pkt->page_data.page, IPA_WAN_PAGE_ORDER);
|
__free_pages(rx_pkt->page_data.page, rx_pkt->page_data.page_order);
|
||||||
fail_page_alloc:
|
fail_page_alloc:
|
||||||
kmem_cache_free(ipa3_ctx->rx_pkt_wrapper_cache, rx_pkt);
|
kmem_cache_free(ipa3_ctx->rx_pkt_wrapper_cache, rx_pkt);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -2643,8 +2672,7 @@ static void free_rx_page(void *chan_user_data, void *xfer_user_data)
|
|||||||
}
|
}
|
||||||
dma_unmap_page(ipa3_ctx->pdev, rx_pkt->page_data.dma_addr,
|
dma_unmap_page(ipa3_ctx->pdev, rx_pkt->page_data.dma_addr,
|
||||||
rx_pkt->len, DMA_FROM_DEVICE);
|
rx_pkt->len, DMA_FROM_DEVICE);
|
||||||
__free_pages(rx_pkt->page_data.page,
|
__free_pages(rx_pkt->page_data.page, rx_pkt->page_data.page_order);
|
||||||
IPA_WAN_PAGE_ORDER);
|
|
||||||
kmem_cache_free(ipa3_ctx->rx_pkt_wrapper_cache, rx_pkt);
|
kmem_cache_free(ipa3_ctx->rx_pkt_wrapper_cache, rx_pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2696,7 +2724,7 @@ static void ipa3_cleanup_rx(struct ipa3_sys_context *sys)
|
|||||||
rx_pkt->len,
|
rx_pkt->len,
|
||||||
DMA_FROM_DEVICE);
|
DMA_FROM_DEVICE);
|
||||||
__free_pages(rx_pkt->page_data.page,
|
__free_pages(rx_pkt->page_data.page,
|
||||||
IPA_WAN_PAGE_ORDER);
|
rx_pkt->page_data.page_order);
|
||||||
}
|
}
|
||||||
kmem_cache_free(ipa3_ctx->rx_pkt_wrapper_cache,
|
kmem_cache_free(ipa3_ctx->rx_pkt_wrapper_cache,
|
||||||
rx_pkt);
|
rx_pkt);
|
||||||
@@ -2716,7 +2744,7 @@ static void ipa3_cleanup_rx(struct ipa3_sys_context *sys)
|
|||||||
rx_pkt->len,
|
rx_pkt->len,
|
||||||
DMA_FROM_DEVICE);
|
DMA_FROM_DEVICE);
|
||||||
__free_pages(rx_pkt->page_data.page,
|
__free_pages(rx_pkt->page_data.page,
|
||||||
IPA_WAN_PAGE_ORDER);
|
rx_pkt->page_data.page_order);
|
||||||
kmem_cache_free(
|
kmem_cache_free(
|
||||||
ipa3_ctx->rx_pkt_wrapper_cache,
|
ipa3_ctx->rx_pkt_wrapper_cache,
|
||||||
rx_pkt);
|
rx_pkt);
|
||||||
@@ -3489,7 +3517,7 @@ static struct sk_buff *handle_page_completion(struct gsi_chan_xfer_notify
|
|||||||
dma_unmap_page(ipa3_ctx->pdev, rx_page.dma_addr,
|
dma_unmap_page(ipa3_ctx->pdev, rx_page.dma_addr,
|
||||||
rx_pkt->len, DMA_FROM_DEVICE);
|
rx_pkt->len, DMA_FROM_DEVICE);
|
||||||
__free_pages(rx_pkt->page_data.page,
|
__free_pages(rx_pkt->page_data.page,
|
||||||
IPA_WAN_PAGE_ORDER);
|
rx_pkt->page_data.page_order);
|
||||||
}
|
}
|
||||||
rx_pkt->sys->free_rx_wrapper(rx_pkt);
|
rx_pkt->sys->free_rx_wrapper(rx_pkt);
|
||||||
IPA_STATS_INC_CNT(ipa3_ctx->stats.rx_page_drop_cnt);
|
IPA_STATS_INC_CNT(ipa3_ctx->stats.rx_page_drop_cnt);
|
||||||
@@ -3517,7 +3545,7 @@ static struct sk_buff *handle_page_completion(struct gsi_chan_xfer_notify
|
|||||||
rx_page.dma_addr,
|
rx_page.dma_addr,
|
||||||
rx_pkt->len, DMA_FROM_DEVICE);
|
rx_pkt->len, DMA_FROM_DEVICE);
|
||||||
__free_pages(rx_pkt->page_data.page,
|
__free_pages(rx_pkt->page_data.page,
|
||||||
IPA_WAN_PAGE_ORDER);
|
rx_pkt->page_data.page_order);
|
||||||
}
|
}
|
||||||
rx_pkt->sys->free_rx_wrapper(rx_pkt);
|
rx_pkt->sys->free_rx_wrapper(rx_pkt);
|
||||||
}
|
}
|
||||||
@@ -3542,7 +3570,7 @@ static struct sk_buff *handle_page_completion(struct gsi_chan_xfer_notify
|
|||||||
skb_shinfo(rx_skb)->nr_frags,
|
skb_shinfo(rx_skb)->nr_frags,
|
||||||
rx_page.page, 0,
|
rx_page.page, 0,
|
||||||
notify->bytes_xfered,
|
notify->bytes_xfered,
|
||||||
PAGE_SIZE << IPA_WAN_PAGE_ORDER);
|
PAGE_SIZE << rx_page.page_order);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012-2019,2021 The Linux Foundation. All rights reserved.
|
* Copyright (c) 2012-2019,2021 The Linux Foundation. All rights reserved.
|
||||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ipa_i.h"
|
#include "ipa_i.h"
|
||||||
@@ -98,8 +98,10 @@ static int ipa3_hdr_proc_ctx_to_hw_format(struct ipa_mem_buffer *mem,
|
|||||||
!entry->offset_entry ||
|
!entry->offset_entry ||
|
||||||
entry->hdr->hdr_len == 0 ||
|
entry->hdr->hdr_len == 0 ||
|
||||||
entry->hdr->hdr_len >
|
entry->hdr->hdr_len >
|
||||||
ipa_hdr_bin_sz[IPA_HDR_BIN_MAX - 1]))
|
ipa_hdr_bin_sz[IPA_HDR_BIN_MAX - 1])) {
|
||||||
|
IPAERR_RL("Found invalid hdr entry\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
ret = ipahal_cp_proc_ctx_to_hw_buff(entry->type, mem->base,
|
ret = ipahal_cp_proc_ctx_to_hw_buff(entry->type, mem->base,
|
||||||
entry->offset_entry->offset,
|
entry->offset_entry->offset,
|
||||||
@@ -132,6 +134,7 @@ static int ipa3_generate_hdr_proc_ctx_hw_tbl(u64 hdr_sys_addr,
|
|||||||
{
|
{
|
||||||
u64 hdr_base_addr;
|
u64 hdr_base_addr;
|
||||||
gfp_t flag = GFP_KERNEL;
|
gfp_t flag = GFP_KERNEL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
mem->size = (ipa3_ctx->hdr_proc_ctx_tbl.end) ? : 4;
|
mem->size = (ipa3_ctx->hdr_proc_ctx_tbl.end) ? : 4;
|
||||||
|
|
||||||
@@ -160,7 +163,12 @@ alloc:
|
|||||||
memset(aligned_mem->base, 0, aligned_mem->size);
|
memset(aligned_mem->base, 0, aligned_mem->size);
|
||||||
hdr_base_addr = (ipa3_ctx->hdr_tbl_lcl) ? IPA_MEM_PART(apps_hdr_ofst) :
|
hdr_base_addr = (ipa3_ctx->hdr_tbl_lcl) ? IPA_MEM_PART(apps_hdr_ofst) :
|
||||||
hdr_sys_addr;
|
hdr_sys_addr;
|
||||||
return ipa3_hdr_proc_ctx_to_hw_format(aligned_mem, hdr_base_addr);
|
ret = ipa3_hdr_proc_ctx_to_hw_format(aligned_mem, hdr_base_addr);
|
||||||
|
if (ret) {
|
||||||
|
dma_free_coherent(ipa3_ctx->pdev, mem->size, mem->base, mem->phys_base);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1383,6 +1383,7 @@ struct ipa3_stats {
|
|||||||
u32 rx_page_drop_cnt;
|
u32 rx_page_drop_cnt;
|
||||||
u32 zero_len_frag_pkt_cnt;
|
u32 zero_len_frag_pkt_cnt;
|
||||||
struct ipa3_page_recycle_stats page_recycle_stats[2];
|
struct ipa3_page_recycle_stats page_recycle_stats[2];
|
||||||
|
u64 lower_order;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* offset for each stats */
|
/* offset for each stats */
|
||||||
|
|||||||
@@ -202,6 +202,7 @@ static const int rt9455_voreg_values[] = {
|
|||||||
4450000, 4450000, 4450000, 4450000, 4450000, 4450000, 4450000, 4450000
|
4450000, 4450000, 4450000, 4450000, 4450000, 4450000, 4450000, 4450000
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_USB_PHY)
|
||||||
/*
|
/*
|
||||||
* When the charger is in boost mode, REG02[7:2] represent boost output
|
* When the charger is in boost mode, REG02[7:2] represent boost output
|
||||||
* voltage.
|
* voltage.
|
||||||
@@ -217,6 +218,7 @@ static const int rt9455_boost_voltage_values[] = {
|
|||||||
5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000,
|
5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000,
|
||||||
5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000,
|
5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000,
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/* REG07[3:0] (VMREG) in uV */
|
/* REG07[3:0] (VMREG) in uV */
|
||||||
static const int rt9455_vmreg_values[] = {
|
static const int rt9455_vmreg_values[] = {
|
||||||
|
|||||||
@@ -834,7 +834,6 @@ static void bnx2fc_free_session_resc(struct bnx2fc_hba *hba,
|
|||||||
|
|
||||||
BNX2FC_TGT_DBG(tgt, "Freeing up session resources\n");
|
BNX2FC_TGT_DBG(tgt, "Freeing up session resources\n");
|
||||||
|
|
||||||
spin_lock_bh(&tgt->cq_lock);
|
|
||||||
ctx_base_ptr = tgt->ctx_base;
|
ctx_base_ptr = tgt->ctx_base;
|
||||||
tgt->ctx_base = NULL;
|
tgt->ctx_base = NULL;
|
||||||
|
|
||||||
@@ -890,7 +889,6 @@ static void bnx2fc_free_session_resc(struct bnx2fc_hba *hba,
|
|||||||
tgt->sq, tgt->sq_dma);
|
tgt->sq, tgt->sq_dma);
|
||||||
tgt->sq = NULL;
|
tgt->sq = NULL;
|
||||||
}
|
}
|
||||||
spin_unlock_bh(&tgt->cq_lock);
|
|
||||||
|
|
||||||
if (ctx_base_ptr)
|
if (ctx_base_ptr)
|
||||||
iounmap(ctx_base_ptr);
|
iounmap(ctx_base_ptr);
|
||||||
|
|||||||
@@ -989,7 +989,6 @@ struct lpfc_hba {
|
|||||||
unsigned long bit_flags;
|
unsigned long bit_flags;
|
||||||
#define FABRIC_COMANDS_BLOCKED 0
|
#define FABRIC_COMANDS_BLOCKED 0
|
||||||
atomic_t num_rsrc_err;
|
atomic_t num_rsrc_err;
|
||||||
atomic_t num_cmd_success;
|
|
||||||
unsigned long last_rsrc_error_time;
|
unsigned long last_rsrc_error_time;
|
||||||
unsigned long last_ramp_down_time;
|
unsigned long last_ramp_down_time;
|
||||||
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
|
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
|
||||||
|
|||||||
@@ -303,11 +303,10 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba)
|
|||||||
struct Scsi_Host *shost;
|
struct Scsi_Host *shost;
|
||||||
struct scsi_device *sdev;
|
struct scsi_device *sdev;
|
||||||
unsigned long new_queue_depth;
|
unsigned long new_queue_depth;
|
||||||
unsigned long num_rsrc_err, num_cmd_success;
|
unsigned long num_rsrc_err;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
num_rsrc_err = atomic_read(&phba->num_rsrc_err);
|
num_rsrc_err = atomic_read(&phba->num_rsrc_err);
|
||||||
num_cmd_success = atomic_read(&phba->num_cmd_success);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The error and success command counters are global per
|
* The error and success command counters are global per
|
||||||
@@ -322,20 +321,16 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba)
|
|||||||
for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
|
for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
|
||||||
shost = lpfc_shost_from_vport(vports[i]);
|
shost = lpfc_shost_from_vport(vports[i]);
|
||||||
shost_for_each_device(sdev, shost) {
|
shost_for_each_device(sdev, shost) {
|
||||||
new_queue_depth =
|
if (num_rsrc_err >= sdev->queue_depth)
|
||||||
sdev->queue_depth * num_rsrc_err /
|
new_queue_depth = 1;
|
||||||
(num_rsrc_err + num_cmd_success);
|
|
||||||
if (!new_queue_depth)
|
|
||||||
new_queue_depth = sdev->queue_depth - 1;
|
|
||||||
else
|
else
|
||||||
new_queue_depth = sdev->queue_depth -
|
new_queue_depth = sdev->queue_depth -
|
||||||
new_queue_depth;
|
num_rsrc_err;
|
||||||
scsi_change_queue_depth(sdev, new_queue_depth);
|
scsi_change_queue_depth(sdev, new_queue_depth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lpfc_destroy_vport_work_array(phba, vports);
|
lpfc_destroy_vport_work_array(phba, vports);
|
||||||
atomic_set(&phba->num_rsrc_err, 0);
|
atomic_set(&phba->num_rsrc_err, 0);
|
||||||
atomic_set(&phba->num_cmd_success, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -390,6 +390,7 @@ static const struct file_operations ufsdbg_err_inj_scenario_ops = {
|
|||||||
.open = ufsdbg_err_inj_scenario_open,
|
.open = ufsdbg_err_inj_scenario_open,
|
||||||
.read = seq_read,
|
.read = seq_read,
|
||||||
.write = ufsdbg_err_inj_scenario_write,
|
.write = ufsdbg_err_inj_scenario_write,
|
||||||
|
.release = single_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ufsdbg_err_inj_stats_read(struct seq_file *file, void *data)
|
static int ufsdbg_err_inj_stats_read(struct seq_file *file, void *data)
|
||||||
@@ -431,6 +432,7 @@ static const struct file_operations ufsdbg_err_inj_stats_ops = {
|
|||||||
.open = ufsdbg_err_inj_stats_open,
|
.open = ufsdbg_err_inj_stats_open,
|
||||||
.read = seq_read,
|
.read = seq_read,
|
||||||
.write = ufsdbg_err_inj_stats_write,
|
.write = ufsdbg_err_inj_stats_write,
|
||||||
|
.release = single_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void ufsdbg_setup_fault_injection(struct ufs_hba *hba)
|
static void ufsdbg_setup_fault_injection(struct ufs_hba *hba)
|
||||||
@@ -614,6 +616,7 @@ static const struct file_operations ufsdbg_tag_stats_fops = {
|
|||||||
.open = ufsdbg_tag_stats_open,
|
.open = ufsdbg_tag_stats_open,
|
||||||
.read = seq_read,
|
.read = seq_read,
|
||||||
.write = ufsdbg_tag_stats_write,
|
.write = ufsdbg_tag_stats_write,
|
||||||
|
.release = single_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ufsdbg_query_stats_show(struct seq_file *file, void *data)
|
static int ufsdbg_query_stats_show(struct seq_file *file, void *data)
|
||||||
@@ -685,6 +688,7 @@ static const struct file_operations ufsdbg_query_stats_fops = {
|
|||||||
.open = ufsdbg_query_stats_open,
|
.open = ufsdbg_query_stats_open,
|
||||||
.read = seq_read,
|
.read = seq_read,
|
||||||
.write = ufsdbg_query_stats_write,
|
.write = ufsdbg_query_stats_write,
|
||||||
|
.release = single_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ufsdbg_err_stats_show(struct seq_file *file, void *data)
|
static int ufsdbg_err_stats_show(struct seq_file *file, void *data)
|
||||||
@@ -789,6 +793,7 @@ static const struct file_operations ufsdbg_err_stats_fops = {
|
|||||||
.open = ufsdbg_err_stats_open,
|
.open = ufsdbg_err_stats_open,
|
||||||
.read = seq_read,
|
.read = seq_read,
|
||||||
.write = ufsdbg_err_stats_write,
|
.write = ufsdbg_err_stats_write,
|
||||||
|
.release = single_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ufshcd_init_statistics(struct ufs_hba *hba)
|
static int ufshcd_init_statistics(struct ufs_hba *hba)
|
||||||
@@ -868,6 +873,7 @@ static int ufsdbg_host_regs_open(struct inode *inode, struct file *file)
|
|||||||
static const struct file_operations ufsdbg_host_regs_fops = {
|
static const struct file_operations ufsdbg_host_regs_fops = {
|
||||||
.open = ufsdbg_host_regs_open,
|
.open = ufsdbg_host_regs_open,
|
||||||
.read = seq_read,
|
.read = seq_read,
|
||||||
|
.release = single_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ufsdbg_dump_device_desc_show(struct seq_file *file, void *data)
|
static int ufsdbg_dump_device_desc_show(struct seq_file *file, void *data)
|
||||||
@@ -1032,6 +1038,7 @@ static int ufsdbg_show_hba_open(struct inode *inode, struct file *file)
|
|||||||
static const struct file_operations ufsdbg_show_hba_fops = {
|
static const struct file_operations ufsdbg_show_hba_fops = {
|
||||||
.open = ufsdbg_show_hba_open,
|
.open = ufsdbg_show_hba_open,
|
||||||
.read = seq_read,
|
.read = seq_read,
|
||||||
|
.release = single_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ufsdbg_dump_device_desc_open(struct inode *inode, struct file *file)
|
static int ufsdbg_dump_device_desc_open(struct inode *inode, struct file *file)
|
||||||
@@ -1043,6 +1050,7 @@ static int ufsdbg_dump_device_desc_open(struct inode *inode, struct file *file)
|
|||||||
static const struct file_operations ufsdbg_dump_device_desc = {
|
static const struct file_operations ufsdbg_dump_device_desc = {
|
||||||
.open = ufsdbg_dump_device_desc_open,
|
.open = ufsdbg_dump_device_desc_open,
|
||||||
.read = seq_read,
|
.read = seq_read,
|
||||||
|
.release = single_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ufsdbg_power_mode_show(struct seq_file *file, void *data)
|
static int ufsdbg_power_mode_show(struct seq_file *file, void *data)
|
||||||
@@ -1330,6 +1338,7 @@ static const struct file_operations ufsdbg_power_mode_desc = {
|
|||||||
.open = ufsdbg_power_mode_open,
|
.open = ufsdbg_power_mode_open,
|
||||||
.read = seq_read,
|
.read = seq_read,
|
||||||
.write = ufsdbg_power_mode_write,
|
.write = ufsdbg_power_mode_write,
|
||||||
|
.release = single_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ufsdbg_dme_read(void *data, u64 *attr_val, bool peer)
|
static int ufsdbg_dme_read(void *data, u64 *attr_val, bool peer)
|
||||||
@@ -1509,6 +1518,7 @@ static const struct file_operations ufsdbg_req_stats_desc = {
|
|||||||
.open = ufsdbg_req_stats_open,
|
.open = ufsdbg_req_stats_open,
|
||||||
.read = seq_read,
|
.read = seq_read,
|
||||||
.write = ufsdbg_req_stats_write,
|
.write = ufsdbg_req_stats_write,
|
||||||
|
.release = single_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ufsdbg_clear_err_state(void *data, u64 val)
|
static int ufsdbg_clear_err_state(void *data, u64 val)
|
||||||
|
|||||||
@@ -188,6 +188,7 @@ static const struct file_operations ufs_qcom_dbg_testbus_cfg_desc = {
|
|||||||
.open = ufs_qcom_dbg_testbus_cfg_open,
|
.open = ufs_qcom_dbg_testbus_cfg_open,
|
||||||
.read = seq_read,
|
.read = seq_read,
|
||||||
.write = ufs_qcom_dbg_testbus_cfg_write,
|
.write = ufs_qcom_dbg_testbus_cfg_write,
|
||||||
|
.release = single_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ufs_qcom_dbg_testbus_bus_read(void *data, u64 *attr_val)
|
static int ufs_qcom_dbg_testbus_bus_read(void *data, u64 *attr_val)
|
||||||
@@ -242,6 +243,7 @@ static int ufs_qcom_dbg_dbg_regs_open(struct inode *inode,
|
|||||||
static const struct file_operations ufs_qcom_dbg_dbg_regs_desc = {
|
static const struct file_operations ufs_qcom_dbg_dbg_regs_desc = {
|
||||||
.open = ufs_qcom_dbg_dbg_regs_open,
|
.open = ufs_qcom_dbg_dbg_regs_open,
|
||||||
.read = seq_read,
|
.read = seq_read,
|
||||||
|
.release = single_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ufs_qcom_dbg_pm_qos_show(struct seq_file *file, void *data)
|
static int ufs_qcom_dbg_pm_qos_show(struct seq_file *file, void *data)
|
||||||
@@ -275,6 +277,7 @@ static int ufs_qcom_dbg_pm_qos_open(struct inode *inode,
|
|||||||
static const struct file_operations ufs_qcom_dbg_pm_qos_desc = {
|
static const struct file_operations ufs_qcom_dbg_pm_qos_desc = {
|
||||||
.open = ufs_qcom_dbg_pm_qos_open,
|
.open = ufs_qcom_dbg_pm_qos_open,
|
||||||
.read = seq_read,
|
.read = seq_read,
|
||||||
|
.release = single_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
void ufs_qcom_dbg_add_debugfs(struct ufs_hba *hba, struct dentry *root)
|
void ufs_qcom_dbg_add_debugfs(struct ufs_hba *hba, struct dentry *root)
|
||||||
|
|||||||
@@ -910,6 +910,7 @@ out:
|
|||||||
static int ufs_qcom_full_reset(struct ufs_hba *hba)
|
static int ufs_qcom_full_reset(struct ufs_hba *hba)
|
||||||
{
|
{
|
||||||
int ret = -ENOTSUPP;
|
int ret = -ENOTSUPP;
|
||||||
|
bool reenable_intr = false;
|
||||||
|
|
||||||
if (!hba->core_reset) {
|
if (!hba->core_reset) {
|
||||||
dev_err(hba->dev, "%s: failed, err = %d\n", __func__,
|
dev_err(hba->dev, "%s: failed, err = %d\n", __func__,
|
||||||
@@ -917,6 +918,10 @@ static int ufs_qcom_full_reset(struct ufs_hba *hba)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reenable_intr = hba->is_irq_enabled;
|
||||||
|
disable_irq(hba->irq);
|
||||||
|
hba->is_irq_enabled = false;
|
||||||
|
|
||||||
ret = reset_control_assert(hba->core_reset);
|
ret = reset_control_assert(hba->core_reset);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(hba->dev, "%s: core_reset assert failed, err = %d\n",
|
dev_err(hba->dev, "%s: core_reset assert failed, err = %d\n",
|
||||||
@@ -936,6 +941,11 @@ static int ufs_qcom_full_reset(struct ufs_hba *hba)
|
|||||||
dev_err(hba->dev, "%s: core_reset deassert failed, err = %d\n",
|
dev_err(hba->dev, "%s: core_reset deassert failed, err = %d\n",
|
||||||
__func__, ret);
|
__func__, ret);
|
||||||
|
|
||||||
|
if (reenable_intr) {
|
||||||
|
enable_irq(hba->irq);
|
||||||
|
hba->is_irq_enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -1497,7 +1507,6 @@ static void ufs_qcom_set_caps(struct ufs_hba *hba)
|
|||||||
if (!host->disable_lpm) {
|
if (!host->disable_lpm) {
|
||||||
hba->caps |= UFSHCD_CAP_CLK_GATING;
|
hba->caps |= UFSHCD_CAP_CLK_GATING;
|
||||||
hba->caps |= UFSHCD_CAP_HIBERN8_WITH_CLK_GATING;
|
hba->caps |= UFSHCD_CAP_HIBERN8_WITH_CLK_GATING;
|
||||||
hba->caps |= UFSHCD_CAP_CLK_SCALING;
|
|
||||||
}
|
}
|
||||||
hba->caps |= UFSHCD_CAP_AUTO_BKOPS_SUSPEND;
|
hba->caps |= UFSHCD_CAP_AUTO_BKOPS_SUSPEND;
|
||||||
|
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ const struct file_operations ufs_test_ ## test_name ## _ops = { \
|
|||||||
.open = ufs_test_ ## test_name ## _open, \
|
.open = ufs_test_ ## test_name ## _open, \
|
||||||
.read = seq_read, \
|
.read = seq_read, \
|
||||||
.write = ufs_test_ ## test_name ## _write, \
|
.write = ufs_test_ ## test_name ## _write, \
|
||||||
|
.release = single_release, \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define add_test(utd, test_name, upper_case_name) \
|
#define add_test(utd, test_name, upper_case_name) \
|
||||||
|
|||||||
@@ -2514,19 +2514,19 @@ static ssize_t ufshcd_clkgate_enable_store(struct device *dev,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
value = !!value;
|
value = !!value;
|
||||||
|
|
||||||
|
spin_lock_irqsave(hba->host->host_lock, flags);
|
||||||
if (value == hba->clk_gating.is_enabled)
|
if (value == hba->clk_gating.is_enabled)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (value) {
|
if (value)
|
||||||
ufshcd_release(hba, false);
|
hba->clk_gating.active_reqs--;
|
||||||
} else {
|
else
|
||||||
spin_lock_irqsave(hba->host->host_lock, flags);
|
|
||||||
hba->clk_gating.active_reqs++;
|
hba->clk_gating.active_reqs++;
|
||||||
spin_unlock_irqrestore(hba->host->host_lock, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
hba->clk_gating.is_enabled = value;
|
hba->clk_gating.is_enabled = value;
|
||||||
out:
|
out:
|
||||||
|
spin_unlock_irqrestore(hba->host->host_lock, flags);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2598,7 +2598,7 @@ static void ufshcd_init_clk_gating(struct ufs_hba *hba)
|
|||||||
snprintf(wq_name, ARRAY_SIZE(wq_name), "ufs_clk_gating_%d",
|
snprintf(wq_name, ARRAY_SIZE(wq_name), "ufs_clk_gating_%d",
|
||||||
hba->host->host_no);
|
hba->host->host_no);
|
||||||
hba->clk_gating.clk_gating_workq = alloc_ordered_workqueue(wq_name,
|
hba->clk_gating.clk_gating_workq = alloc_ordered_workqueue(wq_name,
|
||||||
WQ_MEM_RECLAIM);
|
WQ_MEM_RECLAIM | WQ_HIGHPRI);
|
||||||
|
|
||||||
gating->is_enabled = true;
|
gating->is_enabled = true;
|
||||||
|
|
||||||
|
|||||||
@@ -642,32 +642,21 @@ static int vmk80xx_find_usb_endpoints(struct comedi_device *dev)
|
|||||||
struct vmk80xx_private *devpriv = dev->private;
|
struct vmk80xx_private *devpriv = dev->private;
|
||||||
struct usb_interface *intf = comedi_to_usb_interface(dev);
|
struct usb_interface *intf = comedi_to_usb_interface(dev);
|
||||||
struct usb_host_interface *iface_desc = intf->cur_altsetting;
|
struct usb_host_interface *iface_desc = intf->cur_altsetting;
|
||||||
struct usb_endpoint_descriptor *ep_desc;
|
struct usb_endpoint_descriptor *ep_rx_desc, *ep_tx_desc;
|
||||||
int i;
|
int ret;
|
||||||
|
|
||||||
if (iface_desc->desc.bNumEndpoints != 2)
|
if (devpriv->model == VMK8061_MODEL)
|
||||||
|
ret = usb_find_common_endpoints(iface_desc, &ep_rx_desc,
|
||||||
|
&ep_tx_desc, NULL, NULL);
|
||||||
|
else
|
||||||
|
ret = usb_find_common_endpoints(iface_desc, NULL, NULL,
|
||||||
|
&ep_rx_desc, &ep_tx_desc);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
|
devpriv->ep_rx = ep_rx_desc;
|
||||||
ep_desc = &iface_desc->endpoint[i].desc;
|
devpriv->ep_tx = ep_tx_desc;
|
||||||
|
|
||||||
if (usb_endpoint_is_int_in(ep_desc) ||
|
|
||||||
usb_endpoint_is_bulk_in(ep_desc)) {
|
|
||||||
if (!devpriv->ep_rx)
|
|
||||||
devpriv->ep_rx = ep_desc;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (usb_endpoint_is_int_out(ep_desc) ||
|
|
||||||
usb_endpoint_is_bulk_out(ep_desc)) {
|
|
||||||
if (!devpriv->ep_tx)
|
|
||||||
devpriv->ep_tx = ep_desc;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!devpriv->ep_rx || !devpriv->ep_tx)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
if (!usb_endpoint_maxp(devpriv->ep_rx) || !usb_endpoint_maxp(devpriv->ep_tx))
|
if (!usb_endpoint_maxp(devpriv->ep_rx) || !usb_endpoint_maxp(devpriv->ep_tx))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|||||||
@@ -577,7 +577,7 @@ static u_long get_word(struct vc_data *vc)
|
|||||||
}
|
}
|
||||||
attr_ch = get_char(vc, (u_short *)tmp_pos, &spk_attr);
|
attr_ch = get_char(vc, (u_short *)tmp_pos, &spk_attr);
|
||||||
buf[cnt++] = attr_ch;
|
buf[cnt++] = attr_ch;
|
||||||
while (tmpx < vc->vc_cols - 1) {
|
while (tmpx < vc->vc_cols - 1 && cnt < sizeof(buf) - 1) {
|
||||||
tmp_pos += 2;
|
tmp_pos += 2;
|
||||||
tmpx++;
|
tmpx++;
|
||||||
ch = get_char(vc, (u_short *)tmp_pos, &temp);
|
ch = get_char(vc, (u_short *)tmp_pos, &temp);
|
||||||
|
|||||||
@@ -3240,6 +3240,8 @@ static int __init target_core_init_configfs(void)
|
|||||||
{
|
{
|
||||||
struct configfs_subsystem *subsys = &target_core_fabrics;
|
struct configfs_subsystem *subsys = &target_core_fabrics;
|
||||||
struct t10_alua_lu_gp *lu_gp;
|
struct t10_alua_lu_gp *lu_gp;
|
||||||
|
struct cred *kern_cred;
|
||||||
|
const struct cred *old_cred;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
pr_debug("TARGET_CORE[0]: Loading Generic Kernel Storage"
|
pr_debug("TARGET_CORE[0]: Loading Generic Kernel Storage"
|
||||||
@@ -3316,11 +3318,21 @@ static int __init target_core_init_configfs(void)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
/* We use the kernel credentials to access the target directory */
|
||||||
|
kern_cred = prepare_kernel_cred(&init_task);
|
||||||
|
if (!kern_cred) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
old_cred = override_creds(kern_cred);
|
||||||
target_init_dbroot();
|
target_init_dbroot();
|
||||||
|
revert_creds(old_cred);
|
||||||
|
put_cred(kern_cred);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
target_xcopy_release_pt();
|
||||||
configfs_unregister_subsystem(subsys);
|
configfs_unregister_subsystem(subsys);
|
||||||
core_dev_release_virtual_lun0();
|
core_dev_release_virtual_lun0();
|
||||||
rd_module_exit();
|
rd_module_exit();
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include <linux/console.h>
|
#include <linux/console.h>
|
||||||
#include <linux/vt_kern.h>
|
#include <linux/vt_kern.h>
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
#include <linux/irq_work.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
|
||||||
#define MAX_CONFIG_LEN 40
|
#define MAX_CONFIG_LEN 40
|
||||||
@@ -35,6 +36,25 @@ static int kgdboc_use_kms; /* 1 if we use kernel mode switching */
|
|||||||
static struct tty_driver *kgdb_tty_driver;
|
static struct tty_driver *kgdb_tty_driver;
|
||||||
static int kgdb_tty_line;
|
static int kgdb_tty_line;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When we leave the debug trap handler we need to reset the keyboard status
|
||||||
|
* (since the original keyboard state gets partially clobbered by kdb use of
|
||||||
|
* the keyboard).
|
||||||
|
*
|
||||||
|
* The path to deliver the reset is somewhat circuitous.
|
||||||
|
*
|
||||||
|
* To deliver the reset we register an input handler, reset the keyboard and
|
||||||
|
* then deregister the input handler. However, to get this done right, we do
|
||||||
|
* have to carefully manage the calling context because we can only register
|
||||||
|
* input handlers from task context.
|
||||||
|
*
|
||||||
|
* In particular we need to trigger the action from the debug trap handler with
|
||||||
|
* all its NMI and/or NMI-like oddities. To solve this the kgdboc trap exit code
|
||||||
|
* (the "post_exception" callback) uses irq_work_queue(), which is NMI-safe, to
|
||||||
|
* schedule a callback from a hardirq context. From there we have to defer the
|
||||||
|
* work again, this time using schedule_work(), to get a callback using the
|
||||||
|
* system workqueue, which runs in task context.
|
||||||
|
*/
|
||||||
#ifdef CONFIG_KDB_KEYBOARD
|
#ifdef CONFIG_KDB_KEYBOARD
|
||||||
static int kgdboc_reset_connect(struct input_handler *handler,
|
static int kgdboc_reset_connect(struct input_handler *handler,
|
||||||
struct input_dev *dev,
|
struct input_dev *dev,
|
||||||
@@ -86,10 +106,17 @@ static void kgdboc_restore_input_helper(struct work_struct *dummy)
|
|||||||
|
|
||||||
static DECLARE_WORK(kgdboc_restore_input_work, kgdboc_restore_input_helper);
|
static DECLARE_WORK(kgdboc_restore_input_work, kgdboc_restore_input_helper);
|
||||||
|
|
||||||
|
static void kgdboc_queue_restore_input_helper(struct irq_work *unused)
|
||||||
|
{
|
||||||
|
schedule_work(&kgdboc_restore_input_work);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEFINE_IRQ_WORK(kgdboc_restore_input_irq_work, kgdboc_queue_restore_input_helper);
|
||||||
|
|
||||||
static void kgdboc_restore_input(void)
|
static void kgdboc_restore_input(void)
|
||||||
{
|
{
|
||||||
if (likely(system_state == SYSTEM_RUNNING))
|
if (likely(system_state == SYSTEM_RUNNING))
|
||||||
schedule_work(&kgdboc_restore_input_work);
|
irq_work_queue(&kgdboc_restore_input_irq_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgdboc_register_kbd(char **cptr)
|
static int kgdboc_register_kbd(char **cptr)
|
||||||
@@ -120,6 +147,7 @@ static void kgdboc_unregister_kbd(void)
|
|||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
irq_work_sync(&kgdboc_restore_input_irq_work);
|
||||||
flush_work(&kgdboc_restore_input_work);
|
flush_work(&kgdboc_restore_input_work);
|
||||||
}
|
}
|
||||||
#else /* ! CONFIG_KDB_KEYBOARD */
|
#else /* ! CONFIG_KDB_KEYBOARD */
|
||||||
|
|||||||
@@ -1128,11 +1128,13 @@ static void mxs_auart_set_ldisc(struct uart_port *port,
|
|||||||
|
|
||||||
static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
|
static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
|
||||||
{
|
{
|
||||||
u32 istat;
|
u32 istat, stat;
|
||||||
struct mxs_auart_port *s = context;
|
struct mxs_auart_port *s = context;
|
||||||
u32 mctrl_temp = s->mctrl_prev;
|
u32 mctrl_temp = s->mctrl_prev;
|
||||||
u32 stat = mxs_read(s, REG_STAT);
|
|
||||||
|
|
||||||
|
uart_port_lock(&s->port);
|
||||||
|
|
||||||
|
stat = mxs_read(s, REG_STAT);
|
||||||
istat = mxs_read(s, REG_INTR);
|
istat = mxs_read(s, REG_INTR);
|
||||||
|
|
||||||
/* ack irq */
|
/* ack irq */
|
||||||
@@ -1168,6 +1170,8 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
|
|||||||
istat &= ~AUART_INTR_TXIS;
|
istat &= ~AUART_INTR_TXIS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uart_port_unlock(&s->port);
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -220,7 +220,6 @@ static bool pmz_receive_chars(struct uart_pmac_port *uap)
|
|||||||
{
|
{
|
||||||
struct tty_port *port;
|
struct tty_port *port;
|
||||||
unsigned char ch, r1, drop, error, flag;
|
unsigned char ch, r1, drop, error, flag;
|
||||||
int loops = 0;
|
|
||||||
|
|
||||||
/* Sanity check, make sure the old bug is no longer happening */
|
/* Sanity check, make sure the old bug is no longer happening */
|
||||||
if (uap->port.state == NULL) {
|
if (uap->port.state == NULL) {
|
||||||
@@ -303,24 +302,11 @@ static bool pmz_receive_chars(struct uart_pmac_port *uap)
|
|||||||
if (r1 & Rx_OVR)
|
if (r1 & Rx_OVR)
|
||||||
tty_insert_flip_char(port, 0, TTY_OVERRUN);
|
tty_insert_flip_char(port, 0, TTY_OVERRUN);
|
||||||
next_char:
|
next_char:
|
||||||
/* We can get stuck in an infinite loop getting char 0 when the
|
|
||||||
* line is in a wrong HW state, we break that here.
|
|
||||||
* When that happens, I disable the receive side of the driver.
|
|
||||||
* Note that what I've been experiencing is a real irq loop where
|
|
||||||
* I'm getting flooded regardless of the actual port speed.
|
|
||||||
* Something strange is going on with the HW
|
|
||||||
*/
|
|
||||||
if ((++loops) > 1000)
|
|
||||||
goto flood;
|
|
||||||
ch = read_zsreg(uap, R0);
|
ch = read_zsreg(uap, R0);
|
||||||
if (!(ch & Rx_CH_AV))
|
if (!(ch & Rx_CH_AV))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
flood:
|
|
||||||
pmz_interrupt_control(uap, 0);
|
|
||||||
pmz_error("pmz: rx irq flood !\n");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -471,7 +471,6 @@ out_free_mem:
|
|||||||
static int service_outstanding_interrupt(struct wdm_device *desc)
|
static int service_outstanding_interrupt(struct wdm_device *desc)
|
||||||
{
|
{
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
int used;
|
|
||||||
|
|
||||||
/* submit read urb only if the device is waiting for it */
|
/* submit read urb only if the device is waiting for it */
|
||||||
if (!desc->resp_count || !--desc->resp_count)
|
if (!desc->resp_count || !--desc->resp_count)
|
||||||
@@ -486,10 +485,7 @@ static int service_outstanding_interrupt(struct wdm_device *desc)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
used = test_and_set_bit(WDM_RESPONDING, &desc->flags);
|
set_bit(WDM_RESPONDING, &desc->flags);
|
||||||
if (used)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
spin_unlock_irq(&desc->iuspin);
|
spin_unlock_irq(&desc->iuspin);
|
||||||
rv = usb_submit_urb(desc->response, GFP_KERNEL);
|
rv = usb_submit_urb(desc->response, GFP_KERNEL);
|
||||||
spin_lock_irq(&desc->iuspin);
|
spin_lock_irq(&desc->iuspin);
|
||||||
|
|||||||
@@ -897,13 +897,15 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg,
|
|||||||
struct dwc2_dma_desc *dma_desc;
|
struct dwc2_dma_desc *dma_desc;
|
||||||
struct dwc2_hcd_iso_packet_desc *frame_desc;
|
struct dwc2_hcd_iso_packet_desc *frame_desc;
|
||||||
u16 frame_desc_idx;
|
u16 frame_desc_idx;
|
||||||
struct urb *usb_urb = qtd->urb->priv;
|
struct urb *usb_urb;
|
||||||
u16 remain = 0;
|
u16 remain = 0;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (!qtd->urb)
|
if (!qtd->urb)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
usb_urb = qtd->urb->priv;
|
||||||
|
|
||||||
dma_sync_single_for_cpu(hsotg->dev, qh->desc_list_dma + (idx *
|
dma_sync_single_for_cpu(hsotg->dev, qh->desc_list_dma + (idx *
|
||||||
sizeof(struct dwc2_dma_desc)),
|
sizeof(struct dwc2_dma_desc)),
|
||||||
sizeof(struct dwc2_dma_desc),
|
sizeof(struct dwc2_dma_desc),
|
||||||
|
|||||||
@@ -2062,7 +2062,7 @@ unknown:
|
|||||||
buf[5] = 0x01;
|
buf[5] = 0x01;
|
||||||
switch (ctrl->bRequestType & USB_RECIP_MASK) {
|
switch (ctrl->bRequestType & USB_RECIP_MASK) {
|
||||||
case USB_RECIP_DEVICE:
|
case USB_RECIP_DEVICE:
|
||||||
if (w_index != 0x4 || (w_value >> 8))
|
if (w_index != 0x4 || (w_value & 0xff))
|
||||||
break;
|
break;
|
||||||
buf[6] = w_index;
|
buf[6] = w_index;
|
||||||
/* Number of ext compat interfaces */
|
/* Number of ext compat interfaces */
|
||||||
@@ -2084,9 +2084,9 @@ unknown:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case USB_RECIP_INTERFACE:
|
case USB_RECIP_INTERFACE:
|
||||||
if (w_index != 0x5 || (w_value >> 8))
|
if (w_index != 0x5 || (w_value & 0xff))
|
||||||
break;
|
break;
|
||||||
interface = w_value & 0xFF;
|
interface = w_value >> 8;
|
||||||
if (interface >= MAX_CONFIG_INTERFACES ||
|
if (interface >= MAX_CONFIG_INTERFACES ||
|
||||||
!os_desc_cfg->interface[interface])
|
!os_desc_cfg->interface[interface])
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -3621,7 +3621,7 @@ static int ffs_func_setup(struct usb_function *f,
|
|||||||
__ffs_event_add(ffs, FUNCTIONFS_SETUP);
|
__ffs_event_add(ffs, FUNCTIONFS_SETUP);
|
||||||
spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags);
|
spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags);
|
||||||
|
|
||||||
return creq->wLength == 0 ? USB_GADGET_DELAYED_STATUS : 0;
|
return ffs->ev.setup.wLength == 0 ? USB_GADGET_DELAYED_STATUS : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ffs_func_req_match(struct usb_function *f,
|
static bool ffs_func_req_match(struct usb_function *f,
|
||||||
|
|||||||
@@ -255,6 +255,10 @@ static void option_instat_callback(struct urb *urb);
|
|||||||
#define QUECTEL_PRODUCT_EM061K_LMS 0x0124
|
#define QUECTEL_PRODUCT_EM061K_LMS 0x0124
|
||||||
#define QUECTEL_PRODUCT_EC25 0x0125
|
#define QUECTEL_PRODUCT_EC25 0x0125
|
||||||
#define QUECTEL_PRODUCT_EM060K_128 0x0128
|
#define QUECTEL_PRODUCT_EM060K_128 0x0128
|
||||||
|
#define QUECTEL_PRODUCT_EM060K_129 0x0129
|
||||||
|
#define QUECTEL_PRODUCT_EM060K_12a 0x012a
|
||||||
|
#define QUECTEL_PRODUCT_EM060K_12b 0x012b
|
||||||
|
#define QUECTEL_PRODUCT_EM060K_12c 0x012c
|
||||||
#define QUECTEL_PRODUCT_EG91 0x0191
|
#define QUECTEL_PRODUCT_EG91 0x0191
|
||||||
#define QUECTEL_PRODUCT_EG95 0x0195
|
#define QUECTEL_PRODUCT_EG95 0x0195
|
||||||
#define QUECTEL_PRODUCT_BG96 0x0296
|
#define QUECTEL_PRODUCT_BG96 0x0296
|
||||||
@@ -1218,6 +1222,18 @@ static const struct usb_device_id option_ids[] = {
|
|||||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_128, 0xff, 0xff, 0x30) },
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_128, 0xff, 0xff, 0x30) },
|
||||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_128, 0xff, 0x00, 0x40) },
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_128, 0xff, 0x00, 0x40) },
|
||||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_128, 0xff, 0xff, 0x40) },
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_128, 0xff, 0xff, 0x40) },
|
||||||
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_129, 0xff, 0xff, 0x30) },
|
||||||
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_129, 0xff, 0x00, 0x40) },
|
||||||
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_129, 0xff, 0xff, 0x40) },
|
||||||
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12a, 0xff, 0xff, 0x30) },
|
||||||
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12a, 0xff, 0x00, 0x40) },
|
||||||
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12a, 0xff, 0xff, 0x40) },
|
||||||
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12b, 0xff, 0xff, 0x30) },
|
||||||
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12b, 0xff, 0x00, 0x40) },
|
||||||
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12b, 0xff, 0xff, 0x40) },
|
||||||
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12c, 0xff, 0xff, 0x30) },
|
||||||
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12c, 0xff, 0x00, 0x40) },
|
||||||
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12c, 0xff, 0xff, 0x40) },
|
||||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM061K_LCN, 0xff, 0xff, 0x30) },
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM061K_LCN, 0xff, 0xff, 0x30) },
|
||||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM061K_LCN, 0xff, 0x00, 0x40) },
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM061K_LCN, 0xff, 0x00, 0x40) },
|
||||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM061K_LCN, 0xff, 0xff, 0x40) },
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM061K_LCN, 0xff, 0xff, 0x40) },
|
||||||
@@ -1360,6 +1376,12 @@ static const struct usb_device_id option_ids[] = {
|
|||||||
.driver_info = NCTRL(2) | RSVD(3) },
|
.driver_info = NCTRL(2) | RSVD(3) },
|
||||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1083, 0xff), /* Telit FE990 (ECM) */
|
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1083, 0xff), /* Telit FE990 (ECM) */
|
||||||
.driver_info = NCTRL(0) | RSVD(1) },
|
.driver_info = NCTRL(0) | RSVD(1) },
|
||||||
|
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a0, 0xff), /* Telit FN20C04 (rmnet) */
|
||||||
|
.driver_info = RSVD(0) | NCTRL(3) },
|
||||||
|
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a4, 0xff), /* Telit FN20C04 (rmnet) */
|
||||||
|
.driver_info = RSVD(0) | NCTRL(3) },
|
||||||
|
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a9, 0xff), /* Telit FN20C04 (rmnet) */
|
||||||
|
.driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) },
|
||||||
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910),
|
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910),
|
||||||
.driver_info = NCTRL(0) | RSVD(1) | RSVD(3) },
|
.driver_info = NCTRL(0) | RSVD(1) | RSVD(3) },
|
||||||
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM),
|
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM),
|
||||||
@@ -2052,6 +2074,10 @@ static const struct usb_device_id option_ids[] = {
|
|||||||
.driver_info = RSVD(3) },
|
.driver_info = RSVD(3) },
|
||||||
{ USB_DEVICE_INTERFACE_CLASS(LONGCHEER_VENDOR_ID, 0x9803, 0xff),
|
{ USB_DEVICE_INTERFACE_CLASS(LONGCHEER_VENDOR_ID, 0x9803, 0xff),
|
||||||
.driver_info = RSVD(4) },
|
.driver_info = RSVD(4) },
|
||||||
|
{ USB_DEVICE(LONGCHEER_VENDOR_ID, 0x9b05), /* Longsung U8300 */
|
||||||
|
.driver_info = RSVD(4) | RSVD(5) },
|
||||||
|
{ USB_DEVICE(LONGCHEER_VENDOR_ID, 0x9b3c), /* Longsung U9300 */
|
||||||
|
.driver_info = RSVD(0) | RSVD(4) },
|
||||||
{ USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) },
|
{ USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) },
|
||||||
{ USB_DEVICE(LONGCHEER_VENDOR_ID, IBALL_3_5G_CONNECT) },
|
{ USB_DEVICE(LONGCHEER_VENDOR_ID, IBALL_3_5G_CONNECT) },
|
||||||
{ USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) },
|
{ USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) },
|
||||||
@@ -2272,15 +2298,29 @@ static const struct usb_device_id option_ids[] = {
|
|||||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0xff, 0x30) }, /* Fibocom FG150 Diag */
|
{ USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0xff, 0x30) }, /* Fibocom FG150 Diag */
|
||||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0, 0) }, /* Fibocom FG150 AT */
|
{ USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0, 0) }, /* Fibocom FG150 AT */
|
||||||
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0111, 0xff) }, /* Fibocom FM160 (MBIM mode) */
|
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0111, 0xff) }, /* Fibocom FM160 (MBIM mode) */
|
||||||
|
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0115, 0xff), /* Fibocom FM135 (laptop MBIM) */
|
||||||
|
.driver_info = RSVD(5) },
|
||||||
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a0, 0xff) }, /* Fibocom NL668-AM/NL652-EU (laptop MBIM) */
|
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a0, 0xff) }, /* Fibocom NL668-AM/NL652-EU (laptop MBIM) */
|
||||||
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a2, 0xff) }, /* Fibocom FM101-GL (laptop MBIM) */
|
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a2, 0xff) }, /* Fibocom FM101-GL (laptop MBIM) */
|
||||||
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a3, 0xff) }, /* Fibocom FM101-GL (laptop MBIM) */
|
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a3, 0xff) }, /* Fibocom FM101-GL (laptop MBIM) */
|
||||||
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a4, 0xff), /* Fibocom FM101-GL (laptop MBIM) */
|
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a4, 0xff), /* Fibocom FM101-GL (laptop MBIM) */
|
||||||
.driver_info = RSVD(4) },
|
.driver_info = RSVD(4) },
|
||||||
|
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a04, 0xff) }, /* Fibocom FM650-CN (ECM mode) */
|
||||||
|
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a05, 0xff) }, /* Fibocom FM650-CN (NCM mode) */
|
||||||
|
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a06, 0xff) }, /* Fibocom FM650-CN (RNDIS mode) */
|
||||||
|
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a07, 0xff) }, /* Fibocom FM650-CN (MBIM mode) */
|
||||||
{ USB_DEVICE_INTERFACE_CLASS(0x2df3, 0x9d03, 0xff) }, /* LongSung M5710 */
|
{ USB_DEVICE_INTERFACE_CLASS(0x2df3, 0x9d03, 0xff) }, /* LongSung M5710 */
|
||||||
{ USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) }, /* GosunCn GM500 RNDIS */
|
{ USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) }, /* GosunCn GM500 RNDIS */
|
||||||
{ USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) }, /* GosunCn GM500 MBIM */
|
{ USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) }, /* GosunCn GM500 MBIM */
|
||||||
{ USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1406, 0xff) }, /* GosunCn GM500 ECM/NCM */
|
{ USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1406, 0xff) }, /* GosunCn GM500 ECM/NCM */
|
||||||
|
{ USB_DEVICE(0x33f8, 0x0104), /* Rolling RW101-GL (laptop RMNET) */
|
||||||
|
.driver_info = RSVD(4) | RSVD(5) },
|
||||||
|
{ USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x01a2, 0xff) }, /* Rolling RW101-GL (laptop MBIM) */
|
||||||
|
{ USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x01a3, 0xff) }, /* Rolling RW101-GL (laptop MBIM) */
|
||||||
|
{ USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x01a4, 0xff), /* Rolling RW101-GL (laptop MBIM) */
|
||||||
|
.driver_info = RSVD(4) },
|
||||||
|
{ USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x0115, 0xff), /* Rolling RW135-GL (laptop MBIM) */
|
||||||
|
.driver_info = RSVD(5) },
|
||||||
{ USB_DEVICE_AND_INTERFACE_INFO(OPPO_VENDOR_ID, OPPO_PRODUCT_R11, 0xff, 0xff, 0x30) },
|
{ 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, 0x30) },
|
||||||
{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x40) },
|
{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x40) },
|
||||||
|
|||||||
+12
-2
@@ -2432,9 +2432,19 @@ bool vhost_vq_avail_empty(struct vhost_dev *dev, struct vhost_virtqueue *vq)
|
|||||||
r = vhost_get_avail(vq, avail_idx, &vq->avail->idx);
|
r = vhost_get_avail(vq, avail_idx, &vq->avail->idx);
|
||||||
if (unlikely(r))
|
if (unlikely(r))
|
||||||
return false;
|
return false;
|
||||||
vq->avail_idx = vhost16_to_cpu(vq, avail_idx);
|
|
||||||
|
|
||||||
return vq->avail_idx == vq->last_avail_idx;
|
vq->avail_idx = vhost16_to_cpu(vq, avail_idx);
|
||||||
|
if (vq->avail_idx != vq->last_avail_idx) {
|
||||||
|
/* Since we have updated avail_idx, the following
|
||||||
|
* call to vhost_get_vq_desc() will read available
|
||||||
|
* ring entries. Make sure that read happens after
|
||||||
|
* the avail_idx read.
|
||||||
|
*/
|
||||||
|
smp_rmb();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(vhost_vq_avail_empty);
|
EXPORT_SYMBOL_GPL(vhost_vq_avail_empty);
|
||||||
|
|
||||||
|
|||||||
@@ -691,6 +691,7 @@ const struct file_operations v9fs_file_operations = {
|
|||||||
.lock = v9fs_file_lock,
|
.lock = v9fs_file_lock,
|
||||||
.mmap = generic_file_readonly_mmap,
|
.mmap = generic_file_readonly_mmap,
|
||||||
.fsync = v9fs_file_fsync,
|
.fsync = v9fs_file_fsync,
|
||||||
|
.setlease = simple_nosetlease,
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct file_operations v9fs_file_operations_dotl = {
|
const struct file_operations v9fs_file_operations_dotl = {
|
||||||
@@ -726,4 +727,5 @@ const struct file_operations v9fs_mmap_file_operations_dotl = {
|
|||||||
.flock = v9fs_file_flock_dotl,
|
.flock = v9fs_file_flock_dotl,
|
||||||
.mmap = v9fs_mmap_file_mmap,
|
.mmap = v9fs_mmap_file_mmap,
|
||||||
.fsync = v9fs_file_fsync_dotl,
|
.fsync = v9fs_file_fsync_dotl,
|
||||||
|
.setlease = simple_nosetlease,
|
||||||
};
|
};
|
||||||
+4
-1
@@ -101,7 +101,7 @@ static int p9mode2perm(struct v9fs_session_info *v9ses,
|
|||||||
int res;
|
int res;
|
||||||
int mode = stat->mode;
|
int mode = stat->mode;
|
||||||
|
|
||||||
res = mode & S_IALLUGO;
|
res = mode & 0777; /* S_IRWXUGO */
|
||||||
if (v9fs_proto_dotu(v9ses)) {
|
if (v9fs_proto_dotu(v9ses)) {
|
||||||
if ((mode & P9_DMSETUID) == P9_DMSETUID)
|
if ((mode & P9_DMSETUID) == P9_DMSETUID)
|
||||||
res |= S_ISUID;
|
res |= S_ISUID;
|
||||||
@@ -192,6 +192,9 @@ int v9fs_uflags2omode(int uflags, int extended)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (uflags & O_TRUNC)
|
||||||
|
ret |= P9_OTRUNC;
|
||||||
|
|
||||||
if (extended) {
|
if (extended) {
|
||||||
if (uflags & O_EXCL)
|
if (uflags & O_EXCL)
|
||||||
ret |= P9_OEXCL;
|
ret |= P9_OEXCL;
|
||||||
|
|||||||
@@ -346,6 +346,7 @@ static const struct super_operations v9fs_super_ops = {
|
|||||||
.alloc_inode = v9fs_alloc_inode,
|
.alloc_inode = v9fs_alloc_inode,
|
||||||
.destroy_inode = v9fs_destroy_inode,
|
.destroy_inode = v9fs_destroy_inode,
|
||||||
.statfs = simple_statfs,
|
.statfs = simple_statfs,
|
||||||
|
.drop_inode = v9fs_drop_inode,
|
||||||
.evict_inode = v9fs_evict_inode,
|
.evict_inode = v9fs_evict_inode,
|
||||||
.show_options = v9fs_show_options,
|
.show_options = v9fs_show_options,
|
||||||
.umount_begin = v9fs_umount_begin,
|
.umount_begin = v9fs_umount_begin,
|
||||||
|
|||||||
+3
-9
@@ -2236,20 +2236,14 @@ struct btrfs_data_container *init_data_container(u32 total_bytes)
|
|||||||
size_t alloc_bytes;
|
size_t alloc_bytes;
|
||||||
|
|
||||||
alloc_bytes = max_t(size_t, total_bytes, sizeof(*data));
|
alloc_bytes = max_t(size_t, total_bytes, sizeof(*data));
|
||||||
data = kvmalloc(alloc_bytes, GFP_KERNEL);
|
data = kvzalloc(alloc_bytes, GFP_KERNEL);
|
||||||
if (!data)
|
if (!data)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
if (total_bytes >= sizeof(*data)) {
|
if (total_bytes >= sizeof(*data))
|
||||||
data->bytes_left = total_bytes - sizeof(*data);
|
data->bytes_left = total_bytes - sizeof(*data);
|
||||||
data->bytes_missing = 0;
|
else
|
||||||
} else {
|
|
||||||
data->bytes_missing = sizeof(*data) - total_bytes;
|
data->bytes_missing = sizeof(*data) - total_bytes;
|
||||||
data->bytes_left = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
data->elem_cnt = 0;
|
|
||||||
data->elem_missed = 0;
|
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1133,6 +1133,9 @@ __btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
ret = btrfs_record_root_in_trans(trans, node->root);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
ret = btrfs_update_delayed_inode(trans, node->root, path, node);
|
ret = btrfs_update_delayed_inode(trans, node->root, path, node);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1906,7 +1906,7 @@ static void btrfs_clear_bit_hook(void *private_data,
|
|||||||
*/
|
*/
|
||||||
if (*bits & EXTENT_CLEAR_META_RESV &&
|
if (*bits & EXTENT_CLEAR_META_RESV &&
|
||||||
root != fs_info->tree_root)
|
root != fs_info->tree_root)
|
||||||
btrfs_delalloc_release_metadata(inode, len, false);
|
btrfs_delalloc_release_metadata(inode, len, true);
|
||||||
|
|
||||||
/* For sanity tests. */
|
/* For sanity tests. */
|
||||||
if (btrfs_is_testing(fs_info))
|
if (btrfs_is_testing(fs_info))
|
||||||
|
|||||||
@@ -1271,6 +1271,7 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans)
|
|||||||
radix_tree_tag_clear(&fs_info->fs_roots_radix,
|
radix_tree_tag_clear(&fs_info->fs_roots_radix,
|
||||||
(unsigned long)root->root_key.objectid,
|
(unsigned long)root->root_key.objectid,
|
||||||
BTRFS_ROOT_TRANS_TAG);
|
BTRFS_ROOT_TRANS_TAG);
|
||||||
|
btrfs_qgroup_free_meta_all_pertrans(root);
|
||||||
spin_unlock(&fs_info->fs_roots_radix_lock);
|
spin_unlock(&fs_info->fs_roots_radix_lock);
|
||||||
|
|
||||||
btrfs_free_log(trans, root);
|
btrfs_free_log(trans, root);
|
||||||
@@ -1295,7 +1296,6 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans)
|
|||||||
if (ret2)
|
if (ret2)
|
||||||
return ret2;
|
return ret2;
|
||||||
spin_lock(&fs_info->fs_roots_radix_lock);
|
spin_lock(&fs_info->fs_roots_radix_lock);
|
||||||
btrfs_qgroup_free_meta_all_pertrans(root);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_unlock(&fs_info->fs_roots_radix_lock);
|
spin_unlock(&fs_info->fs_roots_radix_lock);
|
||||||
|
|||||||
@@ -2957,6 +2957,7 @@ again:
|
|||||||
* alignment and size).
|
* alignment and size).
|
||||||
*/
|
*/
|
||||||
ret = -EUCLEAN;
|
ret = -EUCLEAN;
|
||||||
|
mutex_unlock(&fs_info->delete_unused_bgs_mutex);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -1751,7 +1751,8 @@ static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length)
|
|||||||
struct buffer_head *dibh, *bh;
|
struct buffer_head *dibh, *bh;
|
||||||
struct gfs2_holder rd_gh;
|
struct gfs2_holder rd_gh;
|
||||||
unsigned int bsize_shift = sdp->sd_sb.sb_bsize_shift;
|
unsigned int bsize_shift = sdp->sd_sb.sb_bsize_shift;
|
||||||
u64 lblock = (offset + (1 << bsize_shift) - 1) >> bsize_shift;
|
unsigned int bsize = 1 << bsize_shift;
|
||||||
|
u64 lblock = (offset + bsize - 1) >> bsize_shift;
|
||||||
__u16 start_list[GFS2_MAX_META_HEIGHT];
|
__u16 start_list[GFS2_MAX_META_HEIGHT];
|
||||||
__u16 __end_list[GFS2_MAX_META_HEIGHT], *end_list = NULL;
|
__u16 __end_list[GFS2_MAX_META_HEIGHT], *end_list = NULL;
|
||||||
unsigned int start_aligned, end_aligned;
|
unsigned int start_aligned, end_aligned;
|
||||||
@@ -1762,7 +1763,7 @@ static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length)
|
|||||||
u64 prev_bnr = 0;
|
u64 prev_bnr = 0;
|
||||||
__be64 *start, *end;
|
__be64 *start, *end;
|
||||||
|
|
||||||
if (offset >= maxsize) {
|
if (offset + bsize - 1 >= maxsize) {
|
||||||
/*
|
/*
|
||||||
* The starting point lies beyond the allocated meta-data;
|
* The starting point lies beyond the allocated meta-data;
|
||||||
* there are no blocks do deallocate.
|
* there are no blocks do deallocate.
|
||||||
|
|||||||
+1
-1
@@ -243,7 +243,7 @@ nilfs_filetype_table[NILFS_FT_MAX] = {
|
|||||||
|
|
||||||
#define S_SHIFT 12
|
#define S_SHIFT 12
|
||||||
static unsigned char
|
static unsigned char
|
||||||
nilfs_type_by_mode[S_IFMT >> S_SHIFT] = {
|
nilfs_type_by_mode[(S_IFMT >> S_SHIFT) + 1] = {
|
||||||
[S_IFREG >> S_SHIFT] = NILFS_FT_REG_FILE,
|
[S_IFREG >> S_SHIFT] = NILFS_FT_REG_FILE,
|
||||||
[S_IFDIR >> S_SHIFT] = NILFS_FT_DIR,
|
[S_IFDIR >> S_SHIFT] = NILFS_FT_DIR,
|
||||||
[S_IFCHR >> S_SHIFT] = NILFS_FT_CHRDEV,
|
[S_IFCHR >> S_SHIFT] = NILFS_FT_CHRDEV,
|
||||||
|
|||||||
@@ -431,6 +431,8 @@ struct kernfs_node *sysfs_break_active_protection(struct kobject *kobj,
|
|||||||
kn = kernfs_find_and_get(kobj->sd, attr->name);
|
kn = kernfs_find_and_get(kobj->sd, attr->name);
|
||||||
if (kn)
|
if (kn)
|
||||||
kernfs_break_active_protection(kn);
|
kernfs_break_active_protection(kn);
|
||||||
|
else
|
||||||
|
kobject_put(kobj);
|
||||||
return kn;
|
return kn;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(sysfs_break_active_protection);
|
EXPORT_SYMBOL_GPL(sysfs_break_active_protection);
|
||||||
|
|||||||
@@ -522,6 +522,52 @@ static inline unsigned long compare_ether_header(const void *a, const void *b)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* eth_hw_addr_gen - Generate and assign Ethernet address to a port
|
||||||
|
* @dev: pointer to port's net_device structure
|
||||||
|
* @base_addr: base Ethernet address
|
||||||
|
* @id: offset to add to the base address
|
||||||
|
*
|
||||||
|
* Generate a MAC address using a base address and an offset and assign it
|
||||||
|
* to a net_device. Commonly used by switch drivers which need to compute
|
||||||
|
* addresses for all their ports. addr_assign_type is not changed.
|
||||||
|
*/
|
||||||
|
static inline void eth_hw_addr_gen(struct net_device *dev, const u8 *base_addr,
|
||||||
|
unsigned int id)
|
||||||
|
{
|
||||||
|
u64 u = ether_addr_to_u64(base_addr);
|
||||||
|
u8 addr[ETH_ALEN];
|
||||||
|
|
||||||
|
u += id;
|
||||||
|
u64_to_ether_addr(u, addr);
|
||||||
|
eth_hw_addr_set(dev, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* eth_skb_pkt_type - Assign packet type if destination address does not match
|
||||||
|
* @skb: Assigned a packet type if address does not match @dev address
|
||||||
|
* @dev: Network device used to compare packet address against
|
||||||
|
*
|
||||||
|
* If the destination MAC address of the packet does not match the network
|
||||||
|
* device address, assign an appropriate packet type.
|
||||||
|
*/
|
||||||
|
static inline void eth_skb_pkt_type(struct sk_buff *skb,
|
||||||
|
const struct net_device *dev)
|
||||||
|
{
|
||||||
|
const struct ethhdr *eth = eth_hdr(skb);
|
||||||
|
|
||||||
|
if (unlikely(!ether_addr_equal_64bits(eth->h_dest, dev->dev_addr))) {
|
||||||
|
if (unlikely(is_multicast_ether_addr_64bits(eth->h_dest))) {
|
||||||
|
if (ether_addr_equal_64bits(eth->h_dest, dev->broadcast))
|
||||||
|
skb->pkt_type = PACKET_BROADCAST;
|
||||||
|
else
|
||||||
|
skb->pkt_type = PACKET_MULTICAST;
|
||||||
|
} else {
|
||||||
|
skb->pkt_type = PACKET_OTHERHOST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* eth_skb_pad - Pad buffer to mininum number of octets for Ethernet frame
|
* eth_skb_pad - Pad buffer to mininum number of octets for Ethernet frame
|
||||||
* @skb: Buffer to pad
|
* @skb: Buffer to pad
|
||||||
|
|||||||
@@ -890,11 +890,13 @@ struct ipa_rx_data {
|
|||||||
* @page: skb page
|
* @page: skb page
|
||||||
* @dma_addr: DMA address of this Rx packet
|
* @dma_addr: DMA address of this Rx packet
|
||||||
* @is_tmp_alloc: skb page from tmp_alloc or recycle_list
|
* @is_tmp_alloc: skb page from tmp_alloc or recycle_list
|
||||||
|
* @page_order: page order associated with the page.
|
||||||
*/
|
*/
|
||||||
struct ipa_rx_page_data {
|
struct ipa_rx_page_data {
|
||||||
struct page *page;
|
struct page *page;
|
||||||
dma_addr_t dma_addr;
|
dma_addr_t dma_addr;
|
||||||
bool is_tmp_alloc;
|
bool is_tmp_alloc;
|
||||||
|
u32 page_order;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -264,6 +264,85 @@ struct uart_port {
|
|||||||
void *private_data; /* generic platform data pointer */
|
void *private_data; /* generic platform data pointer */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* uart_port_lock - Lock the UART port
|
||||||
|
* @up: Pointer to UART port structure
|
||||||
|
*/
|
||||||
|
static inline void uart_port_lock(struct uart_port *up)
|
||||||
|
{
|
||||||
|
spin_lock(&up->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* uart_port_lock_irq - Lock the UART port and disable interrupts
|
||||||
|
* @up: Pointer to UART port structure
|
||||||
|
*/
|
||||||
|
static inline void uart_port_lock_irq(struct uart_port *up)
|
||||||
|
{
|
||||||
|
spin_lock_irq(&up->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* uart_port_lock_irqsave - Lock the UART port, save and disable interrupts
|
||||||
|
* @up: Pointer to UART port structure
|
||||||
|
* @flags: Pointer to interrupt flags storage
|
||||||
|
*/
|
||||||
|
static inline void uart_port_lock_irqsave(struct uart_port *up, unsigned long *flags)
|
||||||
|
{
|
||||||
|
spin_lock_irqsave(&up->lock, *flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* uart_port_trylock - Try to lock the UART port
|
||||||
|
* @up: Pointer to UART port structure
|
||||||
|
*
|
||||||
|
* Returns: True if lock was acquired, false otherwise
|
||||||
|
*/
|
||||||
|
static inline bool uart_port_trylock(struct uart_port *up)
|
||||||
|
{
|
||||||
|
return spin_trylock(&up->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* uart_port_trylock_irqsave - Try to lock the UART port, save and disable interrupts
|
||||||
|
* @up: Pointer to UART port structure
|
||||||
|
* @flags: Pointer to interrupt flags storage
|
||||||
|
*
|
||||||
|
* Returns: True if lock was acquired, false otherwise
|
||||||
|
*/
|
||||||
|
static inline bool uart_port_trylock_irqsave(struct uart_port *up, unsigned long *flags)
|
||||||
|
{
|
||||||
|
return spin_trylock_irqsave(&up->lock, *flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* uart_port_unlock - Unlock the UART port
|
||||||
|
* @up: Pointer to UART port structure
|
||||||
|
*/
|
||||||
|
static inline void uart_port_unlock(struct uart_port *up)
|
||||||
|
{
|
||||||
|
spin_unlock(&up->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* uart_port_unlock_irq - Unlock the UART port and re-enable interrupts
|
||||||
|
* @up: Pointer to UART port structure
|
||||||
|
*/
|
||||||
|
static inline void uart_port_unlock_irq(struct uart_port *up)
|
||||||
|
{
|
||||||
|
spin_unlock_irq(&up->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* uart_port_unlock_irqrestore - Unlock the UART port, restore interrupts
|
||||||
|
* @up: Pointer to UART port structure
|
||||||
|
* @flags: The saved interrupt flags for restore
|
||||||
|
*/
|
||||||
|
static inline void uart_port_unlock_irqrestore(struct uart_port *up, unsigned long flags)
|
||||||
|
{
|
||||||
|
spin_unlock_irqrestore(&up->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
static inline int serial_port_in(struct uart_port *up, int offset)
|
static inline int serial_port_in(struct uart_port *up, int offset)
|
||||||
{
|
{
|
||||||
return up->serial_in(up, offset);
|
return up->serial_in(up, offset);
|
||||||
|
|||||||
@@ -494,4 +494,24 @@ static inline void memcpy_and_pad(void *dest, size_t dest_len,
|
|||||||
memcpy(dest, src, dest_len);
|
memcpy(dest, src, dest_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* str_has_prefix - Test if a string has a given prefix
|
||||||
|
* @str: The string to test
|
||||||
|
* @prefix: The string to see if @str starts with
|
||||||
|
*
|
||||||
|
* A common way to test a prefix of a string is to do:
|
||||||
|
* strncmp(str, prefix, sizeof(prefix) - 1)
|
||||||
|
*
|
||||||
|
* But this can lead to bugs due to typos, or if prefix is a pointer
|
||||||
|
* and not a constant. Instead use str_has_prefix().
|
||||||
|
*
|
||||||
|
* Returns: 0 if @str does not start with @prefix
|
||||||
|
strlen(@prefix) if @str does start with @prefix
|
||||||
|
*/
|
||||||
|
static __always_inline size_t str_has_prefix(const char *str, const char *prefix)
|
||||||
|
{
|
||||||
|
size_t len = strlen(prefix);
|
||||||
|
return strncmp(str, prefix, len) == 0 ? len : 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* _LINUX_STRING_H_ */
|
#endif /* _LINUX_STRING_H_ */
|
||||||
@@ -416,7 +416,7 @@ struct trace_event_file {
|
|||||||
} \
|
} \
|
||||||
early_initcall(trace_init_perf_perm_##name);
|
early_initcall(trace_init_perf_perm_##name);
|
||||||
|
|
||||||
#define PERF_MAX_TRACE_SIZE 2048
|
#define PERF_MAX_TRACE_SIZE 8192
|
||||||
|
|
||||||
#define MAX_FILTER_STR_VAL 256 /* Should handle KSYM_SYMBOL_LEN */
|
#define MAX_FILTER_STR_VAL 256 /* Should handle KSYM_SYMBOL_LEN */
|
||||||
|
|
||||||
@@ -531,8 +531,6 @@ extern int trace_event_raw_init(struct trace_event_call *call);
|
|||||||
extern int trace_define_field(struct trace_event_call *call, const char *type,
|
extern int trace_define_field(struct trace_event_call *call, const char *type,
|
||||||
const char *name, int offset, int size,
|
const char *name, int offset, int size,
|
||||||
int is_signed, int filter_type);
|
int is_signed, int filter_type);
|
||||||
extern int trace_add_event_call_nolock(struct trace_event_call *call);
|
|
||||||
extern int trace_remove_event_call_nolock(struct trace_event_call *call);
|
|
||||||
extern int trace_add_event_call(struct trace_event_call *call);
|
extern int trace_add_event_call(struct trace_event_call *call);
|
||||||
extern int trace_remove_event_call(struct trace_event_call *call);
|
extern int trace_remove_event_call(struct trace_event_call *call);
|
||||||
extern int trace_event_get_offsets(struct trace_event_call *call);
|
extern int trace_event_get_offsets(struct trace_event_call *call);
|
||||||
|
|||||||
@@ -455,6 +455,10 @@ static inline void in6_ifa_hold(struct inet6_ifaddr *ifp)
|
|||||||
refcount_inc(&ifp->refcnt);
|
refcount_inc(&ifp->refcnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool in6_ifa_hold_safe(struct inet6_ifaddr *ifp)
|
||||||
|
{
|
||||||
|
return refcount_inc_not_zero(&ifp->refcnt);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* compute link-local solicited-node multicast address
|
* compute link-local solicited-node multicast address
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ struct unix_sock {
|
|||||||
struct mutex iolock, bindlock;
|
struct mutex iolock, bindlock;
|
||||||
struct sock *peer;
|
struct sock *peer;
|
||||||
struct list_head link;
|
struct list_head link;
|
||||||
atomic_long_t inflight;
|
unsigned long inflight;
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
unsigned long gc_flags;
|
unsigned long gc_flags;
|
||||||
#define UNIX_GC_CANDIDATE 0
|
#define UNIX_GC_CANDIDATE 0
|
||||||
@@ -72,6 +72,9 @@ enum unix_socket_lock_class {
|
|||||||
U_LOCK_NORMAL,
|
U_LOCK_NORMAL,
|
||||||
U_LOCK_SECOND, /* for double locking, see unix_state_double_lock(). */
|
U_LOCK_SECOND, /* for double locking, see unix_state_double_lock(). */
|
||||||
U_LOCK_DIAG, /* used while dumping icons, see sk_diag_dump_icons(). */
|
U_LOCK_DIAG, /* used while dumping icons, see sk_diag_dump_icons(). */
|
||||||
|
U_LOCK_GC_LISTENER, /* used for listening socket while determining gc
|
||||||
|
* candidates to close a small race window.
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void unix_state_lock_nested(struct sock *sk,
|
static inline void unix_state_lock_nested(struct sock *sk,
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ struct dst_ops {
|
|||||||
void (*destroy)(struct dst_entry *);
|
void (*destroy)(struct dst_entry *);
|
||||||
void (*ifdown)(struct dst_entry *,
|
void (*ifdown)(struct dst_entry *,
|
||||||
struct net_device *dev, int how);
|
struct net_device *dev, int how);
|
||||||
struct dst_entry * (*negative_advice)(struct dst_entry *);
|
void (*negative_advice)(struct sock *sk, struct dst_entry *);
|
||||||
void (*link_failure)(struct sk_buff *);
|
void (*link_failure)(struct sk_buff *);
|
||||||
void (*update_pmtu)(struct dst_entry *dst, struct sock *sk,
|
void (*update_pmtu)(struct dst_entry *dst, struct sock *sk,
|
||||||
struct sk_buff *skb, u32 mtu,
|
struct sk_buff *skb, u32 mtu,
|
||||||
|
|||||||
@@ -348,6 +348,39 @@ static inline bool pskb_inet_may_pull(struct sk_buff *skb)
|
|||||||
return pskb_network_may_pull(skb, nhlen);
|
return pskb_network_may_pull(skb, nhlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Variant of pskb_inet_may_pull().
|
||||||
|
*/
|
||||||
|
static inline bool skb_vlan_inet_prepare(struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
int nhlen = 0, maclen = ETH_HLEN;
|
||||||
|
__be16 type = skb->protocol;
|
||||||
|
|
||||||
|
/* Essentially this is skb_protocol(skb, true)
|
||||||
|
* And we get MAC len.
|
||||||
|
*/
|
||||||
|
if (eth_type_vlan(type))
|
||||||
|
type = __vlan_get_protocol(skb, type, &maclen);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
#if IS_ENABLED(CONFIG_IPV6)
|
||||||
|
case htons(ETH_P_IPV6):
|
||||||
|
nhlen = sizeof(struct ipv6hdr);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case htons(ETH_P_IP):
|
||||||
|
nhlen = sizeof(struct iphdr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* For ETH_P_IPV6/ETH_P_IP we make sure to pull
|
||||||
|
* a base network header in skb->head.
|
||||||
|
*/
|
||||||
|
if (!pskb_may_pull(skb, maclen + nhlen))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
skb_set_network_header(skb, maclen);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int ip_encap_hlen(struct ip_tunnel_encap *e)
|
static inline int ip_encap_hlen(struct ip_tunnel_encap *e)
|
||||||
{
|
{
|
||||||
const struct ip_tunnel_encap_ops *ops;
|
const struct ip_tunnel_encap_ops *ops;
|
||||||
|
|||||||
+3
-10
@@ -1924,19 +1924,12 @@ sk_dst_get(struct sock *sk)
|
|||||||
|
|
||||||
static inline void dst_negative_advice(struct sock *sk)
|
static inline void dst_negative_advice(struct sock *sk)
|
||||||
{
|
{
|
||||||
struct dst_entry *ndst, *dst = __sk_dst_get(sk);
|
struct dst_entry *dst = __sk_dst_get(sk);
|
||||||
|
|
||||||
sk_rethink_txhash(sk);
|
sk_rethink_txhash(sk);
|
||||||
|
|
||||||
if (dst && dst->ops->negative_advice) {
|
if (dst && dst->ops->negative_advice)
|
||||||
ndst = dst->ops->negative_advice(dst);
|
dst->ops->negative_advice(sk, dst);
|
||||||
|
|
||||||
if (ndst != dst) {
|
|
||||||
rcu_assign_pointer(sk->sk_dst_cache, ndst);
|
|
||||||
sk_tx_queue_clear(sk);
|
|
||||||
WRITE_ONCE(sk->sk_dst_pending_confirm, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
|||||||
@@ -22,8 +22,8 @@
|
|||||||
#define RUSAGE_THREAD 1 /* only the calling thread */
|
#define RUSAGE_THREAD 1 /* only the calling thread */
|
||||||
|
|
||||||
struct rusage {
|
struct rusage {
|
||||||
struct __kernel_old_timeval ru_utime; /* user time used */
|
struct timeval ru_utime; /* user time used */
|
||||||
struct __kernel_old_timeval ru_stime; /* system time used */
|
struct timeval ru_stime; /* system time used */
|
||||||
__kernel_long_t ru_maxrss; /* maximum resident set size */
|
__kernel_long_t ru_maxrss; /* maximum resident set size */
|
||||||
__kernel_long_t ru_ixrss; /* integral shared memory size */
|
__kernel_long_t ru_ixrss; /* integral shared memory size */
|
||||||
__kernel_long_t ru_idrss; /* integral unshared data size */
|
__kernel_long_t ru_idrss; /* integral unshared data size */
|
||||||
|
|||||||
@@ -167,6 +167,24 @@ done:
|
|||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* match_dev_by_label - callback for finding a partition using its label
|
||||||
|
* @dev: device passed in by the caller
|
||||||
|
* @data: opaque pointer to the label to match
|
||||||
|
*
|
||||||
|
* Returns 1 if the device matches, and 0 otherwise.
|
||||||
|
*/
|
||||||
|
static int match_dev_by_label(struct device *dev, const void *data)
|
||||||
|
{
|
||||||
|
const char *label = data;
|
||||||
|
struct hd_struct *part = dev_to_part(dev);
|
||||||
|
|
||||||
|
if (part->info && !strcmp(label, part->info->volname))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -190,6 +208,8 @@ done:
|
|||||||
* a partition with a known unique id.
|
* a partition with a known unique id.
|
||||||
* 8) <major>:<minor> major and minor number of the device separated by
|
* 8) <major>:<minor> major and minor number of the device separated by
|
||||||
* a colon.
|
* a colon.
|
||||||
|
* 9) PARTLABEL=<name> with name being the GPT partition label.
|
||||||
|
* MSDOS partitions do not support labels!
|
||||||
*
|
*
|
||||||
* If name doesn't have fall into the categories above, we return (0,0).
|
* If name doesn't have fall into the categories above, we return (0,0).
|
||||||
* block_class is used to check if something is a disk name. If the disk
|
* block_class is used to check if something is a disk name. If the disk
|
||||||
@@ -211,6 +231,17 @@ dev_t name_to_dev_t(const char *name)
|
|||||||
if (!res)
|
if (!res)
|
||||||
goto fail;
|
goto fail;
|
||||||
goto done;
|
goto done;
|
||||||
|
} else if (strncmp(name, "PARTLABEL=", 10) == 0) {
|
||||||
|
struct device *dev;
|
||||||
|
|
||||||
|
dev = class_find_device(&block_class, NULL, name + 10,
|
||||||
|
&match_dev_by_label);
|
||||||
|
if (!dev)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
res = dev->devt;
|
||||||
|
put_device(dev);
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+12
-6
@@ -1565,10 +1565,17 @@ static int check_kprobe_address_safe(struct kprobe *p,
|
|||||||
jump_label_lock();
|
jump_label_lock();
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
|
|
||||||
/* Ensure it is not in reserved area nor out of text */
|
/* Ensure the address is in a text area, and find a module if exists. */
|
||||||
if (!(core_kernel_text((unsigned long) p->addr) ||
|
*probed_mod = NULL;
|
||||||
is_module_text_address((unsigned long) p->addr)) ||
|
if (!core_kernel_text((unsigned long) p->addr)) {
|
||||||
in_gate_area_no_mm((unsigned long) p->addr) ||
|
*probed_mod = __module_text_address((unsigned long) p->addr);
|
||||||
|
if (!(*probed_mod)) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Ensure it is not in reserved area. */
|
||||||
|
if (in_gate_area_no_mm((unsigned long) p->addr) ||
|
||||||
within_kprobe_blacklist((unsigned long) p->addr) ||
|
within_kprobe_blacklist((unsigned long) p->addr) ||
|
||||||
jump_label_text_reserved(p->addr, p->addr) ||
|
jump_label_text_reserved(p->addr, p->addr) ||
|
||||||
find_bug((unsigned long)p->addr)) {
|
find_bug((unsigned long)p->addr)) {
|
||||||
@@ -1576,8 +1583,7 @@ static int check_kprobe_address_safe(struct kprobe *p,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if are we probing a module */
|
/* Get module refcount and reject __init functions for loaded modules. */
|
||||||
*probed_mod = __module_text_address((unsigned long) p->addr);
|
|
||||||
if (*probed_mod) {
|
if (*probed_mod) {
|
||||||
/*
|
/*
|
||||||
* We must hold a refcount of the probed module while updating
|
* We must hold a refcount of the probed module while updating
|
||||||
|
|||||||
Loaded 100 of 159 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user