Skip to content

Commit

Permalink
Merge tag 'char-misc-5.1-rc3' of git://git.kernel.org/pub/scm/linux/k…
Browse files Browse the repository at this point in the history
…ernel/git/gregkh/char-misc

Pull char/misc driver fixes from Greg KH:
 "Here are some binder, habanalabs, and vboxguest driver fixes for
  5.1-rc3.

  The Binder fixes resolve some reported issues found by testing, first
  by the selinux developers, and then earlier today by syzbot.

  The habanalabs fixes are all minor, resolving a number of tiny things.

  The vboxguest patches are a bit larger. They resolve the fact that
  virtual box decided to change their api in their latest release in a
  way that broke the existing kernel code, despite saying that they were
  never going to do that. So this is a bit of a "new feature", but is
  good to get merged so that 5.1 will work with the latest release. The
  changes are not large and of course virtual box "swears" they will not
  break this again, but no one is holding their breath here.

  All of these have been in linux-next for a while with no reported
  issues"

* tag 'char-misc-5.1-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc:
  virt: vbox: Implement passing requestor info to the host for VirtualBox 6.0.x
  binder: fix race between munmap() and direct reclaim
  binder: fix BUG_ON found by selinux-testsuite
  habanalabs: cast to expected type
  habanalabs: prevent host crash during suspend/resume
  habanalabs: perform accounting for active CS
  habanalabs: fix mapping with page size bigger than 4KB
  habanalabs: complete user context cleanup before hard reset
  habanalabs: fix bug when mapping very large memory area
  habanalabs: fix MMU number of pages calculation
  • Loading branch information
torvalds committed Mar 29, 2019
2 parents 3467b90 + 0532a1b commit 6f51092
Show file tree
Hide file tree
Showing 18 changed files with 324 additions and 184 deletions.
3 changes: 2 additions & 1 deletion drivers/android/binder.c
Original file line number Diff line number Diff line change
Expand Up @@ -2057,7 +2057,8 @@ static size_t binder_get_object(struct binder_proc *proc,
size_t object_size = 0;

read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset);
if (read_size < sizeof(*hdr) || !IS_ALIGNED(offset, sizeof(u32)))
if (offset > buffer->data_size || read_size < sizeof(*hdr) ||
!IS_ALIGNED(offset, sizeof(u32)))
return 0;
binder_alloc_copy_from_buffer(&proc->alloc, object, buffer,
offset, read_size);
Expand Down
18 changes: 8 additions & 10 deletions drivers/android/binder_alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -927,14 +927,13 @@ enum lru_status binder_alloc_free_page(struct list_head *item,

index = page - alloc->pages;
page_addr = (uintptr_t)alloc->buffer + index * PAGE_SIZE;

mm = alloc->vma_vm_mm;
if (!mmget_not_zero(mm))
goto err_mmget;
if (!down_write_trylock(&mm->mmap_sem))
goto err_down_write_mmap_sem_failed;
vma = binder_alloc_get_vma(alloc);
if (vma) {
if (!mmget_not_zero(alloc->vma_vm_mm))
goto err_mmget;
mm = alloc->vma_vm_mm;
if (!down_read_trylock(&mm->mmap_sem))
goto err_down_write_mmap_sem_failed;
}

list_lru_isolate(lru, item);
spin_unlock(lock);
Expand All @@ -945,10 +944,9 @@ enum lru_status binder_alloc_free_page(struct list_head *item,
zap_page_range(vma, page_addr, PAGE_SIZE);

trace_binder_unmap_user_end(alloc, index);

up_read(&mm->mmap_sem);
mmput(mm);
}
up_write(&mm->mmap_sem);
mmput(mm);

trace_binder_unmap_kernel_start(alloc, index);

Expand Down
6 changes: 6 additions & 0 deletions drivers/misc/habanalabs/command_submission.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,12 @@ static void cs_do_release(struct kref *ref)

/* We also need to update CI for internal queues */
if (cs->submitted) {
int cs_cnt = atomic_dec_return(&hdev->cs_active_cnt);

WARN_ONCE((cs_cnt < 0),
"hl%d: error in CS active cnt %d\n",
hdev->id, cs_cnt);

hl_int_hw_queue_update_ci(cs);

spin_lock(&hdev->hw_queues_mirror_lock);
Expand Down
7 changes: 4 additions & 3 deletions drivers/misc/habanalabs/debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ static int vm_show(struct seq_file *s, void *data)
struct hl_vm_phys_pg_pack *phys_pg_pack = NULL;
enum vm_type_t *vm_type;
bool once = true;
u64 j;
int i;

if (!dev_entry->hdev->mmu_enable)
Expand Down Expand Up @@ -260,7 +261,7 @@ static int vm_show(struct seq_file *s, void *data)
} else {
phys_pg_pack = hnode->ptr;
seq_printf(s,
" 0x%-14llx %-10u %-4u\n",
" 0x%-14llx %-10llu %-4u\n",
hnode->vaddr, phys_pg_pack->total_size,
phys_pg_pack->handle);
}
Expand All @@ -282,9 +283,9 @@ static int vm_show(struct seq_file *s, void *data)
phys_pg_pack->page_size);
seq_puts(s, " physical address\n");
seq_puts(s, "---------------------\n");
for (i = 0 ; i < phys_pg_pack->npages ; i++) {
for (j = 0 ; j < phys_pg_pack->npages ; j++) {
seq_printf(s, " 0x%-14llx\n",
phys_pg_pack->pages[i]);
phys_pg_pack->pages[j]);
}
}
spin_unlock(&vm->idr_lock);
Expand Down
71 changes: 66 additions & 5 deletions drivers/misc/habanalabs/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include <linux/sched/signal.h>
#include <linux/hwmon.h>

#define HL_PLDM_PENDING_RESET_PER_SEC (HL_PENDING_RESET_PER_SEC * 10)

bool hl_device_disabled_or_in_reset(struct hl_device *hdev)
{
if ((hdev->disabled) || (atomic_read(&hdev->in_reset)))
Expand Down Expand Up @@ -216,6 +218,7 @@ static int device_early_init(struct hl_device *hdev)
spin_lock_init(&hdev->hw_queues_mirror_lock);
atomic_set(&hdev->in_reset, 0);
atomic_set(&hdev->fd_open_cnt, 0);
atomic_set(&hdev->cs_active_cnt, 0);

return 0;

Expand Down Expand Up @@ -413,6 +416,27 @@ int hl_device_suspend(struct hl_device *hdev)

pci_save_state(hdev->pdev);

/* Block future CS/VM/JOB completion operations */
rc = atomic_cmpxchg(&hdev->in_reset, 0, 1);
if (rc) {
dev_err(hdev->dev, "Can't suspend while in reset\n");
return -EIO;
}

/* This blocks all other stuff that is not blocked by in_reset */
hdev->disabled = true;

/*
* Flush anyone that is inside the critical section of enqueue
* jobs to the H/W
*/
hdev->asic_funcs->hw_queues_lock(hdev);
hdev->asic_funcs->hw_queues_unlock(hdev);

/* Flush processes that are sending message to CPU */
mutex_lock(&hdev->send_cpu_message_lock);
mutex_unlock(&hdev->send_cpu_message_lock);

rc = hdev->asic_funcs->suspend(hdev);
if (rc)
dev_err(hdev->dev,
Expand Down Expand Up @@ -440,31 +464,55 @@ int hl_device_resume(struct hl_device *hdev)

pci_set_power_state(hdev->pdev, PCI_D0);
pci_restore_state(hdev->pdev);
rc = pci_enable_device(hdev->pdev);
rc = pci_enable_device_mem(hdev->pdev);
if (rc) {
dev_err(hdev->dev,
"Failed to enable PCI device in resume\n");
return rc;
}

pci_set_master(hdev->pdev);

rc = hdev->asic_funcs->resume(hdev);
if (rc) {
dev_err(hdev->dev,
"Failed to enable PCI access from device CPU\n");
return rc;
dev_err(hdev->dev, "Failed to resume device after suspend\n");
goto disable_device;
}


hdev->disabled = false;
atomic_set(&hdev->in_reset, 0);

rc = hl_device_reset(hdev, true, false);
if (rc) {
dev_err(hdev->dev, "Failed to reset device during resume\n");
goto disable_device;
}

return 0;

disable_device:
pci_clear_master(hdev->pdev);
pci_disable_device(hdev->pdev);

return rc;
}

static void hl_device_hard_reset_pending(struct work_struct *work)
{
struct hl_device_reset_work *device_reset_work =
container_of(work, struct hl_device_reset_work, reset_work);
struct hl_device *hdev = device_reset_work->hdev;
u16 pending_cnt = HL_PENDING_RESET_PER_SEC;
u16 pending_total, pending_cnt;
struct task_struct *task = NULL;

if (hdev->pldm)
pending_total = HL_PLDM_PENDING_RESET_PER_SEC;
else
pending_total = HL_PENDING_RESET_PER_SEC;

pending_cnt = pending_total;

/* Flush all processes that are inside hl_open */
mutex_lock(&hdev->fd_open_cnt_lock);

Expand All @@ -489,6 +537,19 @@ static void hl_device_hard_reset_pending(struct work_struct *work)
}
}

pending_cnt = pending_total;

while ((atomic_read(&hdev->fd_open_cnt)) && (pending_cnt)) {

pending_cnt--;

ssleep(1);
}

if (atomic_read(&hdev->fd_open_cnt))
dev_crit(hdev->dev,
"Going to hard reset with open user contexts\n");

mutex_unlock(&hdev->fd_open_cnt_lock);

hl_device_reset(hdev, true, true);
Expand Down
65 changes: 2 additions & 63 deletions drivers/misc/habanalabs/goya/goya.c
Original file line number Diff line number Diff line change
Expand Up @@ -1201,15 +1201,6 @@ static int goya_stop_external_queues(struct hl_device *hdev)
return retval;
}

static void goya_resume_external_queues(struct hl_device *hdev)
{
WREG32(mmDMA_QM_0_GLBL_CFG1, 0);
WREG32(mmDMA_QM_1_GLBL_CFG1, 0);
WREG32(mmDMA_QM_2_GLBL_CFG1, 0);
WREG32(mmDMA_QM_3_GLBL_CFG1, 0);
WREG32(mmDMA_QM_4_GLBL_CFG1, 0);
}

/*
* goya_init_cpu_queues - Initialize PQ/CQ/EQ of CPU
*
Expand Down Expand Up @@ -2178,36 +2169,6 @@ static int goya_stop_internal_queues(struct hl_device *hdev)
return retval;
}

static void goya_resume_internal_queues(struct hl_device *hdev)
{
WREG32(mmMME_QM_GLBL_CFG1, 0);
WREG32(mmMME_CMDQ_GLBL_CFG1, 0);

WREG32(mmTPC0_QM_GLBL_CFG1, 0);
WREG32(mmTPC0_CMDQ_GLBL_CFG1, 0);

WREG32(mmTPC1_QM_GLBL_CFG1, 0);
WREG32(mmTPC1_CMDQ_GLBL_CFG1, 0);

WREG32(mmTPC2_QM_GLBL_CFG1, 0);
WREG32(mmTPC2_CMDQ_GLBL_CFG1, 0);

WREG32(mmTPC3_QM_GLBL_CFG1, 0);
WREG32(mmTPC3_CMDQ_GLBL_CFG1, 0);

WREG32(mmTPC4_QM_GLBL_CFG1, 0);
WREG32(mmTPC4_CMDQ_GLBL_CFG1, 0);

WREG32(mmTPC5_QM_GLBL_CFG1, 0);
WREG32(mmTPC5_CMDQ_GLBL_CFG1, 0);

WREG32(mmTPC6_QM_GLBL_CFG1, 0);
WREG32(mmTPC6_CMDQ_GLBL_CFG1, 0);

WREG32(mmTPC7_QM_GLBL_CFG1, 0);
WREG32(mmTPC7_CMDQ_GLBL_CFG1, 0);
}

static void goya_dma_stall(struct hl_device *hdev)
{
WREG32(mmDMA_QM_0_GLBL_CFG1, 1 << DMA_QM_0_GLBL_CFG1_DMA_STOP_SHIFT);
Expand Down Expand Up @@ -2905,20 +2866,6 @@ int goya_suspend(struct hl_device *hdev)
{
int rc;

rc = goya_stop_internal_queues(hdev);

if (rc) {
dev_err(hdev->dev, "failed to stop internal queues\n");
return rc;
}

rc = goya_stop_external_queues(hdev);

if (rc) {
dev_err(hdev->dev, "failed to stop external queues\n");
return rc;
}

rc = goya_send_pci_access_msg(hdev, ARMCP_PACKET_DISABLE_PCI_ACCESS);
if (rc)
dev_err(hdev->dev, "Failed to disable PCI access from CPU\n");
Expand All @@ -2928,15 +2875,7 @@ int goya_suspend(struct hl_device *hdev)

int goya_resume(struct hl_device *hdev)
{
int rc;

goya_resume_external_queues(hdev);
goya_resume_internal_queues(hdev);

rc = goya_send_pci_access_msg(hdev, ARMCP_PACKET_ENABLE_PCI_ACCESS);
if (rc)
dev_err(hdev->dev, "Failed to enable PCI access from CPU\n");
return rc;
return goya_init_iatu(hdev);
}

static int goya_cb_mmap(struct hl_device *hdev, struct vm_area_struct *vma,
Expand Down Expand Up @@ -3070,7 +3009,7 @@ void *goya_get_int_queue_base(struct hl_device *hdev, u32 queue_id,

*dma_handle = hdev->asic_prop.sram_base_address;

base = hdev->pcie_bar[SRAM_CFG_BAR_ID];
base = (void *) hdev->pcie_bar[SRAM_CFG_BAR_ID];

switch (queue_id) {
case GOYA_QUEUE_ID_MME:
Expand Down
21 changes: 12 additions & 9 deletions drivers/misc/habanalabs/habanalabs.h
Original file line number Diff line number Diff line change
Expand Up @@ -793,11 +793,11 @@ struct hl_vm_hash_node {
* struct hl_vm_phys_pg_pack - physical page pack.
* @vm_type: describes the type of the virtual area descriptor.
* @pages: the physical page array.
* @npages: num physical pages in the pack.
* @total_size: total size of all the pages in this list.
* @mapping_cnt: number of shared mappings.
* @asid: the context related to this list.
* @npages: num physical pages in the pack.
* @page_size: size of each page in the pack.
* @total_size: total size of all the pages in this list.
* @flags: HL_MEM_* flags related to this list.
* @handle: the provided handle related to this list.
* @offset: offset from the first page.
Expand All @@ -807,11 +807,11 @@ struct hl_vm_hash_node {
struct hl_vm_phys_pg_pack {
enum vm_type_t vm_type; /* must be first */
u64 *pages;
u64 npages;
u64 total_size;
atomic_t mapping_cnt;
u32 asid;
u32 npages;
u32 page_size;
u32 total_size;
u32 flags;
u32 handle;
u32 offset;
Expand Down Expand Up @@ -1056,13 +1056,15 @@ struct hl_device_reset_work {
* @cb_pool_lock: protects the CB pool.
* @user_ctx: current user context executing.
* @dram_used_mem: current DRAM memory consumption.
* @in_reset: is device in reset flow.
* @curr_pll_profile: current PLL profile.
* @fd_open_cnt: number of open user processes.
* @timeout_jiffies: device CS timeout value.
* @max_power: the max power of the device, as configured by the sysadmin. This
* value is saved so in case of hard-reset, KMD will restore this
* value and update the F/W after the re-initialization
* @in_reset: is device in reset flow.
* @curr_pll_profile: current PLL profile.
* @fd_open_cnt: number of open user processes.
* @cs_active_cnt: number of active command submissions on this device (active
* means already in H/W queues)
* @major: habanalabs KMD major.
* @high_pll: high PLL profile frequency.
* @soft_reset_cnt: number of soft reset since KMD loading.
Expand Down Expand Up @@ -1128,11 +1130,12 @@ struct hl_device {
struct hl_ctx *user_ctx;

atomic64_t dram_used_mem;
u64 timeout_jiffies;
u64 max_power;
atomic_t in_reset;
atomic_t curr_pll_profile;
atomic_t fd_open_cnt;
u64 timeout_jiffies;
u64 max_power;
atomic_t cs_active_cnt;
u32 major;
u32 high_pll;
u32 soft_reset_cnt;
Expand Down
5 changes: 3 additions & 2 deletions drivers/misc/habanalabs/hw_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -370,12 +370,13 @@ int hl_hw_queue_schedule_cs(struct hl_cs *cs)
spin_unlock(&hdev->hw_queues_mirror_lock);
}

list_for_each_entry_safe(job, tmp, &cs->job_list, cs_node) {
atomic_inc(&hdev->cs_active_cnt);

list_for_each_entry_safe(job, tmp, &cs->job_list, cs_node)
if (job->ext_queue)
ext_hw_queue_schedule_job(job);
else
int_hw_queue_schedule_job(job);
}

cs->submitted = true;

Expand Down
Loading

0 comments on commit 6f51092

Please sign in to comment.