mirror of
https://github.com/torvalds/linux.git
synced 2026-06-08 06:25:52 +02:00
Merge 6bff9bb8a2 ("Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi") into android-mainline
Steps on the way to 5.10-rc8/final Change-Id: I52a3a13446bf00937f61bf2b2b3559e000e8a47d Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
commit
3f43bd6f2c
|
|
@ -455,7 +455,7 @@ If the generation number of the spte does not equal the global generation
|
|||
number, it will ignore the cached MMIO information and handle the page
|
||||
fault through the slow path.
|
||||
|
||||
Since only 19 bits are used to store generation-number on mmio spte, all
|
||||
Since only 18 bits are used to store generation-number on mmio spte, all
|
||||
pages are zapped when there is an overflow.
|
||||
|
||||
Unfortunately, a single memory access might access kvm_memslots(kvm) multiple
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@
|
|||
/* Shared ISS fault status code(IFSC/DFSC) for Data/Instruction aborts */
|
||||
#define ESR_ELx_FSC (0x3F)
|
||||
#define ESR_ELx_FSC_TYPE (0x3C)
|
||||
#define ESR_ELx_FSC_LEVEL (0x03)
|
||||
#define ESR_ELx_FSC_EXTABT (0x10)
|
||||
#define ESR_ELx_FSC_SERROR (0x11)
|
||||
#define ESR_ELx_FSC_ACCESS (0x08)
|
||||
|
|
|
|||
|
|
@ -350,6 +350,11 @@ static __always_inline u8 kvm_vcpu_trap_get_fault_type(const struct kvm_vcpu *vc
|
|||
return kvm_vcpu_get_esr(vcpu) & ESR_ELx_FSC_TYPE;
|
||||
}
|
||||
|
||||
static __always_inline u8 kvm_vcpu_trap_get_fault_level(const struct kvm_vcpu *vcpu)
|
||||
{
|
||||
return kvm_vcpu_get_esr(vcpu) & ESR_ELx_FSC_LEVEL;
|
||||
}
|
||||
|
||||
static __always_inline bool kvm_vcpu_abt_issea(const struct kvm_vcpu *vcpu)
|
||||
{
|
||||
switch (kvm_vcpu_trap_get_fault(vcpu)) {
|
||||
|
|
|
|||
|
|
@ -470,6 +470,15 @@ static bool stage2_map_walker_try_leaf(u64 addr, u64 end, u32 level,
|
|||
if (!kvm_block_mapping_supported(addr, end, phys, level))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* If the PTE was already valid, drop the refcount on the table
|
||||
* early, as it will be bumped-up again in stage2_map_walk_leaf().
|
||||
* This ensures that the refcount stays constant across a valid to
|
||||
* valid PTE update.
|
||||
*/
|
||||
if (kvm_pte_valid(*ptep))
|
||||
put_page(virt_to_page(ptep));
|
||||
|
||||
if (kvm_set_valid_leaf_pte(ptep, phys, data->attr, level))
|
||||
goto out;
|
||||
|
||||
|
|
@ -493,7 +502,13 @@ static int stage2_map_walk_table_pre(u64 addr, u64 end, u32 level,
|
|||
return 0;
|
||||
|
||||
kvm_set_invalid_pte(ptep);
|
||||
kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, data->mmu, addr, 0);
|
||||
|
||||
/*
|
||||
* Invalidate the whole stage-2, as we may have numerous leaf
|
||||
* entries below us which would otherwise need invalidating
|
||||
* individually.
|
||||
*/
|
||||
kvm_call_hyp(__kvm_tlb_flush_vmid, data->mmu);
|
||||
data->anchor = ptep;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -754,10 +754,12 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
|
|||
gfn_t gfn;
|
||||
kvm_pfn_t pfn;
|
||||
bool logging_active = memslot_is_logging(memslot);
|
||||
unsigned long vma_pagesize;
|
||||
unsigned long fault_level = kvm_vcpu_trap_get_fault_level(vcpu);
|
||||
unsigned long vma_pagesize, fault_granule;
|
||||
enum kvm_pgtable_prot prot = KVM_PGTABLE_PROT_R;
|
||||
struct kvm_pgtable *pgt;
|
||||
|
||||
fault_granule = 1UL << ARM64_HW_PGTABLE_LEVEL_SHIFT(fault_level);
|
||||
write_fault = kvm_is_write_fault(vcpu);
|
||||
exec_fault = kvm_vcpu_trap_is_exec_fault(vcpu);
|
||||
VM_BUG_ON(write_fault && exec_fault);
|
||||
|
|
@ -896,7 +898,12 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
|
|||
else if (cpus_have_const_cap(ARM64_HAS_CACHE_DIC))
|
||||
prot |= KVM_PGTABLE_PROT_X;
|
||||
|
||||
if (fault_status == FSC_PERM && !(logging_active && writable)) {
|
||||
/*
|
||||
* Under the premise of getting a FSC_PERM fault, we just need to relax
|
||||
* permissions only if vma_pagesize equals fault_granule. Otherwise,
|
||||
* kvm_pgtable_stage2_map() should be called to change block size.
|
||||
*/
|
||||
if (fault_status == FSC_PERM && vma_pagesize == fault_granule) {
|
||||
ret = kvm_pgtable_stage2_relax_perms(pgt, fault_ipa, prot);
|
||||
} else {
|
||||
ret = kvm_pgtable_stage2_map(pgt, fault_ipa, vma_pagesize,
|
||||
|
|
|
|||
|
|
@ -60,6 +60,8 @@ static inline u32 get_cycles_hi(void)
|
|||
}
|
||||
#define get_cycles_hi get_cycles_hi
|
||||
|
||||
#endif /* !CONFIG_RISCV_M_MODE */
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
static inline u64 get_cycles64(void)
|
||||
{
|
||||
|
|
@ -79,8 +81,6 @@ static inline u64 get_cycles64(void)
|
|||
}
|
||||
#endif /* CONFIG_64BIT */
|
||||
|
||||
#endif /* !CONFIG_RISCV_M_MODE */
|
||||
|
||||
#define ARCH_HAS_READ_CURRENT_TIMER
|
||||
static inline int read_current_timer(unsigned long *timer_val)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ static u64 generation_mmio_spte_mask(u64 gen)
|
|||
WARN_ON(gen & ~MMIO_SPTE_GEN_MASK);
|
||||
BUILD_BUG_ON((MMIO_SPTE_GEN_HIGH_MASK | MMIO_SPTE_GEN_LOW_MASK) & SPTE_SPECIAL_MASK);
|
||||
|
||||
mask = (gen << MMIO_SPTE_GEN_LOW_START) & MMIO_SPTE_GEN_LOW_MASK;
|
||||
mask |= (gen << MMIO_SPTE_GEN_HIGH_START) & MMIO_SPTE_GEN_HIGH_MASK;
|
||||
mask = (gen << MMIO_SPTE_GEN_LOW_SHIFT) & MMIO_SPTE_GEN_LOW_MASK;
|
||||
mask |= (gen << MMIO_SPTE_GEN_HIGH_SHIFT) & MMIO_SPTE_GEN_HIGH_MASK;
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,11 +56,11 @@
|
|||
#define SPTE_MMU_WRITEABLE (1ULL << (PT_FIRST_AVAIL_BITS_SHIFT + 1))
|
||||
|
||||
/*
|
||||
* Due to limited space in PTEs, the MMIO generation is a 19 bit subset of
|
||||
* Due to limited space in PTEs, the MMIO generation is a 18 bit subset of
|
||||
* the memslots generation and is derived as follows:
|
||||
*
|
||||
* Bits 0-8 of the MMIO generation are propagated to spte bits 3-11
|
||||
* Bits 9-18 of the MMIO generation are propagated to spte bits 52-61
|
||||
* Bits 9-17 of the MMIO generation are propagated to spte bits 54-62
|
||||
*
|
||||
* The KVM_MEMSLOT_GEN_UPDATE_IN_PROGRESS flag is intentionally not included in
|
||||
* the MMIO generation number, as doing so would require stealing a bit from
|
||||
|
|
@ -69,18 +69,29 @@
|
|||
* requires a full MMU zap). The flag is instead explicitly queried when
|
||||
* checking for MMIO spte cache hits.
|
||||
*/
|
||||
#define MMIO_SPTE_GEN_MASK GENMASK_ULL(17, 0)
|
||||
|
||||
#define MMIO_SPTE_GEN_LOW_START 3
|
||||
#define MMIO_SPTE_GEN_LOW_END 11
|
||||
#define MMIO_SPTE_GEN_LOW_MASK GENMASK_ULL(MMIO_SPTE_GEN_LOW_END, \
|
||||
MMIO_SPTE_GEN_LOW_START)
|
||||
|
||||
#define MMIO_SPTE_GEN_HIGH_START PT64_SECOND_AVAIL_BITS_SHIFT
|
||||
#define MMIO_SPTE_GEN_HIGH_END 62
|
||||
|
||||
#define MMIO_SPTE_GEN_LOW_MASK GENMASK_ULL(MMIO_SPTE_GEN_LOW_END, \
|
||||
MMIO_SPTE_GEN_LOW_START)
|
||||
#define MMIO_SPTE_GEN_HIGH_MASK GENMASK_ULL(MMIO_SPTE_GEN_HIGH_END, \
|
||||
MMIO_SPTE_GEN_HIGH_START)
|
||||
|
||||
#define MMIO_SPTE_GEN_LOW_BITS (MMIO_SPTE_GEN_LOW_END - MMIO_SPTE_GEN_LOW_START + 1)
|
||||
#define MMIO_SPTE_GEN_HIGH_BITS (MMIO_SPTE_GEN_HIGH_END - MMIO_SPTE_GEN_HIGH_START + 1)
|
||||
|
||||
/* remember to adjust the comment above as well if you change these */
|
||||
static_assert(MMIO_SPTE_GEN_LOW_BITS == 9 && MMIO_SPTE_GEN_HIGH_BITS == 9);
|
||||
|
||||
#define MMIO_SPTE_GEN_LOW_SHIFT (MMIO_SPTE_GEN_LOW_START - 0)
|
||||
#define MMIO_SPTE_GEN_HIGH_SHIFT (MMIO_SPTE_GEN_HIGH_START - MMIO_SPTE_GEN_LOW_BITS)
|
||||
|
||||
#define MMIO_SPTE_GEN_MASK GENMASK_ULL(MMIO_SPTE_GEN_LOW_BITS + MMIO_SPTE_GEN_HIGH_BITS - 1, 0)
|
||||
|
||||
extern u64 __read_mostly shadow_nx_mask;
|
||||
extern u64 __read_mostly shadow_x_mask; /* mutual exclusive with nx_mask */
|
||||
extern u64 __read_mostly shadow_user_mask;
|
||||
|
|
@ -228,8 +239,8 @@ static inline u64 get_mmio_spte_generation(u64 spte)
|
|||
{
|
||||
u64 gen;
|
||||
|
||||
gen = (spte & MMIO_SPTE_GEN_LOW_MASK) >> MMIO_SPTE_GEN_LOW_START;
|
||||
gen |= (spte & MMIO_SPTE_GEN_HIGH_MASK) >> MMIO_SPTE_GEN_HIGH_START;
|
||||
gen = (spte & MMIO_SPTE_GEN_LOW_MASK) >> MMIO_SPTE_GEN_LOW_SHIFT;
|
||||
gen |= (spte & MMIO_SPTE_GEN_HIGH_MASK) >> MMIO_SPTE_GEN_HIGH_SHIFT;
|
||||
return gen;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ static bool zap_gfn_range(struct kvm *kvm, struct kvm_mmu_page *root,
|
|||
|
||||
void kvm_tdp_mmu_free_root(struct kvm *kvm, struct kvm_mmu_page *root)
|
||||
{
|
||||
gfn_t max_gfn = 1ULL << (boot_cpu_data.x86_phys_bits - PAGE_SHIFT);
|
||||
gfn_t max_gfn = 1ULL << (shadow_phys_bits - PAGE_SHIFT);
|
||||
|
||||
lockdep_assert_held(&kvm->mmu_lock);
|
||||
|
||||
|
|
@ -456,7 +456,7 @@ bool kvm_tdp_mmu_zap_gfn_range(struct kvm *kvm, gfn_t start, gfn_t end)
|
|||
|
||||
void kvm_tdp_mmu_zap_all(struct kvm *kvm)
|
||||
{
|
||||
gfn_t max_gfn = 1ULL << (boot_cpu_data.x86_phys_bits - PAGE_SHIFT);
|
||||
gfn_t max_gfn = 1ULL << (shadow_phys_bits - PAGE_SHIFT);
|
||||
bool flush;
|
||||
|
||||
flush = kvm_tdp_mmu_zap_gfn_range(kvm, 0, max_gfn);
|
||||
|
|
|
|||
|
|
@ -530,12 +530,12 @@ static int svm_hardware_enable(void)
|
|||
|
||||
static void svm_cpu_uninit(int cpu)
|
||||
{
|
||||
struct svm_cpu_data *sd = per_cpu(svm_data, raw_smp_processor_id());
|
||||
struct svm_cpu_data *sd = per_cpu(svm_data, cpu);
|
||||
|
||||
if (!sd)
|
||||
return;
|
||||
|
||||
per_cpu(svm_data, raw_smp_processor_id()) = NULL;
|
||||
per_cpu(svm_data, cpu) = NULL;
|
||||
kfree(sd->sev_vmcbs);
|
||||
__free_page(sd->save_area);
|
||||
kfree(sd);
|
||||
|
|
|
|||
|
|
@ -132,73 +132,12 @@ module_param(log_stats, int, 0644);
|
|||
|
||||
#define BLKBACK_INVALID_HANDLE (~0)
|
||||
|
||||
/* Number of free pages to remove on each call to gnttab_free_pages */
|
||||
#define NUM_BATCH_FREE_PAGES 10
|
||||
|
||||
static inline bool persistent_gnt_timeout(struct persistent_gnt *persistent_gnt)
|
||||
{
|
||||
return pgrant_timeout && (jiffies - persistent_gnt->last_used >=
|
||||
HZ * pgrant_timeout);
|
||||
}
|
||||
|
||||
static inline int get_free_page(struct xen_blkif_ring *ring, struct page **page)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ring->free_pages_lock, flags);
|
||||
if (list_empty(&ring->free_pages)) {
|
||||
BUG_ON(ring->free_pages_num != 0);
|
||||
spin_unlock_irqrestore(&ring->free_pages_lock, flags);
|
||||
return gnttab_alloc_pages(1, page);
|
||||
}
|
||||
BUG_ON(ring->free_pages_num == 0);
|
||||
page[0] = list_first_entry(&ring->free_pages, struct page, lru);
|
||||
list_del(&page[0]->lru);
|
||||
ring->free_pages_num--;
|
||||
spin_unlock_irqrestore(&ring->free_pages_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void put_free_pages(struct xen_blkif_ring *ring, struct page **page,
|
||||
int num)
|
||||
{
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
spin_lock_irqsave(&ring->free_pages_lock, flags);
|
||||
for (i = 0; i < num; i++)
|
||||
list_add(&page[i]->lru, &ring->free_pages);
|
||||
ring->free_pages_num += num;
|
||||
spin_unlock_irqrestore(&ring->free_pages_lock, flags);
|
||||
}
|
||||
|
||||
static inline void shrink_free_pagepool(struct xen_blkif_ring *ring, int num)
|
||||
{
|
||||
/* Remove requested pages in batches of NUM_BATCH_FREE_PAGES */
|
||||
struct page *page[NUM_BATCH_FREE_PAGES];
|
||||
unsigned int num_pages = 0;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ring->free_pages_lock, flags);
|
||||
while (ring->free_pages_num > num) {
|
||||
BUG_ON(list_empty(&ring->free_pages));
|
||||
page[num_pages] = list_first_entry(&ring->free_pages,
|
||||
struct page, lru);
|
||||
list_del(&page[num_pages]->lru);
|
||||
ring->free_pages_num--;
|
||||
if (++num_pages == NUM_BATCH_FREE_PAGES) {
|
||||
spin_unlock_irqrestore(&ring->free_pages_lock, flags);
|
||||
gnttab_free_pages(num_pages, page);
|
||||
spin_lock_irqsave(&ring->free_pages_lock, flags);
|
||||
num_pages = 0;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&ring->free_pages_lock, flags);
|
||||
if (num_pages != 0)
|
||||
gnttab_free_pages(num_pages, page);
|
||||
}
|
||||
|
||||
#define vaddr(page) ((unsigned long)pfn_to_kaddr(page_to_pfn(page)))
|
||||
|
||||
static int do_block_io_op(struct xen_blkif_ring *ring, unsigned int *eoi_flags);
|
||||
|
|
@ -331,7 +270,8 @@ static void free_persistent_gnts(struct xen_blkif_ring *ring, struct rb_root *ro
|
|||
unmap_data.count = segs_to_unmap;
|
||||
BUG_ON(gnttab_unmap_refs_sync(&unmap_data));
|
||||
|
||||
put_free_pages(ring, pages, segs_to_unmap);
|
||||
gnttab_page_cache_put(&ring->free_pages, pages,
|
||||
segs_to_unmap);
|
||||
segs_to_unmap = 0;
|
||||
}
|
||||
|
||||
|
|
@ -371,7 +311,8 @@ void xen_blkbk_unmap_purged_grants(struct work_struct *work)
|
|||
if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST) {
|
||||
unmap_data.count = segs_to_unmap;
|
||||
BUG_ON(gnttab_unmap_refs_sync(&unmap_data));
|
||||
put_free_pages(ring, pages, segs_to_unmap);
|
||||
gnttab_page_cache_put(&ring->free_pages, pages,
|
||||
segs_to_unmap);
|
||||
segs_to_unmap = 0;
|
||||
}
|
||||
kfree(persistent_gnt);
|
||||
|
|
@ -379,7 +320,7 @@ void xen_blkbk_unmap_purged_grants(struct work_struct *work)
|
|||
if (segs_to_unmap > 0) {
|
||||
unmap_data.count = segs_to_unmap;
|
||||
BUG_ON(gnttab_unmap_refs_sync(&unmap_data));
|
||||
put_free_pages(ring, pages, segs_to_unmap);
|
||||
gnttab_page_cache_put(&ring->free_pages, pages, segs_to_unmap);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -664,9 +605,10 @@ int xen_blkif_schedule(void *arg)
|
|||
|
||||
/* Shrink the free pages pool if it is too large. */
|
||||
if (time_before(jiffies, blkif->buffer_squeeze_end))
|
||||
shrink_free_pagepool(ring, 0);
|
||||
gnttab_page_cache_shrink(&ring->free_pages, 0);
|
||||
else
|
||||
shrink_free_pagepool(ring, max_buffer_pages);
|
||||
gnttab_page_cache_shrink(&ring->free_pages,
|
||||
max_buffer_pages);
|
||||
|
||||
if (log_stats && time_after(jiffies, ring->st_print))
|
||||
print_stats(ring);
|
||||
|
|
@ -697,7 +639,7 @@ void xen_blkbk_free_caches(struct xen_blkif_ring *ring)
|
|||
ring->persistent_gnt_c = 0;
|
||||
|
||||
/* Since we are shutting down remove all pages from the buffer */
|
||||
shrink_free_pagepool(ring, 0 /* All */);
|
||||
gnttab_page_cache_shrink(&ring->free_pages, 0 /* All */);
|
||||
}
|
||||
|
||||
static unsigned int xen_blkbk_unmap_prepare(
|
||||
|
|
@ -736,7 +678,7 @@ static void xen_blkbk_unmap_and_respond_callback(int result, struct gntab_unmap_
|
|||
but is this the best way to deal with this? */
|
||||
BUG_ON(result);
|
||||
|
||||
put_free_pages(ring, data->pages, data->count);
|
||||
gnttab_page_cache_put(&ring->free_pages, data->pages, data->count);
|
||||
make_response(ring, pending_req->id,
|
||||
pending_req->operation, pending_req->status);
|
||||
free_req(ring, pending_req);
|
||||
|
|
@ -803,7 +745,8 @@ static void xen_blkbk_unmap(struct xen_blkif_ring *ring,
|
|||
if (invcount) {
|
||||
ret = gnttab_unmap_refs(unmap, NULL, unmap_pages, invcount);
|
||||
BUG_ON(ret);
|
||||
put_free_pages(ring, unmap_pages, invcount);
|
||||
gnttab_page_cache_put(&ring->free_pages, unmap_pages,
|
||||
invcount);
|
||||
}
|
||||
pages += batch;
|
||||
num -= batch;
|
||||
|
|
@ -850,7 +793,8 @@ static int xen_blkbk_map(struct xen_blkif_ring *ring,
|
|||
pages[i]->page = persistent_gnt->page;
|
||||
pages[i]->persistent_gnt = persistent_gnt;
|
||||
} else {
|
||||
if (get_free_page(ring, &pages[i]->page))
|
||||
if (gnttab_page_cache_get(&ring->free_pages,
|
||||
&pages[i]->page))
|
||||
goto out_of_memory;
|
||||
addr = vaddr(pages[i]->page);
|
||||
pages_to_gnt[segs_to_map] = pages[i]->page;
|
||||
|
|
@ -883,7 +827,8 @@ static int xen_blkbk_map(struct xen_blkif_ring *ring,
|
|||
BUG_ON(new_map_idx >= segs_to_map);
|
||||
if (unlikely(map[new_map_idx].status != 0)) {
|
||||
pr_debug("invalid buffer -- could not remap it\n");
|
||||
put_free_pages(ring, &pages[seg_idx]->page, 1);
|
||||
gnttab_page_cache_put(&ring->free_pages,
|
||||
&pages[seg_idx]->page, 1);
|
||||
pages[seg_idx]->handle = BLKBACK_INVALID_HANDLE;
|
||||
ret |= 1;
|
||||
goto next;
|
||||
|
|
@ -944,7 +889,7 @@ static int xen_blkbk_map(struct xen_blkif_ring *ring,
|
|||
|
||||
out_of_memory:
|
||||
pr_alert("%s: out of memory\n", __func__);
|
||||
put_free_pages(ring, pages_to_gnt, segs_to_map);
|
||||
gnttab_page_cache_put(&ring->free_pages, pages_to_gnt, segs_to_map);
|
||||
for (i = last_map; i < num; i++)
|
||||
pages[i]->handle = BLKBACK_INVALID_HANDLE;
|
||||
return -ENOMEM;
|
||||
|
|
|
|||
|
|
@ -288,9 +288,7 @@ struct xen_blkif_ring {
|
|||
struct work_struct persistent_purge_work;
|
||||
|
||||
/* Buffer of free pages to map grant refs. */
|
||||
spinlock_t free_pages_lock;
|
||||
int free_pages_num;
|
||||
struct list_head free_pages;
|
||||
struct gnttab_page_cache free_pages;
|
||||
|
||||
struct work_struct free_work;
|
||||
/* Thread shutdown wait queue. */
|
||||
|
|
|
|||
|
|
@ -144,8 +144,7 @@ static int xen_blkif_alloc_rings(struct xen_blkif *blkif)
|
|||
INIT_LIST_HEAD(&ring->pending_free);
|
||||
INIT_LIST_HEAD(&ring->persistent_purge_list);
|
||||
INIT_WORK(&ring->persistent_purge_work, xen_blkbk_unmap_purged_grants);
|
||||
spin_lock_init(&ring->free_pages_lock);
|
||||
INIT_LIST_HEAD(&ring->free_pages);
|
||||
gnttab_page_cache_init(&ring->free_pages);
|
||||
|
||||
spin_lock_init(&ring->pending_free_lock);
|
||||
init_waitqueue_head(&ring->pending_free_wq);
|
||||
|
|
@ -317,8 +316,7 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif)
|
|||
BUG_ON(atomic_read(&ring->persistent_gnt_in_use) != 0);
|
||||
BUG_ON(!list_empty(&ring->persistent_purge_list));
|
||||
BUG_ON(!RB_EMPTY_ROOT(&ring->persistent_gnts));
|
||||
BUG_ON(!list_empty(&ring->free_pages));
|
||||
BUG_ON(ring->free_pages_num != 0);
|
||||
BUG_ON(ring->free_pages.num_pages != 0);
|
||||
BUG_ON(ring->persistent_gnt_c != 0);
|
||||
WARN_ON(i != (XEN_BLKIF_REQS_PER_PAGE * blkif->nr_ring_pages));
|
||||
ring->active = false;
|
||||
|
|
|
|||
|
|
@ -183,6 +183,7 @@ static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev,
|
|||
"changed: [r%d c%d]: byte %02x\n",
|
||||
row, col, new_state);
|
||||
|
||||
input_event(idev, EV_MSC, MSC_SCAN, pos);
|
||||
input_report_key(idev, keycodes[pos],
|
||||
new_state);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -568,12 +568,15 @@ static int cm109_input_open(struct input_dev *idev)
|
|||
dev->ctl_data->byte[HID_OR2] = dev->keybit;
|
||||
dev->ctl_data->byte[HID_OR3] = 0x00;
|
||||
|
||||
dev->ctl_urb_pending = 1;
|
||||
error = usb_submit_urb(dev->urb_ctl, GFP_KERNEL);
|
||||
if (error)
|
||||
if (error) {
|
||||
dev->ctl_urb_pending = 0;
|
||||
dev_err(&dev->intf->dev, "%s: usb_submit_urb (urb_ctl) failed %d\n",
|
||||
__func__, error);
|
||||
else
|
||||
} else {
|
||||
dev->open = 1;
|
||||
}
|
||||
|
||||
mutex_unlock(&dev->pm_mutex);
|
||||
|
||||
|
|
|
|||
|
|
@ -83,6 +83,17 @@ static const struct dmi_system_id dmi_use_low_level_irq[] = {
|
|||
DMI_MATCH(DMI_PRODUCT_NAME, "One S1003"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/*
|
||||
* Lenovo Yoga Tab2 1051L, something messes with the home-button
|
||||
* IRQ settings, leading to a non working home-button.
|
||||
*/
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "60073"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "1051L"),
|
||||
},
|
||||
},
|
||||
{} /* Terminating entry */
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -611,6 +611,48 @@ static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = {
|
|||
DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A114-31"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A314-31"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A315-31"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire ES1-132"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire ES1-332"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire ES1-432"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate Spin B118-RN"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* Advent 4211 */
|
||||
.matches = {
|
||||
|
|
|
|||
|
|
@ -192,6 +192,18 @@ static const struct dmi_system_id rotated_screen[] = {
|
|||
DMI_MATCH(DMI_BIOS_DATE, "12/19/2014"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "Teclast X98 Pro",
|
||||
.matches = {
|
||||
/*
|
||||
* Only match BIOS date, because the manufacturers
|
||||
* BIOS does not report the board name at all
|
||||
* (sometimes)...
|
||||
*/
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"),
|
||||
DMI_MATCH(DMI_BIOS_DATE, "10/28/2015"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "WinBook TW100",
|
||||
.matches = {
|
||||
|
|
|
|||
|
|
@ -137,45 +137,25 @@ struct raydium_data {
|
|||
bool wake_irq_enabled;
|
||||
};
|
||||
|
||||
static int raydium_i2c_xfer(struct i2c_client *client,
|
||||
u32 addr, void *data, size_t len, bool is_read)
|
||||
/*
|
||||
* Header to be sent for RM_CMD_BANK_SWITCH command. This is used by
|
||||
* raydium_i2c_{read|send} below.
|
||||
*/
|
||||
struct __packed raydium_bank_switch_header {
|
||||
u8 cmd;
|
||||
__be32 be_addr;
|
||||
};
|
||||
|
||||
static int raydium_i2c_xfer(struct i2c_client *client, u32 addr,
|
||||
struct i2c_msg *xfer, size_t xfer_count)
|
||||
{
|
||||
struct raydium_bank_switch_header {
|
||||
u8 cmd;
|
||||
__be32 be_addr;
|
||||
} __packed header = {
|
||||
.cmd = RM_CMD_BANK_SWITCH,
|
||||
.be_addr = cpu_to_be32(addr),
|
||||
};
|
||||
|
||||
u8 reg_addr = addr & 0xff;
|
||||
|
||||
struct i2c_msg xfer[] = {
|
||||
{
|
||||
.addr = client->addr,
|
||||
.len = sizeof(header),
|
||||
.buf = (u8 *)&header,
|
||||
},
|
||||
{
|
||||
.addr = client->addr,
|
||||
.len = 1,
|
||||
.buf = ®_addr,
|
||||
},
|
||||
{
|
||||
.addr = client->addr,
|
||||
.len = len,
|
||||
.buf = data,
|
||||
.flags = is_read ? I2C_M_RD : 0,
|
||||
}
|
||||
};
|
||||
|
||||
int ret;
|
||||
/*
|
||||
* If address is greater than 255, then RM_CMD_BANK_SWITCH needs to be
|
||||
* sent first. Else, skip the header i.e. xfer[0].
|
||||
*/
|
||||
int xfer_start_idx = (addr > 0xff) ? 0 : 1;
|
||||
size_t xfer_count = ARRAY_SIZE(xfer) - xfer_start_idx;
|
||||
int ret;
|
||||
xfer_count -= xfer_start_idx;
|
||||
|
||||
ret = i2c_transfer(client->adapter, &xfer[xfer_start_idx], xfer_count);
|
||||
if (likely(ret == xfer_count))
|
||||
|
|
@ -189,10 +169,46 @@ static int raydium_i2c_send(struct i2c_client *client,
|
|||
{
|
||||
int tries = 0;
|
||||
int error;
|
||||
u8 *tx_buf;
|
||||
u8 reg_addr = addr & 0xff;
|
||||
|
||||
tx_buf = kmalloc(len + 1, GFP_KERNEL);
|
||||
if (!tx_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
tx_buf[0] = reg_addr;
|
||||
memcpy(tx_buf + 1, data, len);
|
||||
|
||||
do {
|
||||
error = raydium_i2c_xfer(client, addr, (void *)data, len,
|
||||
false);
|
||||
struct raydium_bank_switch_header header = {
|
||||
.cmd = RM_CMD_BANK_SWITCH,
|
||||
.be_addr = cpu_to_be32(addr),
|
||||
};
|
||||
|
||||
/*
|
||||
* Perform as a single i2c_transfer transaction to ensure that
|
||||
* no other I2C transactions are initiated on the bus to any
|
||||
* other device in between. Initiating transacations to other
|
||||
* devices after RM_CMD_BANK_SWITCH is sent is known to cause
|
||||
* issues. This is also why regmap infrastructure cannot be used
|
||||
* for this driver. Regmap handles page(bank) switch and reads
|
||||
* as separate i2c_transfer() operations. This can result in
|
||||
* problems if the Raydium device is on a shared I2C bus.
|
||||
*/
|
||||
struct i2c_msg xfer[] = {
|
||||
{
|
||||
.addr = client->addr,
|
||||
.len = sizeof(header),
|
||||
.buf = (u8 *)&header,
|
||||
},
|
||||
{
|
||||
.addr = client->addr,
|
||||
.len = len + 1,
|
||||
.buf = tx_buf,
|
||||
},
|
||||
};
|
||||
|
||||
error = raydium_i2c_xfer(client, addr, xfer, ARRAY_SIZE(xfer));
|
||||
if (likely(!error))
|
||||
return 0;
|
||||
|
||||
|
|
@ -206,12 +222,46 @@ static int raydium_i2c_send(struct i2c_client *client,
|
|||
static int raydium_i2c_read(struct i2c_client *client,
|
||||
u32 addr, void *data, size_t len)
|
||||
{
|
||||
size_t xfer_len;
|
||||
int error;
|
||||
|
||||
while (len) {
|
||||
xfer_len = min_t(size_t, len, RM_MAX_READ_SIZE);
|
||||
error = raydium_i2c_xfer(client, addr, data, xfer_len, true);
|
||||
u8 reg_addr = addr & 0xff;
|
||||
struct raydium_bank_switch_header header = {
|
||||
.cmd = RM_CMD_BANK_SWITCH,
|
||||
.be_addr = cpu_to_be32(addr),
|
||||
};
|
||||
size_t xfer_len = min_t(size_t, len, RM_MAX_READ_SIZE);
|
||||
|
||||
/*
|
||||
* Perform as a single i2c_transfer transaction to ensure that
|
||||
* no other I2C transactions are initiated on the bus to any
|
||||
* other device in between. Initiating transacations to other
|
||||
* devices after RM_CMD_BANK_SWITCH is sent is known to cause
|
||||
* issues. This is also why regmap infrastructure cannot be used
|
||||
* for this driver. Regmap handles page(bank) switch and writes
|
||||
* as separate i2c_transfer() operations. This can result in
|
||||
* problems if the Raydium device is on a shared I2C bus.
|
||||
*/
|
||||
struct i2c_msg xfer[] = {
|
||||
{
|
||||
.addr = client->addr,
|
||||
.len = sizeof(header),
|
||||
.buf = (u8 *)&header,
|
||||
},
|
||||
{
|
||||
.addr = client->addr,
|
||||
.len = 1,
|
||||
.buf = ®_addr,
|
||||
},
|
||||
{
|
||||
.addr = client->addr,
|
||||
.len = xfer_len,
|
||||
.buf = data,
|
||||
.flags = I2C_M_RD,
|
||||
}
|
||||
};
|
||||
|
||||
error = raydium_i2c_xfer(client, addr, xfer, ARRAY_SIZE(xfer));
|
||||
if (unlikely(error))
|
||||
return error;
|
||||
|
||||
|
|
|
|||
|
|
@ -736,7 +736,6 @@ static int at24_probe(struct i2c_client *client)
|
|||
|
||||
nvmem_config.type = NVMEM_TYPE_EEPROM;
|
||||
nvmem_config.dev = dev;
|
||||
nvmem_config.id = NVMEM_DEVID_AUTO;
|
||||
nvmem_config.read_only = !writable;
|
||||
nvmem_config.root_only = !(flags & AT24_FLAG_IRUGO);
|
||||
nvmem_config.owner = THIS_MODULE;
|
||||
|
|
|
|||
|
|
@ -3020,7 +3020,6 @@ static int beiscsi_create_eqs(struct beiscsi_hba *phba,
|
|||
goto create_eq_error;
|
||||
}
|
||||
|
||||
mem->dma = paddr;
|
||||
mem->va = eq_vaddress;
|
||||
ret = be_fill_queue(eq, phba->params.num_eq_entries,
|
||||
sizeof(struct be_eq_entry), eq_vaddress);
|
||||
|
|
@ -3030,6 +3029,7 @@ static int beiscsi_create_eqs(struct beiscsi_hba *phba,
|
|||
goto create_eq_error;
|
||||
}
|
||||
|
||||
mem->dma = paddr;
|
||||
ret = beiscsi_cmd_eq_create(&phba->ctrl, eq,
|
||||
BEISCSI_EQ_DELAY_DEF);
|
||||
if (ret) {
|
||||
|
|
@ -3086,7 +3086,6 @@ static int beiscsi_create_cqs(struct beiscsi_hba *phba,
|
|||
goto create_cq_error;
|
||||
}
|
||||
|
||||
mem->dma = paddr;
|
||||
ret = be_fill_queue(cq, phba->params.num_cq_entries,
|
||||
sizeof(struct sol_cqe), cq_vaddress);
|
||||
if (ret) {
|
||||
|
|
@ -3096,6 +3095,7 @@ static int beiscsi_create_cqs(struct beiscsi_hba *phba,
|
|||
goto create_cq_error;
|
||||
}
|
||||
|
||||
mem->dma = paddr;
|
||||
ret = beiscsi_cmd_cq_create(&phba->ctrl, cq, eq, false,
|
||||
false, 0);
|
||||
if (ret) {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ config SCSI_BNX2_ISCSI
|
|||
depends on NET
|
||||
depends on PCI
|
||||
depends on (IPV6 || IPV6=n)
|
||||
depends on MMU
|
||||
select SCSI_ISCSI_ATTRS
|
||||
select NETDEVICES
|
||||
select ETHERNET
|
||||
|
|
|
|||
|
|
@ -452,6 +452,12 @@ static int hisi_sas_task_prep(struct sas_task *task,
|
|||
blk_tag = blk_mq_unique_tag(scmd->request);
|
||||
dq_index = blk_mq_unique_tag_to_hwq(blk_tag);
|
||||
*dq_pointer = dq = &hisi_hba->dq[dq_index];
|
||||
} else if (hisi_hba->shost->nr_hw_queues) {
|
||||
struct Scsi_Host *shost = hisi_hba->shost;
|
||||
struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT];
|
||||
int queue = qmap->mq_map[raw_smp_processor_id()];
|
||||
|
||||
*dq_pointer = dq = &hisi_hba->dq[queue];
|
||||
} else {
|
||||
*dq_pointer = dq = sas_dev->dq;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2452,6 +2452,11 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba)
|
|||
rc = -ENOENT;
|
||||
goto free_irq_vectors;
|
||||
}
|
||||
cq->irq_mask = pci_irq_get_affinity(pdev, i + BASE_VECTORS_V3_HW);
|
||||
if (!cq->irq_mask) {
|
||||
dev_err(dev, "could not get cq%d irq affinity!\n", i);
|
||||
return -ENOENT;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1703,8 +1703,7 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx,
|
|||
break;
|
||||
case BLK_STS_RESOURCE:
|
||||
case BLK_STS_ZONE_RESOURCE:
|
||||
if (atomic_read(&sdev->device_busy) ||
|
||||
scsi_device_blocked(sdev))
|
||||
if (scsi_device_blocked(sdev))
|
||||
ret = BLK_STS_DEV_RESOURCE;
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -1246,11 +1246,6 @@ static void storvsc_on_channel_callback(void *context)
|
|||
request = (struct storvsc_cmd_request *)
|
||||
((unsigned long)desc->trans_id);
|
||||
|
||||
if (hv_pkt_datalen(desc) < sizeof(struct vstor_packet) - vmscsi_size_delta) {
|
||||
dev_err(&device->device, "Invalid packet len\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (request == &stor_device->init_request ||
|
||||
request == &stor_device->reset_request) {
|
||||
memcpy(&request->vstor_packet, packet,
|
||||
|
|
|
|||
|
|
@ -813,6 +813,129 @@ int gnttab_alloc_pages(int nr_pages, struct page **pages)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(gnttab_alloc_pages);
|
||||
|
||||
#ifdef CONFIG_XEN_UNPOPULATED_ALLOC
|
||||
static inline void cache_init(struct gnttab_page_cache *cache)
|
||||
{
|
||||
cache->pages = NULL;
|
||||
}
|
||||
|
||||
static inline bool cache_empty(struct gnttab_page_cache *cache)
|
||||
{
|
||||
return !cache->pages;
|
||||
}
|
||||
|
||||
static inline struct page *cache_deq(struct gnttab_page_cache *cache)
|
||||
{
|
||||
struct page *page;
|
||||
|
||||
page = cache->pages;
|
||||
cache->pages = page->zone_device_data;
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
static inline void cache_enq(struct gnttab_page_cache *cache, struct page *page)
|
||||
{
|
||||
page->zone_device_data = cache->pages;
|
||||
cache->pages = page;
|
||||
}
|
||||
#else
|
||||
static inline void cache_init(struct gnttab_page_cache *cache)
|
||||
{
|
||||
INIT_LIST_HEAD(&cache->pages);
|
||||
}
|
||||
|
||||
static inline bool cache_empty(struct gnttab_page_cache *cache)
|
||||
{
|
||||
return list_empty(&cache->pages);
|
||||
}
|
||||
|
||||
static inline struct page *cache_deq(struct gnttab_page_cache *cache)
|
||||
{
|
||||
struct page *page;
|
||||
|
||||
page = list_first_entry(&cache->pages, struct page, lru);
|
||||
list_del(&page->lru);
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
static inline void cache_enq(struct gnttab_page_cache *cache, struct page *page)
|
||||
{
|
||||
list_add(&page->lru, &cache->pages);
|
||||
}
|
||||
#endif
|
||||
|
||||
void gnttab_page_cache_init(struct gnttab_page_cache *cache)
|
||||
{
|
||||
spin_lock_init(&cache->lock);
|
||||
cache_init(cache);
|
||||
cache->num_pages = 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gnttab_page_cache_init);
|
||||
|
||||
int gnttab_page_cache_get(struct gnttab_page_cache *cache, struct page **page)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&cache->lock, flags);
|
||||
|
||||
if (cache_empty(cache)) {
|
||||
spin_unlock_irqrestore(&cache->lock, flags);
|
||||
return gnttab_alloc_pages(1, page);
|
||||
}
|
||||
|
||||
page[0] = cache_deq(cache);
|
||||
cache->num_pages--;
|
||||
|
||||
spin_unlock_irqrestore(&cache->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gnttab_page_cache_get);
|
||||
|
||||
void gnttab_page_cache_put(struct gnttab_page_cache *cache, struct page **page,
|
||||
unsigned int num)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int i;
|
||||
|
||||
spin_lock_irqsave(&cache->lock, flags);
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
cache_enq(cache, page[i]);
|
||||
cache->num_pages += num;
|
||||
|
||||
spin_unlock_irqrestore(&cache->lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gnttab_page_cache_put);
|
||||
|
||||
void gnttab_page_cache_shrink(struct gnttab_page_cache *cache, unsigned int num)
|
||||
{
|
||||
struct page *page[10];
|
||||
unsigned int i = 0;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&cache->lock, flags);
|
||||
|
||||
while (cache->num_pages > num) {
|
||||
page[i] = cache_deq(cache);
|
||||
cache->num_pages--;
|
||||
if (++i == ARRAY_SIZE(page)) {
|
||||
spin_unlock_irqrestore(&cache->lock, flags);
|
||||
gnttab_free_pages(i, page);
|
||||
i = 0;
|
||||
spin_lock_irqsave(&cache->lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&cache->lock, flags);
|
||||
|
||||
if (i != 0)
|
||||
gnttab_free_pages(i, page);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gnttab_page_cache_shrink);
|
||||
|
||||
void gnttab_pages_clear_private(int nr_pages, struct page **pages)
|
||||
{
|
||||
int i;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
#include <xen/xen.h>
|
||||
|
||||
static DEFINE_MUTEX(list_lock);
|
||||
static LIST_HEAD(page_list);
|
||||
static struct page *page_list;
|
||||
static unsigned int list_count;
|
||||
|
||||
static int fill_list(unsigned int nr_pages)
|
||||
|
|
@ -84,7 +84,8 @@ static int fill_list(unsigned int nr_pages)
|
|||
struct page *pg = virt_to_page(vaddr + PAGE_SIZE * i);
|
||||
|
||||
BUG_ON(!virt_addr_valid(vaddr + PAGE_SIZE * i));
|
||||
list_add(&pg->lru, &page_list);
|
||||
pg->zone_device_data = page_list;
|
||||
page_list = pg;
|
||||
list_count++;
|
||||
}
|
||||
|
||||
|
|
@ -118,12 +119,10 @@ int xen_alloc_unpopulated_pages(unsigned int nr_pages, struct page **pages)
|
|||
}
|
||||
|
||||
for (i = 0; i < nr_pages; i++) {
|
||||
struct page *pg = list_first_entry_or_null(&page_list,
|
||||
struct page,
|
||||
lru);
|
||||
struct page *pg = page_list;
|
||||
|
||||
BUG_ON(!pg);
|
||||
list_del(&pg->lru);
|
||||
page_list = pg->zone_device_data;
|
||||
list_count--;
|
||||
pages[i] = pg;
|
||||
|
||||
|
|
@ -134,7 +133,8 @@ int xen_alloc_unpopulated_pages(unsigned int nr_pages, struct page **pages)
|
|||
unsigned int j;
|
||||
|
||||
for (j = 0; j <= i; j++) {
|
||||
list_add(&pages[j]->lru, &page_list);
|
||||
pages[j]->zone_device_data = page_list;
|
||||
page_list = pages[j];
|
||||
list_count++;
|
||||
}
|
||||
goto out;
|
||||
|
|
@ -160,7 +160,8 @@ void xen_free_unpopulated_pages(unsigned int nr_pages, struct page **pages)
|
|||
|
||||
mutex_lock(&list_lock);
|
||||
for (i = 0; i < nr_pages; i++) {
|
||||
list_add(&pages[i]->lru, &page_list);
|
||||
pages[i]->zone_device_data = page_list;
|
||||
page_list = pages[i];
|
||||
list_count++;
|
||||
}
|
||||
mutex_unlock(&list_lock);
|
||||
|
|
@ -189,7 +190,8 @@ static int __init init(void)
|
|||
struct page *pg =
|
||||
pfn_to_page(xen_extra_mem[i].start_pfn + j);
|
||||
|
||||
list_add(&pg->lru, &page_list);
|
||||
pg->zone_device_data = page_list;
|
||||
page_list = pg;
|
||||
list_count++;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,6 +99,8 @@ struct vscsibk_info {
|
|||
struct list_head v2p_entry_lists;
|
||||
|
||||
wait_queue_head_t waiting_to_free;
|
||||
|
||||
struct gnttab_page_cache free_pages;
|
||||
};
|
||||
|
||||
/* theoretical maximum of grants for one request */
|
||||
|
|
@ -188,10 +190,6 @@ module_param_named(max_buffer_pages, scsiback_max_buffer_pages, int, 0644);
|
|||
MODULE_PARM_DESC(max_buffer_pages,
|
||||
"Maximum number of free pages to keep in backend buffer");
|
||||
|
||||
static DEFINE_SPINLOCK(free_pages_lock);
|
||||
static int free_pages_num;
|
||||
static LIST_HEAD(scsiback_free_pages);
|
||||
|
||||
/* Global spinlock to protect scsiback TPG list */
|
||||
static DEFINE_MUTEX(scsiback_mutex);
|
||||
static LIST_HEAD(scsiback_list);
|
||||
|
|
@ -207,41 +205,6 @@ static void scsiback_put(struct vscsibk_info *info)
|
|||
wake_up(&info->waiting_to_free);
|
||||
}
|
||||
|
||||
static void put_free_pages(struct page **page, int num)
|
||||
{
|
||||
unsigned long flags;
|
||||
int i = free_pages_num + num, n = num;
|
||||
|
||||
if (num == 0)
|
||||
return;
|
||||
if (i > scsiback_max_buffer_pages) {
|
||||
n = min(num, i - scsiback_max_buffer_pages);
|
||||
gnttab_free_pages(n, page + num - n);
|
||||
n = num - n;
|
||||
}
|
||||
spin_lock_irqsave(&free_pages_lock, flags);
|
||||
for (i = 0; i < n; i++)
|
||||
list_add(&page[i]->lru, &scsiback_free_pages);
|
||||
free_pages_num += n;
|
||||
spin_unlock_irqrestore(&free_pages_lock, flags);
|
||||
}
|
||||
|
||||
static int get_free_page(struct page **page)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&free_pages_lock, flags);
|
||||
if (list_empty(&scsiback_free_pages)) {
|
||||
spin_unlock_irqrestore(&free_pages_lock, flags);
|
||||
return gnttab_alloc_pages(1, page);
|
||||
}
|
||||
page[0] = list_first_entry(&scsiback_free_pages, struct page, lru);
|
||||
list_del(&page[0]->lru);
|
||||
free_pages_num--;
|
||||
spin_unlock_irqrestore(&free_pages_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long vaddr_page(struct page *page)
|
||||
{
|
||||
unsigned long pfn = page_to_pfn(page);
|
||||
|
|
@ -302,7 +265,8 @@ static void scsiback_fast_flush_area(struct vscsibk_pend *req)
|
|||
BUG_ON(err);
|
||||
}
|
||||
|
||||
put_free_pages(req->pages, req->n_grants);
|
||||
gnttab_page_cache_put(&req->info->free_pages, req->pages,
|
||||
req->n_grants);
|
||||
req->n_grants = 0;
|
||||
}
|
||||
|
||||
|
|
@ -445,8 +409,8 @@ static int scsiback_gnttab_data_map_list(struct vscsibk_pend *pending_req,
|
|||
struct vscsibk_info *info = pending_req->info;
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
if (get_free_page(pg + mapcount)) {
|
||||
put_free_pages(pg, mapcount);
|
||||
if (gnttab_page_cache_get(&info->free_pages, pg + mapcount)) {
|
||||
gnttab_page_cache_put(&info->free_pages, pg, mapcount);
|
||||
pr_err("no grant page\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
|
@ -796,6 +760,8 @@ static int scsiback_do_cmd_fn(struct vscsibk_info *info,
|
|||
cond_resched();
|
||||
}
|
||||
|
||||
gnttab_page_cache_shrink(&info->free_pages, scsiback_max_buffer_pages);
|
||||
|
||||
RING_FINAL_CHECK_FOR_REQUESTS(&info->ring, more_to_do);
|
||||
return more_to_do;
|
||||
}
|
||||
|
|
@ -1233,6 +1199,8 @@ static int scsiback_remove(struct xenbus_device *dev)
|
|||
|
||||
scsiback_release_translation_entry(info);
|
||||
|
||||
gnttab_page_cache_shrink(&info->free_pages, 0);
|
||||
|
||||
dev_set_drvdata(&dev->dev, NULL);
|
||||
|
||||
return 0;
|
||||
|
|
@ -1263,6 +1231,7 @@ static int scsiback_probe(struct xenbus_device *dev,
|
|||
info->irq = 0;
|
||||
INIT_LIST_HEAD(&info->v2p_entry_lists);
|
||||
spin_lock_init(&info->v2p_lock);
|
||||
gnttab_page_cache_init(&info->free_pages);
|
||||
|
||||
err = xenbus_printf(XBT_NIL, dev->nodename, "feature-sg-grant", "%u",
|
||||
SG_ALL);
|
||||
|
|
@ -1879,13 +1848,6 @@ static int __init scsiback_init(void)
|
|||
|
||||
static void __exit scsiback_exit(void)
|
||||
{
|
||||
struct page *page;
|
||||
|
||||
while (free_pages_num) {
|
||||
if (get_free_page(&page))
|
||||
BUG();
|
||||
gnttab_free_pages(1, &page);
|
||||
}
|
||||
target_unregister_template(&scsiback_ops);
|
||||
xenbus_unregister_driver(&scsiback_driver);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1284,7 +1284,7 @@ static bool io_identity_cow(struct io_kiocb *req)
|
|||
*/
|
||||
io_init_identity(id);
|
||||
if (creds)
|
||||
req->work.identity->creds = creds;
|
||||
id->creds = creds;
|
||||
|
||||
/* add one for this request */
|
||||
refcount_inc(&id->count);
|
||||
|
|
@ -9183,6 +9183,7 @@ static int io_uring_get_fd(struct io_ring_ctx *ctx)
|
|||
{
|
||||
struct file *file;
|
||||
int ret;
|
||||
int fd;
|
||||
|
||||
#if defined(CONFIG_UNIX)
|
||||
ret = sock_create_kern(&init_net, PF_UNIX, SOCK_RAW, IPPROTO_IP,
|
||||
|
|
@ -9194,12 +9195,12 @@ static int io_uring_get_fd(struct io_ring_ctx *ctx)
|
|||
ret = get_unused_fd_flags(O_RDWR | O_CLOEXEC);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
fd = ret;
|
||||
|
||||
file = anon_inode_getfile("[io_uring]", &io_uring_fops, ctx,
|
||||
O_RDWR | O_CLOEXEC);
|
||||
if (IS_ERR(file)) {
|
||||
err_fd:
|
||||
put_unused_fd(ret);
|
||||
put_unused_fd(fd);
|
||||
ret = PTR_ERR(file);
|
||||
goto err;
|
||||
}
|
||||
|
|
@ -9207,12 +9208,14 @@ static int io_uring_get_fd(struct io_ring_ctx *ctx)
|
|||
#if defined(CONFIG_UNIX)
|
||||
ctx->ring_sock->file = file;
|
||||
#endif
|
||||
if (unlikely(io_uring_add_task_file(ctx, file))) {
|
||||
file = ERR_PTR(-ENOMEM);
|
||||
goto err_fd;
|
||||
ret = io_uring_add_task_file(ctx, file);
|
||||
if (ret) {
|
||||
fput(file);
|
||||
put_unused_fd(fd);
|
||||
goto err;
|
||||
}
|
||||
fd_install(ret, file);
|
||||
return ret;
|
||||
fd_install(fd, file);
|
||||
return fd;
|
||||
err:
|
||||
#if defined(CONFIG_UNIX)
|
||||
sock_release(ctx->ring_sock);
|
||||
|
|
|
|||
|
|
@ -198,6 +198,23 @@ void gnttab_free_auto_xlat_frames(void);
|
|||
int gnttab_alloc_pages(int nr_pages, struct page **pages);
|
||||
void gnttab_free_pages(int nr_pages, struct page **pages);
|
||||
|
||||
struct gnttab_page_cache {
|
||||
spinlock_t lock;
|
||||
#ifdef CONFIG_XEN_UNPOPULATED_ALLOC
|
||||
struct page *pages;
|
||||
#else
|
||||
struct list_head pages;
|
||||
#endif
|
||||
unsigned int num_pages;
|
||||
};
|
||||
|
||||
void gnttab_page_cache_init(struct gnttab_page_cache *cache);
|
||||
int gnttab_page_cache_get(struct gnttab_page_cache *cache, struct page **page);
|
||||
void gnttab_page_cache_put(struct gnttab_page_cache *cache, struct page **page,
|
||||
unsigned int num);
|
||||
void gnttab_page_cache_shrink(struct gnttab_page_cache *cache,
|
||||
unsigned int num);
|
||||
|
||||
#ifdef CONFIG_XEN_GRANT_DMA_ALLOC
|
||||
struct gnttab_dma_alloc_args {
|
||||
/* Device for which DMA memory will be/was allocated. */
|
||||
|
|
|
|||
|
|
@ -742,7 +742,11 @@ class DebugfsProvider(Provider):
|
|||
The fields are all available KVM debugfs files
|
||||
|
||||
"""
|
||||
return self.walkdir(PATH_DEBUGFS_KVM)[2]
|
||||
exempt_list = ['halt_poll_fail_ns', 'halt_poll_success_ns']
|
||||
fields = [field for field in self.walkdir(PATH_DEBUGFS_KVM)[2]
|
||||
if field not in exempt_list]
|
||||
|
||||
return fields
|
||||
|
||||
def update_fields(self, fields_filter):
|
||||
"""Refresh fields, applying fields_filter"""
|
||||
|
|
|
|||
|
|
@ -156,14 +156,23 @@ static void guest_code_move_memory_region(void)
|
|||
GUEST_SYNC(0);
|
||||
|
||||
/*
|
||||
* Spin until the memory region is moved to a misaligned address. This
|
||||
* may or may not trigger MMIO, as the window where the memslot is
|
||||
* invalid is quite small.
|
||||
* Spin until the memory region starts getting moved to a
|
||||
* misaligned address.
|
||||
* Every region move may or may not trigger MMIO, as the
|
||||
* window where the memslot is invalid is usually quite small.
|
||||
*/
|
||||
val = guest_spin_on_val(0);
|
||||
GUEST_ASSERT_1(val == 1 || val == MMIO_VAL, val);
|
||||
|
||||
/* Spin until the memory region is realigned. */
|
||||
/* Spin until the misaligning memory region move completes. */
|
||||
val = guest_spin_on_val(MMIO_VAL);
|
||||
GUEST_ASSERT_1(val == 1 || val == 0, val);
|
||||
|
||||
/* Spin until the memory region starts to get re-aligned. */
|
||||
val = guest_spin_on_val(0);
|
||||
GUEST_ASSERT_1(val == 1 || val == MMIO_VAL, val);
|
||||
|
||||
/* Spin until the re-aligning memory region move completes. */
|
||||
val = guest_spin_on_val(MMIO_VAL);
|
||||
GUEST_ASSERT_1(val == 1, val);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user