mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-10-22 23:13:01 +02:00
This is the 4.18.43 stable release
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJdeqzBAAoJEOvOhAQsB9HWbksP/R915fuHjDkXbaEFNB+ypd/W W7+I/5S6Q5ceSlVS247p4Wk+HUDnjUmtVxDmiGMOihf9YXNRE+lWrI1z1kKlVmy6 /TRxAfin2uh0m4dhG7VqZOk5lgbzW6aQiAGVKRvRnlNFm9bJv1iMgPNgqMLKgvzh hBF+59VXJyNsIazRhix70nVB5/pzpQ7IbZbbkHwxsSUTywlHIDwArQXeoWl+CpaZ VJJycc5YaxP9qZXppV7omNvm2mHDsN1jGkrqUZoaBDA1Sg5gHubW6OrYhDhLsZK+ SGsOQKabMM9AsdbiPhR/baFwUaSYCULYLESQY2qGCrElhh1t9IAZJ7cLzmV/EkPJ CWk8sStRMcNmvSSKxIjFtjADSR+Ul+44r2kVRpiAOnWTsSK9Pro7zQEIKaR+5wSI 6f7v+tM4NB+RyiJ1hIqyP8McV4NeDWxlW6UrGAKjGc2RlxJQPvVMFExnLG+cq69O 6RHl4Bo+WxYbG3YX4raLphmAbRD05aYQSB8fskfd3/OrZxzpzmXDZd06k7W3iAI/ Ccg4OBe4Wmb4wUvKgPdhrO5vZ9m/C/LEazenTIg8vc7bkySYe9FgtUDlD9HpJ4J9 fWOqk9Z7zJvmfJtLj4iS5Qjm4NgB1kyXdDm1zW2u1RJSJ17yoLEgPPQS90WqN+De l6LvRTiFJFtV1tPJvobq =wFlp -----END PGP SIGNATURE----- Merge tag 'v4.18.43' into v4.18/standard/base This is the 4.18.43 stable release
This commit is contained in:
commit
ae3837506c
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
||||||
# SPDX-License-Identifier: GPL-2.0
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
VERSION = 4
|
VERSION = 4
|
||||||
PATCHLEVEL = 18
|
PATCHLEVEL = 18
|
||||||
SUBLEVEL = 42
|
SUBLEVEL = 43
|
||||||
EXTRAVERSION =
|
EXTRAVERSION =
|
||||||
NAME = Merciless Moray
|
NAME = Merciless Moray
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ SYSCALL_DEFINE1(arm64_personality, unsigned int, personality)
|
||||||
*/
|
*/
|
||||||
asmlinkage long sys_rt_sigreturn_wrapper(void);
|
asmlinkage long sys_rt_sigreturn_wrapper(void);
|
||||||
#define sys_rt_sigreturn sys_rt_sigreturn_wrapper
|
#define sys_rt_sigreturn sys_rt_sigreturn_wrapper
|
||||||
#define sys_personality sys_arm64_personality
|
#define __arm64_sys_personality __arm64_sys_arm64_personality
|
||||||
|
|
||||||
#undef __SYSCALL
|
#undef __SYSCALL
|
||||||
#define __SYSCALL(nr, sym) [nr] = sym,
|
#define __SYSCALL(nr, sym) [nr] = sym,
|
||||||
|
|
|
@ -183,6 +183,12 @@ const char *get_system_type(void)
|
||||||
return ath79_sys_type;
|
return ath79_sys_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_c0_perfcount_int(void)
|
||||||
|
{
|
||||||
|
return ATH79_MISC_IRQ(5);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
|
||||||
|
|
||||||
unsigned int get_c0_compare_int(void)
|
unsigned int get_c0_compare_int(void)
|
||||||
{
|
{
|
||||||
return CP0_LEGACY_COMPARE_IRQ;
|
return CP0_LEGACY_COMPARE_IRQ;
|
||||||
|
|
|
@ -203,6 +203,11 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
|
||||||
|
|
||||||
int __virt_addr_valid(const volatile void *kaddr)
|
int __virt_addr_valid(const volatile void *kaddr)
|
||||||
{
|
{
|
||||||
|
unsigned long vaddr = (unsigned long)vaddr;
|
||||||
|
|
||||||
|
if ((vaddr < PAGE_OFFSET) || (vaddr >= MAP_BASE))
|
||||||
|
return 0;
|
||||||
|
|
||||||
return pfn_valid(PFN_DOWN(virt_to_phys(kaddr)));
|
return pfn_valid(PFN_DOWN(virt_to_phys(kaddr)));
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__virt_addr_valid);
|
EXPORT_SYMBOL_GPL(__virt_addr_valid);
|
||||||
|
|
|
@ -6,3 +6,4 @@ cflags-$(CONFIG_MACH_PISTACHIO) += \
|
||||||
-I$(srctree)/arch/mips/include/asm/mach-pistachio
|
-I$(srctree)/arch/mips/include/asm/mach-pistachio
|
||||||
load-$(CONFIG_MACH_PISTACHIO) += 0xffffffff80400000
|
load-$(CONFIG_MACH_PISTACHIO) += 0xffffffff80400000
|
||||||
zload-$(CONFIG_MACH_PISTACHIO) += 0xffffffff81000000
|
zload-$(CONFIG_MACH_PISTACHIO) += 0xffffffff81000000
|
||||||
|
all-$(CONFIG_MACH_PISTACHIO) := uImage.gz
|
||||||
|
|
|
@ -1718,7 +1718,6 @@ static void kvmppc_xive_cleanup_irq(u32 hw_num, struct xive_irq_data *xd)
|
||||||
{
|
{
|
||||||
xive_vm_esb_load(xd, XIVE_ESB_SET_PQ_01);
|
xive_vm_esb_load(xd, XIVE_ESB_SET_PQ_01);
|
||||||
xive_native_configure_irq(hw_num, 0, MASKED, 0);
|
xive_native_configure_irq(hw_num, 0, MASKED, 0);
|
||||||
xive_cleanup_irq_data(xd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kvmppc_xive_free_sources(struct kvmppc_xive_src_block *sb)
|
static void kvmppc_xive_free_sources(struct kvmppc_xive_src_block *sb)
|
||||||
|
@ -1732,9 +1731,10 @@ static void kvmppc_xive_free_sources(struct kvmppc_xive_src_block *sb)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
kvmppc_xive_cleanup_irq(state->ipi_number, &state->ipi_data);
|
kvmppc_xive_cleanup_irq(state->ipi_number, &state->ipi_data);
|
||||||
|
xive_cleanup_irq_data(&state->ipi_data);
|
||||||
xive_native_free_irq(state->ipi_number);
|
xive_native_free_irq(state->ipi_number);
|
||||||
|
|
||||||
/* Pass-through, cleanup too */
|
/* Pass-through, cleanup too but keep IRQ hw data */
|
||||||
if (state->pt_number)
|
if (state->pt_number)
|
||||||
kvmppc_xive_cleanup_irq(state->pt_number, state->pt_data);
|
kvmppc_xive_cleanup_irq(state->pt_number, state->pt_data);
|
||||||
|
|
||||||
|
|
|
@ -1861,6 +1861,7 @@ static int power_pmu_event_init(struct perf_event *event)
|
||||||
int n;
|
int n;
|
||||||
int err;
|
int err;
|
||||||
struct cpu_hw_events *cpuhw;
|
struct cpu_hw_events *cpuhw;
|
||||||
|
u64 bhrb_filter;
|
||||||
|
|
||||||
if (!ppmu)
|
if (!ppmu)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
@ -1966,13 +1967,14 @@ static int power_pmu_event_init(struct perf_event *event)
|
||||||
err = power_check_constraints(cpuhw, events, cflags, n + 1);
|
err = power_check_constraints(cpuhw, events, cflags, n + 1);
|
||||||
|
|
||||||
if (has_branch_stack(event)) {
|
if (has_branch_stack(event)) {
|
||||||
cpuhw->bhrb_filter = ppmu->bhrb_filter_map(
|
bhrb_filter = ppmu->bhrb_filter_map(
|
||||||
event->attr.branch_sample_type);
|
event->attr.branch_sample_type);
|
||||||
|
|
||||||
if (cpuhw->bhrb_filter == -1) {
|
if (bhrb_filter == -1) {
|
||||||
put_cpu_var(cpu_hw_events);
|
put_cpu_var(cpu_hw_events);
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
cpuhw->bhrb_filter = bhrb_filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
put_cpu_var(cpu_hw_events);
|
put_cpu_var(cpu_hw_events);
|
||||||
|
|
|
@ -29,6 +29,7 @@ enum {
|
||||||
#define POWER8_MMCRA_IFM1 0x0000000040000000UL
|
#define POWER8_MMCRA_IFM1 0x0000000040000000UL
|
||||||
#define POWER8_MMCRA_IFM2 0x0000000080000000UL
|
#define POWER8_MMCRA_IFM2 0x0000000080000000UL
|
||||||
#define POWER8_MMCRA_IFM3 0x00000000C0000000UL
|
#define POWER8_MMCRA_IFM3 0x00000000C0000000UL
|
||||||
|
#define POWER8_MMCRA_BHRB_MASK 0x00000000C0000000UL
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Raw event encoding for PowerISA v2.07 (Power8):
|
* Raw event encoding for PowerISA v2.07 (Power8):
|
||||||
|
@ -243,6 +244,8 @@ static u64 power8_bhrb_filter_map(u64 branch_sample_type)
|
||||||
|
|
||||||
static void power8_config_bhrb(u64 pmu_bhrb_filter)
|
static void power8_config_bhrb(u64 pmu_bhrb_filter)
|
||||||
{
|
{
|
||||||
|
pmu_bhrb_filter &= POWER8_MMCRA_BHRB_MASK;
|
||||||
|
|
||||||
/* Enable BHRB filter in PMU */
|
/* Enable BHRB filter in PMU */
|
||||||
mtspr(SPRN_MMCRA, (mfspr(SPRN_MMCRA) | pmu_bhrb_filter));
|
mtspr(SPRN_MMCRA, (mfspr(SPRN_MMCRA) | pmu_bhrb_filter));
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,6 +100,7 @@ enum {
|
||||||
#define POWER9_MMCRA_IFM1 0x0000000040000000UL
|
#define POWER9_MMCRA_IFM1 0x0000000040000000UL
|
||||||
#define POWER9_MMCRA_IFM2 0x0000000080000000UL
|
#define POWER9_MMCRA_IFM2 0x0000000080000000UL
|
||||||
#define POWER9_MMCRA_IFM3 0x00000000C0000000UL
|
#define POWER9_MMCRA_IFM3 0x00000000C0000000UL
|
||||||
|
#define POWER9_MMCRA_BHRB_MASK 0x00000000C0000000UL
|
||||||
|
|
||||||
/* Nasty Power9 specific hack */
|
/* Nasty Power9 specific hack */
|
||||||
#define PVR_POWER9_CUMULUS 0x00002000
|
#define PVR_POWER9_CUMULUS 0x00002000
|
||||||
|
@ -325,6 +326,8 @@ static u64 power9_bhrb_filter_map(u64 branch_sample_type)
|
||||||
|
|
||||||
static void power9_config_bhrb(u64 pmu_bhrb_filter)
|
static void power9_config_bhrb(u64 pmu_bhrb_filter)
|
||||||
{
|
{
|
||||||
|
pmu_bhrb_filter &= POWER9_MMCRA_BHRB_MASK;
|
||||||
|
|
||||||
/* Enable BHRB filter in PMU */
|
/* Enable BHRB filter in PMU */
|
||||||
mtspr(SPRN_MMCRA, (mfspr(SPRN_MMCRA) | pmu_bhrb_filter));
|
mtspr(SPRN_MMCRA, (mfspr(SPRN_MMCRA) | pmu_bhrb_filter));
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,14 +27,14 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/cpufeature.h>
|
#include <linux/cpufeature.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/fips.h>
|
#include <linux/fips.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <crypto/xts.h>
|
#include <crypto/xts.h>
|
||||||
#include <asm/cpacf.h>
|
#include <asm/cpacf.h>
|
||||||
|
|
||||||
static u8 *ctrblk;
|
static u8 *ctrblk;
|
||||||
static DEFINE_SPINLOCK(ctrblk_lock);
|
static DEFINE_MUTEX(ctrblk_lock);
|
||||||
|
|
||||||
static cpacf_mask_t km_functions, kmc_functions, kmctr_functions,
|
static cpacf_mask_t km_functions, kmc_functions, kmctr_functions,
|
||||||
kma_functions;
|
kma_functions;
|
||||||
|
@ -698,7 +698,7 @@ static int ctr_aes_crypt(struct blkcipher_desc *desc, unsigned long modifier,
|
||||||
unsigned int n, nbytes;
|
unsigned int n, nbytes;
|
||||||
int ret, locked;
|
int ret, locked;
|
||||||
|
|
||||||
locked = spin_trylock(&ctrblk_lock);
|
locked = mutex_trylock(&ctrblk_lock);
|
||||||
|
|
||||||
ret = blkcipher_walk_virt_block(desc, walk, AES_BLOCK_SIZE);
|
ret = blkcipher_walk_virt_block(desc, walk, AES_BLOCK_SIZE);
|
||||||
while ((nbytes = walk->nbytes) >= AES_BLOCK_SIZE) {
|
while ((nbytes = walk->nbytes) >= AES_BLOCK_SIZE) {
|
||||||
|
@ -716,7 +716,7 @@ static int ctr_aes_crypt(struct blkcipher_desc *desc, unsigned long modifier,
|
||||||
ret = blkcipher_walk_done(desc, walk, nbytes - n);
|
ret = blkcipher_walk_done(desc, walk, nbytes - n);
|
||||||
}
|
}
|
||||||
if (locked)
|
if (locked)
|
||||||
spin_unlock(&ctrblk_lock);
|
mutex_unlock(&ctrblk_lock);
|
||||||
/*
|
/*
|
||||||
* final block may be < AES_BLOCK_SIZE, copy only nbytes
|
* final block may be < AES_BLOCK_SIZE, copy only nbytes
|
||||||
*/
|
*/
|
||||||
|
@ -826,19 +826,45 @@ static int gcm_aes_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gcm_sg_walk_start(struct gcm_sg_walk *gw, struct scatterlist *sg,
|
static void gcm_walk_start(struct gcm_sg_walk *gw, struct scatterlist *sg,
|
||||||
unsigned int len)
|
unsigned int len)
|
||||||
{
|
{
|
||||||
memset(gw, 0, sizeof(*gw));
|
memset(gw, 0, sizeof(*gw));
|
||||||
gw->walk_bytes_remain = len;
|
gw->walk_bytes_remain = len;
|
||||||
scatterwalk_start(&gw->walk, sg);
|
scatterwalk_start(&gw->walk, sg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gcm_sg_walk_go(struct gcm_sg_walk *gw, unsigned int minbytesneeded)
|
static inline unsigned int _gcm_sg_clamp_and_map(struct gcm_sg_walk *gw)
|
||||||
|
{
|
||||||
|
struct scatterlist *nextsg;
|
||||||
|
|
||||||
|
gw->walk_bytes = scatterwalk_clamp(&gw->walk, gw->walk_bytes_remain);
|
||||||
|
while (!gw->walk_bytes) {
|
||||||
|
nextsg = sg_next(gw->walk.sg);
|
||||||
|
if (!nextsg)
|
||||||
|
return 0;
|
||||||
|
scatterwalk_start(&gw->walk, nextsg);
|
||||||
|
gw->walk_bytes = scatterwalk_clamp(&gw->walk,
|
||||||
|
gw->walk_bytes_remain);
|
||||||
|
}
|
||||||
|
gw->walk_ptr = scatterwalk_map(&gw->walk);
|
||||||
|
return gw->walk_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void _gcm_sg_unmap_and_advance(struct gcm_sg_walk *gw,
|
||||||
|
unsigned int nbytes)
|
||||||
|
{
|
||||||
|
gw->walk_bytes_remain -= nbytes;
|
||||||
|
scatterwalk_unmap(&gw->walk);
|
||||||
|
scatterwalk_advance(&gw->walk, nbytes);
|
||||||
|
scatterwalk_done(&gw->walk, 0, gw->walk_bytes_remain);
|
||||||
|
gw->walk_ptr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gcm_in_walk_go(struct gcm_sg_walk *gw, unsigned int minbytesneeded)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
/* minbytesneeded <= AES_BLOCK_SIZE */
|
|
||||||
if (gw->buf_bytes && gw->buf_bytes >= minbytesneeded) {
|
if (gw->buf_bytes && gw->buf_bytes >= minbytesneeded) {
|
||||||
gw->ptr = gw->buf;
|
gw->ptr = gw->buf;
|
||||||
gw->nbytes = gw->buf_bytes;
|
gw->nbytes = gw->buf_bytes;
|
||||||
|
@ -851,13 +877,11 @@ static int gcm_sg_walk_go(struct gcm_sg_walk *gw, unsigned int minbytesneeded)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
gw->walk_bytes = scatterwalk_clamp(&gw->walk, gw->walk_bytes_remain);
|
if (!_gcm_sg_clamp_and_map(gw)) {
|
||||||
if (!gw->walk_bytes) {
|
gw->ptr = NULL;
|
||||||
scatterwalk_start(&gw->walk, sg_next(gw->walk.sg));
|
gw->nbytes = 0;
|
||||||
gw->walk_bytes = scatterwalk_clamp(&gw->walk,
|
goto out;
|
||||||
gw->walk_bytes_remain);
|
|
||||||
}
|
}
|
||||||
gw->walk_ptr = scatterwalk_map(&gw->walk);
|
|
||||||
|
|
||||||
if (!gw->buf_bytes && gw->walk_bytes >= minbytesneeded) {
|
if (!gw->buf_bytes && gw->walk_bytes >= minbytesneeded) {
|
||||||
gw->ptr = gw->walk_ptr;
|
gw->ptr = gw->walk_ptr;
|
||||||
|
@ -869,51 +893,90 @@ static int gcm_sg_walk_go(struct gcm_sg_walk *gw, unsigned int minbytesneeded)
|
||||||
n = min(gw->walk_bytes, AES_BLOCK_SIZE - gw->buf_bytes);
|
n = min(gw->walk_bytes, AES_BLOCK_SIZE - gw->buf_bytes);
|
||||||
memcpy(gw->buf + gw->buf_bytes, gw->walk_ptr, n);
|
memcpy(gw->buf + gw->buf_bytes, gw->walk_ptr, n);
|
||||||
gw->buf_bytes += n;
|
gw->buf_bytes += n;
|
||||||
gw->walk_bytes_remain -= n;
|
_gcm_sg_unmap_and_advance(gw, n);
|
||||||
scatterwalk_unmap(&gw->walk);
|
|
||||||
scatterwalk_advance(&gw->walk, n);
|
|
||||||
scatterwalk_done(&gw->walk, 0, gw->walk_bytes_remain);
|
|
||||||
|
|
||||||
if (gw->buf_bytes >= minbytesneeded) {
|
if (gw->buf_bytes >= minbytesneeded) {
|
||||||
gw->ptr = gw->buf;
|
gw->ptr = gw->buf;
|
||||||
gw->nbytes = gw->buf_bytes;
|
gw->nbytes = gw->buf_bytes;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
if (!_gcm_sg_clamp_and_map(gw)) {
|
||||||
gw->walk_bytes = scatterwalk_clamp(&gw->walk,
|
gw->ptr = NULL;
|
||||||
gw->walk_bytes_remain);
|
gw->nbytes = 0;
|
||||||
if (!gw->walk_bytes) {
|
goto out;
|
||||||
scatterwalk_start(&gw->walk, sg_next(gw->walk.sg));
|
|
||||||
gw->walk_bytes = scatterwalk_clamp(&gw->walk,
|
|
||||||
gw->walk_bytes_remain);
|
|
||||||
}
|
}
|
||||||
gw->walk_ptr = scatterwalk_map(&gw->walk);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return gw->nbytes;
|
return gw->nbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gcm_sg_walk_done(struct gcm_sg_walk *gw, unsigned int bytesdone)
|
static int gcm_out_walk_go(struct gcm_sg_walk *gw, unsigned int minbytesneeded)
|
||||||
{
|
{
|
||||||
int n;
|
if (gw->walk_bytes_remain == 0) {
|
||||||
|
gw->ptr = NULL;
|
||||||
|
gw->nbytes = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_gcm_sg_clamp_and_map(gw)) {
|
||||||
|
gw->ptr = NULL;
|
||||||
|
gw->nbytes = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gw->walk_bytes >= minbytesneeded) {
|
||||||
|
gw->ptr = gw->walk_ptr;
|
||||||
|
gw->nbytes = gw->walk_bytes;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
scatterwalk_unmap(&gw->walk);
|
||||||
|
gw->walk_ptr = NULL;
|
||||||
|
|
||||||
|
gw->ptr = gw->buf;
|
||||||
|
gw->nbytes = sizeof(gw->buf);
|
||||||
|
|
||||||
|
out:
|
||||||
|
return gw->nbytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gcm_in_walk_done(struct gcm_sg_walk *gw, unsigned int bytesdone)
|
||||||
|
{
|
||||||
if (gw->ptr == NULL)
|
if (gw->ptr == NULL)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
if (gw->ptr == gw->buf) {
|
if (gw->ptr == gw->buf) {
|
||||||
n = gw->buf_bytes - bytesdone;
|
int n = gw->buf_bytes - bytesdone;
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
memmove(gw->buf, gw->buf + bytesdone, n);
|
memmove(gw->buf, gw->buf + bytesdone, n);
|
||||||
gw->buf_bytes -= n;
|
gw->buf_bytes = n;
|
||||||
} else
|
} else
|
||||||
gw->buf_bytes = 0;
|
gw->buf_bytes = 0;
|
||||||
} else {
|
} else
|
||||||
gw->walk_bytes_remain -= bytesdone;
|
_gcm_sg_unmap_and_advance(gw, bytesdone);
|
||||||
scatterwalk_unmap(&gw->walk);
|
|
||||||
scatterwalk_advance(&gw->walk, bytesdone);
|
return bytesdone;
|
||||||
scatterwalk_done(&gw->walk, 0, gw->walk_bytes_remain);
|
}
|
||||||
}
|
|
||||||
|
static int gcm_out_walk_done(struct gcm_sg_walk *gw, unsigned int bytesdone)
|
||||||
|
{
|
||||||
|
int i, n;
|
||||||
|
|
||||||
|
if (gw->ptr == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (gw->ptr == gw->buf) {
|
||||||
|
for (i = 0; i < bytesdone; i += n) {
|
||||||
|
if (!_gcm_sg_clamp_and_map(gw))
|
||||||
|
return i;
|
||||||
|
n = min(gw->walk_bytes, bytesdone - i);
|
||||||
|
memcpy(gw->walk_ptr, gw->buf + i, n);
|
||||||
|
_gcm_sg_unmap_and_advance(gw, n);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
_gcm_sg_unmap_and_advance(gw, bytesdone);
|
||||||
|
|
||||||
|
return bytesdone;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gcm_aes_crypt(struct aead_request *req, unsigned int flags)
|
static int gcm_aes_crypt(struct aead_request *req, unsigned int flags)
|
||||||
|
@ -926,7 +989,7 @@ static int gcm_aes_crypt(struct aead_request *req, unsigned int flags)
|
||||||
unsigned int pclen = req->cryptlen;
|
unsigned int pclen = req->cryptlen;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
unsigned int len, in_bytes, out_bytes,
|
unsigned int n, len, in_bytes, out_bytes,
|
||||||
min_bytes, bytes, aad_bytes, pc_bytes;
|
min_bytes, bytes, aad_bytes, pc_bytes;
|
||||||
struct gcm_sg_walk gw_in, gw_out;
|
struct gcm_sg_walk gw_in, gw_out;
|
||||||
u8 tag[GHASH_DIGEST_SIZE];
|
u8 tag[GHASH_DIGEST_SIZE];
|
||||||
|
@ -963,14 +1026,14 @@ static int gcm_aes_crypt(struct aead_request *req, unsigned int flags)
|
||||||
*(u32 *)(param.j0 + ivsize) = 1;
|
*(u32 *)(param.j0 + ivsize) = 1;
|
||||||
memcpy(param.k, ctx->key, ctx->key_len);
|
memcpy(param.k, ctx->key, ctx->key_len);
|
||||||
|
|
||||||
gcm_sg_walk_start(&gw_in, req->src, len);
|
gcm_walk_start(&gw_in, req->src, len);
|
||||||
gcm_sg_walk_start(&gw_out, req->dst, len);
|
gcm_walk_start(&gw_out, req->dst, len);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
min_bytes = min_t(unsigned int,
|
min_bytes = min_t(unsigned int,
|
||||||
aadlen > 0 ? aadlen : pclen, AES_BLOCK_SIZE);
|
aadlen > 0 ? aadlen : pclen, AES_BLOCK_SIZE);
|
||||||
in_bytes = gcm_sg_walk_go(&gw_in, min_bytes);
|
in_bytes = gcm_in_walk_go(&gw_in, min_bytes);
|
||||||
out_bytes = gcm_sg_walk_go(&gw_out, min_bytes);
|
out_bytes = gcm_out_walk_go(&gw_out, min_bytes);
|
||||||
bytes = min(in_bytes, out_bytes);
|
bytes = min(in_bytes, out_bytes);
|
||||||
|
|
||||||
if (aadlen + pclen <= bytes) {
|
if (aadlen + pclen <= bytes) {
|
||||||
|
@ -997,8 +1060,11 @@ static int gcm_aes_crypt(struct aead_request *req, unsigned int flags)
|
||||||
gw_in.ptr + aad_bytes, pc_bytes,
|
gw_in.ptr + aad_bytes, pc_bytes,
|
||||||
gw_in.ptr, aad_bytes);
|
gw_in.ptr, aad_bytes);
|
||||||
|
|
||||||
gcm_sg_walk_done(&gw_in, aad_bytes + pc_bytes);
|
n = aad_bytes + pc_bytes;
|
||||||
gcm_sg_walk_done(&gw_out, aad_bytes + pc_bytes);
|
if (gcm_in_walk_done(&gw_in, n) != n)
|
||||||
|
return -ENOMEM;
|
||||||
|
if (gcm_out_walk_done(&gw_out, n) != n)
|
||||||
|
return -ENOMEM;
|
||||||
aadlen -= aad_bytes;
|
aadlen -= aad_bytes;
|
||||||
pclen -= pc_bytes;
|
pclen -= pc_bytes;
|
||||||
} while (aadlen + pclen > 0);
|
} while (aadlen + pclen > 0);
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <linux/cpufeature.h>
|
#include <linux/cpufeature.h>
|
||||||
#include <linux/crypto.h>
|
#include <linux/crypto.h>
|
||||||
#include <linux/fips.h>
|
#include <linux/fips.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
#include <crypto/algapi.h>
|
#include <crypto/algapi.h>
|
||||||
#include <crypto/des.h>
|
#include <crypto/des.h>
|
||||||
#include <asm/cpacf.h>
|
#include <asm/cpacf.h>
|
||||||
|
@ -21,7 +22,7 @@
|
||||||
#define DES3_KEY_SIZE (3 * DES_KEY_SIZE)
|
#define DES3_KEY_SIZE (3 * DES_KEY_SIZE)
|
||||||
|
|
||||||
static u8 *ctrblk;
|
static u8 *ctrblk;
|
||||||
static DEFINE_SPINLOCK(ctrblk_lock);
|
static DEFINE_MUTEX(ctrblk_lock);
|
||||||
|
|
||||||
static cpacf_mask_t km_functions, kmc_functions, kmctr_functions;
|
static cpacf_mask_t km_functions, kmc_functions, kmctr_functions;
|
||||||
|
|
||||||
|
@ -387,7 +388,7 @@ static int ctr_desall_crypt(struct blkcipher_desc *desc, unsigned long fc,
|
||||||
unsigned int n, nbytes;
|
unsigned int n, nbytes;
|
||||||
int ret, locked;
|
int ret, locked;
|
||||||
|
|
||||||
locked = spin_trylock(&ctrblk_lock);
|
locked = mutex_trylock(&ctrblk_lock);
|
||||||
|
|
||||||
ret = blkcipher_walk_virt_block(desc, walk, DES_BLOCK_SIZE);
|
ret = blkcipher_walk_virt_block(desc, walk, DES_BLOCK_SIZE);
|
||||||
while ((nbytes = walk->nbytes) >= DES_BLOCK_SIZE) {
|
while ((nbytes = walk->nbytes) >= DES_BLOCK_SIZE) {
|
||||||
|
@ -404,7 +405,7 @@ static int ctr_desall_crypt(struct blkcipher_desc *desc, unsigned long fc,
|
||||||
ret = blkcipher_walk_done(desc, walk, nbytes - n);
|
ret = blkcipher_walk_done(desc, walk, nbytes - n);
|
||||||
}
|
}
|
||||||
if (locked)
|
if (locked)
|
||||||
spin_unlock(&ctrblk_lock);
|
mutex_unlock(&ctrblk_lock);
|
||||||
/* final block may be < DES_BLOCK_SIZE, copy only nbytes */
|
/* final block may be < DES_BLOCK_SIZE, copy only nbytes */
|
||||||
if (nbytes) {
|
if (nbytes) {
|
||||||
cpacf_kmctr(fc, ctx->key, buf, walk->src.virt.addr,
|
cpacf_kmctr(fc, ctx->key, buf, walk->src.virt.addr,
|
||||||
|
|
|
@ -107,7 +107,6 @@ void bust_spinlocks(int yes)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find out which address space caused the exception.
|
* Find out which address space caused the exception.
|
||||||
* Access register mode is impossible, ignore space == 3.
|
|
||||||
*/
|
*/
|
||||||
static inline enum fault_type get_fault_type(struct pt_regs *regs)
|
static inline enum fault_type get_fault_type(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
|
@ -132,6 +131,10 @@ static inline enum fault_type get_fault_type(struct pt_regs *regs)
|
||||||
}
|
}
|
||||||
return VDSO_FAULT;
|
return VDSO_FAULT;
|
||||||
}
|
}
|
||||||
|
if (trans_exc_code == 1) {
|
||||||
|
/* access register mode, not used in the kernel */
|
||||||
|
return USER_FAULT;
|
||||||
|
}
|
||||||
/* home space exception -> access via kernel ASCE */
|
/* home space exception -> access via kernel ASCE */
|
||||||
return KERNEL_FAULT;
|
return KERNEL_FAULT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -587,7 +587,7 @@ xcall_flush_tlb_kernel_range: /* 44 insns */
|
||||||
sub %g7, %g1, %g3
|
sub %g7, %g1, %g3
|
||||||
srlx %g3, 18, %g2
|
srlx %g3, 18, %g2
|
||||||
brnz,pn %g2, 2f
|
brnz,pn %g2, 2f
|
||||||
add %g2, 1, %g2
|
sethi %hi(PAGE_SIZE), %g2
|
||||||
sub %g3, %g2, %g3
|
sub %g3, %g2, %g3
|
||||||
or %g1, 0x20, %g1 ! Nucleus
|
or %g1, 0x20, %g1 ! Nucleus
|
||||||
1: stxa %g0, [%g1 + %g3] ASI_DMMU_DEMAP
|
1: stxa %g0, [%g1 + %g3] ASI_DMMU_DEMAP
|
||||||
|
@ -751,7 +751,7 @@ __cheetah_xcall_flush_tlb_kernel_range: /* 44 insns */
|
||||||
sub %g7, %g1, %g3
|
sub %g7, %g1, %g3
|
||||||
srlx %g3, 18, %g2
|
srlx %g3, 18, %g2
|
||||||
brnz,pn %g2, 2f
|
brnz,pn %g2, 2f
|
||||||
add %g2, 1, %g2
|
sethi %hi(PAGE_SIZE), %g2
|
||||||
sub %g3, %g2, %g3
|
sub %g3, %g2, %g3
|
||||||
or %g1, 0x20, %g1 ! Nucleus
|
or %g1, 0x20, %g1 ! Nucleus
|
||||||
1: stxa %g0, [%g1 + %g3] ASI_DMMU_DEMAP
|
1: stxa %g0, [%g1 + %g3] ASI_DMMU_DEMAP
|
||||||
|
|
|
@ -752,18 +752,21 @@ union ftrace_op_code_union {
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define RET_SIZE 1
|
||||||
|
|
||||||
static unsigned long
|
static unsigned long
|
||||||
create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
|
create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
|
||||||
{
|
{
|
||||||
unsigned const char *jmp;
|
|
||||||
unsigned long start_offset;
|
unsigned long start_offset;
|
||||||
unsigned long end_offset;
|
unsigned long end_offset;
|
||||||
unsigned long op_offset;
|
unsigned long op_offset;
|
||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
|
unsigned long npages;
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
unsigned long ip;
|
unsigned long retq;
|
||||||
unsigned long *ptr;
|
unsigned long *ptr;
|
||||||
void *trampoline;
|
void *trampoline;
|
||||||
|
void *ip;
|
||||||
/* 48 8b 15 <offset> is movq <offset>(%rip), %rdx */
|
/* 48 8b 15 <offset> is movq <offset>(%rip), %rdx */
|
||||||
unsigned const char op_ref[] = { 0x48, 0x8b, 0x15 };
|
unsigned const char op_ref[] = { 0x48, 0x8b, 0x15 };
|
||||||
union ftrace_op_code_union op_ptr;
|
union ftrace_op_code_union op_ptr;
|
||||||
|
@ -783,27 +786,28 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate enough size to store the ftrace_caller code,
|
* Allocate enough size to store the ftrace_caller code,
|
||||||
* the jmp to ftrace_epilogue, as well as the address of
|
* the iret , as well as the address of the ftrace_ops this
|
||||||
* the ftrace_ops this trampoline is used for.
|
* trampoline is used for.
|
||||||
*/
|
*/
|
||||||
trampoline = alloc_tramp(size + MCOUNT_INSN_SIZE + sizeof(void *));
|
trampoline = alloc_tramp(size + RET_SIZE + sizeof(void *));
|
||||||
if (!trampoline)
|
if (!trampoline)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
*tramp_size = size + MCOUNT_INSN_SIZE + sizeof(void *);
|
*tramp_size = size + RET_SIZE + sizeof(void *);
|
||||||
|
npages = DIV_ROUND_UP(*tramp_size, PAGE_SIZE);
|
||||||
|
|
||||||
/* Copy ftrace_caller onto the trampoline memory */
|
/* Copy ftrace_caller onto the trampoline memory */
|
||||||
ret = probe_kernel_read(trampoline, (void *)start_offset, size);
|
ret = probe_kernel_read(trampoline, (void *)start_offset, size);
|
||||||
if (WARN_ON(ret < 0)) {
|
if (WARN_ON(ret < 0))
|
||||||
tramp_free(trampoline, *tramp_size);
|
goto fail;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ip = (unsigned long)trampoline + size;
|
ip = trampoline + size;
|
||||||
|
|
||||||
/* The trampoline ends with a jmp to ftrace_epilogue */
|
/* The trampoline ends with ret(q) */
|
||||||
jmp = ftrace_jmp_replace(ip, (unsigned long)ftrace_epilogue);
|
retq = (unsigned long)ftrace_stub;
|
||||||
memcpy(trampoline + size, jmp, MCOUNT_INSN_SIZE);
|
ret = probe_kernel_read(ip, (void *)retq, RET_SIZE);
|
||||||
|
if (WARN_ON(ret < 0))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The address of the ftrace_ops that is used for this trampoline
|
* The address of the ftrace_ops that is used for this trampoline
|
||||||
|
@ -813,17 +817,15 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
|
||||||
* the global function_trace_op variable.
|
* the global function_trace_op variable.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ptr = (unsigned long *)(trampoline + size + MCOUNT_INSN_SIZE);
|
ptr = (unsigned long *)(trampoline + size + RET_SIZE);
|
||||||
*ptr = (unsigned long)ops;
|
*ptr = (unsigned long)ops;
|
||||||
|
|
||||||
op_offset -= start_offset;
|
op_offset -= start_offset;
|
||||||
memcpy(&op_ptr, trampoline + op_offset, OP_REF_SIZE);
|
memcpy(&op_ptr, trampoline + op_offset, OP_REF_SIZE);
|
||||||
|
|
||||||
/* Are we pointing to the reference? */
|
/* Are we pointing to the reference? */
|
||||||
if (WARN_ON(memcmp(op_ptr.op, op_ref, 3) != 0)) {
|
if (WARN_ON(memcmp(op_ptr.op, op_ref, 3) != 0))
|
||||||
tramp_free(trampoline, *tramp_size);
|
goto fail;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load the contents of ptr into the callback parameter */
|
/* Load the contents of ptr into the callback parameter */
|
||||||
offset = (unsigned long)ptr;
|
offset = (unsigned long)ptr;
|
||||||
|
@ -837,7 +839,16 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
|
||||||
/* ALLOC_TRAMP flags lets us know we created it */
|
/* ALLOC_TRAMP flags lets us know we created it */
|
||||||
ops->flags |= FTRACE_OPS_FL_ALLOC_TRAMP;
|
ops->flags |= FTRACE_OPS_FL_ALLOC_TRAMP;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Module allocation needs to be completed by making the page
|
||||||
|
* executable. The page is still writable, which is a security hazard,
|
||||||
|
* but anyhow ftrace breaks W^X completely.
|
||||||
|
*/
|
||||||
|
set_memory_x((unsigned long)trampoline, npages);
|
||||||
return (unsigned long)trampoline;
|
return (unsigned long)trampoline;
|
||||||
|
fail:
|
||||||
|
tramp_free(trampoline, *tramp_size);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long calc_trampoline_call_offset(bool save_regs)
|
static unsigned long calc_trampoline_call_offset(bool save_regs)
|
||||||
|
|
|
@ -171,9 +171,6 @@ GLOBAL(ftrace_call)
|
||||||
restore_mcount_regs
|
restore_mcount_regs
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The copied trampoline must call ftrace_epilogue as it
|
|
||||||
* still may need to call the function graph tracer.
|
|
||||||
*
|
|
||||||
* The code up to this label is copied into trampolines so
|
* The code up to this label is copied into trampolines so
|
||||||
* think twice before adding any new code or changing the
|
* think twice before adding any new code or changing the
|
||||||
* layout here.
|
* layout here.
|
||||||
|
@ -185,7 +182,10 @@ GLOBAL(ftrace_graph_call)
|
||||||
jmp ftrace_stub
|
jmp ftrace_stub
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* This is weak to keep gas from relaxing the jumps */
|
/*
|
||||||
|
* This is weak to keep gas from relaxing the jumps.
|
||||||
|
* It is also used to copy the retq for trampolines.
|
||||||
|
*/
|
||||||
WEAK(ftrace_stub)
|
WEAK(ftrace_stub)
|
||||||
retq
|
retq
|
||||||
ENDPROC(ftrace_caller)
|
ENDPROC(ftrace_caller)
|
||||||
|
|
|
@ -433,8 +433,20 @@ void *alloc_insn_page(void)
|
||||||
void *page;
|
void *page;
|
||||||
|
|
||||||
page = module_alloc(PAGE_SIZE);
|
page = module_alloc(PAGE_SIZE);
|
||||||
if (page)
|
if (!page)
|
||||||
set_memory_ro((unsigned long)page & PAGE_MASK, 1);
|
return NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First make the page read-only, and only then make it executable to
|
||||||
|
* prevent it from being W+X in between.
|
||||||
|
*/
|
||||||
|
set_memory_ro((unsigned long)page, 1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: Once additional kernel code protection mechanisms are set, ensure
|
||||||
|
* that the page was not maliciously altered and it is still zeroed.
|
||||||
|
*/
|
||||||
|
set_memory_x((unsigned long)page, 1);
|
||||||
|
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
@ -442,8 +454,12 @@ void *alloc_insn_page(void)
|
||||||
/* Recover page to RW mode before releasing it */
|
/* Recover page to RW mode before releasing it */
|
||||||
void free_insn_page(void *page)
|
void free_insn_page(void *page)
|
||||||
{
|
{
|
||||||
set_memory_nx((unsigned long)page & PAGE_MASK, 1);
|
/*
|
||||||
set_memory_rw((unsigned long)page & PAGE_MASK, 1);
|
* First make the page non-executable, and only then make it writable to
|
||||||
|
* prevent it from being W+X in between.
|
||||||
|
*/
|
||||||
|
set_memory_nx((unsigned long)page, 1);
|
||||||
|
set_memory_rw((unsigned long)page, 1);
|
||||||
module_memfree(page);
|
module_memfree(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -130,10 +130,10 @@ SECTIONS
|
||||||
*(.text.__x86.indirect_thunk)
|
*(.text.__x86.indirect_thunk)
|
||||||
__indirect_thunk_end = .;
|
__indirect_thunk_end = .;
|
||||||
#endif
|
#endif
|
||||||
} :text = 0x9090
|
|
||||||
|
|
||||||
/* End of text section */
|
/* End of text section */
|
||||||
_etext = .;
|
_etext = .;
|
||||||
|
} :text = 0x9090
|
||||||
|
|
||||||
NOTES :text :note
|
NOTES :text :note
|
||||||
|
|
||||||
|
|
|
@ -555,7 +555,8 @@ static int get_reg_offset_16(struct insn *insn, struct pt_regs *regs,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get_desc() - Obtain pointer to a segment descriptor
|
* get_desc() - Obtain contents of a segment descriptor
|
||||||
|
* @out: Segment descriptor contents on success
|
||||||
* @sel: Segment selector
|
* @sel: Segment selector
|
||||||
*
|
*
|
||||||
* Given a segment selector, obtain a pointer to the segment descriptor.
|
* Given a segment selector, obtain a pointer to the segment descriptor.
|
||||||
|
@ -563,18 +564,18 @@ static int get_reg_offset_16(struct insn *insn, struct pt_regs *regs,
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
*
|
*
|
||||||
* Pointer to segment descriptor on success.
|
* True on success, false on failure.
|
||||||
*
|
*
|
||||||
* NULL on error.
|
* NULL on error.
|
||||||
*/
|
*/
|
||||||
static struct desc_struct *get_desc(unsigned short sel)
|
static bool get_desc(struct desc_struct *out, unsigned short sel)
|
||||||
{
|
{
|
||||||
struct desc_ptr gdt_desc = {0, 0};
|
struct desc_ptr gdt_desc = {0, 0};
|
||||||
unsigned long desc_base;
|
unsigned long desc_base;
|
||||||
|
|
||||||
#ifdef CONFIG_MODIFY_LDT_SYSCALL
|
#ifdef CONFIG_MODIFY_LDT_SYSCALL
|
||||||
if ((sel & SEGMENT_TI_MASK) == SEGMENT_LDT) {
|
if ((sel & SEGMENT_TI_MASK) == SEGMENT_LDT) {
|
||||||
struct desc_struct *desc = NULL;
|
bool success = false;
|
||||||
struct ldt_struct *ldt;
|
struct ldt_struct *ldt;
|
||||||
|
|
||||||
/* Bits [15:3] contain the index of the desired entry. */
|
/* Bits [15:3] contain the index of the desired entry. */
|
||||||
|
@ -582,12 +583,14 @@ static struct desc_struct *get_desc(unsigned short sel)
|
||||||
|
|
||||||
mutex_lock(¤t->active_mm->context.lock);
|
mutex_lock(¤t->active_mm->context.lock);
|
||||||
ldt = current->active_mm->context.ldt;
|
ldt = current->active_mm->context.ldt;
|
||||||
if (ldt && sel < ldt->nr_entries)
|
if (ldt && sel < ldt->nr_entries) {
|
||||||
desc = &ldt->entries[sel];
|
*out = ldt->entries[sel];
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
|
||||||
mutex_unlock(¤t->active_mm->context.lock);
|
mutex_unlock(¤t->active_mm->context.lock);
|
||||||
|
|
||||||
return desc;
|
return success;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
native_store_gdt(&gdt_desc);
|
native_store_gdt(&gdt_desc);
|
||||||
|
@ -602,9 +605,10 @@ static struct desc_struct *get_desc(unsigned short sel)
|
||||||
desc_base = sel & ~(SEGMENT_RPL_MASK | SEGMENT_TI_MASK);
|
desc_base = sel & ~(SEGMENT_RPL_MASK | SEGMENT_TI_MASK);
|
||||||
|
|
||||||
if (desc_base > gdt_desc.size)
|
if (desc_base > gdt_desc.size)
|
||||||
return NULL;
|
return false;
|
||||||
|
|
||||||
return (struct desc_struct *)(gdt_desc.address + desc_base);
|
*out = *(struct desc_struct *)(gdt_desc.address + desc_base);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -626,7 +630,7 @@ static struct desc_struct *get_desc(unsigned short sel)
|
||||||
*/
|
*/
|
||||||
unsigned long insn_get_seg_base(struct pt_regs *regs, int seg_reg_idx)
|
unsigned long insn_get_seg_base(struct pt_regs *regs, int seg_reg_idx)
|
||||||
{
|
{
|
||||||
struct desc_struct *desc;
|
struct desc_struct desc;
|
||||||
short sel;
|
short sel;
|
||||||
|
|
||||||
sel = get_segment_selector(regs, seg_reg_idx);
|
sel = get_segment_selector(regs, seg_reg_idx);
|
||||||
|
@ -664,11 +668,10 @@ unsigned long insn_get_seg_base(struct pt_regs *regs, int seg_reg_idx)
|
||||||
if (!sel)
|
if (!sel)
|
||||||
return -1L;
|
return -1L;
|
||||||
|
|
||||||
desc = get_desc(sel);
|
if (!get_desc(&desc, sel))
|
||||||
if (!desc)
|
|
||||||
return -1L;
|
return -1L;
|
||||||
|
|
||||||
return get_desc_base(desc);
|
return get_desc_base(&desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -690,7 +693,7 @@ unsigned long insn_get_seg_base(struct pt_regs *regs, int seg_reg_idx)
|
||||||
*/
|
*/
|
||||||
static unsigned long get_seg_limit(struct pt_regs *regs, int seg_reg_idx)
|
static unsigned long get_seg_limit(struct pt_regs *regs, int seg_reg_idx)
|
||||||
{
|
{
|
||||||
struct desc_struct *desc;
|
struct desc_struct desc;
|
||||||
unsigned long limit;
|
unsigned long limit;
|
||||||
short sel;
|
short sel;
|
||||||
|
|
||||||
|
@ -704,8 +707,7 @@ static unsigned long get_seg_limit(struct pt_regs *regs, int seg_reg_idx)
|
||||||
if (!sel)
|
if (!sel)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
desc = get_desc(sel);
|
if (!get_desc(&desc, sel))
|
||||||
if (!desc)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -714,8 +716,8 @@ static unsigned long get_seg_limit(struct pt_regs *regs, int seg_reg_idx)
|
||||||
* not tested when checking the segment limits. In practice,
|
* not tested when checking the segment limits. In practice,
|
||||||
* this means that the segment ends in (limit << 12) + 0xfff.
|
* this means that the segment ends in (limit << 12) + 0xfff.
|
||||||
*/
|
*/
|
||||||
limit = get_desc_limit(desc);
|
limit = get_desc_limit(&desc);
|
||||||
if (desc->g)
|
if (desc.g)
|
||||||
limit = (limit << 12) + 0xfff;
|
limit = (limit << 12) + 0xfff;
|
||||||
|
|
||||||
return limit;
|
return limit;
|
||||||
|
@ -739,7 +741,7 @@ static unsigned long get_seg_limit(struct pt_regs *regs, int seg_reg_idx)
|
||||||
*/
|
*/
|
||||||
int insn_get_code_seg_params(struct pt_regs *regs)
|
int insn_get_code_seg_params(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
struct desc_struct *desc;
|
struct desc_struct desc;
|
||||||
short sel;
|
short sel;
|
||||||
|
|
||||||
if (v8086_mode(regs))
|
if (v8086_mode(regs))
|
||||||
|
@ -750,8 +752,7 @@ int insn_get_code_seg_params(struct pt_regs *regs)
|
||||||
if (sel < 0)
|
if (sel < 0)
|
||||||
return sel;
|
return sel;
|
||||||
|
|
||||||
desc = get_desc(sel);
|
if (!get_desc(&desc, sel))
|
||||||
if (!desc)
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -759,10 +760,10 @@ int insn_get_code_seg_params(struct pt_regs *regs)
|
||||||
* determines whether a segment contains data or code. If this is a data
|
* determines whether a segment contains data or code. If this is a data
|
||||||
* segment, return error.
|
* segment, return error.
|
||||||
*/
|
*/
|
||||||
if (!(desc->type & BIT(3)))
|
if (!(desc.type & BIT(3)))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
switch ((desc->l << 1) | desc->d) {
|
switch ((desc.l << 1) | desc.d) {
|
||||||
case 0: /*
|
case 0: /*
|
||||||
* Legacy mode. CS.L=0, CS.D=0. Address and operand size are
|
* Legacy mode. CS.L=0, CS.D=0. Address and operand size are
|
||||||
* both 16-bit.
|
* both 16-bit.
|
||||||
|
|
|
@ -1311,11 +1311,11 @@ static void blkif_free_ring(struct blkfront_ring_info *rinfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
free_shadow:
|
free_shadow:
|
||||||
kfree(rinfo->shadow[i].grants_used);
|
kvfree(rinfo->shadow[i].grants_used);
|
||||||
rinfo->shadow[i].grants_used = NULL;
|
rinfo->shadow[i].grants_used = NULL;
|
||||||
kfree(rinfo->shadow[i].indirect_grants);
|
kvfree(rinfo->shadow[i].indirect_grants);
|
||||||
rinfo->shadow[i].indirect_grants = NULL;
|
rinfo->shadow[i].indirect_grants = NULL;
|
||||||
kfree(rinfo->shadow[i].sg);
|
kvfree(rinfo->shadow[i].sg);
|
||||||
rinfo->shadow[i].sg = NULL;
|
rinfo->shadow[i].sg = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1354,7 +1354,7 @@ static void blkif_free(struct blkfront_info *info, int suspend)
|
||||||
for (i = 0; i < info->nr_rings; i++)
|
for (i = 0; i < info->nr_rings; i++)
|
||||||
blkif_free_ring(&info->rinfo[i]);
|
blkif_free_ring(&info->rinfo[i]);
|
||||||
|
|
||||||
kfree(info->rinfo);
|
kvfree(info->rinfo);
|
||||||
info->rinfo = NULL;
|
info->rinfo = NULL;
|
||||||
info->nr_rings = 0;
|
info->nr_rings = 0;
|
||||||
}
|
}
|
||||||
|
@ -1906,9 +1906,9 @@ static int negotiate_mq(struct blkfront_info *info)
|
||||||
if (!info->nr_rings)
|
if (!info->nr_rings)
|
||||||
info->nr_rings = 1;
|
info->nr_rings = 1;
|
||||||
|
|
||||||
info->rinfo = kcalloc(info->nr_rings,
|
info->rinfo = kvcalloc(info->nr_rings,
|
||||||
sizeof(struct blkfront_ring_info),
|
sizeof(struct blkfront_ring_info),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!info->rinfo) {
|
if (!info->rinfo) {
|
||||||
xenbus_dev_fatal(info->xbdev, -ENOMEM, "allocating ring_info structure");
|
xenbus_dev_fatal(info->xbdev, -ENOMEM, "allocating ring_info structure");
|
||||||
info->nr_rings = 0;
|
info->nr_rings = 0;
|
||||||
|
@ -2220,17 +2220,17 @@ static int blkfront_setup_indirect(struct blkfront_ring_info *rinfo)
|
||||||
|
|
||||||
for (i = 0; i < BLK_RING_SIZE(info); i++) {
|
for (i = 0; i < BLK_RING_SIZE(info); i++) {
|
||||||
rinfo->shadow[i].grants_used =
|
rinfo->shadow[i].grants_used =
|
||||||
kcalloc(grants,
|
kvcalloc(grants,
|
||||||
sizeof(rinfo->shadow[i].grants_used[0]),
|
sizeof(rinfo->shadow[i].grants_used[0]),
|
||||||
GFP_NOIO);
|
GFP_NOIO);
|
||||||
rinfo->shadow[i].sg = kcalloc(psegs,
|
rinfo->shadow[i].sg = kvcalloc(psegs,
|
||||||
sizeof(rinfo->shadow[i].sg[0]),
|
sizeof(rinfo->shadow[i].sg[0]),
|
||||||
GFP_NOIO);
|
GFP_NOIO);
|
||||||
if (info->max_indirect_segments)
|
if (info->max_indirect_segments)
|
||||||
rinfo->shadow[i].indirect_grants =
|
rinfo->shadow[i].indirect_grants =
|
||||||
kcalloc(INDIRECT_GREFS(grants),
|
kvcalloc(INDIRECT_GREFS(grants),
|
||||||
sizeof(rinfo->shadow[i].indirect_grants[0]),
|
sizeof(rinfo->shadow[i].indirect_grants[0]),
|
||||||
GFP_NOIO);
|
GFP_NOIO);
|
||||||
if ((rinfo->shadow[i].grants_used == NULL) ||
|
if ((rinfo->shadow[i].grants_used == NULL) ||
|
||||||
(rinfo->shadow[i].sg == NULL) ||
|
(rinfo->shadow[i].sg == NULL) ||
|
||||||
(info->max_indirect_segments &&
|
(info->max_indirect_segments &&
|
||||||
|
@ -2244,11 +2244,11 @@ static int blkfront_setup_indirect(struct blkfront_ring_info *rinfo)
|
||||||
|
|
||||||
out_of_memory:
|
out_of_memory:
|
||||||
for (i = 0; i < BLK_RING_SIZE(info); i++) {
|
for (i = 0; i < BLK_RING_SIZE(info); i++) {
|
||||||
kfree(rinfo->shadow[i].grants_used);
|
kvfree(rinfo->shadow[i].grants_used);
|
||||||
rinfo->shadow[i].grants_used = NULL;
|
rinfo->shadow[i].grants_used = NULL;
|
||||||
kfree(rinfo->shadow[i].sg);
|
kvfree(rinfo->shadow[i].sg);
|
||||||
rinfo->shadow[i].sg = NULL;
|
rinfo->shadow[i].sg = NULL;
|
||||||
kfree(rinfo->shadow[i].indirect_grants);
|
kvfree(rinfo->shadow[i].indirect_grants);
|
||||||
rinfo->shadow[i].indirect_grants = NULL;
|
rinfo->shadow[i].indirect_grants = NULL;
|
||||||
}
|
}
|
||||||
if (!list_empty(&rinfo->indirect_pages)) {
|
if (!list_empty(&rinfo->indirect_pages)) {
|
||||||
|
|
|
@ -1,22 +1,14 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
/**
|
/**
|
||||||
* GHASH routines supporting VMX instructions on the Power 8
|
* GHASH routines supporting VMX instructions on the Power 8
|
||||||
*
|
*
|
||||||
* Copyright (C) 2015 International Business Machines Inc.
|
* Copyright (C) 2015, 2019 International Business Machines Inc.
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; version 2 only.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
*
|
*
|
||||||
* Author: Marcelo Henrique Cerri <mhcerri@br.ibm.com>
|
* Author: Marcelo Henrique Cerri <mhcerri@br.ibm.com>
|
||||||
|
*
|
||||||
|
* Extended by Daniel Axtens <dja@axtens.net> to replace the fallback
|
||||||
|
* mechanism. The new approach is based on arm64 code, which is:
|
||||||
|
* Copyright (C) 2014 - 2018 Linaro Ltd. <ard.biesheuvel@linaro.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
@ -39,71 +31,25 @@ void gcm_ghash_p8(u64 Xi[2], const u128 htable[16],
|
||||||
const u8 *in, size_t len);
|
const u8 *in, size_t len);
|
||||||
|
|
||||||
struct p8_ghash_ctx {
|
struct p8_ghash_ctx {
|
||||||
|
/* key used by vector asm */
|
||||||
u128 htable[16];
|
u128 htable[16];
|
||||||
struct crypto_shash *fallback;
|
/* key used by software fallback */
|
||||||
|
be128 key;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct p8_ghash_desc_ctx {
|
struct p8_ghash_desc_ctx {
|
||||||
u64 shash[2];
|
u64 shash[2];
|
||||||
u8 buffer[GHASH_DIGEST_SIZE];
|
u8 buffer[GHASH_DIGEST_SIZE];
|
||||||
int bytes;
|
int bytes;
|
||||||
struct shash_desc fallback_desc;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int p8_ghash_init_tfm(struct crypto_tfm *tfm)
|
|
||||||
{
|
|
||||||
const char *alg = "ghash-generic";
|
|
||||||
struct crypto_shash *fallback;
|
|
||||||
struct crypto_shash *shash_tfm = __crypto_shash_cast(tfm);
|
|
||||||
struct p8_ghash_ctx *ctx = crypto_tfm_ctx(tfm);
|
|
||||||
|
|
||||||
fallback = crypto_alloc_shash(alg, 0, CRYPTO_ALG_NEED_FALLBACK);
|
|
||||||
if (IS_ERR(fallback)) {
|
|
||||||
printk(KERN_ERR
|
|
||||||
"Failed to allocate transformation for '%s': %ld\n",
|
|
||||||
alg, PTR_ERR(fallback));
|
|
||||||
return PTR_ERR(fallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_shash_set_flags(fallback,
|
|
||||||
crypto_shash_get_flags((struct crypto_shash
|
|
||||||
*) tfm));
|
|
||||||
|
|
||||||
/* Check if the descsize defined in the algorithm is still enough. */
|
|
||||||
if (shash_tfm->descsize < sizeof(struct p8_ghash_desc_ctx)
|
|
||||||
+ crypto_shash_descsize(fallback)) {
|
|
||||||
printk(KERN_ERR
|
|
||||||
"Desc size of the fallback implementation (%s) does not match the expected value: %lu vs %u\n",
|
|
||||||
alg,
|
|
||||||
shash_tfm->descsize - sizeof(struct p8_ghash_desc_ctx),
|
|
||||||
crypto_shash_descsize(fallback));
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
ctx->fallback = fallback;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void p8_ghash_exit_tfm(struct crypto_tfm *tfm)
|
|
||||||
{
|
|
||||||
struct p8_ghash_ctx *ctx = crypto_tfm_ctx(tfm);
|
|
||||||
|
|
||||||
if (ctx->fallback) {
|
|
||||||
crypto_free_shash(ctx->fallback);
|
|
||||||
ctx->fallback = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int p8_ghash_init(struct shash_desc *desc)
|
static int p8_ghash_init(struct shash_desc *desc)
|
||||||
{
|
{
|
||||||
struct p8_ghash_ctx *ctx = crypto_tfm_ctx(crypto_shash_tfm(desc->tfm));
|
|
||||||
struct p8_ghash_desc_ctx *dctx = shash_desc_ctx(desc);
|
struct p8_ghash_desc_ctx *dctx = shash_desc_ctx(desc);
|
||||||
|
|
||||||
dctx->bytes = 0;
|
dctx->bytes = 0;
|
||||||
memset(dctx->shash, 0, GHASH_DIGEST_SIZE);
|
memset(dctx->shash, 0, GHASH_DIGEST_SIZE);
|
||||||
dctx->fallback_desc.tfm = ctx->fallback;
|
return 0;
|
||||||
dctx->fallback_desc.flags = desc->flags;
|
|
||||||
return crypto_shash_init(&dctx->fallback_desc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int p8_ghash_setkey(struct crypto_shash *tfm, const u8 *key,
|
static int p8_ghash_setkey(struct crypto_shash *tfm, const u8 *key,
|
||||||
|
@ -121,7 +67,51 @@ static int p8_ghash_setkey(struct crypto_shash *tfm, const u8 *key,
|
||||||
disable_kernel_vsx();
|
disable_kernel_vsx();
|
||||||
pagefault_enable();
|
pagefault_enable();
|
||||||
preempt_enable();
|
preempt_enable();
|
||||||
return crypto_shash_setkey(ctx->fallback, key, keylen);
|
|
||||||
|
memcpy(&ctx->key, key, GHASH_BLOCK_SIZE);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void __ghash_block(struct p8_ghash_ctx *ctx,
|
||||||
|
struct p8_ghash_desc_ctx *dctx)
|
||||||
|
{
|
||||||
|
if (!IN_INTERRUPT) {
|
||||||
|
preempt_disable();
|
||||||
|
pagefault_disable();
|
||||||
|
enable_kernel_vsx();
|
||||||
|
gcm_ghash_p8(dctx->shash, ctx->htable,
|
||||||
|
dctx->buffer, GHASH_DIGEST_SIZE);
|
||||||
|
disable_kernel_vsx();
|
||||||
|
pagefault_enable();
|
||||||
|
preempt_enable();
|
||||||
|
} else {
|
||||||
|
crypto_xor((u8 *)dctx->shash, dctx->buffer, GHASH_BLOCK_SIZE);
|
||||||
|
gf128mul_lle((be128 *)dctx->shash, &ctx->key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void __ghash_blocks(struct p8_ghash_ctx *ctx,
|
||||||
|
struct p8_ghash_desc_ctx *dctx,
|
||||||
|
const u8 *src, unsigned int srclen)
|
||||||
|
{
|
||||||
|
if (!IN_INTERRUPT) {
|
||||||
|
preempt_disable();
|
||||||
|
pagefault_disable();
|
||||||
|
enable_kernel_vsx();
|
||||||
|
gcm_ghash_p8(dctx->shash, ctx->htable,
|
||||||
|
src, srclen);
|
||||||
|
disable_kernel_vsx();
|
||||||
|
pagefault_enable();
|
||||||
|
preempt_enable();
|
||||||
|
} else {
|
||||||
|
while (srclen >= GHASH_BLOCK_SIZE) {
|
||||||
|
crypto_xor((u8 *)dctx->shash, src, GHASH_BLOCK_SIZE);
|
||||||
|
gf128mul_lle((be128 *)dctx->shash, &ctx->key);
|
||||||
|
srclen -= GHASH_BLOCK_SIZE;
|
||||||
|
src += GHASH_BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int p8_ghash_update(struct shash_desc *desc,
|
static int p8_ghash_update(struct shash_desc *desc,
|
||||||
|
@ -131,49 +121,33 @@ static int p8_ghash_update(struct shash_desc *desc,
|
||||||
struct p8_ghash_ctx *ctx = crypto_tfm_ctx(crypto_shash_tfm(desc->tfm));
|
struct p8_ghash_ctx *ctx = crypto_tfm_ctx(crypto_shash_tfm(desc->tfm));
|
||||||
struct p8_ghash_desc_ctx *dctx = shash_desc_ctx(desc);
|
struct p8_ghash_desc_ctx *dctx = shash_desc_ctx(desc);
|
||||||
|
|
||||||
if (IN_INTERRUPT) {
|
if (dctx->bytes) {
|
||||||
return crypto_shash_update(&dctx->fallback_desc, src,
|
if (dctx->bytes + srclen < GHASH_DIGEST_SIZE) {
|
||||||
srclen);
|
|
||||||
} else {
|
|
||||||
if (dctx->bytes) {
|
|
||||||
if (dctx->bytes + srclen < GHASH_DIGEST_SIZE) {
|
|
||||||
memcpy(dctx->buffer + dctx->bytes, src,
|
|
||||||
srclen);
|
|
||||||
dctx->bytes += srclen;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
memcpy(dctx->buffer + dctx->bytes, src,
|
memcpy(dctx->buffer + dctx->bytes, src,
|
||||||
GHASH_DIGEST_SIZE - dctx->bytes);
|
srclen);
|
||||||
preempt_disable();
|
dctx->bytes += srclen;
|
||||||
pagefault_disable();
|
return 0;
|
||||||
enable_kernel_vsx();
|
|
||||||
gcm_ghash_p8(dctx->shash, ctx->htable,
|
|
||||||
dctx->buffer, GHASH_DIGEST_SIZE);
|
|
||||||
disable_kernel_vsx();
|
|
||||||
pagefault_enable();
|
|
||||||
preempt_enable();
|
|
||||||
src += GHASH_DIGEST_SIZE - dctx->bytes;
|
|
||||||
srclen -= GHASH_DIGEST_SIZE - dctx->bytes;
|
|
||||||
dctx->bytes = 0;
|
|
||||||
}
|
}
|
||||||
len = srclen & ~(GHASH_DIGEST_SIZE - 1);
|
memcpy(dctx->buffer + dctx->bytes, src,
|
||||||
if (len) {
|
GHASH_DIGEST_SIZE - dctx->bytes);
|
||||||
preempt_disable();
|
|
||||||
pagefault_disable();
|
__ghash_block(ctx, dctx);
|
||||||
enable_kernel_vsx();
|
|
||||||
gcm_ghash_p8(dctx->shash, ctx->htable, src, len);
|
src += GHASH_DIGEST_SIZE - dctx->bytes;
|
||||||
disable_kernel_vsx();
|
srclen -= GHASH_DIGEST_SIZE - dctx->bytes;
|
||||||
pagefault_enable();
|
dctx->bytes = 0;
|
||||||
preempt_enable();
|
|
||||||
src += len;
|
|
||||||
srclen -= len;
|
|
||||||
}
|
|
||||||
if (srclen) {
|
|
||||||
memcpy(dctx->buffer, src, srclen);
|
|
||||||
dctx->bytes = srclen;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
len = srclen & ~(GHASH_DIGEST_SIZE - 1);
|
||||||
|
if (len) {
|
||||||
|
__ghash_blocks(ctx, dctx, src, len);
|
||||||
|
src += len;
|
||||||
|
srclen -= len;
|
||||||
|
}
|
||||||
|
if (srclen) {
|
||||||
|
memcpy(dctx->buffer, src, srclen);
|
||||||
|
dctx->bytes = srclen;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int p8_ghash_final(struct shash_desc *desc, u8 *out)
|
static int p8_ghash_final(struct shash_desc *desc, u8 *out)
|
||||||
|
@ -182,25 +156,14 @@ static int p8_ghash_final(struct shash_desc *desc, u8 *out)
|
||||||
struct p8_ghash_ctx *ctx = crypto_tfm_ctx(crypto_shash_tfm(desc->tfm));
|
struct p8_ghash_ctx *ctx = crypto_tfm_ctx(crypto_shash_tfm(desc->tfm));
|
||||||
struct p8_ghash_desc_ctx *dctx = shash_desc_ctx(desc);
|
struct p8_ghash_desc_ctx *dctx = shash_desc_ctx(desc);
|
||||||
|
|
||||||
if (IN_INTERRUPT) {
|
if (dctx->bytes) {
|
||||||
return crypto_shash_final(&dctx->fallback_desc, out);
|
for (i = dctx->bytes; i < GHASH_DIGEST_SIZE; i++)
|
||||||
} else {
|
dctx->buffer[i] = 0;
|
||||||
if (dctx->bytes) {
|
__ghash_block(ctx, dctx);
|
||||||
for (i = dctx->bytes; i < GHASH_DIGEST_SIZE; i++)
|
dctx->bytes = 0;
|
||||||
dctx->buffer[i] = 0;
|
|
||||||
preempt_disable();
|
|
||||||
pagefault_disable();
|
|
||||||
enable_kernel_vsx();
|
|
||||||
gcm_ghash_p8(dctx->shash, ctx->htable,
|
|
||||||
dctx->buffer, GHASH_DIGEST_SIZE);
|
|
||||||
disable_kernel_vsx();
|
|
||||||
pagefault_enable();
|
|
||||||
preempt_enable();
|
|
||||||
dctx->bytes = 0;
|
|
||||||
}
|
|
||||||
memcpy(out, dctx->shash, GHASH_DIGEST_SIZE);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
memcpy(out, dctx->shash, GHASH_DIGEST_SIZE);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct shash_alg p8_ghash_alg = {
|
struct shash_alg p8_ghash_alg = {
|
||||||
|
@ -215,11 +178,9 @@ struct shash_alg p8_ghash_alg = {
|
||||||
.cra_name = "ghash",
|
.cra_name = "ghash",
|
||||||
.cra_driver_name = "p8_ghash",
|
.cra_driver_name = "p8_ghash",
|
||||||
.cra_priority = 1000,
|
.cra_priority = 1000,
|
||||||
.cra_flags = CRYPTO_ALG_TYPE_SHASH | CRYPTO_ALG_NEED_FALLBACK,
|
.cra_flags = CRYPTO_ALG_TYPE_SHASH,
|
||||||
.cra_blocksize = GHASH_BLOCK_SIZE,
|
.cra_blocksize = GHASH_BLOCK_SIZE,
|
||||||
.cra_ctxsize = sizeof(struct p8_ghash_ctx),
|
.cra_ctxsize = sizeof(struct p8_ghash_ctx),
|
||||||
.cra_module = THIS_MODULE,
|
.cra_module = THIS_MODULE,
|
||||||
.cra_init = p8_ghash_init_tfm,
|
|
||||||
.cra_exit = p8_ghash_exit_tfm,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,18 +37,10 @@ static void psp_set_funcs(struct amdgpu_device *adev);
|
||||||
static int psp_early_init(void *handle)
|
static int psp_early_init(void *handle)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||||
|
struct psp_context *psp = &adev->psp;
|
||||||
|
|
||||||
psp_set_funcs(adev);
|
psp_set_funcs(adev);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int psp_sw_init(void *handle)
|
|
||||||
{
|
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
|
||||||
struct psp_context *psp = &adev->psp;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
switch (adev->asic_type) {
|
switch (adev->asic_type) {
|
||||||
case CHIP_VEGA10:
|
case CHIP_VEGA10:
|
||||||
case CHIP_VEGA12:
|
case CHIP_VEGA12:
|
||||||
|
@ -67,6 +59,15 @@ static int psp_sw_init(void *handle)
|
||||||
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
|
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int psp_sw_init(void *handle)
|
||||||
|
{
|
||||||
|
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||||
|
struct psp_context *psp = &adev->psp;
|
||||||
|
int ret;
|
||||||
|
|
||||||
ret = psp_init_microcode(psp);
|
ret = psp_init_microcode(psp);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
DRM_ERROR("Failed to load psp firmware!\n");
|
DRM_ERROR("Failed to load psp firmware!\n");
|
||||||
|
|
|
@ -1536,15 +1536,6 @@ int drm_atomic_helper_async_check(struct drm_device *dev,
|
||||||
old_plane_state->crtc != new_plane_state->crtc)
|
old_plane_state->crtc != new_plane_state->crtc)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/*
|
|
||||||
* FIXME: Since prepare_fb and cleanup_fb are always called on
|
|
||||||
* the new_plane_state for async updates we need to block framebuffer
|
|
||||||
* changes. This prevents use of a fb that's been cleaned up and
|
|
||||||
* double cleanups from occuring.
|
|
||||||
*/
|
|
||||||
if (old_plane_state->fb != new_plane_state->fb)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
funcs = plane->helper_private;
|
funcs = plane->helper_private;
|
||||||
if (!funcs->atomic_async_update)
|
if (!funcs->atomic_async_update)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -1575,6 +1566,8 @@ EXPORT_SYMBOL(drm_atomic_helper_async_check);
|
||||||
* drm_atomic_async_check() succeeds. Async commits are not supposed to swap
|
* drm_atomic_async_check() succeeds. Async commits are not supposed to swap
|
||||||
* the states like normal sync commits, but just do in-place changes on the
|
* the states like normal sync commits, but just do in-place changes on the
|
||||||
* current state.
|
* current state.
|
||||||
|
*
|
||||||
|
* TODO: Implement full swap instead of doing in-place changes.
|
||||||
*/
|
*/
|
||||||
void drm_atomic_helper_async_commit(struct drm_device *dev,
|
void drm_atomic_helper_async_commit(struct drm_device *dev,
|
||||||
struct drm_atomic_state *state)
|
struct drm_atomic_state *state)
|
||||||
|
@ -1585,6 +1578,9 @@ void drm_atomic_helper_async_commit(struct drm_device *dev,
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for_each_new_plane_in_state(state, plane, plane_state, i) {
|
for_each_new_plane_in_state(state, plane, plane_state, i) {
|
||||||
|
struct drm_framebuffer *new_fb = plane_state->fb;
|
||||||
|
struct drm_framebuffer *old_fb = plane->state->fb;
|
||||||
|
|
||||||
funcs = plane->helper_private;
|
funcs = plane->helper_private;
|
||||||
funcs->atomic_async_update(plane, plane_state);
|
funcs->atomic_async_update(plane, plane_state);
|
||||||
|
|
||||||
|
@ -1593,11 +1589,17 @@ void drm_atomic_helper_async_commit(struct drm_device *dev,
|
||||||
* plane->state in-place, make sure at least common
|
* plane->state in-place, make sure at least common
|
||||||
* properties have been properly updated.
|
* properties have been properly updated.
|
||||||
*/
|
*/
|
||||||
WARN_ON_ONCE(plane->state->fb != plane_state->fb);
|
WARN_ON_ONCE(plane->state->fb != new_fb);
|
||||||
WARN_ON_ONCE(plane->state->crtc_x != plane_state->crtc_x);
|
WARN_ON_ONCE(plane->state->crtc_x != plane_state->crtc_x);
|
||||||
WARN_ON_ONCE(plane->state->crtc_y != plane_state->crtc_y);
|
WARN_ON_ONCE(plane->state->crtc_y != plane_state->crtc_y);
|
||||||
WARN_ON_ONCE(plane->state->src_x != plane_state->src_x);
|
WARN_ON_ONCE(plane->state->src_x != plane_state->src_x);
|
||||||
WARN_ON_ONCE(plane->state->src_y != plane_state->src_y);
|
WARN_ON_ONCE(plane->state->src_y != plane_state->src_y);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure the FBs have been swapped so that cleanups in the
|
||||||
|
* new_state performs a cleanup in the old FB.
|
||||||
|
*/
|
||||||
|
WARN_ON_ONCE(plane_state->fb != old_fb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_atomic_helper_async_commit);
|
EXPORT_SYMBOL(drm_atomic_helper_async_commit);
|
||||||
|
|
|
@ -588,6 +588,10 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
|
||||||
|
|
||||||
plane = crtc->primary;
|
plane = crtc->primary;
|
||||||
|
|
||||||
|
/* allow disabling with the primary plane leased */
|
||||||
|
if (crtc_req->mode_valid && !drm_lease_held(file_priv, plane->base.id))
|
||||||
|
return -EACCES;
|
||||||
|
|
||||||
mutex_lock(&crtc->dev->mode_config.mutex);
|
mutex_lock(&crtc->dev->mode_config.mutex);
|
||||||
drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
|
drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
|
||||||
retry:
|
retry:
|
||||||
|
|
|
@ -172,6 +172,25 @@ static const struct edid_quirk {
|
||||||
/* Rotel RSX-1058 forwards sink's EDID but only does HDMI 1.1*/
|
/* Rotel RSX-1058 forwards sink's EDID but only does HDMI 1.1*/
|
||||||
{ "ETR", 13896, EDID_QUIRK_FORCE_8BPC },
|
{ "ETR", 13896, EDID_QUIRK_FORCE_8BPC },
|
||||||
|
|
||||||
|
/* Valve Index Headset */
|
||||||
|
{ "VLV", 0x91a8, EDID_QUIRK_NON_DESKTOP },
|
||||||
|
{ "VLV", 0x91b0, EDID_QUIRK_NON_DESKTOP },
|
||||||
|
{ "VLV", 0x91b1, EDID_QUIRK_NON_DESKTOP },
|
||||||
|
{ "VLV", 0x91b2, EDID_QUIRK_NON_DESKTOP },
|
||||||
|
{ "VLV", 0x91b3, EDID_QUIRK_NON_DESKTOP },
|
||||||
|
{ "VLV", 0x91b4, EDID_QUIRK_NON_DESKTOP },
|
||||||
|
{ "VLV", 0x91b5, EDID_QUIRK_NON_DESKTOP },
|
||||||
|
{ "VLV", 0x91b6, EDID_QUIRK_NON_DESKTOP },
|
||||||
|
{ "VLV", 0x91b7, EDID_QUIRK_NON_DESKTOP },
|
||||||
|
{ "VLV", 0x91b8, EDID_QUIRK_NON_DESKTOP },
|
||||||
|
{ "VLV", 0x91b9, EDID_QUIRK_NON_DESKTOP },
|
||||||
|
{ "VLV", 0x91ba, EDID_QUIRK_NON_DESKTOP },
|
||||||
|
{ "VLV", 0x91bb, EDID_QUIRK_NON_DESKTOP },
|
||||||
|
{ "VLV", 0x91bc, EDID_QUIRK_NON_DESKTOP },
|
||||||
|
{ "VLV", 0x91bd, EDID_QUIRK_NON_DESKTOP },
|
||||||
|
{ "VLV", 0x91be, EDID_QUIRK_NON_DESKTOP },
|
||||||
|
{ "VLV", 0x91bf, EDID_QUIRK_NON_DESKTOP },
|
||||||
|
|
||||||
/* HTC Vive and Vive Pro VR Headsets */
|
/* HTC Vive and Vive Pro VR Headsets */
|
||||||
{ "HVR", 0xaa01, EDID_QUIRK_NON_DESKTOP },
|
{ "HVR", 0xaa01, EDID_QUIRK_NON_DESKTOP },
|
||||||
{ "HVR", 0xaa02, EDID_QUIRK_NON_DESKTOP },
|
{ "HVR", 0xaa02, EDID_QUIRK_NON_DESKTOP },
|
||||||
|
@ -193,6 +212,12 @@ static const struct edid_quirk {
|
||||||
|
|
||||||
/* Sony PlayStation VR Headset */
|
/* Sony PlayStation VR Headset */
|
||||||
{ "SNY", 0x0704, EDID_QUIRK_NON_DESKTOP },
|
{ "SNY", 0x0704, EDID_QUIRK_NON_DESKTOP },
|
||||||
|
|
||||||
|
/* Sensics VR Headsets */
|
||||||
|
{ "SEN", 0x1019, EDID_QUIRK_NON_DESKTOP },
|
||||||
|
|
||||||
|
/* OSVR HDK and HDK2 VR Headsets */
|
||||||
|
{ "SVR", 0x1019, EDID_QUIRK_NON_DESKTOP },
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -869,6 +869,11 @@ retry:
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
if (!drm_lease_held(file_priv, crtc->cursor->base.id)) {
|
||||||
|
ret = -EACCES;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
ret = drm_mode_cursor_universal(crtc, req, file_priv, &ctx);
|
ret = drm_mode_cursor_universal(crtc, req, file_priv, &ctx);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -971,6 +976,9 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
|
||||||
|
|
||||||
plane = crtc->primary;
|
plane = crtc->primary;
|
||||||
|
|
||||||
|
if (!drm_lease_held(file_priv, plane->base.id))
|
||||||
|
return -EACCES;
|
||||||
|
|
||||||
if (crtc->funcs->page_flip_target) {
|
if (crtc->funcs->page_flip_target) {
|
||||||
u32 current_vblank;
|
u32 current_vblank;
|
||||||
int r;
|
int r;
|
||||||
|
|
|
@ -594,6 +594,9 @@ void cdv_intel_lvds_init(struct drm_device *dev,
|
||||||
int pipe;
|
int pipe;
|
||||||
u8 pin;
|
u8 pin;
|
||||||
|
|
||||||
|
if (!dev_priv->lvds_enabled_in_vbt)
|
||||||
|
return;
|
||||||
|
|
||||||
pin = GMBUS_PORT_PANEL;
|
pin = GMBUS_PORT_PANEL;
|
||||||
if (!lvds_is_present_in_vbt(dev, &pin)) {
|
if (!lvds_is_present_in_vbt(dev, &pin)) {
|
||||||
DRM_DEBUG_KMS("LVDS is not present in VBT\n");
|
DRM_DEBUG_KMS("LVDS is not present in VBT\n");
|
||||||
|
|
|
@ -436,6 +436,9 @@ parse_driver_features(struct drm_psb_private *dev_priv,
|
||||||
if (driver->lvds_config == BDB_DRIVER_FEATURE_EDP)
|
if (driver->lvds_config == BDB_DRIVER_FEATURE_EDP)
|
||||||
dev_priv->edp.support = 1;
|
dev_priv->edp.support = 1;
|
||||||
|
|
||||||
|
dev_priv->lvds_enabled_in_vbt = driver->lvds_config != 0;
|
||||||
|
DRM_DEBUG_KMS("LVDS VBT config bits: 0x%x\n", driver->lvds_config);
|
||||||
|
|
||||||
/* This bit means to use 96Mhz for DPLL_A or not */
|
/* This bit means to use 96Mhz for DPLL_A or not */
|
||||||
if (driver->primary_lfp_id)
|
if (driver->primary_lfp_id)
|
||||||
dev_priv->dplla_96mhz = true;
|
dev_priv->dplla_96mhz = true;
|
||||||
|
|
|
@ -537,6 +537,7 @@ struct drm_psb_private {
|
||||||
int lvds_ssc_freq;
|
int lvds_ssc_freq;
|
||||||
bool is_lvds_on;
|
bool is_lvds_on;
|
||||||
bool is_mipi_on;
|
bool is_mipi_on;
|
||||||
|
bool lvds_enabled_in_vbt;
|
||||||
u32 mipi_ctrl_display;
|
u32 mipi_ctrl_display;
|
||||||
|
|
||||||
unsigned int core_freq;
|
unsigned int core_freq;
|
||||||
|
|
|
@ -1852,7 +1852,8 @@ static int emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
|
||||||
struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;
|
struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;
|
||||||
unsigned long g_gtt_index = off >> info->gtt_entry_size_shift;
|
unsigned long g_gtt_index = off >> info->gtt_entry_size_shift;
|
||||||
unsigned long gma, gfn;
|
unsigned long gma, gfn;
|
||||||
struct intel_gvt_gtt_entry e, m;
|
struct intel_gvt_gtt_entry e = {.val64 = 0, .type = GTT_TYPE_GGTT_PTE};
|
||||||
|
struct intel_gvt_gtt_entry m = {.val64 = 0, .type = GTT_TYPE_GGTT_PTE};
|
||||||
dma_addr_t dma_addr;
|
dma_addr_t dma_addr;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -1928,7 +1929,8 @@ static int emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
|
||||||
|
|
||||||
if (ops->test_present(&e)) {
|
if (ops->test_present(&e)) {
|
||||||
gfn = ops->get_pfn(&e);
|
gfn = ops->get_pfn(&e);
|
||||||
m = e;
|
m.val64 = e.val64;
|
||||||
|
m.type = e.type;
|
||||||
|
|
||||||
/* one PTE update may be issued in multiple writes and the
|
/* one PTE update may be issued in multiple writes and the
|
||||||
* first write may not construct a valid gfn
|
* first write may not construct a valid gfn
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
* macros. Do **not** mass change existing definitions just to update the style.
|
* macros. Do **not** mass change existing definitions just to update the style.
|
||||||
*
|
*
|
||||||
* Layout
|
* Layout
|
||||||
* ''''''
|
* ~~~~~~
|
||||||
*
|
*
|
||||||
* Keep helper macros near the top. For example, _PIPE() and friends.
|
* Keep helper macros near the top. For example, _PIPE() and friends.
|
||||||
*
|
*
|
||||||
|
@ -78,7 +78,7 @@
|
||||||
* style. Use lower case in hexadecimal values.
|
* style. Use lower case in hexadecimal values.
|
||||||
*
|
*
|
||||||
* Naming
|
* Naming
|
||||||
* ''''''
|
* ~~~~~~
|
||||||
*
|
*
|
||||||
* Try to name registers according to the specs. If the register name changes in
|
* Try to name registers according to the specs. If the register name changes in
|
||||||
* the specs from platform to another, stick to the original name.
|
* the specs from platform to another, stick to the original name.
|
||||||
|
@ -96,7 +96,7 @@
|
||||||
* suffix to the name. For example, ``_SKL`` or ``_GEN8``.
|
* suffix to the name. For example, ``_SKL`` or ``_GEN8``.
|
||||||
*
|
*
|
||||||
* Examples
|
* Examples
|
||||||
* ''''''''
|
* ~~~~~~~~
|
||||||
*
|
*
|
||||||
* (Note that the values in the example are indented using spaces instead of
|
* (Note that the values in the example are indented using spaces instead of
|
||||||
* TABs to avoid misalignment in generated documentation. Use TABs in the
|
* TABs to avoid misalignment in generated documentation. Use TABs in the
|
||||||
|
|
|
@ -1372,6 +1372,10 @@ static int intel_sanitize_fbc_option(struct drm_i915_private *dev_priv)
|
||||||
if (!HAS_FBC(dev_priv))
|
if (!HAS_FBC(dev_priv))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* https://bugs.freedesktop.org/show_bug.cgi?id=108085 */
|
||||||
|
if (IS_GEMINILAKE(dev_priv))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9)
|
if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
* costly and simplifies things. We can revisit this in the future.
|
* costly and simplifies things. We can revisit this in the future.
|
||||||
*
|
*
|
||||||
* Layout
|
* Layout
|
||||||
* ''''''
|
* ~~~~~~
|
||||||
*
|
*
|
||||||
* Keep things in this file ordered by WA type, as per the above (context, GT,
|
* Keep things in this file ordered by WA type, as per the above (context, GT,
|
||||||
* display, register whitelist, batchbuffer). Then, inside each type, keep the
|
* display, register whitelist, batchbuffer). Then, inside each type, keep the
|
||||||
|
|
|
@ -504,6 +504,8 @@ static int mdp5_plane_atomic_async_check(struct drm_plane *plane,
|
||||||
static void mdp5_plane_atomic_async_update(struct drm_plane *plane,
|
static void mdp5_plane_atomic_async_update(struct drm_plane *plane,
|
||||||
struct drm_plane_state *new_state)
|
struct drm_plane_state *new_state)
|
||||||
{
|
{
|
||||||
|
struct drm_framebuffer *old_fb = plane->state->fb;
|
||||||
|
|
||||||
plane->state->src_x = new_state->src_x;
|
plane->state->src_x = new_state->src_x;
|
||||||
plane->state->src_y = new_state->src_y;
|
plane->state->src_y = new_state->src_y;
|
||||||
plane->state->crtc_x = new_state->crtc_x;
|
plane->state->crtc_x = new_state->crtc_x;
|
||||||
|
@ -526,6 +528,8 @@ static void mdp5_plane_atomic_async_update(struct drm_plane *plane,
|
||||||
|
|
||||||
*to_mdp5_plane_state(plane->state) =
|
*to_mdp5_plane_state(plane->state) =
|
||||||
*to_mdp5_plane_state(new_state);
|
*to_mdp5_plane_state(new_state);
|
||||||
|
|
||||||
|
new_state->fb = old_fb;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct drm_plane_helper_funcs mdp5_plane_helper_funcs = {
|
static const struct drm_plane_helper_funcs mdp5_plane_helper_funcs = {
|
||||||
|
|
|
@ -16,10 +16,21 @@ config DRM_NOUVEAU
|
||||||
select INPUT if ACPI && X86
|
select INPUT if ACPI && X86
|
||||||
select THERMAL if ACPI && X86
|
select THERMAL if ACPI && X86
|
||||||
select ACPI_VIDEO if ACPI && X86
|
select ACPI_VIDEO if ACPI && X86
|
||||||
select DRM_VM
|
|
||||||
help
|
help
|
||||||
Choose this option for open-source NVIDIA support.
|
Choose this option for open-source NVIDIA support.
|
||||||
|
|
||||||
|
config NOUVEAU_LEGACY_CTX_SUPPORT
|
||||||
|
bool "Nouveau legacy context support"
|
||||||
|
depends on DRM_NOUVEAU
|
||||||
|
select DRM_VM
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
There was a version of the nouveau DDX that relied on legacy
|
||||||
|
ctx ioctls not erroring out. But that was back in time a long
|
||||||
|
ways, so offer a way to disable it now. For uapi compat with
|
||||||
|
old nouveau ddx this should be on by default, but modern distros
|
||||||
|
should consider turning it off.
|
||||||
|
|
||||||
config NOUVEAU_PLATFORM_DRIVER
|
config NOUVEAU_PLATFORM_DRIVER
|
||||||
bool "Nouveau (NVIDIA) SoC GPUs"
|
bool "Nouveau (NVIDIA) SoC GPUs"
|
||||||
depends on DRM_NOUVEAU && ARCH_TEGRA
|
depends on DRM_NOUVEAU && ARCH_TEGRA
|
||||||
|
|
|
@ -38,6 +38,7 @@ struct nvkm_i2c_bus {
|
||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
struct list_head head;
|
struct list_head head;
|
||||||
struct i2c_adapter i2c;
|
struct i2c_adapter i2c;
|
||||||
|
u8 enabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
int nvkm_i2c_bus_acquire(struct nvkm_i2c_bus *);
|
int nvkm_i2c_bus_acquire(struct nvkm_i2c_bus *);
|
||||||
|
@ -57,6 +58,7 @@ struct nvkm_i2c_aux {
|
||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
struct list_head head;
|
struct list_head head;
|
||||||
struct i2c_adapter i2c;
|
struct i2c_adapter i2c;
|
||||||
|
u8 enabled;
|
||||||
|
|
||||||
u32 intr;
|
u32 intr;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1017,8 +1017,11 @@ nouveau_driver_fops = {
|
||||||
static struct drm_driver
|
static struct drm_driver
|
||||||
driver_stub = {
|
driver_stub = {
|
||||||
.driver_features =
|
.driver_features =
|
||||||
DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_RENDER |
|
DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_RENDER
|
||||||
DRIVER_KMS_LEGACY_CONTEXT,
|
#if defined(CONFIG_NOUVEAU_LEGACY_CTX_SUPPORT)
|
||||||
|
| DRIVER_KMS_LEGACY_CONTEXT
|
||||||
|
#endif
|
||||||
|
,
|
||||||
|
|
||||||
.load = nouveau_drm_load,
|
.load = nouveau_drm_load,
|
||||||
.unload = nouveau_drm_unload,
|
.unload = nouveau_drm_unload,
|
||||||
|
|
|
@ -105,9 +105,15 @@ nvkm_i2c_aux_acquire(struct nvkm_i2c_aux *aux)
|
||||||
{
|
{
|
||||||
struct nvkm_i2c_pad *pad = aux->pad;
|
struct nvkm_i2c_pad *pad = aux->pad;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
AUX_TRACE(aux, "acquire");
|
AUX_TRACE(aux, "acquire");
|
||||||
mutex_lock(&aux->mutex);
|
mutex_lock(&aux->mutex);
|
||||||
ret = nvkm_i2c_pad_acquire(pad, NVKM_I2C_PAD_AUX);
|
|
||||||
|
if (aux->enabled)
|
||||||
|
ret = nvkm_i2c_pad_acquire(pad, NVKM_I2C_PAD_AUX);
|
||||||
|
else
|
||||||
|
ret = -EIO;
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
mutex_unlock(&aux->mutex);
|
mutex_unlock(&aux->mutex);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -145,6 +151,24 @@ nvkm_i2c_aux_del(struct nvkm_i2c_aux **paux)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nvkm_i2c_aux_init(struct nvkm_i2c_aux *aux)
|
||||||
|
{
|
||||||
|
AUX_TRACE(aux, "init");
|
||||||
|
mutex_lock(&aux->mutex);
|
||||||
|
aux->enabled = true;
|
||||||
|
mutex_unlock(&aux->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nvkm_i2c_aux_fini(struct nvkm_i2c_aux *aux)
|
||||||
|
{
|
||||||
|
AUX_TRACE(aux, "fini");
|
||||||
|
mutex_lock(&aux->mutex);
|
||||||
|
aux->enabled = false;
|
||||||
|
mutex_unlock(&aux->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
nvkm_i2c_aux_ctor(const struct nvkm_i2c_aux_func *func,
|
nvkm_i2c_aux_ctor(const struct nvkm_i2c_aux_func *func,
|
||||||
struct nvkm_i2c_pad *pad, int id,
|
struct nvkm_i2c_pad *pad, int id,
|
||||||
|
|
|
@ -16,6 +16,8 @@ int nvkm_i2c_aux_ctor(const struct nvkm_i2c_aux_func *, struct nvkm_i2c_pad *,
|
||||||
int nvkm_i2c_aux_new_(const struct nvkm_i2c_aux_func *, struct nvkm_i2c_pad *,
|
int nvkm_i2c_aux_new_(const struct nvkm_i2c_aux_func *, struct nvkm_i2c_pad *,
|
||||||
int id, struct nvkm_i2c_aux **);
|
int id, struct nvkm_i2c_aux **);
|
||||||
void nvkm_i2c_aux_del(struct nvkm_i2c_aux **);
|
void nvkm_i2c_aux_del(struct nvkm_i2c_aux **);
|
||||||
|
void nvkm_i2c_aux_init(struct nvkm_i2c_aux *);
|
||||||
|
void nvkm_i2c_aux_fini(struct nvkm_i2c_aux *);
|
||||||
int nvkm_i2c_aux_xfer(struct nvkm_i2c_aux *, bool retry, u8 type,
|
int nvkm_i2c_aux_xfer(struct nvkm_i2c_aux *, bool retry, u8 type,
|
||||||
u32 addr, u8 *data, u8 *size);
|
u32 addr, u8 *data, u8 *size);
|
||||||
|
|
||||||
|
|
|
@ -160,8 +160,18 @@ nvkm_i2c_fini(struct nvkm_subdev *subdev, bool suspend)
|
||||||
{
|
{
|
||||||
struct nvkm_i2c *i2c = nvkm_i2c(subdev);
|
struct nvkm_i2c *i2c = nvkm_i2c(subdev);
|
||||||
struct nvkm_i2c_pad *pad;
|
struct nvkm_i2c_pad *pad;
|
||||||
|
struct nvkm_i2c_bus *bus;
|
||||||
|
struct nvkm_i2c_aux *aux;
|
||||||
u32 mask;
|
u32 mask;
|
||||||
|
|
||||||
|
list_for_each_entry(aux, &i2c->aux, head) {
|
||||||
|
nvkm_i2c_aux_fini(aux);
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(bus, &i2c->bus, head) {
|
||||||
|
nvkm_i2c_bus_fini(bus);
|
||||||
|
}
|
||||||
|
|
||||||
if ((mask = (1 << i2c->func->aux) - 1), i2c->func->aux_stat) {
|
if ((mask = (1 << i2c->func->aux) - 1), i2c->func->aux_stat) {
|
||||||
i2c->func->aux_mask(i2c, NVKM_I2C_ANY, mask, 0);
|
i2c->func->aux_mask(i2c, NVKM_I2C_ANY, mask, 0);
|
||||||
i2c->func->aux_stat(i2c, &mask, &mask, &mask, &mask);
|
i2c->func->aux_stat(i2c, &mask, &mask, &mask, &mask);
|
||||||
|
@ -180,6 +190,7 @@ nvkm_i2c_init(struct nvkm_subdev *subdev)
|
||||||
struct nvkm_i2c *i2c = nvkm_i2c(subdev);
|
struct nvkm_i2c *i2c = nvkm_i2c(subdev);
|
||||||
struct nvkm_i2c_bus *bus;
|
struct nvkm_i2c_bus *bus;
|
||||||
struct nvkm_i2c_pad *pad;
|
struct nvkm_i2c_pad *pad;
|
||||||
|
struct nvkm_i2c_aux *aux;
|
||||||
|
|
||||||
list_for_each_entry(pad, &i2c->pad, head) {
|
list_for_each_entry(pad, &i2c->pad, head) {
|
||||||
nvkm_i2c_pad_init(pad);
|
nvkm_i2c_pad_init(pad);
|
||||||
|
@ -189,6 +200,10 @@ nvkm_i2c_init(struct nvkm_subdev *subdev)
|
||||||
nvkm_i2c_bus_init(bus);
|
nvkm_i2c_bus_init(bus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(aux, &i2c->aux, head) {
|
||||||
|
nvkm_i2c_aux_init(aux);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,6 +110,19 @@ nvkm_i2c_bus_init(struct nvkm_i2c_bus *bus)
|
||||||
BUS_TRACE(bus, "init");
|
BUS_TRACE(bus, "init");
|
||||||
if (bus->func->init)
|
if (bus->func->init)
|
||||||
bus->func->init(bus);
|
bus->func->init(bus);
|
||||||
|
|
||||||
|
mutex_lock(&bus->mutex);
|
||||||
|
bus->enabled = true;
|
||||||
|
mutex_unlock(&bus->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nvkm_i2c_bus_fini(struct nvkm_i2c_bus *bus)
|
||||||
|
{
|
||||||
|
BUS_TRACE(bus, "fini");
|
||||||
|
mutex_lock(&bus->mutex);
|
||||||
|
bus->enabled = false;
|
||||||
|
mutex_unlock(&bus->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -126,9 +139,15 @@ nvkm_i2c_bus_acquire(struct nvkm_i2c_bus *bus)
|
||||||
{
|
{
|
||||||
struct nvkm_i2c_pad *pad = bus->pad;
|
struct nvkm_i2c_pad *pad = bus->pad;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
BUS_TRACE(bus, "acquire");
|
BUS_TRACE(bus, "acquire");
|
||||||
mutex_lock(&bus->mutex);
|
mutex_lock(&bus->mutex);
|
||||||
ret = nvkm_i2c_pad_acquire(pad, NVKM_I2C_PAD_I2C);
|
|
||||||
|
if (bus->enabled)
|
||||||
|
ret = nvkm_i2c_pad_acquire(pad, NVKM_I2C_PAD_I2C);
|
||||||
|
else
|
||||||
|
ret = -EIO;
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
mutex_unlock(&bus->mutex);
|
mutex_unlock(&bus->mutex);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -18,6 +18,7 @@ int nvkm_i2c_bus_new_(const struct nvkm_i2c_bus_func *, struct nvkm_i2c_pad *,
|
||||||
int id, struct nvkm_i2c_bus **);
|
int id, struct nvkm_i2c_bus **);
|
||||||
void nvkm_i2c_bus_del(struct nvkm_i2c_bus **);
|
void nvkm_i2c_bus_del(struct nvkm_i2c_bus **);
|
||||||
void nvkm_i2c_bus_init(struct nvkm_i2c_bus *);
|
void nvkm_i2c_bus_init(struct nvkm_i2c_bus *);
|
||||||
|
void nvkm_i2c_bus_fini(struct nvkm_i2c_bus *);
|
||||||
|
|
||||||
int nvkm_i2c_bit_xfer(struct nvkm_i2c_bus *, struct i2c_msg *, int);
|
int nvkm_i2c_bit_xfer(struct nvkm_i2c_bus *, struct i2c_msg *, int);
|
||||||
|
|
||||||
|
|
|
@ -921,12 +921,12 @@ static void avivo_get_fb_ref_div(unsigned nom, unsigned den, unsigned post_div,
|
||||||
ref_div_max = max(min(100 / post_div, ref_div_max), 1u);
|
ref_div_max = max(min(100 / post_div, ref_div_max), 1u);
|
||||||
|
|
||||||
/* get matching reference and feedback divider */
|
/* get matching reference and feedback divider */
|
||||||
*ref_div = min(max(DIV_ROUND_CLOSEST(den, post_div), 1u), ref_div_max);
|
*ref_div = min(max(den/post_div, 1u), ref_div_max);
|
||||||
*fb_div = DIV_ROUND_CLOSEST(nom * *ref_div * post_div, den);
|
*fb_div = DIV_ROUND_CLOSEST(nom * *ref_div * post_div, den);
|
||||||
|
|
||||||
/* limit fb divider to its maximum */
|
/* limit fb divider to its maximum */
|
||||||
if (*fb_div > fb_div_max) {
|
if (*fb_div > fb_div_max) {
|
||||||
*ref_div = DIV_ROUND_CLOSEST(*ref_div * fb_div_max, *fb_div);
|
*ref_div = (*ref_div * fb_div_max)/(*fb_div);
|
||||||
*fb_div = fb_div_max;
|
*fb_div = fb_div_max;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,7 +177,8 @@ static int sun8i_hdmi_phy_config_h3(struct dw_hdmi *hdmi,
|
||||||
SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSW |
|
SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSW |
|
||||||
SUN8I_HDMI_PHY_ANA_CFG2_REG_SLV(4);
|
SUN8I_HDMI_PHY_ANA_CFG2_REG_SLV(4);
|
||||||
ana_cfg3_init |= SUN8I_HDMI_PHY_ANA_CFG3_REG_AMPCK(9) |
|
ana_cfg3_init |= SUN8I_HDMI_PHY_ANA_CFG3_REG_AMPCK(9) |
|
||||||
SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(13);
|
SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(13) |
|
||||||
|
SUN8I_HDMI_PHY_ANA_CFG3_REG_EMP(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
|
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
|
||||||
|
|
|
@ -204,7 +204,7 @@ static void tegra_bo_free(struct drm_device *drm, struct tegra_bo *bo)
|
||||||
{
|
{
|
||||||
if (bo->pages) {
|
if (bo->pages) {
|
||||||
dma_unmap_sg(drm->dev, bo->sgt->sgl, bo->sgt->nents,
|
dma_unmap_sg(drm->dev, bo->sgt->sgl, bo->sgt->nents,
|
||||||
DMA_BIDIRECTIONAL);
|
DMA_FROM_DEVICE);
|
||||||
drm_gem_put_pages(&bo->gem, bo->pages, true, true);
|
drm_gem_put_pages(&bo->gem, bo->pages, true, true);
|
||||||
sg_free_table(bo->sgt);
|
sg_free_table(bo->sgt);
|
||||||
kfree(bo->sgt);
|
kfree(bo->sgt);
|
||||||
|
@ -230,7 +230,7 @@ static int tegra_bo_get_pages(struct drm_device *drm, struct tegra_bo *bo)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = dma_map_sg(drm->dev, bo->sgt->sgl, bo->sgt->nents,
|
err = dma_map_sg(drm->dev, bo->sgt->sgl, bo->sgt->nents,
|
||||||
DMA_BIDIRECTIONAL);
|
DMA_FROM_DEVICE);
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
err = -EFAULT;
|
err = -EFAULT;
|
||||||
goto free_sgt;
|
goto free_sgt;
|
||||||
|
|
|
@ -1247,7 +1247,13 @@ static int vmw_master_set(struct drm_device *dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_priv->active_master = vmaster;
|
dev_priv->active_master = vmaster;
|
||||||
drm_sysfs_hotplug_event(dev);
|
|
||||||
|
/*
|
||||||
|
* Inform a new master that the layout may have changed while
|
||||||
|
* it was gone.
|
||||||
|
*/
|
||||||
|
if (!from_open)
|
||||||
|
drm_sysfs_hotplug_event(dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -503,6 +503,7 @@ static int mlxcpld_i2c_probe(struct platform_device *pdev)
|
||||||
platform_set_drvdata(pdev, priv);
|
platform_set_drvdata(pdev, priv);
|
||||||
|
|
||||||
priv->dev = &pdev->dev;
|
priv->dev = &pdev->dev;
|
||||||
|
priv->base_addr = MLXPLAT_CPLD_LPC_I2C_BASE_ADDR;
|
||||||
|
|
||||||
/* Register with i2c layer */
|
/* Register with i2c layer */
|
||||||
mlxcpld_i2c_adapter.timeout = usecs_to_jiffies(MLXCPLD_I2C_XFER_TO);
|
mlxcpld_i2c_adapter.timeout = usecs_to_jiffies(MLXCPLD_I2C_XFER_TO);
|
||||||
|
@ -518,7 +519,6 @@ static int mlxcpld_i2c_probe(struct platform_device *pdev)
|
||||||
mlxcpld_i2c_adapter.nr = pdev->id;
|
mlxcpld_i2c_adapter.nr = pdev->id;
|
||||||
priv->adap = mlxcpld_i2c_adapter;
|
priv->adap = mlxcpld_i2c_adapter;
|
||||||
priv->adap.dev.parent = &pdev->dev;
|
priv->adap.dev.parent = &pdev->dev;
|
||||||
priv->base_addr = MLXPLAT_CPLD_LPC_I2C_BASE_ADDR;
|
|
||||||
i2c_set_adapdata(&priv->adap, priv);
|
i2c_set_adapdata(&priv->adap, priv);
|
||||||
|
|
||||||
err = i2c_add_numbered_adapter(&priv->adap);
|
err = i2c_add_numbered_adapter(&priv->adap);
|
||||||
|
|
|
@ -356,7 +356,7 @@ static int synquacer_i2c_doxfer(struct synquacer_i2c *i2c,
|
||||||
/* wait 2 clock periods to ensure the stop has been through the bus */
|
/* wait 2 clock periods to ensure the stop has been through the bus */
|
||||||
udelay(DIV_ROUND_UP(2 * 1000, i2c->speed_khz));
|
udelay(DIV_ROUND_UP(2 * 1000, i2c->speed_khz));
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static irqreturn_t synquacer_i2c_isr(int irq, void *dev_id)
|
static irqreturn_t synquacer_i2c_isr(int irq, void *dev_id)
|
||||||
|
|
|
@ -718,11 +718,16 @@ static const struct i2c_algorithm xiic_algorithm = {
|
||||||
.functionality = xiic_func,
|
.functionality = xiic_func,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct i2c_adapter_quirks xiic_quirks = {
|
||||||
|
.max_read_len = 255,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct i2c_adapter xiic_adapter = {
|
static const struct i2c_adapter xiic_adapter = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.name = DRIVER_NAME,
|
.name = DRIVER_NAME,
|
||||||
.class = I2C_CLASS_DEPRECATED,
|
.class = I2C_CLASS_DEPRECATED,
|
||||||
.algo = &xiic_algorithm,
|
.algo = &xiic_algorithm,
|
||||||
|
.quirks = &xiic_quirks,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -397,7 +397,7 @@ static irqreturn_t ads8688_trigger_handler(int irq, void *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
iio_push_to_buffers_with_timestamp(indio_dev, buffer,
|
iio_push_to_buffers_with_timestamp(indio_dev, buffer,
|
||||||
pf->timestamp);
|
iio_get_time_ns(indio_dev));
|
||||||
|
|
||||||
iio_trigger_notify_done(indio_dev->trig);
|
iio_trigger_notify_done(indio_dev->trig);
|
||||||
|
|
||||||
|
|
|
@ -166,7 +166,7 @@ static int ds4424_verify_chip(struct iio_dev *indio_dev)
|
||||||
{
|
{
|
||||||
int ret, val;
|
int ret, val;
|
||||||
|
|
||||||
ret = ds4424_get_value(indio_dev, &val, DS4424_DAC_ADDR(0));
|
ret = ds4424_get_value(indio_dev, &val, 0);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
dev_err(&indio_dev->dev,
|
dev_err(&indio_dev->dev,
|
||||||
"%s failed. ret: %d\n", __func__, ret);
|
"%s failed. ret: %d\n", __func__, ret);
|
||||||
|
|
|
@ -22,15 +22,6 @@
|
||||||
#define AR71XX_RESET_REG_MISC_INT_ENABLE 4
|
#define AR71XX_RESET_REG_MISC_INT_ENABLE 4
|
||||||
|
|
||||||
#define ATH79_MISC_IRQ_COUNT 32
|
#define ATH79_MISC_IRQ_COUNT 32
|
||||||
#define ATH79_MISC_PERF_IRQ 5
|
|
||||||
|
|
||||||
static int ath79_perfcount_irq;
|
|
||||||
|
|
||||||
int get_c0_perfcount_int(void)
|
|
||||||
{
|
|
||||||
return ath79_perfcount_irq;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
|
|
||||||
|
|
||||||
static void ath79_misc_irq_handler(struct irq_desc *desc)
|
static void ath79_misc_irq_handler(struct irq_desc *desc)
|
||||||
{
|
{
|
||||||
|
@ -122,8 +113,6 @@ static void __init ath79_misc_intc_domain_init(
|
||||||
{
|
{
|
||||||
void __iomem *base = domain->host_data;
|
void __iomem *base = domain->host_data;
|
||||||
|
|
||||||
ath79_perfcount_irq = irq_create_mapping(domain, ATH79_MISC_PERF_IRQ);
|
|
||||||
|
|
||||||
/* Disable and clear all interrupts */
|
/* Disable and clear all interrupts */
|
||||||
__raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE);
|
__raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE);
|
||||||
__raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS);
|
__raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS);
|
||||||
|
|
|
@ -401,6 +401,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
|
||||||
struct smsusb_device_t *dev;
|
struct smsusb_device_t *dev;
|
||||||
void *mdev;
|
void *mdev;
|
||||||
int i, rc;
|
int i, rc;
|
||||||
|
int align = 0;
|
||||||
|
|
||||||
/* create device object */
|
/* create device object */
|
||||||
dev = kzalloc(sizeof(struct smsusb_device_t), GFP_KERNEL);
|
dev = kzalloc(sizeof(struct smsusb_device_t), GFP_KERNEL);
|
||||||
|
@ -412,6 +413,24 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
|
||||||
dev->udev = interface_to_usbdev(intf);
|
dev->udev = interface_to_usbdev(intf);
|
||||||
dev->state = SMSUSB_DISCONNECTED;
|
dev->state = SMSUSB_DISCONNECTED;
|
||||||
|
|
||||||
|
for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
|
||||||
|
struct usb_endpoint_descriptor *desc =
|
||||||
|
&intf->cur_altsetting->endpoint[i].desc;
|
||||||
|
|
||||||
|
if (desc->bEndpointAddress & USB_DIR_IN) {
|
||||||
|
dev->in_ep = desc->bEndpointAddress;
|
||||||
|
align = usb_endpoint_maxp(desc) - sizeof(struct sms_msg_hdr);
|
||||||
|
} else {
|
||||||
|
dev->out_ep = desc->bEndpointAddress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_debug("in_ep = %02x, out_ep = %02x\n", dev->in_ep, dev->out_ep);
|
||||||
|
if (!dev->in_ep || !dev->out_ep || align < 0) { /* Missing endpoints? */
|
||||||
|
smsusb_term_device(intf);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
params.device_type = sms_get_board(board_id)->type;
|
params.device_type = sms_get_board(board_id)->type;
|
||||||
|
|
||||||
switch (params.device_type) {
|
switch (params.device_type) {
|
||||||
|
@ -426,24 +445,12 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
|
||||||
/* fall-thru */
|
/* fall-thru */
|
||||||
default:
|
default:
|
||||||
dev->buffer_size = USB2_BUFFER_SIZE;
|
dev->buffer_size = USB2_BUFFER_SIZE;
|
||||||
dev->response_alignment =
|
dev->response_alignment = align;
|
||||||
le16_to_cpu(dev->udev->ep_in[1]->desc.wMaxPacketSize) -
|
|
||||||
sizeof(struct sms_msg_hdr);
|
|
||||||
|
|
||||||
params.flags |= SMS_DEVICE_FAMILY2;
|
params.flags |= SMS_DEVICE_FAMILY2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
|
|
||||||
if (intf->cur_altsetting->endpoint[i].desc. bEndpointAddress & USB_DIR_IN)
|
|
||||||
dev->in_ep = intf->cur_altsetting->endpoint[i].desc.bEndpointAddress;
|
|
||||||
else
|
|
||||||
dev->out_ep = intf->cur_altsetting->endpoint[i].desc.bEndpointAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_debug("in_ep = %02x, out_ep = %02x\n",
|
|
||||||
dev->in_ep, dev->out_ep);
|
|
||||||
|
|
||||||
params.device = &dev->udev->dev;
|
params.device = &dev->udev->dev;
|
||||||
params.usb_device = dev->udev;
|
params.usb_device = dev->udev;
|
||||||
params.buffer_size = dev->buffer_size;
|
params.buffer_size = dev->buffer_size;
|
||||||
|
|
|
@ -909,7 +909,7 @@ static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id,
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
extra_size = ALIGN(extra_size, sizeof(*entity->pads));
|
extra_size = roundup(extra_size, sizeof(*entity->pads));
|
||||||
num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1;
|
num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1;
|
||||||
size = sizeof(*entity) + extra_size + sizeof(*entity->pads) * num_pads
|
size = sizeof(*entity) + extra_size + sizeof(*entity->pads) * num_pads
|
||||||
+ num_inputs;
|
+ num_inputs;
|
||||||
|
|
|
@ -782,6 +782,8 @@ static int genwqe_pin_mem(struct genwqe_file *cfile, struct genwqe_mem *m)
|
||||||
|
|
||||||
if ((m->addr == 0x0) || (m->size == 0))
|
if ((m->addr == 0x0) || (m->size == 0))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
if (m->size > ULONG_MAX - PAGE_SIZE - (m->addr & ~PAGE_MASK))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
map_addr = (m->addr & PAGE_MASK);
|
map_addr = (m->addr & PAGE_MASK);
|
||||||
map_size = round_up(m->size + (m->addr & ~PAGE_MASK), PAGE_SIZE);
|
map_size = round_up(m->size + (m->addr & ~PAGE_MASK), PAGE_SIZE);
|
||||||
|
|
|
@ -587,6 +587,10 @@ int genwqe_user_vmap(struct genwqe_dev *cd, struct dma_mapping *m, void *uaddr,
|
||||||
/* determine space needed for page_list. */
|
/* determine space needed for page_list. */
|
||||||
data = (unsigned long)uaddr;
|
data = (unsigned long)uaddr;
|
||||||
offs = offset_in_page(data);
|
offs = offset_in_page(data);
|
||||||
|
if (size > ULONG_MAX - PAGE_SIZE - offs) {
|
||||||
|
m->size = 0; /* mark unused and not added */
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
m->nr_pages = DIV_ROUND_UP(offs + size, PAGE_SIZE);
|
m->nr_pages = DIV_ROUND_UP(offs + size, PAGE_SIZE);
|
||||||
|
|
||||||
m->page_list = kcalloc(m->nr_pages,
|
m->page_list = kcalloc(m->nr_pages,
|
||||||
|
|
|
@ -3121,13 +3121,18 @@ static int bond_slave_netdev_event(unsigned long event,
|
||||||
case NETDEV_CHANGE:
|
case NETDEV_CHANGE:
|
||||||
/* For 802.3ad mode only:
|
/* For 802.3ad mode only:
|
||||||
* Getting invalid Speed/Duplex values here will put slave
|
* Getting invalid Speed/Duplex values here will put slave
|
||||||
* in weird state. So mark it as link-fail for the time
|
* in weird state. Mark it as link-fail if the link was
|
||||||
* being and let link-monitoring (miimon) set it right when
|
* previously up or link-down if it hasn't yet come up, and
|
||||||
* correct speeds/duplex are available.
|
* let link-monitoring (miimon) set it right when correct
|
||||||
|
* speeds/duplex are available.
|
||||||
*/
|
*/
|
||||||
if (bond_update_speed_duplex(slave) &&
|
if (bond_update_speed_duplex(slave) &&
|
||||||
BOND_MODE(bond) == BOND_MODE_8023AD)
|
BOND_MODE(bond) == BOND_MODE_8023AD) {
|
||||||
slave->link = BOND_LINK_FAIL;
|
if (slave->last_link_up)
|
||||||
|
slave->link = BOND_LINK_FAIL;
|
||||||
|
else
|
||||||
|
slave->link = BOND_LINK_DOWN;
|
||||||
|
}
|
||||||
|
|
||||||
if (BOND_MODE(bond) == BOND_MODE_8023AD)
|
if (BOND_MODE(bond) == BOND_MODE_8023AD)
|
||||||
bond_3ad_adapter_speed_duplex_changed(slave);
|
bond_3ad_adapter_speed_duplex_changed(slave);
|
||||||
|
|
|
@ -784,7 +784,7 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,
|
||||||
err = mv88e6xxx_port_read(chip, port, s->reg + 1, ®);
|
err = mv88e6xxx_port_read(chip, port, s->reg + 1, ®);
|
||||||
if (err)
|
if (err)
|
||||||
return U64_MAX;
|
return U64_MAX;
|
||||||
high = reg;
|
low |= ((u32)reg) << 16;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case STATS_TYPE_BANK1:
|
case STATS_TYPE_BANK1:
|
||||||
|
|
|
@ -228,6 +228,9 @@ static void cxgb4_process_flow_match(struct net_device *dev,
|
||||||
fs->val.ivlan = vlan_tci;
|
fs->val.ivlan = vlan_tci;
|
||||||
fs->mask.ivlan = vlan_tci_mask;
|
fs->mask.ivlan = vlan_tci_mask;
|
||||||
|
|
||||||
|
fs->val.ivlan_vld = 1;
|
||||||
|
fs->mask.ivlan_vld = 1;
|
||||||
|
|
||||||
/* Chelsio adapters use ivlan_vld bit to match vlan packets
|
/* Chelsio adapters use ivlan_vld bit to match vlan packets
|
||||||
* as 802.1Q. Also, when vlan tag is present in packets,
|
* as 802.1Q. Also, when vlan tag is present in packets,
|
||||||
* ethtype match is used then to match on ethtype of inner
|
* ethtype match is used then to match on ethtype of inner
|
||||||
|
@ -238,8 +241,6 @@ static void cxgb4_process_flow_match(struct net_device *dev,
|
||||||
* ethtype value with ethtype of inner header.
|
* ethtype value with ethtype of inner header.
|
||||||
*/
|
*/
|
||||||
if (fs->val.ethtype == ETH_P_8021Q) {
|
if (fs->val.ethtype == ETH_P_8021Q) {
|
||||||
fs->val.ivlan_vld = 1;
|
|
||||||
fs->mask.ivlan_vld = 1;
|
|
||||||
fs->val.ethtype = 0;
|
fs->val.ethtype = 0;
|
||||||
fs->mask.ethtype = 0;
|
fs->mask.ethtype = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3571,7 +3571,7 @@ failed_init:
|
||||||
if (fep->reg_phy)
|
if (fep->reg_phy)
|
||||||
regulator_disable(fep->reg_phy);
|
regulator_disable(fep->reg_phy);
|
||||||
failed_reset:
|
failed_reset:
|
||||||
pm_runtime_put(&pdev->dev);
|
pm_runtime_put_noidle(&pdev->dev);
|
||||||
pm_runtime_disable(&pdev->dev);
|
pm_runtime_disable(&pdev->dev);
|
||||||
failed_regulator:
|
failed_regulator:
|
||||||
clk_disable_unprepare(fep->clk_ahb);
|
clk_disable_unprepare(fep->clk_ahb);
|
||||||
|
|
|
@ -4520,7 +4520,7 @@ static int mvneta_probe(struct platform_device *pdev)
|
||||||
err = register_netdev(dev);
|
err = register_netdev(dev);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
dev_err(&pdev->dev, "failed to register\n");
|
dev_err(&pdev->dev, "failed to register\n");
|
||||||
goto err_free_stats;
|
goto err_netdev;
|
||||||
}
|
}
|
||||||
|
|
||||||
netdev_info(dev, "Using %s mac address %pM\n", mac_from,
|
netdev_info(dev, "Using %s mac address %pM\n", mac_from,
|
||||||
|
@ -4531,13 +4531,11 @@ static int mvneta_probe(struct platform_device *pdev)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_netdev:
|
err_netdev:
|
||||||
unregister_netdev(dev);
|
|
||||||
if (pp->bm_priv) {
|
if (pp->bm_priv) {
|
||||||
mvneta_bm_pool_destroy(pp->bm_priv, pp->pool_long, 1 << pp->id);
|
mvneta_bm_pool_destroy(pp->bm_priv, pp->pool_long, 1 << pp->id);
|
||||||
mvneta_bm_pool_destroy(pp->bm_priv, pp->pool_short,
|
mvneta_bm_pool_destroy(pp->bm_priv, pp->pool_short,
|
||||||
1 << pp->id);
|
1 << pp->id);
|
||||||
}
|
}
|
||||||
err_free_stats:
|
|
||||||
free_percpu(pp->stats);
|
free_percpu(pp->stats);
|
||||||
err_free_ports:
|
err_free_ports:
|
||||||
free_percpu(pp->ports);
|
free_percpu(pp->ports);
|
||||||
|
|
|
@ -1310,8 +1310,8 @@ static void mvpp2_ethtool_get_strings(struct net_device *netdev, u32 sset,
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(mvpp2_ethtool_regs); i++)
|
for (i = 0; i < ARRAY_SIZE(mvpp2_ethtool_regs); i++)
|
||||||
memcpy(data + i * ETH_GSTRING_LEN,
|
strscpy(data + i * ETH_GSTRING_LEN,
|
||||||
&mvpp2_ethtool_regs[i].string, ETH_GSTRING_LEN);
|
mvpp2_ethtool_regs[i].string, ETH_GSTRING_LEN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1404,7 +1404,7 @@ static inline void mvpp2_xlg_max_rx_size_set(struct mvpp2_port *port)
|
||||||
/* Set defaults to the MVPP2 port */
|
/* Set defaults to the MVPP2 port */
|
||||||
static void mvpp2_defaults_set(struct mvpp2_port *port)
|
static void mvpp2_defaults_set(struct mvpp2_port *port)
|
||||||
{
|
{
|
||||||
int tx_port_num, val, queue, ptxq, lrxq;
|
int tx_port_num, val, queue, lrxq;
|
||||||
|
|
||||||
if (port->priv->hw_version == MVPP21) {
|
if (port->priv->hw_version == MVPP21) {
|
||||||
/* Update TX FIFO MIN Threshold */
|
/* Update TX FIFO MIN Threshold */
|
||||||
|
@ -1422,11 +1422,9 @@ static void mvpp2_defaults_set(struct mvpp2_port *port)
|
||||||
mvpp2_write(port->priv, MVPP2_TXP_SCHED_CMD_1_REG, 0);
|
mvpp2_write(port->priv, MVPP2_TXP_SCHED_CMD_1_REG, 0);
|
||||||
|
|
||||||
/* Close bandwidth for all queues */
|
/* Close bandwidth for all queues */
|
||||||
for (queue = 0; queue < MVPP2_MAX_TXQ; queue++) {
|
for (queue = 0; queue < MVPP2_MAX_TXQ; queue++)
|
||||||
ptxq = mvpp2_txq_phys(port->id, queue);
|
|
||||||
mvpp2_write(port->priv,
|
mvpp2_write(port->priv,
|
||||||
MVPP2_TXQ_SCHED_TOKEN_CNTR_REG(ptxq), 0);
|
MVPP2_TXQ_SCHED_TOKEN_CNTR_REG(queue), 0);
|
||||||
}
|
|
||||||
|
|
||||||
/* Set refill period to 1 usec, refill tokens
|
/* Set refill period to 1 usec, refill tokens
|
||||||
* and bucket size to maximum
|
* and bucket size to maximum
|
||||||
|
@ -2271,7 +2269,7 @@ static void mvpp2_txq_deinit(struct mvpp2_port *port,
|
||||||
txq->descs_dma = 0;
|
txq->descs_dma = 0;
|
||||||
|
|
||||||
/* Set minimum bandwidth for disabled TXQs */
|
/* Set minimum bandwidth for disabled TXQs */
|
||||||
mvpp2_write(port->priv, MVPP2_TXQ_SCHED_TOKEN_CNTR_REG(txq->id), 0);
|
mvpp2_write(port->priv, MVPP2_TXQ_SCHED_TOKEN_CNTR_REG(txq->log_id), 0);
|
||||||
|
|
||||||
/* Set Tx descriptors queue starting address and size */
|
/* Set Tx descriptors queue starting address and size */
|
||||||
cpu = get_cpu();
|
cpu = get_cpu();
|
||||||
|
|
|
@ -2010,6 +2010,8 @@ static int mlx4_en_set_tunable(struct net_device *dev,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define MLX4_EEPROM_PAGE_LEN 256
|
||||||
|
|
||||||
static int mlx4_en_get_module_info(struct net_device *dev,
|
static int mlx4_en_get_module_info(struct net_device *dev,
|
||||||
struct ethtool_modinfo *modinfo)
|
struct ethtool_modinfo *modinfo)
|
||||||
{
|
{
|
||||||
|
@ -2044,7 +2046,7 @@ static int mlx4_en_get_module_info(struct net_device *dev,
|
||||||
break;
|
break;
|
||||||
case MLX4_MODULE_ID_SFP:
|
case MLX4_MODULE_ID_SFP:
|
||||||
modinfo->type = ETH_MODULE_SFF_8472;
|
modinfo->type = ETH_MODULE_SFF_8472;
|
||||||
modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
|
modinfo->eeprom_len = MLX4_EEPROM_PAGE_LEN;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -2077,11 +2077,6 @@ int mlx4_get_module_info(struct mlx4_dev *dev, u8 port,
|
||||||
size -= offset + size - I2C_PAGE_SIZE;
|
size -= offset + size - I2C_PAGE_SIZE;
|
||||||
|
|
||||||
i2c_addr = I2C_ADDR_LOW;
|
i2c_addr = I2C_ADDR_LOW;
|
||||||
if (offset >= I2C_PAGE_SIZE) {
|
|
||||||
/* Reset offset to high page */
|
|
||||||
i2c_addr = I2C_ADDR_HIGH;
|
|
||||||
offset -= I2C_PAGE_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
cable_info = (struct mlx4_cable_info *)inmad->data;
|
cable_info = (struct mlx4_cable_info *)inmad->data;
|
||||||
cable_info->dev_mem_address = cpu_to_be16(offset);
|
cable_info->dev_mem_address = cpu_to_be16(offset);
|
||||||
|
|
|
@ -3696,6 +3696,12 @@ static netdev_features_t mlx5e_fix_features(struct net_device *netdev,
|
||||||
netdev_warn(netdev, "Disabling LRO, not supported in legacy RQ\n");
|
netdev_warn(netdev, "Disabling LRO, not supported in legacy RQ\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_CQE_COMPRESS)) {
|
||||||
|
features &= ~NETIF_F_RXHASH;
|
||||||
|
if (netdev->features & NETIF_F_RXHASH)
|
||||||
|
netdev_warn(netdev, "Disabling rxhash, not supported when CQE compress is active\n");
|
||||||
|
}
|
||||||
|
|
||||||
mutex_unlock(&priv->state_lock);
|
mutex_unlock(&priv->state_lock);
|
||||||
|
|
||||||
return features;
|
return features;
|
||||||
|
@ -3812,6 +3818,9 @@ int mlx5e_hwstamp_set(struct mlx5e_priv *priv, struct ifreq *ifr)
|
||||||
memcpy(&priv->tstamp, &config, sizeof(config));
|
memcpy(&priv->tstamp, &config, sizeof(config));
|
||||||
mutex_unlock(&priv->state_lock);
|
mutex_unlock(&priv->state_lock);
|
||||||
|
|
||||||
|
/* might need to fix some features */
|
||||||
|
netdev_update_features(priv->netdev);
|
||||||
|
|
||||||
return copy_to_user(ifr->ifr_data, &config,
|
return copy_to_user(ifr->ifr_data, &config,
|
||||||
sizeof(config)) ? -EFAULT : 0;
|
sizeof(config)) ? -EFAULT : 0;
|
||||||
}
|
}
|
||||||
|
@ -4596,6 +4605,10 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
|
||||||
if (!priv->channels.params.scatter_fcs_en)
|
if (!priv->channels.params.scatter_fcs_en)
|
||||||
netdev->features &= ~NETIF_F_RXFCS;
|
netdev->features &= ~NETIF_F_RXFCS;
|
||||||
|
|
||||||
|
/* prefere CQE compression over rxhash */
|
||||||
|
if (MLX5E_GET_PFLAG(&priv->channels.params, MLX5E_PFLAG_RX_CQE_COMPRESS))
|
||||||
|
netdev->features &= ~NETIF_F_RXHASH;
|
||||||
|
|
||||||
#define FT_CAP(f) MLX5_CAP_FLOWTABLE(mdev, flow_table_properties_nic_receive.f)
|
#define FT_CAP(f) MLX5_CAP_FLOWTABLE(mdev, flow_table_properties_nic_receive.f)
|
||||||
if (FT_CAP(flow_modify_en) &&
|
if (FT_CAP(flow_modify_en) &&
|
||||||
FT_CAP(modify_root) &&
|
FT_CAP(modify_root) &&
|
||||||
|
|
|
@ -2291,7 +2291,7 @@ static struct mlx5_flow_root_namespace
|
||||||
cmds = mlx5_fs_cmd_get_default_ipsec_fpga_cmds(table_type);
|
cmds = mlx5_fs_cmd_get_default_ipsec_fpga_cmds(table_type);
|
||||||
|
|
||||||
/* Create the root namespace */
|
/* Create the root namespace */
|
||||||
root_ns = kvzalloc(sizeof(*root_ns), GFP_KERNEL);
|
root_ns = kzalloc(sizeof(*root_ns), GFP_KERNEL);
|
||||||
if (!root_ns)
|
if (!root_ns)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -2434,6 +2434,7 @@ static void cleanup_egress_acls_root_ns(struct mlx5_core_dev *dev)
|
||||||
cleanup_root_ns(steering->esw_egress_root_ns[i]);
|
cleanup_root_ns(steering->esw_egress_root_ns[i]);
|
||||||
|
|
||||||
kfree(steering->esw_egress_root_ns);
|
kfree(steering->esw_egress_root_ns);
|
||||||
|
steering->esw_egress_root_ns = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cleanup_ingress_acls_root_ns(struct mlx5_core_dev *dev)
|
static void cleanup_ingress_acls_root_ns(struct mlx5_core_dev *dev)
|
||||||
|
@ -2448,6 +2449,7 @@ static void cleanup_ingress_acls_root_ns(struct mlx5_core_dev *dev)
|
||||||
cleanup_root_ns(steering->esw_ingress_root_ns[i]);
|
cleanup_root_ns(steering->esw_ingress_root_ns[i]);
|
||||||
|
|
||||||
kfree(steering->esw_ingress_root_ns);
|
kfree(steering->esw_ingress_root_ns);
|
||||||
|
steering->esw_ingress_root_ns = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mlx5_cleanup_fs(struct mlx5_core_dev *dev)
|
void mlx5_cleanup_fs(struct mlx5_core_dev *dev)
|
||||||
|
@ -2576,6 +2578,7 @@ cleanup_root_ns:
|
||||||
for (i--; i >= 0; i--)
|
for (i--; i >= 0; i--)
|
||||||
cleanup_root_ns(steering->esw_egress_root_ns[i]);
|
cleanup_root_ns(steering->esw_egress_root_ns[i]);
|
||||||
kfree(steering->esw_egress_root_ns);
|
kfree(steering->esw_egress_root_ns);
|
||||||
|
steering->esw_egress_root_ns = NULL;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2603,6 +2606,7 @@ cleanup_root_ns:
|
||||||
for (i--; i >= 0; i--)
|
for (i--; i >= 0; i--)
|
||||||
cleanup_root_ns(steering->esw_ingress_root_ns[i]);
|
cleanup_root_ns(steering->esw_ingress_root_ns[i]);
|
||||||
kfree(steering->esw_ingress_root_ns);
|
kfree(steering->esw_ingress_root_ns);
|
||||||
|
steering->esw_ingress_root_ns = NULL;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -157,7 +157,8 @@ int stmmac_mdio_reset(struct mii_bus *bus)
|
||||||
of_property_read_u32_array(np,
|
of_property_read_u32_array(np,
|
||||||
"snps,reset-delays-us", data->delays, 3);
|
"snps,reset-delays-us", data->delays, 3);
|
||||||
|
|
||||||
if (gpio_request(data->reset_gpio, "mdio-reset"))
|
if (devm_gpio_request(priv->device, data->reset_gpio,
|
||||||
|
"mdio-reset"))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,9 @@
|
||||||
#include <linux/phy.h>
|
#include <linux/phy.h>
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
MV_PMA_BOOT = 0xc050,
|
||||||
|
MV_PMA_BOOT_FATAL = BIT(0),
|
||||||
|
|
||||||
MV_PCS_BASE_T = 0x0000,
|
MV_PCS_BASE_T = 0x0000,
|
||||||
MV_PCS_BASE_R = 0x1000,
|
MV_PCS_BASE_R = 0x1000,
|
||||||
MV_PCS_1000BASEX = 0x2000,
|
MV_PCS_1000BASEX = 0x2000,
|
||||||
|
@ -226,6 +229,16 @@ static int mv3310_probe(struct phy_device *phydev)
|
||||||
(phydev->c45_ids.devices_in_package & mmd_mask) != mmd_mask)
|
(phydev->c45_ids.devices_in_package & mmd_mask) != mmd_mask)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
|
ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_BOOT);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (ret & MV_PMA_BOOT_FATAL) {
|
||||||
|
dev_warn(&phydev->mdio.dev,
|
||||||
|
"PHY failed to boot firmware, status=%04x\n", ret);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
|
priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
|
||||||
if (!priv)
|
if (!priv)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
|
@ -211,6 +211,7 @@ static int sfp_i2c_read(struct sfp *sfp, bool a2, u8 dev_addr, void *buf,
|
||||||
{
|
{
|
||||||
struct i2c_msg msgs[2];
|
struct i2c_msg msgs[2];
|
||||||
u8 bus_addr = a2 ? 0x51 : 0x50;
|
u8 bus_addr = a2 ? 0x51 : 0x50;
|
||||||
|
size_t this_len;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
msgs[0].addr = bus_addr;
|
msgs[0].addr = bus_addr;
|
||||||
|
@ -222,11 +223,26 @@ static int sfp_i2c_read(struct sfp *sfp, bool a2, u8 dev_addr, void *buf,
|
||||||
msgs[1].len = len;
|
msgs[1].len = len;
|
||||||
msgs[1].buf = buf;
|
msgs[1].buf = buf;
|
||||||
|
|
||||||
ret = i2c_transfer(sfp->i2c, msgs, ARRAY_SIZE(msgs));
|
while (len) {
|
||||||
if (ret < 0)
|
this_len = len;
|
||||||
return ret;
|
if (this_len > 16)
|
||||||
|
this_len = 16;
|
||||||
|
|
||||||
return ret == ARRAY_SIZE(msgs) ? len : 0;
|
msgs[1].len = this_len;
|
||||||
|
|
||||||
|
ret = i2c_transfer(sfp->i2c, msgs, ARRAY_SIZE(msgs));
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (ret != ARRAY_SIZE(msgs))
|
||||||
|
break;
|
||||||
|
|
||||||
|
msgs[1].buf += this_len;
|
||||||
|
dev_addr += this_len;
|
||||||
|
len -= this_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return msgs[1].buf - (u8 *)buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sfp_i2c_write(struct sfp *sfp, bool a2, u8 dev_addr, void *buf,
|
static int sfp_i2c_write(struct sfp *sfp, bool a2, u8 dev_addr, void *buf,
|
||||||
|
|
|
@ -506,6 +506,7 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
|
||||||
|
|
||||||
if (netif_running (dev->net) &&
|
if (netif_running (dev->net) &&
|
||||||
netif_device_present (dev->net) &&
|
netif_device_present (dev->net) &&
|
||||||
|
test_bit(EVENT_DEV_OPEN, &dev->flags) &&
|
||||||
!test_bit (EVENT_RX_HALT, &dev->flags) &&
|
!test_bit (EVENT_RX_HALT, &dev->flags) &&
|
||||||
!test_bit (EVENT_DEV_ASLEEP, &dev->flags)) {
|
!test_bit (EVENT_DEV_ASLEEP, &dev->flags)) {
|
||||||
switch (retval = usb_submit_urb (urb, GFP_ATOMIC)) {
|
switch (retval = usb_submit_urb (urb, GFP_ATOMIC)) {
|
||||||
|
@ -1431,6 +1432,11 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
|
||||||
spin_unlock_irqrestore(&dev->txq.lock, flags);
|
spin_unlock_irqrestore(&dev->txq.lock, flags);
|
||||||
goto drop;
|
goto drop;
|
||||||
}
|
}
|
||||||
|
if (netif_queue_stopped(net)) {
|
||||||
|
usb_autopm_put_interface_async(dev->intf);
|
||||||
|
spin_unlock_irqrestore(&dev->txq.lock, flags);
|
||||||
|
goto drop;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
/* if this triggers the device is still a sleep */
|
/* if this triggers the device is still a sleep */
|
||||||
|
|
|
@ -490,11 +490,18 @@ fail:
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr)
|
void brcmf_proto_bcdc_detach_pre_delif(struct brcmf_pub *drvr)
|
||||||
|
{
|
||||||
|
struct brcmf_bcdc *bcdc = drvr->proto->pd;
|
||||||
|
|
||||||
|
brcmf_fws_detach_pre_delif(bcdc->fws);
|
||||||
|
}
|
||||||
|
|
||||||
|
void brcmf_proto_bcdc_detach_post_delif(struct brcmf_pub *drvr)
|
||||||
{
|
{
|
||||||
struct brcmf_bcdc *bcdc = drvr->proto->pd;
|
struct brcmf_bcdc *bcdc = drvr->proto->pd;
|
||||||
|
|
||||||
drvr->proto->pd = NULL;
|
drvr->proto->pd = NULL;
|
||||||
brcmf_fws_detach(bcdc->fws);
|
brcmf_fws_detach_post_delif(bcdc->fws);
|
||||||
kfree(bcdc);
|
kfree(bcdc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,14 +18,16 @@
|
||||||
|
|
||||||
#ifdef CONFIG_BRCMFMAC_PROTO_BCDC
|
#ifdef CONFIG_BRCMFMAC_PROTO_BCDC
|
||||||
int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr);
|
int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr);
|
||||||
void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr);
|
void brcmf_proto_bcdc_detach_pre_delif(struct brcmf_pub *drvr);
|
||||||
|
void brcmf_proto_bcdc_detach_post_delif(struct brcmf_pub *drvr);
|
||||||
void brcmf_proto_bcdc_txflowblock(struct device *dev, bool state);
|
void brcmf_proto_bcdc_txflowblock(struct device *dev, bool state);
|
||||||
void brcmf_proto_bcdc_txcomplete(struct device *dev, struct sk_buff *txp,
|
void brcmf_proto_bcdc_txcomplete(struct device *dev, struct sk_buff *txp,
|
||||||
bool success);
|
bool success);
|
||||||
struct brcmf_fws_info *drvr_to_fws(struct brcmf_pub *drvr);
|
struct brcmf_fws_info *drvr_to_fws(struct brcmf_pub *drvr);
|
||||||
#else
|
#else
|
||||||
static inline int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) { return 0; }
|
static inline int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) { return 0; }
|
||||||
static inline void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr) {}
|
static void brcmf_proto_bcdc_detach_pre_delif(struct brcmf_pub *drvr) {};
|
||||||
|
static inline void brcmf_proto_bcdc_detach_post_delif(struct brcmf_pub *drvr) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* BRCMFMAC_BCDC_H */
|
#endif /* BRCMFMAC_BCDC_H */
|
||||||
|
|
|
@ -1219,6 +1219,8 @@ void brcmf_detach(struct device *dev)
|
||||||
|
|
||||||
brcmf_bus_change_state(bus_if, BRCMF_BUS_DOWN);
|
brcmf_bus_change_state(bus_if, BRCMF_BUS_DOWN);
|
||||||
|
|
||||||
|
brcmf_proto_detach_pre_delif(drvr);
|
||||||
|
|
||||||
/* make sure primary interface removed last */
|
/* make sure primary interface removed last */
|
||||||
for (i = BRCMF_MAX_IFS-1; i > -1; i--)
|
for (i = BRCMF_MAX_IFS-1; i > -1; i--)
|
||||||
brcmf_remove_interface(drvr->iflist[i], false);
|
brcmf_remove_interface(drvr->iflist[i], false);
|
||||||
|
@ -1228,7 +1230,7 @@ void brcmf_detach(struct device *dev)
|
||||||
|
|
||||||
brcmf_bus_stop(drvr->bus_if);
|
brcmf_bus_stop(drvr->bus_if);
|
||||||
|
|
||||||
brcmf_proto_detach(drvr);
|
brcmf_proto_detach_post_delif(drvr);
|
||||||
|
|
||||||
bus_if->drvr = NULL;
|
bus_if->drvr = NULL;
|
||||||
wiphy_free(drvr->wiphy);
|
wiphy_free(drvr->wiphy);
|
||||||
|
|
|
@ -2410,17 +2410,25 @@ struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr)
|
||||||
return fws;
|
return fws;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
brcmf_fws_detach(fws);
|
brcmf_fws_detach_pre_delif(fws);
|
||||||
|
brcmf_fws_detach_post_delif(fws);
|
||||||
return ERR_PTR(rc);
|
return ERR_PTR(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void brcmf_fws_detach(struct brcmf_fws_info *fws)
|
void brcmf_fws_detach_pre_delif(struct brcmf_fws_info *fws)
|
||||||
{
|
{
|
||||||
if (!fws)
|
if (!fws)
|
||||||
return;
|
return;
|
||||||
|
if (fws->fws_wq) {
|
||||||
if (fws->fws_wq)
|
|
||||||
destroy_workqueue(fws->fws_wq);
|
destroy_workqueue(fws->fws_wq);
|
||||||
|
fws->fws_wq = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void brcmf_fws_detach_post_delif(struct brcmf_fws_info *fws)
|
||||||
|
{
|
||||||
|
if (!fws)
|
||||||
|
return;
|
||||||
|
|
||||||
/* cleanup */
|
/* cleanup */
|
||||||
brcmf_fws_lock(fws);
|
brcmf_fws_lock(fws);
|
||||||
|
|
|
@ -19,7 +19,8 @@
|
||||||
#define FWSIGNAL_H_
|
#define FWSIGNAL_H_
|
||||||
|
|
||||||
struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr);
|
struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr);
|
||||||
void brcmf_fws_detach(struct brcmf_fws_info *fws);
|
void brcmf_fws_detach_pre_delif(struct brcmf_fws_info *fws);
|
||||||
|
void brcmf_fws_detach_post_delif(struct brcmf_fws_info *fws);
|
||||||
void brcmf_fws_debugfs_create(struct brcmf_pub *drvr);
|
void brcmf_fws_debugfs_create(struct brcmf_pub *drvr);
|
||||||
bool brcmf_fws_queue_skbs(struct brcmf_fws_info *fws);
|
bool brcmf_fws_queue_skbs(struct brcmf_fws_info *fws);
|
||||||
bool brcmf_fws_fc_active(struct brcmf_fws_info *fws);
|
bool brcmf_fws_fc_active(struct brcmf_fws_info *fws);
|
||||||
|
|
|
@ -67,16 +67,22 @@ fail:
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
void brcmf_proto_detach(struct brcmf_pub *drvr)
|
void brcmf_proto_detach_post_delif(struct brcmf_pub *drvr)
|
||||||
{
|
{
|
||||||
brcmf_dbg(TRACE, "Enter\n");
|
brcmf_dbg(TRACE, "Enter\n");
|
||||||
|
|
||||||
if (drvr->proto) {
|
if (drvr->proto) {
|
||||||
if (drvr->bus_if->proto_type == BRCMF_PROTO_BCDC)
|
if (drvr->bus_if->proto_type == BRCMF_PROTO_BCDC)
|
||||||
brcmf_proto_bcdc_detach(drvr);
|
brcmf_proto_bcdc_detach_post_delif(drvr);
|
||||||
else if (drvr->bus_if->proto_type == BRCMF_PROTO_MSGBUF)
|
else if (drvr->bus_if->proto_type == BRCMF_PROTO_MSGBUF)
|
||||||
brcmf_proto_msgbuf_detach(drvr);
|
brcmf_proto_msgbuf_detach(drvr);
|
||||||
kfree(drvr->proto);
|
kfree(drvr->proto);
|
||||||
drvr->proto = NULL;
|
drvr->proto = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void brcmf_proto_detach_pre_delif(struct brcmf_pub *drvr)
|
||||||
|
{
|
||||||
|
if (drvr->proto && drvr->bus_if->proto_type == BRCMF_PROTO_BCDC)
|
||||||
|
brcmf_proto_bcdc_detach_pre_delif(drvr);
|
||||||
|
}
|
||||||
|
|
|
@ -54,7 +54,8 @@ struct brcmf_proto {
|
||||||
|
|
||||||
|
|
||||||
int brcmf_proto_attach(struct brcmf_pub *drvr);
|
int brcmf_proto_attach(struct brcmf_pub *drvr);
|
||||||
void brcmf_proto_detach(struct brcmf_pub *drvr);
|
void brcmf_proto_detach_pre_delif(struct brcmf_pub *drvr);
|
||||||
|
void brcmf_proto_detach_post_delif(struct brcmf_pub *drvr);
|
||||||
|
|
||||||
static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws,
|
static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws,
|
||||||
struct sk_buff *skb,
|
struct sk_buff *skb,
|
||||||
|
|
|
@ -205,15 +205,24 @@ static void __of_attach_node(struct device_node *np)
|
||||||
const __be32 *phandle;
|
const __be32 *phandle;
|
||||||
int sz;
|
int sz;
|
||||||
|
|
||||||
np->name = __of_get_property(np, "name", NULL) ? : "<NULL>";
|
if (!of_node_check_flag(np, OF_OVERLAY)) {
|
||||||
np->type = __of_get_property(np, "device_type", NULL) ? : "<NULL>";
|
np->name = __of_get_property(np, "name", NULL);
|
||||||
|
np->type = __of_get_property(np, "device_type", NULL);
|
||||||
|
if (!np->name)
|
||||||
|
np->name = "<NULL>";
|
||||||
|
if (!np->type)
|
||||||
|
np->type = "<NULL>";
|
||||||
|
|
||||||
phandle = __of_get_property(np, "phandle", &sz);
|
phandle = __of_get_property(np, "phandle", &sz);
|
||||||
if (!phandle)
|
if (!phandle)
|
||||||
phandle = __of_get_property(np, "linux,phandle", &sz);
|
phandle = __of_get_property(np, "linux,phandle", &sz);
|
||||||
if (IS_ENABLED(CONFIG_PPC_PSERIES) && !phandle)
|
if (IS_ENABLED(CONFIG_PPC_PSERIES) && !phandle)
|
||||||
phandle = __of_get_property(np, "ibm,phandle", &sz);
|
phandle = __of_get_property(np, "ibm,phandle", &sz);
|
||||||
np->phandle = (phandle && (sz >= 4)) ? be32_to_cpup(phandle) : 0;
|
if (phandle && (sz >= 4))
|
||||||
|
np->phandle = be32_to_cpup(phandle);
|
||||||
|
else
|
||||||
|
np->phandle = 0;
|
||||||
|
}
|
||||||
|
|
||||||
np->child = NULL;
|
np->child = NULL;
|
||||||
np->sibling = np->parent->child;
|
np->sibling = np->parent->child;
|
||||||
|
|
|
@ -287,7 +287,12 @@ err_free_target_path:
|
||||||
* @target may be either in the live devicetree or in a new subtree that
|
* @target may be either in the live devicetree or in a new subtree that
|
||||||
* is contained in the changeset.
|
* is contained in the changeset.
|
||||||
*
|
*
|
||||||
* Some special properties are not updated (no error returned).
|
* Some special properties are not added or updated (no error returned):
|
||||||
|
* "name", "phandle", "linux,phandle".
|
||||||
|
*
|
||||||
|
* Properties "#address-cells" and "#size-cells" are not updated if they
|
||||||
|
* are already in the live tree, but if present in the live tree, the values
|
||||||
|
* in the overlay must match the values in the live tree.
|
||||||
*
|
*
|
||||||
* Update of property in symbols node is not allowed.
|
* Update of property in symbols node is not allowed.
|
||||||
*
|
*
|
||||||
|
@ -300,11 +305,13 @@ static int add_changeset_property(struct overlay_changeset *ovcs,
|
||||||
{
|
{
|
||||||
struct property *new_prop = NULL, *prop;
|
struct property *new_prop = NULL, *prop;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
bool check_for_non_overlay_node = false;
|
||||||
|
|
||||||
if (!of_prop_cmp(overlay_prop->name, "name") ||
|
if (target->in_livetree)
|
||||||
!of_prop_cmp(overlay_prop->name, "phandle") ||
|
if (!of_prop_cmp(overlay_prop->name, "name") ||
|
||||||
!of_prop_cmp(overlay_prop->name, "linux,phandle"))
|
!of_prop_cmp(overlay_prop->name, "phandle") ||
|
||||||
return 0;
|
!of_prop_cmp(overlay_prop->name, "linux,phandle"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (target->in_livetree)
|
if (target->in_livetree)
|
||||||
prop = of_find_property(target->np, overlay_prop->name, NULL);
|
prop = of_find_property(target->np, overlay_prop->name, NULL);
|
||||||
|
@ -322,12 +329,36 @@ static int add_changeset_property(struct overlay_changeset *ovcs,
|
||||||
if (!new_prop)
|
if (!new_prop)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (!prop)
|
if (!prop) {
|
||||||
|
check_for_non_overlay_node = true;
|
||||||
|
if (!target->in_livetree) {
|
||||||
|
new_prop->next = target->np->deadprops;
|
||||||
|
target->np->deadprops = new_prop;
|
||||||
|
}
|
||||||
ret = of_changeset_add_property(&ovcs->cset, target->np,
|
ret = of_changeset_add_property(&ovcs->cset, target->np,
|
||||||
new_prop);
|
new_prop);
|
||||||
else
|
} else if (!of_prop_cmp(prop->name, "#address-cells")) {
|
||||||
|
if (!of_prop_val_eq(prop, new_prop)) {
|
||||||
|
pr_err("ERROR: changing value of #address-cells is not allowed in %pOF\n",
|
||||||
|
target->np);
|
||||||
|
ret = -EINVAL;
|
||||||
|
}
|
||||||
|
} else if (!of_prop_cmp(prop->name, "#size-cells")) {
|
||||||
|
if (!of_prop_val_eq(prop, new_prop)) {
|
||||||
|
pr_err("ERROR: changing value of #size-cells is not allowed in %pOF\n",
|
||||||
|
target->np);
|
||||||
|
ret = -EINVAL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
check_for_non_overlay_node = true;
|
||||||
ret = of_changeset_update_property(&ovcs->cset, target->np,
|
ret = of_changeset_update_property(&ovcs->cset, target->np,
|
||||||
new_prop);
|
new_prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_for_non_overlay_node &&
|
||||||
|
!of_node_check_flag(target->np, OF_OVERLAY))
|
||||||
|
pr_err("WARNING: memory leak will occur if overlay removed, property: %pOF/%s\n",
|
||||||
|
target->np, new_prop->name);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
kfree(new_prop->name);
|
kfree(new_prop->name);
|
||||||
|
@ -382,9 +413,10 @@ static int add_changeset_node(struct overlay_changeset *ovcs,
|
||||||
struct target *target, struct device_node *node)
|
struct target *target, struct device_node *node)
|
||||||
{
|
{
|
||||||
const char *node_kbasename;
|
const char *node_kbasename;
|
||||||
|
const __be32 *phandle;
|
||||||
struct device_node *tchild;
|
struct device_node *tchild;
|
||||||
struct target target_child;
|
struct target target_child;
|
||||||
int ret = 0;
|
int ret = 0, size;
|
||||||
|
|
||||||
node_kbasename = kbasename(node->full_name);
|
node_kbasename = kbasename(node->full_name);
|
||||||
|
|
||||||
|
@ -398,6 +430,19 @@ static int add_changeset_node(struct overlay_changeset *ovcs,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
tchild->parent = target->np;
|
tchild->parent = target->np;
|
||||||
|
tchild->name = __of_get_property(node, "name", NULL);
|
||||||
|
tchild->type = __of_get_property(node, "device_type", NULL);
|
||||||
|
|
||||||
|
if (!tchild->name)
|
||||||
|
tchild->name = "<NULL>";
|
||||||
|
if (!tchild->type)
|
||||||
|
tchild->type = "<NULL>";
|
||||||
|
|
||||||
|
/* ignore obsolete "linux,phandle" */
|
||||||
|
phandle = __of_get_property(node, "phandle", &size);
|
||||||
|
if (phandle && (size == 4))
|
||||||
|
tchild->phandle = be32_to_cpup(phandle);
|
||||||
|
|
||||||
of_node_set_flag(tchild, OF_OVERLAY);
|
of_node_set_flag(tchild, OF_OVERLAY);
|
||||||
|
|
||||||
ret = of_changeset_attach_node(&ovcs->cset, tchild);
|
ret = of_changeset_attach_node(&ovcs->cset, tchild);
|
||||||
|
|
|
@ -565,8 +565,6 @@ ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba,
|
||||||
/* We currently only support kernel addresses */
|
/* We currently only support kernel addresses */
|
||||||
BUG_ON(sid != KERNEL_SPACE);
|
BUG_ON(sid != KERNEL_SPACE);
|
||||||
|
|
||||||
mtsp(sid,1);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** WORD 1 - low order word
|
** WORD 1 - low order word
|
||||||
** "hints" parm includes the VALID bit!
|
** "hints" parm includes the VALID bit!
|
||||||
|
@ -597,7 +595,7 @@ ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba,
|
||||||
** Grab virtual index [0:11]
|
** Grab virtual index [0:11]
|
||||||
** Deposit virt_idx bits into I/O PDIR word
|
** Deposit virt_idx bits into I/O PDIR word
|
||||||
*/
|
*/
|
||||||
asm volatile ("lci %%r0(%%sr1, %1), %0" : "=r" (ci) : "r" (vba));
|
asm volatile ("lci %%r0(%1), %0" : "=r" (ci) : "r" (vba));
|
||||||
asm volatile ("extru %1,19,12,%0" : "+r" (ci) : "r" (ci));
|
asm volatile ("extru %1,19,12,%0" : "+r" (ci) : "r" (ci));
|
||||||
asm volatile ("depw %1,15,12,%0" : "+r" (pa) : "r" (ci));
|
asm volatile ("depw %1,15,12,%0" : "+r" (pa) : "r" (ci));
|
||||||
|
|
||||||
|
|
|
@ -575,8 +575,7 @@ sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba,
|
||||||
pa = virt_to_phys(vba);
|
pa = virt_to_phys(vba);
|
||||||
pa &= IOVP_MASK;
|
pa &= IOVP_MASK;
|
||||||
|
|
||||||
mtsp(sid,1);
|
asm("lci 0(%1), %0" : "=r" (ci) : "r" (vba));
|
||||||
asm("lci 0(%%sr1, %1), %0" : "=r" (ci) : "r" (vba));
|
|
||||||
pa |= (ci >> PAGE_SHIFT) & 0xff; /* move CI (8 bits) into lowest byte */
|
pa |= (ci >> PAGE_SHIFT) & 0xff; /* move CI (8 bits) into lowest byte */
|
||||||
|
|
||||||
pa |= SBA_PDIR_VALID_BIT; /* set "valid" bit */
|
pa |= SBA_PDIR_VALID_BIT; /* set "valid" bit */
|
||||||
|
|
|
@ -164,6 +164,7 @@ extern const struct attribute_group *zfcp_port_attr_groups[];
|
||||||
extern struct mutex zfcp_sysfs_port_units_mutex;
|
extern struct mutex zfcp_sysfs_port_units_mutex;
|
||||||
extern struct device_attribute *zfcp_sysfs_sdev_attrs[];
|
extern struct device_attribute *zfcp_sysfs_sdev_attrs[];
|
||||||
extern struct device_attribute *zfcp_sysfs_shost_attrs[];
|
extern struct device_attribute *zfcp_sysfs_shost_attrs[];
|
||||||
|
bool zfcp_sysfs_port_is_removing(const struct zfcp_port *const port);
|
||||||
|
|
||||||
/* zfcp_unit.c */
|
/* zfcp_unit.c */
|
||||||
extern int zfcp_unit_add(struct zfcp_port *, u64);
|
extern int zfcp_unit_add(struct zfcp_port *, u64);
|
||||||
|
|
|
@ -125,6 +125,15 @@ static int zfcp_scsi_slave_alloc(struct scsi_device *sdev)
|
||||||
|
|
||||||
zfcp_sdev->erp_action.port = port;
|
zfcp_sdev->erp_action.port = port;
|
||||||
|
|
||||||
|
mutex_lock(&zfcp_sysfs_port_units_mutex);
|
||||||
|
if (zfcp_sysfs_port_is_removing(port)) {
|
||||||
|
/* port is already gone */
|
||||||
|
mutex_unlock(&zfcp_sysfs_port_units_mutex);
|
||||||
|
put_device(&port->dev); /* undo zfcp_get_port_by_wwpn() */
|
||||||
|
return -ENXIO;
|
||||||
|
}
|
||||||
|
mutex_unlock(&zfcp_sysfs_port_units_mutex);
|
||||||
|
|
||||||
unit = zfcp_unit_find(port, zfcp_scsi_dev_lun(sdev));
|
unit = zfcp_unit_find(port, zfcp_scsi_dev_lun(sdev));
|
||||||
if (unit)
|
if (unit)
|
||||||
put_device(&unit->dev);
|
put_device(&unit->dev);
|
||||||
|
|
|
@ -235,6 +235,53 @@ static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL,
|
||||||
|
|
||||||
DEFINE_MUTEX(zfcp_sysfs_port_units_mutex);
|
DEFINE_MUTEX(zfcp_sysfs_port_units_mutex);
|
||||||
|
|
||||||
|
static void zfcp_sysfs_port_set_removing(struct zfcp_port *const port)
|
||||||
|
{
|
||||||
|
lockdep_assert_held(&zfcp_sysfs_port_units_mutex);
|
||||||
|
atomic_set(&port->units, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool zfcp_sysfs_port_is_removing(const struct zfcp_port *const port)
|
||||||
|
{
|
||||||
|
lockdep_assert_held(&zfcp_sysfs_port_units_mutex);
|
||||||
|
return atomic_read(&port->units) == -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool zfcp_sysfs_port_in_use(struct zfcp_port *const port)
|
||||||
|
{
|
||||||
|
struct zfcp_adapter *const adapter = port->adapter;
|
||||||
|
unsigned long flags;
|
||||||
|
struct scsi_device *sdev;
|
||||||
|
bool in_use = true;
|
||||||
|
|
||||||
|
mutex_lock(&zfcp_sysfs_port_units_mutex);
|
||||||
|
if (atomic_read(&port->units) > 0)
|
||||||
|
goto unlock_port_units_mutex; /* zfcp_unit(s) under port */
|
||||||
|
|
||||||
|
spin_lock_irqsave(adapter->scsi_host->host_lock, flags);
|
||||||
|
__shost_for_each_device(sdev, adapter->scsi_host) {
|
||||||
|
const struct zfcp_scsi_dev *zsdev = sdev_to_zfcp(sdev);
|
||||||
|
|
||||||
|
if (sdev->sdev_state == SDEV_DEL ||
|
||||||
|
sdev->sdev_state == SDEV_CANCEL)
|
||||||
|
continue;
|
||||||
|
if (zsdev->port != port)
|
||||||
|
continue;
|
||||||
|
/* alive scsi_device under port of interest */
|
||||||
|
goto unlock_host_lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* port is about to be removed, so no more unit_add or slave_alloc */
|
||||||
|
zfcp_sysfs_port_set_removing(port);
|
||||||
|
in_use = false;
|
||||||
|
|
||||||
|
unlock_host_lock:
|
||||||
|
spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags);
|
||||||
|
unlock_port_units_mutex:
|
||||||
|
mutex_unlock(&zfcp_sysfs_port_units_mutex);
|
||||||
|
return in_use;
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
|
static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
|
||||||
struct device_attribute *attr,
|
struct device_attribute *attr,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
|
@ -257,15 +304,11 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
|
||||||
else
|
else
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
||||||
mutex_lock(&zfcp_sysfs_port_units_mutex);
|
if (zfcp_sysfs_port_in_use(port)) {
|
||||||
if (atomic_read(&port->units) > 0) {
|
|
||||||
retval = -EBUSY;
|
retval = -EBUSY;
|
||||||
mutex_unlock(&zfcp_sysfs_port_units_mutex);
|
put_device(&port->dev); /* undo zfcp_get_port_by_wwpn() */
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
/* port is about to be removed, so no more unit_add */
|
|
||||||
atomic_set(&port->units, -1);
|
|
||||||
mutex_unlock(&zfcp_sysfs_port_units_mutex);
|
|
||||||
|
|
||||||
write_lock_irq(&adapter->port_list_lock);
|
write_lock_irq(&adapter->port_list_lock);
|
||||||
list_del(&port->list);
|
list_del(&port->list);
|
||||||
|
|
|
@ -124,7 +124,7 @@ int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun)
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
mutex_lock(&zfcp_sysfs_port_units_mutex);
|
mutex_lock(&zfcp_sysfs_port_units_mutex);
|
||||||
if (atomic_read(&port->units) == -1) {
|
if (zfcp_sysfs_port_is_removing(port)) {
|
||||||
/* port is already gone */
|
/* port is already gone */
|
||||||
retval = -ENODEV;
|
retval = -ENODEV;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -168,8 +168,14 @@ int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun)
|
||||||
write_lock_irq(&port->unit_list_lock);
|
write_lock_irq(&port->unit_list_lock);
|
||||||
list_add_tail(&unit->list, &port->unit_list);
|
list_add_tail(&unit->list, &port->unit_list);
|
||||||
write_unlock_irq(&port->unit_list_lock);
|
write_unlock_irq(&port->unit_list_lock);
|
||||||
|
/*
|
||||||
|
* lock order: shost->scan_mutex before zfcp_sysfs_port_units_mutex
|
||||||
|
* due to zfcp_unit_scsi_scan() => zfcp_scsi_slave_alloc()
|
||||||
|
*/
|
||||||
|
mutex_unlock(&zfcp_sysfs_port_units_mutex);
|
||||||
|
|
||||||
zfcp_unit_scsi_scan(unit);
|
zfcp_unit_scsi_scan(unit);
|
||||||
|
return retval;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&zfcp_sysfs_port_units_mutex);
|
mutex_unlock(&zfcp_sysfs_port_units_mutex);
|
||||||
|
|
|
@ -3119,7 +3119,9 @@ static void hfa384x_usbin_callback(struct urb *urb)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Save values from the RX URB before reposting overwrites it. */
|
||||||
urb_status = urb->status;
|
urb_status = urb->status;
|
||||||
|
usbin = (union hfa384x_usbin *)urb->transfer_buffer;
|
||||||
|
|
||||||
if (action != ABORT) {
|
if (action != ABORT) {
|
||||||
/* Repost the RX URB */
|
/* Repost the RX URB */
|
||||||
|
@ -3136,7 +3138,6 @@ static void hfa384x_usbin_callback(struct urb *urb)
|
||||||
/* Note: the check of the sw_support field, the type field doesn't
|
/* Note: the check of the sw_support field, the type field doesn't
|
||||||
* have bit 12 set like the docs suggest.
|
* have bit 12 set like the docs suggest.
|
||||||
*/
|
*/
|
||||||
usbin = (union hfa384x_usbin *)urb->transfer_buffer;
|
|
||||||
type = le16_to_cpu(usbin->type);
|
type = le16_to_cpu(usbin->type);
|
||||||
if (HFA384x_USB_ISRXFRM(type)) {
|
if (HFA384x_USB_ISRXFRM(type)) {
|
||||||
if (action == HANDLE) {
|
if (action == HANDLE) {
|
||||||
|
|
|
@ -576,7 +576,7 @@ static int max310x_set_ref_clk(struct max310x_port *s, unsigned long freq,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Configure clock source */
|
/* Configure clock source */
|
||||||
clksrc = xtal ? MAX310X_CLKSRC_CRYST_BIT : MAX310X_CLKSRC_EXTCLK_BIT;
|
clksrc = MAX310X_CLKSRC_EXTCLK_BIT | (xtal ? MAX310X_CLKSRC_CRYST_BIT : 0);
|
||||||
|
|
||||||
/* Configure PLL */
|
/* Configure PLL */
|
||||||
if (pllcfg) {
|
if (pllcfg) {
|
||||||
|
|
|
@ -860,6 +860,7 @@ static void msm_handle_tx(struct uart_port *port)
|
||||||
struct circ_buf *xmit = &msm_port->uart.state->xmit;
|
struct circ_buf *xmit = &msm_port->uart.state->xmit;
|
||||||
struct msm_dma *dma = &msm_port->tx_dma;
|
struct msm_dma *dma = &msm_port->tx_dma;
|
||||||
unsigned int pio_count, dma_count, dma_min;
|
unsigned int pio_count, dma_count, dma_min;
|
||||||
|
char buf[4] = { 0 };
|
||||||
void __iomem *tf;
|
void __iomem *tf;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
|
@ -869,10 +870,12 @@ static void msm_handle_tx(struct uart_port *port)
|
||||||
else
|
else
|
||||||
tf = port->membase + UART_TF;
|
tf = port->membase + UART_TF;
|
||||||
|
|
||||||
|
buf[0] = port->x_char;
|
||||||
|
|
||||||
if (msm_port->is_uartdm)
|
if (msm_port->is_uartdm)
|
||||||
msm_reset_dm_count(port, 1);
|
msm_reset_dm_count(port, 1);
|
||||||
|
|
||||||
iowrite8_rep(tf, &port->x_char, 1);
|
iowrite32_rep(tf, buf, 1);
|
||||||
port->icount.tx++;
|
port->icount.tx++;
|
||||||
port->x_char = 0;
|
port->x_char = 0;
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -130,9 +130,6 @@ static void uart_start(struct tty_struct *tty)
|
||||||
struct uart_port *port;
|
struct uart_port *port;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (!state)
|
|
||||||
return;
|
|
||||||
|
|
||||||
port = uart_port_lock(state, flags);
|
port = uart_port_lock(state, flags);
|
||||||
__uart_start(tty);
|
__uart_start(tty);
|
||||||
uart_port_unlock(port, flags);
|
uart_port_unlock(port, flags);
|
||||||
|
@ -726,9 +723,6 @@ static void uart_unthrottle(struct tty_struct *tty)
|
||||||
upstat_t mask = UPSTAT_SYNC_FIFO;
|
upstat_t mask = UPSTAT_SYNC_FIFO;
|
||||||
struct uart_port *port;
|
struct uart_port *port;
|
||||||
|
|
||||||
if (!state)
|
|
||||||
return;
|
|
||||||
|
|
||||||
port = uart_port_ref(state);
|
port = uart_port_ref(state);
|
||||||
if (!port)
|
if (!port)
|
||||||
return;
|
return;
|
||||||
|
@ -1764,6 +1758,16 @@ static void uart_dtr_rts(struct tty_port *port, int raise)
|
||||||
uart_port_deref(uport);
|
uart_port_deref(uport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int uart_install(struct tty_driver *driver, struct tty_struct *tty)
|
||||||
|
{
|
||||||
|
struct uart_driver *drv = driver->driver_state;
|
||||||
|
struct uart_state *state = drv->state + tty->index;
|
||||||
|
|
||||||
|
tty->driver_data = state;
|
||||||
|
|
||||||
|
return tty_standard_install(driver, tty);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calls to uart_open are serialised by the tty_lock in
|
* Calls to uart_open are serialised by the tty_lock in
|
||||||
* drivers/tty/tty_io.c:tty_open()
|
* drivers/tty/tty_io.c:tty_open()
|
||||||
|
@ -1776,11 +1780,8 @@ static void uart_dtr_rts(struct tty_port *port, int raise)
|
||||||
*/
|
*/
|
||||||
static int uart_open(struct tty_struct *tty, struct file *filp)
|
static int uart_open(struct tty_struct *tty, struct file *filp)
|
||||||
{
|
{
|
||||||
struct uart_driver *drv = tty->driver->driver_state;
|
struct uart_state *state = tty->driver_data;
|
||||||
int retval, line = tty->index;
|
int retval;
|
||||||
struct uart_state *state = drv->state + line;
|
|
||||||
|
|
||||||
tty->driver_data = state;
|
|
||||||
|
|
||||||
retval = tty_port_open(&state->port, tty, filp);
|
retval = tty_port_open(&state->port, tty, filp);
|
||||||
if (retval > 0)
|
if (retval > 0)
|
||||||
|
@ -2465,6 +2466,7 @@ static void uart_poll_put_char(struct tty_driver *driver, int line, char ch)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const struct tty_operations uart_ops = {
|
static const struct tty_operations uart_ops = {
|
||||||
|
.install = uart_install,
|
||||||
.open = uart_open,
|
.open = uart_open,
|
||||||
.close = uart_close,
|
.close = uart_close,
|
||||||
.write = uart_write,
|
.write = uart_write,
|
||||||
|
|
|
@ -1510,6 +1510,13 @@ static void sci_request_dma(struct uart_port *port)
|
||||||
|
|
||||||
dev_dbg(port->dev, "%s: port %d\n", __func__, port->line);
|
dev_dbg(port->dev, "%s: port %d\n", __func__, port->line);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DMA on console may interfere with Kernel log messages which use
|
||||||
|
* plain putchar(). So, simply don't use it with a console.
|
||||||
|
*/
|
||||||
|
if (uart_console(port))
|
||||||
|
return;
|
||||||
|
|
||||||
if (!port->dev->of_node)
|
if (!port->dev->of_node)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -755,6 +755,13 @@ static void visual_init(struct vc_data *vc, int num, int init)
|
||||||
vc->vc_screenbuf_size = vc->vc_rows * vc->vc_size_row;
|
vc->vc_screenbuf_size = vc->vc_rows * vc->vc_size_row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void visual_deinit(struct vc_data *vc)
|
||||||
|
{
|
||||||
|
vc->vc_sw->con_deinit(vc);
|
||||||
|
module_put(vc->vc_sw->owner);
|
||||||
|
}
|
||||||
|
|
||||||
int vc_allocate(unsigned int currcons) /* return 0 on success */
|
int vc_allocate(unsigned int currcons) /* return 0 on success */
|
||||||
{
|
{
|
||||||
struct vt_notifier_param param;
|
struct vt_notifier_param param;
|
||||||
|
@ -802,6 +809,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
err_free:
|
err_free:
|
||||||
|
visual_deinit(vc);
|
||||||
kfree(vc);
|
kfree(vc);
|
||||||
vc_cons[currcons].d = NULL;
|
vc_cons[currcons].d = NULL;
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -1014,9 +1022,8 @@ struct vc_data *vc_deallocate(unsigned int currcons)
|
||||||
param.vc = vc = vc_cons[currcons].d;
|
param.vc = vc = vc_cons[currcons].d;
|
||||||
atomic_notifier_call_chain(&vt_notifier_list, VT_DEALLOCATE, ¶m);
|
atomic_notifier_call_chain(&vt_notifier_list, VT_DEALLOCATE, ¶m);
|
||||||
vcs_remove_sysfs(currcons);
|
vcs_remove_sysfs(currcons);
|
||||||
vc->vc_sw->con_deinit(vc);
|
visual_deinit(vc);
|
||||||
put_pid(vc->vt_pid);
|
put_pid(vc->vt_pid);
|
||||||
module_put(vc->vc_sw->owner);
|
|
||||||
kfree(vc->vc_screenbuf);
|
kfree(vc->vc_screenbuf);
|
||||||
vc_cons[currcons].d = NULL;
|
vc_cons[currcons].d = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -936,8 +936,8 @@ int usb_get_bos_descriptor(struct usb_device *dev)
|
||||||
|
|
||||||
/* Get BOS descriptor */
|
/* Get BOS descriptor */
|
||||||
ret = usb_get_descriptor(dev, USB_DT_BOS, 0, bos, USB_DT_BOS_SIZE);
|
ret = usb_get_descriptor(dev, USB_DT_BOS, 0, bos, USB_DT_BOS_SIZE);
|
||||||
if (ret < USB_DT_BOS_SIZE) {
|
if (ret < USB_DT_BOS_SIZE || bos->bLength < USB_DT_BOS_SIZE) {
|
||||||
dev_err(ddev, "unable to get BOS descriptor\n");
|
dev_err(ddev, "unable to get BOS descriptor or descriptor too short\n");
|
||||||
if (ret >= 0)
|
if (ret >= 0)
|
||||||
ret = -ENOMSG;
|
ret = -ENOMSG;
|
||||||
kfree(bos);
|
kfree(bos);
|
||||||
|
|
|
@ -209,6 +209,9 @@ static const struct usb_device_id usb_quirk_list[] = {
|
||||||
/* Microsoft LifeCam-VX700 v2.0 */
|
/* Microsoft LifeCam-VX700 v2.0 */
|
||||||
{ USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME },
|
{ USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME },
|
||||||
|
|
||||||
|
/* Microsoft Surface Dock Ethernet (RTL8153 GigE) */
|
||||||
|
{ USB_DEVICE(0x045e, 0x07c6), .driver_info = USB_QUIRK_NO_LPM },
|
||||||
|
|
||||||
/* Cherry Stream G230 2.0 (G85-231) and 3.0 (G85-232) */
|
/* Cherry Stream G230 2.0 (G85-231) and 3.0 (G85-232) */
|
||||||
{ USB_DEVICE(0x046a, 0x0023), .driver_info = USB_QUIRK_RESET_RESUME },
|
{ USB_DEVICE(0x046a, 0x0023), .driver_info = USB_QUIRK_RESET_RESUME },
|
||||||
|
|
||||||
|
|
|
@ -656,6 +656,7 @@ static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci,
|
||||||
struct device *dev = xhci_to_hcd(xhci)->self.controller;
|
struct device *dev = xhci_to_hcd(xhci)->self.controller;
|
||||||
struct xhci_segment *seg = td->bounce_seg;
|
struct xhci_segment *seg = td->bounce_seg;
|
||||||
struct urb *urb = td->urb;
|
struct urb *urb = td->urb;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
if (!ring || !seg || !urb)
|
if (!ring || !seg || !urb)
|
||||||
return;
|
return;
|
||||||
|
@ -666,11 +667,14 @@ static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* for in tranfers we need to copy the data from bounce to sg */
|
|
||||||
sg_pcopy_from_buffer(urb->sg, urb->num_mapped_sgs, seg->bounce_buf,
|
|
||||||
seg->bounce_len, seg->bounce_offs);
|
|
||||||
dma_unmap_single(dev, seg->bounce_dma, ring->bounce_buf_len,
|
dma_unmap_single(dev, seg->bounce_dma, ring->bounce_buf_len,
|
||||||
DMA_FROM_DEVICE);
|
DMA_FROM_DEVICE);
|
||||||
|
/* for in tranfers we need to copy the data from bounce to sg */
|
||||||
|
len = sg_pcopy_from_buffer(urb->sg, urb->num_sgs, seg->bounce_buf,
|
||||||
|
seg->bounce_len, seg->bounce_offs);
|
||||||
|
if (len != seg->bounce_len)
|
||||||
|
xhci_warn(xhci, "WARN Wrong bounce buffer read length: %zu != %d\n",
|
||||||
|
len, seg->bounce_len);
|
||||||
seg->bounce_len = 0;
|
seg->bounce_len = 0;
|
||||||
seg->bounce_offs = 0;
|
seg->bounce_offs = 0;
|
||||||
}
|
}
|
||||||
|
@ -3104,6 +3108,7 @@ static int xhci_align_td(struct xhci_hcd *xhci, struct urb *urb, u32 enqd_len,
|
||||||
unsigned int unalign;
|
unsigned int unalign;
|
||||||
unsigned int max_pkt;
|
unsigned int max_pkt;
|
||||||
u32 new_buff_len;
|
u32 new_buff_len;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
max_pkt = usb_endpoint_maxp(&urb->ep->desc);
|
max_pkt = usb_endpoint_maxp(&urb->ep->desc);
|
||||||
unalign = (enqd_len + *trb_buff_len) % max_pkt;
|
unalign = (enqd_len + *trb_buff_len) % max_pkt;
|
||||||
|
@ -3134,8 +3139,12 @@ static int xhci_align_td(struct xhci_hcd *xhci, struct urb *urb, u32 enqd_len,
|
||||||
|
|
||||||
/* create a max max_pkt sized bounce buffer pointed to by last trb */
|
/* create a max max_pkt sized bounce buffer pointed to by last trb */
|
||||||
if (usb_urb_dir_out(urb)) {
|
if (usb_urb_dir_out(urb)) {
|
||||||
sg_pcopy_to_buffer(urb->sg, urb->num_mapped_sgs,
|
len = sg_pcopy_to_buffer(urb->sg, urb->num_sgs,
|
||||||
seg->bounce_buf, new_buff_len, enqd_len);
|
seg->bounce_buf, new_buff_len, enqd_len);
|
||||||
|
if (len != seg->bounce_len)
|
||||||
|
xhci_warn(xhci,
|
||||||
|
"WARN Wrong bounce buffer write length: %zu != %d\n",
|
||||||
|
len, seg->bounce_len);
|
||||||
seg->bounce_dma = dma_map_single(dev, seg->bounce_buf,
|
seg->bounce_dma = dma_map_single(dev, seg->bounce_buf,
|
||||||
max_pkt, DMA_TO_DEVICE);
|
max_pkt, DMA_TO_DEVICE);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
|
#include <linux/iopoll.h>
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/log2.h>
|
#include <linux/log2.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
@ -52,7 +53,6 @@ static bool td_on_ring(struct xhci_td *td, struct xhci_ring *ring)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: copied from ehci-hcd.c - can this be refactored? */
|
|
||||||
/*
|
/*
|
||||||
* xhci_handshake - spin reading hc until handshake completes or fails
|
* xhci_handshake - spin reading hc until handshake completes or fails
|
||||||
* @ptr: address of hc register to be read
|
* @ptr: address of hc register to be read
|
||||||
|
@ -69,18 +69,16 @@ static bool td_on_ring(struct xhci_td *td, struct xhci_ring *ring)
|
||||||
int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec)
|
int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec)
|
||||||
{
|
{
|
||||||
u32 result;
|
u32 result;
|
||||||
|
int ret;
|
||||||
|
|
||||||
do {
|
ret = readl_poll_timeout_atomic(ptr, result,
|
||||||
result = readl(ptr);
|
(result & mask) == done ||
|
||||||
if (result == ~(u32)0) /* card removed */
|
result == U32_MAX,
|
||||||
return -ENODEV;
|
1, usec);
|
||||||
result &= mask;
|
if (result == U32_MAX) /* card removed */
|
||||||
if (result == done)
|
return -ENODEV;
|
||||||
return 0;
|
|
||||||
udelay(1);
|
return ret;
|
||||||
usec--;
|
|
||||||
} while (usec > 0);
|
|
||||||
return -ETIMEDOUT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -4289,7 +4287,6 @@ static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
|
||||||
pm_addr = ports[port_num]->addr + PORTPMSC;
|
pm_addr = ports[port_num]->addr + PORTPMSC;
|
||||||
pm_val = readl(pm_addr);
|
pm_val = readl(pm_addr);
|
||||||
hlpm_addr = ports[port_num]->addr + PORTHLPMC;
|
hlpm_addr = ports[port_num]->addr + PORTHLPMC;
|
||||||
field = le32_to_cpu(udev->bos->ext_cap->bmAttributes);
|
|
||||||
|
|
||||||
xhci_dbg(xhci, "%s port %d USB2 hardware LPM\n",
|
xhci_dbg(xhci, "%s port %d USB2 hardware LPM\n",
|
||||||
enable ? "enable" : "disable", port_num + 1);
|
enable ? "enable" : "disable", port_num + 1);
|
||||||
|
@ -4301,6 +4298,7 @@ static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
|
||||||
* default one which works with mixed HIRD and BESL
|
* default one which works with mixed HIRD and BESL
|
||||||
* systems. See XHCI_DEFAULT_BESL definition in xhci.h
|
* systems. See XHCI_DEFAULT_BESL definition in xhci.h
|
||||||
*/
|
*/
|
||||||
|
field = le32_to_cpu(udev->bos->ext_cap->bmAttributes);
|
||||||
if ((field & USB_BESL_SUPPORT) &&
|
if ((field & USB_BESL_SUPPORT) &&
|
||||||
(field & USB_BESL_BASELINE_VALID))
|
(field & USB_BESL_BASELINE_VALID))
|
||||||
hird = USB_GET_BESL_BASELINE(field);
|
hird = USB_GET_BESL_BASELINE(field);
|
||||||
|
|
|
@ -86,9 +86,22 @@ static int close_rio(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
struct rio_usb_data *rio = &rio_instance;
|
struct rio_usb_data *rio = &rio_instance;
|
||||||
|
|
||||||
rio->isopen = 0;
|
/* against disconnect() */
|
||||||
|
mutex_lock(&rio500_mutex);
|
||||||
|
mutex_lock(&(rio->lock));
|
||||||
|
|
||||||
dev_info(&rio->rio_dev->dev, "Rio closed.\n");
|
rio->isopen = 0;
|
||||||
|
if (!rio->present) {
|
||||||
|
/* cleanup has been delayed */
|
||||||
|
kfree(rio->ibuf);
|
||||||
|
kfree(rio->obuf);
|
||||||
|
rio->ibuf = NULL;
|
||||||
|
rio->obuf = NULL;
|
||||||
|
} else {
|
||||||
|
dev_info(&rio->rio_dev->dev, "Rio closed.\n");
|
||||||
|
}
|
||||||
|
mutex_unlock(&(rio->lock));
|
||||||
|
mutex_unlock(&rio500_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -447,15 +460,23 @@ static int probe_rio(struct usb_interface *intf,
|
||||||
{
|
{
|
||||||
struct usb_device *dev = interface_to_usbdev(intf);
|
struct usb_device *dev = interface_to_usbdev(intf);
|
||||||
struct rio_usb_data *rio = &rio_instance;
|
struct rio_usb_data *rio = &rio_instance;
|
||||||
int retval;
|
int retval = 0;
|
||||||
|
|
||||||
dev_info(&intf->dev, "USB Rio found at address %d\n", dev->devnum);
|
mutex_lock(&rio500_mutex);
|
||||||
|
if (rio->present) {
|
||||||
|
dev_info(&intf->dev, "Second USB Rio at address %d refused\n", dev->devnum);
|
||||||
|
retval = -EBUSY;
|
||||||
|
goto bail_out;
|
||||||
|
} else {
|
||||||
|
dev_info(&intf->dev, "USB Rio found at address %d\n", dev->devnum);
|
||||||
|
}
|
||||||
|
|
||||||
retval = usb_register_dev(intf, &usb_rio_class);
|
retval = usb_register_dev(intf, &usb_rio_class);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
dev_err(&dev->dev,
|
dev_err(&dev->dev,
|
||||||
"Not able to get a minor for this device.\n");
|
"Not able to get a minor for this device.\n");
|
||||||
return -ENOMEM;
|
retval = -ENOMEM;
|
||||||
|
goto bail_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
rio->rio_dev = dev;
|
rio->rio_dev = dev;
|
||||||
|
@ -464,7 +485,8 @@ static int probe_rio(struct usb_interface *intf,
|
||||||
dev_err(&dev->dev,
|
dev_err(&dev->dev,
|
||||||
"probe_rio: Not enough memory for the output buffer\n");
|
"probe_rio: Not enough memory for the output buffer\n");
|
||||||
usb_deregister_dev(intf, &usb_rio_class);
|
usb_deregister_dev(intf, &usb_rio_class);
|
||||||
return -ENOMEM;
|
retval = -ENOMEM;
|
||||||
|
goto bail_out;
|
||||||
}
|
}
|
||||||
dev_dbg(&intf->dev, "obuf address:%p\n", rio->obuf);
|
dev_dbg(&intf->dev, "obuf address:%p\n", rio->obuf);
|
||||||
|
|
||||||
|
@ -473,7 +495,8 @@ static int probe_rio(struct usb_interface *intf,
|
||||||
"probe_rio: Not enough memory for the input buffer\n");
|
"probe_rio: Not enough memory for the input buffer\n");
|
||||||
usb_deregister_dev(intf, &usb_rio_class);
|
usb_deregister_dev(intf, &usb_rio_class);
|
||||||
kfree(rio->obuf);
|
kfree(rio->obuf);
|
||||||
return -ENOMEM;
|
retval = -ENOMEM;
|
||||||
|
goto bail_out;
|
||||||
}
|
}
|
||||||
dev_dbg(&intf->dev, "ibuf address:%p\n", rio->ibuf);
|
dev_dbg(&intf->dev, "ibuf address:%p\n", rio->ibuf);
|
||||||
|
|
||||||
|
@ -481,8 +504,10 @@ static int probe_rio(struct usb_interface *intf,
|
||||||
|
|
||||||
usb_set_intfdata (intf, rio);
|
usb_set_intfdata (intf, rio);
|
||||||
rio->present = 1;
|
rio->present = 1;
|
||||||
|
bail_out:
|
||||||
|
mutex_unlock(&rio500_mutex);
|
||||||
|
|
||||||
return 0;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void disconnect_rio(struct usb_interface *intf)
|
static void disconnect_rio(struct usb_interface *intf)
|
||||||
|
|
|
@ -3029,6 +3029,13 @@ static int sisusb_probe(struct usb_interface *intf,
|
||||||
|
|
||||||
mutex_init(&(sisusb->lock));
|
mutex_init(&(sisusb->lock));
|
||||||
|
|
||||||
|
sisusb->sisusb_dev = dev;
|
||||||
|
sisusb->vrambase = SISUSB_PCI_MEMBASE;
|
||||||
|
sisusb->mmiobase = SISUSB_PCI_MMIOBASE;
|
||||||
|
sisusb->mmiosize = SISUSB_PCI_MMIOSIZE;
|
||||||
|
sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
|
||||||
|
/* Everything else is zero */
|
||||||
|
|
||||||
/* Register device */
|
/* Register device */
|
||||||
retval = usb_register_dev(intf, &usb_sisusb_class);
|
retval = usb_register_dev(intf, &usb_sisusb_class);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
|
@ -3039,13 +3046,7 @@ static int sisusb_probe(struct usb_interface *intf,
|
||||||
goto error_1;
|
goto error_1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sisusb->sisusb_dev = dev;
|
sisusb->minor = intf->minor;
|
||||||
sisusb->minor = intf->minor;
|
|
||||||
sisusb->vrambase = SISUSB_PCI_MEMBASE;
|
|
||||||
sisusb->mmiobase = SISUSB_PCI_MMIOBASE;
|
|
||||||
sisusb->mmiosize = SISUSB_PCI_MMIOSIZE;
|
|
||||||
sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
|
|
||||||
/* Everything else is zero */
|
|
||||||
|
|
||||||
/* Allocate buffers */
|
/* Allocate buffers */
|
||||||
sisusb->ibufsize = SISUSB_IBUF_SIZE;
|
sisusb->ibufsize = SISUSB_IBUF_SIZE;
|
||||||
|
|
|
@ -301,9 +301,17 @@ static int stub_probe(struct usb_device *udev)
|
||||||
const char *udev_busid = dev_name(&udev->dev);
|
const char *udev_busid = dev_name(&udev->dev);
|
||||||
struct bus_id_priv *busid_priv;
|
struct bus_id_priv *busid_priv;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
char save_status;
|
||||||
|
|
||||||
dev_dbg(&udev->dev, "Enter probe\n");
|
dev_dbg(&udev->dev, "Enter probe\n");
|
||||||
|
|
||||||
|
/* Not sure if this is our device. Allocate here to avoid
|
||||||
|
* calling alloc while holding busid_table lock.
|
||||||
|
*/
|
||||||
|
sdev = stub_device_alloc(udev);
|
||||||
|
if (!sdev)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
/* check we should claim or not by busid_table */
|
/* check we should claim or not by busid_table */
|
||||||
busid_priv = get_busid_priv(udev_busid);
|
busid_priv = get_busid_priv(udev_busid);
|
||||||
if (!busid_priv || (busid_priv->status == STUB_BUSID_REMOV) ||
|
if (!busid_priv || (busid_priv->status == STUB_BUSID_REMOV) ||
|
||||||
|
@ -318,6 +326,9 @@ static int stub_probe(struct usb_device *udev)
|
||||||
* See driver_probe_device() in driver/base/dd.c
|
* See driver_probe_device() in driver/base/dd.c
|
||||||
*/
|
*/
|
||||||
rc = -ENODEV;
|
rc = -ENODEV;
|
||||||
|
if (!busid_priv)
|
||||||
|
goto sdev_free;
|
||||||
|
|
||||||
goto call_put_busid_priv;
|
goto call_put_busid_priv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,12 +348,6 @@ static int stub_probe(struct usb_device *udev)
|
||||||
goto call_put_busid_priv;
|
goto call_put_busid_priv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ok, this is my device */
|
|
||||||
sdev = stub_device_alloc(udev);
|
|
||||||
if (!sdev) {
|
|
||||||
rc = -ENOMEM;
|
|
||||||
goto call_put_busid_priv;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev_info(&udev->dev,
|
dev_info(&udev->dev,
|
||||||
"usbip-host: register new device (bus %u dev %u)\n",
|
"usbip-host: register new device (bus %u dev %u)\n",
|
||||||
|
@ -352,9 +357,16 @@ static int stub_probe(struct usb_device *udev)
|
||||||
|
|
||||||
/* set private data to usb_device */
|
/* set private data to usb_device */
|
||||||
dev_set_drvdata(&udev->dev, sdev);
|
dev_set_drvdata(&udev->dev, sdev);
|
||||||
|
|
||||||
busid_priv->sdev = sdev;
|
busid_priv->sdev = sdev;
|
||||||
busid_priv->udev = udev;
|
busid_priv->udev = udev;
|
||||||
|
|
||||||
|
save_status = busid_priv->status;
|
||||||
|
busid_priv->status = STUB_BUSID_ALLOC;
|
||||||
|
|
||||||
|
/* release the busid_lock */
|
||||||
|
put_busid_priv(busid_priv);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Claim this hub port.
|
* Claim this hub port.
|
||||||
* It doesn't matter what value we pass as owner
|
* It doesn't matter what value we pass as owner
|
||||||
|
@ -372,10 +384,8 @@ static int stub_probe(struct usb_device *udev)
|
||||||
dev_err(&udev->dev, "stub_add_files for %s\n", udev_busid);
|
dev_err(&udev->dev, "stub_add_files for %s\n", udev_busid);
|
||||||
goto err_files;
|
goto err_files;
|
||||||
}
|
}
|
||||||
busid_priv->status = STUB_BUSID_ALLOC;
|
|
||||||
|
|
||||||
rc = 0;
|
return 0;
|
||||||
goto call_put_busid_priv;
|
|
||||||
|
|
||||||
err_files:
|
err_files:
|
||||||
usb_hub_release_port(udev->parent, udev->portnum,
|
usb_hub_release_port(udev->parent, udev->portnum,
|
||||||
|
@ -384,23 +394,30 @@ err_port:
|
||||||
dev_set_drvdata(&udev->dev, NULL);
|
dev_set_drvdata(&udev->dev, NULL);
|
||||||
usb_put_dev(udev);
|
usb_put_dev(udev);
|
||||||
|
|
||||||
|
/* we already have busid_priv, just lock busid_lock */
|
||||||
|
spin_lock(&busid_priv->busid_lock);
|
||||||
busid_priv->sdev = NULL;
|
busid_priv->sdev = NULL;
|
||||||
stub_device_free(sdev);
|
busid_priv->status = save_status;
|
||||||
|
spin_unlock(&busid_priv->busid_lock);
|
||||||
|
/* lock is released - go to free */
|
||||||
|
goto sdev_free;
|
||||||
|
|
||||||
call_put_busid_priv:
|
call_put_busid_priv:
|
||||||
|
/* release the busid_lock */
|
||||||
put_busid_priv(busid_priv);
|
put_busid_priv(busid_priv);
|
||||||
|
|
||||||
|
sdev_free:
|
||||||
|
stub_device_free(sdev);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void shutdown_busid(struct bus_id_priv *busid_priv)
|
static void shutdown_busid(struct bus_id_priv *busid_priv)
|
||||||
{
|
{
|
||||||
if (busid_priv->sdev && !busid_priv->shutdown_busid) {
|
usbip_event_add(&busid_priv->sdev->ud, SDEV_EVENT_REMOVED);
|
||||||
busid_priv->shutdown_busid = 1;
|
|
||||||
usbip_event_add(&busid_priv->sdev->ud, SDEV_EVENT_REMOVED);
|
|
||||||
|
|
||||||
/* wait for the stop of the event handler */
|
/* wait for the stop of the event handler */
|
||||||
usbip_stop_eh(&busid_priv->sdev->ud);
|
usbip_stop_eh(&busid_priv->sdev->ud);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -427,11 +444,16 @@ static void stub_disconnect(struct usb_device *udev)
|
||||||
/* get stub_device */
|
/* get stub_device */
|
||||||
if (!sdev) {
|
if (!sdev) {
|
||||||
dev_err(&udev->dev, "could not get device");
|
dev_err(&udev->dev, "could not get device");
|
||||||
goto call_put_busid_priv;
|
/* release busid_lock */
|
||||||
|
put_busid_priv(busid_priv);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_set_drvdata(&udev->dev, NULL);
|
dev_set_drvdata(&udev->dev, NULL);
|
||||||
|
|
||||||
|
/* release busid_lock before call to remove device files */
|
||||||
|
put_busid_priv(busid_priv);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE: rx/tx threads are invoked for each usb_device.
|
* NOTE: rx/tx threads are invoked for each usb_device.
|
||||||
*/
|
*/
|
||||||
|
@ -442,27 +464,36 @@ static void stub_disconnect(struct usb_device *udev)
|
||||||
(struct usb_dev_state *) udev);
|
(struct usb_dev_state *) udev);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
dev_dbg(&udev->dev, "unable to release port\n");
|
dev_dbg(&udev->dev, "unable to release port\n");
|
||||||
goto call_put_busid_priv;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If usb reset is called from event handler */
|
/* If usb reset is called from event handler */
|
||||||
if (usbip_in_eh(current))
|
if (usbip_in_eh(current))
|
||||||
goto call_put_busid_priv;
|
return;
|
||||||
|
|
||||||
|
/* we already have busid_priv, just lock busid_lock */
|
||||||
|
spin_lock(&busid_priv->busid_lock);
|
||||||
|
if (!busid_priv->shutdown_busid)
|
||||||
|
busid_priv->shutdown_busid = 1;
|
||||||
|
/* release busid_lock */
|
||||||
|
spin_unlock(&busid_priv->busid_lock);
|
||||||
|
|
||||||
/* shutdown the current connection */
|
/* shutdown the current connection */
|
||||||
shutdown_busid(busid_priv);
|
shutdown_busid(busid_priv);
|
||||||
|
|
||||||
usb_put_dev(sdev->udev);
|
usb_put_dev(sdev->udev);
|
||||||
|
|
||||||
|
/* we already have busid_priv, just lock busid_lock */
|
||||||
|
spin_lock(&busid_priv->busid_lock);
|
||||||
/* free sdev */
|
/* free sdev */
|
||||||
busid_priv->sdev = NULL;
|
busid_priv->sdev = NULL;
|
||||||
stub_device_free(sdev);
|
stub_device_free(sdev);
|
||||||
|
|
||||||
if (busid_priv->status == STUB_BUSID_ALLOC)
|
if (busid_priv->status == STUB_BUSID_ALLOC)
|
||||||
busid_priv->status = STUB_BUSID_ADDED;
|
busid_priv->status = STUB_BUSID_ADDED;
|
||||||
|
/* release busid_lock */
|
||||||
call_put_busid_priv:
|
spin_unlock(&busid_priv->busid_lock);
|
||||||
put_busid_priv(busid_priv);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
|
|
|
@ -1223,7 +1223,7 @@ finished:
|
||||||
if (free_font)
|
if (free_font)
|
||||||
vc->vc_font.data = NULL;
|
vc->vc_font.data = NULL;
|
||||||
|
|
||||||
if (vc->vc_hi_font_mask)
|
if (vc->vc_hi_font_mask && vc->vc_screenbuf)
|
||||||
set_vc_hi_font(vc, false);
|
set_vc_hi_font(vc, false);
|
||||||
|
|
||||||
if (!con_is_bound(&fb_con))
|
if (!con_is_bound(&fb_con))
|
||||||
|
|
|
@ -127,8 +127,6 @@ void xen_pcibk_reset_device(struct pci_dev *dev)
|
||||||
if (pci_is_enabled(dev))
|
if (pci_is_enabled(dev))
|
||||||
pci_disable_device(dev);
|
pci_disable_device(dev);
|
||||||
|
|
||||||
pci_write_config_word(dev, PCI_COMMAND, 0);
|
|
||||||
|
|
||||||
dev->is_busmaster = 0;
|
dev->is_busmaster = 0;
|
||||||
} else {
|
} else {
|
||||||
pci_read_config_word(dev, PCI_COMMAND, &cmd);
|
pci_read_config_word(dev, PCI_COMMAND, &cmd);
|
||||||
|
|
|
@ -6440,8 +6440,18 @@ int btrfs_add_link(struct btrfs_trans_handle *trans,
|
||||||
btrfs_i_size_write(parent_inode, parent_inode->vfs_inode.i_size +
|
btrfs_i_size_write(parent_inode, parent_inode->vfs_inode.i_size +
|
||||||
name_len * 2);
|
name_len * 2);
|
||||||
inode_inc_iversion(&parent_inode->vfs_inode);
|
inode_inc_iversion(&parent_inode->vfs_inode);
|
||||||
parent_inode->vfs_inode.i_mtime = parent_inode->vfs_inode.i_ctime =
|
/*
|
||||||
current_time(&parent_inode->vfs_inode);
|
* If we are replaying a log tree, we do not want to update the mtime
|
||||||
|
* and ctime of the parent directory with the current time, since the
|
||||||
|
* log replay procedure is responsible for setting them to their correct
|
||||||
|
* values (the ones it had when the fsync was done).
|
||||||
|
*/
|
||||||
|
if (!test_bit(BTRFS_FS_LOG_RECOVERING, &root->fs_info->flags)) {
|
||||||
|
struct timespec64 now = current_time(&parent_inode->vfs_inode);
|
||||||
|
|
||||||
|
parent_inode->vfs_inode.i_mtime = now;
|
||||||
|
parent_inode->vfs_inode.i_ctime = now;
|
||||||
|
}
|
||||||
ret = btrfs_update_inode(trans, root, &parent_inode->vfs_inode);
|
ret = btrfs_update_inode(trans, root, &parent_inode->vfs_inode);
|
||||||
if (ret)
|
if (ret)
|
||||||
btrfs_abort_transaction(trans, ret);
|
btrfs_abort_transaction(trans, ret);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user