diff options
author | Thomas Zimmermann <tzimmermann@suse.de> | 2023-01-31 14:18:33 +0100 |
---|---|---|
committer | Thomas Zimmermann <tzimmermann@suse.de> | 2023-01-31 14:18:33 +0100 |
commit | df5bf3b942a8d344bd9cbbe6ac31c9a2ea1557a4 (patch) | |
tree | bfbcbe56b9f4f8b1e44242b80800a68b2ae5b2d6 /drivers | |
parent | 532a38292c7213aa6d950e6a1b86659d08b5aa67 (diff) | |
parent | aebd8f0c6f8280ba35bc989f4a9ea47469d3589a (diff) |
Merge drm/drm-next into drm-misc-next
Backmerging to get v6.2-rc6.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Diffstat (limited to 'drivers')
1161 files changed, 17932 insertions, 9959 deletions
diff --git a/drivers/accel/Kconfig b/drivers/accel/Kconfig index 2d88f2afee8c..c437206aa3f1 100644 --- a/drivers/accel/Kconfig +++ b/drivers/accel/Kconfig @@ -24,6 +24,7 @@ menuconfig DRM_ACCEL different device files, called accel/accel* (in /dev, sysfs and debugfs). +source "drivers/accel/habanalabs/Kconfig" source "drivers/accel/ivpu/Kconfig" endif diff --git a/drivers/accel/Makefile b/drivers/accel/Makefile index b1036dbc0ba4..07aa77aed1c8 100644 --- a/drivers/accel/Makefile +++ b/drivers/accel/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only +obj-y += habanalabs/ obj-y += ivpu/ diff --git a/drivers/misc/habanalabs/Kconfig b/drivers/accel/habanalabs/Kconfig index bd01d0d940c0..be85336107f9 100644 --- a/drivers/misc/habanalabs/Kconfig +++ b/drivers/accel/habanalabs/Kconfig @@ -3,8 +3,10 @@ # HabanaLabs AI accelerators driver # -config HABANA_AI - tristate "HabanaAI accelerators (habanalabs)" +config DRM_ACCEL_HABANALABS + tristate "HabanaLabs AI accelerators" + depends on DRM_ACCEL + depends on X86_64 depends on PCI && HAS_IOMEM select GENERIC_ALLOCATOR select HWMON @@ -19,7 +21,7 @@ config HABANA_AI the user to submit workloads to the devices. The user-space interface is described in - include/uapi/misc/habanalabs.h + include/uapi/drm/habanalabs_accel.h If unsure, say N. diff --git a/drivers/misc/habanalabs/Makefile b/drivers/accel/habanalabs/Makefile index a48a9e0969ed..98510cdd5066 100644 --- a/drivers/misc/habanalabs/Makefile +++ b/drivers/accel/habanalabs/Makefile @@ -3,7 +3,7 @@ # Makefile for HabanaLabs AI accelerators driver # -obj-$(CONFIG_HABANA_AI) := habanalabs.o +obj-$(CONFIG_DRM_ACCEL_HABANALABS) := habanalabs.o include $(src)/common/Makefile habanalabs-y += $(HL_COMMON_FILES) diff --git a/drivers/misc/habanalabs/common/Makefile b/drivers/accel/habanalabs/common/Makefile index e6abffea9f87..e6abffea9f87 100644 --- a/drivers/misc/habanalabs/common/Makefile +++ b/drivers/accel/habanalabs/common/Makefile diff --git a/drivers/misc/habanalabs/common/asid.c b/drivers/accel/habanalabs/common/asid.c index c9c2619cc43d..c9c2619cc43d 100644 --- a/drivers/misc/habanalabs/common/asid.c +++ b/drivers/accel/habanalabs/common/asid.c diff --git a/drivers/misc/habanalabs/common/command_buffer.c b/drivers/accel/habanalabs/common/command_buffer.c index 2b332991ac6a..3a0535ac28b1 100644 --- a/drivers/misc/habanalabs/common/command_buffer.c +++ b/drivers/accel/habanalabs/common/command_buffer.c @@ -5,7 +5,7 @@ * All Rights Reserved. */ -#include <uapi/misc/habanalabs.h> +#include <uapi/drm/habanalabs_accel.h> #include "habanalabs.h" #include <linux/mm.h> @@ -88,6 +88,7 @@ static void cb_fini(struct hl_device *hdev, struct hl_cb *cb) static void cb_do_release(struct hl_device *hdev, struct hl_cb *cb) { if (cb->is_pool) { + atomic_set(&cb->is_handle_destroyed, 0); spin_lock(&hdev->cb_pool_lock); list_add(&cb->pool_list, &hdev->cb_pool); spin_unlock(&hdev->cb_pool_lock); @@ -298,8 +299,25 @@ int hl_cb_create(struct hl_device *hdev, struct hl_mem_mgr *mmg, int hl_cb_destroy(struct hl_mem_mgr *mmg, u64 cb_handle) { + struct hl_cb *cb; int rc; + cb = hl_cb_get(mmg, cb_handle); + if (!cb) { + dev_dbg(mmg->dev, "CB destroy failed, no CB was found for handle %#llx\n", + cb_handle); + return -EINVAL; + } + + /* Make sure that CB handle isn't destroyed more than once */ + rc = atomic_cmpxchg(&cb->is_handle_destroyed, 0, 1); + hl_cb_put(cb); + if (rc) { + dev_dbg(mmg->dev, "CB destroy failed, handle %#llx was already destroyed\n", + cb_handle); + return -EINVAL; + } + rc = hl_mmap_mem_buf_put_handle(mmg, cb_handle); if (rc < 0) return rc; /* Invalid handle */ @@ -350,7 +368,7 @@ int hl_cb_ioctl(struct hl_fpriv *hpriv, void *data) int rc; if (!hl_device_operational(hdev, &status)) { - dev_warn_ratelimited(hdev->dev, + dev_dbg_ratelimited(hdev->dev, "Device is %s. Can't execute CB IOCTL\n", hdev->status[status]); return -EBUSY; diff --git a/drivers/misc/habanalabs/common/command_submission.c b/drivers/accel/habanalabs/common/command_submission.c index ea0e5101c10e..8270db0a72a2 100644 --- a/drivers/misc/habanalabs/common/command_submission.c +++ b/drivers/accel/habanalabs/common/command_submission.c @@ -5,7 +5,7 @@ * All Rights Reserved. */ -#include <uapi/misc/habanalabs.h> +#include <uapi/drm/habanalabs_accel.h> #include "habanalabs.h" #include <linux/uaccess.h> @@ -13,7 +13,8 @@ #define HL_CS_FLAGS_TYPE_MASK (HL_CS_FLAGS_SIGNAL | HL_CS_FLAGS_WAIT | \ HL_CS_FLAGS_COLLECTIVE_WAIT | HL_CS_FLAGS_RESERVE_SIGNALS_ONLY | \ - HL_CS_FLAGS_UNRESERVE_SIGNALS_ONLY | HL_CS_FLAGS_ENGINE_CORE_COMMAND) + HL_CS_FLAGS_UNRESERVE_SIGNALS_ONLY | HL_CS_FLAGS_ENGINE_CORE_COMMAND | \ + HL_CS_FLAGS_FLUSH_PCI_HBW_WRITES) #define MAX_TS_ITER_NUM 10 @@ -397,8 +398,16 @@ static void hl_complete_job(struct hl_device *hdev, struct hl_cs_job *job) * flow by calling 'hl_hw_queue_update_ci'. */ if (cs_needs_completion(cs) && - (job->queue_type == QUEUE_TYPE_EXT || job->queue_type == QUEUE_TYPE_HW)) + (job->queue_type == QUEUE_TYPE_EXT || job->queue_type == QUEUE_TYPE_HW)) { + + /* In CS based completions, the timestamp is already available, + * so no need to extract it from job + */ + if (hdev->asic_prop.completion_mode == HL_COMPLETION_MODE_JOB) + cs->completion_timestamp = job->timestamp; + cs_put(cs); + } hl_cs_job_put(job); } @@ -775,7 +784,7 @@ out: } if (cs->timestamp) { - cs->fence->timestamp = ktime_get(); + cs->fence->timestamp = cs->completion_timestamp; hl_push_cs_outcome(hdev, &cs->ctx->outcome_store, cs->sequence, cs->fence->timestamp, cs->fence->error); } @@ -1117,6 +1126,27 @@ void hl_release_pending_user_interrupts(struct hl_device *hdev) wake_pending_user_interrupt_threads(interrupt); } +static void force_complete_cs(struct hl_device *hdev) +{ + struct hl_cs *cs; + + spin_lock(&hdev->cs_mirror_lock); + + list_for_each_entry(cs, &hdev->cs_mirror_list, mirror_node) { + cs->fence->error = -EIO; + complete_all(&cs->fence->completion); + } + + spin_unlock(&hdev->cs_mirror_lock); +} + +void hl_abort_waitings_for_completion(struct hl_device *hdev) +{ + force_complete_cs(hdev); + force_complete_multi_cs(hdev); + hl_release_pending_user_interrupts(hdev); +} + static void job_wq_completion(struct work_struct *work) { struct hl_cs_job *job = container_of(work, struct hl_cs_job, @@ -1274,6 +1304,8 @@ static enum hl_cs_type hl_cs_get_cs_type(u32 cs_type_flags) return CS_UNRESERVE_SIGNALS; else if (cs_type_flags & HL_CS_FLAGS_ENGINE_CORE_COMMAND) return CS_TYPE_ENGINE_CORE; + else if (cs_type_flags & HL_CS_FLAGS_FLUSH_PCI_HBW_WRITES) + return CS_TYPE_FLUSH_PCI_HBW_WRITES; else return CS_TYPE_DEFAULT; } @@ -1286,6 +1318,13 @@ static int hl_cs_sanity_checks(struct hl_fpriv *hpriv, union hl_cs_args *args) enum hl_device_status status; enum hl_cs_type cs_type; bool is_sync_stream; + int i; + + for (i = 0 ; i < sizeof(args->in.pad) ; i++) + if (args->in.pad[i]) { + dev_dbg(hdev->dev, "Padding bytes must be 0\n"); + return -EINVAL; + } if (!hl_device_operational(hdev, &status)) { return -EBUSY; @@ -2422,6 +2461,21 @@ static int cs_ioctl_engine_cores(struct hl_fpriv *hpriv, u64 engine_cores, return rc; } +static int cs_ioctl_flush_pci_hbw_writes(struct hl_fpriv *hpriv) +{ + struct hl_device *hdev = hpriv->hdev; + struct asic_fixed_properties *prop = &hdev->asic_prop; + + if (!prop->hbw_flush_reg) { + dev_dbg(hdev->dev, "HBW flush is not supported\n"); + return -EOPNOTSUPP; + } + + RREG32(prop->hbw_flush_reg); + + return 0; +} + int hl_cs_ioctl(struct hl_fpriv *hpriv, void *data) { union hl_cs_args *args = data; @@ -2478,6 +2532,9 @@ int hl_cs_ioctl(struct hl_fpriv *hpriv, void *data) rc = cs_ioctl_engine_cores(hpriv, args->in.engine_cores, args->in.num_engine_cores, args->in.core_command); break; + case CS_TYPE_FLUSH_PCI_HBW_WRITES: + rc = cs_ioctl_flush_pci_hbw_writes(hpriv); + break; default: rc = cs_ioctl_default(hpriv, chunks, num_chunks, &cs_seq, args->in.cs_flags, @@ -2569,7 +2626,9 @@ report_results: *status = CS_WAIT_STATUS_BUSY; } - if (error == -ETIMEDOUT || error == -EIO) + if (completion_rc == -ERESTARTSYS) + rc = completion_rc; + else if (error == -ETIMEDOUT || error == -EIO) rc = error; return rc; @@ -2699,7 +2758,8 @@ static int hl_cs_poll_fences(struct multi_cs_data *mcs_data, struct multi_cs_com break; default: dev_err(hdev->dev, "Invalid fence status\n"); - return -EINVAL; + rc = -EINVAL; + break; } } @@ -2828,6 +2888,9 @@ static int hl_wait_multi_cs_completion(struct multi_cs_data *mcs_data, if (completion_rc > 0) mcs_data->timestamp = mcs_compl->timestamp; + if (completion_rc == -ERESTARTSYS) + return completion_rc; + mcs_data->wait_status = completion_rc; return 0; @@ -2870,7 +2933,13 @@ static int hl_multi_cs_wait_ioctl(struct hl_fpriv *hpriv, void *data) u32 size_to_copy; u64 *cs_seq_arr; u8 seq_arr_len; - int rc; + int rc, i; + + for (i = 0 ; i < sizeof(args->in.pad) ; i++) + if (args->in.pad[i]) { + dev_dbg(hdev->dev, "Padding bytes must be 0\n"); + return -EINVAL; + } if (!hdev->supports_wait_for_multi_cs) { dev_err(hdev->dev, "Wait for multi CS is not supported\n"); @@ -2973,15 +3042,15 @@ put_ctx: free_seq_arr: kfree(cs_seq_arr); - if (rc) - return rc; - - if (mcs_data.wait_status == -ERESTARTSYS) { + if (rc == -ERESTARTSYS) { dev_err_ratelimited(hdev->dev, "user process got signal while waiting for Multi-CS\n"); - return -EINTR; + rc = -EINTR; } + if (rc) + return rc; + /* update output args */ memset(args, 0, sizeof(*args)); @@ -3119,19 +3188,18 @@ start_over: goto start_over; } } else { + /* Fill up the new registration node info */ + requested_offset_record->ts_reg_info.buf = buf; + requested_offset_record->ts_reg_info.cq_cb = cq_cb; + requested_offset_record->ts_reg_info.timestamp_kernel_addr = + (u64 *) ts_buff->user_buff_address + ts_offset; + requested_offset_record->cq_kernel_addr = + (u64 *) cq_cb->kernel_address + cq_offset; + requested_offset_record->cq_target_value = target_value; + spin_unlock_irqrestore(wait_list_lock, flags); } - /* Fill up the new registration node info */ - requested_offset_record->ts_reg_info.in_use = 1; - requested_offset_record->ts_reg_info.buf = buf; - requested_offset_record->ts_reg_info.cq_cb = cq_cb; - requested_offset_record->ts_reg_info.timestamp_kernel_addr = - (u64 *) ts_buff->user_buff_address + ts_offset; - requested_offset_record->cq_kernel_addr = - (u64 *) cq_cb->kernel_address + cq_offset; - requested_offset_record->cq_target_value = target_value; - *pend = requested_offset_record; dev_dbg(buf->mmg->dev, "Found available node in TS kernel CB %p\n", @@ -3179,7 +3247,7 @@ static int _hl_interrupt_wait_ioctl(struct hl_device *hdev, struct hl_ctx *ctx, goto put_cq_cb; } - /* Find first available record */ + /* get ts buffer record */ rc = ts_buff_get_kernel_ts_record(buf, cq_cb, ts_offset, cq_counters_offset, target_value, &interrupt->wait_list_lock, &pend); @@ -3227,7 +3295,19 @@ static int _hl_interrupt_wait_ioctl(struct hl_device *hdev, struct hl_ctx *ctx, * Note that we cannot have sorted list by target value, * in order to shorten the list pass loop, since * same list could have nodes for different cq counter handle. + * Note: + * Mark ts buff offset as in use here in the spinlock protection area + * to avoid getting in the re-use section in ts_buff_get_kernel_ts_record + * before adding the node to the list. this scenario might happen when + * multiple threads are racing on same offset and one thread could + * set the ts buff in ts_buff_get_kernel_ts_record then the other thread + * takes over and get to ts_buff_get_kernel_ts_record and then we will try + * to re-use the same ts buff offset, and will try to delete a non existing + * node from the list. */ + if (register_ts_record) + pend->ts_reg_info.in_use = 1; + list_add_tail(&pend->wait_list_node, &interrupt->wait_list_head); spin_unlock_irqrestore(&interrupt->wait_list_lock, flags); @@ -3489,14 +3569,15 @@ static int hl_interrupt_wait_ioctl(struct hl_fpriv *hpriv, void *data) int hl_wait_ioctl(struct hl_fpriv *hpriv, void *data) { + struct hl_device *hdev = hpriv->hdev; union hl_wait_cs_args *args = data; u32 flags = args->in.flags; int rc; - /* If the device is not operational, no point in waiting for any command submission or - * user interrupt + /* If the device is not operational, or if an error has happened and user should release the + * device, there is no point in waiting for any command submission or user interrupt. */ - if (!hl_device_operational(hpriv->hdev, NULL)) + if (!hl_device_operational(hpriv->hdev, NULL) || hdev->reset_info.watchdog_active) return -EBUSY; if (flags & HL_WAIT_CS_FLAGS_INTERRUPT) diff --git a/drivers/misc/habanalabs/common/context.c b/drivers/accel/habanalabs/common/context.c index 9c8b1b37b510..9c8b1b37b510 100644 --- a/drivers/misc/habanalabs/common/context.c +++ b/drivers/accel/habanalabs/common/context.c diff --git a/drivers/misc/habanalabs/common/debugfs.c b/drivers/accel/habanalabs/common/debugfs.c index 945c0e6758ca..945c0e6758ca 100644 --- a/drivers/misc/habanalabs/common/debugfs.c +++ b/drivers/accel/habanalabs/common/debugfs.c diff --git a/drivers/misc/habanalabs/common/decoder.c b/drivers/accel/habanalabs/common/decoder.c index 2aab14d74b53..2aab14d74b53 100644 --- a/drivers/misc/habanalabs/common/decoder.c +++ b/drivers/accel/habanalabs/common/decoder.c diff --git a/drivers/misc/habanalabs/common/device.c b/drivers/accel/habanalabs/common/device.c index 87ab329e65d4..9933e5858a36 100644 --- a/drivers/misc/habanalabs/common/device.c +++ b/drivers/accel/habanalabs/common/device.c @@ -7,7 +7,7 @@ #define pr_fmt(fmt) "habanalabs: " fmt -#include <uapi/misc/habanalabs.h> +#include <uapi/drm/habanalabs_accel.h> #include "habanalabs.h" #include <linux/pci.h> @@ -428,8 +428,10 @@ static void hpriv_release(struct kref *ref) */ reset_device = hdev->reset_upon_device_release || hdev->reset_info.watchdog_active; - /* Unless device is reset in any case, check idle status and reset if device is not idle */ - if (!reset_device && hdev->pdev && !hdev->pldm) + /* Check the device idle status and reset if not idle. + * Skip it if already in reset, or if device is going to be reset in any case. + */ + if (!hdev->reset_info.in_reset && !reset_device && hdev->pdev && !hdev->pldm) device_is_idle = hdev->asic_funcs->is_device_idle(hdev, idle_mask, HL_BUSY_ENGINES_MASK_EXT_SIZE, NULL); if (!device_is_idle) { @@ -511,11 +513,6 @@ static int hl_device_release(struct inode *inode, struct file *filp) return 0; } - /* Each pending user interrupt holds the user's context, hence we - * must release them all before calling hl_ctx_mgr_fini(). - */ - hl_release_pending_user_interrupts(hpriv->hdev); - hl_ctx_mgr_fini(hdev, &hpriv->ctx_mgr); hl_mem_mgr_fini(&hpriv->mem_mgr); @@ -1428,8 +1425,8 @@ static void handle_reset_trigger(struct hl_device *hdev, u32 flags) int hl_device_reset(struct hl_device *hdev, u32 flags) { bool hard_reset, from_hard_reset_thread, fw_reset, hard_instead_soft = false, - reset_upon_device_release = false, schedule_hard_reset = false, delay_reset, - from_dev_release, from_watchdog_thread; + reset_upon_device_release = false, schedule_hard_reset = false, + delay_reset, from_dev_release, from_watchdog_thread; u64 idle_mask[HL_BUSY_ENGINES_MASK_EXT_SIZE] = {0}; struct hl_ctx *ctx; int i, rc; @@ -1446,12 +1443,17 @@ int hl_device_reset(struct hl_device *hdev, u32 flags) delay_reset = !!(flags & HL_DRV_RESET_DELAY); from_watchdog_thread = !!(flags & HL_DRV_RESET_FROM_WD_THR); + if (!hard_reset && (hl_device_status(hdev) == HL_DEVICE_STATUS_MALFUNCTION)) { + dev_dbg(hdev->dev, "soft-reset isn't supported on a malfunctioning device\n"); + return 0; + } + if (!hard_reset && !hdev->asic_prop.supports_compute_reset) { hard_instead_soft = true; hard_reset = true; } - if (hdev->reset_upon_device_release && (flags & HL_DRV_RESET_DEV_RELEASE)) { + if (hdev->reset_upon_device_release && from_dev_release) { if (hard_reset) { dev_crit(hdev->dev, "Aborting reset because hard-reset is mutually exclusive with reset-on-device-release\n"); @@ -1512,6 +1514,7 @@ do_reset: &hdev->device_release_watchdog_work.reset_work); if (from_dev_release) { + hdev->reset_info.in_compute_reset = 0; flags |= HL_DRV_RESET_HARD; flags &= ~HL_DRV_RESET_DEV_RELEASE; hard_reset = true; @@ -1566,7 +1569,8 @@ kill_processes: if (rc == -EBUSY) { if (hdev->device_fini_pending) { dev_crit(hdev->dev, - "Failed to kill all open processes, stopping hard reset\n"); + "%s Failed to kill all open processes, stopping hard reset\n", + dev_name(&(hdev)->pdev->dev)); goto out_err; } @@ -1576,7 +1580,8 @@ kill_processes: if (rc) { dev_crit(hdev->dev, - "Failed to kill all open processes, stopping hard reset\n"); + "%s Failed to kill all open processes, stopping hard reset\n", + dev_name(&(hdev)->pdev->dev)); goto out_err; } @@ -1627,14 +1632,16 @@ kill_processes: * ensure driver puts the driver in a unusable state */ dev_crit(hdev->dev, - "Consecutive FW fatal errors received, stopping hard reset\n"); + "%s Consecutive FW fatal errors received, stopping hard reset\n", + dev_name(&(hdev)->pdev->dev)); rc = -EIO; goto out_err; } if (hdev->kernel_ctx) { dev_crit(hdev->dev, - "kernel ctx was alive during hard reset, something is terribly wrong\n"); + "%s kernel ctx was alive during hard reset, something is terribly wrong\n", + dev_name(&(hdev)->pdev->dev)); rc = -EBUSY; goto out_err; } @@ -1732,7 +1739,7 @@ kill_processes: rc = hdev->asic_funcs->scrub_device_mem(hdev); if (rc) { dev_err(hdev->dev, "scrub mem failed from device reset (%d)\n", rc); - return rc; + goto out_err; } spin_lock(&hdev->reset_info.lock); @@ -1752,9 +1759,13 @@ kill_processes: hdev->reset_info.needs_reset = false; if (hard_reset) - dev_info(hdev->dev, "Successfully finished resetting the device\n"); + dev_info(hdev->dev, + "Successfully finished resetting the %s device\n", + dev_name(&(hdev)->pdev->dev)); else - dev_dbg(hdev->dev, "Successfully finished resetting the device\n"); + dev_dbg(hdev->dev, + "Successfully finished resetting the %s device\n", + dev_name(&(hdev)->pdev->dev)); if (hard_reset) { hdev->reset_info.hard_reset_cnt++; @@ -1789,7 +1800,9 @@ out_err: hdev->reset_info.in_compute_reset = 0; if (hard_reset) { - dev_err(hdev->dev, "Failed to reset! Device is NOT usable\n"); + dev_err(hdev->dev, + "%s Failed to reset! Device is NOT usable\n", + dev_name(&(hdev)->pdev->dev)); hdev->reset_info.hard_reset_cnt++; } else if (reset_upon_device_release) { spin_unlock(&hdev->reset_info.lock); @@ -1870,6 +1883,8 @@ out: hl_ctx_put(ctx); + hl_abort_waitings_for_completion(hdev); + return 0; device_reset: @@ -2186,7 +2201,8 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass) } dev_notice(hdev->dev, - "Successfully added device to habanalabs driver\n"); + "Successfully added device %s to habanalabs driver\n", + dev_name(&(hdev)->pdev->dev)); hdev->init_done = true; @@ -2235,11 +2251,11 @@ out_disabled: device_cdev_sysfs_add(hdev); if (hdev->pdev) dev_err(&hdev->pdev->dev, - "Failed to initialize hl%d. Device is NOT usable !\n", - hdev->cdev_idx); + "Failed to initialize hl%d. Device %s is NOT usable !\n", + hdev->cdev_idx, dev_name(&(hdev)->pdev->dev)); else - pr_err("Failed to initialize hl%d. Device is NOT usable !\n", - hdev->cdev_idx); + pr_err("Failed to initialize hl%d. Device %s is NOT usable !\n", + hdev->cdev_idx, dev_name(&(hdev)->pdev->dev)); return rc; } @@ -2295,7 +2311,8 @@ void hl_device_fini(struct hl_device *hdev) if (ktime_compare(ktime_get(), timeout) > 0) { dev_crit(hdev->dev, - "Failed to remove device because reset function did not finish\n"); + "%s Failed to remove device because reset function did not finish\n", + dev_name(&(hdev)->pdev->dev)); return; } } @@ -2363,7 +2380,7 @@ void hl_device_fini(struct hl_device *hdev) hl_mmu_fini(hdev); - vfree(hdev->captured_err_info.pgf_info.user_mappings); + vfree(hdev->captured_err_info.page_fault_info.user_mappings); hl_eq_fini(hdev, &hdev->event_queue); @@ -2402,7 +2419,12 @@ void hl_device_fini(struct hl_device *hdev) */ inline u32 hl_rreg(struct hl_device *hdev, u32 reg) { - return readl(hdev->rmmio + reg); + u32 val = readl(hdev->rmmio + reg); + + if (unlikely(trace_habanalabs_rreg32_enabled())) + trace_habanalabs_rreg32(hdev->dev, reg, val); + + return val; } /* @@ -2417,12 +2439,17 @@ inline u32 hl_rreg(struct hl_device *hdev, u32 reg) */ inline void hl_wreg(struct hl_device *hdev, u32 reg, u32 val) { + if (unlikely(trace_habanalabs_wreg32_enabled())) + trace_habanalabs_wreg32(hdev->dev, reg, val); + writel(val, hdev->rmmio + reg); } void hl_capture_razwi(struct hl_device *hdev, u64 addr, u16 *engine_id, u16 num_of_engines, u8 flags) { + struct razwi_info *razwi_info = &hdev->captured_err_info.razwi_info; + if (num_of_engines > HL_RAZWI_MAX_NUM_OF_ENGINES_PER_RTR) { dev_err(hdev->dev, "Number of possible razwi initiators (%u) exceeded limit (%u)\n", @@ -2431,15 +2458,17 @@ void hl_capture_razwi(struct hl_device *hdev, u64 addr, u16 *engine_id, u16 num_ } /* In case it's the first razwi since the device was opened, capture its parameters */ - if (atomic_cmpxchg(&hdev->captured_err_info.razwi_info_recorded, 0, 1)) + if (atomic_cmpxchg(&hdev->captured_err_info.razwi_info.razwi_detected, 0, 1)) return; - hdev->captured_err_info.razwi.timestamp = ktime_to_ns(ktime_get()); - hdev->captured_err_info.razwi.addr = addr; - hdev->captured_err_info.razwi.num_of_possible_engines = num_of_engines; - memcpy(&hdev->captured_err_info.razwi.engine_id[0], &engine_id[0], + razwi_info->razwi.timestamp = ktime_to_ns(ktime_get()); + razwi_info->razwi.addr = addr; + razwi_info->razwi.num_of_possible_engines = num_of_engines; + memcpy(&razwi_info->razwi.engine_id[0], &engine_id[0], num_of_engines * sizeof(u16)); - hdev->captured_err_info.razwi.flags = flags; + razwi_info->razwi.flags = flags; + + razwi_info->razwi_info_available = true; } void hl_handle_razwi(struct hl_device *hdev, u64 addr, u16 *engine_id, u16 num_of_engines, @@ -2453,7 +2482,7 @@ void hl_handle_razwi(struct hl_device *hdev, u64 addr, u16 *engine_id, u16 num_o static void hl_capture_user_mappings(struct hl_device *hdev, bool is_pmmu) { - struct page_fault_info *pgf_info = &hdev->captured_err_info.pgf_info; + struct page_fault_info *pgf_info = &hdev->captured_err_info.page_fault_info; struct hl_vm_phys_pg_pack *phys_pg_pack = NULL; struct hl_vm_hash_node *hnode; struct hl_userptr *userptr; @@ -2515,14 +2544,18 @@ finish: void hl_capture_page_fault(struct hl_device *hdev, u64 addr, u16 eng_id, bool is_pmmu) { + struct page_fault_info *pgf_info = &hdev->captured_err_info.page_fault_info; + /* Capture only the first page fault */ - if (atomic_cmpxchg(&hdev->captured_err_info.pgf_info_recorded, 0, 1)) + if (atomic_cmpxchg(&pgf_info->page_fault_detected, 0, 1)) return; - hdev->captured_err_info.pgf_info.pgf.timestamp = ktime_to_ns(ktime_get()); - hdev->captured_err_info.pgf_info.pgf.addr = addr; - hdev->captured_err_info.pgf_info.pgf.engine_id = eng_id; + pgf_info->page_fault.timestamp = ktime_to_ns(ktime_get()); + pgf_info->page_fault.addr = addr; + pgf_info->page_fault.engine_id = eng_id; hl_capture_user_mappings(hdev, is_pmmu); + + pgf_info->page_fault_info_available = true; } void hl_handle_page_fault(struct hl_device *hdev, u64 addr, u16 eng_id, bool is_pmmu, diff --git a/drivers/misc/habanalabs/common/firmware_if.c b/drivers/accel/habanalabs/common/firmware_if.c index 228b92278e48..da892d8fb3d6 100644 --- a/drivers/misc/habanalabs/common/firmware_if.c +++ b/drivers/accel/habanalabs/common/firmware_if.c @@ -14,8 +14,32 @@ #include <linux/ctype.h> #include <linux/vmalloc.h> +#include <trace/events/habanalabs.h> + #define FW_FILE_MAX_SIZE 0x1400000 /* maximum size of 20MB */ +static char *comms_cmd_str_arr[COMMS_INVLD_LAST] = { + [COMMS_NOOP] = __stringify(COMMS_NOOP), + [COMMS_CLR_STS] = __stringify(COMMS_CLR_STS), + [COMMS_RST_STATE] = __stringify(COMMS_RST_STATE), + [COMMS_PREP_DESC] = __stringify(COMMS_PREP_DESC), + [COMMS_DATA_RDY] = __stringify(COMMS_DATA_RDY), + [COMMS_EXEC] = __stringify(COMMS_EXEC), + [COMMS_RST_DEV] = __stringify(COMMS_RST_DEV), + [COMMS_GOTO_WFE] = __stringify(COMMS_GOTO_WFE), + [COMMS_SKIP_BMC] = __stringify(COMMS_SKIP_BMC), + [COMMS_PREP_DESC_ELBI] = __stringify(COMMS_PREP_DESC_ELBI), +}; + +static char *comms_sts_str_arr[COMMS_STS_INVLD_LAST] = { + [COMMS_STS_NOOP] = __stringify(COMMS_STS_NOOP), + [COMMS_STS_ACK] = __stringify(COMMS_STS_ACK), + [COMMS_STS_OK] = __stringify(COMMS_STS_OK), + [COMMS_STS_ERR] = __stringify(COMMS_STS_ERR), + [COMMS_STS_VALID_ERR] = __stringify(COMMS_STS_VALID_ERR), + [COMMS_STS_TIMEOUT_ERR] = __stringify(COMMS_STS_TIMEOUT_ERR), +}; + static char *extract_fw_ver_from_str(const char *fw_str) { char *str, *fw_ver, *whitespace; @@ -311,7 +335,7 @@ int hl_fw_send_cpu_message(struct hl_device *hdev, u32 hw_queue_id, u32 *msg, dev_dbg(hdev->dev, "Device CPU packet timeout (0x%x) due to FW reset\n", tmp); else - dev_err(hdev->dev, "Device CPU packet timeout (0x%x)\n", tmp); + dev_err(hdev->dev, "Device CPU packet timeout (status = 0x%x)\n", tmp); hdev->device_cpu_disabled = true; goto out; } @@ -1322,13 +1346,12 @@ static void detect_cpu_boot_status(struct hl_device *hdev, u32 status) break; default: dev_err(hdev->dev, - "Device boot progress - Invalid status code %d\n", - status); + "Device boot progress - Invalid or unexpected status code %d\n", status); break; } } -static int hl_fw_wait_preboot_ready(struct hl_device *hdev) +int hl_fw_wait_preboot_ready(struct hl_device *hdev) { struct pre_fw_load_props *pre_fw_load = &hdev->fw_loader.pre_fw_load; u32 status; @@ -1353,8 +1376,8 @@ static int hl_fw_wait_preboot_ready(struct hl_device *hdev) pre_fw_load->wait_for_preboot_timeout); if (rc) { - dev_err(hdev->dev, "CPU boot ready status timeout\n"); detect_cpu_boot_status(hdev, status); + dev_err(hdev->dev, "CPU boot ready timeout (status = %d)\n", status); /* If we read all FF, then something is totally wrong, no point * of reading specific errors @@ -1634,6 +1657,7 @@ static void hl_fw_dynamic_send_cmd(struct hl_device *hdev, val = FIELD_PREP(COMMS_COMMAND_CMD_MASK, cmd); val |= FIELD_PREP(COMMS_COMMAND_SIZE_MASK, size); + trace_habanalabs_comms_send_cmd(hdev->dev, comms_cmd_str_arr[cmd]); WREG32(le32_to_cpu(dyn_regs->kmd_msg_to_cpu), val); } @@ -1691,6 +1715,8 @@ static int hl_fw_dynamic_wait_for_status(struct hl_device *hdev, dyn_regs = &fw_loader->dynamic_loader.comm_desc.cpu_dyn_regs; + trace_habanalabs_comms_wait_status(hdev->dev, comms_sts_str_arr[expected_status]); + /* Wait for expected status */ rc = hl_poll_timeout( hdev, @@ -1706,6 +1732,8 @@ static int hl_fw_dynamic_wait_for_status(struct hl_device *hdev, return -EIO; } + trace_habanalabs_comms_wait_status_done(hdev->dev, comms_sts_str_arr[expected_status]); + /* * skip storing FW response for NOOP to preserve the actual desired * FW status @@ -1778,6 +1806,8 @@ int hl_fw_dynamic_send_protocol_cmd(struct hl_device *hdev, { int rc; + trace_habanalabs_comms_protocol_cmd(hdev->dev, comms_cmd_str_arr[cmd]); + /* first send clear command to clean former commands */ rc = hl_fw_dynamic_send_clear_cmd(hdev, fw_loader); if (rc) @@ -1884,7 +1914,7 @@ static int hl_fw_dynamic_validate_memory_bound(struct hl_device *hdev, * * @hdev: pointer to the habanalabs device structure * @fw_loader: managing structure for loading device's FW - * @fw_desc: the descriptor form FW + * @fw_desc: the descriptor from FW * * @return 0 on success, otherwise non-zero error code */ @@ -1901,11 +1931,11 @@ static int hl_fw_dynamic_validate_descriptor(struct hl_device *hdev, int rc; if (le32_to_cpu(fw_desc->header.magic) != HL_COMMS_DESC_MAGIC) - dev_warn(hdev->dev, "Invalid magic for dynamic FW descriptor (%x)\n", + dev_dbg(hdev->dev, "Invalid magic for dynamic FW descriptor (%x)\n", fw_desc->header.magic); if (fw_desc->header.version != HL_COMMS_DESC_VER) - dev_warn(hdev->dev, "Invalid version for dynamic FW descriptor (%x)\n", + dev_dbg(hdev->dev, "Invalid version for dynamic FW descriptor (%x)\n", fw_desc->header.version); /* @@ -1976,6 +2006,43 @@ static int hl_fw_dynamic_validate_response(struct hl_device *hdev, return rc; } +/* + * hl_fw_dynamic_read_descriptor_msg - read and show the ascii msg that sent by fw + * + * @hdev: pointer to the habanalabs device structure + * @fw_desc: the descriptor from FW + */ +static void hl_fw_dynamic_read_descriptor_msg(struct hl_device *hdev, + struct lkd_fw_comms_desc *fw_desc) +{ + int i; + char *msg; + + for (i = 0 ; i < LKD_FW_ASCII_MSG_MAX ; i++) { + if (!fw_desc->ascii_msg[i].valid) + return; + + /* force NULL termination */ + msg = fw_desc->ascii_msg[i].msg; + msg[LKD_FW_ASCII_MSG_MAX_LEN - 1] = '\0'; + + switch (fw_desc->ascii_msg[i].msg_lvl) { + case LKD_FW_ASCII_MSG_ERR: + dev_err(hdev->dev, "fw: %s", fw_desc->ascii_msg[i].msg); + break; + case LKD_FW_ASCII_MSG_WRN: + dev_warn(hdev->dev, "fw: %s", fw_desc->ascii_msg[i].msg); + break; + case LKD_FW_ASCII_MSG_INF: + dev_info(hdev->dev, "fw: %s", fw_desc->ascii_msg[i].msg); + break; + default: + dev_dbg(hdev->dev, "fw: %s", fw_desc->ascii_msg[i].msg); + break; + } + } +} + /** * hl_fw_dynamic_read_and_validate_descriptor - read and validate FW descriptor * @@ -1988,9 +2055,10 @@ static int hl_fw_dynamic_read_and_validate_descriptor(struct hl_device *hdev, struct fw_load_mgr *fw_loader) { struct lkd_fw_comms_desc *fw_desc; - void __iomem *src, *temp_fw_desc; struct pci_mem_region *region; struct fw_response *response; + void *temp_fw_desc; + void __iomem *src; u16 fw_data_size; enum pci_region region_id; int rc; @@ -2039,6 +2107,10 @@ static int hl_fw_dynamic_read_and_validate_descriptor(struct hl_device *hdev, rc = hl_fw_dynamic_validate_descriptor(hdev, fw_loader, (struct lkd_fw_comms_desc *) temp_fw_desc); + + if (!rc) + hl_fw_dynamic_read_descriptor_msg(hdev, temp_fw_desc); + vfree(temp_fw_desc); return rc; @@ -2354,7 +2426,7 @@ static int hl_fw_dynamic_wait_for_boot_fit_active(struct hl_device *hdev, hdev->fw_poll_interval_usec, dyn_loader->wait_for_bl_timeout); if (rc) { - dev_err(hdev->dev, "failed to wait for boot\n"); + dev_err(hdev->dev, "failed to wait for boot (status = %d)\n", status); return rc; } @@ -2381,7 +2453,7 @@ static int hl_fw_dynamic_wait_for_linux_active(struct hl_device *hdev, hdev->fw_poll_interval_usec, fw_loader->cpu_timeout); if (rc) { - dev_err(hdev->dev, "failed to wait for Linux\n"); + dev_err(hdev->dev, "failed to wait for Linux (status = %d)\n", status); return rc; } @@ -2459,51 +2531,54 @@ static void hl_fw_linux_update_state(struct hl_device *hdev, static int hl_fw_dynamic_send_msg(struct hl_device *hdev, struct fw_load_mgr *fw_loader, u8 msg_type, void *data) { - struct lkd_msg_comms msg; + struct lkd_msg_comms *msg; int rc; - memset(&msg, 0, sizeof(msg)); + msg = kzalloc(sizeof(*msg), GFP_KERNEL); + if (!msg) + return -ENOMEM; /* create message to be sent */ - msg.header.type = msg_type; - msg.header.size = cpu_to_le16(sizeof(struct comms_msg_header)); - msg.header.magic = cpu_to_le32(HL_COMMS_MSG_MAGIC); + msg->header.type = msg_type; + msg->header.size = cpu_to_le16(sizeof(struct comms_msg_header)); + msg->header.magic = cpu_to_le32(HL_COMMS_MSG_MAGIC); switch (msg_type) { case HL_COMMS_RESET_CAUSE_TYPE: - msg.reset_cause = *(__u8 *) data; + msg->reset_cause = *(__u8 *) data; break; default: dev_err(hdev->dev, "Send COMMS message - invalid message type %u\n", msg_type); - return -EINVAL; + rc = -EINVAL; + goto out; } rc = hl_fw_dynamic_request_descriptor(hdev, fw_loader, sizeof(struct lkd_msg_comms)); if (rc) - return rc; + goto out; /* copy message to space allocated by FW */ - rc = hl_fw_dynamic_copy_msg(hdev, &msg, fw_loader); + rc = hl_fw_dynamic_copy_msg(hdev, msg, fw_loader); if (rc) - return rc; + goto out; rc = hl_fw_dynamic_send_protocol_cmd(hdev, fw_loader, COMMS_DATA_RDY, 0, true, fw_loader->cpu_timeout); if (rc) - return rc; + goto out; rc = hl_fw_dynamic_send_protocol_cmd(hdev, fw_loader, COMMS_EXEC, 0, true, fw_loader->cpu_timeout); - if (rc) - return rc; - return 0; +out: + kfree(msg); + return rc; } /** @@ -2560,13 +2635,43 @@ static int hl_fw_dynamic_init_cpu(struct hl_device *hdev, } if (!(hdev->fw_components & FW_TYPE_BOOT_CPU)) { + struct lkd_fw_binning_info *binning_info; + rc = hl_fw_dynamic_request_descriptor(hdev, fw_loader, 0); if (rc) goto protocol_err; /* read preboot version */ - return hl_fw_dynamic_read_device_fw_version(hdev, FW_COMP_PREBOOT, + rc = hl_fw_dynamic_read_device_fw_version(hdev, FW_COMP_PREBOOT, fw_loader->dynamic_loader.comm_desc.cur_fw_ver); + + if (rc) + return rc; + + /* read binning info from preboot */ + if (hdev->support_preboot_binning) { + binning_info = &fw_loader->dynamic_loader.comm_desc.binning_info; + hdev->tpc_binning = le64_to_cpu(binning_info->tpc_mask_l); + hdev->dram_binning = le32_to_cpu(binning_info->dram_mask); + hdev->edma_binning = le32_to_cpu(binning_info->edma_mask); + hdev->decoder_binning = le32_to_cpu(binning_info->dec_mask); + hdev->rotator_binning = le32_to_cpu(binning_info->rot_mask); + + rc = hdev->asic_funcs->set_dram_properties(hdev); + if (rc) + return rc; + + rc = hdev->asic_funcs->set_binning_masks(hdev); + if (rc) + return rc; + + dev_dbg(hdev->dev, + "Read binning masks: tpc: 0x%llx, dram: 0x%llx, edma: 0x%x, dec: 0x%x, rot:0x%x\n", + hdev->tpc_binning, hdev->dram_binning, hdev->edma_binning, + hdev->decoder_binning, hdev->rotator_binning); + } + + return 0; } /* load boot fit to FW */ @@ -2687,7 +2792,7 @@ static int hl_fw_static_init_cpu(struct hl_device *hdev, if (rc) { dev_dbg(hdev->dev, - "No boot fit request received, resuming boot\n"); + "No boot fit request received (status = %d), resuming boot\n", status); } else { rc = hdev->asic_funcs->load_boot_fit_to_device(hdev); if (rc) @@ -2710,7 +2815,7 @@ static int hl_fw_static_init_cpu(struct hl_device *hdev, if (rc) { dev_err(hdev->dev, - "Timeout waiting for boot fit load ack\n"); + "Timeout waiting for boot fit load ack (status = %d)\n", status); goto out; } @@ -2788,7 +2893,7 @@ static int hl_fw_static_init_cpu(struct hl_device *hdev, if (rc) { dev_err(hdev->dev, - "Failed to get ACK on skipping BMC, %d\n", + "Failed to get ACK on skipping BMC (status = %d)\n", status); WREG32(msg_to_cpu_reg, KMD_MSG_NA); rc = -EIO; @@ -2815,7 +2920,7 @@ static int hl_fw_static_init_cpu(struct hl_device *hdev, "Device reports FIT image is corrupted\n"); else dev_err(hdev->dev, - "Failed to load firmware to device, %d\n", + "Failed to load firmware to device (status = %d)\n", status); rc = -EIO; @@ -3043,3 +3148,27 @@ int hl_fw_get_sec_attest_info(struct hl_device *hdev, struct cpucp_sec_attest_in sizeof(struct cpucp_sec_attest_info), nonce, HL_CPUCP_SEC_ATTEST_INFO_TINEOUT_USEC); } + +int hl_fw_send_generic_request(struct hl_device *hdev, enum hl_passthrough_type sub_opcode, + dma_addr_t buff, u32 *size) +{ + struct cpucp_packet pkt = {0}; + u64 result; + int rc = 0; + + pkt.ctl = cpu_to_le32(CPUCP_PACKET_GENERIC_PASSTHROUGH << CPUCP_PKT_CTL_OPCODE_SHIFT); + pkt.addr = cpu_to_le64(buff); + pkt.data_max_size = cpu_to_le32(*size); + pkt.pkt_subidx = cpu_to_le32(sub_opcode); + + rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *)&pkt, sizeof(pkt), + HL_CPUCP_INFO_TIMEOUT_USEC, &result); + if (rc) + dev_err(hdev->dev, "failed to send CPUCP data of generic fw pkt\n"); + else + dev_dbg(hdev->dev, "generic pkt was successful, result: 0x%llx\n", result); + + *size = (u32)result; + + return rc; +} diff --git a/drivers/misc/habanalabs/common/habanalabs.h b/drivers/accel/habanalabs/common/habanalabs.h index e2527d976ee0..fa05e76d3d21 100644 --- a/drivers/misc/habanalabs/common/habanalabs.h +++ b/drivers/accel/habanalabs/common/habanalabs.h @@ -11,7 +11,7 @@ #include "../include/common/cpucp_if.h" #include "../include/common/qman_if.h" #include "../include/hw_ip/mmu/mmu_general.h" -#include <uapi/misc/habanalabs.h> +#include <uapi/drm/habanalabs_accel.h> #include <linux/cdev.h> #include <linux/iopoll.h> @@ -29,6 +29,8 @@ #include <linux/coresight.h> #include <linux/dma-buf.h> +#include "security.h" + #define HL_NAME "habanalabs" struct hl_device; @@ -375,7 +377,8 @@ enum hl_cs_type { CS_TYPE_COLLECTIVE_WAIT, CS_RESERVE_SIGNALS, CS_UNRESERVE_SIGNALS, - CS_TYPE_ENGINE_CORE + CS_TYPE_ENGINE_CORE, + CS_TYPE_FLUSH_PCI_HBW_WRITES, }; /* @@ -545,6 +548,8 @@ struct hl_hints_range { /** * struct asic_fixed_properties - ASIC specific immutable properties. * @hw_queues_props: H/W queues properties. + * @special_blocks: points to an array containing special blocks info. + * @skip_special_blocks_cfg: special blocks skip configs. * @cpucp_info: received various information from CPU-CP regarding the H/W, e.g. * available sensors. * @uboot_ver: F/W U-boot version. @@ -644,6 +649,10 @@ struct hl_hints_range { * (i.e. the DRAM supports multiple page sizes), otherwise * it will shall be equal to dram_page_size. * @num_engine_cores: number of engine cpu cores + * @num_of_special_blocks: special_blocks array size. + * @glbl_err_cause_num: global err cause number. + * @hbw_flush_reg: register to read to generate HBW flush. value of 0 means HBW flush is + * not supported. * @collective_first_sob: first sync object available for collective use * @collective_first_mon: first monitor available for collective use * @sync_stream_first_sob: first sync object available for sync stream use @@ -692,6 +701,8 @@ struct hl_hints_range { */ struct asic_fixed_properties { struct hw_queue_properties *hw_queues_props; + struct hl_special_block_info *special_blocks; + struct hl_skip_blocks_cfg skip_special_blocks_cfg; struct cpucp_info cpucp_info; char uboot_ver[VERSION_MAX_LEN]; char preboot_ver[VERSION_MAX_LEN]; @@ -764,6 +775,9 @@ struct asic_fixed_properties { u32 xbar_edge_enabled_mask; u32 device_mem_alloc_default_page_size; u32 num_engine_cores; + u32 num_of_special_blocks; + u32 glbl_err_cause_num; + u32 hbw_flush_reg; u16 collective_first_sob; u16 collective_first_mon; u16 sync_stream_first_sob; @@ -935,6 +949,7 @@ struct hl_mmap_mem_buf { * @size: holds the CB's size. * @roundup_size: holds the cb size after roundup to page size. * @cs_cnt: holds number of CS that this CB participates in. + * @is_handle_destroyed: atomic boolean indicating whether or not the CB handle was destroyed. * @is_pool: true if CB was acquired from the pool, false otherwise. * @is_internal: internally allocated * @is_mmu_mapped: true if the CB is mapped to the device's MMU. @@ -951,6 +966,7 @@ struct hl_cb { u32 size; u32 roundup_size; atomic_t cs_cnt; + atomic_t is_handle_destroyed; u8 is_pool; u8 is_internal; u8 is_mmu_mapped; @@ -1077,20 +1093,25 @@ struct hl_cq { atomic_t free_slots_cnt; }; +enum hl_user_interrupt_type { + HL_USR_INTERRUPT_CQ = 0, + HL_USR_INTERRUPT_DECODER, +}; + /** * struct hl_user_interrupt - holds user interrupt information * @hdev: pointer to the device structure + * @type: user interrupt type * @wait_list_head: head to the list of user threads pending on this interrupt * @wait_list_lock: protects wait_list_head * @interrupt_id: msix interrupt id - * @is_decoder: whether this entry represents a decoder interrupt */ struct hl_user_interrupt { - struct hl_device *hdev; - struct list_head wait_list_head; - spinlock_t wait_list_lock; - u32 interrupt_id; - bool is_decoder; + struct hl_device *hdev; + enum hl_user_interrupt_type type; + struct list_head wait_list_head; + spinlock_t wait_list_lock; + u32 interrupt_id; }; /** @@ -1540,8 +1561,10 @@ struct engines_data { * @check_if_razwi_happened: check if there was a razwi due to RR violation. * @access_dev_mem: access device memory * @set_dram_bar_base: set the base of the DRAM BAR - * @set_engine_cores: set a config command to enigne cores + * @set_engine_cores: set a config command to engine cores * @send_device_activity: indication to FW about device availability + * @set_dram_properties: set DRAM related properties. + * @set_binning_masks: set binning/enable masks for all relevant components. */ struct hl_asic_funcs { int (*early_init)(struct hl_device *hdev); @@ -1679,6 +1702,8 @@ struct hl_asic_funcs { int (*set_engine_cores)(struct hl_device *hdev, u32 *core_ids, u32 num_cores, u32 core_command); int (*send_device_activity)(struct hl_device *hdev, bool open); + int (*set_dram_properties)(struct hl_device *hdev); + int (*set_binning_masks)(struct hl_device *hdev); }; @@ -1739,8 +1764,9 @@ struct hl_cs_counters_atomic { * struct hl_dmabuf_priv - a dma-buf private object. * @dmabuf: pointer to dma-buf object. * @ctx: pointer to the dma-buf owner's context. - * @phys_pg_pack: pointer to physical page pack if the dma-buf was exported for - * memory allocation handle. + * @phys_pg_pack: pointer to physical page pack if the dma-buf was exported + * where virtual memory is supported. + * @memhash_hnode: pointer to the memhash node. this object holds the export count. * @device_address: physical address of the device's memory. Relevant only * if phys_pg_pack is NULL (dma-buf was exported from address). * The total size can be taken from the dmabuf object. @@ -1749,6 +1775,7 @@ struct hl_dmabuf_priv { struct dma_buf *dmabuf; struct hl_ctx *ctx; struct hl_vm_phys_pg_pack *phys_pg_pack; + struct hl_vm_hash_node *memhash_hnode; uint64_t device_address; }; @@ -1923,6 +1950,7 @@ struct hl_userptr { * @type: CS_TYPE_*. * @jobs_cnt: counter of submitted jobs on all queues. * @encaps_sig_hdl_id: encaps signals handle id, set for the first staged cs. + * @completion_timestamp: timestamp of the last completed cs job. * @sob_addr_offset: sob offset from the configuration base address. * @initial_sob_count: count of completed signals in SOB before current submission of signal or * cs with encaps signals. @@ -1955,6 +1983,7 @@ struct hl_cs { struct list_head staged_cs_node; struct list_head debugfs_list; struct hl_cs_encaps_sig_handle *encaps_sig_hdl; + ktime_t completion_timestamp; u64 sequence; u64 staged_sequence; u64 timeout_jiffies; @@ -1990,6 +2019,7 @@ struct hl_cs { * @debugfs_list: node in debugfs list of command submission jobs. * @refcount: reference counter for usage of the CS job. * @queue_type: the type of the H/W queue this job is submitted to. + * @timestamp: timestamp upon job completion * @id: the id of this job inside a CS. * @hw_queue_id: the id of the H/W queue this job is submitted to. * @user_cb_size: the actual size of the CB we got from the user. @@ -2016,6 +2046,7 @@ struct hl_cs_job { struct list_head debugfs_list; struct kref refcount; enum hl_queue_type queue_type; + ktime_t timestamp; u32 id; u32 hw_queue_id; u32 user_cb_size; @@ -2076,12 +2107,16 @@ struct hl_cs_parser { * hl_userptr). * @node: node to hang on the hash table in context object. * @vaddr: key virtual address. + * @handle: memory handle for device memory allocation. * @ptr: value pointer (hl_vm_phys_pg_list or hl_userptr). + * @export_cnt: number of exports from within the VA block. */ struct hl_vm_hash_node { struct hlist_node node; u64 vaddr; + u64 handle; void *ptr; + int export_cnt; }; /** @@ -2109,10 +2144,10 @@ struct hl_vm_hw_block_list_node { * @pages: the physical page array. * @npages: num physical pages in the pack. * @total_size: total size of all the pages in this list. + * @exported_size: buffer exported size. * @node: used to attach to deletion list that is used when all the allocations are cleared * at the teardown of the context. * @mapping_cnt: number of shared mappings. - * @exporting_cnt: number of dma-buf exporting. * @asid: the context related to this list. * @page_size: size of each page in the pack. * @flags: HL_MEM_* flags related to this list. @@ -2126,9 +2161,9 @@ struct hl_vm_phys_pg_pack { u64 *pages; u64 npages; u64 total_size; + u64 exported_size; struct list_head node; atomic_t mapping_cnt; - u32 exporting_cnt; u32 asid; u32 page_size; u32 flags; @@ -2675,11 +2710,11 @@ void hl_wreg(struct hl_device *hdev, u32 reg, u32 val); p->size = sz; \ }) -#define HL_USR_INTR_STRUCT_INIT(usr_intr, hdev, intr_id, decoder) \ +#define HL_USR_INTR_STRUCT_INIT(usr_intr, hdev, intr_id, intr_type) \ ({ \ usr_intr.hdev = hdev; \ usr_intr.interrupt_id = intr_id; \ - usr_intr.is_decoder = decoder; \ + usr_intr.type = intr_type; \ INIT_LIST_HEAD(&usr_intr.wait_list_head); \ spin_lock_init(&usr_intr.wait_list_lock); \ }) @@ -2961,37 +2996,53 @@ struct undefined_opcode_info { }; /** - * struct page_fault_info - info about page fault - * @pgf_info: page fault information. + * struct page_fault_info - page fault information. + * @page_fault: holds information collected during a page fault. * @user_mappings: buffer containing user mappings. * @num_of_user_mappings: number of user mappings. + * @page_fault_detected: if set as 1, then a page-fault was discovered for the + * first time after the driver has finished booting-up. + * Since we're looking for the page-fault's root cause, + * we don't care of the others that might follow it- + * so once changed to 1, it will remain that way. + * @page_fault_info_available: indicates that a page fault info is now available. */ struct page_fault_info { - struct hl_page_fault_info pgf; + struct hl_page_fault_info page_fault; struct hl_user_mapping *user_mappings; u64 num_of_user_mappings; + atomic_t page_fault_detected; + bool page_fault_info_available; +}; + +/** + * struct razwi_info - RAZWI information. + * @razwi: holds information collected during a RAZWI + * @razwi_detected: if set as 1, then a RAZWI was discovered for the + * first time after the driver has finished booting-up. + * Since we're looking for the RAZWI's root cause, + * we don't care of the others that might follow it- + * so once changed to 1, it will remain that way. + * @razwi_info_available: indicates that a RAZWI info is now available. + */ +struct razwi_info { + struct hl_info_razwi_event razwi; + atomic_t razwi_detected; + bool razwi_info_available; }; /** * struct hl_error_info - holds information collected during an error. * @cs_timeout: CS timeout error information. - * @razwi: razwi information. - * @razwi_info_recorded: if set writing to razwi information is enabled. - * otherwise - disabled, so the first (root cause) razwi will not be - * overwritten. - * @undef_opcode: undefined opcode information - * @pgf_info: page fault information. - * @pgf_info_recorded: if set writing to page fault information is enabled. - * otherwise - disabled, so the first (root cause) page fault will not be - * overwritten. + * @razwi_info: RAZWI information. + * @undef_opcode: undefined opcode information. + * @page_fault_info: page fault information. */ struct hl_error_info { struct cs_timeout_info cs_timeout; - struct hl_info_razwi_event razwi; - atomic_t razwi_info_recorded; + struct razwi_info razwi_info; struct undefined_opcode_info undef_opcode; - struct page_fault_info pgf_info; - atomic_t pgf_info_recorded; + struct page_fault_info page_fault_info; }; /** @@ -3157,6 +3208,8 @@ struct hl_reset_info { * @edma_binning: contains mask of edma engines that is received from the f/w which * indicates which edma engines are binned-out * @device_release_watchdog_timeout_sec: device release watchdog timeout value in seconds. + * @rotator_binning: contains mask of rotators engines that is received from the f/w + * which indicates which rotator engines are binned-out(Gaudi3 and above). * @id: device minor. * @id_control: minor of the control device. * @cdev_idx: char device index. Used for setting its name. @@ -3214,6 +3267,7 @@ struct hl_reset_info { * @heartbeat: Controls if we want to enable the heartbeat mechanism vs. the f/w, which verifies * that the f/w is always alive. Used only for testing. * @supports_ctx_switch: true if a ctx switch is required upon first submission. + * @support_preboot_binning: true if we support read binning info from preboot. */ struct hl_device { struct pci_dev *pdev; @@ -3322,6 +3376,7 @@ struct hl_device { u32 decoder_binning; u32 edma_binning; u32 device_release_watchdog_timeout_sec; + u32 rotator_binning; u16 id; u16 id_control; u16 cdev_idx; @@ -3355,6 +3410,7 @@ struct hl_device { u8 supports_mmu_prefetch; u8 reset_upon_device_release; u8 supports_ctx_switch; + u8 support_preboot_binning; /* Parameters for bring-up */ u64 nic_ports_mask; @@ -3729,6 +3785,7 @@ int hl_fw_cpucp_power_get(struct hl_device *hdev, u64 *power); void hl_fw_ask_hard_reset_without_linux(struct hl_device *hdev); void hl_fw_ask_halt_machine_without_linux(struct hl_device *hdev); int hl_fw_init_cpu(struct hl_device *hdev); +int hl_fw_wait_preboot_ready(struct hl_device *hdev); int hl_fw_read_preboot_status(struct hl_device *hdev); int hl_fw_dynamic_send_protocol_cmd(struct hl_device *hdev, struct fw_load_mgr *fw_loader, @@ -3772,6 +3829,8 @@ int hl_fw_get_clk_rate(struct hl_device *hdev, u32 *cur_clk, u32 *max_clk); void hl_fw_set_pll_profile(struct hl_device *hdev); void hl_sysfs_add_dev_clk_attr(struct hl_device *hdev, struct attribute_group *dev_clk_attr_grp); void hl_sysfs_add_dev_vrm_attr(struct hl_device *hdev, struct attribute_group *dev_vrm_attr_grp); +int hl_fw_send_generic_request(struct hl_device *hdev, enum hl_passthrough_type sub_opcode, + dma_addr_t buff, u32 *size); void hw_sob_get(struct hl_hw_sob *hw_sob); void hw_sob_put(struct hl_hw_sob *hw_sob); @@ -3786,6 +3845,7 @@ void hl_dec_fini(struct hl_device *hdev); void hl_dec_ctx_fini(struct hl_ctx *ctx); void hl_release_pending_user_interrupts(struct hl_device *hdev); +void hl_abort_waitings_for_completion(struct hl_device *hdev); int hl_cs_signal_sob_wraparound_handler(struct hl_device *hdev, u32 q_idx, struct hl_hw_sob **hw_sob, u32 count, bool encaps_sig); diff --git a/drivers/misc/habanalabs/common/habanalabs_drv.c b/drivers/accel/habanalabs/common/habanalabs_drv.c index 7815c60df54e..03dae57dc838 100644 --- a/drivers/misc/habanalabs/common/habanalabs_drv.c +++ b/drivers/accel/habanalabs/common/habanalabs_drv.c @@ -222,9 +222,11 @@ int hl_device_open(struct inode *inode, struct file *filp) hl_debugfs_add_file(hpriv); atomic_set(&hdev->captured_err_info.cs_timeout.write_enable, 1); - atomic_set(&hdev->captured_err_info.razwi_info_recorded, 0); - atomic_set(&hdev->captured_err_info.pgf_info_recorded, 0); + atomic_set(&hdev->captured_err_info.razwi_info.razwi_detected, 0); + atomic_set(&hdev->captured_err_info.page_fault_info.page_fault_detected, 0); hdev->captured_err_info.undef_opcode.write_enable = true; + hdev->captured_err_info.razwi_info.razwi_info_available = false; + hdev->captured_err_info.page_fault_info.page_fault_info_available = false; hdev->open_counter++; hdev->last_successful_open_jif = jiffies; diff --git a/drivers/misc/habanalabs/common/habanalabs_ioctl.c b/drivers/accel/habanalabs/common/habanalabs_ioctl.c index b6abfa7761a7..5005e6fca691 100644 --- a/drivers/misc/habanalabs/common/habanalabs_ioctl.c +++ b/drivers/accel/habanalabs/common/habanalabs_ioctl.c @@ -7,7 +7,7 @@ #define pr_fmt(fmt) "habanalabs: " fmt -#include <uapi/misc/habanalabs.h> +#include <uapi/drm/habanalabs_accel.h> #include "habanalabs.h" #include <linux/fs.h> @@ -607,16 +607,20 @@ static int cs_timeout_info(struct hl_fpriv *hpriv, struct hl_info_args *args) static int razwi_info(struct hl_fpriv *hpriv, struct hl_info_args *args) { + void __user *out = (void __user *) (uintptr_t) args->return_pointer; struct hl_device *hdev = hpriv->hdev; u32 max_size = args->return_size; - struct hl_info_razwi_event *info = &hdev->captured_err_info.razwi; - void __user *out = (void __user *) (uintptr_t) args->return_pointer; + struct razwi_info *razwi_info; if ((!max_size) || (!out)) return -EINVAL; - return copy_to_user(out, info, min_t(size_t, max_size, sizeof(struct hl_info_razwi_event))) - ? -EFAULT : 0; + razwi_info = &hdev->captured_err_info.razwi_info; + if (!razwi_info->razwi_info_available) + return 0; + + return copy_to_user(out, &razwi_info->razwi, + min_t(size_t, max_size, sizeof(struct hl_info_razwi_event))) ? -EFAULT : 0; } static int undefined_opcode_info(struct hl_fpriv *hpriv, struct hl_info_args *args) @@ -786,16 +790,20 @@ static int engine_status_info(struct hl_fpriv *hpriv, struct hl_info_args *args) static int page_fault_info(struct hl_fpriv *hpriv, struct hl_info_args *args) { + void __user *out = (void __user *) (uintptr_t) args->return_pointer; struct hl_device *hdev = hpriv->hdev; u32 max_size = args->return_size; - struct hl_page_fault_info *info = &hdev->captured_err_info.pgf_info.pgf; - void __user *out = (void __user *) (uintptr_t) args->return_pointer; + struct page_fault_info *pgf_info; if ((!max_size) || (!out)) return -EINVAL; - return copy_to_user(out, info, min_t(size_t, max_size, sizeof(struct hl_page_fault_info))) - ? -EFAULT : 0; + pgf_info = &hdev->captured_err_info.page_fault_info; + if (!pgf_info->page_fault_info_available) + return 0; + + return copy_to_user(out, &pgf_info->page_fault, + min_t(size_t, max_size, sizeof(struct hl_page_fault_info))) ? -EFAULT : 0; } static int user_mappings_info(struct hl_fpriv *hpriv, struct hl_info_args *args) @@ -806,18 +814,68 @@ static int user_mappings_info(struct hl_fpriv *hpriv, struct hl_info_args *args) struct page_fault_info *pgf_info; u64 actual_size; - pgf_info = &hdev->captured_err_info.pgf_info; - args->array_size = pgf_info->num_of_user_mappings; - if (!out) return -EINVAL; + pgf_info = &hdev->captured_err_info.page_fault_info; + if (!pgf_info->page_fault_info_available) + return 0; + + args->array_size = pgf_info->num_of_user_mappings; + actual_size = pgf_info->num_of_user_mappings * sizeof(struct hl_user_mapping); if (user_buf_size < actual_size) return -ENOMEM; - return copy_to_user(out, pgf_info->user_mappings, min_t(size_t, user_buf_size, actual_size)) - ? -EFAULT : 0; + return copy_to_user(out, pgf_info->user_mappings, actual_size) ? -EFAULT : 0; +} + +static int send_fw_generic_request(struct hl_device *hdev, struct hl_info_args *info_args) +{ + void __user *buff = (void __user *) (uintptr_t) info_args->return_pointer; + u32 size = info_args->return_size; + dma_addr_t dma_handle; + bool need_input_buff; + void *fw_buff; + int rc = 0; + + switch (info_args->fw_sub_opcode) { + case HL_PASSTHROUGH_VERSIONS: + need_input_buff = false; + break; + default: + return -EINVAL; + } + + if (size > SZ_1M) { + dev_err(hdev->dev, "buffer size cannot exceed 1MB\n"); + return -EINVAL; + } + + fw_buff = hl_cpu_accessible_dma_pool_alloc(hdev, size, &dma_handle); + if (!fw_buff) + return -ENOMEM; + + + if (need_input_buff && copy_from_user(fw_buff, buff, size)) { + dev_dbg(hdev->dev, "Failed to copy from user FW buff\n"); + rc = -EFAULT; + goto free_buff; + } + + rc = hl_fw_send_generic_request(hdev, info_args->fw_sub_opcode, dma_handle, &size); + if (rc) + goto free_buff; + + if (copy_to_user(buff, fw_buff, min(size, info_args->return_size))) { + dev_dbg(hdev->dev, "Failed to copy to user FW generic req output\n"); + rc = -EFAULT; + } + +free_buff: + hl_cpu_accessible_dma_pool_free(hdev, info_args->return_size, fw_buff); + + return rc; } static int _hl_info_ioctl(struct hl_fpriv *hpriv, void *data, @@ -826,9 +884,13 @@ static int _hl_info_ioctl(struct hl_fpriv *hpriv, void *data, enum hl_device_status status; struct hl_info_args *args = data; struct hl_device *hdev = hpriv->hdev; - int rc; + if (args->pad) { + dev_dbg(hdev->dev, "Padding bytes must be 0\n"); + return -EINVAL; + } + /* * Information is returned for the following opcodes even if the device * is disabled or in reset. @@ -893,7 +955,7 @@ static int _hl_info_ioctl(struct hl_fpriv *hpriv, void *data, } if (!hl_device_operational(hdev, &status)) { - dev_warn_ratelimited(dev, + dev_dbg_ratelimited(dev, "Device is %s. Can't execute INFO IOCTL\n", hdev->status[status]); return -EBUSY; @@ -947,6 +1009,9 @@ static int _hl_info_ioctl(struct hl_fpriv *hpriv, void *data, case HL_INFO_ENGINE_STATUS: return engine_status_info(hpriv, args); + case HL_INFO_FW_GENERIC_REQ: + return send_fw_generic_request(hdev, args); + default: dev_err(dev, "Invalid request %d\n", args->op); rc = -EINVAL; @@ -975,7 +1040,7 @@ static int hl_debug_ioctl(struct hl_fpriv *hpriv, void *data) int rc = 0; if (!hl_device_operational(hdev, &status)) { - dev_warn_ratelimited(hdev->dev, + dev_dbg_ratelimited(hdev->dev, "Device is %s. Can't execute DEBUG IOCTL\n", hdev->status[status]); return -EBUSY; @@ -1072,8 +1137,6 @@ static long _hl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg, retcode = -EFAULT; goto out_err; } - } else if (cmd & IOC_OUT) { - memset(kdata, 0, usize); } retcode = func(hpriv, kdata); diff --git a/drivers/misc/habanalabs/common/hw_queue.c b/drivers/accel/habanalabs/common/hw_queue.c index d0087c0ec48c..d0087c0ec48c 100644 --- a/drivers/misc/habanalabs/common/hw_queue.c +++ b/drivers/accel/habanalabs/common/hw_queue.c diff --git a/drivers/misc/habanalabs/common/hwmon.c b/drivers/accel/habanalabs/common/hwmon.c index 55eb0203817f..55eb0203817f 100644 --- a/drivers/misc/habanalabs/common/hwmon.c +++ b/drivers/accel/habanalabs/common/hwmon.c diff --git a/drivers/misc/habanalabs/common/irq.c b/drivers/accel/habanalabs/common/irq.c index 94d537fd4fde..04844e843a7b 100644 --- a/drivers/misc/habanalabs/common/irq.c +++ b/drivers/accel/habanalabs/common/irq.c @@ -72,15 +72,17 @@ static void irq_handle_eqe(struct work_struct *work) * @hdev: pointer to device structure * @cs_seq: command submission sequence * @cq: completion queue + * @timestamp: interrupt timestamp * */ -static void job_finish(struct hl_device *hdev, u32 cs_seq, struct hl_cq *cq) +static void job_finish(struct hl_device *hdev, u32 cs_seq, struct hl_cq *cq, ktime_t timestamp) { struct hl_hw_queue *queue; struct hl_cs_job *job; queue = &hdev->kernel_queues[cq->hw_queue_id]; job = queue->shadow_queue[hl_pi_2_offset(cs_seq)]; + job->timestamp = timestamp; queue_work(hdev->cq_wq[cq->cq_idx], &job->finish_work); atomic_inc(&queue->ci); @@ -91,9 +93,10 @@ static void job_finish(struct hl_device *hdev, u32 cs_seq, struct hl_cq *cq) * * @hdev: pointer to device structure * @cs_seq: command submission sequence + * @timestamp: interrupt timestamp * */ -static void cs_finish(struct hl_device *hdev, u16 cs_seq) +static void cs_finish(struct hl_device *hdev, u16 cs_seq, ktime_t timestamp) { struct asic_fixed_properties *prop = &hdev->asic_prop; struct hl_hw_queue *queue; @@ -113,6 +116,7 @@ static void cs_finish(struct hl_device *hdev, u16 cs_seq) atomic_inc(&queue->ci); } + cs->completion_timestamp = timestamp; queue_work(hdev->cs_cmplt_wq, &cs->finish_work); } @@ -130,6 +134,7 @@ irqreturn_t hl_irq_handler_cq(int irq, void *arg) bool shadow_index_valid, entry_ready; u16 shadow_index; struct hl_cq_entry *cq_entry, *cq_base; + ktime_t timestamp = ktime_get(); if (hdev->disabled) { dev_dbg(hdev->dev, @@ -171,9 +176,9 @@ irqreturn_t hl_irq_handler_cq(int irq, void *arg) if (shadow_index_valid && !hdev->disabled) { if (hdev->asic_prop.completion_mode == HL_COMPLETION_MODE_CS) - cs_finish(hdev, shadow_index); + cs_finish(hdev, shadow_index, timestamp); else - job_finish(hdev, shadow_index, cq); + job_finish(hdev, shadow_index, cq, timestamp); } /* Clear CQ entry ready bit */ @@ -228,7 +233,7 @@ static void hl_ts_free_objects(struct work_struct *work) * list to a dedicated workqueue to do the actual put. */ static int handle_registration_node(struct hl_device *hdev, struct hl_user_pending_interrupt *pend, - struct list_head **free_list) + struct list_head **free_list, ktime_t now) { struct timestamp_reg_free_node *free_node; u64 timestamp; @@ -246,7 +251,7 @@ static int handle_registration_node(struct hl_device *hdev, struct hl_user_pendi if (!free_node) return -ENOMEM; - timestamp = ktime_get_ns(); + timestamp = ktime_to_ns(now); *pend->ts_reg_info.timestamp_kernel_addr = timestamp; @@ -298,7 +303,7 @@ static void handle_user_interrupt(struct hl_device *hdev, struct hl_user_interru if (pend->ts_reg_info.buf) { if (!reg_node_handle_fail) { rc = handle_registration_node(hdev, pend, - &ts_reg_free_list_head); + &ts_reg_free_list_head, now); if (rc) reg_node_handle_fail = true; } @@ -333,13 +338,22 @@ irqreturn_t hl_irq_handler_user_interrupt(int irq, void *arg) struct hl_user_interrupt *user_int = arg; struct hl_device *hdev = user_int->hdev; - if (user_int->is_decoder) - handle_user_interrupt(hdev, &hdev->common_decoder_interrupt); - else + switch (user_int->type) { + case HL_USR_INTERRUPT_CQ: handle_user_interrupt(hdev, &hdev->common_user_cq_interrupt); - /* Handle user cq or decoder interrupts registered on this specific irq */ - handle_user_interrupt(hdev, user_int); + /* Handle user cq interrupt registered on this specific irq */ + handle_user_interrupt(hdev, user_int); + break; + case HL_USR_INTERRUPT_DECODER: + handle_user_interrupt(hdev, &hdev->common_decoder_interrupt); + + /* Handle decoder interrupt registered on this specific irq */ + handle_user_interrupt(hdev, user_int); + break; + default: + break; + } return IRQ_HANDLED; } diff --git a/drivers/misc/habanalabs/common/memory.c b/drivers/accel/habanalabs/common/memory.c index 5e9ae7600d75..e6474d38afc4 100644 --- a/drivers/misc/habanalabs/common/memory.c +++ b/drivers/accel/habanalabs/common/memory.c @@ -5,7 +5,7 @@ * All Rights Reserved. */ -#include <uapi/misc/habanalabs.h> +#include <uapi/drm/habanalabs_accel.h> #include "habanalabs.h" #include "../include/hw_ip/mmu/mmu_general.h" @@ -19,7 +19,9 @@ MODULE_IMPORT_NS(DMA_BUF); #define HL_MMU_DEBUG 0 /* use small pages for supporting non-pow2 (32M/40M/48M) DRAM phys page sizes */ -#define DRAM_POOL_PAGE_SIZE SZ_8M +#define DRAM_POOL_PAGE_SIZE SZ_8M + +#define MEM_HANDLE_INVALID ULONG_MAX static int allocate_timestamps_buffers(struct hl_fpriv *hpriv, struct hl_mem_in *args, u64 *handle); @@ -371,12 +373,6 @@ static int free_device_memory(struct hl_ctx *ctx, struct hl_mem_in *args) return -EINVAL; } - if (phys_pg_pack->exporting_cnt) { - spin_unlock(&vm->idr_lock); - dev_dbg(hdev->dev, "handle %u is exported, cannot free\n", handle); - return -EINVAL; - } - /* must remove from idr before the freeing of the physical pages as the refcount of the pool * is also the trigger of the idr destroy */ @@ -1240,6 +1236,7 @@ static int map_device_va(struct hl_ctx *ctx, struct hl_mem_in *args, u64 *device hnode->ptr = vm_type; hnode->vaddr = ret_vaddr; + hnode->handle = is_userptr ? MEM_HANDLE_INVALID : handle; mutex_lock(&ctx->mem_hash_lock); hash_add(ctx->mem_hash, &hnode->node, ret_vaddr); @@ -1313,6 +1310,12 @@ static int unmap_device_va(struct hl_ctx *ctx, struct hl_mem_in *args, return -EINVAL; } + if (hnode->export_cnt) { + mutex_unlock(&ctx->mem_hash_lock); + dev_err(hdev->dev, "failed to unmap %#llx, memory is exported\n", vaddr); + return -EINVAL; + } + hash_del(&hnode->node); mutex_unlock(&ctx->mem_hash_lock); @@ -1545,10 +1548,10 @@ static int set_dma_sg(struct scatterlist *sg, u64 bar_address, u64 chunk_size, } static struct sg_table *alloc_sgt_from_device_pages(struct hl_device *hdev, u64 *pages, u64 npages, - u64 page_size, struct device *dev, - enum dma_data_direction dir) + u64 page_size, u64 exported_size, + struct device *dev, enum dma_data_direction dir) { - u64 chunk_size, bar_address, dma_max_seg_size; + u64 chunk_size, bar_address, dma_max_seg_size, cur_size_to_export, cur_npages; struct asic_fixed_properties *prop; int rc, i, j, nents, cur_page; struct scatterlist *sg; @@ -1574,16 +1577,23 @@ static struct sg_table *alloc_sgt_from_device_pages(struct hl_device *hdev, u64 if (!sgt) return ERR_PTR(-ENOMEM); + /* remove export size restrictions in case not explicitly defined */ + cur_size_to_export = exported_size ? exported_size : (npages * page_size); + /* If the size of each page is larger than the dma max segment size, * then we can't combine pages and the number of entries in the SGL * will just be the * <number of pages> * <chunks of max segment size in each page> */ - if (page_size > dma_max_seg_size) - nents = npages * DIV_ROUND_UP_ULL(page_size, dma_max_seg_size); - else + if (page_size > dma_max_seg_size) { + /* we should limit number of pages according to the exported size */ + cur_npages = DIV_ROUND_UP_SECTOR_T(cur_size_to_export, page_size); + nents = cur_npages * DIV_ROUND_UP_SECTOR_T(page_size, dma_max_seg_size); + } else { + cur_npages = npages; + /* Get number of non-contiguous chunks */ - for (i = 1, nents = 1, chunk_size = page_size ; i < npages ; i++) { + for (i = 1, nents = 1, chunk_size = page_size ; i < cur_npages ; i++) { if (pages[i - 1] + page_size != pages[i] || chunk_size + page_size > dma_max_seg_size) { nents++; @@ -1593,6 +1603,7 @@ static struct sg_table *alloc_sgt_from_device_pages(struct hl_device *hdev, u64 chunk_size += page_size; } + } rc = sg_alloc_table(sgt, nents, GFP_KERNEL | __GFP_ZERO); if (rc) @@ -1615,7 +1626,8 @@ static struct sg_table *alloc_sgt_from_device_pages(struct hl_device *hdev, u64 else cur_device_address += dma_max_seg_size; - chunk_size = min(size_left, dma_max_seg_size); + /* make sure not to export over exported size */ + chunk_size = min3(size_left, dma_max_seg_size, cur_size_to_export); bar_address = hdev->dram_pci_bar_start + cur_device_address; @@ -1623,6 +1635,8 @@ static struct sg_table *alloc_sgt_from_device_pages(struct hl_device *hdev, u64 if (rc) goto error_unmap; + cur_size_to_export -= chunk_size; + if (size_left > dma_max_seg_size) { size_left -= dma_max_seg_size; } else { @@ -1634,7 +1648,7 @@ static struct sg_table *alloc_sgt_from_device_pages(struct hl_device *hdev, u64 /* Merge pages and put them into the scatterlist */ for_each_sgtable_dma_sg(sgt, sg, i) { chunk_size = page_size; - for (j = cur_page + 1 ; j < npages ; j++) { + for (j = cur_page + 1 ; j < cur_npages ; j++) { if (pages[j - 1] + page_size != pages[j] || chunk_size + page_size > dma_max_seg_size) break; @@ -1645,10 +1659,13 @@ static struct sg_table *alloc_sgt_from_device_pages(struct hl_device *hdev, u64 bar_address = hdev->dram_pci_bar_start + (pages[cur_page] - prop->dram_base_address); + /* make sure not to export over exported size */ + chunk_size = min(chunk_size, cur_size_to_export); rc = set_dma_sg(sg, bar_address, chunk_size, dev, dir); if (rc) goto error_unmap; + cur_size_to_export -= chunk_size; cur_page = j; } } @@ -1719,6 +1736,7 @@ static struct sg_table *hl_map_dmabuf(struct dma_buf_attachment *attachment, phys_pg_pack->pages, phys_pg_pack->npages, phys_pg_pack->page_size, + phys_pg_pack->exported_size, attachment->dev, dir); else @@ -1726,6 +1744,7 @@ static struct sg_table *hl_map_dmabuf(struct dma_buf_attachment *attachment, &hl_dmabuf->device_address, 1, hl_dmabuf->dmabuf->size, + 0, attachment->dev, dir); @@ -1763,18 +1782,20 @@ static void hl_unmap_dmabuf(struct dma_buf_attachment *attachment, static void hl_release_dmabuf(struct dma_buf *dmabuf) { struct hl_dmabuf_priv *hl_dmabuf = dmabuf->priv; - struct hl_ctx *ctx = hl_dmabuf->ctx; - struct hl_device *hdev = ctx->hdev; - struct hl_vm *vm = &hdev->vm; + struct hl_ctx *ctx; - if (hl_dmabuf->phys_pg_pack) { - spin_lock(&vm->idr_lock); - hl_dmabuf->phys_pg_pack->exporting_cnt--; - spin_unlock(&vm->idr_lock); - } + if (!hl_dmabuf) + return; - hl_ctx_put(hl_dmabuf->ctx); + ctx = hl_dmabuf->ctx; + if (hl_dmabuf->memhash_hnode) { + mutex_lock(&ctx->mem_hash_lock); + hl_dmabuf->memhash_hnode->export_cnt--; + mutex_unlock(&ctx->mem_hash_lock); + } + + hl_ctx_put(ctx); kfree(hl_dmabuf); } @@ -1785,7 +1806,7 @@ static const struct dma_buf_ops habanalabs_dmabuf_ops = { .release = hl_release_dmabuf, }; -static int export_dmabuf_common(struct hl_ctx *ctx, +static int export_dmabuf(struct hl_ctx *ctx, struct hl_dmabuf_priv *hl_dmabuf, u64 total_size, int flags, int *dmabuf_fd) { @@ -1806,7 +1827,7 @@ static int export_dmabuf_common(struct hl_ctx *ctx, fd = dma_buf_fd(hl_dmabuf->dmabuf, flags); if (fd < 0) { - dev_err(hdev->dev, "failed to get a file descriptor for a dma-buf\n"); + dev_err(hdev->dev, "failed to get a file descriptor for a dma-buf, %d\n", fd); rc = fd; goto err_dma_buf_put; } @@ -1819,36 +1840,13 @@ static int export_dmabuf_common(struct hl_ctx *ctx, return 0; err_dma_buf_put: + hl_dmabuf->dmabuf->priv = NULL; dma_buf_put(hl_dmabuf->dmabuf); return rc; } -/** - * export_dmabuf_from_addr() - export a dma-buf object for the given memory - * address and size. - * @ctx: pointer to the context structure. - * @device_addr: device memory physical address. - * @size: size of device memory. - * @flags: DMA-BUF file/FD flags. - * @dmabuf_fd: pointer to result FD that represents the dma-buf object. - * - * Create and export a dma-buf object for an existing memory allocation inside - * the device memory, and return a FD which is associated with the dma-buf - * object. - * - * Return: 0 on success, non-zero for failure. - */ -static int export_dmabuf_from_addr(struct hl_ctx *ctx, u64 device_addr, - u64 size, int flags, int *dmabuf_fd) +static int validate_export_params_common(struct hl_device *hdev, u64 device_addr, u64 size) { - struct hl_dmabuf_priv *hl_dmabuf; - struct hl_device *hdev = ctx->hdev; - struct asic_fixed_properties *prop; - u64 bar_address; - int rc; - - prop = &hdev->asic_prop; - if (!IS_ALIGNED(device_addr, PAGE_SIZE)) { dev_dbg(hdev->dev, "exported device memory address 0x%llx should be aligned to 0x%lx\n", @@ -1863,49 +1861,150 @@ static int export_dmabuf_from_addr(struct hl_ctx *ctx, u64 device_addr, return -EINVAL; } + return 0; +} + +static int validate_export_params_no_mmu(struct hl_device *hdev, u64 device_addr, u64 size) +{ + struct asic_fixed_properties *prop = &hdev->asic_prop; + u64 bar_address; + int rc; + + rc = validate_export_params_common(hdev, device_addr, size); + if (rc) + return rc; + if (device_addr < prop->dram_user_base_address || - device_addr + size > prop->dram_end_address || - device_addr + size < device_addr) { + (device_addr + size) > prop->dram_end_address || + (device_addr + size) < device_addr) { dev_dbg(hdev->dev, "DRAM memory range 0x%llx (+0x%llx) is outside of DRAM boundaries\n", device_addr, size); return -EINVAL; } - bar_address = hdev->dram_pci_bar_start + - (device_addr - prop->dram_base_address); + bar_address = hdev->dram_pci_bar_start + (device_addr - prop->dram_base_address); - if (bar_address + size > - hdev->dram_pci_bar_start + prop->dram_pci_bar_size || - bar_address + size < bar_address) { + if ((bar_address + size) > (hdev->dram_pci_bar_start + prop->dram_pci_bar_size) || + (bar_address + size) < bar_address) { dev_dbg(hdev->dev, "DRAM memory range 0x%llx (+0x%llx) is outside of PCI BAR boundaries\n", device_addr, size); return -EINVAL; } - hl_dmabuf = kzalloc(sizeof(*hl_dmabuf), GFP_KERNEL); - if (!hl_dmabuf) - return -ENOMEM; + return 0; +} - hl_dmabuf->device_address = device_addr; +static int validate_export_params(struct hl_device *hdev, u64 device_addr, u64 size, u64 offset, + struct hl_vm_phys_pg_pack *phys_pg_pack) +{ + struct asic_fixed_properties *prop = &hdev->asic_prop; + u64 bar_address; + int i, rc; - rc = export_dmabuf_common(ctx, hl_dmabuf, size, flags, dmabuf_fd); + rc = validate_export_params_common(hdev, device_addr, size); if (rc) - goto err_free_dmabuf_wrapper; + return rc; + + if ((offset + size) > phys_pg_pack->total_size) { + dev_dbg(hdev->dev, "offset %#llx and size %#llx exceed total map size %#llx\n", + offset, size, phys_pg_pack->total_size); + return -EINVAL; + } + + for (i = 0 ; i < phys_pg_pack->npages ; i++) { + + bar_address = hdev->dram_pci_bar_start + + (phys_pg_pack->pages[i] - prop->dram_base_address); + + if ((bar_address + phys_pg_pack->page_size) > + (hdev->dram_pci_bar_start + prop->dram_pci_bar_size) || + (bar_address + phys_pg_pack->page_size) < bar_address) { + dev_dbg(hdev->dev, + "DRAM memory range 0x%llx (+0x%x) is outside of PCI BAR boundaries\n", + phys_pg_pack->pages[i], + phys_pg_pack->page_size); + + return -EINVAL; + } + } return 0; +} -err_free_dmabuf_wrapper: - kfree(hl_dmabuf); - return rc; +static struct hl_vm_hash_node *memhash_node_export_get(struct hl_ctx *ctx, u64 addr) +{ + struct hl_device *hdev = ctx->hdev; + struct hl_vm_hash_node *hnode; + + /* get the memory handle */ + mutex_lock(&ctx->mem_hash_lock); + hash_for_each_possible(ctx->mem_hash, hnode, node, (unsigned long)addr) + if (addr == hnode->vaddr) + break; + + if (!hnode) { + mutex_unlock(&ctx->mem_hash_lock); + dev_dbg(hdev->dev, "map address %#llx not found\n", addr); + return ERR_PTR(-EINVAL); + } + + if (upper_32_bits(hnode->handle)) { + mutex_unlock(&ctx->mem_hash_lock); + dev_dbg(hdev->dev, "invalid handle %#llx for map address %#llx\n", + hnode->handle, addr); + return ERR_PTR(-EINVAL); + } + + /* + * node found, increase export count so this memory cannot be unmapped + * and the hash node cannot be deleted. + */ + hnode->export_cnt++; + mutex_unlock(&ctx->mem_hash_lock); + + return hnode; +} + +static void memhash_node_export_put(struct hl_ctx *ctx, struct hl_vm_hash_node *hnode) +{ + mutex_lock(&ctx->mem_hash_lock); + hnode->export_cnt--; + mutex_unlock(&ctx->mem_hash_lock); +} + +static struct hl_vm_phys_pg_pack *get_phys_pg_pack_from_hash_node(struct hl_device *hdev, + struct hl_vm_hash_node *hnode) +{ + struct hl_vm_phys_pg_pack *phys_pg_pack; + struct hl_vm *vm = &hdev->vm; + + spin_lock(&vm->idr_lock); + phys_pg_pack = idr_find(&vm->phys_pg_pack_handles, (u32) hnode->handle); + if (!phys_pg_pack) { + spin_unlock(&vm->idr_lock); + dev_dbg(hdev->dev, "no match for handle 0x%x\n", (u32) hnode->handle); + return ERR_PTR(-EINVAL); + } + + spin_unlock(&vm->idr_lock); + + if (phys_pg_pack->vm_type != VM_TYPE_PHYS_PACK) { + dev_dbg(hdev->dev, "handle 0x%llx does not represent DRAM memory\n", hnode->handle); + return ERR_PTR(-EINVAL); + } + + return phys_pg_pack; } /** - * export_dmabuf_from_handle() - export a dma-buf object for the given memory - * handle. + * export_dmabuf_from_addr() - export a dma-buf object for the given memory + * address and size. * @ctx: pointer to the context structure. - * @handle: device memory allocation handle. + * @addr: device address. + * @size: size of device memory to export. + * @offset: the offset into the buffer from which to start exporting * @flags: DMA-BUF file/FD flags. * @dmabuf_fd: pointer to result FD that represents the dma-buf object. * @@ -1915,87 +2014,69 @@ err_free_dmabuf_wrapper: * * Return: 0 on success, non-zero for failure. */ -static int export_dmabuf_from_handle(struct hl_ctx *ctx, u64 handle, int flags, - int *dmabuf_fd) +static int export_dmabuf_from_addr(struct hl_ctx *ctx, u64 addr, u64 size, u64 offset, + int flags, int *dmabuf_fd) { - struct hl_vm_phys_pg_pack *phys_pg_pack; - struct hl_dmabuf_priv *hl_dmabuf; - struct hl_device *hdev = ctx->hdev; + struct hl_vm_phys_pg_pack *phys_pg_pack = NULL; + struct hl_vm_hash_node *hnode = NULL; struct asic_fixed_properties *prop; - struct hl_vm *vm = &hdev->vm; - u64 bar_address; - int rc, i; + struct hl_dmabuf_priv *hl_dmabuf; + struct hl_device *hdev; + u64 export_addr; + int rc; + hdev = ctx->hdev; prop = &hdev->asic_prop; - if (upper_32_bits(handle)) { - dev_dbg(hdev->dev, "no match for handle 0x%llx\n", handle); + /* offset must be 0 in devices without virtual memory support */ + if (!prop->dram_supports_virtual_memory && offset) { + dev_dbg(hdev->dev, "offset is not allowed in device without virtual memory\n"); return -EINVAL; } - spin_lock(&vm->idr_lock); + export_addr = addr + offset; - phys_pg_pack = idr_find(&vm->phys_pg_pack_handles, (u32) handle); - if (!phys_pg_pack) { - spin_unlock(&vm->idr_lock); - dev_dbg(hdev->dev, "no match for handle 0x%x\n", (u32) handle); - return -EINVAL; - } - - /* increment now to avoid freeing device memory while exporting */ - phys_pg_pack->exporting_cnt++; - - spin_unlock(&vm->idr_lock); - - if (phys_pg_pack->vm_type != VM_TYPE_PHYS_PACK) { - dev_dbg(hdev->dev, "handle 0x%llx does not represent DRAM memory\n", handle); - rc = -EINVAL; - goto err_dec_exporting_cnt; - } - - for (i = 0 ; i < phys_pg_pack->npages ; i++) { - - bar_address = hdev->dram_pci_bar_start + - (phys_pg_pack->pages[i] - - prop->dram_base_address); - - if (bar_address + phys_pg_pack->page_size > - hdev->dram_pci_bar_start + prop->dram_pci_bar_size || - bar_address + phys_pg_pack->page_size < bar_address) { - - dev_dbg(hdev->dev, - "DRAM memory range 0x%llx (+0x%x) is outside of PCI BAR boundaries\n", - phys_pg_pack->pages[i], - phys_pg_pack->page_size); + hl_dmabuf = kzalloc(sizeof(*hl_dmabuf), GFP_KERNEL); + if (!hl_dmabuf) + return -ENOMEM; - rc = -EINVAL; - goto err_dec_exporting_cnt; + if (prop->dram_supports_virtual_memory) { + hnode = memhash_node_export_get(ctx, addr); + if (IS_ERR(hnode)) { + rc = PTR_ERR(hnode); + goto err_free_dmabuf_wrapper; } - } + phys_pg_pack = get_phys_pg_pack_from_hash_node(hdev, hnode); + if (IS_ERR(phys_pg_pack)) { + rc = PTR_ERR(phys_pg_pack); + goto dec_memhash_export_cnt; + } + rc = validate_export_params(hdev, export_addr, size, offset, phys_pg_pack); + if (rc) + goto dec_memhash_export_cnt; - hl_dmabuf = kzalloc(sizeof(*hl_dmabuf), GFP_KERNEL); - if (!hl_dmabuf) { - rc = -ENOMEM; - goto err_dec_exporting_cnt; + phys_pg_pack->exported_size = size; + hl_dmabuf->phys_pg_pack = phys_pg_pack; + hl_dmabuf->memhash_hnode = hnode; + } else { + rc = validate_export_params_no_mmu(hdev, export_addr, size); + if (rc) + goto err_free_dmabuf_wrapper; } - hl_dmabuf->phys_pg_pack = phys_pg_pack; + hl_dmabuf->device_address = export_addr; - rc = export_dmabuf_common(ctx, hl_dmabuf, phys_pg_pack->total_size, - flags, dmabuf_fd); + rc = export_dmabuf(ctx, hl_dmabuf, size, flags, dmabuf_fd); if (rc) - goto err_free_dmabuf_wrapper; + goto dec_memhash_export_cnt; return 0; +dec_memhash_export_cnt: + if (prop->dram_supports_virtual_memory) + memhash_node_export_put(ctx, hnode); err_free_dmabuf_wrapper: kfree(hl_dmabuf); - -err_dec_exporting_cnt: - spin_lock(&vm->idr_lock); - phys_pg_pack->exporting_cnt--; - spin_unlock(&vm->idr_lock); - return rc; } @@ -2089,12 +2170,13 @@ static int hl_ts_mmap(struct hl_mmap_mem_buf *buf, struct vm_area_struct *vma, v static int hl_ts_alloc_buf(struct hl_mmap_mem_buf *buf, gfp_t gfp, void *args) { struct hl_ts_buff *ts_buff = NULL; - u32 size, num_elements; + u32 num_elements; + size_t size; void *p; num_elements = *(u32 *)args; - ts_buff = kzalloc(sizeof(*ts_buff), GFP_KERNEL); + ts_buff = kzalloc(sizeof(*ts_buff), gfp); if (!ts_buff) return -ENOMEM; @@ -2180,7 +2262,7 @@ int hl_mem_ioctl(struct hl_fpriv *hpriv, void *data) int rc, dmabuf_fd = -EBADF; if (!hl_device_operational(hdev, &status)) { - dev_warn_ratelimited(hdev->dev, + dev_dbg_ratelimited(hdev->dev, "Device is %s. Can't execute MEMORY IOCTL\n", hdev->status[status]); return -EBUSY; @@ -2269,17 +2351,12 @@ int hl_mem_ioctl(struct hl_fpriv *hpriv, void *data) break; case HL_MEM_OP_EXPORT_DMABUF_FD: - if (hdev->asic_prop.dram_supports_virtual_memory) - rc = export_dmabuf_from_handle(ctx, - args->in.export_dmabuf_fd.handle, - args->in.flags, - &dmabuf_fd); - else - rc = export_dmabuf_from_addr(ctx, - args->in.export_dmabuf_fd.handle, - args->in.export_dmabuf_fd.mem_size, - args->in.flags, - &dmabuf_fd); + rc = export_dmabuf_from_addr(ctx, + args->in.export_dmabuf_fd.addr, + args->in.export_dmabuf_fd.mem_size, + args->in.export_dmabuf_fd.offset, + args->in.flags, + &dmabuf_fd); memset(args, 0, sizeof(*args)); args->out.fd = dmabuf_fd; break; diff --git a/drivers/misc/habanalabs/common/memory_mgr.c b/drivers/accel/habanalabs/common/memory_mgr.c index 1936d653699e..0f2759e26547 100644 --- a/drivers/misc/habanalabs/common/memory_mgr.c +++ b/drivers/accel/habanalabs/common/memory_mgr.c @@ -25,8 +25,7 @@ struct hl_mmap_mem_buf *hl_mmap_mem_buf_get(struct hl_mem_mgr *mmg, u64 handle) buf = idr_find(&mmg->handles, lower_32_bits(handle >> PAGE_SHIFT)); if (!buf) { spin_unlock(&mmg->lock); - dev_warn(mmg->dev, - "Buff get failed, no match to handle %#llx\n", handle); + dev_dbg(mmg->dev, "Buff get failed, no match to handle %#llx\n", handle); return NULL; } kref_get(&buf->refcount); diff --git a/drivers/misc/habanalabs/common/mmu/Makefile b/drivers/accel/habanalabs/common/mmu/Makefile index 1806c524e04a..1806c524e04a 100644 --- a/drivers/misc/habanalabs/common/mmu/Makefile +++ b/drivers/accel/habanalabs/common/mmu/Makefile diff --git a/drivers/misc/habanalabs/common/mmu/mmu.c b/drivers/accel/habanalabs/common/mmu/mmu.c index 2c1005f74cf4..a42ae8bc61e8 100644 --- a/drivers/misc/habanalabs/common/mmu/mmu.c +++ b/drivers/accel/habanalabs/common/mmu/mmu.c @@ -781,7 +781,7 @@ static void mmu_dma_mem_free_from_chunk(struct gen_pool *pool, struct gen_pool_chunk *chunk, void *data) { - struct hl_device *hdev = (struct hl_device *)data; + struct hl_device *hdev = data; hl_asic_dma_free_coherent(hdev, (chunk->end_addr - chunk->start_addr) + 1, (void *)chunk->start_addr, chunk->phys_addr); diff --git a/drivers/misc/habanalabs/common/mmu/mmu_v1.c b/drivers/accel/habanalabs/common/mmu/mmu_v1.c index 8a40de4a4761..d925dc4dd097 100644 --- a/drivers/misc/habanalabs/common/mmu/mmu_v1.c +++ b/drivers/accel/habanalabs/common/mmu/mmu_v1.c @@ -345,7 +345,6 @@ static void dram_default_mapping_fini(struct hl_ctx *ctx) } hop2_pte_addr = hop2_addr; - hop2_pte_addr = hop2_addr; for (i = 0 ; i < num_of_hop3 ; i++) { clear_pte(ctx, hop2_pte_addr); put_pte(ctx, hop2_addr); diff --git a/drivers/misc/habanalabs/common/mmu/mmu_v2_hr.c b/drivers/accel/habanalabs/common/mmu/mmu_v2_hr.c index afe7ef964f82..afe7ef964f82 100644 --- a/drivers/misc/habanalabs/common/mmu/mmu_v2_hr.c +++ b/drivers/accel/habanalabs/common/mmu/mmu_v2_hr.c diff --git a/drivers/misc/habanalabs/common/pci/Makefile b/drivers/accel/habanalabs/common/pci/Makefile index dc922a686683..dc922a686683 100644 --- a/drivers/misc/habanalabs/common/pci/Makefile +++ b/drivers/accel/habanalabs/common/pci/Makefile diff --git a/drivers/misc/habanalabs/common/pci/pci.c b/drivers/accel/habanalabs/common/pci/pci.c index 5fe3da5fba30..d1f4c695baf2 100644 --- a/drivers/misc/habanalabs/common/pci/pci.c +++ b/drivers/accel/habanalabs/common/pci/pci.c @@ -10,6 +10,8 @@ #include <linux/pci.h> +#include <trace/events/habanalabs.h> + #define HL_PLDM_PCI_ELBI_TIMEOUT_MSEC (HL_PCI_ELBI_TIMEOUT_MSEC * 100) #define IATU_REGION_CTRL_REGION_EN_MASK BIT(31) @@ -120,6 +122,9 @@ int hl_pci_elbi_read(struct hl_device *hdev, u64 addr, u32 *data) if ((val & PCI_CONFIG_ELBI_STS_MASK) == PCI_CONFIG_ELBI_STS_DONE) { pci_read_config_dword(pdev, mmPCI_CONFIG_ELBI_DATA, data); + if (unlikely(trace_habanalabs_elbi_read_enabled())) + trace_habanalabs_elbi_read(hdev->dev, (u32) addr, val); + return 0; } @@ -179,8 +184,11 @@ static int hl_pci_elbi_write(struct hl_device *hdev, u64 addr, u32 data) usleep_range(300, 500); } - if ((val & PCI_CONFIG_ELBI_STS_MASK) == PCI_CONFIG_ELBI_STS_DONE) + if ((val & PCI_CONFIG_ELBI_STS_MASK) == PCI_CONFIG_ELBI_STS_DONE) { + if (unlikely(trace_habanalabs_elbi_write_enabled())) + trace_habanalabs_elbi_write(hdev->dev, (u32) addr, val); return 0; + } if (val & PCI_CONFIG_ELBI_STS_ERR) return -EIO; diff --git a/drivers/misc/habanalabs/common/security.c b/drivers/accel/habanalabs/common/security.c index 6196c0487c8b..5f03ade07ead 100644 --- a/drivers/misc/habanalabs/common/security.c +++ b/drivers/accel/habanalabs/common/security.c @@ -7,6 +7,19 @@ #include "habanalabs.h" +static const char * const hl_glbl_error_cause[HL_MAX_NUM_OF_GLBL_ERR_CAUSE] = { + "Error due to un-priv read", + "Error due to un-secure read", + "Error due to read from unmapped reg", + "Error due to un-priv write", + "Error due to un-secure write", + "Error due to write to unmapped reg", + "External I/F write sec violation", + "External I/F write to un-mapped reg", + "Read to write only", + "Write to read only" +}; + /** * hl_get_pb_block - return the relevant block within the block array * @@ -598,3 +611,164 @@ void hl_ack_pb_single_dcore(struct hl_device *hdev, u32 dcore_offset, blocks_array_size); } + +static u32 hl_automated_get_block_base_addr(struct hl_device *hdev, + struct hl_special_block_info *block_info, + u32 major, u32 minor, u32 sub_minor) +{ + u32 fw_block_base_address = block_info->base_addr + + major * block_info->major_offset + + minor * block_info->minor_offset + + sub_minor * block_info->sub_minor_offset; + struct asic_fixed_properties *prop = &hdev->asic_prop; + + /* Calculation above returns an address for FW use, and therefore should + * be casted for driver use. + */ + return (fw_block_base_address - lower_32_bits(prop->cfg_base_address)); +} + +static bool hl_check_block_type_exclusion(struct hl_skip_blocks_cfg *skip_blocks_cfg, + int block_type) +{ + int i; + + /* Check if block type is listed in the exclusion list of block types */ + for (i = 0 ; i < skip_blocks_cfg->block_types_len ; i++) + if (block_type == skip_blocks_cfg->block_types[i]) + return true; + + return false; +} + +static bool hl_check_block_range_exclusion(struct hl_device *hdev, + struct hl_skip_blocks_cfg *skip_blocks_cfg, + struct hl_special_block_info *block_info, + u32 major, u32 minor, u32 sub_minor) +{ + u32 blocks_in_range, block_base_addr_in_range, block_base_addr; + int i, j; + + block_base_addr = hl_automated_get_block_base_addr(hdev, block_info, + major, minor, sub_minor); + + for (i = 0 ; i < skip_blocks_cfg->block_ranges_len ; i++) { + blocks_in_range = (skip_blocks_cfg->block_ranges[i].end - + skip_blocks_cfg->block_ranges[i].start) / + HL_BLOCK_SIZE + 1; + for (j = 0 ; j < blocks_in_range ; j++) { + block_base_addr_in_range = skip_blocks_cfg->block_ranges[i].start + + j * HL_BLOCK_SIZE; + if (block_base_addr == block_base_addr_in_range) + return true; + } + } + + return false; +} + +static int hl_read_glbl_errors(struct hl_device *hdev, + u32 blk_idx, u32 major, u32 minor, u32 sub_minor, void *data) +{ + struct hl_special_block_info *special_blocks = hdev->asic_prop.special_blocks; + struct hl_special_block_info *current_block = &special_blocks[blk_idx]; + u32 glbl_err_addr, glbl_err_cause, addr_val, cause_val, block_base, + base = current_block->base_addr - lower_32_bits(hdev->asic_prop.cfg_base_address); + int i; + + block_base = base + major * current_block->major_offset + + minor * current_block->minor_offset + + sub_minor * current_block->sub_minor_offset; + + glbl_err_cause = block_base + HL_GLBL_ERR_CAUSE_OFFSET; + cause_val = RREG32(glbl_err_cause); + if (!cause_val) + return 0; + + glbl_err_addr = block_base + HL_GLBL_ERR_ADDR_OFFSET; + addr_val = RREG32(glbl_err_addr); + + for (i = 0 ; i < hdev->asic_prop.glbl_err_cause_num ; i++) { + if (cause_val & BIT(i)) + dev_err_ratelimited(hdev->dev, + "%s, addr %#llx\n", + hl_glbl_error_cause[i], + hdev->asic_prop.cfg_base_address + block_base + + FIELD_GET(HL_GLBL_ERR_ADDRESS_MASK, addr_val)); + } + + WREG32(glbl_err_cause, cause_val); + + return 0; +} + +void hl_check_for_glbl_errors(struct hl_device *hdev) +{ + struct asic_fixed_properties *prop = &hdev->asic_prop; + struct hl_special_blocks_cfg special_blocks_cfg; + struct iterate_special_ctx glbl_err_iter; + int rc; + + memset(&special_blocks_cfg, 0, sizeof(special_blocks_cfg)); + special_blocks_cfg.skip_blocks_cfg = &prop->skip_special_blocks_cfg; + + glbl_err_iter.fn = &hl_read_glbl_errors; + glbl_err_iter.data = &special_blocks_cfg; + + rc = hl_iterate_special_blocks(hdev, &glbl_err_iter); + if (rc) + dev_err_ratelimited(hdev->dev, + "Could not iterate special blocks, glbl error check failed\n"); +} + +int hl_iterate_special_blocks(struct hl_device *hdev, struct iterate_special_ctx *ctx) +{ + struct hl_special_blocks_cfg *special_blocks_cfg = + (struct hl_special_blocks_cfg *)ctx->data; + struct hl_skip_blocks_cfg *skip_blocks_cfg = + special_blocks_cfg->skip_blocks_cfg; + u32 major, minor, sub_minor, blk_idx, num_blocks; + struct hl_special_block_info *block_info_arr; + int rc; + + block_info_arr = hdev->asic_prop.special_blocks; + if (!block_info_arr) + return -EINVAL; + + num_blocks = hdev->asic_prop.num_of_special_blocks; + + for (blk_idx = 0 ; blk_idx < num_blocks ; blk_idx++, block_info_arr++) { + if (hl_check_block_type_exclusion(skip_blocks_cfg, block_info_arr->block_type)) + continue; + + for (major = 0 ; major < block_info_arr->major ; major++) { + minor = 0; + do { + sub_minor = 0; + do { + if ((hl_check_block_range_exclusion(hdev, + skip_blocks_cfg, block_info_arr, + major, minor, sub_minor)) || + (skip_blocks_cfg->skip_block_hook && + skip_blocks_cfg->skip_block_hook(hdev, + special_blocks_cfg, + blk_idx, major, minor, sub_minor))) { + sub_minor++; + continue; + } + + rc = ctx->fn(hdev, blk_idx, major, minor, + sub_minor, ctx->data); + if (rc) + return rc; + + sub_minor++; + } while (sub_minor < block_info_arr->sub_minor); + + minor++; + } while (minor < block_info_arr->minor); + } + } + + return 0; +} diff --git a/drivers/accel/habanalabs/common/security.h b/drivers/accel/habanalabs/common/security.h new file mode 100644 index 000000000000..234b4a6ed8bc --- /dev/null +++ b/drivers/accel/habanalabs/common/security.h @@ -0,0 +1,163 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright 2016-2022 HabanaLabs, Ltd. + * All Rights Reserved. + * + */ + +#ifndef SECURITY_H_ +#define SECURITY_H_ + +#include <linux/io-64-nonatomic-lo-hi.h> + +extern struct hl_device *hdev; + +/* special blocks */ +#define HL_MAX_NUM_OF_GLBL_ERR_CAUSE 10 +#define HL_GLBL_ERR_ADDRESS_MASK GENMASK(11, 0) +/* GLBL_ERR_ADDR register offset from the start of the block */ +#define HL_GLBL_ERR_ADDR_OFFSET 0xF44 +/* GLBL_ERR_CAUSE register offset from the start of the block */ +#define HL_GLBL_ERR_CAUSE_OFFSET 0xF48 + +/* + * struct hl_special_block_info - stores address details of a particular type of + * IP block which has a SPECIAL part. + * + * @block_type: block type as described in every ASIC's block_types enum. + * @base_addr: base address of the first block of particular type, + * e.g., address of NIC0_UMR0_0 of 'NIC_UMR' block. + * @major: number of major blocks of particular type. + * @minor: number of minor blocks of particular type. + * @sub_minor: number of sub minor blocks of particular type. + * @major_offset: address gap between 2 consecutive major blocks of particular type, + * e.g., offset between NIC0_UMR0_0 and NIC1_UMR0_0 is 0x80000. + * @minor_offset: address gap between 2 consecutive minor blocks of particular type, + * e.g., offset between NIC0_UMR0_0 and NIC0_UMR1_0 is 0x20000. + * @sub_minor_offset: address gap between 2 consecutive sub_minor blocks of particular + * type, e.g., offset between NIC0_UMR0_0 and NIC0_UMR0_1 is 0x1000. + * + * e.g., in Gaudi2, NIC_UMR blocks can be interpreted as: + * NIC<major>_UMR<minor>_<sub_minor> where major=12, minor=2, sub_minor=15. + * In other words, for each of 12 major numbers (i.e 0 to 11) there are + * 2 blocks with different minor numbers (i.e. 0 to 1). Again, for each minor + * number there are 15 blocks with different sub_minor numbers (i.e. 0 to 14). + * So different blocks are NIC0_UMR0_0, NIC0_UMR0_1, ..., NIC0_UMR1_0, ...., + * NIC11_UMR1_14. + * + * Struct's formatted data is located in the SOL-based auto-generated protbits headers. + */ +struct hl_special_block_info { + int block_type; + u32 base_addr; + u32 major; + u32 minor; + u32 sub_minor; + u32 major_offset; + u32 minor_offset; + u32 sub_minor_offset; +}; + +/* + * struct hl_automated_pb_cfg - represents configurations of a particular type + * of IP block which has protection bits. + * + * @addr: address details as described in hl_automation_pb_addr struct. + * @prot_map: each bit corresponds to one among 32 protection configuration regs + * (e.g., SPECIAL_GLBL_PRIV). '1' means 0xffffffff and '0' means 0x0 + * to be written into the corresponding protection configuration reg. + * This bit is meaningful if same bit in data_map is 0, otherwise ignored. + * @data_map: each bit corresponds to one among 32 protection configuration regs + * (e.g., SPECIAL_GLBL_PRIV). '1' means corresponding protection + * configuration reg is to be written with a value in array pointed + * by 'data', otherwise the value is decided by 'prot_map'. + * @data: pointer to data array which stores the config value(s) to be written + * to corresponding protection configuration reg(s). + * @data_size: size of the data array. + * + * Each bit of 'data_map' and 'prot_map' fields corresponds to one among 32 + * protection configuration registers e.g., SPECIAL GLBL PRIV regs (starting at + * offset 0xE80). '1' in 'data_map' means protection configuration to be done + * using configuration in data array. '0' in 'data_map" means protection + * configuration to be done as per the value of corresponding bit in 'prot_map'. + * '1' in 'prot_map' means the register to be programmed with 0xFFFFFFFF + * (all non-protected). '0' in 'prot_map' means the register to be programmed + * with 0x0 (all protected). + * + * e.g., prot_map = 0x00000001, data_map = 0xC0000000 , data = {0xff, 0x12} + * SPECIAL_GLBL_PRIV[0] = 0xFFFFFFFF + * SPECIAL_GLBL_PRIV[1..29] = 0x0 + * SPECIAL_GLBL_PRIV[30] = 0xFF + * SPECIAL_GLBL_PRIV[31] = 0x12 + */ +struct hl_automated_pb_cfg { + struct hl_special_block_info addr; + u32 prot_map; + u32 data_map; + const u32 *data; + u8 data_size; +}; + +/* struct hl_special_blocks_cfg - holds special blocks cfg data. + * + * @priv_automated_pb_cfg: points to the main privileged PB array. + * @sec_automated_pb_cfg: points to the main secured PB array. + * @skip_blocks_cfg: holds arrays of block types & block ranges to be excluded. + * @priv_cfg_size: size of the main privileged PB array. + * @sec_cfg_size: size of the main secured PB array. + * @prot_lvl_priv: indication if it's a privileged/secured PB configurations. + */ +struct hl_special_blocks_cfg { + struct hl_automated_pb_cfg *priv_automated_pb_cfg; + struct hl_automated_pb_cfg *sec_automated_pb_cfg; + struct hl_skip_blocks_cfg *skip_blocks_cfg; + u32 priv_cfg_size; + u32 sec_cfg_size; + u8 prot_lvl_priv; +}; + +/* Automated security */ + +/* struct hl_skip_blocks_cfg - holds arrays of block types & block ranges to be + * excluded from special blocks configurations. + * + * @block_types: an array of block types NOT to be configured. + * @block_types_len: len of an array of block types not to be configured. + * @block_ranges: an array of block ranges not to be configured. + * @block_ranges_len: len of an array of block ranges not to be configured. + * @skip_block_hook: hook that will be called before initializing special blocks. + */ +struct hl_skip_blocks_cfg { + int *block_types; + size_t block_types_len; + struct range *block_ranges; + size_t block_ranges_len; + bool (*skip_block_hook)(struct hl_device *hdev, + struct hl_special_blocks_cfg *special_blocks_cfg, + u32 blk_idx, u32 major, u32 minor, u32 sub_minor); +}; + +/** + * struct iterate_special_ctx - HW module special block iterator + * @fn: function to apply to each HW module special block instance + * @data: optional internal data to the function iterator + */ +struct iterate_special_ctx { + /* + * callback for the HW module special block iterator + * @hdev: pointer to the habanalabs device structure + * @block_id: block (ASIC specific definition can be dcore/hdcore) + * @major: major block index within block_id + * @minor: minor block index within the major block + * @sub_minor: sub_minor block index within the minor block + * @data: function specific data + */ + int (*fn)(struct hl_device *hdev, u32 block_id, u32 major, u32 minor, + u32 sub_minor, void *data); + void *data; +}; + +int hl_iterate_special_blocks(struct hl_device *hdev, struct iterate_special_ctx *ctx); +void hl_check_for_glbl_errors(struct hl_device *hdev); + +#endif /* SECURITY_H_ */ diff --git a/drivers/misc/habanalabs/common/state_dump.c b/drivers/accel/habanalabs/common/state_dump.c index 74726907c95e..3a9931f24259 100644 --- a/drivers/misc/habanalabs/common/state_dump.c +++ b/drivers/accel/habanalabs/common/state_dump.c @@ -6,7 +6,7 @@ */ #include <linux/vmalloc.h> -#include <uapi/misc/habanalabs.h> +#include <uapi/drm/habanalabs_accel.h> #include "habanalabs.h" /** diff --git a/drivers/misc/habanalabs/common/sysfs.c b/drivers/accel/habanalabs/common/sysfs.c index 735d8bed0066..735d8bed0066 100644 --- a/drivers/misc/habanalabs/common/sysfs.c +++ b/drivers/accel/habanalabs/common/sysfs.c diff --git a/drivers/misc/habanalabs/gaudi/Makefile b/drivers/accel/habanalabs/gaudi/Makefile index 10577c33a816..10577c33a816 100644 --- a/drivers/misc/habanalabs/gaudi/Makefile +++ b/drivers/accel/habanalabs/gaudi/Makefile diff --git a/drivers/misc/habanalabs/gaudi/gaudi.c b/drivers/accel/habanalabs/gaudi/gaudi.c index 9f5e208701ba..71debe862c86 100644 --- a/drivers/misc/habanalabs/gaudi/gaudi.c +++ b/drivers/accel/habanalabs/gaudi/gaudi.c @@ -701,6 +701,8 @@ static int gaudi_set_fixed_properties(struct hl_device *hdev) prop->dma_mask = 48; + prop->hbw_flush_reg = mmPCIE_WRAP_RR_ELBI_RD_SEC_REG_CTRL; + return 0; } @@ -6432,12 +6434,6 @@ static int gaudi_send_job_on_qman0(struct hl_device *hdev, else timeout = HL_DEVICE_TIMEOUT_USEC; - if (!hdev->asic_funcs->is_device_idle(hdev, NULL, 0, NULL)) { - dev_err_ratelimited(hdev->dev, - "Can't send driver job on QMAN0 because the device is not idle\n"); - return -EBUSY; - } - fence_ptr = hl_asic_dma_pool_zalloc(hdev, 4, GFP_KERNEL, &fence_dma_addr); if (!fence_ptr) { dev_err(hdev->dev, @@ -7584,7 +7580,7 @@ static int tpc_krn_event_to_tpc_id(u16 tpc_dec_event_type) return (tpc_dec_event_type - GAUDI_EVENT_TPC0_KRN_ERR) / 6; } -static void gaudi_print_clk_change_info(struct hl_device *hdev, u16 event_type) +static void gaudi_print_clk_change_info(struct hl_device *hdev, u16 event_type, u64 *event_mask) { ktime_t zero_time = ktime_set(0, 0); @@ -7612,6 +7608,7 @@ static void gaudi_print_clk_change_info(struct hl_device *hdev, u16 event_type) hdev->clk_throttling.aggregated_reason |= HL_CLK_THROTTLE_THERMAL; hdev->clk_throttling.timestamp[HL_CLK_THROTTLE_TYPE_THERMAL].start = ktime_get(); hdev->clk_throttling.timestamp[HL_CLK_THROTTLE_TYPE_THERMAL].end = zero_time; + *event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR; dev_info_ratelimited(hdev->dev, "Clock throttling due to overheating\n"); break; @@ -7619,6 +7616,7 @@ static void gaudi_print_clk_change_info(struct hl_device *hdev, u16 event_type) case GAUDI_EVENT_FIX_THERMAL_ENV_E: hdev->clk_throttling.current_reason &= ~HL_CLK_THROTTLE_THERMAL; hdev->clk_throttling.timestamp[HL_CLK_THROTTLE_TYPE_THERMAL].end = ktime_get(); + *event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR; dev_info_ratelimited(hdev->dev, "Thermal envelop is safe, back to optimal clock\n"); break; @@ -7887,8 +7885,7 @@ static void gaudi_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_entr break; case GAUDI_EVENT_FIX_POWER_ENV_S ... GAUDI_EVENT_FIX_THERMAL_ENV_E: - event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR; - gaudi_print_clk_change_info(hdev, event_type); + gaudi_print_clk_change_info(hdev, event_type, &event_mask); hl_fw_unmask_irq(hdev, event_type); break; @@ -9133,6 +9130,16 @@ static u32 *gaudi_get_stream_master_qid_arr(void) return gaudi_stream_master; } +static int gaudi_set_dram_properties(struct hl_device *hdev) +{ + return 0; +} + +static int gaudi_set_binning_masks(struct hl_device *hdev) +{ + return 0; +} + static void gaudi_check_if_razwi_happened(struct hl_device *hdev) { } @@ -9259,6 +9266,8 @@ static const struct hl_asic_funcs gaudi_funcs = { .access_dev_mem = hl_access_dev_mem, .set_dram_bar_base = gaudi_set_hbm_bar_base, .send_device_activity = gaudi_send_device_activity, + .set_dram_properties = gaudi_set_dram_properties, + .set_binning_masks = gaudi_set_binning_masks, }; /** diff --git a/drivers/misc/habanalabs/gaudi/gaudiP.h b/drivers/accel/habanalabs/gaudi/gaudiP.h index 4fbcf3f0afe5..3d88d56c8eb3 100644 --- a/drivers/misc/habanalabs/gaudi/gaudiP.h +++ b/drivers/accel/habanalabs/gaudi/gaudiP.h @@ -8,7 +8,7 @@ #ifndef GAUDIP_H_ #define GAUDIP_H_ -#include <uapi/misc/habanalabs.h> +#include <uapi/drm/habanalabs_accel.h> #include "../common/habanalabs.h" #include "../include/common/hl_boot_if.h" #include "../include/gaudi/gaudi_packets.h" diff --git a/drivers/misc/habanalabs/gaudi/gaudi_coresight.c b/drivers/accel/habanalabs/gaudi/gaudi_coresight.c index 08108f5fed67..3455b14554c6 100644 --- a/drivers/misc/habanalabs/gaudi/gaudi_coresight.c +++ b/drivers/accel/habanalabs/gaudi/gaudi_coresight.c @@ -11,7 +11,8 @@ #include "../include/gaudi/gaudi_masks.h" #include "../include/gaudi/gaudi_reg_map.h" -#include <uapi/misc/habanalabs.h> +#include <uapi/drm/habanalabs_accel.h> + #define SPMU_SECTION_SIZE MME0_ACC_SPMU_MAX_OFFSET #define SPMU_EVENT_TYPES_OFFSET 0x400 #define SPMU_MAX_COUNTERS 6 diff --git a/drivers/misc/habanalabs/gaudi/gaudi_security.c b/drivers/accel/habanalabs/gaudi/gaudi_security.c index 81a3c79a8bc6..81a3c79a8bc6 100644 --- a/drivers/misc/habanalabs/gaudi/gaudi_security.c +++ b/drivers/accel/habanalabs/gaudi/gaudi_security.c diff --git a/drivers/misc/habanalabs/gaudi2/Makefile b/drivers/accel/habanalabs/gaudi2/Makefile index 1e047883ba74..1e047883ba74 100644 --- a/drivers/misc/habanalabs/gaudi2/Makefile +++ b/drivers/accel/habanalabs/gaudi2/Makefile diff --git a/drivers/misc/habanalabs/gaudi2/gaudi2.c b/drivers/accel/habanalabs/gaudi2/gaudi2.c index e793fb2bdcbe..f1f2a58ee68c 100644 --- a/drivers/misc/habanalabs/gaudi2/gaudi2.c +++ b/drivers/accel/habanalabs/gaudi2/gaudi2.c @@ -7,6 +7,7 @@ #include "gaudi2P.h" #include "gaudi2_masks.h" +#include "../include/gaudi2/gaudi2_special_blocks.h" #include "../include/hw_ip/mmu/mmu_general.h" #include "../include/hw_ip/mmu/mmu_v2_0.h" #include "../include/gaudi2/gaudi2_packets.h" @@ -53,6 +54,7 @@ #define GAUDI2_HIF_HMMU_FULL_MASK 0xFFFF #define GAUDI2_DECODER_FULL_MASK 0x3FF +#define GAUDI2_NA_EVENT_CAUSE 0xFF #define GAUDI2_NUM_OF_QM_ERR_CAUSE 18 #define GAUDI2_NUM_OF_QM_LCP_ERR_CAUSE 25 #define GAUDI2_NUM_OF_QM_ARB_ERR_CAUSE 3 @@ -675,14 +677,13 @@ static const char * const gaudi2_kdma_core_interrupts_cause[GAUDI2_NUM_OF_DMA_CO struct gaudi2_sm_sei_cause_data { const char *cause_name; const char *log_name; - u32 log_mask; }; static const struct gaudi2_sm_sei_cause_data gaudi2_sm_sei_cause[GAUDI2_NUM_OF_SM_SEI_ERR_CAUSE] = { - {"calculated SO value overflow/underflow", "SOB group ID", 0x7FF}, - {"payload address of monitor is not aligned to 4B", "monitor addr", 0xFFFF}, - {"armed monitor write got BRESP (SLVERR or DECERR)", "AXI id", 0xFFFF}, + {"calculated SO value overflow/underflow", "SOB ID"}, + {"payload address of monitor is not aligned to 4B", "monitor addr"}, + {"armed monitor write got BRESP (SLVERR or DECERR)", "AXI id"}, }; static const char * const @@ -1568,7 +1569,7 @@ enum rtr_id { DCORE3_RTR7, }; -static const u32 gaudi2_tpc_initiator_rtr_id[NUM_OF_TPC_PER_DCORE * NUM_OF_DCORES + 1] = { +static const u32 gaudi2_tpc_initiator_hbw_rtr_id[NUM_OF_TPC_PER_DCORE * NUM_OF_DCORES + 1] = { DCORE0_RTR1, DCORE0_RTR1, DCORE0_RTR2, DCORE0_RTR2, DCORE0_RTR3, DCORE0_RTR3, DCORE1_RTR6, DCORE1_RTR6, DCORE1_RTR5, DCORE1_RTR5, DCORE1_RTR4, DCORE1_RTR4, DCORE2_RTR3, DCORE2_RTR3, DCORE2_RTR2, DCORE2_RTR2, DCORE2_RTR1, DCORE2_RTR1, @@ -1576,33 +1577,61 @@ static const u32 gaudi2_tpc_initiator_rtr_id[NUM_OF_TPC_PER_DCORE * NUM_OF_DCORE DCORE0_RTR0 }; -static const u32 gaudi2_dec_initiator_rtr_id[NUMBER_OF_DEC] = { +static const u32 gaudi2_tpc_initiator_lbw_rtr_id[NUM_OF_TPC_PER_DCORE * NUM_OF_DCORES + 1] = { + DCORE0_RTR1, DCORE0_RTR1, DCORE0_RTR1, DCORE0_RTR1, DCORE0_RTR2, DCORE0_RTR2, + DCORE1_RTR7, DCORE1_RTR7, DCORE1_RTR6, DCORE1_RTR6, DCORE1_RTR5, DCORE1_RTR5, + DCORE2_RTR2, DCORE2_RTR2, DCORE2_RTR1, DCORE2_RTR1, DCORE2_RTR0, DCORE2_RTR0, + DCORE3_RTR5, DCORE3_RTR5, DCORE3_RTR6, DCORE3_RTR6, DCORE3_RTR7, DCORE3_RTR7, + DCORE0_RTR0 +}; + +static const u32 gaudi2_dec_initiator_hbw_rtr_id[NUMBER_OF_DEC] = { DCORE0_RTR0, DCORE0_RTR0, DCORE1_RTR7, DCORE1_RTR7, DCORE2_RTR0, DCORE2_RTR0, DCORE3_RTR7, DCORE3_RTR7, DCORE0_RTR0, DCORE0_RTR0 }; -static const u32 gaudi2_nic_initiator_rtr_id[NIC_NUMBER_OF_MACROS] = { +static const u32 gaudi2_dec_initiator_lbw_rtr_id[NUMBER_OF_DEC] = { + DCORE0_RTR1, DCORE0_RTR1, DCORE1_RTR6, DCORE1_RTR6, DCORE2_RTR1, DCORE2_RTR1, + DCORE3_RTR6, DCORE3_RTR6, DCORE0_RTR0, DCORE0_RTR0 +}; + +static const u32 gaudi2_nic_initiator_hbw_rtr_id[NIC_NUMBER_OF_MACROS] = { DCORE1_RTR7, DCORE1_RTR7, DCORE1_RTR7, DCORE1_RTR7, DCORE1_RTR7, DCORE2_RTR0, DCORE2_RTR0, DCORE2_RTR0, DCORE2_RTR0, DCORE3_RTR7, DCORE3_RTR7, DCORE3_RTR7 }; -struct sft_info { - u8 interface_id; - u8 dcore_id; +static const u32 gaudi2_nic_initiator_lbw_rtr_id[NIC_NUMBER_OF_MACROS] = { + DCORE1_RTR7, DCORE1_RTR7, DCORE1_RTR7, DCORE1_RTR7, DCORE1_RTR7, DCORE2_RTR0, + DCORE2_RTR0, DCORE2_RTR0, DCORE2_RTR0, DCORE3_RTR7, DCORE3_RTR7, DCORE3_RTR7 }; -static const struct sft_info gaudi2_edma_initiator_sft_id[NUM_OF_EDMA_PER_DCORE * NUM_OF_DCORES] = { - {0, 0}, {1, 0}, {0, 1}, {1, 1}, {1, 2}, {1, 3}, {0, 2}, {0, 3}, +static const u32 gaudi2_edma_initiator_hbw_sft[NUM_OF_EDMA_PER_DCORE * NUM_OF_DCORES] = { + mmSFT0_HBW_RTR_IF1_MSTR_IF_RR_SHRD_HBW_BASE, + mmSFT0_HBW_RTR_IF0_MSTR_IF_RR_SHRD_HBW_BASE, + mmSFT1_HBW_RTR_IF1_MSTR_IF_RR_SHRD_HBW_BASE, + mmSFT1_HBW_RTR_IF0_MSTR_IF_RR_SHRD_HBW_BASE, + mmSFT2_HBW_RTR_IF0_MSTR_IF_RR_SHRD_HBW_BASE, + mmSFT2_HBW_RTR_IF1_MSTR_IF_RR_SHRD_HBW_BASE, + mmSFT3_HBW_RTR_IF0_MSTR_IF_RR_SHRD_HBW_BASE, + mmSFT3_HBW_RTR_IF1_MSTR_IF_RR_SHRD_HBW_BASE }; -static const u32 gaudi2_pdma_initiator_rtr_id[NUM_OF_PDMA] = { +static const u32 gaudi2_pdma_initiator_hbw_rtr_id[NUM_OF_PDMA] = { DCORE0_RTR0, DCORE0_RTR0 }; -static const u32 gaudi2_rot_initiator_rtr_id[NUM_OF_ROT] = { +static const u32 gaudi2_pdma_initiator_lbw_rtr_id[NUM_OF_PDMA] = { + DCORE0_RTR2, DCORE0_RTR2 +}; + +static const u32 gaudi2_rot_initiator_hbw_rtr_id[NUM_OF_ROT] = { DCORE2_RTR0, DCORE3_RTR7 }; +static const u32 gaudi2_rot_initiator_lbw_rtr_id[NUM_OF_ROT] = { + DCORE2_RTR2, DCORE3_RTR5 +}; + struct mme_initiators_rtr_id { u32 wap0; u32 wap1; @@ -1655,6 +1684,30 @@ struct hbm_mc_error_causes { char cause[50]; }; +static struct hl_special_block_info gaudi2_special_blocks[] = GAUDI2_SPECIAL_BLOCKS; + +/* Special blocks iterator is currently used to configure security protection bits, + * and read global errors. Most HW blocks are addressable and those who aren't (N/A)- + * must be skipped. Following configurations are commonly used for both PB config + * and global error reading, since currently they both share the same settings. + * Once it changes, we must remember to use separate configurations for either one. + */ +static int gaudi2_iterator_skip_block_types[] = { + GAUDI2_BLOCK_TYPE_PLL, + GAUDI2_BLOCK_TYPE_EU_BIST, + GAUDI2_BLOCK_TYPE_HBM, + GAUDI2_BLOCK_TYPE_XFT +}; + +static struct range gaudi2_iterator_skip_block_ranges[] = { + /* Skip all PSOC blocks except for PSOC_GLOBAL_CONF */ + {mmPSOC_I2C_M0_BASE, mmPSOC_EFUSE_BASE}, + {mmPSOC_BTL_BASE, mmPSOC_MSTR_IF_RR_SHRD_HBW_BASE}, + /* Skip all CPU blocks except for CPU_IF */ + {mmCPU_CA53_CFG_BASE, mmCPU_CA53_CFG_BASE}, + {mmCPU_TIMESTAMP_BASE, mmCPU_MSTR_IF_RR_SHRD_HBW_BASE} +}; + static struct hbm_mc_error_causes hbm_mc_spi[GAUDI2_NUM_OF_HBM_MC_SPI_CAUSE] = { {HBM_MC_SPI_TEMP_PIN_CHG_MASK, "temperature pins changed"}, {HBM_MC_SPI_THR_ENG_MASK, "temperature-based throttling engaged"}, @@ -2070,6 +2123,8 @@ static int gaudi2_set_fixed_properties(struct hl_device *hdev) prop->dma_mask = 64; + prop->hbw_flush_reg = mmPCIE_WRAP_SPECIAL_GLBL_SPARE_0; + return 0; } @@ -2434,6 +2489,25 @@ static int gaudi2_set_cluster_binning_masks(struct hl_device *hdev) return 0; } +static int gaudi2_set_binning_masks(struct hl_device *hdev) +{ + int rc; + + rc = gaudi2_set_cluster_binning_masks(hdev); + if (rc) + return rc; + + rc = gaudi2_set_tpc_binning_masks(hdev); + if (rc) + return rc; + + rc = gaudi2_set_dec_binning_masks(hdev); + if (rc) + return rc; + + return 0; +} + static int gaudi2_cpucp_info_get(struct hl_device *hdev) { struct gaudi2_device *gaudi2 = hdev->asic_specific; @@ -2485,19 +2559,11 @@ static int gaudi2_cpucp_info_get(struct hl_device *hdev) * at this point the DRAM parameters need to be updated according to data obtained * from the FW */ - rc = gaudi2_set_dram_properties(hdev); + rc = hdev->asic_funcs->set_dram_properties(hdev); if (rc) return rc; - rc = gaudi2_set_cluster_binning_masks(hdev); - if (rc) - return rc; - - rc = gaudi2_set_tpc_binning_masks(hdev); - if (rc) - return rc; - - rc = gaudi2_set_dec_binning_masks(hdev); + rc = hdev->asic_funcs->set_binning_masks(hdev); if (rc) return rc; @@ -2925,11 +2991,11 @@ static void gaudi2_user_interrupt_setup(struct hl_device *hdev) /* Initialize common user CQ interrupt */ HL_USR_INTR_STRUCT_INIT(hdev->common_user_cq_interrupt, hdev, - HL_COMMON_USER_CQ_INTERRUPT_ID, false); + HL_COMMON_USER_CQ_INTERRUPT_ID, HL_USR_INTERRUPT_CQ); /* Initialize common decoder interrupt */ HL_USR_INTR_STRUCT_INIT(hdev->common_decoder_interrupt, hdev, - HL_COMMON_DEC_INTERRUPT_ID, true); + HL_COMMON_DEC_INTERRUPT_ID, HL_USR_INTERRUPT_DECODER); /* User interrupts structure holds both decoder and user interrupts from various engines. * We first initialize the decoder interrupts and then we add the user interrupts. @@ -2942,10 +3008,11 @@ static void gaudi2_user_interrupt_setup(struct hl_device *hdev) */ for (i = GAUDI2_IRQ_NUM_DCORE0_DEC0_NRM, j = 0 ; i <= GAUDI2_IRQ_NUM_SHARED_DEC1_NRM; i += 2, j++) - HL_USR_INTR_STRUCT_INIT(hdev->user_interrupt[j], hdev, i, true); + HL_USR_INTR_STRUCT_INIT(hdev->user_interrupt[j], hdev, i, + HL_USR_INTERRUPT_DECODER); for (i = GAUDI2_IRQ_NUM_USER_FIRST, k = 0 ; k < prop->user_interrupt_count; i++, j++, k++) - HL_USR_INTR_STRUCT_INIT(hdev->user_interrupt[j], hdev, i, false); + HL_USR_INTR_STRUCT_INIT(hdev->user_interrupt[j], hdev, i, HL_USR_INTERRUPT_CQ); } static inline int gaudi2_get_non_zero_random_int(void) @@ -2955,6 +3022,99 @@ static inline int gaudi2_get_non_zero_random_int(void) return rand ? rand : 1; } +static void gaudi2_special_blocks_free(struct hl_device *hdev) +{ + struct asic_fixed_properties *prop = &hdev->asic_prop; + struct hl_skip_blocks_cfg *skip_special_blocks_cfg = + &prop->skip_special_blocks_cfg; + + kfree(prop->special_blocks); + kfree(skip_special_blocks_cfg->block_types); + kfree(skip_special_blocks_cfg->block_ranges); +} + +static void gaudi2_special_blocks_iterator_free(struct hl_device *hdev) +{ + gaudi2_special_blocks_free(hdev); +} + +static bool gaudi2_special_block_skip(struct hl_device *hdev, + struct hl_special_blocks_cfg *special_blocks_cfg, + u32 blk_idx, u32 major, u32 minor, u32 sub_minor) +{ + return false; +} + +static int gaudi2_special_blocks_config(struct hl_device *hdev) +{ + struct asic_fixed_properties *prop = &hdev->asic_prop; + int i, rc; + + /* Configure Special blocks */ + prop->glbl_err_cause_num = GAUDI2_NUM_OF_GLBL_ERR_CAUSE; + prop->num_of_special_blocks = ARRAY_SIZE(gaudi2_special_blocks); + prop->special_blocks = kmalloc_array(prop->num_of_special_blocks, + sizeof(*prop->special_blocks), GFP_KERNEL); + if (!prop->special_blocks) + return -ENOMEM; + + for (i = 0 ; i < prop->num_of_special_blocks ; i++) + memcpy(&prop->special_blocks[i], &gaudi2_special_blocks[i], + sizeof(*prop->special_blocks)); + + /* Configure when to skip Special blocks */ + memset(&prop->skip_special_blocks_cfg, 0, sizeof(prop->skip_special_blocks_cfg)); + prop->skip_special_blocks_cfg.skip_block_hook = gaudi2_special_block_skip; + + if (ARRAY_SIZE(gaudi2_iterator_skip_block_types)) { + prop->skip_special_blocks_cfg.block_types = + kmalloc_array(ARRAY_SIZE(gaudi2_iterator_skip_block_types), + sizeof(gaudi2_iterator_skip_block_types[0]), GFP_KERNEL); + if (!prop->skip_special_blocks_cfg.block_types) { + rc = -ENOMEM; + goto free_special_blocks; + } + + memcpy(prop->skip_special_blocks_cfg.block_types, gaudi2_iterator_skip_block_types, + sizeof(gaudi2_iterator_skip_block_types)); + + prop->skip_special_blocks_cfg.block_types_len = + ARRAY_SIZE(gaudi2_iterator_skip_block_types); + } + + if (ARRAY_SIZE(gaudi2_iterator_skip_block_ranges)) { + prop->skip_special_blocks_cfg.block_ranges = + kmalloc_array(ARRAY_SIZE(gaudi2_iterator_skip_block_ranges), + sizeof(gaudi2_iterator_skip_block_ranges[0]), GFP_KERNEL); + if (!prop->skip_special_blocks_cfg.block_ranges) { + rc = -ENOMEM; + goto free_skip_special_blocks_types; + } + + for (i = 0 ; i < ARRAY_SIZE(gaudi2_iterator_skip_block_ranges) ; i++) + memcpy(&prop->skip_special_blocks_cfg.block_ranges[i], + &gaudi2_iterator_skip_block_ranges[i], + sizeof(struct range)); + + prop->skip_special_blocks_cfg.block_ranges_len = + ARRAY_SIZE(gaudi2_iterator_skip_block_ranges); + } + + return 0; + +free_skip_special_blocks_types: + kfree(prop->skip_special_blocks_cfg.block_types); +free_special_blocks: + kfree(prop->special_blocks); + + return rc; +} + +static int gaudi2_special_blocks_iterator_config(struct hl_device *hdev) +{ + return gaudi2_special_blocks_config(hdev); +} + static int gaudi2_sw_init(struct hl_device *hdev) { struct asic_fixed_properties *prop = &hdev->asic_prop; @@ -3050,8 +3210,15 @@ static int gaudi2_sw_init(struct hl_device *hdev) hdev->asic_funcs->set_pci_memory_regions(hdev); + rc = gaudi2_special_blocks_iterator_config(hdev); + if (rc) + goto free_scratchpad_mem; + return 0; +free_scratchpad_mem: + hl_asic_dma_pool_free(hdev, gaudi2->scratchpad_kernel_address, + gaudi2->scratchpad_bus_address); free_virt_msix_db_mem: hl_cpu_accessible_dma_pool_free(hdev, prop->pmmu.page_size, gaudi2->virt_msix_db_cpu_addr); free_cpu_accessible_dma_pool: @@ -3071,6 +3238,8 @@ static int gaudi2_sw_fini(struct hl_device *hdev) struct asic_fixed_properties *prop = &hdev->asic_prop; struct gaudi2_device *gaudi2 = hdev->asic_specific; + gaudi2_special_blocks_iterator_free(hdev); + hl_cpu_accessible_dma_pool_free(hdev, prop->pmmu.page_size, gaudi2->virt_msix_db_cpu_addr); gen_pool_destroy(hdev->cpu_accessible_dma_pool); @@ -5483,7 +5652,31 @@ static void gaudi2_hw_fini(struct hl_device *hdev, bool hard_reset, bool fw_rese skip_reset: if (driver_performs_reset || hard_reset) - gaudi2_poll_btm_indication(hdev, reset_sleep_ms, poll_timeout_us); + /* + * Instead of waiting for BTM indication we should wait for preboot ready: + * Consider the below scenario: + * 1. FW update is being triggered + * - setting the dirty bit + * 2. hard reset will be triggered due to the dirty bit + * 3. FW initiates the reset: + * - dirty bit cleared + * - BTM indication cleared + * - preboot ready indication cleared + * 4. during hard reset: + * - BTM indication will be set + * - BIST test performed and another reset triggered + * 5. only after this reset the preboot will set the preboot ready + * + * when polling on BTM indication alone we can lose sync with FW while trying to + * communicate with FW that is during reset. + * to overcome this we will always wait to preboot ready indication + */ + if ((hdev->fw_components & FW_TYPE_PREBOOT_CPU)) { + msleep(reset_sleep_ms); + hl_fw_wait_preboot_ready(hdev); + } else { + gaudi2_poll_btm_indication(hdev, reset_sleep_ms, poll_timeout_us); + } else gaudi2_get_soft_rst_done_indication(hdev, poll_timeout_us); @@ -6803,38 +6996,37 @@ static inline bool is_info_event(u32 event) switch (event) { case GAUDI2_EVENT_CPU_CPLD_SHUTDOWN_CAUSE: case GAUDI2_EVENT_CPU_FIX_POWER_ENV_S ... GAUDI2_EVENT_CPU_FIX_THERMAL_ENV_E: + + /* return in case of NIC status event - these events are received periodically and not as + * an indication to an error. + */ + case GAUDI2_EVENT_CPU0_STATUS_NIC0_ENG0 ... GAUDI2_EVENT_CPU11_STATUS_NIC11_ENG1: return true; default: return false; } } -static void gaudi2_print_irq_info(struct hl_device *hdev, u16 event_type) +static void gaudi2_print_event(struct hl_device *hdev, u16 event_type, + bool ratelimited, const char *fmt, ...) { - char desc[64] = ""; - bool event_valid = false; + struct va_format vaf; + va_list args; - /* return in case of NIC status event - these events are received periodically and not as - * an indication to an error, thus not printed. - */ - if (event_type >= GAUDI2_EVENT_CPU0_STATUS_NIC0_ENG0 && - event_type <= GAUDI2_EVENT_CPU11_STATUS_NIC11_ENG1) - return; + va_start(args, fmt); + vaf.fmt = fmt; + vaf.va = &args; - if (gaudi2_irq_map_table[event_type].valid) { - snprintf(desc, sizeof(desc), gaudi2_irq_map_table[event_type].name); - event_valid = true; - } - - if (!event_valid) - snprintf(desc, sizeof(desc), "N/A"); - - if (is_info_event(event_type)) - dev_info_ratelimited(hdev->dev, "Received H/W interrupt %d [\"%s\"]\n", - event_type, desc); + if (ratelimited) + dev_err_ratelimited(hdev->dev, "%s: %pV\n", + gaudi2_irq_map_table[event_type].valid ? + gaudi2_irq_map_table[event_type].name : "N/A Event", &vaf); else - dev_err_ratelimited(hdev->dev, "Received H/W interrupt %d [\"%s\"]\n", - event_type, desc); + dev_err(hdev->dev, "%s: %pV\n", + gaudi2_irq_map_table[event_type].valid ? + gaudi2_irq_map_table[event_type].name : "N/A Event", &vaf); + + va_end(args); } static bool gaudi2_handle_ecc_event(struct hl_device *hdev, u16 event_type, @@ -6847,7 +7039,7 @@ static bool gaudi2_handle_ecc_event(struct hl_device *hdev, u16 event_type, ecc_syndrom = le64_to_cpu(ecc_data->ecc_syndrom); memory_wrapper_idx = ecc_data->memory_wrapper_idx; - dev_err(hdev->dev, + gaudi2_print_event(hdev, event_type, !ecc_data->is_critical, "ECC error detected. address: %#llx. Syndrom: %#llx. block id %u. critical %u.\n", ecc_address, ecc_syndrom, memory_wrapper_idx, ecc_data->is_critical); @@ -6987,10 +7179,10 @@ static void print_qman_data_on_err(struct hl_device *hdev, u32 qid_base, u32 str gaudi2_print_last_pqes_on_err(hdev, qid_base, i, qman_base, false); } -static void gaudi2_handle_qman_err_generic(struct hl_device *hdev, const char *qm_name, - u64 qman_base, u32 qid_base) +static int gaudi2_handle_qman_err_generic(struct hl_device *hdev, u16 event_type, + u64 qman_base, u32 qid_base) { - u32 i, j, glbl_sts_val, arb_err_val, num_error_causes; + u32 i, j, glbl_sts_val, arb_err_val, num_error_causes, error_count = 0; u64 glbl_sts_addr, arb_err_addr; char reg_desc[32]; @@ -7013,12 +7205,14 @@ static void gaudi2_handle_qman_err_generic(struct hl_device *hdev, const char *q } for (j = 0 ; j < num_error_causes ; j++) - if (glbl_sts_val & BIT(j)) - dev_err_ratelimited(hdev->dev, "%s %s. err cause: %s\n", - qm_name, reg_desc, - i == QMAN_STREAMS ? - gaudi2_qman_lower_cp_error_cause[j] : - gaudi2_qman_error_cause[j]); + if (glbl_sts_val & BIT(j)) { + gaudi2_print_event(hdev, event_type, true, + "%s. err cause: %s", reg_desc, + i == QMAN_STREAMS ? + gaudi2_qman_lower_cp_error_cause[j] : + gaudi2_qman_error_cause[j]); + error_count++; + } print_qman_data_on_err(hdev, qid_base, i, qman_base); } @@ -7026,18 +7220,23 @@ static void gaudi2_handle_qman_err_generic(struct hl_device *hdev, const char *q arb_err_val = RREG32(arb_err_addr); if (!arb_err_val) - return; + goto out; for (j = 0 ; j < GAUDI2_NUM_OF_QM_ARB_ERR_CAUSE ; j++) { - if (arb_err_val & BIT(j)) - dev_err_ratelimited(hdev->dev, "%s ARB_ERR. err cause: %s\n", - qm_name, gaudi2_qman_arb_error_cause[j]); + if (arb_err_val & BIT(j)) { + gaudi2_print_event(hdev, event_type, true, + "ARB_ERR. err cause: %s", + gaudi2_qman_arb_error_cause[j]); + error_count++; + } } + +out: + return error_count; } static void gaudi2_razwi_rr_hbw_shared_printf_info(struct hl_device *hdev, u64 rtr_mstr_if_base_addr, bool is_write, char *name, - bool read_razwi_regs, struct hl_eq_razwi_info *razwi_info, enum gaudi2_engine_id id, u64 *event_mask) { u32 razwi_hi, razwi_lo, razwi_xy; @@ -7045,26 +7244,14 @@ static void gaudi2_razwi_rr_hbw_shared_printf_info(struct hl_device *hdev, u8 rd_wr_flag; if (is_write) { - if (read_razwi_regs) { - razwi_hi = RREG32(rtr_mstr_if_base_addr + RR_SHRD_HBW_AW_RAZWI_HI); - razwi_lo = RREG32(rtr_mstr_if_base_addr + RR_SHRD_HBW_AW_RAZWI_LO); - razwi_xy = RREG32(rtr_mstr_if_base_addr + RR_SHRD_HBW_AW_RAZWI_XY); - } else { - razwi_hi = le32_to_cpu(razwi_info->hbw.rr_aw_razwi_hi_reg); - razwi_lo = le32_to_cpu(razwi_info->hbw.rr_aw_razwi_lo_reg); - razwi_xy = le32_to_cpu(razwi_info->hbw.rr_aw_razwi_id_reg); - } + razwi_hi = RREG32(rtr_mstr_if_base_addr + RR_SHRD_HBW_AW_RAZWI_HI); + razwi_lo = RREG32(rtr_mstr_if_base_addr + RR_SHRD_HBW_AW_RAZWI_LO); + razwi_xy = RREG32(rtr_mstr_if_base_addr + RR_SHRD_HBW_AW_RAZWI_XY); rd_wr_flag = HL_RAZWI_WRITE; } else { - if (read_razwi_regs) { - razwi_hi = RREG32(rtr_mstr_if_base_addr + RR_SHRD_HBW_AR_RAZWI_HI); - razwi_lo = RREG32(rtr_mstr_if_base_addr + RR_SHRD_HBW_AR_RAZWI_LO); - razwi_xy = RREG32(rtr_mstr_if_base_addr + RR_SHRD_HBW_AR_RAZWI_XY); - } else { - razwi_hi = le32_to_cpu(razwi_info->hbw.rr_ar_razwi_hi_reg); - razwi_lo = le32_to_cpu(razwi_info->hbw.rr_ar_razwi_lo_reg); - razwi_xy = le32_to_cpu(razwi_info->hbw.rr_ar_razwi_id_reg); - } + razwi_hi = RREG32(rtr_mstr_if_base_addr + RR_SHRD_HBW_AR_RAZWI_HI); + razwi_lo = RREG32(rtr_mstr_if_base_addr + RR_SHRD_HBW_AR_RAZWI_LO); + razwi_xy = RREG32(rtr_mstr_if_base_addr + RR_SHRD_HBW_AR_RAZWI_XY); rd_wr_flag = HL_RAZWI_READ; } @@ -7078,38 +7265,26 @@ static void gaudi2_razwi_rr_hbw_shared_printf_info(struct hl_device *hdev, static void gaudi2_razwi_rr_lbw_shared_printf_info(struct hl_device *hdev, u64 rtr_mstr_if_base_addr, bool is_write, char *name, - bool read_razwi_regs, struct hl_eq_razwi_info *razwi_info, enum gaudi2_engine_id id, u64 *event_mask) { - u32 razwi_addr, razwi_xy; + u64 razwi_addr = CFG_BASE; + u32 razwi_xy; u16 eng_id = id; u8 rd_wr_flag; if (is_write) { - if (read_razwi_regs) { - razwi_addr = RREG32(rtr_mstr_if_base_addr + RR_SHRD_LBW_AW_RAZWI); - razwi_xy = RREG32(rtr_mstr_if_base_addr + RR_SHRD_LBW_AW_RAZWI_XY); - } else { - razwi_addr = le32_to_cpu(razwi_info->lbw.rr_aw_razwi_reg); - razwi_xy = le32_to_cpu(razwi_info->lbw.rr_aw_razwi_id_reg); - } - + razwi_addr += RREG32(rtr_mstr_if_base_addr + RR_SHRD_LBW_AW_RAZWI); + razwi_xy = RREG32(rtr_mstr_if_base_addr + RR_SHRD_LBW_AW_RAZWI_XY); rd_wr_flag = HL_RAZWI_WRITE; } else { - if (read_razwi_regs) { - razwi_addr = RREG32(rtr_mstr_if_base_addr + RR_SHRD_LBW_AR_RAZWI); - razwi_xy = RREG32(rtr_mstr_if_base_addr + RR_SHRD_LBW_AR_RAZWI_XY); - } else { - razwi_addr = le32_to_cpu(razwi_info->lbw.rr_ar_razwi_reg); - razwi_xy = le32_to_cpu(razwi_info->lbw.rr_ar_razwi_id_reg); - } - + razwi_addr += RREG32(rtr_mstr_if_base_addr + RR_SHRD_LBW_AR_RAZWI); + razwi_xy = RREG32(rtr_mstr_if_base_addr + RR_SHRD_LBW_AR_RAZWI_XY); rd_wr_flag = HL_RAZWI_READ; } hl_handle_razwi(hdev, razwi_addr, &eng_id, 1, rd_wr_flag | HL_RAZWI_LBW, event_mask); dev_err_ratelimited(hdev->dev, - "%s-RAZWI SHARED RR LBW %s error, mstr_if 0x%llx, captured address 0x%x Initiator coordinates 0x%x\n", + "%s-RAZWI SHARED RR LBW %s error, mstr_if 0x%llx, captured address 0x%llX Initiator coordinates 0x%x\n", name, is_write ? "WR" : "RD", rtr_mstr_if_base_addr, razwi_addr, razwi_xy); } @@ -7164,183 +7339,148 @@ static enum gaudi2_engine_id gaudi2_razwi_calc_engine_id(struct hl_device *hdev, */ static void gaudi2_ack_module_razwi_event_handler(struct hl_device *hdev, enum razwi_event_sources module, u8 module_idx, - u8 module_sub_idx, struct hl_eq_razwi_info *razwi_info, - u64 *event_mask) + u8 module_sub_idx, u64 *event_mask) { - bool via_sft = false, read_razwi_regs = false; - u32 rtr_id, dcore_id, dcore_rtr_id, sft_id, eng_id; - u64 rtr_mstr_if_base_addr; + bool via_sft = false; + u32 hbw_rtr_id, lbw_rtr_id, dcore_id, dcore_rtr_id, eng_id; + u64 hbw_rtr_mstr_if_base_addr, lbw_rtr_mstr_if_base_addr; u32 hbw_shrd_aw = 0, hbw_shrd_ar = 0; u32 lbw_shrd_aw = 0, lbw_shrd_ar = 0; char initiator_name[64]; - if (hdev->pldm || !(hdev->fw_components & FW_TYPE_LINUX) || !razwi_info) - read_razwi_regs = true; - switch (module) { case RAZWI_TPC: - rtr_id = gaudi2_tpc_initiator_rtr_id[module_idx]; + hbw_rtr_id = gaudi2_tpc_initiator_hbw_rtr_id[module_idx]; + + /* TODO : remove this check and depend only on tpc routers table + * when SW-118828 is resolved + */ + if (!hdev->asic_prop.fw_security_enabled && + ((module_idx == 0) || (module_idx == 1))) + lbw_rtr_id = DCORE0_RTR0; + else + lbw_rtr_id = gaudi2_tpc_initiator_lbw_rtr_id[module_idx]; sprintf(initiator_name, "TPC_%u", module_idx); break; case RAZWI_MME: sprintf(initiator_name, "MME_%u", module_idx); switch (module_sub_idx) { case MME_WAP0: - rtr_id = gaudi2_mme_initiator_rtr_id[module_idx].wap0; + hbw_rtr_id = gaudi2_mme_initiator_rtr_id[module_idx].wap0; break; case MME_WAP1: - rtr_id = gaudi2_mme_initiator_rtr_id[module_idx].wap1; + hbw_rtr_id = gaudi2_mme_initiator_rtr_id[module_idx].wap1; break; case MME_WRITE: - rtr_id = gaudi2_mme_initiator_rtr_id[module_idx].write; + hbw_rtr_id = gaudi2_mme_initiator_rtr_id[module_idx].write; break; case MME_READ: - rtr_id = gaudi2_mme_initiator_rtr_id[module_idx].read; + hbw_rtr_id = gaudi2_mme_initiator_rtr_id[module_idx].read; break; case MME_SBTE0: - rtr_id = gaudi2_mme_initiator_rtr_id[module_idx].sbte0; + hbw_rtr_id = gaudi2_mme_initiator_rtr_id[module_idx].sbte0; break; case MME_SBTE1: - rtr_id = gaudi2_mme_initiator_rtr_id[module_idx].sbte1; + hbw_rtr_id = gaudi2_mme_initiator_rtr_id[module_idx].sbte1; break; case MME_SBTE2: - rtr_id = gaudi2_mme_initiator_rtr_id[module_idx].sbte2; + hbw_rtr_id = gaudi2_mme_initiator_rtr_id[module_idx].sbte2; break; case MME_SBTE3: - rtr_id = gaudi2_mme_initiator_rtr_id[module_idx].sbte3; + hbw_rtr_id = gaudi2_mme_initiator_rtr_id[module_idx].sbte3; break; case MME_SBTE4: - rtr_id = gaudi2_mme_initiator_rtr_id[module_idx].sbte4; + hbw_rtr_id = gaudi2_mme_initiator_rtr_id[module_idx].sbte4; break; default: return; } + lbw_rtr_id = hbw_rtr_id; break; case RAZWI_EDMA: - sft_id = gaudi2_edma_initiator_sft_id[module_idx].interface_id; - dcore_id = gaudi2_edma_initiator_sft_id[module_idx].dcore_id; + hbw_rtr_mstr_if_base_addr = gaudi2_edma_initiator_hbw_sft[module_idx]; + dcore_id = module_idx / NUM_OF_EDMA_PER_DCORE; + /* SFT has separate MSTR_IF for LBW, only there we can + * read the LBW razwi related registers + */ + lbw_rtr_mstr_if_base_addr = mmSFT0_LBW_RTR_IF_MSTR_IF_RR_SHRD_HBW_BASE + + dcore_id * SFT_DCORE_OFFSET; via_sft = true; sprintf(initiator_name, "EDMA_%u", module_idx); break; case RAZWI_PDMA: - rtr_id = gaudi2_pdma_initiator_rtr_id[module_idx]; + hbw_rtr_id = gaudi2_pdma_initiator_hbw_rtr_id[module_idx]; + lbw_rtr_id = gaudi2_pdma_initiator_lbw_rtr_id[module_idx]; sprintf(initiator_name, "PDMA_%u", module_idx); break; case RAZWI_NIC: - rtr_id = gaudi2_nic_initiator_rtr_id[module_idx]; + hbw_rtr_id = gaudi2_nic_initiator_hbw_rtr_id[module_idx]; + lbw_rtr_id = gaudi2_nic_initiator_lbw_rtr_id[module_idx]; sprintf(initiator_name, "NIC_%u", module_idx); break; case RAZWI_DEC: - rtr_id = gaudi2_dec_initiator_rtr_id[module_idx]; + hbw_rtr_id = gaudi2_dec_initiator_hbw_rtr_id[module_idx]; + lbw_rtr_id = gaudi2_dec_initiator_lbw_rtr_id[module_idx]; sprintf(initiator_name, "DEC_%u", module_idx); break; case RAZWI_ROT: - rtr_id = gaudi2_rot_initiator_rtr_id[module_idx]; + hbw_rtr_id = gaudi2_rot_initiator_hbw_rtr_id[module_idx]; + lbw_rtr_id = gaudi2_rot_initiator_lbw_rtr_id[module_idx]; sprintf(initiator_name, "ROT_%u", module_idx); break; default: return; } - if (!read_razwi_regs) { - if (le32_to_cpu(razwi_info->razwi_happened_mask) & RAZWI_HAPPENED_HBW) { - hbw_shrd_aw = le32_to_cpu(razwi_info->razwi_happened_mask) & - RAZWI_HAPPENED_AW; - hbw_shrd_ar = le32_to_cpu(razwi_info->razwi_happened_mask) & - RAZWI_HAPPENED_AR; - } else if (le32_to_cpu(razwi_info->razwi_happened_mask) & RAZWI_HAPPENED_LBW) { - lbw_shrd_aw = le32_to_cpu(razwi_info->razwi_happened_mask) & - RAZWI_HAPPENED_AW; - lbw_shrd_ar = le32_to_cpu(razwi_info->razwi_happened_mask) & - RAZWI_HAPPENED_AR; - } - rtr_mstr_if_base_addr = 0; - - goto dump_info; - } - /* Find router mstr_if register base */ - if (via_sft) { - rtr_mstr_if_base_addr = mmSFT0_HBW_RTR_IF0_RTR_CTRL_BASE + - dcore_id * SFT_DCORE_OFFSET + - sft_id * SFT_IF_OFFSET + - RTR_MSTR_IF_OFFSET; - } else { - dcore_id = rtr_id / NUM_OF_RTR_PER_DCORE; - dcore_rtr_id = rtr_id % NUM_OF_RTR_PER_DCORE; - rtr_mstr_if_base_addr = mmDCORE0_RTR0_CTRL_BASE + + if (!via_sft) { + dcore_id = hbw_rtr_id / NUM_OF_RTR_PER_DCORE; + dcore_rtr_id = hbw_rtr_id % NUM_OF_RTR_PER_DCORE; + hbw_rtr_mstr_if_base_addr = mmDCORE0_RTR0_CTRL_BASE + dcore_id * DCORE_OFFSET + dcore_rtr_id * DCORE_RTR_OFFSET + RTR_MSTR_IF_OFFSET; + lbw_rtr_mstr_if_base_addr = hbw_rtr_mstr_if_base_addr + + (((s32)lbw_rtr_id - hbw_rtr_id) * DCORE_RTR_OFFSET); } /* Find out event cause by reading "RAZWI_HAPPENED" registers */ - hbw_shrd_aw = RREG32(rtr_mstr_if_base_addr + RR_SHRD_HBW_AW_RAZWI_HAPPENED); - - hbw_shrd_ar = RREG32(rtr_mstr_if_base_addr + RR_SHRD_HBW_AR_RAZWI_HAPPENED); - - if (via_sft) { - /* SFT has separate MSTR_IF for LBW, only there we can - * read the LBW razwi related registers - */ - u64 base; - - base = mmSFT0_HBW_RTR_IF0_RTR_CTRL_BASE + dcore_id * SFT_DCORE_OFFSET + - RTR_LBW_MSTR_IF_OFFSET; - - lbw_shrd_aw = RREG32(base + RR_SHRD_LBW_AW_RAZWI_HAPPENED); - - lbw_shrd_ar = RREG32(base + RR_SHRD_LBW_AR_RAZWI_HAPPENED); - } else { - lbw_shrd_aw = RREG32(rtr_mstr_if_base_addr + RR_SHRD_LBW_AW_RAZWI_HAPPENED); - - lbw_shrd_ar = RREG32(rtr_mstr_if_base_addr + RR_SHRD_LBW_AR_RAZWI_HAPPENED); - } - -dump_info: - /* check if there is no RR razwi indication at all */ - if (!hbw_shrd_aw && !hbw_shrd_ar && !lbw_shrd_aw && !lbw_shrd_ar) - return; + hbw_shrd_aw = RREG32(hbw_rtr_mstr_if_base_addr + RR_SHRD_HBW_AW_RAZWI_HAPPENED); + hbw_shrd_ar = RREG32(hbw_rtr_mstr_if_base_addr + RR_SHRD_HBW_AR_RAZWI_HAPPENED); + lbw_shrd_aw = RREG32(lbw_rtr_mstr_if_base_addr + RR_SHRD_LBW_AW_RAZWI_HAPPENED); + lbw_shrd_ar = RREG32(lbw_rtr_mstr_if_base_addr + RR_SHRD_LBW_AR_RAZWI_HAPPENED); eng_id = gaudi2_razwi_calc_engine_id(hdev, module, module_idx); if (hbw_shrd_aw) { - gaudi2_razwi_rr_hbw_shared_printf_info(hdev, rtr_mstr_if_base_addr, true, - initiator_name, read_razwi_regs, razwi_info, - eng_id, event_mask); + gaudi2_razwi_rr_hbw_shared_printf_info(hdev, hbw_rtr_mstr_if_base_addr, true, + initiator_name, eng_id, event_mask); /* Clear event indication */ - if (read_razwi_regs) - WREG32(rtr_mstr_if_base_addr + RR_SHRD_HBW_AW_RAZWI_HAPPENED, hbw_shrd_aw); + WREG32(hbw_rtr_mstr_if_base_addr + RR_SHRD_HBW_AW_RAZWI_HAPPENED, hbw_shrd_aw); } if (hbw_shrd_ar) { - gaudi2_razwi_rr_hbw_shared_printf_info(hdev, rtr_mstr_if_base_addr, false, - initiator_name, read_razwi_regs, razwi_info, - eng_id, event_mask); + gaudi2_razwi_rr_hbw_shared_printf_info(hdev, hbw_rtr_mstr_if_base_addr, false, + initiator_name, eng_id, event_mask); /* Clear event indication */ - if (read_razwi_regs) - WREG32(rtr_mstr_if_base_addr + RR_SHRD_HBW_AR_RAZWI_HAPPENED, hbw_shrd_ar); + WREG32(hbw_rtr_mstr_if_base_addr + RR_SHRD_HBW_AR_RAZWI_HAPPENED, hbw_shrd_ar); } if (lbw_shrd_aw) { - gaudi2_razwi_rr_lbw_shared_printf_info(hdev, rtr_mstr_if_base_addr, true, - initiator_name, read_razwi_regs, razwi_info, - eng_id, event_mask); + gaudi2_razwi_rr_lbw_shared_printf_info(hdev, lbw_rtr_mstr_if_base_addr, true, + initiator_name, eng_id, event_mask); /* Clear event indication */ - if (read_razwi_regs) - WREG32(rtr_mstr_if_base_addr + RR_SHRD_LBW_AW_RAZWI_HAPPENED, lbw_shrd_aw); + WREG32(lbw_rtr_mstr_if_base_addr + RR_SHRD_LBW_AW_RAZWI_HAPPENED, lbw_shrd_aw); } if (lbw_shrd_ar) { - gaudi2_razwi_rr_lbw_shared_printf_info(hdev, rtr_mstr_if_base_addr, false, - initiator_name, read_razwi_regs, razwi_info, - eng_id, event_mask); + gaudi2_razwi_rr_lbw_shared_printf_info(hdev, lbw_rtr_mstr_if_base_addr, false, + initiator_name, eng_id, event_mask); /* Clear event indication */ - if (read_razwi_regs) - WREG32(rtr_mstr_if_base_addr + RR_SHRD_LBW_AR_RAZWI_HAPPENED, lbw_shrd_ar); + WREG32(lbw_rtr_mstr_if_base_addr + RR_SHRD_LBW_AR_RAZWI_HAPPENED, lbw_shrd_ar); } } @@ -7352,42 +7492,38 @@ static void gaudi2_check_if_razwi_happened(struct hl_device *hdev) /* check all TPCs */ for (mod_idx = 0 ; mod_idx < (NUM_OF_TPC_PER_DCORE * NUM_OF_DCORES + 1) ; mod_idx++) { if (prop->tpc_enabled_mask & BIT(mod_idx)) - gaudi2_ack_module_razwi_event_handler(hdev, RAZWI_TPC, mod_idx, 0, NULL, - NULL); + gaudi2_ack_module_razwi_event_handler(hdev, RAZWI_TPC, mod_idx, 0, NULL); } /* check all MMEs */ for (mod_idx = 0 ; mod_idx < (NUM_OF_MME_PER_DCORE * NUM_OF_DCORES) ; mod_idx++) for (sub_mod = MME_WAP0 ; sub_mod < MME_INITIATORS_MAX ; sub_mod++) gaudi2_ack_module_razwi_event_handler(hdev, RAZWI_MME, mod_idx, - sub_mod, NULL, NULL); + sub_mod, NULL); /* check all EDMAs */ for (mod_idx = 0 ; mod_idx < (NUM_OF_EDMA_PER_DCORE * NUM_OF_DCORES) ; mod_idx++) if (prop->edma_enabled_mask & BIT(mod_idx)) - gaudi2_ack_module_razwi_event_handler(hdev, RAZWI_EDMA, mod_idx, 0, NULL, - NULL); + gaudi2_ack_module_razwi_event_handler(hdev, RAZWI_EDMA, mod_idx, 0, NULL); /* check all PDMAs */ for (mod_idx = 0 ; mod_idx < NUM_OF_PDMA ; mod_idx++) - gaudi2_ack_module_razwi_event_handler(hdev, RAZWI_PDMA, mod_idx, 0, NULL, - NULL); + gaudi2_ack_module_razwi_event_handler(hdev, RAZWI_PDMA, mod_idx, 0, NULL); /* check all NICs */ for (mod_idx = 0 ; mod_idx < NIC_NUMBER_OF_PORTS ; mod_idx++) if (hdev->nic_ports_mask & BIT(mod_idx)) gaudi2_ack_module_razwi_event_handler(hdev, RAZWI_NIC, mod_idx >> 1, 0, - NULL, NULL); + NULL); /* check all DECs */ for (mod_idx = 0 ; mod_idx < NUMBER_OF_DEC ; mod_idx++) if (prop->decoder_enabled_mask & BIT(mod_idx)) - gaudi2_ack_module_razwi_event_handler(hdev, RAZWI_DEC, mod_idx, 0, NULL, - NULL); + gaudi2_ack_module_razwi_event_handler(hdev, RAZWI_DEC, mod_idx, 0, NULL); /* check all ROTs */ for (mod_idx = 0 ; mod_idx < NUM_OF_ROT ; mod_idx++) - gaudi2_ack_module_razwi_event_handler(hdev, RAZWI_ROT, mod_idx, 0, NULL, NULL); + gaudi2_ack_module_razwi_event_handler(hdev, RAZWI_ROT, mod_idx, 0, NULL); } static const char *gaudi2_get_initiators_name(u32 rtr_id) @@ -7645,19 +7781,19 @@ static void gaudi2_razwi_unmapped_addr_lbw_printf_info(struct hl_device *hdev, u u64 *event_mask) { u16 engines[HL_RAZWI_MAX_NUM_OF_ENGINES_PER_RTR], num_of_eng; - u32 razwi_addr; + u64 razwi_addr = CFG_BASE; u8 rd_wr_flag; num_of_eng = gaudi2_get_razwi_initiators(rtr_id, &engines[0]); if (is_write) { - razwi_addr = RREG32(rtr_ctrl_base_addr + DEC_RAZWI_LBW_AW_ADDR); + razwi_addr += RREG32(rtr_ctrl_base_addr + DEC_RAZWI_LBW_AW_ADDR); rd_wr_flag = HL_RAZWI_WRITE; /* Clear set indication */ WREG32(rtr_ctrl_base_addr + DEC_RAZWI_LBW_AW_SET, 0x1); } else { - razwi_addr = RREG32(rtr_ctrl_base_addr + DEC_RAZWI_LBW_AR_ADDR); + razwi_addr += RREG32(rtr_ctrl_base_addr + DEC_RAZWI_LBW_AR_ADDR); rd_wr_flag = HL_RAZWI_READ; /* Clear set indication */ @@ -7667,7 +7803,7 @@ static void gaudi2_razwi_unmapped_addr_lbw_printf_info(struct hl_device *hdev, u hl_handle_razwi(hdev, razwi_addr, &engines[0], num_of_eng, rd_wr_flag | HL_RAZWI_LBW, event_mask); dev_err_ratelimited(hdev->dev, - "RAZWI PSOC unmapped LBW %s error, rtr id %u, address %#x\n", + "RAZWI PSOC unmapped LBW %s error, rtr id %u, address 0x%llX\n", is_write ? "WR" : "RD", rtr_id, razwi_addr); dev_err_ratelimited(hdev->dev, @@ -7675,17 +7811,17 @@ static void gaudi2_razwi_unmapped_addr_lbw_printf_info(struct hl_device *hdev, u } /* PSOC RAZWI interrupt occurs only when trying to access a bad address */ -static void gaudi2_ack_psoc_razwi_event_handler(struct hl_device *hdev, u64 *event_mask) +static int gaudi2_ack_psoc_razwi_event_handler(struct hl_device *hdev, u64 *event_mask) { u32 hbw_aw_set, hbw_ar_set, lbw_aw_set, lbw_ar_set, rtr_id, dcore_id, dcore_rtr_id, xy, - razwi_mask_info, razwi_intr = 0; + razwi_mask_info, razwi_intr = 0, error_count = 0; int rtr_map_arr_len = NUM_OF_RTR_PER_DCORE * NUM_OF_DCORES; u64 rtr_ctrl_base_addr; if (hdev->pldm || !(hdev->fw_components & FW_TYPE_LINUX)) { razwi_intr = RREG32(mmPSOC_GLOBAL_CONF_RAZWI_INTERRUPT); if (!razwi_intr) - return; + return 0; } razwi_mask_info = RREG32(mmPSOC_GLOBAL_CONF_RAZWI_MASK_INFO); @@ -7743,33 +7879,41 @@ static void gaudi2_ack_psoc_razwi_event_handler(struct hl_device *hdev, u64 *eve gaudi2_razwi_unmapped_addr_lbw_printf_info(hdev, rtr_id, rtr_ctrl_base_addr, false, event_mask); + error_count++; + clear: /* Clear Interrupts only on pldm or if f/w doesn't handle interrupts */ if (hdev->pldm || !(hdev->fw_components & FW_TYPE_LINUX)) WREG32(mmPSOC_GLOBAL_CONF_RAZWI_INTERRUPT, razwi_intr); + + return error_count; } -static void _gaudi2_handle_qm_sei_err(struct hl_device *hdev, u64 qman_base) +static int _gaudi2_handle_qm_sei_err(struct hl_device *hdev, u64 qman_base, u16 event_type) { - u32 i, sts_val, sts_clr_val = 0; + u32 i, sts_val, sts_clr_val = 0, error_count = 0; sts_val = RREG32(qman_base + QM_SEI_STATUS_OFFSET); for (i = 0 ; i < GAUDI2_NUM_OF_QM_SEI_ERR_CAUSE ; i++) { if (sts_val & BIT(i)) { - dev_err_ratelimited(hdev->dev, "QM SEI. err cause: %s\n", - gaudi2_qm_sei_error_cause[i]); + gaudi2_print_event(hdev, event_type, true, + "err cause: %s", gaudi2_qm_sei_error_cause[i]); sts_clr_val |= BIT(i); + error_count++; } } WREG32(qman_base + QM_SEI_STATUS_OFFSET, sts_clr_val); + + return error_count; } -static void gaudi2_handle_qm_sei_err(struct hl_device *hdev, u16 event_type, - struct hl_eq_razwi_info *razwi_info, u64 *event_mask) +static int gaudi2_handle_qm_sei_err(struct hl_device *hdev, u16 event_type, + bool extended_err_check, u64 *event_mask) { enum razwi_event_sources module; + u32 error_count = 0; u64 qman_base; u8 index; @@ -7808,26 +7952,30 @@ static void gaudi2_handle_qm_sei_err(struct hl_device *hdev, u16 event_type, module = RAZWI_ROT; break; default: - return; + return 0; } - _gaudi2_handle_qm_sei_err(hdev, qman_base); + error_count = _gaudi2_handle_qm_sei_err(hdev, qman_base, event_type); /* There is a single event per NIC macro, so should check its both QMAN blocks */ if (event_type >= GAUDI2_EVENT_NIC0_AXI_ERROR_RESPONSE && event_type <= GAUDI2_EVENT_NIC11_AXI_ERROR_RESPONSE) - _gaudi2_handle_qm_sei_err(hdev, qman_base + NIC_QM_OFFSET); + error_count += _gaudi2_handle_qm_sei_err(hdev, + qman_base + NIC_QM_OFFSET, event_type); - /* check if RAZWI happened */ - if (razwi_info) - gaudi2_ack_module_razwi_event_handler(hdev, module, 0, 0, razwi_info, event_mask); + if (extended_err_check) { + /* check if RAZWI happened */ + gaudi2_ack_module_razwi_event_handler(hdev, module, 0, 0, event_mask); + hl_check_for_glbl_errors(hdev); + } + + return error_count; } -static void gaudi2_handle_qman_err(struct hl_device *hdev, u16 event_type) +static int gaudi2_handle_qman_err(struct hl_device *hdev, u16 event_type, u64 *event_mask) { - u32 qid_base; + u32 qid_base, error_count = 0; u64 qman_base; - char desc[32]; u8 index; switch (event_type) { @@ -7835,194 +7983,207 @@ static void gaudi2_handle_qman_err(struct hl_device *hdev, u16 event_type) index = event_type - GAUDI2_EVENT_TPC0_QM; qid_base = GAUDI2_QUEUE_ID_DCORE0_TPC_0_0 + index * QMAN_STREAMS; qman_base = mmDCORE0_TPC0_QM_BASE + index * DCORE_TPC_OFFSET; - snprintf(desc, ARRAY_SIZE(desc), "DCORE0_TPC%d_QM", index); break; case GAUDI2_EVENT_TPC6_QM ... GAUDI2_EVENT_TPC11_QM: index = event_type - GAUDI2_EVENT_TPC6_QM; qid_base = GAUDI2_QUEUE_ID_DCORE1_TPC_0_0 + index * QMAN_STREAMS; qman_base = mmDCORE1_TPC0_QM_BASE + index * DCORE_TPC_OFFSET; - snprintf(desc, ARRAY_SIZE(desc), "DCORE1_TPC%d_QM", index); break; case GAUDI2_EVENT_TPC12_QM ... GAUDI2_EVENT_TPC17_QM: index = event_type - GAUDI2_EVENT_TPC12_QM; qid_base = GAUDI2_QUEUE_ID_DCORE2_TPC_0_0 + index * QMAN_STREAMS; qman_base = mmDCORE2_TPC0_QM_BASE + index * DCORE_TPC_OFFSET; - snprintf(desc, ARRAY_SIZE(desc), "DCORE2_TPC%d_QM", index); break; case GAUDI2_EVENT_TPC18_QM ... GAUDI2_EVENT_TPC23_QM: index = event_type - GAUDI2_EVENT_TPC18_QM; qid_base = GAUDI2_QUEUE_ID_DCORE3_TPC_0_0 + index * QMAN_STREAMS; qman_base = mmDCORE3_TPC0_QM_BASE + index * DCORE_TPC_OFFSET; - snprintf(desc, ARRAY_SIZE(desc), "DCORE3_TPC%d_QM", index); break; case GAUDI2_EVENT_TPC24_QM: qid_base = GAUDI2_QUEUE_ID_DCORE0_TPC_6_0; qman_base = mmDCORE0_TPC6_QM_BASE; - snprintf(desc, ARRAY_SIZE(desc), "DCORE0_TPC6_QM"); break; case GAUDI2_EVENT_MME0_QM: qid_base = GAUDI2_QUEUE_ID_DCORE0_MME_0_0; qman_base = mmDCORE0_MME_QM_BASE; - snprintf(desc, ARRAY_SIZE(desc), "DCORE0_MME_QM"); break; case GAUDI2_EVENT_MME1_QM: qid_base = GAUDI2_QUEUE_ID_DCORE1_MME_0_0; qman_base = mmDCORE1_MME_QM_BASE; - snprintf(desc, ARRAY_SIZE(desc), "DCORE1_MME_QM"); break; case GAUDI2_EVENT_MME2_QM: qid_base = GAUDI2_QUEUE_ID_DCORE2_MME_0_0; qman_base = mmDCORE2_MME_QM_BASE; - snprintf(desc, ARRAY_SIZE(desc), "DCORE2_MME_QM"); break; case GAUDI2_EVENT_MME3_QM: qid_base = GAUDI2_QUEUE_ID_DCORE3_MME_0_0; qman_base = mmDCORE3_MME_QM_BASE; - snprintf(desc, ARRAY_SIZE(desc), "DCORE3_MME_QM"); break; case GAUDI2_EVENT_HDMA0_QM: + index = 0; qid_base = GAUDI2_QUEUE_ID_DCORE0_EDMA_0_0; qman_base = mmDCORE0_EDMA0_QM_BASE; - snprintf(desc, ARRAY_SIZE(desc), "DCORE0_EDMA0_QM"); break; case GAUDI2_EVENT_HDMA1_QM: + index = 1; qid_base = GAUDI2_QUEUE_ID_DCORE0_EDMA_1_0; qman_base = mmDCORE0_EDMA1_QM_BASE; - snprintf(desc, ARRAY_SIZE(desc), "DCORE0_EDMA1_QM"); break; case GAUDI2_EVENT_HDMA2_QM: + index = 2; qid_base = GAUDI2_QUEUE_ID_DCORE1_EDMA_0_0; qman_base = mmDCORE1_EDMA0_QM_BASE; - snprintf(desc, ARRAY_SIZE(desc), "DCORE1_EDMA0_QM"); break; case GAUDI2_EVENT_HDMA3_QM: + index = 3; qid_base = GAUDI2_QUEUE_ID_DCORE1_EDMA_1_0; qman_base = mmDCORE1_EDMA1_QM_BASE; - snprintf(desc, ARRAY_SIZE(desc), "DCORE1_EDMA1_QM"); break; case GAUDI2_EVENT_HDMA4_QM: + index = 4; qid_base = GAUDI2_QUEUE_ID_DCORE2_EDMA_0_0; qman_base = mmDCORE2_EDMA0_QM_BASE; - snprintf(desc, ARRAY_SIZE(desc), "DCORE2_EDMA0_QM"); break; case GAUDI2_EVENT_HDMA5_QM: + index = 5; qid_base = GAUDI2_QUEUE_ID_DCORE2_EDMA_1_0; qman_base = mmDCORE2_EDMA1_QM_BASE; - snprintf(desc, ARRAY_SIZE(desc), "DCORE2_EDMA1_QM"); break; case GAUDI2_EVENT_HDMA6_QM: + index = 6; qid_base = GAUDI2_QUEUE_ID_DCORE3_EDMA_0_0; qman_base = mmDCORE3_EDMA0_QM_BASE; - snprintf(desc, ARRAY_SIZE(desc), "DCORE3_EDMA0_QM"); break; case GAUDI2_EVENT_HDMA7_QM: + index = 7; qid_base = GAUDI2_QUEUE_ID_DCORE3_EDMA_1_0; qman_base = mmDCORE3_EDMA1_QM_BASE; - snprintf(desc, ARRAY_SIZE(desc), "DCORE3_EDMA1_QM"); break; case GAUDI2_EVENT_PDMA0_QM: qid_base = GAUDI2_QUEUE_ID_PDMA_0_0; qman_base = mmPDMA0_QM_BASE; - snprintf(desc, ARRAY_SIZE(desc), "PDMA0_QM"); break; case GAUDI2_EVENT_PDMA1_QM: qid_base = GAUDI2_QUEUE_ID_PDMA_1_0; qman_base = mmPDMA1_QM_BASE; - snprintf(desc, ARRAY_SIZE(desc), "PDMA1_QM"); break; case GAUDI2_EVENT_ROTATOR0_ROT0_QM: qid_base = GAUDI2_QUEUE_ID_ROT_0_0; qman_base = mmROT0_QM_BASE; - snprintf(desc, ARRAY_SIZE(desc), "ROTATOR0_QM"); break; case GAUDI2_EVENT_ROTATOR1_ROT1_QM: qid_base = GAUDI2_QUEUE_ID_ROT_1_0; qman_base = mmROT1_QM_BASE; - snprintf(desc, ARRAY_SIZE(desc), "ROTATOR1_QM"); break; default: - return; + return 0; } - gaudi2_handle_qman_err_generic(hdev, desc, qman_base, qid_base); + error_count = gaudi2_handle_qman_err_generic(hdev, event_type, qman_base, qid_base); /* Handle EDMA QM SEI here because there is no AXI error response event for EDMA */ - if (event_type >= GAUDI2_EVENT_HDMA2_QM && event_type <= GAUDI2_EVENT_HDMA5_QM) - _gaudi2_handle_qm_sei_err(hdev, qman_base); + if (event_type >= GAUDI2_EVENT_HDMA2_QM && event_type <= GAUDI2_EVENT_HDMA5_QM) { + error_count += _gaudi2_handle_qm_sei_err(hdev, qman_base, event_type); + gaudi2_ack_module_razwi_event_handler(hdev, RAZWI_EDMA, index, 0, event_mask); + } + + hl_check_for_glbl_errors(hdev); + + return error_count; } -static void gaudi2_handle_arc_farm_sei_err(struct hl_device *hdev) +static int gaudi2_handle_arc_farm_sei_err(struct hl_device *hdev, u16 event_type) { - u32 i, sts_val, sts_clr_val = 0; + u32 i, sts_val, sts_clr_val = 0, error_count = 0; sts_val = RREG32(mmARC_FARM_ARC0_AUX_ARC_SEI_INTR_STS); for (i = 0 ; i < GAUDI2_NUM_OF_ARC_SEI_ERR_CAUSE ; i++) { if (sts_val & BIT(i)) { - dev_err_ratelimited(hdev->dev, "ARC SEI. err cause: %s\n", - gaudi2_arc_sei_error_cause[i]); + gaudi2_print_event(hdev, event_type, true, + "err cause: %s", gaudi2_arc_sei_error_cause[i]); sts_clr_val |= BIT(i); + error_count++; } } + hl_check_for_glbl_errors(hdev); + WREG32(mmARC_FARM_ARC0_AUX_ARC_SEI_INTR_CLR, sts_clr_val); + + return error_count; } -static void gaudi2_handle_cpu_sei_err(struct hl_device *hdev) +static int gaudi2_handle_cpu_sei_err(struct hl_device *hdev, u16 event_type) { - u32 i, sts_val, sts_clr_val = 0; + u32 i, sts_val, sts_clr_val = 0, error_count = 0; sts_val = RREG32(mmCPU_IF_CPU_SEI_INTR_STS); for (i = 0 ; i < GAUDI2_NUM_OF_CPU_SEI_ERR_CAUSE ; i++) { if (sts_val & BIT(i)) { - dev_err_ratelimited(hdev->dev, "CPU SEI. err cause: %s\n", - gaudi2_cpu_sei_error_cause[i]); + gaudi2_print_event(hdev, event_type, true, + "err cause: %s", gaudi2_cpu_sei_error_cause[i]); sts_clr_val |= BIT(i); + error_count++; } } + hl_check_for_glbl_errors(hdev); + WREG32(mmCPU_IF_CPU_SEI_INTR_CLR, sts_clr_val); + + return error_count; } -static void gaudi2_handle_rot_err(struct hl_device *hdev, u8 rot_index, +static int gaudi2_handle_rot_err(struct hl_device *hdev, u8 rot_index, u16 event_type, struct hl_eq_razwi_with_intr_cause *razwi_with_intr_cause, u64 *event_mask) { u64 intr_cause_data = le64_to_cpu(razwi_with_intr_cause->intr_cause.intr_cause_data); + u32 error_count = 0; int i; for (i = 0 ; i < GAUDI2_NUM_OF_ROT_ERR_CAUSE ; i++) - if (intr_cause_data & BIT(i)) - dev_err_ratelimited(hdev->dev, "ROT%u. err cause: %s\n", - rot_index, guadi2_rot_error_cause[i]); + if (intr_cause_data & BIT(i)) { + gaudi2_print_event(hdev, event_type, true, + "err cause: %s", guadi2_rot_error_cause[i]); + error_count++; + } /* check if RAZWI happened */ - gaudi2_ack_module_razwi_event_handler(hdev, RAZWI_ROT, rot_index, 0, - &razwi_with_intr_cause->razwi_info, event_mask); + gaudi2_ack_module_razwi_event_handler(hdev, RAZWI_ROT, rot_index, 0, event_mask); + hl_check_for_glbl_errors(hdev); + + return error_count; } -static void gaudi2_tpc_ack_interrupts(struct hl_device *hdev, u8 tpc_index, char *interrupt_name, +static int gaudi2_tpc_ack_interrupts(struct hl_device *hdev, u8 tpc_index, u16 event_type, struct hl_eq_razwi_with_intr_cause *razwi_with_intr_cause, u64 *event_mask) { u64 intr_cause_data = le64_to_cpu(razwi_with_intr_cause->intr_cause.intr_cause_data); + u32 error_count = 0; int i; for (i = 0 ; i < GAUDI2_NUM_OF_TPC_INTR_CAUSE ; i++) - if (intr_cause_data & BIT(i)) - dev_err_ratelimited(hdev->dev, "TPC%d_%s interrupt cause: %s\n", - tpc_index, interrupt_name, gaudi2_tpc_interrupts_cause[i]); + if (intr_cause_data & BIT(i)) { + gaudi2_print_event(hdev, event_type, true, + "interrupt cause: %s", gaudi2_tpc_interrupts_cause[i]); + error_count++; + } /* check if RAZWI happened */ - gaudi2_ack_module_razwi_event_handler(hdev, RAZWI_TPC, tpc_index, 0, - &razwi_with_intr_cause->razwi_info, event_mask); + gaudi2_ack_module_razwi_event_handler(hdev, RAZWI_TPC, tpc_index, 0, event_mask); + hl_check_for_glbl_errors(hdev); + + return error_count; } -static void gaudi2_handle_dec_err(struct hl_device *hdev, u8 dec_index, const char *interrupt_name, - struct hl_eq_razwi_info *razwi_info, u64 *event_mask) +static int gaudi2_handle_dec_err(struct hl_device *hdev, u8 dec_index, u16 event_type, + u64 *event_mask) { - u32 sts_addr, sts_val, sts_clr_val = 0; + u32 sts_addr, sts_val, sts_clr_val = 0, error_count = 0; int i; if (dec_index < NUM_OF_VDEC_PER_DCORE * NUM_OF_DCORES) @@ -8039,24 +8200,27 @@ static void gaudi2_handle_dec_err(struct hl_device *hdev, u8 dec_index, const ch for (i = 0 ; i < GAUDI2_NUM_OF_DEC_ERR_CAUSE ; i++) { if (sts_val & BIT(i)) { - dev_err_ratelimited(hdev->dev, "DEC%u_%s err cause: %s\n", - dec_index, interrupt_name, gaudi2_dec_error_cause[i]); + gaudi2_print_event(hdev, event_type, true, + "err cause: %s", gaudi2_dec_error_cause[i]); sts_clr_val |= BIT(i); + error_count++; } } /* check if RAZWI happened */ - gaudi2_ack_module_razwi_event_handler(hdev, RAZWI_DEC, dec_index, 0, razwi_info, - event_mask); + gaudi2_ack_module_razwi_event_handler(hdev, RAZWI_DEC, dec_index, 0, event_mask); + hl_check_for_glbl_errors(hdev); /* Write 1 clear errors */ WREG32(sts_addr, sts_clr_val); + + return error_count; } -static void gaudi2_handle_mme_err(struct hl_device *hdev, u8 mme_index, const char *interrupt_name, - struct hl_eq_razwi_info *razwi_info, u64 *event_mask) +static int gaudi2_handle_mme_err(struct hl_device *hdev, u8 mme_index, u16 event_type, + u64 *event_mask) { - u32 sts_addr, sts_val, sts_clr_addr, sts_clr_val = 0; + u32 sts_addr, sts_val, sts_clr_addr, sts_clr_val = 0, error_count = 0; int i; sts_addr = mmDCORE0_MME_CTRL_LO_INTR_CAUSE + DCORE_OFFSET * mme_index; @@ -8066,35 +8230,45 @@ static void gaudi2_handle_mme_err(struct hl_device *hdev, u8 mme_index, const ch for (i = 0 ; i < GAUDI2_NUM_OF_MME_ERR_CAUSE ; i++) { if (sts_val & BIT(i)) { - dev_err_ratelimited(hdev->dev, "MME%u_%s err cause: %s\n", - mme_index, interrupt_name, guadi2_mme_error_cause[i]); + gaudi2_print_event(hdev, event_type, true, + "err cause: %s", guadi2_mme_error_cause[i]); sts_clr_val |= BIT(i); + error_count++; } } /* check if RAZWI happened */ for (i = MME_WRITE ; i < MME_INITIATORS_MAX ; i++) - gaudi2_ack_module_razwi_event_handler(hdev, RAZWI_MME, mme_index, i, razwi_info, - event_mask); + gaudi2_ack_module_razwi_event_handler(hdev, RAZWI_MME, mme_index, i, event_mask); + + hl_check_for_glbl_errors(hdev); WREG32(sts_clr_addr, sts_clr_val); + + return error_count; } -static void gaudi2_handle_mme_sbte_err(struct hl_device *hdev, u8 mme_index, u8 sbte_index, +static int gaudi2_handle_mme_sbte_err(struct hl_device *hdev, u16 event_type, u64 intr_cause_data) { - int i; + int i, error_count = 0; for (i = 0 ; i < GAUDI2_NUM_OF_MME_SBTE_ERR_CAUSE ; i++) - if (intr_cause_data & BIT(i)) - dev_err_ratelimited(hdev->dev, "MME%uSBTE%u_AXI_ERR_RSP err cause: %s\n", - mme_index, sbte_index, guadi2_mme_sbte_error_cause[i]); + if (intr_cause_data & BIT(i)) { + gaudi2_print_event(hdev, event_type, true, + "err cause: %s", guadi2_mme_sbte_error_cause[i]); + error_count++; + } + + hl_check_for_glbl_errors(hdev); + + return error_count; } -static void gaudi2_handle_mme_wap_err(struct hl_device *hdev, u8 mme_index, - struct hl_eq_razwi_info *razwi_info, u64 *event_mask) +static int gaudi2_handle_mme_wap_err(struct hl_device *hdev, u8 mme_index, u16 event_type, + u64 *event_mask) { - u32 sts_addr, sts_val, sts_clr_addr, sts_clr_val = 0; + u32 sts_addr, sts_val, sts_clr_addr, sts_clr_val = 0, error_count = 0; int i; sts_addr = mmDCORE0_MME_ACC_INTR_CAUSE + DCORE_OFFSET * mme_index; @@ -8104,24 +8278,27 @@ static void gaudi2_handle_mme_wap_err(struct hl_device *hdev, u8 mme_index, for (i = 0 ; i < GAUDI2_NUM_OF_MME_WAP_ERR_CAUSE ; i++) { if (sts_val & BIT(i)) { - dev_err_ratelimited(hdev->dev, - "MME%u_WAP_SOURCE_RESULT_INVALID err cause: %s\n", - mme_index, guadi2_mme_wap_error_cause[i]); + gaudi2_print_event(hdev, event_type, true, + "err cause: %s", guadi2_mme_wap_error_cause[i]); sts_clr_val |= BIT(i); + error_count++; } } /* check if RAZWI happened on WAP0/1 */ - gaudi2_ack_module_razwi_event_handler(hdev, RAZWI_MME, mme_index, MME_WAP0, razwi_info, - event_mask); - gaudi2_ack_module_razwi_event_handler(hdev, RAZWI_MME, mme_index, MME_WAP1, razwi_info, - event_mask); + gaudi2_ack_module_razwi_event_handler(hdev, RAZWI_MME, mme_index, MME_WAP0, event_mask); + gaudi2_ack_module_razwi_event_handler(hdev, RAZWI_MME, mme_index, MME_WAP1, event_mask); + hl_check_for_glbl_errors(hdev); WREG32(sts_clr_addr, sts_clr_val); + + return error_count; } -static void gaudi2_handle_kdma_core_event(struct hl_device *hdev, u64 intr_cause_data) +static int gaudi2_handle_kdma_core_event(struct hl_device *hdev, u16 event_type, + u64 intr_cause_data) { + u32 error_count = 0; int i; /* If an AXI read or write error is received, an error is reported and @@ -8130,19 +8307,33 @@ static void gaudi2_handle_kdma_core_event(struct hl_device *hdev, u64 intr_cause * the actual error caused by a LBW KDMA transaction. */ for (i = 0 ; i < GAUDI2_NUM_OF_DMA_CORE_INTR_CAUSE ; i++) - if (intr_cause_data & BIT(i)) - dev_err_ratelimited(hdev->dev, "kdma core err cause: %s\n", - gaudi2_kdma_core_interrupts_cause[i]); + if (intr_cause_data & BIT(i)) { + gaudi2_print_event(hdev, event_type, true, + "err cause: %s", gaudi2_kdma_core_interrupts_cause[i]); + error_count++; + } + + hl_check_for_glbl_errors(hdev); + + return error_count; } -static void gaudi2_handle_dma_core_event(struct hl_device *hdev, u64 intr_cause_data) +static int gaudi2_handle_dma_core_event(struct hl_device *hdev, u16 event_type, + u64 intr_cause_data) { + u32 error_count = 0; int i; for (i = 0 ; i < GAUDI2_NUM_OF_DMA_CORE_INTR_CAUSE ; i++) - if (intr_cause_data & BIT(i)) - dev_err_ratelimited(hdev->dev, "dma core err cause: %s\n", - gaudi2_dma_core_interrupts_cause[i]); + if (intr_cause_data & BIT(i)) { + gaudi2_print_event(hdev, event_type, true, + "err cause: %s", gaudi2_dma_core_interrupts_cause[i]); + error_count++; + } + + hl_check_for_glbl_errors(hdev); + + return error_count; } static void gaudi2_print_pcie_mstr_rr_mstr_if_razwi_info(struct hl_device *hdev, u64 *event_mask) @@ -8151,86 +8342,98 @@ static void gaudi2_print_pcie_mstr_rr_mstr_if_razwi_info(struct hl_device *hdev, razwi_happened_addr = mstr_if_base_addr + RR_SHRD_HBW_AW_RAZWI_HAPPENED; if (RREG32(razwi_happened_addr)) { - gaudi2_razwi_rr_hbw_shared_printf_info(hdev, mstr_if_base_addr, true, "PCIE", true, - NULL, GAUDI2_ENGINE_ID_PCIE, event_mask); + gaudi2_razwi_rr_hbw_shared_printf_info(hdev, mstr_if_base_addr, true, "PCIE", + GAUDI2_ENGINE_ID_PCIE, event_mask); WREG32(razwi_happened_addr, 0x1); } razwi_happened_addr = mstr_if_base_addr + RR_SHRD_HBW_AR_RAZWI_HAPPENED; if (RREG32(razwi_happened_addr)) { - gaudi2_razwi_rr_hbw_shared_printf_info(hdev, mstr_if_base_addr, false, "PCIE", true, - NULL, GAUDI2_ENGINE_ID_PCIE, event_mask); + gaudi2_razwi_rr_hbw_shared_printf_info(hdev, mstr_if_base_addr, false, "PCIE", + GAUDI2_ENGINE_ID_PCIE, event_mask); WREG32(razwi_happened_addr, 0x1); } razwi_happened_addr = mstr_if_base_addr + RR_SHRD_LBW_AW_RAZWI_HAPPENED; if (RREG32(razwi_happened_addr)) { - gaudi2_razwi_rr_lbw_shared_printf_info(hdev, mstr_if_base_addr, true, "PCIE", true, - NULL, GAUDI2_ENGINE_ID_PCIE, event_mask); + gaudi2_razwi_rr_lbw_shared_printf_info(hdev, mstr_if_base_addr, true, "PCIE", + GAUDI2_ENGINE_ID_PCIE, event_mask); WREG32(razwi_happened_addr, 0x1); } razwi_happened_addr = mstr_if_base_addr + RR_SHRD_LBW_AR_RAZWI_HAPPENED; if (RREG32(razwi_happened_addr)) { - gaudi2_razwi_rr_lbw_shared_printf_info(hdev, mstr_if_base_addr, false, "PCIE", true, - NULL, GAUDI2_ENGINE_ID_PCIE, event_mask); + gaudi2_razwi_rr_lbw_shared_printf_info(hdev, mstr_if_base_addr, false, "PCIE", + GAUDI2_ENGINE_ID_PCIE, event_mask); WREG32(razwi_happened_addr, 0x1); } } -static void gaudi2_print_pcie_addr_dec_info(struct hl_device *hdev, u64 intr_cause_data, - u64 *event_mask) +static int gaudi2_print_pcie_addr_dec_info(struct hl_device *hdev, u16 event_type, + u64 intr_cause_data, u64 *event_mask) { + u32 error_count = 0; int i; for (i = 0 ; i < GAUDI2_NUM_OF_PCIE_ADDR_DEC_ERR_CAUSE ; i++) { if (!(intr_cause_data & BIT_ULL(i))) continue; - dev_err_ratelimited(hdev->dev, "PCIE ADDR DEC Error: %s\n", - gaudi2_pcie_addr_dec_error_cause[i]); + gaudi2_print_event(hdev, event_type, true, + "err cause: %s", gaudi2_pcie_addr_dec_error_cause[i]); + error_count++; switch (intr_cause_data & BIT_ULL(i)) { case PCIE_WRAP_PCIE_IC_SEI_INTR_IND_AXI_LBW_ERR_INTR_MASK: + hl_check_for_glbl_errors(hdev); break; case PCIE_WRAP_PCIE_IC_SEI_INTR_IND_BAD_ACCESS_INTR_MASK: gaudi2_print_pcie_mstr_rr_mstr_if_razwi_info(hdev, event_mask); break; } } + + return error_count; } -static void gaudi2_handle_pif_fatal(struct hl_device *hdev, u64 intr_cause_data) +static int gaudi2_handle_pif_fatal(struct hl_device *hdev, u16 event_type, + u64 intr_cause_data) { + u32 error_count = 0; int i; for (i = 0 ; i < GAUDI2_NUM_OF_PMMU_FATAL_ERR_CAUSE ; i++) { - if (intr_cause_data & BIT_ULL(i)) - dev_err_ratelimited(hdev->dev, "PMMU PIF err cause: %s\n", - gaudi2_pmmu_fatal_interrupts_cause[i]); + if (intr_cause_data & BIT_ULL(i)) { + gaudi2_print_event(hdev, event_type, true, + "err cause: %s", gaudi2_pmmu_fatal_interrupts_cause[i]); + error_count++; + } } + + return error_count; } -static void gaudi2_handle_hif_fatal(struct hl_device *hdev, u16 event_type, u64 intr_cause_data) +static int gaudi2_handle_hif_fatal(struct hl_device *hdev, u16 event_type, u64 intr_cause_data) { - u32 dcore_id, hif_id; + u32 error_count = 0; int i; - dcore_id = (event_type - GAUDI2_EVENT_HIF0_FATAL) / 4; - hif_id = (event_type - GAUDI2_EVENT_HIF0_FATAL) % 4; - for (i = 0 ; i < GAUDI2_NUM_OF_HIF_FATAL_ERR_CAUSE ; i++) { - if (intr_cause_data & BIT_ULL(i)) - dev_err_ratelimited(hdev->dev, "DCORE%u_HIF%u: %s\n", dcore_id, hif_id, - gaudi2_hif_fatal_interrupts_cause[i]); + if (intr_cause_data & BIT_ULL(i)) { + gaudi2_print_event(hdev, event_type, true, + "err cause: %s", gaudi2_hif_fatal_interrupts_cause[i]); + error_count++; + } } + + return error_count; } static void gaudi2_handle_page_error(struct hl_device *hdev, u64 mmu_base, bool is_pmmu, u64 *event_mask) { - u32 valid, val; + u32 valid, val, axid_l, axid_h; u64 addr; valid = RREG32(mmu_base + MMU_OFFSET(mmDCORE0_HMMU0_MMU_ACCESS_PAGE_ERROR_VALID)); @@ -8243,8 +8446,11 @@ static void gaudi2_handle_page_error(struct hl_device *hdev, u64 mmu_base, bool addr <<= 32; addr |= RREG32(mmu_base + MMU_OFFSET(mmDCORE0_HMMU0_MMU_PAGE_ERROR_CAPTURE_VA)); - dev_err_ratelimited(hdev->dev, "%s page fault on va 0x%llx\n", - is_pmmu ? "PMMU" : "HMMU", addr); + axid_l = RREG32(mmu_base + MMU_OFFSET(mmDCORE0_HMMU0_MMU_PAGE_FAULT_ID_LSB)); + axid_h = RREG32(mmu_base + MMU_OFFSET(mmDCORE0_HMMU0_MMU_PAGE_FAULT_ID_MSB)); + + dev_err_ratelimited(hdev->dev, "%s page fault on va 0x%llx, transaction id 0x%llX\n", + is_pmmu ? "PMMU" : "HMMU", addr, ((u64)axid_h << 32) + axid_l); hl_handle_page_fault(hdev, addr, 0, is_pmmu, event_mask); WREG32(mmu_base + MMU_OFFSET(mmDCORE0_HMMU0_MMU_PAGE_ERROR_CAPTURE), 0); @@ -8270,18 +8476,18 @@ static void gaudi2_handle_access_error(struct hl_device *hdev, u64 mmu_base, boo WREG32(mmu_base + MMU_OFFSET(mmDCORE0_HMMU0_MMU_ACCESS_ERROR_CAPTURE), 0); } -static void gaudi2_handle_mmu_spi_sei_generic(struct hl_device *hdev, const char *mmu_name, +static int gaudi2_handle_mmu_spi_sei_generic(struct hl_device *hdev, u16 event_type, u64 mmu_base, bool is_pmmu, u64 *event_mask) { - u32 spi_sei_cause, interrupt_clr = 0x0; + u32 spi_sei_cause, interrupt_clr = 0x0, error_count = 0; int i; spi_sei_cause = RREG32(mmu_base + MMU_SPI_SEI_CAUSE_OFFSET); for (i = 0 ; i < GAUDI2_NUM_OF_MMU_SPI_SEI_CAUSE ; i++) { if (spi_sei_cause & BIT(i)) { - dev_err_ratelimited(hdev->dev, "%s SPI_SEI ERR. err cause: %s\n", - mmu_name, gaudi2_mmu_spi_sei[i].cause); + gaudi2_print_event(hdev, event_type, true, + "err cause: %s", gaudi2_mmu_spi_sei[i].cause); if (i == 0) gaudi2_handle_page_error(hdev, mmu_base, is_pmmu, event_mask); @@ -8290,6 +8496,8 @@ static void gaudi2_handle_mmu_spi_sei_generic(struct hl_device *hdev, const char if (gaudi2_mmu_spi_sei[i].clear_bit >= 0) interrupt_clr |= BIT(gaudi2_mmu_spi_sei[i].clear_bit); + + error_count++; } } @@ -8298,12 +8506,14 @@ static void gaudi2_handle_mmu_spi_sei_generic(struct hl_device *hdev, const char /* Clear interrupt */ WREG32(mmu_base + MMU_INTERRUPT_CLR_OFFSET, interrupt_clr); + + return error_count; } -static void gaudi2_handle_sm_err(struct hl_device *hdev, u8 sm_index) +static int gaudi2_handle_sm_err(struct hl_device *hdev, u16 event_type, u8 sm_index) { - u32 sei_cause_addr, sei_cause_val, sei_cause_cause, sei_cause_log; - u32 cq_intr_addr, cq_intr_val, cq_intr_queue_index; + u32 sei_cause_addr, sei_cause_val, sei_cause_cause, sei_cause_log, + cq_intr_addr, cq_intr_val, cq_intr_queue_index, error_count = 0; int i; sei_cause_addr = mmDCORE0_SYNC_MNGR_GLBL_SM_SEI_CAUSE + DCORE_OFFSET * sm_index; @@ -8323,11 +8533,12 @@ static void gaudi2_handle_sm_err(struct hl_device *hdev, u8 sm_index) if (!(sei_cause_cause & BIT(i))) continue; - dev_err_ratelimited(hdev->dev, "SM%u SEI ERR. err cause: %s. %s: 0x%X\n", - sm_index, - gaudi2_sm_sei_cause[i].cause_name, - gaudi2_sm_sei_cause[i].log_name, - sei_cause_log & gaudi2_sm_sei_cause[i].log_mask); + gaudi2_print_event(hdev, event_type, true, + "err cause: %s. %s: 0x%X\n", + gaudi2_sm_sei_cause[i].cause_name, + gaudi2_sm_sei_cause[i].log_name, + sei_cause_log); + error_count++; break; } @@ -8343,16 +8554,21 @@ static void gaudi2_handle_sm_err(struct hl_device *hdev, u8 sm_index) dev_err_ratelimited(hdev->dev, "SM%u err. err cause: CQ_INTR. queue index: %u\n", sm_index, cq_intr_queue_index); + error_count++; /* Clear CQ_INTR */ WREG32(cq_intr_addr, 0); } + + hl_check_for_glbl_errors(hdev); + + return error_count; } -static void gaudi2_handle_mmu_spi_sei_err(struct hl_device *hdev, u16 event_type, u64 *event_mask) +static int gaudi2_handle_mmu_spi_sei_err(struct hl_device *hdev, u16 event_type, u64 *event_mask) { bool is_pmmu = false; - char desc[32]; + u32 error_count = 0; u64 mmu_base; u8 index; @@ -8360,54 +8576,49 @@ static void gaudi2_handle_mmu_spi_sei_err(struct hl_device *hdev, u16 event_type case GAUDI2_EVENT_HMMU0_PAGE_FAULT_OR_WR_PERM ... GAUDI2_EVENT_HMMU3_SECURITY_ERROR: index = (event_type - GAUDI2_EVENT_HMMU0_PAGE_FAULT_OR_WR_PERM) / 3; mmu_base = mmDCORE0_HMMU0_MMU_BASE + index * DCORE_HMMU_OFFSET; - snprintf(desc, ARRAY_SIZE(desc), "DCORE0_HMMU%d", index); break; case GAUDI2_EVENT_HMMU_0_AXI_ERR_RSP ... GAUDI2_EVENT_HMMU_3_AXI_ERR_RSP: index = (event_type - GAUDI2_EVENT_HMMU_0_AXI_ERR_RSP); mmu_base = mmDCORE0_HMMU0_MMU_BASE + index * DCORE_HMMU_OFFSET; - snprintf(desc, ARRAY_SIZE(desc), "DCORE0_HMMU%d", index); break; case GAUDI2_EVENT_HMMU8_PAGE_FAULT_WR_PERM ... GAUDI2_EVENT_HMMU11_SECURITY_ERROR: index = (event_type - GAUDI2_EVENT_HMMU8_PAGE_FAULT_WR_PERM) / 3; mmu_base = mmDCORE1_HMMU0_MMU_BASE + index * DCORE_HMMU_OFFSET; - snprintf(desc, ARRAY_SIZE(desc), "DCORE1_HMMU%d", index); break; case GAUDI2_EVENT_HMMU_8_AXI_ERR_RSP ... GAUDI2_EVENT_HMMU_11_AXI_ERR_RSP: index = (event_type - GAUDI2_EVENT_HMMU_8_AXI_ERR_RSP); mmu_base = mmDCORE1_HMMU0_MMU_BASE + index * DCORE_HMMU_OFFSET; - snprintf(desc, ARRAY_SIZE(desc), "DCORE1_HMMU%d", index); break; case GAUDI2_EVENT_HMMU7_PAGE_FAULT_WR_PERM ... GAUDI2_EVENT_HMMU4_SECURITY_ERROR: index = (event_type - GAUDI2_EVENT_HMMU7_PAGE_FAULT_WR_PERM) / 3; mmu_base = mmDCORE2_HMMU0_MMU_BASE + index * DCORE_HMMU_OFFSET; - snprintf(desc, ARRAY_SIZE(desc), "DCORE2_HMMU%d", index); break; case GAUDI2_EVENT_HMMU_7_AXI_ERR_RSP ... GAUDI2_EVENT_HMMU_4_AXI_ERR_RSP: index = (event_type - GAUDI2_EVENT_HMMU_7_AXI_ERR_RSP); mmu_base = mmDCORE2_HMMU0_MMU_BASE + index * DCORE_HMMU_OFFSET; - snprintf(desc, ARRAY_SIZE(desc), "DCORE2_HMMU%d", index); break; case GAUDI2_EVENT_HMMU15_PAGE_FAULT_WR_PERM ... GAUDI2_EVENT_HMMU12_SECURITY_ERROR: index = (event_type - GAUDI2_EVENT_HMMU15_PAGE_FAULT_WR_PERM) / 3; mmu_base = mmDCORE3_HMMU0_MMU_BASE + index * DCORE_HMMU_OFFSET; - snprintf(desc, ARRAY_SIZE(desc), "DCORE3_HMMU%d", index); break; case GAUDI2_EVENT_HMMU_15_AXI_ERR_RSP ... GAUDI2_EVENT_HMMU_12_AXI_ERR_RSP: index = (event_type - GAUDI2_EVENT_HMMU_15_AXI_ERR_RSP); mmu_base = mmDCORE3_HMMU0_MMU_BASE + index * DCORE_HMMU_OFFSET; - snprintf(desc, ARRAY_SIZE(desc), "DCORE3_HMMU%d", index); break; case GAUDI2_EVENT_PMMU0_PAGE_FAULT_WR_PERM ... GAUDI2_EVENT_PMMU0_SECURITY_ERROR: case GAUDI2_EVENT_PMMU_AXI_ERR_RSP_0: is_pmmu = true; mmu_base = mmPMMU_HBW_MMU_BASE; - snprintf(desc, ARRAY_SIZE(desc), "PMMU"); break; default: - return; + return 0; } - gaudi2_handle_mmu_spi_sei_generic(hdev, desc, mmu_base, is_pmmu, event_mask); + error_count = gaudi2_handle_mmu_spi_sei_generic(hdev, event_type, mmu_base, + is_pmmu, event_mask); + hl_check_for_glbl_errors(hdev); + + return error_count; } @@ -8527,22 +8738,17 @@ static bool gaudi2_handle_hbm_mc_sei_err(struct hl_device *hdev, u16 event_type, cause_idx = sei_data->hdr.sei_cause; if (cause_idx > GAUDI2_NUM_OF_HBM_SEI_CAUSE - 1) { - dev_err_ratelimited(hdev->dev, "Invalid HBM SEI event cause (%d) provided by FW\n", - cause_idx); + gaudi2_print_event(hdev, event_type, true, + "err cause: %s", + "Invalid HBM SEI event cause (%d) provided by FW\n", cause_idx); return true; } - if (sei_data->hdr.is_critical) - dev_err(hdev->dev, - "System Critical Error Interrupt - HBM(%u) MC(%u) MC_CH(%u) MC_PC(%u). Error cause: %s\n", - hbm_id, mc_id, sei_data->hdr.mc_channel, sei_data->hdr.mc_pseudo_channel, - hbm_mc_sei_cause[cause_idx]); - - else - dev_err_ratelimited(hdev->dev, - "System Non-Critical Error Interrupt - HBM(%u) MC(%u) MC_CH(%u) MC_PC(%u). Error cause: %s\n", - hbm_id, mc_id, sei_data->hdr.mc_channel, sei_data->hdr.mc_pseudo_channel, - hbm_mc_sei_cause[cause_idx]); + gaudi2_print_event(hdev, event_type, !sei_data->hdr.is_critical, + "System %s Error Interrupt - HBM(%u) MC(%u) MC_CH(%u) MC_PC(%u). Error cause: %s\n", + sei_data->hdr.is_critical ? "Critical" : "Non-critical", + hbm_id, mc_id, sei_data->hdr.mc_channel, sei_data->hdr.mc_pseudo_channel, + hbm_mc_sei_cause[cause_idx]); /* Print error-specific info */ switch (cause_idx) { @@ -8586,24 +8792,33 @@ static bool gaudi2_handle_hbm_mc_sei_err(struct hl_device *hdev, u16 event_type, return require_hard_reset; } -static void gaudi2_handle_hbm_cattrip(struct hl_device *hdev, u64 intr_cause_data) +static int gaudi2_handle_hbm_cattrip(struct hl_device *hdev, u16 event_type, + u64 intr_cause_data) { - dev_err(hdev->dev, - "HBM catastrophic temperature error (CATTRIP) cause %#llx\n", - intr_cause_data); + if (intr_cause_data) { + gaudi2_print_event(hdev, event_type, true, + "temperature error cause: %#llx", intr_cause_data); + return 1; + } + + return 0; } -static void gaudi2_handle_hbm_mc_spi(struct hl_device *hdev, u64 intr_cause_data) +static int gaudi2_handle_hbm_mc_spi(struct hl_device *hdev, u64 intr_cause_data) { - u32 i; + u32 i, error_count = 0; for (i = 0 ; i < GAUDI2_NUM_OF_HBM_MC_SPI_CAUSE ; i++) - if (intr_cause_data & hbm_mc_spi[i].mask) + if (intr_cause_data & hbm_mc_spi[i].mask) { dev_dbg(hdev->dev, "HBM spi event: notification cause(%s)\n", hbm_mc_spi[i].cause); + error_count++; + } + + return error_count; } -static void gaudi2_print_clk_change_info(struct hl_device *hdev, u16 event_type) +static void gaudi2_print_clk_change_info(struct hl_device *hdev, u16 event_type, u64 *event_mask) { ktime_t zero_time = ktime_set(0, 0); @@ -8615,13 +8830,13 @@ static void gaudi2_print_clk_change_info(struct hl_device *hdev, u16 event_type) hdev->clk_throttling.aggregated_reason |= HL_CLK_THROTTLE_POWER; hdev->clk_throttling.timestamp[HL_CLK_THROTTLE_TYPE_POWER].start = ktime_get(); hdev->clk_throttling.timestamp[HL_CLK_THROTTLE_TYPE_POWER].end = zero_time; - dev_info_ratelimited(hdev->dev, "Clock throttling due to power consumption\n"); + dev_dbg_ratelimited(hdev->dev, "Clock throttling due to power consumption\n"); break; case GAUDI2_EVENT_CPU_FIX_POWER_ENV_E: hdev->clk_throttling.current_reason &= ~HL_CLK_THROTTLE_POWER; hdev->clk_throttling.timestamp[HL_CLK_THROTTLE_TYPE_POWER].end = ktime_get(); - dev_info_ratelimited(hdev->dev, "Power envelop is safe, back to optimal clock\n"); + dev_dbg_ratelimited(hdev->dev, "Power envelop is safe, back to optimal clock\n"); break; case GAUDI2_EVENT_CPU_FIX_THERMAL_ENV_S: @@ -8629,12 +8844,14 @@ static void gaudi2_print_clk_change_info(struct hl_device *hdev, u16 event_type) hdev->clk_throttling.aggregated_reason |= HL_CLK_THROTTLE_THERMAL; hdev->clk_throttling.timestamp[HL_CLK_THROTTLE_TYPE_THERMAL].start = ktime_get(); hdev->clk_throttling.timestamp[HL_CLK_THROTTLE_TYPE_THERMAL].end = zero_time; + *event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR; dev_info_ratelimited(hdev->dev, "Clock throttling due to overheating\n"); break; case GAUDI2_EVENT_CPU_FIX_THERMAL_ENV_E: hdev->clk_throttling.current_reason &= ~HL_CLK_THROTTLE_THERMAL; hdev->clk_throttling.timestamp[HL_CLK_THROTTLE_TYPE_THERMAL].end = ktime_get(); + *event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR; dev_info_ratelimited(hdev->dev, "Thermal envelop is safe, back to optimal clock\n"); break; @@ -8646,43 +8863,49 @@ static void gaudi2_print_clk_change_info(struct hl_device *hdev, u16 event_type) mutex_unlock(&hdev->clk_throttling.lock); } -static void gaudi2_print_out_of_sync_info(struct hl_device *hdev, +static void gaudi2_print_out_of_sync_info(struct hl_device *hdev, u16 event_type, struct cpucp_pkt_sync_err *sync_err) { struct hl_hw_queue *q = &hdev->kernel_queues[GAUDI2_QUEUE_ID_CPU_PQ]; - dev_err(hdev->dev, "Out of sync with FW, FW: pi=%u, ci=%u, LKD: pi=%u, ci=%d\n", - le32_to_cpu(sync_err->pi), le32_to_cpu(sync_err->ci), q->pi, atomic_read(&q->ci)); + gaudi2_print_event(hdev, event_type, false, + "FW: pi=%u, ci=%u, LKD: pi=%u, ci=%d\n", + le32_to_cpu(sync_err->pi), le32_to_cpu(sync_err->ci), + q->pi, atomic_read(&q->ci)); } -static void gaudi2_handle_pcie_p2p_msix(struct hl_device *hdev) +static int gaudi2_handle_pcie_p2p_msix(struct hl_device *hdev, u16 event_type) { - u32 p2p_intr, msix_gw_intr; + u32 p2p_intr, msix_gw_intr, error_count = 0; p2p_intr = RREG32(mmPCIE_WRAP_P2P_INTR); msix_gw_intr = RREG32(mmPCIE_WRAP_MSIX_GW_INTR); if (p2p_intr) { - dev_err_ratelimited(hdev->dev, + gaudi2_print_event(hdev, event_type, true, "pcie p2p transaction terminated due to security, req_id(0x%x)\n", RREG32(mmPCIE_WRAP_P2P_REQ_ID)); WREG32(mmPCIE_WRAP_P2P_INTR, 0x1); + error_count++; } if (msix_gw_intr) { - dev_err_ratelimited(hdev->dev, + gaudi2_print_event(hdev, event_type, true, "pcie msi-x gen denied due to vector num check failure, vec(0x%X)\n", RREG32(mmPCIE_WRAP_MSIX_GW_VEC)); WREG32(mmPCIE_WRAP_MSIX_GW_INTR, 0x1); + error_count++; } + + return error_count; } -static void gaudi2_handle_pcie_drain(struct hl_device *hdev, +static int gaudi2_handle_pcie_drain(struct hl_device *hdev, struct hl_eq_pcie_drain_ind_data *drain_data) { - u64 lbw_rd, lbw_wr, hbw_rd, hbw_wr, cause; + u64 lbw_rd, lbw_wr, hbw_rd, hbw_wr, cause, error_count = 0; cause = le64_to_cpu(drain_data->intr_cause.intr_cause_data); lbw_rd = le64_to_cpu(drain_data->drain_rd_addr_lbw); @@ -8690,39 +8913,52 @@ static void gaudi2_handle_pcie_drain(struct hl_device *hdev, hbw_rd = le64_to_cpu(drain_data->drain_rd_addr_hbw); hbw_wr = le64_to_cpu(drain_data->drain_wr_addr_hbw); - if (cause & BIT_ULL(0)) + if (cause & BIT_ULL(0)) { dev_err_ratelimited(hdev->dev, "PCIE AXI drain LBW completed, read_err %u, write_err %u\n", !!lbw_rd, !!lbw_wr); + error_count++; + } - if (cause & BIT_ULL(1)) + if (cause & BIT_ULL(1)) { dev_err_ratelimited(hdev->dev, "PCIE AXI drain HBW completed, raddr %#llx, waddr %#llx\n", hbw_rd, hbw_wr); + error_count++; + } + + return error_count; } -static void gaudi2_handle_psoc_drain(struct hl_device *hdev, u64 intr_cause_data) +static int gaudi2_handle_psoc_drain(struct hl_device *hdev, u64 intr_cause_data) { + u32 error_count = 0; int i; for (i = 0 ; i < GAUDI2_NUM_OF_AXI_DRAIN_ERR_CAUSE ; i++) { - if (intr_cause_data & BIT_ULL(i)) + if (intr_cause_data & BIT_ULL(i)) { dev_err_ratelimited(hdev->dev, "PSOC %s completed\n", gaudi2_psoc_axi_drain_interrupts_cause[i]); + error_count++; + } } + + hl_check_for_glbl_errors(hdev); + + return error_count; } -static void gaudi2_print_cpu_pkt_failure_info(struct hl_device *hdev, +static void gaudi2_print_cpu_pkt_failure_info(struct hl_device *hdev, u16 event_type, struct cpucp_pkt_sync_err *sync_err) { struct hl_hw_queue *q = &hdev->kernel_queues[GAUDI2_QUEUE_ID_CPU_PQ]; - dev_warn(hdev->dev, + gaudi2_print_event(hdev, event_type, false, "FW reported sanity check failure, FW: pi=%u, ci=%u, LKD: pi=%u, ci=%d\n", le32_to_cpu(sync_err->pi), le32_to_cpu(sync_err->ci), q->pi, atomic_read(&q->ci)); } -static void hl_arc_event_handle(struct hl_device *hdev, +static int hl_arc_event_handle(struct hl_device *hdev, u16 event_type, struct hl_eq_engine_arc_intr_data *data) { struct hl_engine_arc_dccm_queue_full_irq *q; @@ -8737,12 +8973,13 @@ static void hl_arc_event_handle(struct hl_device *hdev, case ENGINE_ARC_DCCM_QUEUE_FULL_IRQ: q = (struct hl_engine_arc_dccm_queue_full_irq *) &payload; - dev_err_ratelimited(hdev->dev, + gaudi2_print_event(hdev, event_type, true, "ARC DCCM Full event: EngId: %u, Intr_type: %u, Qidx: %u\n", engine_id, intr_type, q->queue_index); - break; + return 1; default: - dev_err_ratelimited(hdev->dev, "Unknown ARC event type\n"); + gaudi2_print_event(hdev, event_type, true, "Unknown ARC event type\n"); + return 0; } } @@ -8750,8 +8987,7 @@ static void gaudi2_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_ent { struct gaudi2_device *gaudi2 = hdev->asic_specific; bool reset_required = false, is_critical = false; - u32 ctl, reset_flags = HL_DRV_RESET_HARD; - int index, sbte_index; + u32 index, ctl, reset_flags = HL_DRV_RESET_HARD, error_count = 0; u64 event_mask = 0; u16 event_type; @@ -8767,8 +9003,6 @@ static void gaudi2_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_ent gaudi2->events_stat[event_type]++; gaudi2->events_stat_aggregate[event_type]++; - gaudi2_print_irq_info(hdev, event_type); - switch (event_type) { case GAUDI2_EVENT_PCIE_CORE_SERR ... GAUDI2_EVENT_ARC0_ECC_DERR: fallthrough; @@ -8777,6 +9011,7 @@ static void gaudi2_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_ent event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR; reset_required = gaudi2_handle_ecc_event(hdev, event_type, &eq_entry->ecc_data); is_critical = eq_entry->ecc_data.is_critical; + error_count++; break; case GAUDI2_EVENT_TPC0_QM ... GAUDI2_EVENT_PDMA1_QM: @@ -8784,48 +9019,48 @@ static void gaudi2_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_ent case GAUDI2_EVENT_ROTATOR0_ROT0_QM ... GAUDI2_EVENT_ROTATOR1_ROT1_QM: fallthrough; case GAUDI2_EVENT_NIC0_QM0 ... GAUDI2_EVENT_NIC11_QM1: - gaudi2_handle_qman_err(hdev, event_type); + error_count = gaudi2_handle_qman_err(hdev, event_type, &event_mask); event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR; break; case GAUDI2_EVENT_ARC_AXI_ERROR_RESPONSE_0: reset_flags |= HL_DRV_RESET_FW_FATAL_ERR; - gaudi2_handle_arc_farm_sei_err(hdev); + error_count = gaudi2_handle_arc_farm_sei_err(hdev, event_type); event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR; break; case GAUDI2_EVENT_CPU_AXI_ERR_RSP: - gaudi2_handle_cpu_sei_err(hdev); + error_count = gaudi2_handle_cpu_sei_err(hdev, event_type); event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR; break; case GAUDI2_EVENT_PDMA_CH0_AXI_ERR_RSP: case GAUDI2_EVENT_PDMA_CH1_AXI_ERR_RSP: reset_flags |= HL_DRV_RESET_FW_FATAL_ERR; - gaudi2_handle_qm_sei_err(hdev, event_type, &eq_entry->razwi_info, &event_mask); + error_count = gaudi2_handle_qm_sei_err(hdev, event_type, true, &event_mask); event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR; break; case GAUDI2_EVENT_ROTATOR0_AXI_ERROR_RESPONSE: case GAUDI2_EVENT_ROTATOR1_AXI_ERROR_RESPONSE: index = event_type - GAUDI2_EVENT_ROTATOR0_AXI_ERROR_RESPONSE; - gaudi2_handle_rot_err(hdev, index, &eq_entry->razwi_with_intr_cause, &event_mask); - gaudi2_handle_qm_sei_err(hdev, event_type, NULL, &event_mask); + error_count = gaudi2_handle_rot_err(hdev, index, event_type, + &eq_entry->razwi_with_intr_cause, &event_mask); + error_count += gaudi2_handle_qm_sei_err(hdev, event_type, false, &event_mask); event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR; break; case GAUDI2_EVENT_TPC0_AXI_ERR_RSP ... GAUDI2_EVENT_TPC24_AXI_ERR_RSP: index = event_type - GAUDI2_EVENT_TPC0_AXI_ERR_RSP; - gaudi2_tpc_ack_interrupts(hdev, index, "AXI_ERR_RSP", + error_count = gaudi2_tpc_ack_interrupts(hdev, index, event_type, &eq_entry->razwi_with_intr_cause, &event_mask); - gaudi2_handle_qm_sei_err(hdev, event_type, NULL, &event_mask); + error_count += gaudi2_handle_qm_sei_err(hdev, event_type, false, &event_mask); event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR; break; case GAUDI2_EVENT_DEC0_AXI_ERR_RSPONSE ... GAUDI2_EVENT_DEC9_AXI_ERR_RSPONSE: index = event_type - GAUDI2_EVENT_DEC0_AXI_ERR_RSPONSE; - gaudi2_handle_dec_err(hdev, index, "AXI_ERR_RESPONSE", &eq_entry->razwi_info, - &event_mask); + error_count = gaudi2_handle_dec_err(hdev, index, event_type, &event_mask); event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR; break; @@ -8856,8 +9091,8 @@ static void gaudi2_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_ent case GAUDI2_EVENT_TPC24_KERNEL_ERR: index = (event_type - GAUDI2_EVENT_TPC0_KERNEL_ERR) / (GAUDI2_EVENT_TPC1_KERNEL_ERR - GAUDI2_EVENT_TPC0_KERNEL_ERR); - gaudi2_tpc_ack_interrupts(hdev, index, "KRN_ERR", &eq_entry->razwi_with_intr_cause, - &event_mask); + error_count = gaudi2_tpc_ack_interrupts(hdev, index, event_type, + &eq_entry->razwi_with_intr_cause, &event_mask); event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR; break; @@ -8873,7 +9108,7 @@ static void gaudi2_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_ent case GAUDI2_EVENT_DEC9_SPI: index = (event_type - GAUDI2_EVENT_DEC0_SPI) / (GAUDI2_EVENT_DEC1_SPI - GAUDI2_EVENT_DEC0_SPI); - gaudi2_handle_dec_err(hdev, index, "SPI", &eq_entry->razwi_info, &event_mask); + error_count = gaudi2_handle_dec_err(hdev, index, event_type, &event_mask); event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR; break; @@ -8884,9 +9119,8 @@ static void gaudi2_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_ent index = (event_type - GAUDI2_EVENT_MME0_CTRL_AXI_ERROR_RESPONSE) / (GAUDI2_EVENT_MME1_CTRL_AXI_ERROR_RESPONSE - GAUDI2_EVENT_MME0_CTRL_AXI_ERROR_RESPONSE); - gaudi2_handle_mme_err(hdev, index, - "CTRL_AXI_ERROR_RESPONSE", &eq_entry->razwi_info, &event_mask); - gaudi2_handle_qm_sei_err(hdev, event_type, NULL, &event_mask); + error_count = gaudi2_handle_mme_err(hdev, index, event_type, &event_mask); + error_count += gaudi2_handle_qm_sei_err(hdev, event_type, false, &event_mask); event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR; break; @@ -8897,8 +9131,7 @@ static void gaudi2_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_ent index = (event_type - GAUDI2_EVENT_MME0_QMAN_SW_ERROR) / (GAUDI2_EVENT_MME1_QMAN_SW_ERROR - GAUDI2_EVENT_MME0_QMAN_SW_ERROR); - gaudi2_handle_mme_err(hdev, index, "QMAN_SW_ERROR", &eq_entry->razwi_info, - &event_mask); + error_count = gaudi2_handle_mme_err(hdev, index, event_type, &event_mask); event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR; break; @@ -8909,25 +9142,25 @@ static void gaudi2_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_ent index = (event_type - GAUDI2_EVENT_MME0_WAP_SOURCE_RESULT_INVALID) / (GAUDI2_EVENT_MME1_WAP_SOURCE_RESULT_INVALID - GAUDI2_EVENT_MME0_WAP_SOURCE_RESULT_INVALID); - gaudi2_handle_mme_wap_err(hdev, index, &eq_entry->razwi_info, &event_mask); + error_count = gaudi2_handle_mme_wap_err(hdev, index, event_type, &event_mask); event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR; break; case GAUDI2_EVENT_KDMA_CH0_AXI_ERR_RSP: case GAUDI2_EVENT_KDMA0_CORE: - gaudi2_handle_kdma_core_event(hdev, + error_count = gaudi2_handle_kdma_core_event(hdev, event_type, le64_to_cpu(eq_entry->intr_cause.intr_cause_data)); event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR; break; case GAUDI2_EVENT_HDMA2_CORE ... GAUDI2_EVENT_PDMA1_CORE: - gaudi2_handle_dma_core_event(hdev, + error_count = gaudi2_handle_dma_core_event(hdev, event_type, le64_to_cpu(eq_entry->intr_cause.intr_cause_data)); event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR; break; case GAUDI2_EVENT_PCIE_ADDR_DEC_ERR: - gaudi2_print_pcie_addr_dec_info(hdev, + error_count = gaudi2_print_pcie_addr_dec_info(hdev, event_type, le64_to_cpu(eq_entry->intr_cause.intr_cause_data), &event_mask); reset_flags |= HL_DRV_RESET_FW_FATAL_ERR; event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR; @@ -8937,27 +9170,27 @@ static void gaudi2_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_ent case GAUDI2_EVENT_HMMU_0_AXI_ERR_RSP ... GAUDI2_EVENT_HMMU_12_AXI_ERR_RSP: case GAUDI2_EVENT_PMMU0_PAGE_FAULT_WR_PERM ... GAUDI2_EVENT_PMMU0_SECURITY_ERROR: case GAUDI2_EVENT_PMMU_AXI_ERR_RSP_0: - gaudi2_handle_mmu_spi_sei_err(hdev, event_type, &event_mask); + error_count = gaudi2_handle_mmu_spi_sei_err(hdev, event_type, &event_mask); reset_flags |= HL_DRV_RESET_FW_FATAL_ERR; event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR; break; case GAUDI2_EVENT_HIF0_FATAL ... GAUDI2_EVENT_HIF12_FATAL: - gaudi2_handle_hif_fatal(hdev, event_type, + error_count = gaudi2_handle_hif_fatal(hdev, event_type, le64_to_cpu(eq_entry->intr_cause.intr_cause_data)); reset_flags |= HL_DRV_RESET_FW_FATAL_ERR; event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR; break; case GAUDI2_EVENT_PMMU_FATAL_0: - gaudi2_handle_pif_fatal(hdev, + error_count = gaudi2_handle_pif_fatal(hdev, event_type, le64_to_cpu(eq_entry->intr_cause.intr_cause_data)); reset_flags |= HL_DRV_RESET_FW_FATAL_ERR; event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR; break; case GAUDI2_EVENT_PSOC63_RAZWI_OR_PID_MIN_MAX_INTERRUPT: - gaudi2_ack_psoc_razwi_event_handler(hdev, &event_mask); + error_count = gaudi2_ack_psoc_razwi_event_handler(hdev, &event_mask); event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR; break; @@ -8967,33 +9200,39 @@ static void gaudi2_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_ent reset_flags |= HL_DRV_RESET_FW_FATAL_ERR; reset_required = true; } + error_count++; break; case GAUDI2_EVENT_HBM_CATTRIP_0 ... GAUDI2_EVENT_HBM_CATTRIP_5: - gaudi2_handle_hbm_cattrip(hdev, le64_to_cpu(eq_entry->intr_cause.intr_cause_data)); + error_count = gaudi2_handle_hbm_cattrip(hdev, event_type, + le64_to_cpu(eq_entry->intr_cause.intr_cause_data)); event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR; break; case GAUDI2_EVENT_HBM0_MC0_SPI ... GAUDI2_EVENT_HBM5_MC1_SPI: - gaudi2_handle_hbm_mc_spi(hdev, le64_to_cpu(eq_entry->intr_cause.intr_cause_data)); + error_count = gaudi2_handle_hbm_mc_spi(hdev, + le64_to_cpu(eq_entry->intr_cause.intr_cause_data)); event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR; break; case GAUDI2_EVENT_PCIE_DRAIN_COMPLETE: - gaudi2_handle_pcie_drain(hdev, &eq_entry->pcie_drain_ind_data); + error_count = gaudi2_handle_pcie_drain(hdev, &eq_entry->pcie_drain_ind_data); event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR; break; case GAUDI2_EVENT_PSOC59_RPM_ERROR_OR_DRAIN: - gaudi2_handle_psoc_drain(hdev, le64_to_cpu(eq_entry->intr_cause.intr_cause_data)); + error_count = gaudi2_handle_psoc_drain(hdev, + le64_to_cpu(eq_entry->intr_cause.intr_cause_data)); event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR; break; case GAUDI2_EVENT_CPU_AXI_ECC: + error_count = GAUDI2_NA_EVENT_CAUSE; reset_flags |= HL_DRV_RESET_FW_FATAL_ERR; event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR; break; case GAUDI2_EVENT_CPU_L2_RAM_ECC: + error_count = GAUDI2_NA_EVENT_CAUSE; reset_flags |= HL_DRV_RESET_FW_FATAL_ERR; event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR; break; @@ -9001,31 +9240,30 @@ static void gaudi2_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_ent case GAUDI2_EVENT_MME1_SBTE0_AXI_ERR_RSP ... GAUDI2_EVENT_MME1_SBTE4_AXI_ERR_RSP: case GAUDI2_EVENT_MME2_SBTE0_AXI_ERR_RSP ... GAUDI2_EVENT_MME2_SBTE4_AXI_ERR_RSP: case GAUDI2_EVENT_MME3_SBTE0_AXI_ERR_RSP ... GAUDI2_EVENT_MME3_SBTE4_AXI_ERR_RSP: - index = (event_type - GAUDI2_EVENT_MME0_SBTE0_AXI_ERR_RSP) / - (GAUDI2_EVENT_MME1_SBTE0_AXI_ERR_RSP - - GAUDI2_EVENT_MME0_SBTE0_AXI_ERR_RSP); - sbte_index = (event_type - GAUDI2_EVENT_MME0_SBTE0_AXI_ERR_RSP) % - (GAUDI2_EVENT_MME1_SBTE0_AXI_ERR_RSP - - GAUDI2_EVENT_MME0_SBTE0_AXI_ERR_RSP); - gaudi2_handle_mme_sbte_err(hdev, index, sbte_index, + error_count = gaudi2_handle_mme_sbte_err(hdev, event_type, le64_to_cpu(eq_entry->intr_cause.intr_cause_data)); event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR; break; case GAUDI2_EVENT_VM0_ALARM_A ... GAUDI2_EVENT_VM3_ALARM_B: + error_count = GAUDI2_NA_EVENT_CAUSE; reset_flags |= HL_DRV_RESET_FW_FATAL_ERR; event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR; break; case GAUDI2_EVENT_PSOC_AXI_ERR_RSP: + error_count = GAUDI2_NA_EVENT_CAUSE; event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR; break; case GAUDI2_EVENT_PSOC_PRSTN_FALL: + error_count = GAUDI2_NA_EVENT_CAUSE; event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR; break; case GAUDI2_EVENT_PCIE_APB_TIMEOUT: + error_count = GAUDI2_NA_EVENT_CAUSE; reset_flags |= HL_DRV_RESET_FW_FATAL_ERR; event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR; break; case GAUDI2_EVENT_PCIE_FATAL_ERR: + error_count = GAUDI2_NA_EVENT_CAUSE; event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR; break; case GAUDI2_EVENT_TPC0_BMON_SPMU: @@ -9078,6 +9316,7 @@ static void gaudi2_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_ent case GAUDI2_EVENT_DEC8_BMON_SPMU: case GAUDI2_EVENT_DEC9_BMON_SPMU: case GAUDI2_EVENT_ROTATOR0_BMON_SPMU ... GAUDI2_EVENT_SM3_BMON_SPMU: + error_count = GAUDI2_NA_EVENT_CAUSE; event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR; break; @@ -9085,67 +9324,87 @@ static void gaudi2_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_ent case GAUDI2_EVENT_CPU_FIX_POWER_ENV_E: case GAUDI2_EVENT_CPU_FIX_THERMAL_ENV_S: case GAUDI2_EVENT_CPU_FIX_THERMAL_ENV_E: - gaudi2_print_clk_change_info(hdev, event_type); - event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR; + gaudi2_print_clk_change_info(hdev, event_type, &event_mask); + error_count = GAUDI2_NA_EVENT_CAUSE; break; case GAUDI2_EVENT_CPU_PKT_QUEUE_OUT_SYNC: - gaudi2_print_out_of_sync_info(hdev, &eq_entry->pkt_sync_err); + gaudi2_print_out_of_sync_info(hdev, event_type, &eq_entry->pkt_sync_err); + error_count = GAUDI2_NA_EVENT_CAUSE; event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR; break; case GAUDI2_EVENT_PCIE_FLR_REQUESTED: event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR; + error_count = GAUDI2_NA_EVENT_CAUSE; /* Do nothing- FW will handle it */ break; case GAUDI2_EVENT_PCIE_P2P_MSIX: - gaudi2_handle_pcie_p2p_msix(hdev); + error_count = gaudi2_handle_pcie_p2p_msix(hdev, event_type); event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR; break; case GAUDI2_EVENT_SM0_AXI_ERROR_RESPONSE ... GAUDI2_EVENT_SM3_AXI_ERROR_RESPONSE: index = event_type - GAUDI2_EVENT_SM0_AXI_ERROR_RESPONSE; - gaudi2_handle_sm_err(hdev, index); + error_count = gaudi2_handle_sm_err(hdev, event_type, index); event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR; break; case GAUDI2_EVENT_PSOC_MME_PLL_LOCK_ERR ... GAUDI2_EVENT_DCORE2_HBM_PLL_LOCK_ERR: + error_count = GAUDI2_NA_EVENT_CAUSE; event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR; break; case GAUDI2_EVENT_CPU_CPLD_SHUTDOWN_CAUSE: dev_info(hdev->dev, "CPLD shutdown cause, reset reason: 0x%llx\n", le64_to_cpu(eq_entry->data[0])); + error_count = GAUDI2_NA_EVENT_CAUSE; event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR; break; case GAUDI2_EVENT_CPU_CPLD_SHUTDOWN_EVENT: dev_err(hdev->dev, "CPLD shutdown event, reset reason: 0x%llx\n", le64_to_cpu(eq_entry->data[0])); + error_count = GAUDI2_NA_EVENT_CAUSE; event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR; break; case GAUDI2_EVENT_CPU_PKT_SANITY_FAILED: - gaudi2_print_cpu_pkt_failure_info(hdev, &eq_entry->pkt_sync_err); + gaudi2_print_cpu_pkt_failure_info(hdev, event_type, &eq_entry->pkt_sync_err); + error_count = GAUDI2_NA_EVENT_CAUSE; event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR; break; case GAUDI2_EVENT_ARC_DCCM_FULL: - hl_arc_event_handle(hdev, &eq_entry->arc_data); + error_count = hl_arc_event_handle(hdev, event_type, &eq_entry->arc_data); event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR; break; case GAUDI2_EVENT_CPU_FP32_NOT_SUPPORTED: + case GAUDI2_EVENT_DEV_RESET_REQ: event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR; + error_count = GAUDI2_NA_EVENT_CAUSE; is_critical = true; break; default: - if (gaudi2_irq_map_table[event_type].valid) + if (gaudi2_irq_map_table[event_type].valid) { dev_err_ratelimited(hdev->dev, "Cannot find handler for event %d\n", event_type); + error_count = GAUDI2_NA_EVENT_CAUSE; + } } + /* Make sure to dump an error in case no error cause was printed so far. + * Note that although we have counted the errors, we use this number as + * a boolean. + */ + if (error_count == GAUDI2_NA_EVENT_CAUSE && !is_info_event(event_type)) + gaudi2_print_event(hdev, event_type, true, "%d", event_type); + else if (error_count == 0) + gaudi2_print_event(hdev, event_type, true, + "No error cause for H/W event %u\n", event_type); + if ((gaudi2_irq_map_table[event_type].reset || reset_required) && (hdev->hard_reset_on_fw_events || (hdev->asic_prop.fw_security_enabled && is_critical))) @@ -10466,6 +10725,8 @@ static const struct hl_asic_funcs gaudi2_funcs = { .set_dram_bar_base = gaudi2_set_hbm_bar_base, .set_engine_cores = gaudi2_set_engine_cores, .send_device_activity = gaudi2_send_device_activity, + .set_dram_properties = gaudi2_set_dram_properties, + .set_binning_masks = gaudi2_set_binning_masks, }; void gaudi2_set_asic_funcs(struct hl_device *hdev) diff --git a/drivers/misc/habanalabs/gaudi2/gaudi2P.h b/drivers/accel/habanalabs/gaudi2/gaudi2P.h index b4383c199bbb..2687404d9d21 100644 --- a/drivers/misc/habanalabs/gaudi2/gaudi2P.h +++ b/drivers/accel/habanalabs/gaudi2/gaudi2P.h @@ -8,7 +8,7 @@ #ifndef GAUDI2P_H_ #define GAUDI2P_H_ -#include <uapi/misc/habanalabs.h> +#include <uapi/drm/habanalabs_accel.h> #include "../common/habanalabs.h" #include "../include/common/hl_boot_if.h" #include "../include/gaudi2/gaudi2.h" @@ -240,6 +240,8 @@ #define GAUDI2_SOB_INCREMENT_BY_ONE (FIELD_PREP(DCORE0_SYNC_MNGR_OBJS_SOB_OBJ_VAL_MASK, 1) | \ FIELD_PREP(DCORE0_SYNC_MNGR_OBJS_SOB_OBJ_INC_MASK, 1)) +#define GAUDI2_NUM_OF_GLBL_ERR_CAUSE 8 + enum gaudi2_reserved_sob_id { GAUDI2_RESERVED_SOB_CS_COMPLETION_FIRST, GAUDI2_RESERVED_SOB_CS_COMPLETION_LAST = @@ -532,6 +534,41 @@ struct gaudi2_device { u32 num_of_valid_hw_events; }; +/* + * Types of the Gaudi2 IP blocks, used by special blocks iterator. + * Required for scenarios where only particular block types can be + * addressed (e.g., special PLDM images). + */ +enum gaudi2_block_types { + GAUDI2_BLOCK_TYPE_PLL, + GAUDI2_BLOCK_TYPE_RTR, + GAUDI2_BLOCK_TYPE_CPU, + GAUDI2_BLOCK_TYPE_HIF, + GAUDI2_BLOCK_TYPE_HBM, + GAUDI2_BLOCK_TYPE_NIC, + GAUDI2_BLOCK_TYPE_PCIE, + GAUDI2_BLOCK_TYPE_PCIE_PMA, + GAUDI2_BLOCK_TYPE_PDMA, + GAUDI2_BLOCK_TYPE_EDMA, + GAUDI2_BLOCK_TYPE_PMMU, + GAUDI2_BLOCK_TYPE_PSOC, + GAUDI2_BLOCK_TYPE_ROT, + GAUDI2_BLOCK_TYPE_ARC_FARM, + GAUDI2_BLOCK_TYPE_DEC, + GAUDI2_BLOCK_TYPE_MME, + GAUDI2_BLOCK_TYPE_EU_BIST, + GAUDI2_BLOCK_TYPE_SYNC_MNGR, + GAUDI2_BLOCK_TYPE_STLB, + GAUDI2_BLOCK_TYPE_TPC, + GAUDI2_BLOCK_TYPE_HMMU, + GAUDI2_BLOCK_TYPE_SRAM, + GAUDI2_BLOCK_TYPE_XBAR, + GAUDI2_BLOCK_TYPE_KDMA, + GAUDI2_BLOCK_TYPE_XDMA, + GAUDI2_BLOCK_TYPE_XFT, + GAUDI2_BLOCK_TYPE_MAX +}; + extern const u32 gaudi2_dma_core_blocks_bases[DMA_CORE_ID_SIZE]; extern const u32 gaudi2_qm_blocks_bases[GAUDI2_QUEUE_ID_SIZE]; extern const u32 gaudi2_mme_acc_blocks_bases[MME_ID_SIZE]; diff --git a/drivers/misc/habanalabs/gaudi2/gaudi2_coresight.c b/drivers/accel/habanalabs/gaudi2/gaudi2_coresight.c index 56c6ab692482..1dfbe293ecec 100644 --- a/drivers/misc/habanalabs/gaudi2/gaudi2_coresight.c +++ b/drivers/accel/habanalabs/gaudi2/gaudi2_coresight.c @@ -5,7 +5,7 @@ * All Rights Reserved. */ #include "gaudi2_coresight_regs.h" -#include <uapi/misc/habanalabs.h> +#include <uapi/drm/habanalabs_accel.h> #define GAUDI2_PLDM_CORESIGHT_TIMEOUT_USEC (CORESIGHT_TIMEOUT_USEC * 2000) #define SPMU_MAX_COUNTERS 6 @@ -2376,10 +2376,10 @@ static int gaudi2_config_bmon(struct hl_device *hdev, struct hl_debug_params *pa WREG32(base_reg + mmBMON_ADDRH_S2_OFFSET, upper_32_bits(input->start_addr2)); WREG32(base_reg + mmBMON_ADDRL_E2_OFFSET, lower_32_bits(input->end_addr2)); WREG32(base_reg + mmBMON_ADDRH_E2_OFFSET, upper_32_bits(input->end_addr2)); - WREG32(base_reg + mmBMON_ADDRL_S3_OFFSET, lower_32_bits(input->start_addr2)); - WREG32(base_reg + mmBMON_ADDRH_S3_OFFSET, upper_32_bits(input->start_addr2)); - WREG32(base_reg + mmBMON_ADDRL_E3_OFFSET, lower_32_bits(input->end_addr2)); - WREG32(base_reg + mmBMON_ADDRH_E3_OFFSET, upper_32_bits(input->end_addr2)); + WREG32(base_reg + mmBMON_ADDRL_S3_OFFSET, lower_32_bits(input->start_addr3)); + WREG32(base_reg + mmBMON_ADDRH_S3_OFFSET, upper_32_bits(input->start_addr3)); + WREG32(base_reg + mmBMON_ADDRL_E3_OFFSET, lower_32_bits(input->end_addr3)); + WREG32(base_reg + mmBMON_ADDRH_E3_OFFSET, upper_32_bits(input->end_addr3)); WREG32(base_reg + mmBMON_IDL_OFFSET, 0x0); WREG32(base_reg + mmBMON_IDH_OFFSET, 0x0); diff --git a/drivers/misc/habanalabs/gaudi2/gaudi2_coresight_regs.h b/drivers/accel/habanalabs/gaudi2/gaudi2_coresight_regs.h index df8729286e06..df8729286e06 100644 --- a/drivers/misc/habanalabs/gaudi2/gaudi2_coresight_regs.h +++ b/drivers/accel/habanalabs/gaudi2/gaudi2_coresight_regs.h diff --git a/drivers/misc/habanalabs/gaudi2/gaudi2_masks.h b/drivers/accel/habanalabs/gaudi2/gaudi2_masks.h index e9ac87828221..e9ac87828221 100644 --- a/drivers/misc/habanalabs/gaudi2/gaudi2_masks.h +++ b/drivers/accel/habanalabs/gaudi2/gaudi2_masks.h diff --git a/drivers/misc/habanalabs/gaudi2/gaudi2_security.c b/drivers/accel/habanalabs/gaudi2/gaudi2_security.c index 768c2f3dc900..a212f82e6604 100644 --- a/drivers/misc/habanalabs/gaudi2/gaudi2_security.c +++ b/drivers/accel/habanalabs/gaudi2/gaudi2_security.c @@ -1561,6 +1561,7 @@ static const u32 gaudi2_pb_dcr0_tpc0_unsecured_regs[] = { mmDCORE0_TPC0_CFG_LUT_FUNC128_BASE_ADDR_HI, mmDCORE0_TPC0_CFG_LUT_FUNC256_BASE_ADDR_LO, mmDCORE0_TPC0_CFG_LUT_FUNC256_BASE_ADDR_HI, + mmDCORE0_TPC0_CFG_KERNEL_KERNEL_CONFIG, mmDCORE0_TPC0_CFG_KERNEL_SRF_0, mmDCORE0_TPC0_CFG_KERNEL_SRF_1, mmDCORE0_TPC0_CFG_KERNEL_SRF_2, @@ -1666,6 +1667,10 @@ static const u32 gaudi2_pb_dcr0_sm_glbl[] = { mmDCORE0_SYNC_MNGR_GLBL_BASE, }; +static const u32 gaudi2_pb_dcr1_sm_glbl[] = { + mmDCORE1_SYNC_MNGR_GLBL_BASE, +}; + static const struct range gaudi2_pb_dcr0_sm_glbl_unsecured_regs[] = { {mmDCORE0_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_1, mmDCORE0_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_63}, {mmDCORE0_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_1, mmDCORE0_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_63}, @@ -1678,14 +1683,14 @@ static const struct range gaudi2_pb_dcr0_sm_glbl_unsecured_regs[] = { }; static const struct range gaudi2_pb_dcr_x_sm_glbl_unsecured_regs[] = { - {mmDCORE0_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_0, mmDCORE0_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_63}, - {mmDCORE0_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_0, mmDCORE0_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_63}, - {mmDCORE0_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_0, mmDCORE0_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_63}, - {mmDCORE0_SYNC_MNGR_GLBL_CQ_PI_0, mmDCORE0_SYNC_MNGR_GLBL_CQ_PI_63}, - {mmDCORE0_SYNC_MNGR_GLBL_LBW_ADDR_L_0, mmDCORE0_SYNC_MNGR_GLBL_LBW_ADDR_L_63}, - {mmDCORE0_SYNC_MNGR_GLBL_LBW_ADDR_H_0, mmDCORE0_SYNC_MNGR_GLBL_LBW_ADDR_H_63}, - {mmDCORE0_SYNC_MNGR_GLBL_LBW_DATA_0, mmDCORE0_SYNC_MNGR_GLBL_LBW_DATA_63}, - {mmDCORE0_SYNC_MNGR_GLBL_CQ_INC_MODE_0, mmDCORE0_SYNC_MNGR_GLBL_CQ_INC_MODE_63}, + {mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_0, mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_63}, + {mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_0, mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_63}, + {mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_0, mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_63}, + {mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_0, mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_63}, + {mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_0, mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_63}, + {mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_0, mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_63}, + {mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_0, mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_63}, + {mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_0, mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_63}, }; static const u32 gaudi2_pb_arc_sched[] = { @@ -3358,14 +3363,6 @@ static int gaudi2_init_protection_bits(struct hl_device *hdev) /* Sync Manager GLBL */ - /* Unsecure all CQ registers */ - rc |= hl_init_pb_ranges(hdev, NUM_OF_DCORES, DCORE_OFFSET, - HL_PB_SINGLE_INSTANCE, HL_PB_NA, - gaudi2_pb_dcr0_sm_glbl, - ARRAY_SIZE(gaudi2_pb_dcr0_sm_glbl), - gaudi2_pb_dcr_x_sm_glbl_unsecured_regs, - ARRAY_SIZE(gaudi2_pb_dcr_x_sm_glbl_unsecured_regs)); - /* Secure Dcore0 CQ0 registers */ rc |= hl_init_pb_ranges(hdev, HL_PB_SHARED, HL_PB_NA, HL_PB_SINGLE_INSTANCE, HL_PB_NA, @@ -3374,6 +3371,14 @@ static int gaudi2_init_protection_bits(struct hl_device *hdev) gaudi2_pb_dcr0_sm_glbl_unsecured_regs, ARRAY_SIZE(gaudi2_pb_dcr0_sm_glbl_unsecured_regs)); + /* Unsecure all other CQ registers */ + rc |= hl_init_pb_ranges(hdev, NUM_OF_DCORES - 1, DCORE_OFFSET, + HL_PB_SINGLE_INSTANCE, HL_PB_NA, + gaudi2_pb_dcr1_sm_glbl, + ARRAY_SIZE(gaudi2_pb_dcr1_sm_glbl), + gaudi2_pb_dcr_x_sm_glbl_unsecured_regs, + ARRAY_SIZE(gaudi2_pb_dcr_x_sm_glbl_unsecured_regs)); + /* PSOC. * Except for PSOC_GLOBAL_CONF, skip when security is enabled in F/W, because the blocks are * protected by privileged RR. diff --git a/drivers/misc/habanalabs/goya/Makefile b/drivers/accel/habanalabs/goya/Makefile index b3f3b7b96683..b3f3b7b96683 100644 --- a/drivers/misc/habanalabs/goya/Makefile +++ b/drivers/accel/habanalabs/goya/Makefile diff --git a/drivers/misc/habanalabs/goya/goya.c b/drivers/accel/habanalabs/goya/goya.c index 0f083fcf81a6..2b135e856607 100644 --- a/drivers/misc/habanalabs/goya/goya.c +++ b/drivers/accel/habanalabs/goya/goya.c @@ -5420,6 +5420,16 @@ static int goya_scrub_device_dram(struct hl_device *hdev, u64 val) return -EOPNOTSUPP; } +static int goya_set_dram_properties(struct hl_device *hdev) +{ + return 0; +} + +static int goya_set_binning_masks(struct hl_device *hdev) +{ + return 0; +} + static int goya_send_device_activity(struct hl_device *hdev, bool open) { return 0; @@ -5518,6 +5528,8 @@ static const struct hl_asic_funcs goya_funcs = { .access_dev_mem = hl_access_dev_mem, .set_dram_bar_base = goya_set_ddr_bar_base, .send_device_activity = goya_send_device_activity, + .set_dram_properties = goya_set_dram_properties, + .set_binning_masks = goya_set_binning_masks, }; /* diff --git a/drivers/misc/habanalabs/goya/goyaP.h b/drivers/accel/habanalabs/goya/goyaP.h index d6ec43d6f6b0..5df3d30b91fd 100644 --- a/drivers/misc/habanalabs/goya/goyaP.h +++ b/drivers/accel/habanalabs/goya/goyaP.h @@ -8,7 +8,7 @@ #ifndef GOYAP_H_ #define GOYAP_H_ -#include <uapi/misc/habanalabs.h> +#include <uapi/drm/habanalabs_accel.h> #include "../common/habanalabs.h" #include "../include/common/hl_boot_if.h" #include "../include/goya/goya_packets.h" diff --git a/drivers/misc/habanalabs/goya/goya_coresight.c b/drivers/accel/habanalabs/goya/goya_coresight.c index 2c5133cfae65..e7ac3046cfaa 100644 --- a/drivers/misc/habanalabs/goya/goya_coresight.c +++ b/drivers/accel/habanalabs/goya/goya_coresight.c @@ -10,7 +10,7 @@ #include "../include/goya/asic_reg/goya_regs.h" #include "../include/goya/asic_reg/goya_masks.h" -#include <uapi/misc/habanalabs.h> +#include <uapi/drm/habanalabs_accel.h> #define GOYA_PLDM_CORESIGHT_TIMEOUT_USEC (CORESIGHT_TIMEOUT_USEC * 100) diff --git a/drivers/misc/habanalabs/goya/goya_hwmgr.c b/drivers/accel/habanalabs/goya/goya_hwmgr.c index b595721751c1..b595721751c1 100644 --- a/drivers/misc/habanalabs/goya/goya_hwmgr.c +++ b/drivers/accel/habanalabs/goya/goya_hwmgr.c diff --git a/drivers/misc/habanalabs/goya/goya_security.c b/drivers/accel/habanalabs/goya/goya_security.c index 14c3bae3ccdc..14c3bae3ccdc 100644 --- a/drivers/misc/habanalabs/goya/goya_security.c +++ b/drivers/accel/habanalabs/goya/goya_security.c diff --git a/drivers/misc/habanalabs/include/common/cpucp_if.h b/drivers/accel/habanalabs/include/common/cpucp_if.h index baa5aa43b6f4..d713252a4f13 100644 --- a/drivers/misc/habanalabs/include/common/cpucp_if.h +++ b/drivers/accel/habanalabs/include/common/cpucp_if.h @@ -344,6 +344,16 @@ struct hl_eq_engine_arc_intr_data { __le64 pad[5]; }; +#define ADDR_DEC_ADDRESS_COUNT_MAX 4 + +/* Data structure specifies details of ADDR_DEC interrupt */ +struct hl_eq_addr_dec_intr_data { + struct hl_eq_intr_cause intr_cause; + __le64 addr[ADDR_DEC_ADDRESS_COUNT_MAX]; + __u8 addr_cnt; + __u8 pad[7]; +}; + struct hl_eq_entry { struct hl_eq_header hdr; union { @@ -358,6 +368,7 @@ struct hl_eq_entry { struct hl_eq_razwi_with_intr_cause razwi_with_intr_cause; struct hl_eq_hbm_sei_data sei_data; /* Gaudi2 HBM */ struct hl_eq_engine_arc_intr_data arc_data; + struct hl_eq_addr_dec_intr_data addr_dec; __le64 data[7]; }; }; @@ -643,6 +654,10 @@ enum pq_init_status { * data corruption in case of mismatched driver/FW versions. * Relevant only to Gaudi. * + * CPUCP_PACKET_GENERIC_PASSTHROUGH - + * Generic opcode for all firmware info that is only passed to host + * through the LKD, without getting parsed there. + * * CPUCP_PACKET_ACTIVE_STATUS_SET - * LKD sends FW indication whether device is free or in use, this indication is reported * also to the BMC. @@ -704,9 +719,12 @@ enum cpucp_packet_id { CPUCP_PACKET_RESERVED5, /* not used */ CPUCP_PACKET_RESERVED6, /* not used */ CPUCP_PACKET_RESERVED7, /* not used */ + CPUCP_PACKET_GENERIC_PASSTHROUGH, /* IOCTL */ CPUCP_PACKET_RESERVED8, /* not used */ - CPUCP_PACKET_RESERVED9, /* not used */ CPUCP_PACKET_ACTIVE_STATUS_SET, /* internal */ + CPUCP_PACKET_RESERVED9, /* not used */ + CPUCP_PACKET_RESERVED10, /* not used */ + CPUCP_PACKET_RESERVED11, /* not used */ CPUCP_PACKET_ID_MAX /* must be last */ }; @@ -727,6 +745,11 @@ enum cpucp_packet_id { #define CPUCP_PKT_RES_PLL_OUT3_SHIFT 48 #define CPUCP_PKT_RES_PLL_OUT3_MASK 0xFFFF000000000000ull +#define CPUCP_PKT_RES_EEPROM_OUT0_SHIFT 0 +#define CPUCP_PKT_RES_EEPROM_OUT0_MASK 0x000000000000FFFFull +#define CPUCP_PKT_RES_EEPROM_OUT1_SHIFT 16 +#define CPUCP_PKT_RES_EEPROM_OUT1_MASK 0x0000000000FF0000ull + #define CPUCP_PKT_VAL_PFC_IN1_SHIFT 0 #define CPUCP_PKT_VAL_PFC_IN1_MASK 0x0000000000000001ull #define CPUCP_PKT_VAL_PFC_IN2_SHIFT 1 @@ -805,8 +828,13 @@ struct cpucp_packet { __le32 nonce; }; - /* For NIC requests */ - __le32 port_index; + union { + /* For NIC requests */ + __le32 port_index; + + /* For Generic packet sub index */ + __le32 pkt_subidx; + }; }; struct cpucp_unmask_irq_arr_packet { @@ -881,7 +909,9 @@ enum cpucp_in_attributes { cpucp_in_max, cpucp_in_lowest = 6, cpucp_in_highest = 7, - cpucp_in_reset_history + cpucp_in_reset_history, + cpucp_in_intr_alarm_a, + cpucp_in_intr_alarm_b, }; enum cpucp_curr_attributes { @@ -976,6 +1006,11 @@ enum pll_index { IC_PLL = 16, MC_PLL = 17, EMMC_PLL = 18, + D2D_PLL = 19, + CS_PLL = 20, + C2C_PLL = 21, + NCH_PLL = 22, + C2M_PLL = 23, PLL_MAX }; @@ -1135,8 +1170,9 @@ enum cpucp_serdes_type { HLS1_SERDES_TYPE, HLS1H_SERDES_TYPE, HLS2_SERDES_TYPE, - UNKNOWN_SERDES_TYPE, - MAX_NUM_SERDES_TYPE = UNKNOWN_SERDES_TYPE + HLS2_TYPE_1_SERDES_TYPE, + MAX_NUM_SERDES_TYPE, /* number of types */ + UNKNOWN_SERDES_TYPE = 0xFFFF /* serdes_type is u16 */ }; struct cpucp_nic_info { @@ -1161,6 +1197,21 @@ struct page_discard_info { }; /* + * struct frac_val - fracture value represented by "integer.frac". + * @integer: the integer part of the fracture value; + * @frac: the fracture part of the fracture value. + */ +struct frac_val { + union { + struct { + __le16 integer; + __le16 frac; + }; + __le32 val; + }; +}; + +/* * struct ser_val - the SER (symbol error rate) value is represented by "integer * 10 ^ -exp". * @integer: the integer part of the SER value; * @exp: the exponent part of the SER value. @@ -1183,8 +1234,12 @@ struct ser_val { * @pcs_link: has PCS link. * @phy_ready: is PHY ready. * @auto_neg: is Autoneg enabled. - * @timeout_retransmission_cnt: timeout retransmission events - * @high_ber_cnt: high ber events + * @timeout_retransmission_cnt: timeout retransmission events. + * @high_ber_cnt: high ber events. + * @pre_fec_ser: pre FEC SER value. + * @post_fec_ser: post FEC SER value. + * @throughput: measured throughput. + * @latency: measured latency. */ struct cpucp_nic_status { __le32 port; @@ -1200,6 +1255,10 @@ struct cpucp_nic_status { __u8 auto_neg; __le32 timeout_retransmission_cnt; __le32 high_ber_cnt; + struct ser_val pre_fec_ser; + struct ser_val post_fec_ser; + struct frac_val bandwidth; + struct frac_val lat; }; enum cpucp_hbm_row_replace_cause { @@ -1292,6 +1351,7 @@ struct cpucp_dev_info_signed { __u8 certificate[SEC_CERTIFICATE_BUF_SZ]; }; +#define DCORE_MON_REGS_SZ 512 /* * struct dcore_monitor_regs_data - DCORE monitor regs data. * the structure follows sync manager block layout. relevant only to Gaudi. @@ -1302,11 +1362,11 @@ struct cpucp_dev_info_signed { * @mon_status: array of monitor status. */ struct dcore_monitor_regs_data { - __le32 mon_pay_addrl[512]; - __le32 mon_pay_addrh[512]; - __le32 mon_pay_data[512]; - __le32 mon_arm[512]; - __le32 mon_status[512]; + __le32 mon_pay_addrl[DCORE_MON_REGS_SZ]; + __le32 mon_pay_addrh[DCORE_MON_REGS_SZ]; + __le32 mon_pay_data[DCORE_MON_REGS_SZ]; + __le32 mon_arm[DCORE_MON_REGS_SZ]; + __le32 mon_status[DCORE_MON_REGS_SZ]; }; /* contains SM data for each SYNC_MNGR (relevant only to Gaudi) */ @@ -1317,4 +1377,14 @@ struct cpucp_monitor_dump { struct dcore_monitor_regs_data sync_mngr_e_n; }; +/* + * The Type of the generic request (and other input arguments) will be fetched from user by reading + * from "pkt_subidx" field in struct cpucp_packet. + * + * HL_PASSTHROUGHT_VERSIONS - Fetch all firmware versions. + */ +enum hl_passthrough_type { + HL_PASSTHROUGH_VERSIONS, +}; + #endif /* CPUCP_IF_H */ diff --git a/drivers/misc/habanalabs/include/common/hl_boot_if.h b/drivers/accel/habanalabs/include/common/hl_boot_if.h index e0ea51cc7475..2256add057c5 100644 --- a/drivers/misc/habanalabs/include/common/hl_boot_if.h +++ b/drivers/accel/habanalabs/include/common/hl_boot_if.h @@ -41,6 +41,19 @@ enum cpu_boot_err { }; /* + * Mask for fatal failures + * This mask contains all possible fatal failures, and a dynamic code + * will clear the non-relevant ones. + */ +#define CPU_BOOT_ERR_FATAL_MASK \ + ((1 << CPU_BOOT_ERR_DRAM_INIT_FAIL) | \ + (1 << CPU_BOOT_ERR_PLL_FAIL) | \ + (1 << CPU_BOOT_ERR_DEVICE_UNUSABLE_FAIL) | \ + (1 << CPU_BOOT_ERR_BINNING_FAIL) | \ + (1 << CPU_BOOT_ERR_DRAM_SKIPPED) | \ + (1 << CPU_BOOT_ERR_EEPROM_FAIL)) + +/* * CPU error bits in BOOT_ERROR registers * * CPU_BOOT_ERR0_DRAM_INIT_FAIL DRAM initialization failed. @@ -439,7 +452,7 @@ struct cpu_dyn_regs { /* TODO: remove the desc magic after the code is updated to use message */ /* HCDM - Habana Communications Descriptor Magic */ #define HL_COMMS_DESC_MAGIC 0x4843444D -#define HL_COMMS_DESC_VER 1 +#define HL_COMMS_DESC_VER 3 /* HCMv - Habana Communications Message + header version */ #define HL_COMMS_MSG_MAGIC_VALUE 0x48434D00 @@ -450,8 +463,10 @@ struct cpu_dyn_regs { ((ver) & HL_COMMS_MSG_MAGIC_VER_MASK)) #define HL_COMMS_MSG_MAGIC_V0 HL_COMMS_DESC_MAGIC #define HL_COMMS_MSG_MAGIC_V1 HL_COMMS_MSG_MAGIC_VER(1) +#define HL_COMMS_MSG_MAGIC_V2 HL_COMMS_MSG_MAGIC_VER(2) +#define HL_COMMS_MSG_MAGIC_V3 HL_COMMS_MSG_MAGIC_VER(3) -#define HL_COMMS_MSG_MAGIC HL_COMMS_MSG_MAGIC_V1 +#define HL_COMMS_MSG_MAGIC HL_COMMS_MSG_MAGIC_V3 #define HL_COMMS_MSG_MAGIC_VALIDATE_MAGIC(magic) \ (((magic) & HL_COMMS_MSG_MAGIC_MASK) == \ @@ -474,22 +489,31 @@ enum comms_msg_type { /* * Binning information shared between LKD and FW - * @tpc_mask - TPC binning information + * @tpc_mask_l - TPC binning information lower 64 bit * @dec_mask - Decoder binning information - * @hbm_mask - HBM binning information + * @dram_mask - DRAM binning information * @edma_mask - EDMA binning information * @mme_mask_l - MME binning information lower 32 * @mme_mask_h - MME binning information upper 32 - * @reserved - reserved field for 64 bit alignment + * @rot_mask - Rotator binning information + * @xbar_mask - xBAR binning information + * @reserved - reserved field for future binning info w/o ABI change + * @tpc_mask_h - TPC binning information upper 64 bit + * @nic_mask - NIC binning information */ struct lkd_fw_binning_info { - __le64 tpc_mask; + __le64 tpc_mask_l; __le32 dec_mask; - __le32 hbm_mask; + __le32 dram_mask; __le32 edma_mask; __le32 mme_mask_l; __le32 mme_mask_h; - __le32 reserved; + __le32 rot_mask; + __le32 xbar_mask; + __le32 reserved0; + __le64 tpc_mask_h; + __le64 nic_mask; + __le32 reserved1[8]; }; /* TODO: remove this struct after the code is updated to use message */ @@ -512,6 +536,23 @@ struct comms_msg_header { __u8 reserved[4]; /* pad to 64 bit */ }; +enum lkd_fw_ascii_msg_lvls { + LKD_FW_ASCII_MSG_ERR = 0, + LKD_FW_ASCII_MSG_WRN = 1, + LKD_FW_ASCII_MSG_INF = 2, + LKD_FW_ASCII_MSG_DBG = 3, +}; + +#define LKD_FW_ASCII_MSG_MAX_LEN 128 +#define LKD_FW_ASCII_MSG_MAX 4 /* consider ABI when changing */ + +struct lkd_fw_ascii_msg { + __u8 valid; + __u8 msg_lvl; + __u8 reserved[6]; + char msg[LKD_FW_ASCII_MSG_MAX_LEN]; +}; + /* this is the main FW descriptor - consider ABI when changing */ struct lkd_fw_comms_desc { struct comms_desc_header header; @@ -521,6 +562,8 @@ struct lkd_fw_comms_desc { /* can be used for 1 more version w/o ABI change */ char reserved0[VERSION_MAX_LEN]; __le64 img_addr; /* address for next FW component load */ + struct lkd_fw_binning_info binning_info; + struct lkd_fw_ascii_msg ascii_msg[LKD_FW_ASCII_MSG_MAX]; }; enum comms_reset_cause { @@ -545,6 +588,8 @@ struct lkd_fw_comms_msg { char reserved0[VERSION_MAX_LEN]; /* address for next FW component load */ __le64 img_addr; + struct lkd_fw_binning_info binning_info; + struct lkd_fw_ascii_msg ascii_msg[LKD_FW_ASCII_MSG_MAX]; }; struct { __u8 reset_cause; @@ -552,7 +597,7 @@ struct lkd_fw_comms_msg { struct { __u8 fw_cfg_skip; /* 1 - skip, 0 - don't skip */ }; - struct lkd_fw_binning_info binning_info; + struct lkd_fw_binning_info binning_conf; }; }; @@ -699,4 +744,92 @@ struct comms_status { }; }; +/** + * HL_MODULES_MAX_NUM is determined by the size of modules_mask in struct + * hl_component_versions + */ +enum hl_modules { + HL_MODULES_BOOT_INFO = 0, + HL_MODULES_EEPROM, + HL_MODULES_FDT, + HL_MODULES_I2C, + HL_MODULES_LZ4, + HL_MODULES_MBEDTLS, + HL_MODULES_MAX_NUM = 16 +}; + +/** + * HL_COMPONENTS_MAX_NUM is determined by the size of components_mask in + * struct cpucp_versions + */ +enum hl_components { + HL_COMPONENTS_PID = 0, + HL_COMPONENTS_MGMT, + HL_COMPONENTS_PREBOOT, + HL_COMPONENTS_PPBOOT, + HL_COMPONENTS_ARMCP, + HL_COMPONENTS_CPLD, + HL_COMPONENTS_UBOOT, + HL_COMPONENTS_MAX_NUM = 16 +}; + +/** + * struct hl_component_versions - versions associated with hl component. + * @struct_size: size of all the struct (including dynamic size of modules). + * @modules_offset: offset of the modules field in this struct. + * @component: version of the component itself. + * @fw_os: Firmware OS Version. + * @modules_mask: i'th bit (from LSB) is a flag - on if module i in enum + * hl_modules is used. + * @modules_counter: number of set bits in modules_mask. + * @reserved: reserved for future use. + * @modules: versions of the component's modules. Elborated explanation in + * struct cpucp_versions. + */ +struct hl_component_versions { + __le16 struct_size; + __le16 modules_offset; + __u8 component[VERSION_MAX_LEN]; + __u8 fw_os[VERSION_MAX_LEN]; + __le16 modules_mask; + __u8 modules_counter; + __u8 reserved[1]; + __u8 modules[][VERSION_MAX_LEN]; +}; + +/** + * struct hl_fw_versions - all versions (fuse, cpucp's components with their + * modules) + * @struct_size: size of all the struct (including dynamic size of components). + * @components_offset: offset of the components field in this struct. + * @fuse: silicon production FUSE information. + * @components_mask: i'th bit (from LSB) is a flag - on if component i in enum + * hl_components is used. + * @components_counter: number of set bits in components_mask. + * @reserved: reserved for future use. + * @components: versions of hl components. Index i corresponds to the i'th bit + * that is *on* in components_mask. For example, if + * components_mask=0b101, then *components represents arcpid and + * *(hl_component_versions*)((char*)components + 1') represents + * preboot, where 1' = components[0].struct_size. + */ +struct hl_fw_versions { + __le16 struct_size; + __le16 components_offset; + __u8 fuse[VERSION_MAX_LEN]; + __le16 components_mask; + __u8 components_counter; + __u8 reserved[1]; + struct hl_component_versions components[]; +}; + +/* Max size of struct hl_component_versions */ +#define HL_COMPONENT_VERSIONS_MAX_SIZE \ + (sizeof(struct hl_component_versions) + HL_MODULES_MAX_NUM * \ + VERSION_MAX_LEN) + +/* Max size of struct hl_fw_versions */ +#define HL_FW_VERSIONS_MAX_SIZE (sizeof(struct hl_fw_versions) + \ + HL_COMPONENTS_MAX_NUM * HL_COMPONENT_VERSIONS_MAX_SIZE) + #endif /* HL_BOOT_IF_H */ diff --git a/drivers/misc/habanalabs/include/common/qman_if.h b/drivers/accel/habanalabs/include/common/qman_if.h index 7ed7739575ee..7ed7739575ee 100644 --- a/drivers/misc/habanalabs/include/common/qman_if.h +++ b/drivers/accel/habanalabs/include/common/qman_if.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/cpu_if_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/cpu_if_regs.h index cf80e31317ad..cf80e31317ad 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/cpu_if_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/cpu_if_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma0_core_masks.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma0_core_masks.h index d079a37acab8..d079a37acab8 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma0_core_masks.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma0_core_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma0_core_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma0_core_regs.h index 1fdd5d5fc6d2..1fdd5d5fc6d2 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma0_core_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma0_core_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma0_qm_masks.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma0_qm_masks.h index 48376aabc3ba..48376aabc3ba 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma0_qm_masks.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma0_qm_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma0_qm_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma0_qm_regs.h index 8e56a93d88a1..8e56a93d88a1 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma0_qm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma0_qm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma1_core_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma1_core_regs.h index 4d8d8f26c5d4..4d8d8f26c5d4 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma1_core_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma1_core_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma1_qm_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma1_qm_regs.h index c3ef300849be..c3ef300849be 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma1_qm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma1_qm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma2_core_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma2_core_regs.h index a42862cd5ae0..a42862cd5ae0 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma2_core_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma2_core_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma2_qm_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma2_qm_regs.h index 8c4d4e016852..8c4d4e016852 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma2_qm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma2_qm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma3_core_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma3_core_regs.h index fb145f416fe6..fb145f416fe6 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma3_core_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma3_core_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma3_qm_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma3_qm_regs.h index a4b461ca3d94..a4b461ca3d94 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma3_qm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma3_qm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma4_core_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma4_core_regs.h index 192d11404b1c..192d11404b1c 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma4_core_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma4_core_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma4_qm_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma4_qm_regs.h index f0cbda0d1e4d..f0cbda0d1e4d 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma4_qm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma4_qm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma5_core_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma5_core_regs.h index 6e07c6fb6fc9..6e07c6fb6fc9 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma5_core_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma5_core_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma5_qm_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma5_qm_regs.h index 0faea21756c5..0faea21756c5 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma5_qm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma5_qm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma6_core_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma6_core_regs.h index 4962c13e2e2e..4962c13e2e2e 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma6_core_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma6_core_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma6_qm_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma6_qm_regs.h index af87adb94c94..af87adb94c94 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma6_qm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma6_qm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma7_core_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma7_core_regs.h index 8dd705d20195..8dd705d20195 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma7_core_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma7_core_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma7_qm_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma7_qm_regs.h index d6c631f63e3e..d6c631f63e3e 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma7_qm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma7_qm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma_if_e_n_down_ch0_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma_if_e_n_down_ch0_regs.h index 8c1c72df4469..8c1c72df4469 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma_if_e_n_down_ch0_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma_if_e_n_down_ch0_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma_if_e_n_down_ch1_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma_if_e_n_down_ch1_regs.h index b2b593fcec30..b2b593fcec30 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma_if_e_n_down_ch1_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma_if_e_n_down_ch1_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma_if_e_n_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma_if_e_n_regs.h index 8a10c6a76156..8a10c6a76156 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma_if_e_n_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma_if_e_n_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma_if_e_s_down_ch0_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma_if_e_s_down_ch0_regs.h index cd61289a1e8a..cd61289a1e8a 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma_if_e_s_down_ch0_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma_if_e_s_down_ch0_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma_if_e_s_down_ch1_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma_if_e_s_down_ch1_regs.h index 3f32370a14c7..3f32370a14c7 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma_if_e_s_down_ch1_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma_if_e_s_down_ch1_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma_if_e_s_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma_if_e_s_regs.h index 78c18da7154b..78c18da7154b 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma_if_e_s_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma_if_e_s_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma_if_w_n_down_ch0_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma_if_w_n_down_ch0_regs.h index 4ccaf8712948..4ccaf8712948 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma_if_w_n_down_ch0_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma_if_w_n_down_ch0_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma_if_w_n_down_ch1_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma_if_w_n_down_ch1_regs.h index 9236f4183084..9236f4183084 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma_if_w_n_down_ch1_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma_if_w_n_down_ch1_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma_if_w_n_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma_if_w_n_regs.h index da60893a5fab..da60893a5fab 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma_if_w_n_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma_if_w_n_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma_if_w_s_down_ch0_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma_if_w_s_down_ch0_regs.h index 56ffc920d58a..56ffc920d58a 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma_if_w_s_down_ch0_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma_if_w_s_down_ch0_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma_if_w_s_down_ch1_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma_if_w_s_down_ch1_regs.h index cbc642918deb..cbc642918deb 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma_if_w_s_down_ch1_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma_if_w_s_down_ch1_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma_if_w_s_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma_if_w_s_regs.h index 2382bc41bea6..2382bc41bea6 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/dma_if_w_s_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/dma_if_w_s_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/gaudi_blocks.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/gaudi_blocks.h index c7596aac7a5c..c7596aac7a5c 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/gaudi_blocks.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/gaudi_blocks.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/gaudi_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/gaudi_regs.h index 1a6576666794..23ee8691db46 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/gaudi_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/gaudi_regs.h @@ -320,4 +320,6 @@ #define mmPSOC_TPC_PLL_NR 0xC73100 #define mmIF_W_PLL_NR 0x488100 +#define mmPCIE_WRAP_RR_ELBI_RD_SEC_REG_CTRL 0xC01208 + #endif /* ASIC_REG_GAUDI_REGS_H_ */ diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/mme0_ctrl_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/mme0_ctrl_regs.h index 083d073a0128..083d073a0128 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/mme0_ctrl_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/mme0_ctrl_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/mme0_qm_masks.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/mme0_qm_masks.h index e6dd30ce0ca7..e6dd30ce0ca7 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/mme0_qm_masks.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/mme0_qm_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/mme0_qm_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/mme0_qm_regs.h index 4f078b328b00..4f078b328b00 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/mme0_qm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/mme0_qm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/mme1_ctrl_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/mme1_ctrl_regs.h index 6c07f7d45490..6c07f7d45490 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/mme1_ctrl_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/mme1_ctrl_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/mme2_ctrl_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/mme2_ctrl_regs.h index a1f2eb8b91bd..a1f2eb8b91bd 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/mme2_ctrl_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/mme2_ctrl_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/mme2_qm_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/mme2_qm_regs.h index c1ea6a422010..c1ea6a422010 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/mme2_qm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/mme2_qm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/mme3_ctrl_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/mme3_ctrl_regs.h index 36f6edc72e3d..36f6edc72e3d 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/mme3_ctrl_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/mme3_ctrl_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/mmu_up_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/mmu_up_regs.h index 61465b599850..61465b599850 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/mmu_up_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/mmu_up_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/nic0_qm0_masks.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/nic0_qm0_masks.h index bd37b6452133..bd37b6452133 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/nic0_qm0_masks.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/nic0_qm0_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/nic0_qm0_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/nic0_qm0_regs.h index 7c97f4041b8e..7c97f4041b8e 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/nic0_qm0_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/nic0_qm0_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/nic0_qm1_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/nic0_qm1_regs.h index fe96c575b5c6..fe96c575b5c6 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/nic0_qm1_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/nic0_qm1_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/nic1_qm0_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/nic1_qm0_regs.h index 0d1caf057ad0..0d1caf057ad0 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/nic1_qm0_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/nic1_qm0_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/nic1_qm1_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/nic1_qm1_regs.h index 1b115ee6d6f0..1b115ee6d6f0 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/nic1_qm1_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/nic1_qm1_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/nic2_qm0_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/nic2_qm0_regs.h index a89116a4586f..a89116a4586f 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/nic2_qm0_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/nic2_qm0_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/nic2_qm1_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/nic2_qm1_regs.h index b7f091ddc89c..b7f091ddc89c 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/nic2_qm1_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/nic2_qm1_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/nic3_qm0_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/nic3_qm0_regs.h index 4712cc62b009..4712cc62b009 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/nic3_qm0_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/nic3_qm0_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/nic3_qm1_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/nic3_qm1_regs.h index 7fa040f65004..7fa040f65004 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/nic3_qm1_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/nic3_qm1_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/nic4_qm0_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/nic4_qm0_regs.h index 99d5319672dd..99d5319672dd 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/nic4_qm0_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/nic4_qm0_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/nic4_qm1_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/nic4_qm1_regs.h index 34b21b21da52..34b21b21da52 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/nic4_qm1_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/nic4_qm1_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_0_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_0_regs.h index 2efa2a54deb4..2efa2a54deb4 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_0_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_0_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_1_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_1_regs.h index a6047d4e2560..a6047d4e2560 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_1_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_1_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_2_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_2_regs.h index 9de8442f9bc2..9de8442f9bc2 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_2_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_2_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_3_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_3_regs.h index 34fd47685edd..34fd47685edd 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_3_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_3_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_4_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_4_regs.h index 543a98f81767..543a98f81767 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_4_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_4_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_5_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_5_regs.h index 95486b7ddf1d..95486b7ddf1d 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_5_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_5_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_6_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_6_regs.h index b79c59887b21..b79c59887b21 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_6_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_6_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_7_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_7_regs.h index 3a6a34ba2958..3a6a34ba2958 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_7_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/nif_rtr_ctrl_7_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/psoc_cpu_pll_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/psoc_cpu_pll_regs.h index 2585c70f59ef..2585c70f59ef 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/psoc_cpu_pll_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/psoc_cpu_pll_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/psoc_etr_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/psoc_etr_regs.h index b7c33e025db5..b7c33e025db5 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/psoc_etr_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/psoc_etr_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/psoc_global_conf_masks.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/psoc_global_conf_masks.h index 6703e678ee9f..6703e678ee9f 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/psoc_global_conf_masks.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/psoc_global_conf_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/psoc_global_conf_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/psoc_global_conf_regs.h index 1b5cfcc1d85f..1b5cfcc1d85f 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/psoc_global_conf_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/psoc_global_conf_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/psoc_timestamp_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/psoc_timestamp_regs.h index 9ce24597d4b0..9ce24597d4b0 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/psoc_timestamp_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/psoc_timestamp_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_0_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_0_regs.h index ddf824392cf7..ddf824392cf7 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_0_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_0_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_1_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_1_regs.h index c6d517dbbd54..c6d517dbbd54 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_1_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_1_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_2_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_2_regs.h index 330e5b42d679..330e5b42d679 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_2_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_2_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_3_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_3_regs.h index d749f1968e5e..d749f1968e5e 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_3_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_3_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_4_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_4_regs.h index ad48773c4bbd..ad48773c4bbd 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_4_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_4_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_5_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_5_regs.h index 6c27850ca3f5..6c27850ca3f5 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_5_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_5_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_6_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_6_regs.h index a9ea89aa6405..a9ea89aa6405 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_6_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_6_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_7_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_7_regs.h index a37772c531d9..a37772c531d9 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_7_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/sif_rtr_ctrl_7_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/stlb_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/stlb_regs.h index 07d2a9000102..07d2a9000102 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/stlb_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/stlb_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc0_cfg_masks.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc0_cfg_masks.h index 8f67c11c8de9..8f67c11c8de9 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc0_cfg_masks.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc0_cfg_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc0_cfg_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc0_cfg_regs.h index b82a906265a8..b82a906265a8 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc0_cfg_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc0_cfg_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc0_qm_masks.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc0_qm_masks.h index 8e71532c6f36..8e71532c6f36 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc0_qm_masks.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc0_qm_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc0_qm_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc0_qm_regs.h index f9e310ab6df2..f9e310ab6df2 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc0_qm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc0_qm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc1_cfg_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc1_cfg_regs.h index 6736c476d979..6736c476d979 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc1_cfg_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc1_cfg_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc1_qm_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc1_qm_regs.h index af10ef7a87d9..af10ef7a87d9 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc1_qm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc1_qm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc2_cfg_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc2_cfg_regs.h index 3e77c37952bc..3e77c37952bc 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc2_cfg_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc2_cfg_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc2_qm_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc2_qm_regs.h index 2919e2fa58f8..2919e2fa58f8 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc2_qm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc2_qm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc3_cfg_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc3_cfg_regs.h index 6d42469659f1..6d42469659f1 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc3_cfg_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc3_cfg_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc3_qm_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc3_qm_regs.h index 5f2a0fd86c9e..5f2a0fd86c9e 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc3_qm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc3_qm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc4_cfg_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc4_cfg_regs.h index 7a9447f39a74..7a9447f39a74 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc4_cfg_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc4_cfg_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc4_qm_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc4_qm_regs.h index 80e63402f6e0..80e63402f6e0 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc4_qm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc4_qm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc5_cfg_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc5_cfg_regs.h index f428f891935a..f428f891935a 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc5_cfg_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc5_cfg_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc5_qm_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc5_qm_regs.h index cd3a810ff4c4..cd3a810ff4c4 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc5_qm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc5_qm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc6_cfg_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc6_cfg_regs.h index eb251e72813f..eb251e72813f 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc6_cfg_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc6_cfg_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc6_qm_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc6_qm_regs.h index e35ef7fd8b1c..e35ef7fd8b1c 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc6_qm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc6_qm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc7_cfg_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc7_cfg_regs.h index 1887b10e58e2..1887b10e58e2 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc7_cfg_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc7_cfg_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc7_qm_regs.h b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc7_qm_regs.h index 5c36c972c027..5c36c972c027 100644 --- a/drivers/misc/habanalabs/include/gaudi/asic_reg/tpc7_qm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi/asic_reg/tpc7_qm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi/gaudi.h b/drivers/accel/habanalabs/include/gaudi/gaudi.h index ffae107b1693..ffae107b1693 100644 --- a/drivers/misc/habanalabs/include/gaudi/gaudi.h +++ b/drivers/accel/habanalabs/include/gaudi/gaudi.h diff --git a/drivers/misc/habanalabs/include/gaudi/gaudi_async_events.h b/drivers/accel/habanalabs/include/gaudi/gaudi_async_events.h index c07ed4ed304c..c07ed4ed304c 100644 --- a/drivers/misc/habanalabs/include/gaudi/gaudi_async_events.h +++ b/drivers/accel/habanalabs/include/gaudi/gaudi_async_events.h diff --git a/drivers/misc/habanalabs/include/gaudi/gaudi_async_ids_map_extended.h b/drivers/accel/habanalabs/include/gaudi/gaudi_async_ids_map_extended.h index 479b6b038254..479b6b038254 100644 --- a/drivers/misc/habanalabs/include/gaudi/gaudi_async_ids_map_extended.h +++ b/drivers/accel/habanalabs/include/gaudi/gaudi_async_ids_map_extended.h diff --git a/drivers/misc/habanalabs/include/gaudi/gaudi_coresight.h b/drivers/accel/habanalabs/include/gaudi/gaudi_coresight.h index c45cc7f4d4d7..c45cc7f4d4d7 100644 --- a/drivers/misc/habanalabs/include/gaudi/gaudi_coresight.h +++ b/drivers/accel/habanalabs/include/gaudi/gaudi_coresight.h diff --git a/drivers/misc/habanalabs/include/gaudi/gaudi_fw_if.h b/drivers/accel/habanalabs/include/gaudi/gaudi_fw_if.h index 2dba02757d37..2dba02757d37 100644 --- a/drivers/misc/habanalabs/include/gaudi/gaudi_fw_if.h +++ b/drivers/accel/habanalabs/include/gaudi/gaudi_fw_if.h diff --git a/drivers/misc/habanalabs/include/gaudi/gaudi_masks.h b/drivers/accel/habanalabs/include/gaudi/gaudi_masks.h index 880c57b26c63..880c57b26c63 100644 --- a/drivers/misc/habanalabs/include/gaudi/gaudi_masks.h +++ b/drivers/accel/habanalabs/include/gaudi/gaudi_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi/gaudi_packets.h b/drivers/accel/habanalabs/include/gaudi/gaudi_packets.h index 66fc083a7c6a..66fc083a7c6a 100644 --- a/drivers/misc/habanalabs/include/gaudi/gaudi_packets.h +++ b/drivers/accel/habanalabs/include/gaudi/gaudi_packets.h diff --git a/drivers/misc/habanalabs/include/gaudi/gaudi_reg_map.h b/drivers/accel/habanalabs/include/gaudi/gaudi_reg_map.h index 92f25c2ae083..92f25c2ae083 100644 --- a/drivers/misc/habanalabs/include/gaudi/gaudi_reg_map.h +++ b/drivers/accel/habanalabs/include/gaudi/gaudi_reg_map.h diff --git a/drivers/accel/habanalabs/include/gaudi2/arc/gaudi2_arc_common_packets.h b/drivers/accel/habanalabs/include/gaudi2/arc/gaudi2_arc_common_packets.h new file mode 100644 index 000000000000..22a6ab9a7f47 --- /dev/null +++ b/drivers/accel/habanalabs/include/gaudi2/arc/gaudi2_arc_common_packets.h @@ -0,0 +1,211 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2020 HabanaLabs Ltd. + * All Rights Reserved. + */ + +#ifndef __GAUDI2_ARC_COMMON_PACKETS_H__ +#define __GAUDI2_ARC_COMMON_PACKETS_H__ + +enum { + CPU_ID_SCHED_ARC0 = 0, /* FARM_ARC0 */ + CPU_ID_SCHED_ARC1 = 1, /* FARM_ARC1 */ + CPU_ID_SCHED_ARC2 = 2, /* FARM_ARC2 */ + CPU_ID_SCHED_ARC3 = 3, /* FARM_ARC3 */ + /* Dcore1 MME Engine ARC instance used as scheduler */ + CPU_ID_SCHED_ARC4 = 4, /* DCORE1_MME0 */ + /* Dcore3 MME Engine ARC instance used as scheduler */ + CPU_ID_SCHED_ARC5 = 5, /* DCORE3_MME0 */ + + CPU_ID_TPC_QMAN_ARC0 = 6, /* DCORE0_TPC0 */ + CPU_ID_TPC_QMAN_ARC1 = 7, /* DCORE0_TPC1 */ + CPU_ID_TPC_QMAN_ARC2 = 8, /* DCORE0_TPC2 */ + CPU_ID_TPC_QMAN_ARC3 = 9, /* DCORE0_TPC3 */ + CPU_ID_TPC_QMAN_ARC4 = 10, /* DCORE0_TPC4 */ + CPU_ID_TPC_QMAN_ARC5 = 11, /* DCORE0_TPC5 */ + CPU_ID_TPC_QMAN_ARC6 = 12, /* DCORE1_TPC0 */ + CPU_ID_TPC_QMAN_ARC7 = 13, /* DCORE1_TPC1 */ + CPU_ID_TPC_QMAN_ARC8 = 14, /* DCORE1_TPC2 */ + CPU_ID_TPC_QMAN_ARC9 = 15, /* DCORE1_TPC3 */ + CPU_ID_TPC_QMAN_ARC10 = 16, /* DCORE1_TPC4 */ + CPU_ID_TPC_QMAN_ARC11 = 17, /* DCORE1_TPC5 */ + CPU_ID_TPC_QMAN_ARC12 = 18, /* DCORE2_TPC0 */ + CPU_ID_TPC_QMAN_ARC13 = 19, /* DCORE2_TPC1 */ + CPU_ID_TPC_QMAN_ARC14 = 20, /* DCORE2_TPC2 */ + CPU_ID_TPC_QMAN_ARC15 = 21, /* DCORE2_TPC3 */ + CPU_ID_TPC_QMAN_ARC16 = 22, /* DCORE2_TPC4 */ + CPU_ID_TPC_QMAN_ARC17 = 23, /* DCORE2_TPC5 */ + CPU_ID_TPC_QMAN_ARC18 = 24, /* DCORE3_TPC0 */ + CPU_ID_TPC_QMAN_ARC19 = 25, /* DCORE3_TPC1 */ + CPU_ID_TPC_QMAN_ARC20 = 26, /* DCORE3_TPC2 */ + CPU_ID_TPC_QMAN_ARC21 = 27, /* DCORE3_TPC3 */ + CPU_ID_TPC_QMAN_ARC22 = 28, /* DCORE3_TPC4 */ + CPU_ID_TPC_QMAN_ARC23 = 29, /* DCORE3_TPC5 */ + CPU_ID_TPC_QMAN_ARC24 = 30, /* DCORE0_TPC6 - Never present */ + + CPU_ID_MME_QMAN_ARC0 = 31, /* DCORE0_MME0 */ + CPU_ID_MME_QMAN_ARC1 = 32, /* DCORE2_MME0 */ + + CPU_ID_EDMA_QMAN_ARC0 = 33, /* DCORE0_EDMA0 */ + CPU_ID_EDMA_QMAN_ARC1 = 34, /* DCORE0_EDMA1 */ + CPU_ID_EDMA_QMAN_ARC2 = 35, /* DCORE1_EDMA0 */ + CPU_ID_EDMA_QMAN_ARC3 = 36, /* DCORE1_EDMA1 */ + CPU_ID_EDMA_QMAN_ARC4 = 37, /* DCORE2_EDMA0 */ + CPU_ID_EDMA_QMAN_ARC5 = 38, /* DCORE2_EDMA1 */ + CPU_ID_EDMA_QMAN_ARC6 = 39, /* DCORE3_EDMA0 */ + CPU_ID_EDMA_QMAN_ARC7 = 40, /* DCORE3_EDMA1 */ + + CPU_ID_PDMA_QMAN_ARC0 = 41, /* DCORE0_PDMA0 */ + CPU_ID_PDMA_QMAN_ARC1 = 42, /* DCORE0_PDMA1 */ + + CPU_ID_ROT_QMAN_ARC0 = 43, /* ROT0 */ + CPU_ID_ROT_QMAN_ARC1 = 44, /* ROT1 */ + + CPU_ID_NIC_QMAN_ARC0 = 45, /* NIC0_0 */ + CPU_ID_NIC_QMAN_ARC1 = 46, /* NIC0_1 */ + CPU_ID_NIC_QMAN_ARC2 = 47, /* NIC1_0 */ + CPU_ID_NIC_QMAN_ARC3 = 48, /* NIC1_1 */ + CPU_ID_NIC_QMAN_ARC4 = 49, /* NIC2_0 */ + CPU_ID_NIC_QMAN_ARC5 = 50, /* NIC2_1 */ + CPU_ID_NIC_QMAN_ARC6 = 51, /* NIC3_0 */ + CPU_ID_NIC_QMAN_ARC7 = 52, /* NIC3_1 */ + CPU_ID_NIC_QMAN_ARC8 = 53, /* NIC4_0 */ + CPU_ID_NIC_QMAN_ARC9 = 54, /* NIC4_1 */ + CPU_ID_NIC_QMAN_ARC10 = 55, /* NIC5_0 */ + CPU_ID_NIC_QMAN_ARC11 = 56, /* NIC5_1 */ + CPU_ID_NIC_QMAN_ARC12 = 57, /* NIC6_0 */ + CPU_ID_NIC_QMAN_ARC13 = 58, /* NIC6_1 */ + CPU_ID_NIC_QMAN_ARC14 = 59, /* NIC7_0 */ + CPU_ID_NIC_QMAN_ARC15 = 60, /* NIC7_1 */ + CPU_ID_NIC_QMAN_ARC16 = 61, /* NIC8_0 */ + CPU_ID_NIC_QMAN_ARC17 = 62, /* NIC8_1 */ + CPU_ID_NIC_QMAN_ARC18 = 63, /* NIC9_0 */ + CPU_ID_NIC_QMAN_ARC19 = 64, /* NIC9_1 */ + CPU_ID_NIC_QMAN_ARC20 = 65, /* NIC10_0 */ + CPU_ID_NIC_QMAN_ARC21 = 66, /* NIC10_1 */ + CPU_ID_NIC_QMAN_ARC22 = 67, /* NIC11_0 */ + CPU_ID_NIC_QMAN_ARC23 = 68, /* NIC11_1 */ + + CPU_ID_MAX = 69, + CPU_ID_SCHED_MAX = 6, + + CPU_ID_ALL = 0xFE, + CPU_ID_INVALID = 0xFF, +}; + +enum arc_regions_t { + ARC_REGION0_UNSED = 0, + /* + * Extension registers + * None + */ + ARC_REGION1_SRAM = 1, + /* + * Extension registers + * AUX_SRAM_LSB_ADDR + * AUX_SRAM_MSB_ADDR + * ARC Address: 0x1000_0000 + */ + ARC_REGION2_CFG = 2, + /* + * Extension registers + * AUX_CFG_LSB_ADDR + * AUX_CFG_MSB_ADDR + * ARC Address: 0x2000_0000 + */ + ARC_REGION3_GENERAL = 3, + /* + * Extension registers + * AUX_GENERAL_PURPOSE_LSB_ADDR_0 + * AUX_GENERAL_PURPOSE_MSB_ADDR_0 + * ARC Address: 0x3000_0000 + */ + ARC_REGION4_HBM0_FW = 4, + /* + * Extension registers + * AUX_HBM0_LSB_ADDR + * AUX_HBM0_MSB_ADDR + * AUX_HBM0_OFFSET + * ARC Address: 0x4000_0000 + */ + ARC_REGION5_HBM1_GC_DATA = 5, + /* + * Extension registers + * AUX_HBM1_LSB_ADDR + * AUX_HBM1_MSB_ADDR + * AUX_HBM1_OFFSET + * ARC Address: 0x5000_0000 + */ + ARC_REGION6_HBM2_GC_DATA = 6, + /* + * Extension registers + * AUX_HBM2_LSB_ADDR + * AUX_HBM2_MSB_ADDR + * AUX_HBM2_OFFSET + * ARC Address: 0x6000_0000 + */ + ARC_REGION7_HBM3_GC_DATA = 7, + /* + * Extension registers + * AUX_HBM3_LSB_ADDR + * AUX_HBM3_MSB_ADDR + * AUX_HBM3_OFFSET + * ARC Address: 0x7000_0000 + */ + ARC_REGION8_DCCM = 8, + /* + * Extension registers + * None + * ARC Address: 0x8000_0000 + */ + ARC_REGION9_PCIE = 9, + /* + * Extension registers + * AUX_PCIE_LSB_ADDR + * AUX_PCIE_MSB_ADDR + * ARC Address: 0x9000_0000 + */ + ARC_REGION10_GENERAL = 10, + /* + * Extension registers + * AUX_GENERAL_PURPOSE_LSB_ADDR_1 + * AUX_GENERAL_PURPOSE_MSB_ADDR_1 + * ARC Address: 0xA000_0000 + */ + ARC_REGION11_GENERAL = 11, + /* + * Extension registers + * AUX_GENERAL_PURPOSE_LSB_ADDR_2 + * AUX_GENERAL_PURPOSE_MSB_ADDR_2 + * ARC Address: 0xB000_0000 + */ + ARC_REGION12_GENERAL = 12, + /* + * Extension registers + * AUX_GENERAL_PURPOSE_LSB_ADDR_3 + * AUX_GENERAL_PURPOSE_MSB_ADDR_3 + * ARC Address: 0xC000_0000 + */ + ARC_REGION13_GENERAL = 13, + /* + * Extension registers + * AUX_GENERAL_PURPOSE_LSB_ADDR_4 + * AUX_GENERAL_PURPOSE_MSB_ADDR_4 + * ARC Address: 0xD000_0000 + */ + ARC_REGION14_GENERAL = 14, + /* + * Extension registers + * AUX_GENERAL_PURPOSE_LSB_ADDR_5 + * AUX_GENERAL_PURPOSE_MSB_ADDR_5 + * ARC Address: 0xE000_0000 + */ + ARC_REGION15_LBU = 15 + /* + * Extension registers + * None + * ARC Address: 0xF000_0000 + */ +}; + +#endif /* __GAUDI2_ARC_COMMON_PACKETS_H__ */ diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/arc_farm_arc0_acp_eng_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/arc_farm_arc0_acp_eng_regs.h index 1974df13b5f9..1974df13b5f9 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/arc_farm_arc0_acp_eng_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/arc_farm_arc0_acp_eng_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/arc_farm_arc0_aux_masks.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/arc_farm_arc0_aux_masks.h index fc2c52af6509..fc2c52af6509 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/arc_farm_arc0_aux_masks.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/arc_farm_arc0_aux_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/arc_farm_arc0_aux_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/arc_farm_arc0_aux_regs.h index 5345b5faa3a2..5345b5faa3a2 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/arc_farm_arc0_aux_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/arc_farm_arc0_aux_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/arc_farm_arc0_dup_eng_axuser_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/arc_farm_arc0_dup_eng_axuser_regs.h index bde077eed285..bde077eed285 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/arc_farm_arc0_dup_eng_axuser_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/arc_farm_arc0_dup_eng_axuser_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/arc_farm_arc0_dup_eng_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/arc_farm_arc0_dup_eng_regs.h index 491af75c12c3..491af75c12c3 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/arc_farm_arc0_dup_eng_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/arc_farm_arc0_dup_eng_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_ctx_axuser_masks.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_ctx_axuser_masks.h index 12d6a124a2e9..12d6a124a2e9 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_ctx_axuser_masks.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_ctx_axuser_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_ctx_axuser_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_ctx_axuser_regs.h index 23f9d2df52a7..23f9d2df52a7 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_ctx_axuser_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_ctx_axuser_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_ctx_masks.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_ctx_masks.h index bee4de0b28d6..bee4de0b28d6 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_ctx_masks.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_ctx_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_ctx_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_ctx_regs.h index b9f09e8199e6..b9f09e8199e6 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_ctx_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_ctx_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_kdma_cgm_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_kdma_cgm_regs.h index d6dd2c066fa9..d6dd2c066fa9 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_kdma_cgm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_kdma_cgm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_masks.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_masks.h index 5903dbacec80..5903dbacec80 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_masks.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_regs.h index e312cf810c0e..e312cf810c0e 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/arc_farm_kdma_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/cpu_if_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/cpu_if_regs.h index 9b3eceec9d5d..9b3eceec9d5d 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/cpu_if_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/cpu_if_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_dec0_cmd_masks.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_dec0_cmd_masks.h index 296ab832013f..296ab832013f 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_dec0_cmd_masks.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_dec0_cmd_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_dec0_cmd_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_dec0_cmd_regs.h index e26f0d77c9dc..e26f0d77c9dc 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_dec0_cmd_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_dec0_cmd_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_core_ctx_axuser_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_core_ctx_axuser_regs.h index 8de48939243b..8de48939243b 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_core_ctx_axuser_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_core_ctx_axuser_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_core_ctx_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_core_ctx_regs.h index f73e76c8f5bd..f73e76c8f5bd 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_core_ctx_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_core_ctx_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_core_masks.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_core_masks.h index d600f6bf70d8..d600f6bf70d8 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_core_masks.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_core_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_core_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_core_regs.h index 84f068e4c602..84f068e4c602 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_core_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_core_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_qm_arc_aux_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_qm_arc_aux_regs.h index 0fc45300df81..0fc45300df81 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_qm_arc_aux_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_qm_arc_aux_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_qm_axuser_nonsecured_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_qm_axuser_nonsecured_regs.h index 88d2a133f129..88d2a133f129 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_qm_axuser_nonsecured_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_qm_axuser_nonsecured_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_qm_cgm_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_qm_cgm_regs.h index 0b0a76a5b2a0..0b0a76a5b2a0 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_qm_cgm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_qm_cgm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_qm_masks.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_qm_masks.h index 102e2a65811c..102e2a65811c 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_qm_masks.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_qm_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_qm_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_qm_regs.h index 32d475b9ed11..32d475b9ed11 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_qm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_edma0_qm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_edma1_core_ctx_axuser_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_edma1_core_ctx_axuser_regs.h index b608a634562f..b608a634562f 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_edma1_core_ctx_axuser_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_edma1_core_ctx_axuser_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_edma1_qm_axuser_nonsecured_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_edma1_qm_axuser_nonsecured_regs.h index c3a462f2a9ac..c3a462f2a9ac 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_edma1_qm_axuser_nonsecured_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_edma1_qm_axuser_nonsecured_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_hmmu0_mmu_masks.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_hmmu0_mmu_masks.h index df51eac10dd7..2965b6a3b423 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_hmmu0_mmu_masks.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_hmmu0_mmu_masks.h @@ -150,8 +150,7 @@ #define DCORE0_HMMU0_MMU_STATIC_MULTI_PAGE_SIZE_HOP1_PAGE_SIZE_SHIFT 16 #define DCORE0_HMMU0_MMU_STATIC_MULTI_PAGE_SIZE_HOP1_PAGE_SIZE_MASK 0xF0000 #define DCORE0_HMMU0_MMU_STATIC_MULTI_PAGE_SIZE_CFG_8_BITS_HOP_MODE_EN_SHIFT 20 -#define DCORE0_HMMU0_MMU_STATIC_MULTI_PAGE_SIZE_CFG_8_BITS_HOP_MODE_EN_MASK \ -0x100000 +#define DCORE0_HMMU0_MMU_STATIC_MULTI_PAGE_SIZE_CFG_8_BITS_HOP_MODE_EN_MASK 0x100000 /* DCORE0_HMMU0_MMU_CORE_SEP_CACHE_RNG */ #define DCORE0_HMMU0_MMU_CORE_SEP_CACHE_RNG_CORE_SET_MASK_SHIFT 0 @@ -235,23 +234,19 @@ /* DCORE0_HMMU0_MMU_ILLEGAL_ADDR_WRITE_63_32 */ #define DCORE0_HMMU0_MMU_ILLEGAL_ADDR_WRITE_63_32_ILLEGAL_ADDR_63_32_SHIFT 0 -#define DCORE0_HMMU0_MMU_ILLEGAL_ADDR_WRITE_63_32_ILLEGAL_ADDR_63_32_MASK \ -0xFFFFFFFF +#define DCORE0_HMMU0_MMU_ILLEGAL_ADDR_WRITE_63_32_ILLEGAL_ADDR_63_32_MASK 0xFFFFFFFF /* DCORE0_HMMU0_MMU_ILLEGAL_ADDR_WRITE_31_0 */ #define DCORE0_HMMU0_MMU_ILLEGAL_ADDR_WRITE_31_0_ILLEGAL_ADDR_31_0_SHIFT 0 -#define DCORE0_HMMU0_MMU_ILLEGAL_ADDR_WRITE_31_0_ILLEGAL_ADDR_31_0_MASK \ -0xFFFFFFFF +#define DCORE0_HMMU0_MMU_ILLEGAL_ADDR_WRITE_31_0_ILLEGAL_ADDR_31_0_MASK 0xFFFFFFFF /* DCORE0_HMMU0_MMU_ILLEGAL_ADDR_READ_63_32 */ #define DCORE0_HMMU0_MMU_ILLEGAL_ADDR_READ_63_32_ILLEGAL_ADDR_63_32_SHIFT 0 -#define DCORE0_HMMU0_MMU_ILLEGAL_ADDR_READ_63_32_ILLEGAL_ADDR_63_32_MASK \ -0xFFFFFFFF +#define DCORE0_HMMU0_MMU_ILLEGAL_ADDR_READ_63_32_ILLEGAL_ADDR_63_32_MASK 0xFFFFFFFF /* DCORE0_HMMU0_MMU_ILLEGAL_ADDR_READ_31_0 */ #define DCORE0_HMMU0_MMU_ILLEGAL_ADDR_READ_31_0_ILLEGAL_ADDR_31_0_SHIFT 0 -#define DCORE0_HMMU0_MMU_ILLEGAL_ADDR_READ_31_0_ILLEGAL_ADDR_31_0_MASK \ -0xFFFFFFFF +#define DCORE0_HMMU0_MMU_ILLEGAL_ADDR_READ_31_0_ILLEGAL_ADDR_31_0_MASK 0xFFFFFFFF /* DCORE0_HMMU0_MMU_RAZWI_WRITE_VLD */ #define DCORE0_HMMU0_MMU_RAZWI_WRITE_VLD_R_SHIFT 0 diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_hmmu0_mmu_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_hmmu0_mmu_regs.h index 08ccd695ec89..08ccd695ec89 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_hmmu0_mmu_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_hmmu0_mmu_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_hmmu0_stlb_masks.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_hmmu0_stlb_masks.h index 192eba5f07bb..a311778b21e7 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_hmmu0_stlb_masks.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_hmmu0_stlb_masks.h @@ -92,8 +92,7 @@ #define DCORE0_HMMU0_STLB_HOP_CONFIGURATION_ONLY_LARGE_PAGE_SHIFT 20 #define DCORE0_HMMU0_STLB_HOP_CONFIGURATION_ONLY_LARGE_PAGE_MASK 0x100000 #define DCORE0_HMMU0_STLB_HOP_CONFIGURATION_LARGE_PAGE_INDICATION_BIT_SHIFT 21 -#define DCORE0_HMMU0_STLB_HOP_CONFIGURATION_LARGE_PAGE_INDICATION_BIT_MASK \ -0x7E00000 +#define DCORE0_HMMU0_STLB_HOP_CONFIGURATION_LARGE_PAGE_INDICATION_BIT_MASK 0x7E00000 /* DCORE0_HMMU0_STLB_LINK_LIST_LOOKUP_MASK_63_32 */ #define DCORE0_HMMU0_STLB_LINK_LIST_LOOKUP_MASK_63_32_R_SHIFT 0 @@ -228,12 +227,8 @@ #define DCORE0_HMMU0_STLB_MEM_READ_ARPROT_R_MASK 0x7 /* DCORE0_HMMU0_STLB_RANGE_CACHE_INVALIDATION */ -#define \ -DCORE0_HMMU0_STLB_RANGE_CACHE_INVALIDATION_RANGE_INVALIDATION_ENABLE_SHIFT \ -0 -#define \ -DCORE0_HMMU0_STLB_RANGE_CACHE_INVALIDATION_RANGE_INVALIDATION_ENABLE_MASK \ -0x1 +#define DCORE0_HMMU0_STLB_RANGE_CACHE_INVALIDATION_RANGE_INVALIDATION_ENABLE_SHIFT 0 +#define DCORE0_HMMU0_STLB_RANGE_CACHE_INVALIDATION_RANGE_INVALIDATION_ENABLE_MASK 0x1 #define DCORE0_HMMU0_STLB_RANGE_CACHE_INVALIDATION_INVALIDATION_ASID_EN_SHIFT 1 #define DCORE0_HMMU0_STLB_RANGE_CACHE_INVALIDATION_INVALIDATION_ASID_EN_MASK 0x2 #define DCORE0_HMMU0_STLB_RANGE_CACHE_INVALIDATION_INVALIDATION_ASID_SHIFT 2 @@ -261,53 +256,43 @@ DCORE0_HMMU0_STLB_RANGE_CACHE_INVALIDATION_RANGE_INVALIDATION_ENABLE_MASK \ /* DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_0 */ #define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_0_ASID_POLY_MATRIX_H3_SHIFT 0 -#define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_0_ASID_POLY_MATRIX_H3_MASK \ -0x1FF +#define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_0_ASID_POLY_MATRIX_H3_MASK 0x1FF /* DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_1 */ #define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_1_ASID_POLY_MATRIX_H3_SHIFT 0 -#define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_1_ASID_POLY_MATRIX_H3_MASK \ -0x1FF +#define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_1_ASID_POLY_MATRIX_H3_MASK 0x1FF /* DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_2 */ #define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_2_ASID_POLY_MATRIX_H3_SHIFT 0 -#define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_2_ASID_POLY_MATRIX_H3_MASK \ -0x1FF +#define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_2_ASID_POLY_MATRIX_H3_MASK 0x1FF /* DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_3 */ #define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_3_ASID_POLY_MATRIX_H3_SHIFT 0 -#define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_3_ASID_POLY_MATRIX_H3_MASK \ -0x1FF +#define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_3_ASID_POLY_MATRIX_H3_MASK 0x1FF /* DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_4 */ #define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_4_ASID_POLY_MATRIX_H3_SHIFT 0 -#define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_4_ASID_POLY_MATRIX_H3_MASK \ -0x1FF +#define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_4_ASID_POLY_MATRIX_H3_MASK 0x1FF /* DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_5 */ #define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_5_ASID_POLY_MATRIX_H3_SHIFT 0 -#define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_5_ASID_POLY_MATRIX_H3_MASK \ -0x1FF +#define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_5_ASID_POLY_MATRIX_H3_MASK 0x1FF /* DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_6 */ #define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_6_ASID_POLY_MATRIX_H3_SHIFT 0 -#define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_6_ASID_POLY_MATRIX_H3_MASK \ -0x1FF +#define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_6_ASID_POLY_MATRIX_H3_MASK 0x1FF /* DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_7 */ #define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_7_ASID_POLY_MATRIX_H3_SHIFT 0 -#define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_7_ASID_POLY_MATRIX_H3_MASK \ -0x1FF +#define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_7_ASID_POLY_MATRIX_H3_MASK 0x1FF /* DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_8 */ #define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_8_ASID_POLY_MATRIX_H3_SHIFT 0 -#define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_8_ASID_POLY_MATRIX_H3_MASK \ -0x1FF +#define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_8_ASID_POLY_MATRIX_H3_MASK 0x1FF /* DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_9 */ #define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_9_ASID_POLY_MATRIX_H3_SHIFT 0 -#define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_9_ASID_POLY_MATRIX_H3_MASK \ -0x1FF +#define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MATRIX_H3_9_ASID_POLY_MATRIX_H3_MASK 0x1FF /* DCORE0_HMMU0_STLB_ASID_SCR_POLY_MAT_H3_10 */ #define DCORE0_HMMU0_STLB_ASID_SCR_POLY_MAT_H3_10_ASID_POLY_MATRIX_H3_SHIFT 0 diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_hmmu0_stlb_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_hmmu0_stlb_regs.h index 864a259f68e2..864a259f68e2 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_hmmu0_stlb_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_hmmu0_stlb_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_acc_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_acc_regs.h index 07bed3ec740e..07bed3ec740e 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_acc_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_acc_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_cout0_master_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_cout0_master_regs.h index c9043979fd69..c9043979fd69 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_cout0_master_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_cout0_master_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_cout0_slave_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_cout0_slave_regs.h index 7d74aea4576f..7d74aea4576f 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_cout0_slave_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_cout0_slave_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_cout1_master_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_cout1_master_regs.h index f6f519eb5f6f..f6f519eb5f6f 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_cout1_master_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_cout1_master_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_cout1_slave_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_cout1_slave_regs.h index 0e0c056ade9b..0e0c056ade9b 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_cout1_slave_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_cout1_slave_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in0_master_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in0_master_regs.h index 34c6134a2f93..34c6134a2f93 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in0_master_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in0_master_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in0_slave_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in0_slave_regs.h index 55065032f87c..55065032f87c 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in0_slave_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in0_slave_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in1_master_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in1_master_regs.h index 6022b387eacf..6022b387eacf 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in1_master_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in1_master_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in1_slave_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in1_slave_regs.h index f9c9b01f0d1a..f9c9b01f0d1a 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in1_slave_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in1_slave_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in2_master_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in2_master_regs.h index d96119b8c435..d96119b8c435 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in2_master_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in2_master_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in2_slave_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in2_slave_regs.h index c80d6817efe1..c80d6817efe1 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in2_slave_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in2_slave_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in3_master_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in3_master_regs.h index 753b31dc1760..753b31dc1760 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in3_master_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in3_master_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in3_slave_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in3_slave_regs.h index f68d043edcd9..f68d043edcd9 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in3_slave_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in3_slave_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in4_master_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in4_master_regs.h index a6dce326bd74..a6dce326bd74 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in4_master_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in4_master_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in4_slave_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in4_slave_regs.h index 5ace0f43cc78..5ace0f43cc78 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in4_slave_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_agu_in4_slave_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_base_addr_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_base_addr_regs.h index b375393dfdc0..b375393dfdc0 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_base_addr_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_base_addr_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_non_tensor_end_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_non_tensor_end_regs.h index 7c22b9383f3c..fb53feb0a1a6 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_non_tensor_end_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_non_tensor_end_regs.h @@ -20,8 +20,7 @@ ***************************************** */ -#define mmDCORE0_MME_CTRL_LO_ARCH_NON_TENSOR_END_CONV_KERNEL_SIZE_MINUS_1 \ -0x40CB280 +#define mmDCORE0_MME_CTRL_LO_ARCH_NON_TENSOR_END_CONV_KERNEL_SIZE_MINUS_1 0x40CB280 #define mmDCORE0_MME_CTRL_LO_ARCH_NON_TENSOR_END_CONV_LOW 0x40CB284 @@ -29,8 +28,7 @@ #define mmDCORE0_MME_CTRL_LO_ARCH_NON_TENSOR_END_OUTER_LOOP 0x40CB28C -#define mmDCORE0_MME_CTRL_LO_ARCH_NON_TENSOR_END_NUM_ITERATIONS_MINUS_1 \ -0x40CB290 +#define mmDCORE0_MME_CTRL_LO_ARCH_NON_TENSOR_END_NUM_ITERATIONS_MINUS_1 0x40CB290 #define mmDCORE0_MME_CTRL_LO_ARCH_NON_TENSOR_END_SB_REPEAT 0x40CB294 diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_non_tensor_start_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_non_tensor_start_regs.h index d17c165faf8b..d17c165faf8b 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_non_tensor_start_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_non_tensor_start_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_tensor_a_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_tensor_a_regs.h index 7b77884e0024..7b77884e0024 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_tensor_a_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_tensor_a_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_tensor_b_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_tensor_b_regs.h index a2a2ba454d6d..a2a2ba454d6d 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_tensor_b_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_tensor_b_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_tensor_cout_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_tensor_cout_regs.h index 7ad7b197cf87..7ad7b197cf87 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_tensor_cout_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_arch_tensor_cout_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_masks.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_masks.h index f699661d76aa..da0c94075e64 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_masks.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_masks.h @@ -78,8 +78,7 @@ #define DCORE0_MME_CTRL_LO_ARCH_SYNC_OBJ_DW0_MASTER_WAIT_SLAVE_FENCE_SHIFT 15 #define DCORE0_MME_CTRL_LO_ARCH_SYNC_OBJ_DW0_MASTER_WAIT_SLAVE_FENCE_MASK 0x8000 #define DCORE0_MME_CTRL_LO_ARCH_SYNC_OBJ_DW0_SLAVE_SEND_FENCE2MASTER_SHIFT 16 -#define DCORE0_MME_CTRL_LO_ARCH_SYNC_OBJ_DW0_SLAVE_SEND_FENCE2MASTER_MASK \ -0x10000 +#define DCORE0_MME_CTRL_LO_ARCH_SYNC_OBJ_DW0_SLAVE_SEND_FENCE2MASTER_MASK 0x10000 #define DCORE0_MME_CTRL_LO_ARCH_SYNC_OBJ_DW0_SLAVE_SIGNAL_EN_SHIFT 17 #define DCORE0_MME_CTRL_LO_ARCH_SYNC_OBJ_DW0_SLAVE_SIGNAL_EN_MASK 0x20000 #define DCORE0_MME_CTRL_LO_ARCH_SYNC_OBJ_DW0_SLAVE0_USE_SLV_ADR_SHIFT 18 @@ -87,11 +86,9 @@ #define DCORE0_MME_CTRL_LO_ARCH_SYNC_OBJ_DW0_SLAVE1_USE_SLV_ADR_SHIFT 19 #define DCORE0_MME_CTRL_LO_ARCH_SYNC_OBJ_DW0_SLAVE1_USE_SLV_ADR_MASK 0x80000 #define DCORE0_MME_CTRL_LO_ARCH_SYNC_OBJ_DW0_SLAVE0_USE_MSTR_ADR_PLUS4_SHIFT 20 -#define DCORE0_MME_CTRL_LO_ARCH_SYNC_OBJ_DW0_SLAVE0_USE_MSTR_ADR_PLUS4_MASK \ -0x100000 +#define DCORE0_MME_CTRL_LO_ARCH_SYNC_OBJ_DW0_SLAVE0_USE_MSTR_ADR_PLUS4_MASK 0x100000 #define DCORE0_MME_CTRL_LO_ARCH_SYNC_OBJ_DW0_SLAVE1_USE_MSTR_ADR_PLUS4_SHIFT 21 -#define DCORE0_MME_CTRL_LO_ARCH_SYNC_OBJ_DW0_SLAVE1_USE_MSTR_ADR_PLUS4_MASK \ -0x200000 +#define DCORE0_MME_CTRL_LO_ARCH_SYNC_OBJ_DW0_SLAVE1_USE_MSTR_ADR_PLUS4_MASK 0x200000 /* DCORE0_MME_CTRL_LO_ARCH_SYNC_OBJ_ADDR0 */ #define DCORE0_MME_CTRL_LO_ARCH_SYNC_OBJ_ADDR0_V_SHIFT 0 diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_mme_axuser_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_mme_axuser_regs.h index a51617a6f1fb..a51617a6f1fb 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_mme_axuser_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_mme_axuser_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_regs.h index 1b91c9c13132..1b91c9c13132 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_ctrl_lo_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_arc_acp_eng_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_arc_acp_eng_regs.h index f702fe6e9365..f702fe6e9365 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_arc_acp_eng_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_arc_acp_eng_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_arc_aux_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_arc_aux_regs.h index 917f8ab88373..917f8ab88373 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_arc_aux_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_arc_aux_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_arc_dup_eng_axuser_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_arc_dup_eng_axuser_regs.h index c7ebaf73c51e..c7ebaf73c51e 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_arc_dup_eng_axuser_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_arc_dup_eng_axuser_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_arc_dup_eng_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_arc_dup_eng_regs.h index 61654e37335b..61654e37335b 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_arc_dup_eng_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_arc_dup_eng_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_axuser_nonsecured_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_axuser_nonsecured_regs.h index 32089b8250ed..32089b8250ed 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_axuser_nonsecured_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_axuser_nonsecured_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_axuser_secured_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_axuser_secured_regs.h index e168c1cc2a7d..e168c1cc2a7d 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_axuser_secured_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_axuser_secured_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_cgm_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_cgm_regs.h index 543aba18ef68..543aba18ef68 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_cgm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_cgm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_regs.h index c45583fcc2cf..c45583fcc2cf 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_qm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_sbte0_masks.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_sbte0_masks.h index 077ae5232790..077ae5232790 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_sbte0_masks.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_sbte0_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_sbte0_mstr_if_axuser_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_sbte0_mstr_if_axuser_regs.h index 211fa2c2c35b..211fa2c2c35b 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_sbte0_mstr_if_axuser_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_sbte0_mstr_if_axuser_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_wb0_mstr_if_axuser_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_wb0_mstr_if_axuser_regs.h index 374a01d2b8d5..374a01d2b8d5 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_mme_wb0_mstr_if_axuser_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_mme_wb0_mstr_if_axuser_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_rtr0_ctrl_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_rtr0_ctrl_regs.h index 22f4d6c805c5..22f4d6c805c5 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_rtr0_ctrl_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_rtr0_ctrl_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_rtr0_mstr_if_rr_prvt_hbw_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_rtr0_mstr_if_rr_prvt_hbw_regs.h index 3a7290b3a5c9..3a7290b3a5c9 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_rtr0_mstr_if_rr_prvt_hbw_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_rtr0_mstr_if_rr_prvt_hbw_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_rtr0_mstr_if_rr_prvt_lbw_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_rtr0_mstr_if_rr_prvt_lbw_regs.h index 5b52b88fee0f..5b52b88fee0f 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_rtr0_mstr_if_rr_prvt_lbw_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_rtr0_mstr_if_rr_prvt_lbw_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_rtr0_mstr_if_rr_shrd_hbw_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_rtr0_mstr_if_rr_shrd_hbw_regs.h index d9b3f5cd392b..d9b3f5cd392b 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_rtr0_mstr_if_rr_shrd_hbw_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_rtr0_mstr_if_rr_shrd_hbw_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_rtr0_mstr_if_rr_shrd_lbw_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_rtr0_mstr_if_rr_shrd_lbw_regs.h index 1bba940d3031..1bba940d3031 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_rtr0_mstr_if_rr_shrd_lbw_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_rtr0_mstr_if_rr_shrd_lbw_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_sync_mngr_glbl_masks.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_sync_mngr_glbl_masks.h index f21540501cdd..f21540501cdd 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_sync_mngr_glbl_masks.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_sync_mngr_glbl_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_sync_mngr_glbl_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_sync_mngr_glbl_regs.h index c3c4991e6660..c3c4991e6660 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_sync_mngr_glbl_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_sync_mngr_glbl_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_sync_mngr_mstr_if_axuser_masks.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_sync_mngr_mstr_if_axuser_masks.h index 76b273a41255..76b273a41255 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_sync_mngr_mstr_if_axuser_masks.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_sync_mngr_mstr_if_axuser_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_sync_mngr_mstr_if_axuser_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_sync_mngr_mstr_if_axuser_regs.h index 0bddc734329f..0bddc734329f 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_sync_mngr_mstr_if_axuser_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_sync_mngr_mstr_if_axuser_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_sync_mngr_objs_masks.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_sync_mngr_objs_masks.h index 3a5b27df0ab4..3a5b27df0ab4 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_sync_mngr_objs_masks.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_sync_mngr_objs_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_sync_mngr_objs_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_sync_mngr_objs_regs.h index 8f082a1c9b1b..8f082a1c9b1b 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_sync_mngr_objs_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_sync_mngr_objs_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_axuser_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_axuser_regs.h index 2d4a22680a23..2d4a22680a23 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_axuser_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_axuser_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_kernel_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_kernel_regs.h index cdab39debd2c..cdab39debd2c 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_kernel_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_kernel_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_kernel_tensor_0_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_kernel_tensor_0_regs.h index 4ef1c1edc5f7..4ef1c1edc5f7 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_kernel_tensor_0_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_kernel_tensor_0_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_masks.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_masks.h index cdecbd0f9d84..cdecbd0f9d84 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_masks.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_qm_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_qm_regs.h index 4cd9e26a150f..4cd9e26a150f 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_qm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_qm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_qm_sync_object_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_qm_sync_object_regs.h index 8da278a3f3fe..8da278a3f3fe 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_qm_sync_object_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_qm_sync_object_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_qm_tensor_0_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_qm_tensor_0_regs.h index 2e4ff06e4858..2e4ff06e4858 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_qm_tensor_0_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_qm_tensor_0_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_regs.h index 4d48f0c6880b..4d48f0c6880b 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_special_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_special_regs.h index 76ab8a1a7f31..76ab8a1a7f31 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_special_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_cfg_special_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_eml_busmon_0_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_eml_busmon_0_regs.h index f07da4a24f06..f07da4a24f06 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_eml_busmon_0_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_eml_busmon_0_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_eml_etf_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_eml_etf_regs.h index aee9cbc78c3d..aee9cbc78c3d 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_eml_etf_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_eml_etf_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_eml_funnel_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_eml_funnel_regs.h index dee670b666ee..dee670b666ee 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_eml_funnel_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_eml_funnel_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_eml_spmu_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_eml_spmu_regs.h index 580ae57476bd..580ae57476bd 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_eml_spmu_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_eml_spmu_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_eml_stm_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_eml_stm_regs.h index 91686c563fe5..91686c563fe5 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_eml_stm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_eml_stm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_qm_arc_aux_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_qm_arc_aux_regs.h index e007dabc5382..e007dabc5382 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_qm_arc_aux_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_qm_arc_aux_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_qm_axuser_nonsecured_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_qm_axuser_nonsecured_regs.h index 149b85f5f045..149b85f5f045 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_qm_axuser_nonsecured_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_qm_axuser_nonsecured_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_qm_cgm_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_qm_cgm_regs.h index d4aad1875ad6..d4aad1875ad6 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_qm_cgm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_qm_cgm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_qm_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_qm_regs.h index cca8683cbca1..cca8683cbca1 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_qm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_tpc0_qm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_axuser_dec_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_axuser_dec_regs.h index e68667cc795a..e68667cc795a 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_axuser_dec_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_axuser_dec_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_axuser_msix_abnrm_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_axuser_msix_abnrm_regs.h index f7ffdcbd1a76..f7ffdcbd1a76 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_axuser_msix_abnrm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_axuser_msix_abnrm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_axuser_msix_l2c_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_axuser_msix_l2c_regs.h index 4c1bb5306cba..4c1bb5306cba 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_axuser_msix_l2c_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_axuser_msix_l2c_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_axuser_msix_nrm_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_axuser_msix_nrm_regs.h index e413905ffe25..e413905ffe25 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_axuser_msix_nrm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_axuser_msix_nrm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_axuser_msix_vcd_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_axuser_msix_vcd_regs.h index bce75ac6e279..bce75ac6e279 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_axuser_msix_vcd_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_axuser_msix_vcd_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_masks.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_masks.h index 68dd98459c86..1c02f3dfdb6e 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_masks.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_masks.h @@ -106,8 +106,7 @@ #define DCORE0_VDEC0_BRDG_CTRL_HBW_AXI_VIOL_CAUSE_AWBURST_VIOL_SHIFT 2 #define DCORE0_VDEC0_BRDG_CTRL_HBW_AXI_VIOL_CAUSE_AWBURST_VIOL_MASK 0x4 #define DCORE0_VDEC0_BRDG_CTRL_HBW_AXI_VIOL_CAUSE_AWADDR_SIZE_ALIGN_VIOL_SHIFT 3 -#define DCORE0_VDEC0_BRDG_CTRL_HBW_AXI_VIOL_CAUSE_AWADDR_SIZE_ALIGN_VIOL_MASK \ -0x8 +#define DCORE0_VDEC0_BRDG_CTRL_HBW_AXI_VIOL_CAUSE_AWADDR_SIZE_ALIGN_VIOL_MASK 0x8 #define DCORE0_VDEC0_BRDG_CTRL_HBW_AXI_VIOL_CAUSE_AWSIZE_VIOL_SHIFT 4 #define DCORE0_VDEC0_BRDG_CTRL_HBW_AXI_VIOL_CAUSE_AWSIZE_VIOL_MASK 0x10 #define DCORE0_VDEC0_BRDG_CTRL_HBW_AXI_VIOL_CAUSE_ARLEN_GT_31_SHIFT 5 @@ -117,8 +116,7 @@ #define DCORE0_VDEC0_BRDG_CTRL_HBW_AXI_VIOL_CAUSE_ARBURST_VIOL_SHIFT 7 #define DCORE0_VDEC0_BRDG_CTRL_HBW_AXI_VIOL_CAUSE_ARBURST_VIOL_MASK 0x80 #define DCORE0_VDEC0_BRDG_CTRL_HBW_AXI_VIOL_CAUSE_ARADDR_SIZE_ALIGN_VIOL_SHIFT 8 -#define DCORE0_VDEC0_BRDG_CTRL_HBW_AXI_VIOL_CAUSE_ARADDR_SIZE_ALIGN_VIOL_MASK \ -0x100 +#define DCORE0_VDEC0_BRDG_CTRL_HBW_AXI_VIOL_CAUSE_ARADDR_SIZE_ALIGN_VIOL_MASK 0x100 #define DCORE0_VDEC0_BRDG_CTRL_HBW_AXI_VIOL_CAUSE_ARSIZE_VIOL_SHIFT 9 #define DCORE0_VDEC0_BRDG_CTRL_HBW_AXI_VIOL_CAUSE_ARSIZE_VIOL_MASK 0x200 diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_regs.h index d2844307a6bf..d2844307a6bf 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_brdg_ctrl_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_ctrl_special_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_ctrl_special_regs.h index 89b522b12998..89b522b12998 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_ctrl_special_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore0_vdec0_ctrl_special_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore1_mme_ctrl_lo_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore1_mme_ctrl_lo_regs.h index 622613dc76fb..622613dc76fb 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore1_mme_ctrl_lo_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore1_mme_ctrl_lo_regs.h diff --git a/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore1_sync_mngr_glbl_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore1_sync_mngr_glbl_regs.h new file mode 100644 index 000000000000..3d3802755814 --- /dev/null +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore1_sync_mngr_glbl_regs.h @@ -0,0 +1,1203 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright 2016-2020 HabanaLabs, Ltd. + * All Rights Reserved. + * + */ + +/************************************ + ** This is an auto-generated file ** + ** DO NOT EDIT BELOW ** + ************************************/ + +#ifndef ASIC_REG_DCORE1_SYNC_MNGR_GLBL_REGS_H_ +#define ASIC_REG_DCORE1_SYNC_MNGR_GLBL_REGS_H_ + +/* + ***************************************** + * DCORE1_SYNC_MNGR_GLBL + * (Prototype: SOB_GLBL) + ***************************************** + */ + +#define mmDCORE1_SYNC_MNGR_GLBL_SM_SEI_MASK 0x431E000 + +#define mmDCORE1_SYNC_MNGR_GLBL_SM_SEI_CAUSE 0x431E004 + +#define mmDCORE1_SYNC_MNGR_GLBL_L2H_CPMR_L 0x431E008 + +#define mmDCORE1_SYNC_MNGR_GLBL_L2H_CPMR_H 0x431E00C + +#define mmDCORE1_SYNC_MNGR_GLBL_L2H_MASK_L 0x431E020 + +#define mmDCORE1_SYNC_MNGR_GLBL_L2H_MASK_H 0x431E024 + +#define mmDCORE1_SYNC_MNGR_GLBL_ASID_SEC 0x431E030 + +#define mmDCORE1_SYNC_MNGR_GLBL_ASID_PRIV_ONLY 0x431E034 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DELAY 0x431E038 + +#define mmDCORE1_SYNC_MNGR_GLBL_PI_SIZE 0x431E03C + +#define mmDCORE1_SYNC_MNGR_GLBL_SOB_ONLY 0x431E040 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INTR 0x431E044 + +#define mmDCORE1_SYNC_MNGR_GLBL_ASID_NONE_SEC_PRIV 0x431E048 + +#define mmDCORE1_SYNC_MNGR_GLBL_PI_INC_MODE_SIZE 0x431E04C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_0 0x431E050 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_1 0x431E054 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_2 0x431E058 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_3 0x431E05C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_4 0x431E060 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_5 0x431E064 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_6 0x431E068 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_7 0x431E06C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_8 0x431E070 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_9 0x431E074 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_10 0x431E078 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_11 0x431E07C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_12 0x431E080 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_13 0x431E084 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_14 0x431E088 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_15 0x431E08C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_16 0x431E090 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_17 0x431E094 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_18 0x431E098 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_19 0x431E09C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_20 0x431E0A0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_21 0x431E0A4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_22 0x431E0A8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_23 0x431E0AC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_24 0x431E0B0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_25 0x431E0B4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_26 0x431E0B8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_27 0x431E0BC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_28 0x431E0C0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_29 0x431E0C4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_30 0x431E0C8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_31 0x431E0CC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_32 0x431E0D0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_33 0x431E0D4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_34 0x431E0D8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_35 0x431E0DC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_36 0x431E0E0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_37 0x431E0E4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_38 0x431E0E8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_39 0x431E0EC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_40 0x431E0F0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_41 0x431E0F4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_42 0x431E0F8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_43 0x431E0FC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_44 0x431E100 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_45 0x431E104 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_46 0x431E108 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_47 0x431E10C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_48 0x431E110 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_49 0x431E114 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_50 0x431E118 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_51 0x431E11C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_52 0x431E120 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_53 0x431E124 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_54 0x431E128 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_55 0x431E12C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_56 0x431E130 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_57 0x431E134 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_58 0x431E138 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_59 0x431E13C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_60 0x431E140 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_61 0x431E144 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_62 0x431E148 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_L_63 0x431E14C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_0 0x431E150 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_1 0x431E154 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_2 0x431E158 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_3 0x431E15C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_4 0x431E160 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_5 0x431E164 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_6 0x431E168 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_7 0x431E16C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_8 0x431E170 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_9 0x431E174 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_10 0x431E178 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_11 0x431E17C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_12 0x431E180 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_13 0x431E184 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_14 0x431E188 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_15 0x431E18C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_16 0x431E190 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_17 0x431E194 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_18 0x431E198 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_19 0x431E19C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_20 0x431E1A0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_21 0x431E1A4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_22 0x431E1A8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_23 0x431E1AC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_24 0x431E1B0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_25 0x431E1B4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_26 0x431E1B8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_27 0x431E1BC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_28 0x431E1C0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_29 0x431E1C4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_30 0x431E1C8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_31 0x431E1CC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_32 0x431E1D0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_33 0x431E1D4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_34 0x431E1D8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_35 0x431E1DC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_36 0x431E1E0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_37 0x431E1E4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_38 0x431E1E8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_39 0x431E1EC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_40 0x431E1F0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_41 0x431E1F4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_42 0x431E1F8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_43 0x431E1FC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_44 0x431E200 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_45 0x431E204 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_46 0x431E208 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_47 0x431E20C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_48 0x431E210 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_49 0x431E214 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_50 0x431E218 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_51 0x431E21C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_52 0x431E220 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_53 0x431E224 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_54 0x431E228 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_55 0x431E22C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_56 0x431E230 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_57 0x431E234 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_58 0x431E238 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_59 0x431E23C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_60 0x431E240 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_61 0x431E244 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_62 0x431E248 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_BASE_ADDR_H_63 0x431E24C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_0 0x431E250 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_1 0x431E254 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_2 0x431E258 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_3 0x431E25C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_4 0x431E260 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_5 0x431E264 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_6 0x431E268 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_7 0x431E26C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_8 0x431E270 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_9 0x431E274 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_10 0x431E278 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_11 0x431E27C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_12 0x431E280 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_13 0x431E284 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_14 0x431E288 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_15 0x431E28C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_16 0x431E290 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_17 0x431E294 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_18 0x431E298 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_19 0x431E29C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_20 0x431E2A0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_21 0x431E2A4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_22 0x431E2A8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_23 0x431E2AC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_24 0x431E2B0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_25 0x431E2B4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_26 0x431E2B8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_27 0x431E2BC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_28 0x431E2C0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_29 0x431E2C4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_30 0x431E2C8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_31 0x431E2CC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_32 0x431E2D0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_33 0x431E2D4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_34 0x431E2D8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_35 0x431E2DC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_36 0x431E2E0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_37 0x431E2E4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_38 0x431E2E8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_39 0x431E2EC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_40 0x431E2F0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_41 0x431E2F4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_42 0x431E2F8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_43 0x431E2FC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_44 0x431E300 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_45 0x431E304 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_46 0x431E308 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_47 0x431E30C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_48 0x431E310 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_49 0x431E314 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_50 0x431E318 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_51 0x431E31C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_52 0x431E320 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_53 0x431E324 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_54 0x431E328 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_55 0x431E32C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_56 0x431E330 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_57 0x431E334 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_58 0x431E338 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_59 0x431E33C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_60 0x431E340 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_61 0x431E344 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_62 0x431E348 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SIZE_LOG2_63 0x431E34C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_0 0x431E350 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_1 0x431E354 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_2 0x431E358 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_3 0x431E35C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_4 0x431E360 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_5 0x431E364 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_6 0x431E368 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_7 0x431E36C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_8 0x431E370 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_9 0x431E374 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_10 0x431E378 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_11 0x431E37C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_12 0x431E380 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_13 0x431E384 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_14 0x431E388 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_15 0x431E38C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_16 0x431E390 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_17 0x431E394 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_18 0x431E398 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_19 0x431E39C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_20 0x431E3A0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_21 0x431E3A4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_22 0x431E3A8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_23 0x431E3AC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_24 0x431E3B0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_25 0x431E3B4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_26 0x431E3B8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_27 0x431E3BC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_28 0x431E3C0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_29 0x431E3C4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_30 0x431E3C8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_31 0x431E3CC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_32 0x431E3D0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_33 0x431E3D4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_34 0x431E3D8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_35 0x431E3DC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_36 0x431E3E0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_37 0x431E3E4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_38 0x431E3E8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_39 0x431E3EC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_40 0x431E3F0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_41 0x431E3F4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_42 0x431E3F8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_43 0x431E3FC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_44 0x431E400 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_45 0x431E404 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_46 0x431E408 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_47 0x431E40C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_48 0x431E410 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_49 0x431E414 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_50 0x431E418 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_51 0x431E41C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_52 0x431E420 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_53 0x431E424 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_54 0x431E428 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_55 0x431E42C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_56 0x431E430 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_57 0x431E434 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_58 0x431E438 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_59 0x431E43C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_60 0x431E440 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_61 0x431E444 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_62 0x431E448 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_PI_63 0x431E44C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_0 0x431E450 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_1 0x431E454 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_2 0x431E458 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_3 0x431E45C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_4 0x431E460 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_5 0x431E464 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_6 0x431E468 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_7 0x431E46C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_8 0x431E470 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_9 0x431E474 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_10 0x431E478 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_11 0x431E47C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_12 0x431E480 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_13 0x431E484 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_14 0x431E488 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_15 0x431E48C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_16 0x431E490 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_17 0x431E494 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_18 0x431E498 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_19 0x431E49C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_20 0x431E4A0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_21 0x431E4A4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_22 0x431E4A8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_23 0x431E4AC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_24 0x431E4B0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_25 0x431E4B4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_26 0x431E4B8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_27 0x431E4BC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_28 0x431E4C0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_29 0x431E4C4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_30 0x431E4C8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_31 0x431E4CC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_32 0x431E4D0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_33 0x431E4D4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_34 0x431E4D8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_35 0x431E4DC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_36 0x431E4E0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_37 0x431E4E4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_38 0x431E4E8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_39 0x431E4EC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_40 0x431E4F0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_41 0x431E4F4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_42 0x431E4F8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_43 0x431E4FC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_44 0x431E500 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_45 0x431E504 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_46 0x431E508 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_47 0x431E50C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_48 0x431E510 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_49 0x431E514 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_50 0x431E518 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_51 0x431E51C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_52 0x431E520 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_53 0x431E524 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_54 0x431E528 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_55 0x431E52C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_56 0x431E530 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_57 0x431E534 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_58 0x431E538 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_59 0x431E53C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_60 0x431E540 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_61 0x431E544 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_62 0x431E548 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_SEC_63 0x431E54C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_0 0x431E550 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_1 0x431E554 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_2 0x431E558 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_3 0x431E55C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_4 0x431E560 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_5 0x431E564 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_6 0x431E568 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_7 0x431E56C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_8 0x431E570 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_9 0x431E574 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_10 0x431E578 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_11 0x431E57C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_12 0x431E580 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_13 0x431E584 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_14 0x431E588 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_15 0x431E58C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_16 0x431E590 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_17 0x431E594 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_18 0x431E598 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_19 0x431E59C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_20 0x431E5A0 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_21 0x431E5A4 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_22 0x431E5A8 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_23 0x431E5AC + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_24 0x431E5B0 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_25 0x431E5B4 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_26 0x431E5B8 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_27 0x431E5BC + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_28 0x431E5C0 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_29 0x431E5C4 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_30 0x431E5C8 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_31 0x431E5CC + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_32 0x431E5D0 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_33 0x431E5D4 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_34 0x431E5D8 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_35 0x431E5DC + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_36 0x431E5E0 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_37 0x431E5E4 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_38 0x431E5E8 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_39 0x431E5EC + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_40 0x431E5F0 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_41 0x431E5F4 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_42 0x431E5F8 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_43 0x431E5FC + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_44 0x431E600 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_45 0x431E604 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_46 0x431E608 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_47 0x431E60C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_48 0x431E610 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_49 0x431E614 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_50 0x431E618 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_51 0x431E61C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_52 0x431E620 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_53 0x431E624 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_54 0x431E628 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_55 0x431E62C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_56 0x431E630 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_57 0x431E634 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_58 0x431E638 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_59 0x431E63C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_60 0x431E640 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_61 0x431E644 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_62 0x431E648 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_L_63 0x431E64C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_0 0x431E650 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_1 0x431E654 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_2 0x431E658 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_3 0x431E65C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_4 0x431E660 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_5 0x431E664 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_6 0x431E668 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_7 0x431E66C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_8 0x431E670 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_9 0x431E674 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_10 0x431E678 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_11 0x431E67C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_12 0x431E680 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_13 0x431E684 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_14 0x431E688 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_15 0x431E68C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_16 0x431E690 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_17 0x431E694 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_18 0x431E698 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_19 0x431E69C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_20 0x431E6A0 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_21 0x431E6A4 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_22 0x431E6A8 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_23 0x431E6AC + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_24 0x431E6B0 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_25 0x431E6B4 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_26 0x431E6B8 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_27 0x431E6BC + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_28 0x431E6C0 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_29 0x431E6C4 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_30 0x431E6C8 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_31 0x431E6CC + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_32 0x431E6D0 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_33 0x431E6D4 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_34 0x431E6D8 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_35 0x431E6DC + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_36 0x431E6E0 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_37 0x431E6E4 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_38 0x431E6E8 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_39 0x431E6EC + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_40 0x431E6F0 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_41 0x431E6F4 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_42 0x431E6F8 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_43 0x431E6FC + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_44 0x431E700 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_45 0x431E704 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_46 0x431E708 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_47 0x431E70C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_48 0x431E710 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_49 0x431E714 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_50 0x431E718 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_51 0x431E71C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_52 0x431E720 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_53 0x431E724 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_54 0x431E728 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_55 0x431E72C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_56 0x431E730 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_57 0x431E734 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_58 0x431E738 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_59 0x431E73C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_60 0x431E740 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_61 0x431E744 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_62 0x431E748 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_ADDR_H_63 0x431E74C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_0 0x431E750 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_1 0x431E754 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_2 0x431E758 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_3 0x431E75C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_4 0x431E760 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_5 0x431E764 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_6 0x431E768 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_7 0x431E76C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_8 0x431E770 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_9 0x431E774 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_10 0x431E778 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_11 0x431E77C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_12 0x431E780 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_13 0x431E784 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_14 0x431E788 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_15 0x431E78C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_16 0x431E790 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_17 0x431E794 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_18 0x431E798 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_19 0x431E79C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_20 0x431E7A0 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_21 0x431E7A4 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_22 0x431E7A8 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_23 0x431E7AC + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_24 0x431E7B0 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_25 0x431E7B4 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_26 0x431E7B8 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_27 0x431E7BC + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_28 0x431E7C0 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_29 0x431E7C4 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_30 0x431E7C8 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_31 0x431E7CC + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_32 0x431E7D0 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_33 0x431E7D4 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_34 0x431E7D8 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_35 0x431E7DC + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_36 0x431E7E0 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_37 0x431E7E4 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_38 0x431E7E8 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_39 0x431E7EC + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_40 0x431E7F0 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_41 0x431E7F4 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_42 0x431E7F8 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_43 0x431E7FC + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_44 0x431E800 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_45 0x431E804 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_46 0x431E808 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_47 0x431E80C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_48 0x431E810 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_49 0x431E814 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_50 0x431E818 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_51 0x431E81C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_52 0x431E820 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_53 0x431E824 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_54 0x431E828 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_55 0x431E82C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_56 0x431E830 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_57 0x431E834 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_58 0x431E838 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_59 0x431E83C + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_60 0x431E840 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_61 0x431E844 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_62 0x431E848 + +#define mmDCORE1_SYNC_MNGR_GLBL_LBW_DATA_63 0x431E84C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_0 0x431E850 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_1 0x431E854 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_2 0x431E858 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_3 0x431E85C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_4 0x431E860 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_5 0x431E864 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_6 0x431E868 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_7 0x431E86C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_8 0x431E870 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_9 0x431E874 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_10 0x431E878 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_11 0x431E87C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_12 0x431E880 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_13 0x431E884 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_14 0x431E888 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_15 0x431E88C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_16 0x431E890 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_17 0x431E894 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_18 0x431E898 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_19 0x431E89C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_20 0x431E8A0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_21 0x431E8A4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_22 0x431E8A8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_23 0x431E8AC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_24 0x431E8B0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_25 0x431E8B4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_26 0x431E8B8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_27 0x431E8BC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_28 0x431E8C0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_29 0x431E8C4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_30 0x431E8C8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_31 0x431E8CC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_32 0x431E8D0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_33 0x431E8D4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_34 0x431E8D8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_35 0x431E8DC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_36 0x431E8E0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_37 0x431E8E4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_38 0x431E8E8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_39 0x431E8EC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_40 0x431E8F0 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_41 0x431E8F4 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_42 0x431E8F8 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_43 0x431E8FC + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_44 0x431E900 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_45 0x431E904 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_46 0x431E908 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_47 0x431E90C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_48 0x431E910 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_49 0x431E914 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_50 0x431E918 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_51 0x431E91C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_52 0x431E920 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_53 0x431E924 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_54 0x431E928 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_55 0x431E92C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_56 0x431E930 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_57 0x431E934 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_58 0x431E938 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_59 0x431E93C + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_60 0x431E940 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_61 0x431E944 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_62 0x431E948 + +#define mmDCORE1_SYNC_MNGR_GLBL_CQ_INC_MODE_63 0x431E94C + +#endif /* ASIC_REG_DCORE1_SYNC_MNGR_GLBL_REGS_H_ */ diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore3_mme_ctrl_lo_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore3_mme_ctrl_lo_regs.h index b06469f5a279..b06469f5a279 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/dcore3_mme_ctrl_lo_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/dcore3_mme_ctrl_lo_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/gaudi2_blocks_linux_driver.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/gaudi2_blocks_linux_driver.h index 3caee4515ad6..3caee4515ad6 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/gaudi2_blocks_linux_driver.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/gaudi2_blocks_linux_driver.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/gaudi2_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/gaudi2_regs.h index 6aa1b1412462..0bf3092bfeea 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/gaudi2_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/gaudi2_regs.h @@ -31,6 +31,7 @@ #include "dcore0_sync_mngr_objs_regs.h" #include "dcore0_sync_mngr_glbl_regs.h" #include "dcore0_sync_mngr_mstr_if_axuser_regs.h" +#include "dcore1_sync_mngr_glbl_regs.h" #include "pdma0_qm_arc_aux_regs.h" #include "pdma0_core_ctx_regs.h" #include "pdma0_core_regs.h" diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/nic0_qm0_cgm_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/nic0_qm0_cgm_regs.h index d49906a68511..d49906a68511 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/nic0_qm0_cgm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/nic0_qm0_cgm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/nic0_qm0_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/nic0_qm0_regs.h index acb19c1cd4bd..acb19c1cd4bd 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/nic0_qm0_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/nic0_qm0_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/nic0_qm_arc_aux0_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/nic0_qm_arc_aux0_regs.h index 5f380a44dd21..5f380a44dd21 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/nic0_qm_arc_aux0_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/nic0_qm_arc_aux0_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/nic0_qpc0_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/nic0_qpc0_regs.h index eaee29da4244..eaee29da4244 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/nic0_qpc0_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/nic0_qpc0_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/nic0_umr0_0_completion_queue_ci_1_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/nic0_umr0_0_completion_queue_ci_1_regs.h index 2153319a50a0..2153319a50a0 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/nic0_umr0_0_completion_queue_ci_1_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/nic0_umr0_0_completion_queue_ci_1_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/nic0_umr0_0_unsecure_doorbell0_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/nic0_umr0_0_unsecure_doorbell0_regs.h index de8eac74c2fb..de8eac74c2fb 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/nic0_umr0_0_unsecure_doorbell0_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/nic0_umr0_0_unsecure_doorbell0_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_aux_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_aux_regs.h index 44182fc18234..44182fc18234 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_aux_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_aux_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_dbi_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_dbi_regs.h index cc5842ec6ceb..2ee79d8e62d0 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_dbi_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_dbi_regs.h @@ -48,8 +48,7 @@ #define mmPCIE_DBI_PCI_CAP_PTR_REG 0x4C02034 -#define mmPCIE_DBI_MAX_LATENCY_MIN_GRANT_INTERRUPT_PIN_INTERRUPT_LINE_REG \ -0x4C0203C +#define mmPCIE_DBI_MAX_LATENCY_MIN_GRANT_INTERRUPT_PIN_INTERRUPT_LINE_REG 0x4C0203C #define mmPCIE_DBI_CAP_ID_NXT_PTR_REG 0x4C02040 diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_dec0_cmd_masks.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_dec0_cmd_masks.h index 2b5af010c7a5..2b5af010c7a5 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_dec0_cmd_masks.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_dec0_cmd_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_dec0_cmd_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_dec0_cmd_regs.h index dc7d3f6a4b50..dc7d3f6a4b50 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_dec0_cmd_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_dec0_cmd_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_axuser_dec_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_axuser_dec_regs.h index 242c6525bd71..242c6525bd71 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_axuser_dec_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_axuser_dec_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_axuser_msix_abnrm_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_axuser_msix_abnrm_regs.h index 98d035463561..98d035463561 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_axuser_msix_abnrm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_axuser_msix_abnrm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_axuser_msix_l2c_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_axuser_msix_l2c_regs.h index 33ef37619417..33ef37619417 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_axuser_msix_l2c_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_axuser_msix_l2c_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_axuser_msix_nrm_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_axuser_msix_nrm_regs.h index c4587d5d6406..c4587d5d6406 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_axuser_msix_nrm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_axuser_msix_nrm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_axuser_msix_vcd_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_axuser_msix_vcd_regs.h index 35349ad375d0..35349ad375d0 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_axuser_msix_vcd_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_axuser_msix_vcd_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_masks.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_masks.h index d29837883216..7a96aebf08b3 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_masks.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_masks.h @@ -116,8 +116,7 @@ #define PCIE_VDEC0_BRDG_CTRL_HBW_AXI_VIOL_CAUSE_ARBURST_VIOL_SHIFT 7 #define PCIE_VDEC0_BRDG_CTRL_HBW_AXI_VIOL_CAUSE_ARBURST_VIOL_MASK 0x80 #define PCIE_VDEC0_BRDG_CTRL_HBW_AXI_VIOL_CAUSE_ARADDR_SIZE_ALIGN_VIOL_SHIFT 8 -#define PCIE_VDEC0_BRDG_CTRL_HBW_AXI_VIOL_CAUSE_ARADDR_SIZE_ALIGN_VIOL_MASK \ -0x100 +#define PCIE_VDEC0_BRDG_CTRL_HBW_AXI_VIOL_CAUSE_ARADDR_SIZE_ALIGN_VIOL_MASK 0x100 #define PCIE_VDEC0_BRDG_CTRL_HBW_AXI_VIOL_CAUSE_ARSIZE_VIOL_SHIFT 9 #define PCIE_VDEC0_BRDG_CTRL_HBW_AXI_VIOL_CAUSE_ARSIZE_VIOL_MASK 0x200 diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_regs.h index c7badd212f2b..c7badd212f2b 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_brdg_ctrl_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_ctrl_special_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_ctrl_special_regs.h index 491b0cd935af..491b0cd935af 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_ctrl_special_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_vdec0_ctrl_special_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_wrap_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_wrap_regs.h index a09422f2f281..a09422f2f281 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_wrap_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_wrap_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_wrap_special_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_wrap_special_regs.h index 46558e7a7f63..46558e7a7f63 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pcie_wrap_special_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_wrap_special_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pdma0_core_ctx_axuser_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pdma0_core_ctx_axuser_regs.h index bacbe4c6fc3c..bacbe4c6fc3c 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pdma0_core_ctx_axuser_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pdma0_core_ctx_axuser_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pdma0_core_ctx_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pdma0_core_ctx_regs.h index 02b57f07cfaf..02b57f07cfaf 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pdma0_core_ctx_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pdma0_core_ctx_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pdma0_core_masks.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pdma0_core_masks.h index 909cda03c246..909cda03c246 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pdma0_core_masks.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pdma0_core_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pdma0_core_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pdma0_core_regs.h index 84079b5077e2..84079b5077e2 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pdma0_core_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pdma0_core_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pdma0_core_special_masks.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pdma0_core_special_masks.h index 15d257e3830e..15d257e3830e 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pdma0_core_special_masks.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pdma0_core_special_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pdma0_qm_arc_aux_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pdma0_qm_arc_aux_regs.h index 9b1cb609d134..9b1cb609d134 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pdma0_qm_arc_aux_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pdma0_qm_arc_aux_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pdma0_qm_axuser_nonsecured_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pdma0_qm_axuser_nonsecured_regs.h index d2e0756ec5f2..d2e0756ec5f2 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pdma0_qm_axuser_nonsecured_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pdma0_qm_axuser_nonsecured_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pdma0_qm_axuser_secured_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pdma0_qm_axuser_secured_regs.h index 8bf0516b83f7..8bf0516b83f7 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pdma0_qm_axuser_secured_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pdma0_qm_axuser_secured_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pdma0_qm_cgm_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pdma0_qm_cgm_regs.h index 96c0ce176e73..96c0ce176e73 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pdma0_qm_cgm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pdma0_qm_cgm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pdma0_qm_masks.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pdma0_qm_masks.h index b79cae8f5571..b79cae8f5571 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pdma0_qm_masks.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pdma0_qm_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pdma0_qm_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pdma0_qm_regs.h index 77d803c938d4..77d803c938d4 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pdma0_qm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pdma0_qm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pdma1_core_ctx_axuser_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pdma1_core_ctx_axuser_regs.h index ccc6dfd22dd7..ccc6dfd22dd7 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pdma1_core_ctx_axuser_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pdma1_core_ctx_axuser_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pdma1_qm_axuser_nonsecured_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pdma1_qm_axuser_nonsecured_regs.h index 5fd72d050fff..5fd72d050fff 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pdma1_qm_axuser_nonsecured_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pdma1_qm_axuser_nonsecured_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pmmu_hbw_stlb_masks.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pmmu_hbw_stlb_masks.h index 0276506ea523..b4f32632cd36 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pmmu_hbw_stlb_masks.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pmmu_hbw_stlb_masks.h @@ -228,8 +228,7 @@ /* PMMU_HBW_STLB_RANGE_CACHE_INVALIDATION */ #define PMMU_HBW_STLB_RANGE_CACHE_INVALIDATION_RANGE_INVALIDATION_ENABLE_SHIFT 0 -#define PMMU_HBW_STLB_RANGE_CACHE_INVALIDATION_RANGE_INVALIDATION_ENABLE_MASK \ -0x1 +#define PMMU_HBW_STLB_RANGE_CACHE_INVALIDATION_RANGE_INVALIDATION_ENABLE_MASK 0x1 #define PMMU_HBW_STLB_RANGE_CACHE_INVALIDATION_INVALIDATION_ASID_EN_SHIFT 1 #define PMMU_HBW_STLB_RANGE_CACHE_INVALIDATION_INVALIDATION_ASID_EN_MASK 0x2 #define PMMU_HBW_STLB_RANGE_CACHE_INVALIDATION_INVALIDATION_ASID_SHIFT 2 diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pmmu_hbw_stlb_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pmmu_hbw_stlb_regs.h index 87c66c08e24a..87c66c08e24a 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pmmu_hbw_stlb_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pmmu_hbw_stlb_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pmmu_pif_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pmmu_pif_regs.h index dd12793734b4..dd12793734b4 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/pmmu_pif_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/pmmu_pif_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/psoc_etr_masks.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/psoc_etr_masks.h index 42e67c1059c4..42e67c1059c4 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/psoc_etr_masks.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/psoc_etr_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/psoc_etr_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/psoc_etr_regs.h index 980a3e0054c5..980a3e0054c5 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/psoc_etr_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/psoc_etr_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/psoc_global_conf_masks.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/psoc_global_conf_masks.h index 9be3d656da3a..85a81e2cb546 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/psoc_global_conf_masks.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/psoc_global_conf_masks.h @@ -1306,11 +1306,9 @@ #define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL0_ADDR_EXTMEM_PC_LOC2_SHIFT 12 #define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL0_ADDR_EXTMEM_PC_LOC2_MASK 0x3F000 #define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL0_ADDR_EXTMEM_PC_LOC3_SHIFT 18 -#define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL0_ADDR_EXTMEM_PC_LOC3_MASK \ -0xFC0000 +#define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL0_ADDR_EXTMEM_PC_LOC3_MASK 0xFC0000 #define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL0_ADDR_EXTMEM_HBM_LOC0_SHIFT 24 -#define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL0_ADDR_EXTMEM_HBM_LOC0_MASK \ -0x3F000000 +#define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL0_ADDR_EXTMEM_HBM_LOC0_MASK 0x3F000000 /* PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL1 */ #define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL1_ADDR_EXTMEM_HBM_LOC1_SHIFT 0 @@ -1322,24 +1320,17 @@ #define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL1_NON_LIN_HBM_CNT_EN_SHIFT 13 #define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL1_NON_LIN_HBM_CNT_EN_MASK 0x2000 #define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL1_NON_LIN_HBM_ALL_ADDR_EN_SHIFT 14 -#define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL1_NON_LIN_HBM_ALL_ADDR_EN_MASK \ -0x4000 -#define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL1_NON_LIN_HBM_ALL_ADDR_MASK_SHIFT \ -16 -#define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL1_NON_LIN_HBM_ALL_ADDR_MASK_MASK \ -0xFF0000 +#define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL1_NON_LIN_HBM_ALL_ADDR_EN_MASK 0x4000 +#define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL1_NON_LIN_HBM_ALL_ADDR_MASK_SHIFT 16 +#define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL1_NON_LIN_HBM_ALL_ADDR_MASK_MASK 0xFF0000 #define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL1_HBM_NUM_SHIFT 24 #define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL1_HBM_NUM_MASK 0x7000000 /* PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL2 */ -#define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL2_SCRAM_NONLIN_HBM_CNT_MASK_SHIFT \ -0 -#define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL2_SCRAM_NONLIN_HBM_CNT_MASK_MASK \ -0xFFFF -#define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL2_SCRAM_NONLIN_EXTM_PC_MASK_SHIFT \ -16 -#define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL2_SCRAM_NONLIN_EXTM_PC_MASK_MASK \ -0xFFFF0000 +#define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL2_SCRAM_NONLIN_HBM_CNT_MASK_SHIFT 0 +#define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL2_SCRAM_NONLIN_HBM_CNT_MASK_MASK 0xFFFF +#define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL2_SCRAM_NONLIN_EXTM_PC_MASK_SHIFT 16 +#define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL2_SCRAM_NONLIN_EXTM_PC_MASK_MASK 0xFFFF0000 /* PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL3 */ #define PSOC_GLOBAL_CONF_AXI_DRAIN_NL_SRC_CTRL3_HBM_MAP0_SHIFT 0 diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/psoc_global_conf_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/psoc_global_conf_regs.h index 48980fa8e37b..48980fa8e37b 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/psoc_global_conf_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/psoc_global_conf_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/psoc_reset_conf_masks.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/psoc_reset_conf_masks.h index e0cf35226e7f..e0cf35226e7f 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/psoc_reset_conf_masks.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/psoc_reset_conf_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/psoc_reset_conf_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/psoc_reset_conf_regs.h index 6a89624f01d1..6a89624f01d1 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/psoc_reset_conf_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/psoc_reset_conf_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/psoc_timestamp_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/psoc_timestamp_regs.h index 699becc28887..699becc28887 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/psoc_timestamp_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/psoc_timestamp_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/rot0_desc_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/rot0_desc_regs.h index 79320320ebcb..79320320ebcb 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/rot0_desc_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/rot0_desc_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/rot0_masks.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/rot0_masks.h index f2e739ede3d9..f2e739ede3d9 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/rot0_masks.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/rot0_masks.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/rot0_qm_arc_aux_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/rot0_qm_arc_aux_regs.h index e83daa33d737..e83daa33d737 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/rot0_qm_arc_aux_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/rot0_qm_arc_aux_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/rot0_qm_axuser_nonsecured_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/rot0_qm_axuser_nonsecured_regs.h index 8e040a2ef1c1..8e040a2ef1c1 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/rot0_qm_axuser_nonsecured_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/rot0_qm_axuser_nonsecured_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/rot0_qm_cgm_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/rot0_qm_cgm_regs.h index 077ae2347a3d..077ae2347a3d 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/rot0_qm_cgm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/rot0_qm_cgm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/rot0_qm_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/rot0_qm_regs.h index de3c85510af2..de3c85510af2 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/rot0_qm_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/rot0_qm_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/rot0_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/rot0_regs.h index 7d85dc5559da..7d85dc5559da 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/rot0_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/rot0_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/xbar_edge_0_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/xbar_edge_0_regs.h index e8aebd7f5f85..e8aebd7f5f85 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/xbar_edge_0_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/xbar_edge_0_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/asic_reg/xbar_mid_0_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/xbar_mid_0_regs.h index 3d39d1a94851..3d39d1a94851 100644 --- a/drivers/misc/habanalabs/include/gaudi2/asic_reg/xbar_mid_0_regs.h +++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/xbar_mid_0_regs.h diff --git a/drivers/misc/habanalabs/include/gaudi2/gaudi2.h b/drivers/accel/habanalabs/include/gaudi2/gaudi2.h index 5b4f9e108798..5b4f9e108798 100644 --- a/drivers/misc/habanalabs/include/gaudi2/gaudi2.h +++ b/drivers/accel/habanalabs/include/gaudi2/gaudi2.h diff --git a/drivers/misc/habanalabs/include/gaudi2/gaudi2_async_events.h b/drivers/accel/habanalabs/include/gaudi2/gaudi2_async_events.h index 305b576222e6..50852cc80373 100644 --- a/drivers/misc/habanalabs/include/gaudi2/gaudi2_async_events.h +++ b/drivers/accel/habanalabs/include/gaudi2/gaudi2_async_events.h @@ -958,6 +958,7 @@ enum gaudi2_async_event_id { GAUDI2_EVENT_CPU11_STATUS_NIC11_ENG1 = 1318, GAUDI2_EVENT_ARC_DCCM_FULL = 1319, GAUDI2_EVENT_CPU_FP32_NOT_SUPPORTED = 1320, + GAUDI2_EVENT_DEV_RESET_REQ = 1321, GAUDI2_EVENT_SIZE, }; diff --git a/drivers/misc/habanalabs/include/gaudi2/gaudi2_async_ids_map_extended.h b/drivers/accel/habanalabs/include/gaudi2/gaudi2_async_ids_map_extended.h index d510cb10c883..82be01bea98e 100644 --- a/drivers/misc/habanalabs/include/gaudi2/gaudi2_async_ids_map_extended.h +++ b/drivers/accel/habanalabs/include/gaudi2/gaudi2_async_ids_map_extended.h @@ -2665,6 +2665,8 @@ static struct gaudi2_async_events_ids_map gaudi2_irq_map_table[] = { .msg = 1, .reset = 0, .name = "ARC_DCCM_FULL" }, { .fc_id = 1320, .cpu_id = 626, .valid = 1, .msg = 1, .reset = 1, .name = "FP32_NOT_SUPPORTED" }, + { .fc_id = 1321, .cpu_id = 627, .valid = 1, + .msg = 1, .reset = 1, .name = "DEV_RESET_REQ" }, }; #endif /* __GAUDI2_ASYNC_IDS_MAP_EVENTS_EXT_H_ */ diff --git a/drivers/misc/habanalabs/include/gaudi2/gaudi2_coresight.h b/drivers/accel/habanalabs/include/gaudi2/gaudi2_coresight.h index 14f09d7758c7..14f09d7758c7 100644 --- a/drivers/misc/habanalabs/include/gaudi2/gaudi2_coresight.h +++ b/drivers/accel/habanalabs/include/gaudi2/gaudi2_coresight.h diff --git a/drivers/misc/habanalabs/include/gaudi2/gaudi2_fw_if.h b/drivers/accel/habanalabs/include/gaudi2/gaudi2_fw_if.h index e4a7d5725096..82f3ca2a3966 100644 --- a/drivers/misc/habanalabs/include/gaudi2/gaudi2_fw_if.h +++ b/drivers/accel/habanalabs/include/gaudi2/gaudi2_fw_if.h @@ -20,22 +20,25 @@ #define GAUDI2_NUM_MME 4 +#define NUM_OF_GPIOS_PER_PORT 16 +#define GAUDI2_WD_GPIO (62 % NUM_OF_GPIOS_PER_PORT) + #define GAUDI2_ARCPID_TX_MB_SIZE 0x1000 #define GAUDI2_ARCPID_RX_MB_SIZE 0x400 #define GAUDI2_ARM_TX_MB_SIZE 0x400 #define GAUDI2_ARM_RX_MB_SIZE 0x1800 #define GAUDI2_DCCM_BASE_ADDR 0x27020000 -#define GAUDI2_ARCPID_TX_MB_ADDR GAUDI2_DCCM_BASE_ADDR - -#define GAUDI2_ARCPID_RX_MB_ADDR (GAUDI2_ARCPID_TX_MB_ADDR + \ - GAUDI2_ARCPID_TX_MB_SIZE) #define GAUDI2_ARM_TX_MB_ADDR GAUDI2_MAILBOX_BASE_ADDR #define GAUDI2_ARM_RX_MB_ADDR (GAUDI2_ARM_TX_MB_ADDR + \ GAUDI2_ARM_TX_MB_SIZE) +#define GAUDI2_ARCPID_TX_MB_ADDR (GAUDI2_ARM_RX_MB_ADDR + GAUDI2_ARM_RX_MB_SIZE) + +#define GAUDI2_ARCPID_RX_MB_ADDR (GAUDI2_ARCPID_TX_MB_ADDR + GAUDI2_ARCPID_TX_MB_SIZE) + #define GAUDI2_ARM_TX_MB_OFFSET (GAUDI2_ARM_TX_MB_ADDR - \ GAUDI2_SP_SRAM_BASE_ADDR) @@ -58,7 +61,9 @@ struct gaudi2_cold_rst_data { u32 spsram_init_done : 1; u32 fake_security_enable : 1; u32 fake_sig_validation_en : 1; - u32 reserved : 26; + u32 bist_skip_enable : 1; + u32 bist_need_iatu_config : 1; + u32 reserved : 24; }; __le32 data; }; @@ -77,10 +82,10 @@ enum gaudi2_rst_src { }; struct gaudi2_redundancy_ctx { - int redundant_hbm; - int redundant_edma; - int redundant_tpc; - int redundant_vdec; + __le32 redundant_hbm; + __le32 redundant_edma; + __le32 redundant_tpc; + __le32 redundant_vdec; __le64 hbm_mask; __le64 edma_mask; __le64 tpc_mask; diff --git a/drivers/misc/habanalabs/include/gaudi2/gaudi2_packets.h b/drivers/accel/habanalabs/include/gaudi2/gaudi2_packets.h index 8bf90fc18bf5..a812f8503f90 100644 --- a/drivers/misc/habanalabs/include/gaudi2/gaudi2_packets.h +++ b/drivers/accel/habanalabs/include/gaudi2/gaudi2_packets.h @@ -59,7 +59,7 @@ struct gaudi2_packet { /* The rest of the packet data follows. Use the corresponding * packet_XXX struct to deference the data, based on packet type */ - u8 contents[0]; + u8 contents[]; }; struct packet_nop { @@ -80,7 +80,7 @@ struct packet_wreg32 { struct packet_wreg_bulk { __le32 size64; __le32 ctl; - __le64 values[0]; /* data starts here */ + __le64 values[]; /* data starts here */ }; struct packet_msg_long { diff --git a/drivers/misc/habanalabs/include/gaudi2/gaudi2_reg_map.h b/drivers/accel/habanalabs/include/gaudi2/gaudi2_reg_map.h index ae7feb388f63..f3eaeb6d9b7e 100644 --- a/drivers/misc/habanalabs/include/gaudi2/gaudi2_reg_map.h +++ b/drivers/accel/habanalabs/include/gaudi2/gaudi2_reg_map.h @@ -24,14 +24,14 @@ #define mmGIC_HOST_HALT_IRQ_POLL_REG mmPSOC_GLOBAL_CONF_SCRATCHPAD_10 #define mmGIC_HOST_INTS_IRQ_POLL_REG mmPSOC_GLOBAL_CONF_SCRATCHPAD_11 #define mmGIC_HOST_SOFT_RST_IRQ_POLL_REG mmPSOC_GLOBAL_CONF_SCRATCHPAD_12 -#define mmEEPROM_COPY_LOCATION_REG mmPSOC_GLOBAL_CONF_SCRATCHPAD_13 #define mmCPU_RST_STATUS_TO_HOST mmPSOC_GLOBAL_CONF_SCRATCHPAD_14 -#define mmENGINE_ARC_IRQ_CTRL_POLL_REG mmPSOC_GLOBAL_CONF_SCRATCHPAD_15 -#define mmPID_CFG_REG mmPSOC_GLOBAL_CONF_SCRATCHPAD_18 /* - * TODO: mmGIC_RAZWI_STATUS_REG is temporary - * macro and to be removed after GAUDI2 PO + * Single scratchpad register used for all ARCs to notify dccm queue full event to FW. + * So a new event would overwrite any unhandled previous event. In other words, incase + * of multiple events before previous ones are handled, last one would be considered. */ +#define mmENGINE_ARC_IRQ_CTRL_POLL_REG mmPSOC_GLOBAL_CONF_SCRATCHPAD_15 +#define mmPID_CFG_REG mmPSOC_GLOBAL_CONF_SCRATCHPAD_18 #define mmGIC_RAZWI_STATUS_REG mmPSOC_GLOBAL_CONF_SCRATCHPAD_19 #define mmCPU_BOOT_DEV_STS0 mmPSOC_GLOBAL_CONF_SCRATCHPAD_20 #define mmCPU_BOOT_DEV_STS1 mmPSOC_GLOBAL_CONF_SCRATCHPAD_21 @@ -40,11 +40,10 @@ #define mmCPU_BOOT_ERR1 mmPSOC_GLOBAL_CONF_SCRATCHPAD_25 #define mmUPD_STS mmPSOC_GLOBAL_CONF_SCRATCHPAD_26 #define mmUPD_CMD mmPSOC_GLOBAL_CONF_SCRATCHPAD_27 -#define mmUBOOT_VER_OFFSET mmPSOC_GLOBAL_CONF_SCRATCHPAD_29 +#define mmPPBOOT_VER_OFFSET mmPSOC_GLOBAL_CONF_SCRATCHPAD_28 #define mmRDWR_TEST mmPSOC_GLOBAL_CONF_SCRATCHPAD_30 #define mmBTL_ID mmPSOC_GLOBAL_CONF_SCRATCHPAD_31 #define mmRST_SRC mmPSOC_GLOBAL_CONF_COLD_RST_FLOPS_0 -#define mmPREBOOT_PCIE_EN mmPSOC_GLOBAL_CONF_COLD_RST_FLOPS_1 #define mmCOLD_RST_DATA mmPSOC_GLOBAL_CONF_COLD_RST_FLOPS_2 #define mmUPD_PENDING_STS mmPSOC_GLOBAL_CONF_COLD_RST_FLOPS_3 #define mmPID_CMD_REQ_REG mmPSOC_PID_PID_CMD_0 @@ -55,5 +54,8 @@ #define mmPID_CMD_TELEMETRY_REG_0_HI mmPSOC_PID_PID_CMD_5 #define mmPID_CMD_TELEMETRY_REG_1 mmPSOC_PID_PID_CMD_6 #define mmPID_CMD_TELEMETRY_REG_1_HI mmPSOC_PID_PID_CMD_7 +#define mmWD_GPIO_OUTSET_REG mmPSOC_GPIO3_OUTENSET +#define mmWD_GPIO_DATAOUT_REG mmPSOC_GPIO3_DATAOUT +#define mmSTM_PROFILER_SPE_REG mmPSOC_STM_STMSPER #endif /* GAUDI2_REG_MAP_H_ */ diff --git a/drivers/accel/habanalabs/include/gaudi2/gaudi2_special_blocks.h b/drivers/accel/habanalabs/include/gaudi2/gaudi2_special_blocks.h new file mode 100644 index 000000000000..a55668f92dd1 --- /dev/null +++ b/drivers/accel/habanalabs/include/gaudi2/gaudi2_special_blocks.h @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright 2022 HabanaLabs, Ltd. + * All Rights Reserved. + */ + +/* + * This file was generated automatically. + * DON'T EDIT THIS FILE. + */ + +#ifndef GAUDI2_SPECIAL_BLOCKS_H +#define GAUDI2_SPECIAL_BLOCKS_H + +#define GAUDI2_SPECIAL_BLOCKS { \ + { GAUDI2_BLOCK_TYPE_TPC, 0xfc008000, 4, 6, 0, 0x200000, 0x10000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_TPC, 0xfc00a000, 4, 6, 0, 0x200000, 0x10000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_TPC, 0xfc00b000, 4, 6, 0, 0x200000, 0x10000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_TPC, 0xfc00c000, 4, 6, 0, 0x200000, 0x10000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_HMMU, 0xfc080000, 4, 4, 0, 0x200000, 0x10000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_HMMU, 0xfc081000, 4, 4, 0, 0x200000, 0x10000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_HMMU, 0xfc083000, 4, 4, 0, 0x200000, 0x10000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_HMMU, 0xfc084000, 4, 4, 0, 0x200000, 0x10000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_MME, 0xfc0c8000, 4, 0, 0, 0x200000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_MME, 0xfc0c9000, 4, 0, 0, 0x200000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_MME, 0xfc0ca000, 4, 0, 0, 0x200000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_MME, 0xfc0cb000, 4, 0, 0, 0x200000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_MME, 0xfc0cc000, 4, 0, 0, 0x200000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_EU_BIST, 0xfc0cd000, 4, 0, 0, 0x200000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_MME, 0xfc0ce000, 4, 0, 0, 0x200000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_MME, 0xfc0cf000, 4, 0, 0, 0x200000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_MME, 0xfc0d0000, 4, 5, 0, 0x200000, 0x8000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_MME, 0xfc0d1000, 4, 5, 0, 0x200000, 0x8000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_MME, 0xfc0f8000, 4, 0, 0, 0x200000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_MME, 0xfc0f9000, 4, 2, 0, 0x200000, 0x1000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_SYNC_MNGR, 0xfc11e000, 4, 0, 0, 0x200000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_SYNC_MNGR, 0xfc11f000, 4, 0, 0, 0x200000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_HIF, 0xfc120000, 4, 4, 0, 0x200000, 0x4000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_RTR, 0xfc140000, 4, 8, 0, 0x200000, 0x8000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_RTR, 0xfc141000, 4, 8, 0, 0x200000, 0x8000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_RTR, 0xfc142000, 4, 8, 0, 0x200000, 0x8000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_RTR, 0xfc143000, 4, 8, 0, 0x200000, 0x8000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_RTR, 0xfc144000, 4, 8, 0, 0x200000, 0x8000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_RTR, 0xfc145000, 4, 8, 0, 0x200000, 0x8000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_SRAM, 0xfc180000, 4, 8, 0, 0x200000, 0x8000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_RTR, 0xfc181000, 4, 8, 0, 0x200000, 0x8000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_SRAM, 0xfc182000, 4, 8, 0, 0x200000, 0x8000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_EDMA, 0xfc1c8000, 4, 2, 0, 0x200000, 0x10000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_EDMA, 0xfc1ca000, 4, 2, 0, 0x200000, 0x10000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_EDMA, 0xfc1cb000, 4, 2, 0, 0x200000, 0x10000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_EDMA, 0xfc1cc000, 4, 2, 0, 0x200000, 0x10000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_DEC, 0xfc1e3000, 4, 2, 0, 0x200000, 0x10000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_DEC, 0xfc1e4000, 4, 2, 0, 0x200000, 0x10000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_DEC, 0xfc1e5000, 4, 2, 0, 0x200000, 0x10000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PCIE, 0xfcc01000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PCIE, 0xfcc04000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PCIE, 0xfcc07000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PCIE, 0xfcc10000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PCIE, 0xfcc14000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PCIE, 0xfcc15000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PCIE, 0xfcc16000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PSOC, 0xfcc4a000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PSOC, 0xfcc4b000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PSOC, 0xfcc4e000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PSOC, 0xfcc4f000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PSOC, 0xfcc53000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PSOC, 0xfcc54000, 2, 0, 0, 0x1000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PSOC, 0xfcc58000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PSOC, 0xfcc59000, 2, 0, 0, 0x3000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PSOC, 0xfcc5a000, 2, 0, 0, 0x3000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PSOC, 0xfcc5b000, 2, 0, 0, 0x3000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PSOC, 0xfcc60000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PSOC, 0xfcc61000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PSOC, 0xfcc62000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PSOC, 0xfcc63000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PSOC, 0xfcc64000, 3, 0, 0, 0x1000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PLL, 0xfcc6c000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PLL, 0xfcc6d000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PLL, 0xfcc6e000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PSOC, 0xfcc74000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PSOC, 0xfcc76000, 3, 0, 0, 0x1000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PSOC, 0xfcc79000, 2, 0, 0, 0x1000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PSOC, 0xfcc7b000, 3, 0, 0, 0x1000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PSOC, 0xfcc7f000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PDMA, 0xfcc88000, 2, 0, 0, 0x10000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PDMA, 0xfcc8a000, 2, 0, 0, 0x10000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PDMA, 0xfcc8b000, 2, 0, 0, 0x10000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PDMA, 0xfcc8c000, 2, 0, 0, 0x10000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_CPU, 0xfccc0000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_CPU, 0xfccc1000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_CPU, 0xfccc3000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PMMU, 0xfcd00000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PMMU, 0xfcd01000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PMMU, 0xfcd02000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PMMU, 0xfcd03000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PLL, 0xfcd04000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PLL, 0xfcd05000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_XBAR, 0xfcd40000, 4, 0, 0, 0x10000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PLL, 0xfcd41000, 4, 0, 0, 0x10000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PLL, 0xfcd42000, 4, 0, 0, 0x10000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PLL, 0xfcd43000, 4, 0, 0, 0x10000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PLL, 0xfcd44000, 2, 0, 0, 0x10000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_XBAR, 0xfcd48000, 4, 0, 0, 0x10000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PLL, 0xfcd55000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PLL, 0xfcd64000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PLL, 0xfcd65000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PLL, 0xfcd74000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_ROT, 0xfce08000, 2, 0, 0, 0x10000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_ROT, 0xfce0a000, 2, 0, 0, 0x10000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_ROT, 0xfce0b000, 2, 0, 0, 0x10000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_ROT, 0xfce0c000, 2, 0, 0, 0x10000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_RTR, 0xfce40000, 4, 2, 0, 0x10000, 0x4000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_RTR, 0xfce41000, 4, 2, 0, 0x10000, 0x4000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_RTR, 0xfce42000, 4, 2, 0, 0x10000, 0x4000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_RTR, 0xfce43000, 4, 2, 0, 0x10000, 0x4000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_RTR, 0xfce48000, 4, 0, 0, 0x10000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_RTR, 0xfce49000, 4, 0, 0, 0x10000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_RTR, 0xfce4a000, 4, 0, 0, 0x10000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_RTR, 0xfce4b000, 4, 0, 0, 0x10000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_RTR, 0xfce4c000, 4, 0, 0, 0x10000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_ARC_FARM, 0xfce81000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_ARC_FARM, 0xfce82000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_ARC_FARM, 0xfce88000, 4, 0, 0, 0x20000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_ARC_FARM, 0xfce89000, 4, 0, 0, 0x20000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_ARC_FARM, 0xfce8b000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_ARC_FARM, 0xfce8c000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_ARC_FARM, 0xfce8f000, 4, 0, 0, 0x20000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_DEC, 0xfcf03000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_DEC, 0xfcf04000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_DEC, 0xfcf05000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_XFT, 0xfcf40000, 4, 0, 0, 0x10000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PLL, 0xfcf41000, 4, 0, 0, 0x10000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PLL, 0xfcf42000, 4, 0, 0, 0x10000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PLL, 0xfcf43000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PLL, 0xfcf53000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_PLL, 0xfcf73000, 1, 0, 0, 0x0, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_HBM, 0xfd000000, 6, 2, 0, 0x80000, 0x20000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_HBM, 0xfd001000, 6, 2, 8, 0x80000, 0x20000, 0x1000 }, \ + { GAUDI2_BLOCK_TYPE_HBM, 0xfd009000, 6, 2, 0, 0x80000, 0x20000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_NIC, 0xfd400000, 12, 2, 15, 0x80000, 0x20000, 0x1000 }, \ + { GAUDI2_BLOCK_TYPE_NIC, 0xfd418000, 12, 2, 0, 0x80000, 0x20000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_NIC, 0xfd41a000, 12, 2, 0, 0x80000, 0x20000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_NIC, 0xfd41f000, 12, 2, 0, 0x80000, 0x20000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_NIC, 0xfd448000, 12, 0, 0, 0x80000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_NIC, 0xfd449000, 12, 0, 0, 0x80000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_NIC, 0xfd44a000, 12, 2, 0, 0x80000, 0x1000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_NIC, 0xfd44c000, 12, 2, 0, 0x80000, 0x1000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_NIC, 0xfd450000, 12, 2, 0, 0x80000, 0x1000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_NIC, 0xfd452000, 12, 2, 0, 0x80000, 0x1000, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_NIC, 0xfd454000, 12, 0, 0, 0x80000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_NIC, 0xfd455000, 12, 0, 0, 0x80000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_NIC, 0xfd460000, 12, 0, 0, 0x80000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_NIC, 0xfd468000, 12, 0, 0, 0x80000, 0x0, 0x0 }, \ + { GAUDI2_BLOCK_TYPE_NIC, 0xfd469000, 12, 0, 0, 0x80000, 0x0, 0x0 }, \ +} + +#endif diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/cpu_ca53_cfg_masks.h b/drivers/accel/habanalabs/include/goya/asic_reg/cpu_ca53_cfg_masks.h index 4e0dbbbbde20..4e0dbbbbde20 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/cpu_ca53_cfg_masks.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/cpu_ca53_cfg_masks.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/cpu_ca53_cfg_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/cpu_ca53_cfg_regs.h index f3faf1aad91a..f3faf1aad91a 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/cpu_ca53_cfg_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/cpu_ca53_cfg_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/cpu_if_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/cpu_if_regs.h index cf657918962a..cf657918962a 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/cpu_if_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/cpu_if_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/cpu_pll_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/cpu_pll_regs.h index 8c8f9726d4b9..8c8f9726d4b9 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/cpu_pll_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/cpu_pll_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_0_masks.h b/drivers/accel/habanalabs/include/goya/asic_reg/dma_ch_0_masks.h index 028143408401..028143408401 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_0_masks.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/dma_ch_0_masks.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_0_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/dma_ch_0_regs.h index 0b246fe6ad04..0b246fe6ad04 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_0_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/dma_ch_0_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_1_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/dma_ch_1_regs.h index 5449031722f2..5449031722f2 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_1_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/dma_ch_1_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_2_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/dma_ch_2_regs.h index a4768521d18a..a4768521d18a 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_2_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/dma_ch_2_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_3_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/dma_ch_3_regs.h index 619d01897ff8..619d01897ff8 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_3_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/dma_ch_3_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_4_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/dma_ch_4_regs.h index 038617e163f1..038617e163f1 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_4_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/dma_ch_4_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_macro_masks.h b/drivers/accel/habanalabs/include/goya/asic_reg/dma_macro_masks.h index f43b564af1be..f43b564af1be 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/dma_macro_masks.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/dma_macro_masks.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_macro_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/dma_macro_regs.h index c3bfc1b8e3fd..c3bfc1b8e3fd 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/dma_macro_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/dma_macro_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_nrtr_masks.h b/drivers/accel/habanalabs/include/goya/asic_reg/dma_nrtr_masks.h index bc977488c072..bc977488c072 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/dma_nrtr_masks.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/dma_nrtr_masks.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_nrtr_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/dma_nrtr_regs.h index c4abc7ff1fc6..c4abc7ff1fc6 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/dma_nrtr_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/dma_nrtr_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_0_masks.h b/drivers/accel/habanalabs/include/goya/asic_reg/dma_qm_0_masks.h index b17f72c31ab6..b17f72c31ab6 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_0_masks.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/dma_qm_0_masks.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_0_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/dma_qm_0_regs.h index bf360b301154..bf360b301154 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_0_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/dma_qm_0_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_1_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/dma_qm_1_regs.h index 51d432d05ac4..51d432d05ac4 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_1_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/dma_qm_1_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_2_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/dma_qm_2_regs.h index 18fc0c2b6cc2..18fc0c2b6cc2 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_2_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/dma_qm_2_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_3_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/dma_qm_3_regs.h index 6cf7204bf5cc..6cf7204bf5cc 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_3_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/dma_qm_3_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_4_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/dma_qm_4_regs.h index 36fef2682875..36fef2682875 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_4_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/dma_qm_4_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/goya_blocks.h b/drivers/accel/habanalabs/include/goya/asic_reg/goya_blocks.h index 85b15010cd7a..85b15010cd7a 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/goya_blocks.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/goya_blocks.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/goya_masks.h b/drivers/accel/habanalabs/include/goya/asic_reg/goya_masks.h index 9ff3cb245580..9ff3cb245580 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/goya_masks.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/goya_masks.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/goya_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/goya_regs.h index ce65c9da5c60..ce65c9da5c60 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/goya_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/goya_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/ic_pll_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/ic_pll_regs.h index 4ae7fed8b18c..4ae7fed8b18c 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/ic_pll_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/ic_pll_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mc_pll_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/mc_pll_regs.h index 6d35d852798b..6d35d852798b 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/mc_pll_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/mc_pll_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mme1_rtr_masks.h b/drivers/accel/habanalabs/include/goya/asic_reg/mme1_rtr_masks.h index 6c23f8b96e7e..6c23f8b96e7e 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/mme1_rtr_masks.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/mme1_rtr_masks.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mme1_rtr_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/mme1_rtr_regs.h index 122e9d529939..122e9d529939 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/mme1_rtr_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/mme1_rtr_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mme2_rtr_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/mme2_rtr_regs.h index 00ce2252bbfb..00ce2252bbfb 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/mme2_rtr_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/mme2_rtr_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mme3_rtr_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/mme3_rtr_regs.h index 8e3eb7fd2070..8e3eb7fd2070 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/mme3_rtr_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/mme3_rtr_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mme4_rtr_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/mme4_rtr_regs.h index 79b67bbc8567..79b67bbc8567 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/mme4_rtr_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/mme4_rtr_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mme5_rtr_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/mme5_rtr_regs.h index 0ac3c37ce47f..0ac3c37ce47f 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/mme5_rtr_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/mme5_rtr_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mme6_rtr_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/mme6_rtr_regs.h index 50c49cce72a6..50c49cce72a6 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/mme6_rtr_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/mme6_rtr_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mme_cmdq_masks.h b/drivers/accel/habanalabs/include/goya/asic_reg/mme_cmdq_masks.h index fe7d95bdcef9..fe7d95bdcef9 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/mme_cmdq_masks.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/mme_cmdq_masks.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mme_cmdq_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/mme_cmdq_regs.h index 5f8b85d2b4b1..5f8b85d2b4b1 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/mme_cmdq_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/mme_cmdq_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mme_masks.h b/drivers/accel/habanalabs/include/goya/asic_reg/mme_masks.h index 1882c413cbe0..1882c413cbe0 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/mme_masks.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/mme_masks.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mme_qm_masks.h b/drivers/accel/habanalabs/include/goya/asic_reg/mme_qm_masks.h index e464e381555c..e464e381555c 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/mme_qm_masks.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/mme_qm_masks.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mme_qm_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/mme_qm_regs.h index 538708beffc9..538708beffc9 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/mme_qm_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/mme_qm_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mme_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/mme_regs.h index 0396cbfd5c89..0396cbfd5c89 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/mme_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/mme_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mmu_masks.h b/drivers/accel/habanalabs/include/goya/asic_reg/mmu_masks.h index c3e69062b135..c3e69062b135 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/mmu_masks.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/mmu_masks.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mmu_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/mmu_regs.h index 7ec81f12031e..7ec81f12031e 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/mmu_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/mmu_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/pci_nrtr_masks.h b/drivers/accel/habanalabs/include/goya/asic_reg/pci_nrtr_masks.h index ceb59f2e28b3..ceb59f2e28b3 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/pci_nrtr_masks.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/pci_nrtr_masks.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/pci_nrtr_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/pci_nrtr_regs.h index dd067f301ac2..dd067f301ac2 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/pci_nrtr_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/pci_nrtr_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/pcie_aux_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/pcie_aux_regs.h index 35b1d8ac6f63..35b1d8ac6f63 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/pcie_aux_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/pcie_aux_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/pcie_wrap_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/pcie_wrap_regs.h index d1e55aace4a0..d1e55aace4a0 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/pcie_wrap_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/pcie_wrap_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/psoc_emmc_pll_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/psoc_emmc_pll_regs.h index 9271ea95ebe9..9271ea95ebe9 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/psoc_emmc_pll_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/psoc_emmc_pll_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/psoc_etr_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/psoc_etr_regs.h index b7c33e025db5..b7c33e025db5 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/psoc_etr_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/psoc_etr_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/psoc_global_conf_masks.h b/drivers/accel/habanalabs/include/goya/asic_reg/psoc_global_conf_masks.h index 324266653c9a..324266653c9a 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/psoc_global_conf_masks.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/psoc_global_conf_masks.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/psoc_global_conf_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/psoc_global_conf_regs.h index 8141f422e712..8141f422e712 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/psoc_global_conf_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/psoc_global_conf_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/psoc_mme_pll_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/psoc_mme_pll_regs.h index 4789ebb9c337..4789ebb9c337 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/psoc_mme_pll_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/psoc_mme_pll_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/psoc_pci_pll_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/psoc_pci_pll_regs.h index 27a296ea6c3d..27a296ea6c3d 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/psoc_pci_pll_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/psoc_pci_pll_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/psoc_spi_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/psoc_spi_regs.h index 66aee7fa6b1e..66aee7fa6b1e 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/psoc_spi_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/psoc_spi_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/psoc_timestamp_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/psoc_timestamp_regs.h index 9ce24597d4b0..9ce24597d4b0 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/psoc_timestamp_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/psoc_timestamp_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x0_rtr_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/sram_y0_x0_rtr_regs.h index 2ea1770b078f..2ea1770b078f 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x0_rtr_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/sram_y0_x0_rtr_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x1_rtr_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/sram_y0_x1_rtr_regs.h index 37e0713efa73..37e0713efa73 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x1_rtr_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/sram_y0_x1_rtr_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x2_rtr_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/sram_y0_x2_rtr_regs.h index d2572279a2b9..d2572279a2b9 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x2_rtr_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/sram_y0_x2_rtr_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x3_rtr_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/sram_y0_x3_rtr_regs.h index 68c5b402c506..68c5b402c506 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x3_rtr_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/sram_y0_x3_rtr_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x4_rtr_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/sram_y0_x4_rtr_regs.h index a42f1ba06d28..a42f1ba06d28 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x4_rtr_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/sram_y0_x4_rtr_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/stlb_masks.h b/drivers/accel/habanalabs/include/goya/asic_reg/stlb_masks.h index 94f2ed4a36bd..94f2ed4a36bd 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/stlb_masks.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/stlb_masks.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/stlb_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/stlb_regs.h index 35013f65acd2..35013f65acd2 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/stlb_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/stlb_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_cfg_masks.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc0_cfg_masks.h index 89c9507a512f..89c9507a512f 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_cfg_masks.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc0_cfg_masks.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_cfg_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc0_cfg_regs.h index 7d71c4b73a5e..7d71c4b73a5e 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_cfg_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc0_cfg_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_cmdq_masks.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc0_cmdq_masks.h index 9395f2458771..9395f2458771 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_cmdq_masks.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc0_cmdq_masks.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_cmdq_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc0_cmdq_regs.h index bc51df573bf0..bc51df573bf0 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_cmdq_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc0_cmdq_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_eml_cfg_masks.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc0_eml_cfg_masks.h index 553c6b6bd5ec..553c6b6bd5ec 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_eml_cfg_masks.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc0_eml_cfg_masks.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_eml_cfg_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc0_eml_cfg_regs.h index 8495479c3659..8495479c3659 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_eml_cfg_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc0_eml_cfg_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_nrtr_masks.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc0_nrtr_masks.h index 43fafcf01041..43fafcf01041 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_nrtr_masks.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc0_nrtr_masks.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_nrtr_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc0_nrtr_regs.h index ce3346dd2042..ce3346dd2042 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_nrtr_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc0_nrtr_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_qm_masks.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc0_qm_masks.h index 2e4b45947944..2e4b45947944 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_qm_masks.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc0_qm_masks.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_qm_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc0_qm_regs.h index 4fa09eb88878..4fa09eb88878 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_qm_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc0_qm_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc1_cfg_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc1_cfg_regs.h index 928eef1808ae..928eef1808ae 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc1_cfg_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc1_cfg_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc1_cmdq_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc1_cmdq_regs.h index 30ae0f307328..30ae0f307328 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc1_cmdq_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc1_cmdq_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc1_qm_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc1_qm_regs.h index b95de4f95ba9..b95de4f95ba9 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc1_qm_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc1_qm_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc1_rtr_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc1_rtr_regs.h index 0f91e307879e..0f91e307879e 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc1_rtr_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc1_rtr_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc2_cfg_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc2_cfg_regs.h index 73421227f35b..73421227f35b 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc2_cfg_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc2_cfg_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc2_cmdq_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc2_cmdq_regs.h index 27b66bf2da9f..27b66bf2da9f 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc2_cmdq_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc2_cmdq_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc2_qm_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc2_qm_regs.h index 31e5b2f53905..31e5b2f53905 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc2_qm_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc2_qm_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc2_rtr_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc2_rtr_regs.h index 4eddeaa15d94..4eddeaa15d94 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc2_rtr_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc2_rtr_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc3_cfg_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc3_cfg_regs.h index ce573a1a8361..ce573a1a8361 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc3_cfg_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc3_cfg_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc3_cmdq_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc3_cmdq_regs.h index 11d81fca0a0f..11d81fca0a0f 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc3_cmdq_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc3_cmdq_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc3_qm_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc3_qm_regs.h index e41595a19e69..e41595a19e69 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc3_qm_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc3_qm_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc3_rtr_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc3_rtr_regs.h index 34a438b1efe5..34a438b1efe5 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc3_rtr_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc3_rtr_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc4_cfg_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc4_cfg_regs.h index d44caf0fc1bb..d44caf0fc1bb 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc4_cfg_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc4_cfg_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc4_cmdq_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc4_cmdq_regs.h index f13a6532961f..f13a6532961f 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc4_cmdq_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc4_cmdq_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc4_qm_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc4_qm_regs.h index db081fc17cfc..db081fc17cfc 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc4_qm_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc4_qm_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc4_rtr_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc4_rtr_regs.h index 8c5372303b28..8c5372303b28 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc4_rtr_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc4_rtr_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc5_cfg_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc5_cfg_regs.h index 5139fde71011..5139fde71011 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc5_cfg_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc5_cfg_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc5_cmdq_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc5_cmdq_regs.h index 1e7cd6e1e888..1e7cd6e1e888 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc5_cmdq_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc5_cmdq_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc5_qm_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc5_qm_regs.h index ac0d3820cd6b..ac0d3820cd6b 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc5_qm_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc5_qm_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc5_rtr_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc5_rtr_regs.h index 57f83bc3b17d..57f83bc3b17d 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc5_rtr_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc5_rtr_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc6_cfg_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc6_cfg_regs.h index 94e0191c06c1..94e0191c06c1 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc6_cfg_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc6_cfg_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc6_cmdq_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc6_cmdq_regs.h index 7a1a0e87b225..7a1a0e87b225 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc6_cmdq_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc6_cmdq_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc6_qm_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc6_qm_regs.h index 80fa0fe0f60f..80fa0fe0f60f 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc6_qm_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc6_qm_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc6_rtr_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc6_rtr_regs.h index d6cae8b8af66..d6cae8b8af66 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc6_rtr_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc6_rtr_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc7_cfg_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc7_cfg_regs.h index 234147adb779..234147adb779 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc7_cfg_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc7_cfg_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc7_cmdq_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc7_cmdq_regs.h index 4c160632fe7d..4c160632fe7d 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc7_cmdq_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc7_cmdq_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc7_nrtr_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc7_nrtr_regs.h index 0c13d4d167aa..0c13d4d167aa 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc7_nrtr_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc7_nrtr_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc7_qm_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc7_qm_regs.h index cbe11425bfb0..cbe11425bfb0 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc7_qm_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc7_qm_regs.h diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc_pll_regs.h b/drivers/accel/habanalabs/include/goya/asic_reg/tpc_pll_regs.h index e25e19660a9d..e25e19660a9d 100644 --- a/drivers/misc/habanalabs/include/goya/asic_reg/tpc_pll_regs.h +++ b/drivers/accel/habanalabs/include/goya/asic_reg/tpc_pll_regs.h diff --git a/drivers/misc/habanalabs/include/goya/goya.h b/drivers/accel/habanalabs/include/goya/goya.h index 1b4ca435021d..1b4ca435021d 100644 --- a/drivers/misc/habanalabs/include/goya/goya.h +++ b/drivers/accel/habanalabs/include/goya/goya.h diff --git a/drivers/misc/habanalabs/include/goya/goya_async_events.h b/drivers/accel/habanalabs/include/goya/goya_async_events.h index 09081401cb1d..09081401cb1d 100644 --- a/drivers/misc/habanalabs/include/goya/goya_async_events.h +++ b/drivers/accel/habanalabs/include/goya/goya_async_events.h diff --git a/drivers/misc/habanalabs/include/goya/goya_coresight.h b/drivers/accel/habanalabs/include/goya/goya_coresight.h index 6e933c0ca5cd..6e933c0ca5cd 100644 --- a/drivers/misc/habanalabs/include/goya/goya_coresight.h +++ b/drivers/accel/habanalabs/include/goya/goya_coresight.h diff --git a/drivers/misc/habanalabs/include/goya/goya_fw_if.h b/drivers/accel/habanalabs/include/goya/goya_fw_if.h index bc05f86c73ac..bc05f86c73ac 100644 --- a/drivers/misc/habanalabs/include/goya/goya_fw_if.h +++ b/drivers/accel/habanalabs/include/goya/goya_fw_if.h diff --git a/drivers/misc/habanalabs/include/goya/goya_packets.h b/drivers/accel/habanalabs/include/goya/goya_packets.h index 896799204fb0..896799204fb0 100644 --- a/drivers/misc/habanalabs/include/goya/goya_packets.h +++ b/drivers/accel/habanalabs/include/goya/goya_packets.h diff --git a/drivers/misc/habanalabs/include/goya/goya_reg_map.h b/drivers/accel/habanalabs/include/goya/goya_reg_map.h index f3ab282cafa4..f3ab282cafa4 100644 --- a/drivers/misc/habanalabs/include/goya/goya_reg_map.h +++ b/drivers/accel/habanalabs/include/goya/goya_reg_map.h diff --git a/drivers/misc/habanalabs/include/hw_ip/mmu/mmu_general.h b/drivers/accel/habanalabs/include/hw_ip/mmu/mmu_general.h index d408feecd483..d408feecd483 100644 --- a/drivers/misc/habanalabs/include/hw_ip/mmu/mmu_general.h +++ b/drivers/accel/habanalabs/include/hw_ip/mmu/mmu_general.h diff --git a/drivers/misc/habanalabs/include/hw_ip/mmu/mmu_v1_0.h b/drivers/accel/habanalabs/include/hw_ip/mmu/mmu_v1_0.h index 86511002e367..86511002e367 100644 --- a/drivers/misc/habanalabs/include/hw_ip/mmu/mmu_v1_0.h +++ b/drivers/accel/habanalabs/include/hw_ip/mmu/mmu_v1_0.h diff --git a/drivers/misc/habanalabs/include/hw_ip/mmu/mmu_v1_1.h b/drivers/accel/habanalabs/include/hw_ip/mmu/mmu_v1_1.h index 9c727a5d47b4..9c727a5d47b4 100644 --- a/drivers/misc/habanalabs/include/hw_ip/mmu/mmu_v1_1.h +++ b/drivers/accel/habanalabs/include/hw_ip/mmu/mmu_v1_1.h diff --git a/drivers/misc/habanalabs/include/hw_ip/mmu/mmu_v2_0.h b/drivers/accel/habanalabs/include/hw_ip/mmu/mmu_v2_0.h index cd7bf25d2da9..cd7bf25d2da9 100644 --- a/drivers/misc/habanalabs/include/hw_ip/mmu/mmu_v2_0.h +++ b/drivers/accel/habanalabs/include/hw_ip/mmu/mmu_v2_0.h diff --git a/drivers/misc/habanalabs/include/hw_ip/pci/pci_general.h b/drivers/accel/habanalabs/include/hw_ip/pci/pci_general.h index f5d497dc9bdc..f5d497dc9bdc 100644 --- a/drivers/misc/habanalabs/include/hw_ip/pci/pci_general.h +++ b/drivers/accel/habanalabs/include/hw_ip/pci/pci_general.h diff --git a/drivers/accessibility/speakup/spk_ttyio.c b/drivers/accessibility/speakup/spk_ttyio.c index 08cf8a17754b..07373b3debd1 100644 --- a/drivers/accessibility/speakup/spk_ttyio.c +++ b/drivers/accessibility/speakup/spk_ttyio.c @@ -354,6 +354,9 @@ void spk_ttyio_release(struct spk_synth *in_synth) { struct tty_struct *tty = in_synth->dev; + if (tty == NULL) + return; + tty_lock(tty); if (tty->ops->close) diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 204fe94c7e45..a194f30876c5 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -75,7 +75,8 @@ static struct acpi_bus_type *acpi_get_bus_type(struct device *dev) } #define FIND_CHILD_MIN_SCORE 1 -#define FIND_CHILD_MAX_SCORE 2 +#define FIND_CHILD_MID_SCORE 2 +#define FIND_CHILD_MAX_SCORE 3 static int match_any(struct acpi_device *adev, void *not_used) { @@ -96,8 +97,17 @@ static int find_child_checks(struct acpi_device *adev, bool check_children) return -ENODEV; status = acpi_evaluate_integer(adev->handle, "_STA", NULL, &sta); - if (status == AE_NOT_FOUND) + if (status == AE_NOT_FOUND) { + /* + * Special case: backlight device objects without _STA are + * preferred to other objects with the same _ADR value, because + * it is more likely that they are actually useful. + */ + if (adev->pnp.type.backlight) + return FIND_CHILD_MID_SCORE; + return FIND_CHILD_MIN_SCORE; + } if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_ENABLED)) return -ENODEV; diff --git a/drivers/acpi/prmt.c b/drivers/acpi/prmt.c index 998101cf16e4..3d4c4620f9f9 100644 --- a/drivers/acpi/prmt.c +++ b/drivers/acpi/prmt.c @@ -236,6 +236,11 @@ static acpi_status acpi_platformrt_space_handler(u32 function, efi_status_t status; struct prm_context_buffer context; + if (!efi_enabled(EFI_RUNTIME_SERVICES)) { + pr_err_ratelimited("PRM: EFI runtime services no longer available\n"); + return AE_NO_HANDLER; + } + /* * The returned acpi_status will always be AE_OK. Error values will be * saved in the first byte of the PRM message buffer to be used by ASL. @@ -325,6 +330,11 @@ void __init init_prmt(void) pr_info("PRM: found %u modules\n", mc); + if (!efi_enabled(EFI_RUNTIME_SERVICES)) { + pr_err("PRM: EFI runtime services unavailable\n"); + return; + } + status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT, ACPI_ADR_SPACE_PLATFORM_RT, &acpi_platformrt_space_handler, diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 16dcd31d124f..192d1784e409 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -433,6 +433,13 @@ static const struct dmi_system_id asus_laptop[] = { }, }, { + .ident = "Asus ExpertBook B2402CBA", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_BOARD_NAME, "B2402CBA"), + }, + }, + { .ident = "Asus ExpertBook B2502", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 274344434282..0c6f06abe3f4 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1370,9 +1370,12 @@ static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp, * Some devices don't reliably have _HIDs & _CIDs, so add * synthetic HIDs to make sure drivers can find them. */ - if (acpi_is_video_device(handle)) + if (acpi_is_video_device(handle)) { acpi_add_id(pnp, ACPI_VIDEO_HID); - else if (acpi_bay_match(handle)) + pnp->type.backlight = 1; + break; + } + if (acpi_bay_match(handle)) acpi_add_id(pnp, ACPI_BAY_HID); else if (acpi_dock_match(handle)) acpi_add_id(pnp, ACPI_DOCK_HID); diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 0b557c0d405e..4ca667251272 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -60,13 +60,17 @@ static struct notifier_block tts_notifier = { .priority = 0, }; +#ifndef acpi_skip_set_wakeup_address +#define acpi_skip_set_wakeup_address() false +#endif + static int acpi_sleep_prepare(u32 acpi_state) { #ifdef CONFIG_ACPI_SLEEP unsigned long acpi_wakeup_address; /* do we have a wakeup address for S2 and S3? */ - if (acpi_state == ACPI_STATE_S3) { + if (acpi_state == ACPI_STATE_S3 && !acpi_skip_set_wakeup_address()) { acpi_wakeup_address = acpi_get_wakeup_address(); if (!acpi_wakeup_address) return -EFAULT; diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 1b78c7434492..a8c02608dde4 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -50,6 +50,10 @@ static void acpi_video_parse_cmdline(void) acpi_backlight_cmdline = acpi_backlight_video; if (!strcmp("native", acpi_video_backlight_string)) acpi_backlight_cmdline = acpi_backlight_native; + if (!strcmp("nvidia_wmi_ec", acpi_video_backlight_string)) + acpi_backlight_cmdline = acpi_backlight_nvidia_wmi_ec; + if (!strcmp("apple_gmux", acpi_video_backlight_string)) + acpi_backlight_cmdline = acpi_backlight_apple_gmux; if (!strcmp("none", acpi_video_backlight_string)) acpi_backlight_cmdline = acpi_backlight_none; } @@ -106,26 +110,6 @@ static bool nvidia_wmi_ec_supported(void) } #endif -static bool apple_gmux_backlight_present(void) -{ - struct acpi_device *adev; - struct device *dev; - - adev = acpi_dev_get_first_match_dev(GMUX_ACPI_HID, NULL, -1); - if (!adev) - return false; - - dev = acpi_get_first_physical_node(adev); - if (!dev) - return false; - - /* - * drivers/platform/x86/apple-gmux.c only supports old style - * Apple GMUX with an IO-resource. - */ - return pnp_get_resource(to_pnp_dev(dev), IORESOURCE_IO, 0) != NULL; -} - /* Force to use vendor driver when the ACPI device is known to be * buggy */ static int video_detect_force_vendor(const struct dmi_system_id *d) @@ -513,6 +497,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = { }, { .callback = video_detect_force_native, + /* Acer Aspire 4810T */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 4810T"), + }, + }, + { + .callback = video_detect_force_native, /* Acer Aspire 5738z */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), @@ -600,6 +592,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = { }, { .callback = video_detect_force_native, + /* Asus U46E */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "U46E"), + }, + }, + { + .callback = video_detect_force_native, /* Asus UX303UB */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), @@ -608,6 +608,23 @@ static const struct dmi_system_id video_detect_dmi_table[] = { }, { .callback = video_detect_force_native, + /* HP EliteBook 8460p */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 8460p"), + }, + }, + { + .callback = video_detect_force_native, + /* HP Pavilion g6-1d80nr / B4U19UA */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion g6 Notebook PC"), + DMI_MATCH(DMI_PRODUCT_SKU, "B4U19UA"), + }, + }, + { + .callback = video_detect_force_native, /* Samsung N150P */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), @@ -754,6 +771,7 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native) { static DEFINE_MUTEX(init_mutex); static bool nvidia_wmi_ec_present; + static bool apple_gmux_present; static bool native_available; static bool init_done; static long video_caps; @@ -767,6 +785,7 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native) ACPI_UINT32_MAX, find_video, NULL, &video_caps, NULL); nvidia_wmi_ec_present = nvidia_wmi_ec_supported(); + apple_gmux_present = apple_gmux_detect(NULL, NULL); init_done = true; } if (native) @@ -788,7 +807,7 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native) if (nvidia_wmi_ec_present) return acpi_backlight_nvidia_wmi_ec; - if (apple_gmux_backlight_present()) + if (apple_gmux_present) return acpi_backlight_apple_gmux; /* Use ACPI video if available, except when native should be preferred. */ diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index eceaec33af65..9695c4404e26 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -640,6 +640,7 @@ config PATA_CS5530 config PATA_CS5535 tristate "CS5535 PATA support (Experimental)" depends on PCI && (X86_32 || (X86_64 && COMPILE_TEST)) + depends on !UML help This option enables support for the NatSemi/AMD CS5535 companion chip used with the Geode processor family. diff --git a/drivers/base/property.c b/drivers/base/property.c index bbb3e499ff4a..083a95791d3b 100644 --- a/drivers/base/property.c +++ b/drivers/base/property.c @@ -997,26 +997,32 @@ struct fwnode_handle * fwnode_graph_get_next_endpoint(const struct fwnode_handle *fwnode, struct fwnode_handle *prev) { + struct fwnode_handle *ep, *port_parent = NULL; const struct fwnode_handle *parent; - struct fwnode_handle *ep; /* * If this function is in a loop and the previous iteration returned * an endpoint from fwnode->secondary, then we need to use the secondary * as parent rather than @fwnode. */ - if (prev) - parent = fwnode_graph_get_port_parent(prev); - else + if (prev) { + port_parent = fwnode_graph_get_port_parent(prev); + parent = port_parent; + } else { parent = fwnode; + } if (IS_ERR_OR_NULL(parent)) return NULL; ep = fwnode_call_ptr_op(parent, graph_get_next_endpoint, prev); if (ep) - return ep; + goto out_put_port_parent; + + ep = fwnode_graph_get_next_endpoint(parent->secondary, NULL); - return fwnode_graph_get_next_endpoint(parent->secondary, NULL); +out_put_port_parent: + fwnode_handle_put(port_parent); + return ep; } EXPORT_SYMBOL_GPL(fwnode_graph_get_next_endpoint); diff --git a/drivers/base/test/test_async_driver_probe.c b/drivers/base/test/test_async_driver_probe.c index 4d1976ca5072..929410d0dd6f 100644 --- a/drivers/base/test/test_async_driver_probe.c +++ b/drivers/base/test/test_async_driver_probe.c @@ -145,7 +145,7 @@ static int __init test_async_probe_init(void) calltime = ktime_get(); for_each_online_cpu(cpu) { nid = cpu_to_node(cpu); - pdev = &sync_dev[sync_id]; + pdev = &async_dev[async_id]; *pdev = test_platform_device_register_node("test_async_driver", async_id, diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index a2184b428493..a41145d52de9 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -285,6 +285,49 @@ config BLK_DEV_RAM_SIZE The default value is 4096 kilobytes. Only change this if you know what you are doing. +config CDROM_PKTCDVD + tristate "Packet writing on CD/DVD media (DEPRECATED)" + depends on !UML + depends on SCSI + select CDROM + help + Note: This driver is deprecated and will be removed from the + kernel in the near future! + + If you have a CDROM/DVD drive that supports packet writing, say + Y to include support. It should work with any MMC/Mt Fuji + compliant ATAPI or SCSI drive, which is just about any newer + DVD/CD writer. + + Currently only writing to CD-RW, DVD-RW, DVD+RW and DVDRAM discs + is possible. + DVD-RW disks must be in restricted overwrite mode. + + See the file <file:Documentation/cdrom/packet-writing.rst> + for further information on the use of this driver. + + To compile this driver as a module, choose M here: the + module will be called pktcdvd. + +config CDROM_PKTCDVD_BUFFERS + int "Free buffers for data gathering" + depends on CDROM_PKTCDVD + default "8" + help + This controls the maximum number of active concurrent packets. More + concurrent packets can increase write performance, but also require + more memory. Each concurrent packet will require approximately 64Kb + of non-swappable kernel memory, memory which will be allocated when + a disc is opened for writing. + +config CDROM_PKTCDVD_WCACHE + bool "Enable write caching" + depends on CDROM_PKTCDVD + help + If enabled, write caching will be set for the CD-R/W device. For now + this option is dangerous unless the CD-RW media is known good, as we + don't do deferred write error handling yet. + config ATA_OVER_ETH tristate "ATA over Ethernet support" depends on NET diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 962ee65d8ca3..101612cba303 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o obj-$(CONFIG_N64CART) += n64cart.o obj-$(CONFIG_BLK_DEV_RAM) += brd.o obj-$(CONFIG_BLK_DEV_LOOP) += loop.o +obj-$(CONFIG_CDROM_PKTCDVD) += pktcdvd.o obj-$(CONFIG_SUNVDC) += sunvdc.o obj-$(CONFIG_BLK_DEV_NBD) += nbd.o diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index eb14ec8ec04c..e36216d50753 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -1607,6 +1607,8 @@ void drbd_submit_bio(struct bio *bio) struct drbd_device *device = bio->bi_bdev->bd_disk->private_data; bio = bio_split_to_limits(bio); + if (!bio) + return; /* * what we "blindly" assume: diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c new file mode 100644 index 000000000000..2f1a92509271 --- /dev/null +++ b/drivers/block/pktcdvd.c @@ -0,0 +1,2946 @@ +/* + * Copyright (C) 2000 Jens Axboe <axboe@suse.de> + * Copyright (C) 2001-2004 Peter Osterlund <petero2@telia.com> + * Copyright (C) 2006 Thomas Maier <balagi@justmail.de> + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Packet writing layer for ATAPI and SCSI CD-RW, DVD+RW, DVD-RW and + * DVD-RAM devices. + * + * Theory of operation: + * + * At the lowest level, there is the standard driver for the CD/DVD device, + * such as drivers/scsi/sr.c. This driver can handle read and write requests, + * but it doesn't know anything about the special restrictions that apply to + * packet writing. One restriction is that write requests must be aligned to + * packet boundaries on the physical media, and the size of a write request + * must be equal to the packet size. Another restriction is that a + * GPCMD_FLUSH_CACHE command has to be issued to the drive before a read + * command, if the previous command was a write. + * + * The purpose of the packet writing driver is to hide these restrictions from + * higher layers, such as file systems, and present a block device that can be + * randomly read and written using 2kB-sized blocks. + * + * The lowest layer in the packet writing driver is the packet I/O scheduler. + * Its data is defined by the struct packet_iosched and includes two bio + * queues with pending read and write requests. These queues are processed + * by the pkt_iosched_process_queue() function. The write requests in this + * queue are already properly aligned and sized. This layer is responsible for + * issuing the flush cache commands and scheduling the I/O in a good order. + * + * The next layer transforms unaligned write requests to aligned writes. This + * transformation requires reading missing pieces of data from the underlying + * block device, assembling the pieces to full packets and queuing them to the + * packet I/O scheduler. + * + * At the top layer there is a custom ->submit_bio function that forwards + * read requests directly to the iosched queue and puts write requests in the + * unaligned write queue. A kernel thread performs the necessary read + * gathering to convert the unaligned writes to aligned writes and then feeds + * them to the packet I/O scheduler. + * + *************************************************************************/ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/pktcdvd.h> +#include <linux/module.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/compat.h> +#include <linux/kthread.h> +#include <linux/errno.h> +#include <linux/spinlock.h> +#include <linux/file.h> +#include <linux/proc_fs.h> +#include <linux/seq_file.h> +#include <linux/miscdevice.h> +#include <linux/freezer.h> +#include <linux/mutex.h> +#include <linux/slab.h> +#include <linux/backing-dev.h> +#include <scsi/scsi_cmnd.h> +#include <scsi/scsi_ioctl.h> +#include <scsi/scsi.h> +#include <linux/debugfs.h> +#include <linux/device.h> +#include <linux/nospec.h> +#include <linux/uaccess.h> + +#define DRIVER_NAME "pktcdvd" + +#define pkt_err(pd, fmt, ...) \ + pr_err("%s: " fmt, pd->name, ##__VA_ARGS__) +#define pkt_notice(pd, fmt, ...) \ + pr_notice("%s: " fmt, pd->name, ##__VA_ARGS__) +#define pkt_info(pd, fmt, ...) \ + pr_info("%s: " fmt, pd->name, ##__VA_ARGS__) + +#define pkt_dbg(level, pd, fmt, ...) \ +do { \ + if (level == 2 && PACKET_DEBUG >= 2) \ + pr_notice("%s: %s():" fmt, \ + pd->name, __func__, ##__VA_ARGS__); \ + else if (level == 1 && PACKET_DEBUG >= 1) \ + pr_notice("%s: " fmt, pd->name, ##__VA_ARGS__); \ +} while (0) + +#define MAX_SPEED 0xffff + +static DEFINE_MUTEX(pktcdvd_mutex); +static struct pktcdvd_device *pkt_devs[MAX_WRITERS]; +static struct proc_dir_entry *pkt_proc; +static int pktdev_major; +static int write_congestion_on = PKT_WRITE_CONGESTION_ON; +static int write_congestion_off = PKT_WRITE_CONGESTION_OFF; +static struct mutex ctl_mutex; /* Serialize open/close/setup/teardown */ +static mempool_t psd_pool; +static struct bio_set pkt_bio_set; + +static struct class *class_pktcdvd = NULL; /* /sys/class/pktcdvd */ +static struct dentry *pkt_debugfs_root = NULL; /* /sys/kernel/debug/pktcdvd */ + +/* forward declaration */ +static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev); +static int pkt_remove_dev(dev_t pkt_dev); +static int pkt_seq_show(struct seq_file *m, void *p); + +static sector_t get_zone(sector_t sector, struct pktcdvd_device *pd) +{ + return (sector + pd->offset) & ~(sector_t)(pd->settings.size - 1); +} + +/********************************************************** + * sysfs interface for pktcdvd + * by (C) 2006 Thomas Maier <balagi@justmail.de> + + /sys/class/pktcdvd/pktcdvd[0-7]/ + stat/reset + stat/packets_started + stat/packets_finished + stat/kb_written + stat/kb_read + stat/kb_read_gather + write_queue/size + write_queue/congestion_off + write_queue/congestion_on + **********************************************************/ + +static ssize_t packets_started_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pktcdvd_device *pd = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%lu\n", pd->stats.pkt_started); +} +static DEVICE_ATTR_RO(packets_started); + +static ssize_t packets_finished_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pktcdvd_device *pd = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%lu\n", pd->stats.pkt_ended); +} +static DEVICE_ATTR_RO(packets_finished); + +static ssize_t kb_written_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pktcdvd_device *pd = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%lu\n", pd->stats.secs_w >> 1); +} +static DEVICE_ATTR_RO(kb_written); + +static ssize_t kb_read_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pktcdvd_device *pd = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%lu\n", pd->stats.secs_r >> 1); +} +static DEVICE_ATTR_RO(kb_read); + +static ssize_t kb_read_gather_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pktcdvd_device *pd = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%lu\n", pd->stats.secs_rg >> 1); +} +static DEVICE_ATTR_RO(kb_read_gather); + +static ssize_t reset_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct pktcdvd_device *pd = dev_get_drvdata(dev); + + if (len > 0) { + pd->stats.pkt_started = 0; + pd->stats.pkt_ended = 0; + pd->stats.secs_w = 0; + pd->stats.secs_rg = 0; + pd->stats.secs_r = 0; + } + return len; +} +static DEVICE_ATTR_WO(reset); + +static struct attribute *pkt_stat_attrs[] = { + &dev_attr_packets_finished.attr, + &dev_attr_packets_started.attr, + &dev_attr_kb_read.attr, + &dev_attr_kb_written.attr, + &dev_attr_kb_read_gather.attr, + &dev_attr_reset.attr, + NULL, +}; + +static const struct attribute_group pkt_stat_group = { + .name = "stat", + .attrs = pkt_stat_attrs, +}; + +static ssize_t size_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pktcdvd_device *pd = dev_get_drvdata(dev); + int n; + + spin_lock(&pd->lock); + n = sysfs_emit(buf, "%d\n", pd->bio_queue_size); + spin_unlock(&pd->lock); + return n; +} +static DEVICE_ATTR_RO(size); + +static void init_write_congestion_marks(int* lo, int* hi) +{ + if (*hi > 0) { + *hi = max(*hi, 500); + *hi = min(*hi, 1000000); + if (*lo <= 0) + *lo = *hi - 100; + else { + *lo = min(*lo, *hi - 100); + *lo = max(*lo, 100); + } + } else { + *hi = -1; + *lo = -1; + } +} + +static ssize_t congestion_off_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pktcdvd_device *pd = dev_get_drvdata(dev); + int n; + + spin_lock(&pd->lock); + n = sysfs_emit(buf, "%d\n", pd->write_congestion_off); + spin_unlock(&pd->lock); + return n; +} + +static ssize_t congestion_off_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct pktcdvd_device *pd = dev_get_drvdata(dev); + int val; + + if (sscanf(buf, "%d", &val) == 1) { + spin_lock(&pd->lock); + pd->write_congestion_off = val; + init_write_congestion_marks(&pd->write_congestion_off, + &pd->write_congestion_on); + spin_unlock(&pd->lock); + } + return len; +} +static DEVICE_ATTR_RW(congestion_off); + +static ssize_t congestion_on_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pktcdvd_device *pd = dev_get_drvdata(dev); + int n; + + spin_lock(&pd->lock); + n = sysfs_emit(buf, "%d\n", pd->write_congestion_on); + spin_unlock(&pd->lock); + return n; +} + +static ssize_t congestion_on_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct pktcdvd_device *pd = dev_get_drvdata(dev); + int val; + + if (sscanf(buf, "%d", &val) == 1) { + spin_lock(&pd->lock); + pd->write_congestion_on = val; + init_write_congestion_marks(&pd->write_congestion_off, + &pd->write_congestion_on); + spin_unlock(&pd->lock); + } + return len; +} +static DEVICE_ATTR_RW(congestion_on); + +static struct attribute *pkt_wq_attrs[] = { + &dev_attr_congestion_on.attr, + &dev_attr_congestion_off.attr, + &dev_attr_size.attr, + NULL, +}; + +static const struct attribute_group pkt_wq_group = { + .name = "write_queue", + .attrs = pkt_wq_attrs, +}; + +static const struct attribute_group *pkt_groups[] = { + &pkt_stat_group, + &pkt_wq_group, + NULL, +}; + +static void pkt_sysfs_dev_new(struct pktcdvd_device *pd) +{ + if (class_pktcdvd) { + pd->dev = device_create_with_groups(class_pktcdvd, NULL, + MKDEV(0, 0), pd, pkt_groups, + "%s", pd->name); + if (IS_ERR(pd->dev)) + pd->dev = NULL; + } +} + +static void pkt_sysfs_dev_remove(struct pktcdvd_device *pd) +{ + if (class_pktcdvd) + device_unregister(pd->dev); +} + + +/******************************************************************** + /sys/class/pktcdvd/ + add map block device + remove unmap packet dev + device_map show mappings + *******************************************************************/ + +static void class_pktcdvd_release(struct class *cls) +{ + kfree(cls); +} + +static ssize_t device_map_show(struct class *c, struct class_attribute *attr, + char *data) +{ + int n = 0; + int idx; + mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); + for (idx = 0; idx < MAX_WRITERS; idx++) { + struct pktcdvd_device *pd = pkt_devs[idx]; + if (!pd) + continue; + n += sprintf(data+n, "%s %u:%u %u:%u\n", + pd->name, + MAJOR(pd->pkt_dev), MINOR(pd->pkt_dev), + MAJOR(pd->bdev->bd_dev), + MINOR(pd->bdev->bd_dev)); + } + mutex_unlock(&ctl_mutex); + return n; +} +static CLASS_ATTR_RO(device_map); + +static ssize_t add_store(struct class *c, struct class_attribute *attr, + const char *buf, size_t count) +{ + unsigned int major, minor; + + if (sscanf(buf, "%u:%u", &major, &minor) == 2) { + /* pkt_setup_dev() expects caller to hold reference to self */ + if (!try_module_get(THIS_MODULE)) + return -ENODEV; + + pkt_setup_dev(MKDEV(major, minor), NULL); + + module_put(THIS_MODULE); + + return count; + } + + return -EINVAL; +} +static CLASS_ATTR_WO(add); + +static ssize_t remove_store(struct class *c, struct class_attribute *attr, + const char *buf, size_t count) +{ + unsigned int major, minor; + if (sscanf(buf, "%u:%u", &major, &minor) == 2) { + pkt_remove_dev(MKDEV(major, minor)); + return count; + } + return -EINVAL; +} +static CLASS_ATTR_WO(remove); + +static struct attribute *class_pktcdvd_attrs[] = { + &class_attr_add.attr, + &class_attr_remove.attr, + &class_attr_device_map.attr, + NULL, +}; +ATTRIBUTE_GROUPS(class_pktcdvd); + +static int pkt_sysfs_init(void) +{ + int ret = 0; + + /* + * create control files in sysfs + * /sys/class/pktcdvd/... + */ + class_pktcdvd = kzalloc(sizeof(*class_pktcdvd), GFP_KERNEL); + if (!class_pktcdvd) + return -ENOMEM; + class_pktcdvd->name = DRIVER_NAME; + class_pktcdvd->owner = THIS_MODULE; + class_pktcdvd->class_release = class_pktcdvd_release; + class_pktcdvd->class_groups = class_pktcdvd_groups; + ret = class_register(class_pktcdvd); + if (ret) { + kfree(class_pktcdvd); + class_pktcdvd = NULL; + pr_err("failed to create class pktcdvd\n"); + return ret; + } + return 0; +} + +static void pkt_sysfs_cleanup(void) +{ + if (class_pktcdvd) + class_destroy(class_pktcdvd); + class_pktcdvd = NULL; +} + +/******************************************************************** + entries in debugfs + + /sys/kernel/debug/pktcdvd[0-7]/ + info + + *******************************************************************/ + +static int pkt_debugfs_seq_show(struct seq_file *m, void *p) +{ + return pkt_seq_show(m, p); +} + +static int pkt_debugfs_fops_open(struct inode *inode, struct file *file) +{ + return single_open(file, pkt_debugfs_seq_show, inode->i_private); +} + +static const struct file_operations debug_fops = { + .open = pkt_debugfs_fops_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static void pkt_debugfs_dev_new(struct pktcdvd_device *pd) +{ + if (!pkt_debugfs_root) + return; + pd->dfs_d_root = debugfs_create_dir(pd->name, pkt_debugfs_root); + if (!pd->dfs_d_root) + return; + + pd->dfs_f_info = debugfs_create_file("info", 0444, + pd->dfs_d_root, pd, &debug_fops); +} + +static void pkt_debugfs_dev_remove(struct pktcdvd_device *pd) +{ + if (!pkt_debugfs_root) + return; + debugfs_remove(pd->dfs_f_info); + debugfs_remove(pd->dfs_d_root); + pd->dfs_f_info = NULL; + pd->dfs_d_root = NULL; +} + +static void pkt_debugfs_init(void) +{ + pkt_debugfs_root = debugfs_create_dir(DRIVER_NAME, NULL); +} + +static void pkt_debugfs_cleanup(void) +{ + debugfs_remove(pkt_debugfs_root); + pkt_debugfs_root = NULL; +} + +/* ----------------------------------------------------------*/ + + +static void pkt_bio_finished(struct pktcdvd_device *pd) +{ + BUG_ON(atomic_read(&pd->cdrw.pending_bios) <= 0); + if (atomic_dec_and_test(&pd->cdrw.pending_bios)) { + pkt_dbg(2, pd, "queue empty\n"); + atomic_set(&pd->iosched.attention, 1); + wake_up(&pd->wqueue); + } +} + +/* + * Allocate a packet_data struct + */ +static struct packet_data *pkt_alloc_packet_data(int frames) +{ + int i; + struct packet_data *pkt; + + pkt = kzalloc(sizeof(struct packet_data), GFP_KERNEL); + if (!pkt) + goto no_pkt; + + pkt->frames = frames; + pkt->w_bio = bio_kmalloc(frames, GFP_KERNEL); + if (!pkt->w_bio) + goto no_bio; + + for (i = 0; i < frames / FRAMES_PER_PAGE; i++) { + pkt->pages[i] = alloc_page(GFP_KERNEL|__GFP_ZERO); + if (!pkt->pages[i]) + goto no_page; + } + + spin_lock_init(&pkt->lock); + bio_list_init(&pkt->orig_bios); + + for (i = 0; i < frames; i++) { + pkt->r_bios[i] = bio_kmalloc(1, GFP_KERNEL); + if (!pkt->r_bios[i]) + goto no_rd_bio; + } + + return pkt; + +no_rd_bio: + for (i = 0; i < frames; i++) + kfree(pkt->r_bios[i]); +no_page: + for (i = 0; i < frames / FRAMES_PER_PAGE; i++) + if (pkt->pages[i]) + __free_page(pkt->pages[i]); + kfree(pkt->w_bio); +no_bio: + kfree(pkt); +no_pkt: + return NULL; +} + +/* + * Free a packet_data struct + */ +static void pkt_free_packet_data(struct packet_data *pkt) +{ + int i; + + for (i = 0; i < pkt->frames; i++) + kfree(pkt->r_bios[i]); + for (i = 0; i < pkt->frames / FRAMES_PER_PAGE; i++) + __free_page(pkt->pages[i]); + kfree(pkt->w_bio); + kfree(pkt); +} + +static void pkt_shrink_pktlist(struct pktcdvd_device *pd) +{ + struct packet_data *pkt, *next; + + BUG_ON(!list_empty(&pd->cdrw.pkt_active_list)); + + list_for_each_entry_safe(pkt, next, &pd->cdrw.pkt_free_list, list) { + pkt_free_packet_data(pkt); + } + INIT_LIST_HEAD(&pd->cdrw.pkt_free_list); +} + +static int pkt_grow_pktlist(struct pktcdvd_device *pd, int nr_packets) +{ + struct packet_data *pkt; + + BUG_ON(!list_empty(&pd->cdrw.pkt_free_list)); + + while (nr_packets > 0) { + pkt = pkt_alloc_packet_data(pd->settings.size >> 2); + if (!pkt) { + pkt_shrink_pktlist(pd); + return 0; + } + pkt->id = nr_packets; + pkt->pd = pd; + list_add(&pkt->list, &pd->cdrw.pkt_free_list); + nr_packets--; + } + return 1; +} + +static inline struct pkt_rb_node *pkt_rbtree_next(struct pkt_rb_node *node) +{ + struct rb_node *n = rb_next(&node->rb_node); + if (!n) + return NULL; + return rb_entry(n, struct pkt_rb_node, rb_node); +} + +static void pkt_rbtree_erase(struct pktcdvd_device *pd, struct pkt_rb_node *node) +{ + rb_erase(&node->rb_node, &pd->bio_queue); + mempool_free(node, &pd->rb_pool); + pd->bio_queue_size--; + BUG_ON(pd->bio_queue_size < 0); +} + +/* + * Find the first node in the pd->bio_queue rb tree with a starting sector >= s. + */ +static struct pkt_rb_node *pkt_rbtree_find(struct pktcdvd_device *pd, sector_t s) +{ + struct rb_node *n = pd->bio_queue.rb_node; + struct rb_node *next; + struct pkt_rb_node *tmp; + + if (!n) { + BUG_ON(pd->bio_queue_size > 0); + return NULL; + } + + for (;;) { + tmp = rb_entry(n, struct pkt_rb_node, rb_node); + if (s <= tmp->bio->bi_iter.bi_sector) + next = n->rb_left; + else + next = n->rb_right; + if (!next) + break; + n = next; + } + + if (s > tmp->bio->bi_iter.bi_sector) { + tmp = pkt_rbtree_next(tmp); + if (!tmp) + return NULL; + } + BUG_ON(s > tmp->bio->bi_iter.bi_sector); + return tmp; +} + +/* + * Insert a node into the pd->bio_queue rb tree. + */ +static void pkt_rbtree_insert(struct pktcdvd_device *pd, struct pkt_rb_node *node) +{ + struct rb_node **p = &pd->bio_queue.rb_node; + struct rb_node *parent = NULL; + sector_t s = node->bio->bi_iter.bi_sector; + struct pkt_rb_node *tmp; + + while (*p) { + parent = *p; + tmp = rb_entry(parent, struct pkt_rb_node, rb_node); + if (s < tmp->bio->bi_iter.bi_sector) + p = &(*p)->rb_left; + else + p = &(*p)->rb_right; + } + rb_link_node(&node->rb_node, parent, p); + rb_insert_color(&node->rb_node, &pd->bio_queue); + pd->bio_queue_size++; +} + +/* + * Send a packet_command to the underlying block device and + * wait for completion. + */ +static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *cgc) +{ + struct request_queue *q = bdev_get_queue(pd->bdev); + struct scsi_cmnd *scmd; + struct request *rq; + int ret = 0; + + rq = scsi_alloc_request(q, (cgc->data_direction == CGC_DATA_WRITE) ? + REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0); + if (IS_ERR(rq)) + return PTR_ERR(rq); + scmd = blk_mq_rq_to_pdu(rq); + + if (cgc->buflen) { + ret = blk_rq_map_kern(q, rq, cgc->buffer, cgc->buflen, + GFP_NOIO); + if (ret) + goto out; + } + + scmd->cmd_len = COMMAND_SIZE(cgc->cmd[0]); + memcpy(scmd->cmnd, cgc->cmd, CDROM_PACKET_SIZE); + + rq->timeout = 60*HZ; + if (cgc->quiet) + rq->rq_flags |= RQF_QUIET; + + blk_execute_rq(rq, false); + if (scmd->result) + ret = -EIO; +out: + blk_mq_free_request(rq); + return ret; +} + +static const char *sense_key_string(__u8 index) +{ + static const char * const info[] = { + "No sense", "Recovered error", "Not ready", + "Medium error", "Hardware error", "Illegal request", + "Unit attention", "Data protect", "Blank check", + }; + + return index < ARRAY_SIZE(info) ? info[index] : "INVALID"; +} + +/* + * A generic sense dump / resolve mechanism should be implemented across + * all ATAPI + SCSI devices. + */ +static void pkt_dump_sense(struct pktcdvd_device *pd, + struct packet_command *cgc) +{ + struct scsi_sense_hdr *sshdr = cgc->sshdr; + + if (sshdr) + pkt_err(pd, "%*ph - sense %02x.%02x.%02x (%s)\n", + CDROM_PACKET_SIZE, cgc->cmd, + sshdr->sense_key, sshdr->asc, sshdr->ascq, + sense_key_string(sshdr->sense_key)); + else + pkt_err(pd, "%*ph - no sense\n", CDROM_PACKET_SIZE, cgc->cmd); +} + +/* + * flush the drive cache to media + */ +static int pkt_flush_cache(struct pktcdvd_device *pd) +{ + struct packet_command cgc; + + init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE); + cgc.cmd[0] = GPCMD_FLUSH_CACHE; + cgc.quiet = 1; + + /* + * the IMMED bit -- we default to not setting it, although that + * would allow a much faster close, this is safer + */ +#if 0 + cgc.cmd[1] = 1 << 1; +#endif + return pkt_generic_packet(pd, &cgc); +} + +/* + * speed is given as the normal factor, e.g. 4 for 4x + */ +static noinline_for_stack int pkt_set_speed(struct pktcdvd_device *pd, + unsigned write_speed, unsigned read_speed) +{ + struct packet_command cgc; + struct scsi_sense_hdr sshdr; + int ret; + + init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE); + cgc.sshdr = &sshdr; + cgc.cmd[0] = GPCMD_SET_SPEED; + cgc.cmd[2] = (read_speed >> 8) & 0xff; + cgc.cmd[3] = read_speed & 0xff; + cgc.cmd[4] = (write_speed >> 8) & 0xff; + cgc.cmd[5] = write_speed & 0xff; + + ret = pkt_generic_packet(pd, &cgc); + if (ret) + pkt_dump_sense(pd, &cgc); + + return ret; +} + +/* + * Queue a bio for processing by the low-level CD device. Must be called + * from process context. + */ +static void pkt_queue_bio(struct pktcdvd_device *pd, struct bio *bio) +{ + spin_lock(&pd->iosched.lock); + if (bio_data_dir(bio) == READ) + bio_list_add(&pd->iosched.read_queue, bio); + else + bio_list_add(&pd->iosched.write_queue, bio); + spin_unlock(&pd->iosched.lock); + + atomic_set(&pd->iosched.attention, 1); + wake_up(&pd->wqueue); +} + +/* + * Process the queued read/write requests. This function handles special + * requirements for CDRW drives: + * - A cache flush command must be inserted before a read request if the + * previous request was a write. + * - Switching between reading and writing is slow, so don't do it more often + * than necessary. + * - Optimize for throughput at the expense of latency. This means that streaming + * writes will never be interrupted by a read, but if the drive has to seek + * before the next write, switch to reading instead if there are any pending + * read requests. + * - Set the read speed according to current usage pattern. When only reading + * from the device, it's best to use the highest possible read speed, but + * when switching often between reading and writing, it's better to have the + * same read and write speeds. + */ +static void pkt_iosched_process_queue(struct pktcdvd_device *pd) +{ + + if (atomic_read(&pd->iosched.attention) == 0) + return; + atomic_set(&pd->iosched.attention, 0); + + for (;;) { + struct bio *bio; + int reads_queued, writes_queued; + + spin_lock(&pd->iosched.lock); + reads_queued = !bio_list_empty(&pd->iosched.read_queue); + writes_queued = !bio_list_empty(&pd->iosched.write_queue); + spin_unlock(&pd->iosched.lock); + + if (!reads_queued && !writes_queued) + break; + + if (pd->iosched.writing) { + int need_write_seek = 1; + spin_lock(&pd->iosched.lock); + bio = bio_list_peek(&pd->iosched.write_queue); + spin_unlock(&pd->iosched.lock); + if (bio && (bio->bi_iter.bi_sector == + pd->iosched.last_write)) + need_write_seek = 0; + if (need_write_seek && reads_queued) { + if (atomic_read(&pd->cdrw.pending_bios) > 0) { + pkt_dbg(2, pd, "write, waiting\n"); + break; + } + pkt_flush_cache(pd); + pd->iosched.writing = 0; + } + } else { + if (!reads_queued && writes_queued) { + if (atomic_read(&pd->cdrw.pending_bios) > 0) { + pkt_dbg(2, pd, "read, waiting\n"); + break; + } + pd->iosched.writing = 1; + } + } + + spin_lock(&pd->iosched.lock); + if (pd->iosched.writing) + bio = bio_list_pop(&pd->iosched.write_queue); + else + bio = bio_list_pop(&pd->iosched.read_queue); + spin_unlock(&pd->iosched.lock); + + if (!bio) + continue; + + if (bio_data_dir(bio) == READ) + pd->iosched.successive_reads += + bio->bi_iter.bi_size >> 10; + else { + pd->iosched.successive_reads = 0; + pd->iosched.last_write = bio_end_sector(bio); + } + if (pd->iosched.successive_reads >= HI_SPEED_SWITCH) { + if (pd->read_speed == pd->write_speed) { + pd->read_speed = MAX_SPEED; + pkt_set_speed(pd, pd->write_speed, pd->read_speed); + } + } else { + if (pd->read_speed != pd->write_speed) { + pd->read_speed = pd->write_speed; + pkt_set_speed(pd, pd->write_speed, pd->read_speed); + } + } + + atomic_inc(&pd->cdrw.pending_bios); + submit_bio_noacct(bio); + } +} + +/* + * Special care is needed if the underlying block device has a small + * max_phys_segments value. + */ +static int pkt_set_segment_merging(struct pktcdvd_device *pd, struct request_queue *q) +{ + if ((pd->settings.size << 9) / CD_FRAMESIZE + <= queue_max_segments(q)) { + /* + * The cdrom device can handle one segment/frame + */ + clear_bit(PACKET_MERGE_SEGS, &pd->flags); + return 0; + } else if ((pd->settings.size << 9) / PAGE_SIZE + <= queue_max_segments(q)) { + /* + * We can handle this case at the expense of some extra memory + * copies during write operations + */ + set_bit(PACKET_MERGE_SEGS, &pd->flags); + return 0; + } else { + pkt_err(pd, "cdrom max_phys_segments too small\n"); + return -EIO; + } +} + +static void pkt_end_io_read(struct bio *bio) +{ + struct packet_data *pkt = bio->bi_private; + struct pktcdvd_device *pd = pkt->pd; + BUG_ON(!pd); + + pkt_dbg(2, pd, "bio=%p sec0=%llx sec=%llx err=%d\n", + bio, (unsigned long long)pkt->sector, + (unsigned long long)bio->bi_iter.bi_sector, bio->bi_status); + + if (bio->bi_status) + atomic_inc(&pkt->io_errors); + bio_uninit(bio); + if (atomic_dec_and_test(&pkt->io_wait)) { + atomic_inc(&pkt->run_sm); + wake_up(&pd->wqueue); + } + pkt_bio_finished(pd); +} + +static void pkt_end_io_packet_write(struct bio *bio) +{ + struct packet_data *pkt = bio->bi_private; + struct pktcdvd_device *pd = pkt->pd; + BUG_ON(!pd); + + pkt_dbg(2, pd, "id=%d, err=%d\n", pkt->id, bio->bi_status); + + pd->stats.pkt_ended++; + + bio_uninit(bio); + pkt_bio_finished(pd); + atomic_dec(&pkt->io_wait); + atomic_inc(&pkt->run_sm); + wake_up(&pd->wqueue); +} + +/* + * Schedule reads for the holes in a packet + */ +static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt) +{ + int frames_read = 0; + struct bio *bio; + int f; + char written[PACKET_MAX_SIZE]; + + BUG_ON(bio_list_empty(&pkt->orig_bios)); + + atomic_set(&pkt->io_wait, 0); + atomic_set(&pkt->io_errors, 0); + + /* + * Figure out which frames we need to read before we can write. + */ + memset(written, 0, sizeof(written)); + spin_lock(&pkt->lock); + bio_list_for_each(bio, &pkt->orig_bios) { + int first_frame = (bio->bi_iter.bi_sector - pkt->sector) / + (CD_FRAMESIZE >> 9); + int num_frames = bio->bi_iter.bi_size / CD_FRAMESIZE; + pd->stats.secs_w += num_frames * (CD_FRAMESIZE >> 9); + BUG_ON(first_frame < 0); + BUG_ON(first_frame + num_frames > pkt->frames); + for (f = first_frame; f < first_frame + num_frames; f++) + written[f] = 1; + } + spin_unlock(&pkt->lock); + + if (pkt->cache_valid) { + pkt_dbg(2, pd, "zone %llx cached\n", + (unsigned long long)pkt->sector); + goto out_account; + } + + /* + * Schedule reads for missing parts of the packet. + */ + for (f = 0; f < pkt->frames; f++) { + int p, offset; + + if (written[f]) + continue; + + bio = pkt->r_bios[f]; + bio_init(bio, pd->bdev, bio->bi_inline_vecs, 1, REQ_OP_READ); + bio->bi_iter.bi_sector = pkt->sector + f * (CD_FRAMESIZE >> 9); + bio->bi_end_io = pkt_end_io_read; + bio->bi_private = pkt; + + p = (f * CD_FRAMESIZE) / PAGE_SIZE; + offset = (f * CD_FRAMESIZE) % PAGE_SIZE; + pkt_dbg(2, pd, "Adding frame %d, page:%p offs:%d\n", + f, pkt->pages[p], offset); + if (!bio_add_page(bio, pkt->pages[p], CD_FRAMESIZE, offset)) + BUG(); + + atomic_inc(&pkt->io_wait); + pkt_queue_bio(pd, bio); + frames_read++; + } + +out_account: + pkt_dbg(2, pd, "need %d frames for zone %llx\n", + frames_read, (unsigned long long)pkt->sector); + pd->stats.pkt_started++; + pd->stats.secs_rg += frames_read * (CD_FRAMESIZE >> 9); +} + +/* + * Find a packet matching zone, or the least recently used packet if + * there is no match. + */ +static struct packet_data *pkt_get_packet_data(struct pktcdvd_device *pd, int zone) +{ + struct packet_data *pkt; + + list_for_each_entry(pkt, &pd->cdrw.pkt_free_list, list) { + if (pkt->sector == zone || pkt->list.next == &pd->cdrw.pkt_free_list) { + list_del_init(&pkt->list); + if (pkt->sector != zone) + pkt->cache_valid = 0; + return pkt; + } + } + BUG(); + return NULL; +} + +static void pkt_put_packet_data(struct pktcdvd_device *pd, struct packet_data *pkt) +{ + if (pkt->cache_valid) { + list_add(&pkt->list, &pd->cdrw.pkt_free_list); + } else { + list_add_tail(&pkt->list, &pd->cdrw.pkt_free_list); + } +} + +static inline void pkt_set_state(struct packet_data *pkt, enum packet_data_state state) +{ +#if PACKET_DEBUG > 1 + static const char *state_name[] = { + "IDLE", "WAITING", "READ_WAIT", "WRITE_WAIT", "RECOVERY", "FINISHED" + }; + enum packet_data_state old_state = pkt->state; + pkt_dbg(2, pd, "pkt %2d : s=%6llx %s -> %s\n", + pkt->id, (unsigned long long)pkt->sector, + state_name[old_state], state_name[state]); +#endif + pkt->state = state; +} + +/* + * Scan the work queue to see if we can start a new packet. + * returns non-zero if any work was done. + */ +static int pkt_handle_queue(struct pktcdvd_device *pd) +{ + struct packet_data *pkt, *p; + struct bio *bio = NULL; + sector_t zone = 0; /* Suppress gcc warning */ + struct pkt_rb_node *node, *first_node; + struct rb_node *n; + + atomic_set(&pd->scan_queue, 0); + + if (list_empty(&pd->cdrw.pkt_free_list)) { + pkt_dbg(2, pd, "no pkt\n"); + return 0; + } + + /* + * Try to find a zone we are not already working on. + */ + spin_lock(&pd->lock); + first_node = pkt_rbtree_find(pd, pd->current_sector); + if (!first_node) { + n = rb_first(&pd->bio_queue); + if (n) + first_node = rb_entry(n, struct pkt_rb_node, rb_node); + } + node = first_node; + while (node) { + bio = node->bio; + zone = get_zone(bio->bi_iter.bi_sector, pd); + list_for_each_entry(p, &pd->cdrw.pkt_active_list, list) { + if (p->sector == zone) { + bio = NULL; + goto try_next_bio; + } + } + break; +try_next_bio: + node = pkt_rbtree_next(node); + if (!node) { + n = rb_first(&pd->bio_queue); + if (n) + node = rb_entry(n, struct pkt_rb_node, rb_node); + } + if (node == first_node) + node = NULL; + } + spin_unlock(&pd->lock); + if (!bio) { + pkt_dbg(2, pd, "no bio\n"); + return 0; + } + + pkt = pkt_get_packet_data(pd, zone); + + pd->current_sector = zone + pd->settings.size; + pkt->sector = zone; + BUG_ON(pkt->frames != pd->settings.size >> 2); + pkt->write_size = 0; + + /* + * Scan work queue for bios in the same zone and link them + * to this packet. + */ + spin_lock(&pd->lock); + pkt_dbg(2, pd, "looking for zone %llx\n", (unsigned long long)zone); + while ((node = pkt_rbtree_find(pd, zone)) != NULL) { + bio = node->bio; + pkt_dbg(2, pd, "found zone=%llx\n", (unsigned long long) + get_zone(bio->bi_iter.bi_sector, pd)); + if (get_zone(bio->bi_iter.bi_sector, pd) != zone) + break; + pkt_rbtree_erase(pd, node); + spin_lock(&pkt->lock); + bio_list_add(&pkt->orig_bios, bio); + pkt->write_size += bio->bi_iter.bi_size / CD_FRAMESIZE; + spin_unlock(&pkt->lock); + } + /* check write congestion marks, and if bio_queue_size is + * below, wake up any waiters + */ + if (pd->congested && + pd->bio_queue_size <= pd->write_congestion_off) { + pd->congested = false; + wake_up_var(&pd->congested); + } + spin_unlock(&pd->lock); + + pkt->sleep_time = max(PACKET_WAIT_TIME, 1); + pkt_set_state(pkt, PACKET_WAITING_STATE); + atomic_set(&pkt->run_sm, 1); + + spin_lock(&pd->cdrw.active_list_lock); + list_add(&pkt->list, &pd->cdrw.pkt_active_list); + spin_unlock(&pd->cdrw.active_list_lock); + + return 1; +} + +/** + * bio_list_copy_data - copy contents of data buffers from one chain of bios to + * another + * @src: source bio list + * @dst: destination bio list + * + * Stops when it reaches the end of either the @src list or @dst list - that is, + * copies min(src->bi_size, dst->bi_size) bytes (or the equivalent for lists of + * bios). + */ +static void bio_list_copy_data(struct bio *dst, struct bio *src) +{ + struct bvec_iter src_iter = src->bi_iter; + struct bvec_iter dst_iter = dst->bi_iter; + + while (1) { + if (!src_iter.bi_size) { + src = src->bi_next; + if (!src) + break; + + src_iter = src->bi_iter; + } + + if (!dst_iter.bi_size) { + dst = dst->bi_next; + if (!dst) + break; + + dst_iter = dst->bi_iter; + } + + bio_copy_data_iter(dst, &dst_iter, src, &src_iter); + } +} + +/* + * Assemble a bio to write one packet and queue the bio for processing + * by the underlying block device. + */ +static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt) +{ + int f; + + bio_init(pkt->w_bio, pd->bdev, pkt->w_bio->bi_inline_vecs, pkt->frames, + REQ_OP_WRITE); + pkt->w_bio->bi_iter.bi_sector = pkt->sector; + pkt->w_bio->bi_end_io = pkt_end_io_packet_write; + pkt->w_bio->bi_private = pkt; + + /* XXX: locking? */ + for (f = 0; f < pkt->frames; f++) { + struct page *page = pkt->pages[(f * CD_FRAMESIZE) / PAGE_SIZE]; + unsigned offset = (f * CD_FRAMESIZE) % PAGE_SIZE; + + if (!bio_add_page(pkt->w_bio, page, CD_FRAMESIZE, offset)) + BUG(); + } + pkt_dbg(2, pd, "vcnt=%d\n", pkt->w_bio->bi_vcnt); + + /* + * Fill-in bvec with data from orig_bios. + */ + spin_lock(&pkt->lock); + bio_list_copy_data(pkt->w_bio, pkt->orig_bios.head); + + pkt_set_state(pkt, PACKET_WRITE_WAIT_STATE); + spin_unlock(&pkt->lock); + + pkt_dbg(2, pd, "Writing %d frames for zone %llx\n", + pkt->write_size, (unsigned long long)pkt->sector); + + if (test_bit(PACKET_MERGE_SEGS, &pd->flags) || (pkt->write_size < pkt->frames)) + pkt->cache_valid = 1; + else + pkt->cache_valid = 0; + + /* Start the write request */ + atomic_set(&pkt->io_wait, 1); + pkt_queue_bio(pd, pkt->w_bio); +} + +static void pkt_finish_packet(struct packet_data *pkt, blk_status_t status) +{ + struct bio *bio; + + if (status) + pkt->cache_valid = 0; + + /* Finish all bios corresponding to this packet */ + while ((bio = bio_list_pop(&pkt->orig_bios))) { + bio->bi_status = status; + bio_endio(bio); + } +} + +static void pkt_run_state_machine(struct pktcdvd_device *pd, struct packet_data *pkt) +{ + pkt_dbg(2, pd, "pkt %d\n", pkt->id); + + for (;;) { + switch (pkt->state) { + case PACKET_WAITING_STATE: + if ((pkt->write_size < pkt->frames) && (pkt->sleep_time > 0)) + return; + + pkt->sleep_time = 0; + pkt_gather_data(pd, pkt); + pkt_set_state(pkt, PACKET_READ_WAIT_STATE); + break; + + case PACKET_READ_WAIT_STATE: + if (atomic_read(&pkt->io_wait) > 0) + return; + + if (atomic_read(&pkt->io_errors) > 0) { + pkt_set_state(pkt, PACKET_RECOVERY_STATE); + } else { + pkt_start_write(pd, pkt); + } + break; + + case PACKET_WRITE_WAIT_STATE: + if (atomic_read(&pkt->io_wait) > 0) + return; + + if (!pkt->w_bio->bi_status) { + pkt_set_state(pkt, PACKET_FINISHED_STATE); + } else { + pkt_set_state(pkt, PACKET_RECOVERY_STATE); + } + break; + + case PACKET_RECOVERY_STATE: + pkt_dbg(2, pd, "No recovery possible\n"); + pkt_set_state(pkt, PACKET_FINISHED_STATE); + break; + + case PACKET_FINISHED_STATE: + pkt_finish_packet(pkt, pkt->w_bio->bi_status); + return; + + default: + BUG(); + break; + } + } +} + +static void pkt_handle_packets(struct pktcdvd_device *pd) +{ + struct packet_data *pkt, *next; + + /* + * Run state machine for active packets + */ + list_for_each_entry(pkt, &pd->cdrw.pkt_active_list, list) { + if (atomic_read(&pkt->run_sm) > 0) { + atomic_set(&pkt->run_sm, 0); + pkt_run_state_machine(pd, pkt); + } + } + + /* + * Move no longer active packets to the free list + */ + spin_lock(&pd->cdrw.active_list_lock); + list_for_each_entry_safe(pkt, next, &pd->cdrw.pkt_active_list, list) { + if (pkt->state == PACKET_FINISHED_STATE) { + list_del(&pkt->list); + pkt_put_packet_data(pd, pkt); + pkt_set_state(pkt, PACKET_IDLE_STATE); + atomic_set(&pd->scan_queue, 1); + } + } + spin_unlock(&pd->cdrw.active_list_lock); +} + +static void pkt_count_states(struct pktcdvd_device *pd, int *states) +{ + struct packet_data *pkt; + int i; + + for (i = 0; i < PACKET_NUM_STATES; i++) + states[i] = 0; + + spin_lock(&pd->cdrw.active_list_lock); + list_for_each_entry(pkt, &pd->cdrw.pkt_active_list, list) { + states[pkt->state]++; + } + spin_unlock(&pd->cdrw.active_list_lock); +} + +/* + * kcdrwd is woken up when writes have been queued for one of our + * registered devices + */ +static int kcdrwd(void *foobar) +{ + struct pktcdvd_device *pd = foobar; + struct packet_data *pkt; + long min_sleep_time, residue; + + set_user_nice(current, MIN_NICE); + set_freezable(); + + for (;;) { + DECLARE_WAITQUEUE(wait, current); + + /* + * Wait until there is something to do + */ + add_wait_queue(&pd->wqueue, &wait); + for (;;) { + set_current_state(TASK_INTERRUPTIBLE); + + /* Check if we need to run pkt_handle_queue */ + if (atomic_read(&pd->scan_queue) > 0) + goto work_to_do; + + /* Check if we need to run the state machine for some packet */ + list_for_each_entry(pkt, &pd->cdrw.pkt_active_list, list) { + if (atomic_read(&pkt->run_sm) > 0) + goto work_to_do; + } + + /* Check if we need to process the iosched queues */ + if (atomic_read(&pd->iosched.attention) != 0) + goto work_to_do; + + /* Otherwise, go to sleep */ + if (PACKET_DEBUG > 1) { + int states[PACKET_NUM_STATES]; + pkt_count_states(pd, states); + pkt_dbg(2, pd, "i:%d ow:%d rw:%d ww:%d rec:%d fin:%d\n", + states[0], states[1], states[2], + states[3], states[4], states[5]); + } + + min_sleep_time = MAX_SCHEDULE_TIMEOUT; + list_for_each_entry(pkt, &pd->cdrw.pkt_active_list, list) { + if (pkt->sleep_time && pkt->sleep_time < min_sleep_time) + min_sleep_time = pkt->sleep_time; + } + + pkt_dbg(2, pd, "sleeping\n"); + residue = schedule_timeout(min_sleep_time); + pkt_dbg(2, pd, "wake up\n"); + + /* make swsusp happy with our thread */ + try_to_freeze(); + + list_for_each_entry(pkt, &pd->cdrw.pkt_active_list, list) { + if (!pkt->sleep_time) + continue; + pkt->sleep_time -= min_sleep_time - residue; + if (pkt->sleep_time <= 0) { + pkt->sleep_time = 0; + atomic_inc(&pkt->run_sm); + } + } + + if (kthread_should_stop()) + break; + } +work_to_do: + set_current_state(TASK_RUNNING); + remove_wait_queue(&pd->wqueue, &wait); + + if (kthread_should_stop()) + break; + + /* + * if pkt_handle_queue returns true, we can queue + * another request. + */ + while (pkt_handle_queue(pd)) + ; + + /* + * Handle packet state machine + */ + pkt_handle_packets(pd); + + /* + * Handle iosched queues + */ + pkt_iosched_process_queue(pd); + } + + return 0; +} + +static void pkt_print_settings(struct pktcdvd_device *pd) +{ + pkt_info(pd, "%s packets, %u blocks, Mode-%c disc\n", + pd->settings.fp ? "Fixed" : "Variable", + pd->settings.size >> 2, + pd->settings.block_mode == 8 ? '1' : '2'); +} + +static int pkt_mode_sense(struct pktcdvd_device *pd, struct packet_command *cgc, int page_code, int page_control) +{ + memset(cgc->cmd, 0, sizeof(cgc->cmd)); + + cgc->cmd[0] = GPCMD_MODE_SENSE_10; + cgc->cmd[2] = page_code | (page_control << 6); + cgc->cmd[7] = cgc->buflen >> 8; + cgc->cmd[8] = cgc->buflen & 0xff; + cgc->data_direction = CGC_DATA_READ; + return pkt_generic_packet(pd, cgc); +} + +static int pkt_mode_select(struct pktcdvd_device *pd, struct packet_command *cgc) +{ + memset(cgc->cmd, 0, sizeof(cgc->cmd)); + memset(cgc->buffer, 0, 2); + cgc->cmd[0] = GPCMD_MODE_SELECT_10; + cgc->cmd[1] = 0x10; /* PF */ + cgc->cmd[7] = cgc->buflen >> 8; + cgc->cmd[8] = cgc->buflen & 0xff; + cgc->data_direction = CGC_DATA_WRITE; + return pkt_generic_packet(pd, cgc); +} + +static int pkt_get_disc_info(struct pktcdvd_device *pd, disc_information *di) +{ + struct packet_command cgc; + int ret; + + /* set up command and get the disc info */ + init_cdrom_command(&cgc, di, sizeof(*di), CGC_DATA_READ); + cgc.cmd[0] = GPCMD_READ_DISC_INFO; + cgc.cmd[8] = cgc.buflen = 2; + cgc.quiet = 1; + + ret = pkt_generic_packet(pd, &cgc); + if (ret) + return ret; + + /* not all drives have the same disc_info length, so requeue + * packet with the length the drive tells us it can supply + */ + cgc.buflen = be16_to_cpu(di->disc_information_length) + + sizeof(di->disc_information_length); + + if (cgc.buflen > sizeof(disc_information)) + cgc.buflen = sizeof(disc_information); + + cgc.cmd[8] = cgc.buflen; + return pkt_generic_packet(pd, &cgc); +} + +static int pkt_get_track_info(struct pktcdvd_device *pd, __u16 track, __u8 type, track_information *ti) +{ + struct packet_command cgc; + int ret; + + init_cdrom_command(&cgc, ti, 8, CGC_DATA_READ); + cgc.cmd[0] = GPCMD_READ_TRACK_RZONE_INFO; + cgc.cmd[1] = type & 3; + cgc.cmd[4] = (track & 0xff00) >> 8; + cgc.cmd[5] = track & 0xff; + cgc.cmd[8] = 8; + cgc.quiet = 1; + + ret = pkt_generic_packet(pd, &cgc); + if (ret) + return ret; + + cgc.buflen = be16_to_cpu(ti->track_information_length) + + sizeof(ti->track_information_length); + + if (cgc.buflen > sizeof(track_information)) + cgc.buflen = sizeof(track_information); + + cgc.cmd[8] = cgc.buflen; + return pkt_generic_packet(pd, &cgc); +} + +static noinline_for_stack int pkt_get_last_written(struct pktcdvd_device *pd, + long *last_written) +{ + disc_information di; + track_information ti; + __u32 last_track; + int ret; + + ret = pkt_get_disc_info(pd, &di); + if (ret) + return ret; + + last_track = (di.last_track_msb << 8) | di.last_track_lsb; + ret = pkt_get_track_info(pd, last_track, 1, &ti); + if (ret) + return ret; + + /* if this track is blank, try the previous. */ + if (ti.blank) { + last_track--; + ret = pkt_get_track_info(pd, last_track, 1, &ti); + if (ret) + return ret; + } + + /* if last recorded field is valid, return it. */ + if (ti.lra_v) { + *last_written = be32_to_cpu(ti.last_rec_address); + } else { + /* make it up instead */ + *last_written = be32_to_cpu(ti.track_start) + + be32_to_cpu(ti.track_size); + if (ti.free_blocks) + *last_written -= (be32_to_cpu(ti.free_blocks) + 7); + } + return 0; +} + +/* + * write mode select package based on pd->settings + */ +static noinline_for_stack int pkt_set_write_settings(struct pktcdvd_device *pd) +{ + struct packet_command cgc; + struct scsi_sense_hdr sshdr; + write_param_page *wp; + char buffer[128]; + int ret, size; + + /* doesn't apply to DVD+RW or DVD-RAM */ + if ((pd->mmc3_profile == 0x1a) || (pd->mmc3_profile == 0x12)) + return 0; + + memset(buffer, 0, sizeof(buffer)); + init_cdrom_command(&cgc, buffer, sizeof(*wp), CGC_DATA_READ); + cgc.sshdr = &sshdr; + ret = pkt_mode_sense(pd, &cgc, GPMODE_WRITE_PARMS_PAGE, 0); + if (ret) { + pkt_dump_sense(pd, &cgc); + return ret; + } + + size = 2 + ((buffer[0] << 8) | (buffer[1] & 0xff)); + pd->mode_offset = (buffer[6] << 8) | (buffer[7] & 0xff); + if (size > sizeof(buffer)) + size = sizeof(buffer); + + /* + * now get it all + */ + init_cdrom_command(&cgc, buffer, size, CGC_DATA_READ); + cgc.sshdr = &sshdr; + ret = pkt_mode_sense(pd, &cgc, GPMODE_WRITE_PARMS_PAGE, 0); + if (ret) { + pkt_dump_sense(pd, &cgc); + return ret; + } + + /* + * write page is offset header + block descriptor length + */ + wp = (write_param_page *) &buffer[sizeof(struct mode_page_header) + pd->mode_offset]; + + wp->fp = pd->settings.fp; + wp->track_mode = pd->settings.track_mode; + wp->write_type = pd->settings.write_type; + wp->data_block_type = pd->settings.block_mode; + + wp->multi_session = 0; + +#ifdef PACKET_USE_LS + wp->link_size = 7; + wp->ls_v = 1; +#endif + + if (wp->data_block_type == PACKET_BLOCK_MODE1) { + wp->session_format = 0; + wp->subhdr2 = 0x20; + } else if (wp->data_block_type == PACKET_BLOCK_MODE2) { + wp->session_format = 0x20; + wp->subhdr2 = 8; +#if 0 + wp->mcn[0] = 0x80; + memcpy(&wp->mcn[1], PACKET_MCN, sizeof(wp->mcn) - 1); +#endif + } else { + /* + * paranoia + */ + pkt_err(pd, "write mode wrong %d\n", wp->data_block_type); + return 1; + } + wp->packet_size = cpu_to_be32(pd->settings.size >> 2); + + cgc.buflen = cgc.cmd[8] = size; + ret = pkt_mode_select(pd, &cgc); + if (ret) { + pkt_dump_sense(pd, &cgc); + return ret; + } + + pkt_print_settings(pd); + return 0; +} + +/* + * 1 -- we can write to this track, 0 -- we can't + */ +static int pkt_writable_track(struct pktcdvd_device *pd, track_information *ti) +{ + switch (pd->mmc3_profile) { + case 0x1a: /* DVD+RW */ + case 0x12: /* DVD-RAM */ + /* The track is always writable on DVD+RW/DVD-RAM */ + return 1; + default: + break; + } + + if (!ti->packet || !ti->fp) + return 0; + + /* + * "good" settings as per Mt Fuji. + */ + if (ti->rt == 0 && ti->blank == 0) + return 1; + + if (ti->rt == 0 && ti->blank == 1) + return 1; + + if (ti->rt == 1 && ti->blank == 0) + return 1; + + pkt_err(pd, "bad state %d-%d-%d\n", ti->rt, ti->blank, ti->packet); + return 0; +} + +/* + * 1 -- we can write to this disc, 0 -- we can't + */ +static int pkt_writable_disc(struct pktcdvd_device *pd, disc_information *di) +{ + switch (pd->mmc3_profile) { + case 0x0a: /* CD-RW */ + case 0xffff: /* MMC3 not supported */ + break; + case 0x1a: /* DVD+RW */ + case 0x13: /* DVD-RW */ + case 0x12: /* DVD-RAM */ + return 1; + default: + pkt_dbg(2, pd, "Wrong disc profile (%x)\n", + pd->mmc3_profile); + return 0; + } + + /* + * for disc type 0xff we should probably reserve a new track. + * but i'm not sure, should we leave this to user apps? probably. + */ + if (di->disc_type == 0xff) { + pkt_notice(pd, "unknown disc - no track?\n"); + return 0; + } + + if (di->disc_type != 0x20 && di->disc_type != 0) { + pkt_err(pd, "wrong disc type (%x)\n", di->disc_type); + return 0; + } + + if (di->erasable == 0) { + pkt_notice(pd, "disc not erasable\n"); + return 0; + } + + if (di->border_status == PACKET_SESSION_RESERVED) { + pkt_err(pd, "can't write to last track (reserved)\n"); + return 0; + } + + return 1; +} + +static noinline_for_stack int pkt_probe_settings(struct pktcdvd_device *pd) +{ + struct packet_command cgc; + unsigned char buf[12]; + disc_information di; + track_information ti; + int ret, track; + + init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ); + cgc.cmd[0] = GPCMD_GET_CONFIGURATION; + cgc.cmd[8] = 8; + ret = pkt_generic_packet(pd, &cgc); + pd->mmc3_profile = ret ? 0xffff : buf[6] << 8 | buf[7]; + + memset(&di, 0, sizeof(disc_information)); + memset(&ti, 0, sizeof(track_information)); + + ret = pkt_get_disc_info(pd, &di); + if (ret) { + pkt_err(pd, "failed get_disc\n"); + return ret; + } + + if (!pkt_writable_disc(pd, &di)) + return -EROFS; + + pd->type = di.erasable ? PACKET_CDRW : PACKET_CDR; + + track = 1; /* (di.last_track_msb << 8) | di.last_track_lsb; */ + ret = pkt_get_track_info(pd, track, 1, &ti); + if (ret) { + pkt_err(pd, "failed get_track\n"); + return ret; + } + + if (!pkt_writable_track(pd, &ti)) { + pkt_err(pd, "can't write to this track\n"); + return -EROFS; + } + + /* + * we keep packet size in 512 byte units, makes it easier to + * deal with request calculations. + */ + pd->settings.size = be32_to_cpu(ti.fixed_packet_size) << 2; + if (pd->settings.size == 0) { + pkt_notice(pd, "detected zero packet size!\n"); + return -ENXIO; + } + if (pd->settings.size > PACKET_MAX_SECTORS) { + pkt_err(pd, "packet size is too big\n"); + return -EROFS; + } + pd->settings.fp = ti.fp; + pd->offset = (be32_to_cpu(ti.track_start) << 2) & (pd->settings.size - 1); + + if (ti.nwa_v) { + pd->nwa = be32_to_cpu(ti.next_writable); + set_bit(PACKET_NWA_VALID, &pd->flags); + } + + /* + * in theory we could use lra on -RW media as well and just zero + * blocks that haven't been written yet, but in practice that + * is just a no-go. we'll use that for -R, naturally. + */ + if (ti.lra_v) { + pd->lra = be32_to_cpu(ti.last_rec_address); + set_bit(PACKET_LRA_VALID, &pd->flags); + } else { + pd->lra = 0xffffffff; + set_bit(PACKET_LRA_VALID, &pd->flags); + } + + /* + * fine for now + */ + pd->settings.link_loss = 7; + pd->settings.write_type = 0; /* packet */ + pd->settings.track_mode = ti.track_mode; + + /* + * mode1 or mode2 disc + */ + switch (ti.data_mode) { + case PACKET_MODE1: + pd->settings.block_mode = PACKET_BLOCK_MODE1; + break; + case PACKET_MODE2: + pd->settings.block_mode = PACKET_BLOCK_MODE2; + break; + default: + pkt_err(pd, "unknown data mode\n"); + return -EROFS; + } + return 0; +} + +/* + * enable/disable write caching on drive + */ +static noinline_for_stack int pkt_write_caching(struct pktcdvd_device *pd, + int set) +{ + struct packet_command cgc; + struct scsi_sense_hdr sshdr; + unsigned char buf[64]; + int ret; + + init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ); + cgc.sshdr = &sshdr; + cgc.buflen = pd->mode_offset + 12; + + /* + * caching mode page might not be there, so quiet this command + */ + cgc.quiet = 1; + + ret = pkt_mode_sense(pd, &cgc, GPMODE_WCACHING_PAGE, 0); + if (ret) + return ret; + + buf[pd->mode_offset + 10] |= (!!set << 2); + + cgc.buflen = cgc.cmd[8] = 2 + ((buf[0] << 8) | (buf[1] & 0xff)); + ret = pkt_mode_select(pd, &cgc); + if (ret) { + pkt_err(pd, "write caching control failed\n"); + pkt_dump_sense(pd, &cgc); + } else if (!ret && set) + pkt_notice(pd, "enabled write caching\n"); + return ret; +} + +static int pkt_lock_door(struct pktcdvd_device *pd, int lockflag) +{ + struct packet_command cgc; + + init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE); + cgc.cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL; + cgc.cmd[4] = lockflag ? 1 : 0; + return pkt_generic_packet(pd, &cgc); +} + +/* + * Returns drive maximum write speed + */ +static noinline_for_stack int pkt_get_max_speed(struct pktcdvd_device *pd, + unsigned *write_speed) +{ + struct packet_command cgc; + struct scsi_sense_hdr sshdr; + unsigned char buf[256+18]; + unsigned char *cap_buf; + int ret, offset; + + cap_buf = &buf[sizeof(struct mode_page_header) + pd->mode_offset]; + init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_UNKNOWN); + cgc.sshdr = &sshdr; + + ret = pkt_mode_sense(pd, &cgc, GPMODE_CAPABILITIES_PAGE, 0); + if (ret) { + cgc.buflen = pd->mode_offset + cap_buf[1] + 2 + + sizeof(struct mode_page_header); + ret = pkt_mode_sense(pd, &cgc, GPMODE_CAPABILITIES_PAGE, 0); + if (ret) { + pkt_dump_sense(pd, &cgc); + return ret; + } + } + + offset = 20; /* Obsoleted field, used by older drives */ + if (cap_buf[1] >= 28) + offset = 28; /* Current write speed selected */ + if (cap_buf[1] >= 30) { + /* If the drive reports at least one "Logical Unit Write + * Speed Performance Descriptor Block", use the information + * in the first block. (contains the highest speed) + */ + int num_spdb = (cap_buf[30] << 8) + cap_buf[31]; + if (num_spdb > 0) + offset = 34; + } + + *write_speed = (cap_buf[offset] << 8) | cap_buf[offset + 1]; + return 0; +} + +/* These tables from cdrecord - I don't have orange book */ +/* standard speed CD-RW (1-4x) */ +static char clv_to_speed[16] = { + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */ + 0, 2, 4, 6, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; +/* high speed CD-RW (-10x) */ +static char hs_clv_to_speed[16] = { + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */ + 0, 2, 4, 6, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; +/* ultra high speed CD-RW */ +static char us_clv_to_speed[16] = { + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */ + 0, 2, 4, 8, 0, 0,16, 0,24,32,40,48, 0, 0, 0, 0 +}; + +/* + * reads the maximum media speed from ATIP + */ +static noinline_for_stack int pkt_media_speed(struct pktcdvd_device *pd, + unsigned *speed) +{ + struct packet_command cgc; + struct scsi_sense_hdr sshdr; + unsigned char buf[64]; + unsigned int size, st, sp; + int ret; + + init_cdrom_command(&cgc, buf, 2, CGC_DATA_READ); + cgc.sshdr = &sshdr; + cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP; + cgc.cmd[1] = 2; + cgc.cmd[2] = 4; /* READ ATIP */ + cgc.cmd[8] = 2; + ret = pkt_generic_packet(pd, &cgc); + if (ret) { + pkt_dump_sense(pd, &cgc); + return ret; + } + size = ((unsigned int) buf[0]<<8) + buf[1] + 2; + if (size > sizeof(buf)) + size = sizeof(buf); + + init_cdrom_command(&cgc, buf, size, CGC_DATA_READ); + cgc.sshdr = &sshdr; + cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP; + cgc.cmd[1] = 2; + cgc.cmd[2] = 4; + cgc.cmd[8] = size; + ret = pkt_generic_packet(pd, &cgc); + if (ret) { + pkt_dump_sense(pd, &cgc); + return ret; + } + + if (!(buf[6] & 0x40)) { + pkt_notice(pd, "disc type is not CD-RW\n"); + return 1; + } + if (!(buf[6] & 0x4)) { + pkt_notice(pd, "A1 values on media are not valid, maybe not CDRW?\n"); + return 1; + } + + st = (buf[6] >> 3) & 0x7; /* disc sub-type */ + + sp = buf[16] & 0xf; /* max speed from ATIP A1 field */ + + /* Info from cdrecord */ + switch (st) { + case 0: /* standard speed */ + *speed = clv_to_speed[sp]; + break; + case 1: /* high speed */ + *speed = hs_clv_to_speed[sp]; + break; + case 2: /* ultra high speed */ + *speed = us_clv_to_speed[sp]; + break; + default: + pkt_notice(pd, "unknown disc sub-type %d\n", st); + return 1; + } + if (*speed) { + pkt_info(pd, "maximum media speed: %d\n", *speed); + return 0; + } else { + pkt_notice(pd, "unknown speed %d for sub-type %d\n", sp, st); + return 1; + } +} + +static noinline_for_stack int pkt_perform_opc(struct pktcdvd_device *pd) +{ + struct packet_command cgc; + struct scsi_sense_hdr sshdr; + int ret; + + pkt_dbg(2, pd, "Performing OPC\n"); + + init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE); + cgc.sshdr = &sshdr; + cgc.timeout = 60*HZ; + cgc.cmd[0] = GPCMD_SEND_OPC; + cgc.cmd[1] = 1; + ret = pkt_generic_packet(pd, &cgc); + if (ret) + pkt_dump_sense(pd, &cgc); + return ret; +} + +static int pkt_open_write(struct pktcdvd_device *pd) +{ + int ret; + unsigned int write_speed, media_write_speed, read_speed; + + ret = pkt_probe_settings(pd); + if (ret) { + pkt_dbg(2, pd, "failed probe\n"); + return ret; + } + + ret = pkt_set_write_settings(pd); + if (ret) { + pkt_dbg(1, pd, "failed saving write settings\n"); + return -EIO; + } + + pkt_write_caching(pd, USE_WCACHING); + + ret = pkt_get_max_speed(pd, &write_speed); + if (ret) + write_speed = 16 * 177; + switch (pd->mmc3_profile) { + case 0x13: /* DVD-RW */ + case 0x1a: /* DVD+RW */ + case 0x12: /* DVD-RAM */ + pkt_dbg(1, pd, "write speed %ukB/s\n", write_speed); + break; + default: + ret = pkt_media_speed(pd, &media_write_speed); + if (ret) + media_write_speed = 16; + write_speed = min(write_speed, media_write_speed * 177); + pkt_dbg(1, pd, "write speed %ux\n", write_speed / 176); + break; + } + read_speed = write_speed; + + ret = pkt_set_speed(pd, write_speed, read_speed); + if (ret) { + pkt_dbg(1, pd, "couldn't set write speed\n"); + return -EIO; + } + pd->write_speed = write_speed; + pd->read_speed = read_speed; + + ret = pkt_perform_opc(pd); + if (ret) { + pkt_dbg(1, pd, "Optimum Power Calibration failed\n"); + } + + return 0; +} + +/* + * called at open time. + */ +static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write) +{ + int ret; + long lba; + struct request_queue *q; + struct block_device *bdev; + + /* + * We need to re-open the cdrom device without O_NONBLOCK to be able + * to read/write from/to it. It is already opened in O_NONBLOCK mode + * so open should not fail. + */ + bdev = blkdev_get_by_dev(pd->bdev->bd_dev, FMODE_READ | FMODE_EXCL, pd); + if (IS_ERR(bdev)) { + ret = PTR_ERR(bdev); + goto out; + } + + ret = pkt_get_last_written(pd, &lba); + if (ret) { + pkt_err(pd, "pkt_get_last_written failed\n"); + goto out_putdev; + } + + set_capacity(pd->disk, lba << 2); + set_capacity_and_notify(pd->bdev->bd_disk, lba << 2); + + q = bdev_get_queue(pd->bdev); + if (write) { + ret = pkt_open_write(pd); + if (ret) + goto out_putdev; + /* + * Some CDRW drives can not handle writes larger than one packet, + * even if the size is a multiple of the packet size. + */ + blk_queue_max_hw_sectors(q, pd->settings.size); + set_bit(PACKET_WRITABLE, &pd->flags); + } else { + pkt_set_speed(pd, MAX_SPEED, MAX_SPEED); + clear_bit(PACKET_WRITABLE, &pd->flags); + } + + ret = pkt_set_segment_merging(pd, q); + if (ret) + goto out_putdev; + + if (write) { + if (!pkt_grow_pktlist(pd, CONFIG_CDROM_PKTCDVD_BUFFERS)) { + pkt_err(pd, "not enough memory for buffers\n"); + ret = -ENOMEM; + goto out_putdev; + } + pkt_info(pd, "%lukB available on disc\n", lba << 1); + } + + return 0; + +out_putdev: + blkdev_put(bdev, FMODE_READ | FMODE_EXCL); +out: + return ret; +} + +/* + * called when the device is closed. makes sure that the device flushes + * the internal cache before we close. + */ +static void pkt_release_dev(struct pktcdvd_device *pd, int flush) +{ + if (flush && pkt_flush_cache(pd)) + pkt_dbg(1, pd, "not flushing cache\n"); + + pkt_lock_door(pd, 0); + + pkt_set_speed(pd, MAX_SPEED, MAX_SPEED); + blkdev_put(pd->bdev, FMODE_READ | FMODE_EXCL); + + pkt_shrink_pktlist(pd); +} + +static struct pktcdvd_device *pkt_find_dev_from_minor(unsigned int dev_minor) +{ + if (dev_minor >= MAX_WRITERS) + return NULL; + + dev_minor = array_index_nospec(dev_minor, MAX_WRITERS); + return pkt_devs[dev_minor]; +} + +static int pkt_open(struct block_device *bdev, fmode_t mode) +{ + struct pktcdvd_device *pd = NULL; + int ret; + + mutex_lock(&pktcdvd_mutex); + mutex_lock(&ctl_mutex); + pd = pkt_find_dev_from_minor(MINOR(bdev->bd_dev)); + if (!pd) { + ret = -ENODEV; + goto out; + } + BUG_ON(pd->refcnt < 0); + + pd->refcnt++; + if (pd->refcnt > 1) { + if ((mode & FMODE_WRITE) && + !test_bit(PACKET_WRITABLE, &pd->flags)) { + ret = -EBUSY; + goto out_dec; + } + } else { + ret = pkt_open_dev(pd, mode & FMODE_WRITE); + if (ret) + goto out_dec; + /* + * needed here as well, since ext2 (among others) may change + * the blocksize at mount time + */ + set_blocksize(bdev, CD_FRAMESIZE); + } + + mutex_unlock(&ctl_mutex); + mutex_unlock(&pktcdvd_mutex); + return 0; + +out_dec: + pd->refcnt--; +out: + mutex_unlock(&ctl_mutex); + mutex_unlock(&pktcdvd_mutex); + return ret; +} + +static void pkt_close(struct gendisk *disk, fmode_t mode) +{ + struct pktcdvd_device *pd = disk->private_data; + + mutex_lock(&pktcdvd_mutex); + mutex_lock(&ctl_mutex); + pd->refcnt--; + BUG_ON(pd->refcnt < 0); + if (pd->refcnt == 0) { + int flush = test_bit(PACKET_WRITABLE, &pd->flags); + pkt_release_dev(pd, flush); + } + mutex_unlock(&ctl_mutex); + mutex_unlock(&pktcdvd_mutex); +} + + +static void pkt_end_io_read_cloned(struct bio *bio) +{ + struct packet_stacked_data *psd = bio->bi_private; + struct pktcdvd_device *pd = psd->pd; + + psd->bio->bi_status = bio->bi_status; + bio_put(bio); + bio_endio(psd->bio); + mempool_free(psd, &psd_pool); + pkt_bio_finished(pd); +} + +static void pkt_make_request_read(struct pktcdvd_device *pd, struct bio *bio) +{ + struct bio *cloned_bio = + bio_alloc_clone(pd->bdev, bio, GFP_NOIO, &pkt_bio_set); + struct packet_stacked_data *psd = mempool_alloc(&psd_pool, GFP_NOIO); + + psd->pd = pd; + psd->bio = bio; + cloned_bio->bi_private = psd; + cloned_bio->bi_end_io = pkt_end_io_read_cloned; + pd->stats.secs_r += bio_sectors(bio); + pkt_queue_bio(pd, cloned_bio); +} + +static void pkt_make_request_write(struct request_queue *q, struct bio *bio) +{ + struct pktcdvd_device *pd = q->queuedata; + sector_t zone; + struct packet_data *pkt; + int was_empty, blocked_bio; + struct pkt_rb_node *node; + + zone = get_zone(bio->bi_iter.bi_sector, pd); + + /* + * If we find a matching packet in state WAITING or READ_WAIT, we can + * just append this bio to that packet. + */ + spin_lock(&pd->cdrw.active_list_lock); + blocked_bio = 0; + list_for_each_entry(pkt, &pd->cdrw.pkt_active_list, list) { + if (pkt->sector == zone) { + spin_lock(&pkt->lock); + if ((pkt->state == PACKET_WAITING_STATE) || + (pkt->state == PACKET_READ_WAIT_STATE)) { + bio_list_add(&pkt->orig_bios, bio); + pkt->write_size += + bio->bi_iter.bi_size / CD_FRAMESIZE; + if ((pkt->write_size >= pkt->frames) && + (pkt->state == PACKET_WAITING_STATE)) { + atomic_inc(&pkt->run_sm); + wake_up(&pd->wqueue); + } + spin_unlock(&pkt->lock); + spin_unlock(&pd->cdrw.active_list_lock); + return; + } else { + blocked_bio = 1; + } + spin_unlock(&pkt->lock); + } + } + spin_unlock(&pd->cdrw.active_list_lock); + + /* + * Test if there is enough room left in the bio work queue + * (queue size >= congestion on mark). + * If not, wait till the work queue size is below the congestion off mark. + */ + spin_lock(&pd->lock); + if (pd->write_congestion_on > 0 + && pd->bio_queue_size >= pd->write_congestion_on) { + struct wait_bit_queue_entry wqe; + + init_wait_var_entry(&wqe, &pd->congested, 0); + for (;;) { + prepare_to_wait_event(__var_waitqueue(&pd->congested), + &wqe.wq_entry, + TASK_UNINTERRUPTIBLE); + if (pd->bio_queue_size <= pd->write_congestion_off) + break; + pd->congested = true; + spin_unlock(&pd->lock); + schedule(); + spin_lock(&pd->lock); + } + } + spin_unlock(&pd->lock); + + /* + * No matching packet found. Store the bio in the work queue. + */ + node = mempool_alloc(&pd->rb_pool, GFP_NOIO); + node->bio = bio; + spin_lock(&pd->lock); + BUG_ON(pd->bio_queue_size < 0); + was_empty = (pd->bio_queue_size == 0); + pkt_rbtree_insert(pd, node); + spin_unlock(&pd->lock); + + /* + * Wake up the worker thread. + */ + atomic_set(&pd->scan_queue, 1); + if (was_empty) { + /* This wake_up is required for correct operation */ + wake_up(&pd->wqueue); + } else if (!list_empty(&pd->cdrw.pkt_free_list) && !blocked_bio) { + /* + * This wake up is not required for correct operation, + * but improves performance in some cases. + */ + wake_up(&pd->wqueue); + } +} + +static void pkt_submit_bio(struct bio *bio) +{ + struct pktcdvd_device *pd = bio->bi_bdev->bd_disk->queue->queuedata; + struct bio *split; + + bio = bio_split_to_limits(bio); + if (!bio) + return; + + pkt_dbg(2, pd, "start = %6llx stop = %6llx\n", + (unsigned long long)bio->bi_iter.bi_sector, + (unsigned long long)bio_end_sector(bio)); + + /* + * Clone READ bios so we can have our own bi_end_io callback. + */ + if (bio_data_dir(bio) == READ) { + pkt_make_request_read(pd, bio); + return; + } + + if (!test_bit(PACKET_WRITABLE, &pd->flags)) { + pkt_notice(pd, "WRITE for ro device (%llu)\n", + (unsigned long long)bio->bi_iter.bi_sector); + goto end_io; + } + + if (!bio->bi_iter.bi_size || (bio->bi_iter.bi_size % CD_FRAMESIZE)) { + pkt_err(pd, "wrong bio size\n"); + goto end_io; + } + + do { + sector_t zone = get_zone(bio->bi_iter.bi_sector, pd); + sector_t last_zone = get_zone(bio_end_sector(bio) - 1, pd); + + if (last_zone != zone) { + BUG_ON(last_zone != zone + pd->settings.size); + + split = bio_split(bio, last_zone - + bio->bi_iter.bi_sector, + GFP_NOIO, &pkt_bio_set); + bio_chain(split, bio); + } else { + split = bio; + } + + pkt_make_request_write(bio->bi_bdev->bd_disk->queue, split); + } while (split != bio); + + return; +end_io: + bio_io_error(bio); +} + +static void pkt_init_queue(struct pktcdvd_device *pd) +{ + struct request_queue *q = pd->disk->queue; + + blk_queue_logical_block_size(q, CD_FRAMESIZE); + blk_queue_max_hw_sectors(q, PACKET_MAX_SECTORS); + q->queuedata = pd; +} + +static int pkt_seq_show(struct seq_file *m, void *p) +{ + struct pktcdvd_device *pd = m->private; + char *msg; + int states[PACKET_NUM_STATES]; + + seq_printf(m, "Writer %s mapped to %pg:\n", pd->name, pd->bdev); + + seq_printf(m, "\nSettings:\n"); + seq_printf(m, "\tpacket size:\t\t%dkB\n", pd->settings.size / 2); + + if (pd->settings.write_type == 0) + msg = "Packet"; + else + msg = "Unknown"; + seq_printf(m, "\twrite type:\t\t%s\n", msg); + + seq_printf(m, "\tpacket type:\t\t%s\n", pd->settings.fp ? "Fixed" : "Variable"); + seq_printf(m, "\tlink loss:\t\t%d\n", pd->settings.link_loss); + + seq_printf(m, "\ttrack mode:\t\t%d\n", pd->settings.track_mode); + + if (pd->settings.block_mode == PACKET_BLOCK_MODE1) + msg = "Mode 1"; + else if (pd->settings.block_mode == PACKET_BLOCK_MODE2) + msg = "Mode 2"; + else + msg = "Unknown"; + seq_printf(m, "\tblock mode:\t\t%s\n", msg); + + seq_printf(m, "\nStatistics:\n"); + seq_printf(m, "\tpackets started:\t%lu\n", pd->stats.pkt_started); + seq_printf(m, "\tpackets ended:\t\t%lu\n", pd->stats.pkt_ended); + seq_printf(m, "\twritten:\t\t%lukB\n", pd->stats.secs_w >> 1); + seq_printf(m, "\tread gather:\t\t%lukB\n", pd->stats.secs_rg >> 1); + seq_printf(m, "\tread:\t\t\t%lukB\n", pd->stats.secs_r >> 1); + + seq_printf(m, "\nMisc:\n"); + seq_printf(m, "\treference count:\t%d\n", pd->refcnt); + seq_printf(m, "\tflags:\t\t\t0x%lx\n", pd->flags); + seq_printf(m, "\tread speed:\t\t%ukB/s\n", pd->read_speed); + seq_printf(m, "\twrite speed:\t\t%ukB/s\n", pd->write_speed); + seq_printf(m, "\tstart offset:\t\t%lu\n", pd->offset); + seq_printf(m, "\tmode page offset:\t%u\n", pd->mode_offset); + + seq_printf(m, "\nQueue state:\n"); + seq_printf(m, "\tbios queued:\t\t%d\n", pd->bio_queue_size); + seq_printf(m, "\tbios pending:\t\t%d\n", atomic_read(&pd->cdrw.pending_bios)); + seq_printf(m, "\tcurrent sector:\t\t0x%llx\n", (unsigned long long)pd->current_sector); + + pkt_count_states(pd, states); + seq_printf(m, "\tstate:\t\t\ti:%d ow:%d rw:%d ww:%d rec:%d fin:%d\n", + states[0], states[1], states[2], states[3], states[4], states[5]); + + seq_printf(m, "\twrite congestion marks:\toff=%d on=%d\n", + pd->write_congestion_off, + pd->write_congestion_on); + return 0; +} + +static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev) +{ + int i; + struct block_device *bdev; + struct scsi_device *sdev; + + if (pd->pkt_dev == dev) { + pkt_err(pd, "recursive setup not allowed\n"); + return -EBUSY; + } + for (i = 0; i < MAX_WRITERS; i++) { + struct pktcdvd_device *pd2 = pkt_devs[i]; + if (!pd2) + continue; + if (pd2->bdev->bd_dev == dev) { + pkt_err(pd, "%pg already setup\n", pd2->bdev); + return -EBUSY; + } + if (pd2->pkt_dev == dev) { + pkt_err(pd, "can't chain pktcdvd devices\n"); + return -EBUSY; + } + } + + bdev = blkdev_get_by_dev(dev, FMODE_READ | FMODE_NDELAY, NULL); + if (IS_ERR(bdev)) + return PTR_ERR(bdev); + sdev = scsi_device_from_queue(bdev->bd_disk->queue); + if (!sdev) { + blkdev_put(bdev, FMODE_READ | FMODE_NDELAY); + return -EINVAL; + } + put_device(&sdev->sdev_gendev); + + /* This is safe, since we have a reference from open(). */ + __module_get(THIS_MODULE); + + pd->bdev = bdev; + set_blocksize(bdev, CD_FRAMESIZE); + + pkt_init_queue(pd); + + atomic_set(&pd->cdrw.pending_bios, 0); + pd->cdrw.thread = kthread_run(kcdrwd, pd, "%s", pd->name); + if (IS_ERR(pd->cdrw.thread)) { + pkt_err(pd, "can't start kernel thread\n"); + goto out_mem; + } + + proc_create_single_data(pd->name, 0, pkt_proc, pkt_seq_show, pd); + pkt_dbg(1, pd, "writer mapped to %pg\n", bdev); + return 0; + +out_mem: + blkdev_put(bdev, FMODE_READ | FMODE_NDELAY); + /* This is safe: open() is still holding a reference. */ + module_put(THIS_MODULE); + return -ENOMEM; +} + +static int pkt_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) +{ + struct pktcdvd_device *pd = bdev->bd_disk->private_data; + int ret; + + pkt_dbg(2, pd, "cmd %x, dev %d:%d\n", + cmd, MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev)); + + mutex_lock(&pktcdvd_mutex); + switch (cmd) { + case CDROMEJECT: + /* + * The door gets locked when the device is opened, so we + * have to unlock it or else the eject command fails. + */ + if (pd->refcnt == 1) + pkt_lock_door(pd, 0); + fallthrough; + /* + * forward selected CDROM ioctls to CD-ROM, for UDF + */ + case CDROMMULTISESSION: + case CDROMREADTOCENTRY: + case CDROM_LAST_WRITTEN: + case CDROM_SEND_PACKET: + case SCSI_IOCTL_SEND_COMMAND: + if (!bdev->bd_disk->fops->ioctl) + ret = -ENOTTY; + else + ret = bdev->bd_disk->fops->ioctl(bdev, mode, cmd, arg); + break; + default: + pkt_dbg(2, pd, "Unknown ioctl (%x)\n", cmd); + ret = -ENOTTY; + } + mutex_unlock(&pktcdvd_mutex); + + return ret; +} + +static unsigned int pkt_check_events(struct gendisk *disk, + unsigned int clearing) +{ + struct pktcdvd_device *pd = disk->private_data; + struct gendisk *attached_disk; + + if (!pd) + return 0; + if (!pd->bdev) + return 0; + attached_disk = pd->bdev->bd_disk; + if (!attached_disk || !attached_disk->fops->check_events) + return 0; + return attached_disk->fops->check_events(attached_disk, clearing); +} + +static char *pkt_devnode(struct gendisk *disk, umode_t *mode) +{ + return kasprintf(GFP_KERNEL, "pktcdvd/%s", disk->disk_name); +} + +static const struct block_device_operations pktcdvd_ops = { + .owner = THIS_MODULE, + .submit_bio = pkt_submit_bio, + .open = pkt_open, + .release = pkt_close, + .ioctl = pkt_ioctl, + .compat_ioctl = blkdev_compat_ptr_ioctl, + .check_events = pkt_check_events, + .devnode = pkt_devnode, +}; + +/* + * Set up mapping from pktcdvd device to CD-ROM device. + */ +static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev) +{ + int idx; + int ret = -ENOMEM; + struct pktcdvd_device *pd; + struct gendisk *disk; + + mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); + + for (idx = 0; idx < MAX_WRITERS; idx++) + if (!pkt_devs[idx]) + break; + if (idx == MAX_WRITERS) { + pr_err("max %d writers supported\n", MAX_WRITERS); + ret = -EBUSY; + goto out_mutex; + } + + pd = kzalloc(sizeof(struct pktcdvd_device), GFP_KERNEL); + if (!pd) + goto out_mutex; + + ret = mempool_init_kmalloc_pool(&pd->rb_pool, PKT_RB_POOL_SIZE, + sizeof(struct pkt_rb_node)); + if (ret) + goto out_mem; + + INIT_LIST_HEAD(&pd->cdrw.pkt_free_list); + INIT_LIST_HEAD(&pd->cdrw.pkt_active_list); + spin_lock_init(&pd->cdrw.active_list_lock); + + spin_lock_init(&pd->lock); + spin_lock_init(&pd->iosched.lock); + bio_list_init(&pd->iosched.read_queue); + bio_list_init(&pd->iosched.write_queue); + sprintf(pd->name, DRIVER_NAME"%d", idx); + init_waitqueue_head(&pd->wqueue); + pd->bio_queue = RB_ROOT; + + pd->write_congestion_on = write_congestion_on; + pd->write_congestion_off = write_congestion_off; + + ret = -ENOMEM; + disk = blk_alloc_disk(NUMA_NO_NODE); + if (!disk) + goto out_mem; + pd->disk = disk; + disk->major = pktdev_major; + disk->first_minor = idx; + disk->minors = 1; + disk->fops = &pktcdvd_ops; + disk->flags = GENHD_FL_REMOVABLE | GENHD_FL_NO_PART; + strcpy(disk->disk_name, pd->name); + disk->private_data = pd; + + pd->pkt_dev = MKDEV(pktdev_major, idx); + ret = pkt_new_dev(pd, dev); + if (ret) + goto out_mem2; + + /* inherit events of the host device */ + disk->events = pd->bdev->bd_disk->events; + + ret = add_disk(disk); + if (ret) + goto out_mem2; + + pkt_sysfs_dev_new(pd); + pkt_debugfs_dev_new(pd); + + pkt_devs[idx] = pd; + if (pkt_dev) + *pkt_dev = pd->pkt_dev; + + mutex_unlock(&ctl_mutex); + return 0; + +out_mem2: + put_disk(disk); +out_mem: + mempool_exit(&pd->rb_pool); + kfree(pd); +out_mutex: + mutex_unlock(&ctl_mutex); + pr_err("setup of pktcdvd device failed\n"); + return ret; +} + +/* + * Tear down mapping from pktcdvd device to CD-ROM device. + */ +static int pkt_remove_dev(dev_t pkt_dev) +{ + struct pktcdvd_device *pd; + int idx; + int ret = 0; + + mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); + + for (idx = 0; idx < MAX_WRITERS; idx++) { + pd = pkt_devs[idx]; + if (pd && (pd->pkt_dev == pkt_dev)) + break; + } + if (idx == MAX_WRITERS) { + pr_debug("dev not setup\n"); + ret = -ENXIO; + goto out; + } + + if (pd->refcnt > 0) { + ret = -EBUSY; + goto out; + } + if (!IS_ERR(pd->cdrw.thread)) + kthread_stop(pd->cdrw.thread); + + pkt_devs[idx] = NULL; + + pkt_debugfs_dev_remove(pd); + pkt_sysfs_dev_remove(pd); + + blkdev_put(pd->bdev, FMODE_READ | FMODE_NDELAY); + + remove_proc_entry(pd->name, pkt_proc); + pkt_dbg(1, pd, "writer unmapped\n"); + + del_gendisk(pd->disk); + put_disk(pd->disk); + + mempool_exit(&pd->rb_pool); + kfree(pd); + + /* This is safe: open() is still holding a reference. */ + module_put(THIS_MODULE); + +out: + mutex_unlock(&ctl_mutex); + return ret; +} + +static void pkt_get_status(struct pkt_ctrl_command *ctrl_cmd) +{ + struct pktcdvd_device *pd; + + mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); + + pd = pkt_find_dev_from_minor(ctrl_cmd->dev_index); + if (pd) { + ctrl_cmd->dev = new_encode_dev(pd->bdev->bd_dev); + ctrl_cmd->pkt_dev = new_encode_dev(pd->pkt_dev); + } else { + ctrl_cmd->dev = 0; + ctrl_cmd->pkt_dev = 0; + } + ctrl_cmd->num_devices = MAX_WRITERS; + + mutex_unlock(&ctl_mutex); +} + +static long pkt_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + void __user *argp = (void __user *)arg; + struct pkt_ctrl_command ctrl_cmd; + int ret = 0; + dev_t pkt_dev = 0; + + if (cmd != PACKET_CTRL_CMD) + return -ENOTTY; + + if (copy_from_user(&ctrl_cmd, argp, sizeof(struct pkt_ctrl_command))) + return -EFAULT; + + switch (ctrl_cmd.command) { + case PKT_CTRL_CMD_SETUP: + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + ret = pkt_setup_dev(new_decode_dev(ctrl_cmd.dev), &pkt_dev); + ctrl_cmd.pkt_dev = new_encode_dev(pkt_dev); + break; + case PKT_CTRL_CMD_TEARDOWN: + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + ret = pkt_remove_dev(new_decode_dev(ctrl_cmd.pkt_dev)); + break; + case PKT_CTRL_CMD_STATUS: + pkt_get_status(&ctrl_cmd); + break; + default: + return -ENOTTY; + } + + if (copy_to_user(argp, &ctrl_cmd, sizeof(struct pkt_ctrl_command))) + return -EFAULT; + return ret; +} + +#ifdef CONFIG_COMPAT +static long pkt_ctl_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + return pkt_ctl_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); +} +#endif + +static const struct file_operations pkt_ctl_fops = { + .open = nonseekable_open, + .unlocked_ioctl = pkt_ctl_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = pkt_ctl_compat_ioctl, +#endif + .owner = THIS_MODULE, + .llseek = no_llseek, +}; + +static struct miscdevice pkt_misc = { + .minor = MISC_DYNAMIC_MINOR, + .name = DRIVER_NAME, + .nodename = "pktcdvd/control", + .fops = &pkt_ctl_fops +}; + +static int __init pkt_init(void) +{ + int ret; + + mutex_init(&ctl_mutex); + + ret = mempool_init_kmalloc_pool(&psd_pool, PSD_POOL_SIZE, + sizeof(struct packet_stacked_data)); + if (ret) + return ret; + ret = bioset_init(&pkt_bio_set, BIO_POOL_SIZE, 0, 0); + if (ret) { + mempool_exit(&psd_pool); + return ret; + } + + ret = register_blkdev(pktdev_major, DRIVER_NAME); + if (ret < 0) { + pr_err("unable to register block device\n"); + goto out2; + } + if (!pktdev_major) + pktdev_major = ret; + + ret = pkt_sysfs_init(); + if (ret) + goto out; + + pkt_debugfs_init(); + + ret = misc_register(&pkt_misc); + if (ret) { + pr_err("unable to register misc device\n"); + goto out_misc; + } + + pkt_proc = proc_mkdir("driver/"DRIVER_NAME, NULL); + + return 0; + +out_misc: + pkt_debugfs_cleanup(); + pkt_sysfs_cleanup(); +out: + unregister_blkdev(pktdev_major, DRIVER_NAME); +out2: + mempool_exit(&psd_pool); + bioset_exit(&pkt_bio_set); + return ret; +} + +static void __exit pkt_exit(void) +{ + remove_proc_entry("driver/"DRIVER_NAME, NULL); + misc_deregister(&pkt_misc); + + pkt_debugfs_cleanup(); + pkt_sysfs_cleanup(); + + unregister_blkdev(pktdev_major, DRIVER_NAME); + mempool_exit(&psd_pool); + bioset_exit(&pkt_bio_set); +} + +MODULE_DESCRIPTION("Packet writing layer for CD/DVD drives"); +MODULE_AUTHOR("Jens Axboe <axboe@suse.de>"); +MODULE_LICENSE("GPL"); + +module_init(pkt_init); +module_exit(pkt_exit); diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c index c76e0148eada..574e470b220b 100644 --- a/drivers/block/ps3vram.c +++ b/drivers/block/ps3vram.c @@ -587,6 +587,8 @@ static void ps3vram_submit_bio(struct bio *bio) dev_dbg(&dev->core, "%s\n", __func__); bio = bio_split_to_limits(bio); + if (!bio) + return; spin_lock_irq(&priv->lock); busy = !bio_list_empty(&priv->list); diff --git a/drivers/block/rnbd/rnbd-clt.c b/drivers/block/rnbd/rnbd-clt.c index 78334da74d8b..5eb8c7855970 100644 --- a/drivers/block/rnbd/rnbd-clt.c +++ b/drivers/block/rnbd/rnbd-clt.c @@ -1440,7 +1440,7 @@ static struct rnbd_clt_dev *init_dev(struct rnbd_clt_session *sess, goto out_alloc; } - ret = ida_alloc_max(&index_ida, 1 << (MINORBITS - RNBD_PART_BITS), + ret = ida_alloc_max(&index_ida, (1 << (MINORBITS - RNBD_PART_BITS)) - 1, GFP_KERNEL); if (ret < 0) { pr_err("Failed to initialize device '%s' from session %s, allocating idr failed, err: %d\n", diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index e9de9d846b73..e54693204630 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c @@ -1992,6 +1992,9 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd, struct ublksrv_ctrl_cmd *header = (struct ublksrv_ctrl_cmd *)cmd->cmd; int ret = -EINVAL; + if (issue_flags & IO_URING_F_NONBLOCK) + return -EAGAIN; + ublk_ctrl_cmd_dump(cmd); if (!(issue_flags & IO_URING_F_SQE128)) @@ -2089,13 +2092,12 @@ static void __exit ublk_exit(void) struct ublk_device *ub; int id; - class_destroy(ublk_chr_class); - - misc_deregister(&ublk_misc); - idr_for_each_entry(&ublk_index_idr, ub, id) ublk_remove(ub); + class_destroy(ublk_chr_class); + misc_deregister(&ublk_misc); + idr_destroy(&ublk_index_idr); unregister_chrdev_region(ublk_chr_devt, UBLK_MINORS); } diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 68bd2f7961b3..6a77fa917428 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -315,22 +315,35 @@ static void virtio_commit_rqs(struct blk_mq_hw_ctx *hctx) virtqueue_notify(vq->vq); } +static blk_status_t virtblk_fail_to_queue(struct request *req, int rc) +{ + virtblk_cleanup_cmd(req); + switch (rc) { + case -ENOSPC: + return BLK_STS_DEV_RESOURCE; + case -ENOMEM: + return BLK_STS_RESOURCE; + default: + return BLK_STS_IOERR; + } +} + static blk_status_t virtblk_prep_rq(struct blk_mq_hw_ctx *hctx, struct virtio_blk *vblk, struct request *req, struct virtblk_req *vbr) { blk_status_t status; + int num; status = virtblk_setup_cmd(vblk->vdev, req, vbr); if (unlikely(status)) return status; - vbr->sg_table.nents = virtblk_map_data(hctx, req, vbr); - if (unlikely(vbr->sg_table.nents < 0)) { - virtblk_cleanup_cmd(req); - return BLK_STS_RESOURCE; - } + num = virtblk_map_data(hctx, req, vbr); + if (unlikely(num < 0)) + return virtblk_fail_to_queue(req, -ENOMEM); + vbr->sg_table.nents = num; blk_mq_start_request(req); @@ -364,15 +377,7 @@ static blk_status_t virtio_queue_rq(struct blk_mq_hw_ctx *hctx, blk_mq_stop_hw_queue(hctx); spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags); virtblk_unmap_data(req, vbr); - virtblk_cleanup_cmd(req); - switch (err) { - case -ENOSPC: - return BLK_STS_DEV_RESOURCE; - case -ENOMEM: - return BLK_STS_RESOURCE; - default: - return BLK_STS_IOERR; - } + return virtblk_fail_to_queue(req, err); } if (bd->last && virtqueue_kick_prepare(vblk->vqs[qid].vq)) @@ -991,7 +996,7 @@ static int virtblk_probe(struct virtio_device *vdev) blk_queue_max_segments(q, sg_elems); /* No real sector limit. */ - blk_queue_max_hw_sectors(q, -1U); + blk_queue_max_hw_sectors(q, UINT_MAX); max_size = virtio_max_dma_size(vdev); diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index c0227dfa4688..4807af1d5805 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -524,7 +524,7 @@ static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle, return 0; } -static int xen_blkbk_remove(struct xenbus_device *dev) +static void xen_blkbk_remove(struct xenbus_device *dev) { struct backend_info *be = dev_get_drvdata(&dev->dev); @@ -547,8 +547,6 @@ static int xen_blkbk_remove(struct xenbus_device *dev) /* Put the reference we set in xen_blkif_alloc(). */ xen_blkif_put(be->blkif); } - - return 0; } int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt, diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index b28489290323..23ed258b57f0 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -2467,7 +2467,7 @@ static void blkback_changed(struct xenbus_device *dev, } } -static int blkfront_remove(struct xenbus_device *xbdev) +static void blkfront_remove(struct xenbus_device *xbdev) { struct blkfront_info *info = dev_get_drvdata(&xbdev->dev); @@ -2488,7 +2488,6 @@ static int blkfront_remove(struct xenbus_device *xbdev) } kfree(info); - return 0; } static int blkfront_is_ready(struct xenbus_device *dev) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 6eddc23e49d9..bbe9cf1cae27 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -2164,10 +2164,17 @@ static void qca_serdev_shutdown(struct device *dev) int timeout = msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS); struct serdev_device *serdev = to_serdev_device(dev); struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev); + struct hci_uart *hu = &qcadev->serdev_hu; + struct hci_dev *hdev = hu->hdev; + struct qca_data *qca = hu->priv; const u8 ibs_wake_cmd[] = { 0xFD }; const u8 edl_reset_soc_cmd[] = { 0x01, 0x00, 0xFC, 0x01, 0x05 }; if (qcadev->btsoc_type == QCA_QCA6390) { + if (test_bit(QCA_BT_OFF, &qca->flags) || + !test_bit(HCI_RUNNING, &hdev->flags)) + return; + serdev_device_write_flush(serdev); ret = serdev_device_write_buf(serdev, ibs_wake_cmd, sizeof(ibs_wake_cmd)); diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index d69905233aff..7e513b771832 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -412,7 +412,9 @@ int tpm_pm_suspend(struct device *dev) } suspended: - return rc; + if (rc) + dev_err(dev, "Ignoring error %d while suspending\n", rc); + return 0; } EXPORT_SYMBOL_GPL(tpm_pm_suspend); diff --git a/drivers/char/tpm/xen-tpmfront.c b/drivers/char/tpm/xen-tpmfront.c index 379291826261..80cca3b83b22 100644 --- a/drivers/char/tpm/xen-tpmfront.c +++ b/drivers/char/tpm/xen-tpmfront.c @@ -360,14 +360,13 @@ static int tpmfront_probe(struct xenbus_device *dev, return tpm_chip_register(priv->chip); } -static int tpmfront_remove(struct xenbus_device *dev) +static void tpmfront_remove(struct xenbus_device *dev) { struct tpm_chip *chip = dev_get_drvdata(&dev->dev); struct tpm_private *priv = dev_get_drvdata(&chip->dev); tpm_chip_unregister(chip); ring_free(priv); dev_set_drvdata(&chip->dev, NULL); - return 0; } static int tpmfront_resume(struct xenbus_device *dev) diff --git a/drivers/comedi/drivers/adv_pci1760.c b/drivers/comedi/drivers/adv_pci1760.c index fcfc2e299110..27f3890f471d 100644 --- a/drivers/comedi/drivers/adv_pci1760.c +++ b/drivers/comedi/drivers/adv_pci1760.c @@ -58,7 +58,7 @@ #define PCI1760_CMD_CLR_IMB2 0x00 /* Clears IMB2 */ #define PCI1760_CMD_SET_DO 0x01 /* Set output state */ #define PCI1760_CMD_GET_DO 0x02 /* Read output status */ -#define PCI1760_CMD_GET_STATUS 0x03 /* Read current status */ +#define PCI1760_CMD_GET_STATUS 0x07 /* Read current status */ #define PCI1760_CMD_GET_FW_VER 0x0e /* Read firmware version */ #define PCI1760_CMD_GET_HW_VER 0x0f /* Read hardware version */ #define PCI1760_CMD_SET_PWM_HI(x) (0x10 + (x) * 2) /* Set "hi" period */ diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c index 204e39006dda..c17bd845f5fc 100644 --- a/drivers/cpufreq/amd-pstate.c +++ b/drivers/cpufreq/amd-pstate.c @@ -307,6 +307,7 @@ static void amd_pstate_adjust_perf(unsigned int cpu, max_perf = min_perf; amd_pstate_update(cpudata, min_perf, des_perf, max_perf, true); + cpufreq_cpu_put(policy); } static int amd_get_min_freq(struct amd_cpudata *cpudata) diff --git a/drivers/cpufreq/apple-soc-cpufreq.c b/drivers/cpufreq/apple-soc-cpufreq.c index d1801281cdd9..c11d22fd84c3 100644 --- a/drivers/cpufreq/apple-soc-cpufreq.c +++ b/drivers/cpufreq/apple-soc-cpufreq.c @@ -280,6 +280,7 @@ static int apple_soc_cpufreq_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = transition_latency; policy->dvfs_possible_from_any_cpu = true; policy->fast_switch_possible = true; + policy->suspend_freq = freq_table[0].frequency; if (policy_has_boost_freq(policy)) { ret = cpufreq_enable_boost_support(); @@ -321,7 +322,6 @@ static struct cpufreq_driver apple_soc_cpufreq_driver = { .flags = CPUFREQ_HAVE_GOVERNOR_PER_POLICY | CPUFREQ_NEED_INITIAL_FREQ_CHECK | CPUFREQ_IS_COOLING_DEV, .verify = cpufreq_generic_frequency_table_verify, - .attr = cpufreq_generic_attr, .get = apple_soc_cpufreq_get_rate, .init = apple_soc_cpufreq_init, .exit = apple_soc_cpufreq_exit, @@ -329,6 +329,7 @@ static struct cpufreq_driver apple_soc_cpufreq_driver = { .fast_switch = apple_soc_cpufreq_fast_switch, .register_em = cpufreq_register_em_with_opp, .attr = apple_soc_cpufreq_hw_attr, + .suspend = cpufreq_generic_suspend, }; static int __init apple_soc_cpufreq_module_init(void) diff --git a/drivers/cpufreq/armada-37xx-cpufreq.c b/drivers/cpufreq/armada-37xx-cpufreq.c index c10fc33b29b1..b74289a95a17 100644 --- a/drivers/cpufreq/armada-37xx-cpufreq.c +++ b/drivers/cpufreq/armada-37xx-cpufreq.c @@ -445,7 +445,7 @@ static int __init armada37xx_cpufreq_driver_init(void) return -ENODEV; } - clk = clk_get(cpu_dev, 0); + clk = clk_get(cpu_dev, NULL); if (IS_ERR(clk)) { dev_err(cpu_dev, "Cannot get clock for CPU0\n"); return PTR_ERR(clk); diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c index 432dfb4e8027..022e3555407c 100644 --- a/drivers/cpufreq/cppc_cpufreq.c +++ b/drivers/cpufreq/cppc_cpufreq.c @@ -487,7 +487,8 @@ static unsigned int get_perf_level_count(struct cpufreq_policy *policy) cpu_data = policy->driver_data; perf_caps = &cpu_data->perf_caps; max_cap = arch_scale_cpu_capacity(cpu); - min_cap = div_u64(max_cap * perf_caps->lowest_perf, perf_caps->highest_perf); + min_cap = div_u64((u64)max_cap * perf_caps->lowest_perf, + perf_caps->highest_perf); if ((min_cap == 0) || (max_cap < min_cap)) return 0; return 1 + max_cap / CPPC_EM_CAP_STEP - min_cap / CPPC_EM_CAP_STEP; @@ -519,10 +520,10 @@ static int cppc_get_cpu_power(struct device *cpu_dev, cpu_data = policy->driver_data; perf_caps = &cpu_data->perf_caps; max_cap = arch_scale_cpu_capacity(cpu_dev->id); - min_cap = div_u64(max_cap * perf_caps->lowest_perf, - perf_caps->highest_perf); - - perf_step = CPPC_EM_CAP_STEP * perf_caps->highest_perf / max_cap; + min_cap = div_u64((u64)max_cap * perf_caps->lowest_perf, + perf_caps->highest_perf); + perf_step = div_u64((u64)CPPC_EM_CAP_STEP * perf_caps->highest_perf, + max_cap); min_step = min_cap / CPPC_EM_CAP_STEP; max_step = max_cap / CPPC_EM_CAP_STEP; diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 8ab672883043..e85703651098 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -137,6 +137,7 @@ static const struct of_device_id blocklist[] __initconst = { { .compatible = "nvidia,tegra30", }, { .compatible = "nvidia,tegra124", }, { .compatible = "nvidia,tegra210", }, + { .compatible = "nvidia,tegra234", }, { .compatible = "qcom,apq8096", }, { .compatible = "qcom,msm8996", }, @@ -150,6 +151,7 @@ static const struct of_device_id blocklist[] __initconst = { { .compatible = "qcom,sdm845", }, { .compatible = "qcom,sm6115", }, { .compatible = "qcom,sm6350", }, + { .compatible = "qcom,sm6375", }, { .compatible = "qcom,sm8150", }, { .compatible = "qcom,sm8250", }, { .compatible = "qcom,sm8350", }, diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c index 340fed35e45d..9505a812d6a1 100644 --- a/drivers/cpufreq/qcom-cpufreq-hw.c +++ b/drivers/cpufreq/qcom-cpufreq-hw.c @@ -649,9 +649,10 @@ static int qcom_cpufreq_hw_driver_probe(struct platform_device *pdev) { struct clk_hw_onecell_data *clk_data; struct device *dev = &pdev->dev; + struct device_node *soc_node; struct device *cpu_dev; struct clk *clk; - int ret, i, num_domains; + int ret, i, num_domains, reg_sz; clk = clk_get(dev, "xo"); if (IS_ERR(clk)) @@ -679,7 +680,21 @@ static int qcom_cpufreq_hw_driver_probe(struct platform_device *pdev) return ret; /* Allocate qcom_cpufreq_data based on the available frequency domains in DT */ - num_domains = of_property_count_elems_of_size(dev->of_node, "reg", sizeof(u32) * 4); + soc_node = of_get_parent(dev->of_node); + if (!soc_node) + return -EINVAL; + + ret = of_property_read_u32(soc_node, "#address-cells", ®_sz); + if (ret) + goto of_exit; + + ret = of_property_read_u32(soc_node, "#size-cells", &i); + if (ret) + goto of_exit; + + reg_sz += i; + + num_domains = of_property_count_elems_of_size(dev->of_node, "reg", sizeof(u32) * reg_sz); if (num_domains <= 0) return num_domains; @@ -743,6 +758,9 @@ static int qcom_cpufreq_hw_driver_probe(struct platform_device *pdev) else dev_dbg(dev, "QCOM CPUFreq HW driver initialized\n"); +of_exit: + of_node_put(soc_node); + return ret; } diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index 53100fb9b07b..12205e2b53b4 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -3,7 +3,7 @@ * Microchip / Atmel ECC (I2C) driver. * * Copyright (c) 2017, Microchip Technology Inc. - * Author: Tudor Ambarus <tudor.ambarus@microchip.com> + * Author: Tudor Ambarus */ #include <linux/delay.h> @@ -411,6 +411,6 @@ static void __exit atmel_ecc_exit(void) module_init(atmel_ecc_init); module_exit(atmel_ecc_exit); -MODULE_AUTHOR("Tudor Ambarus <tudor.ambarus@microchip.com>"); +MODULE_AUTHOR("Tudor Ambarus"); MODULE_DESCRIPTION("Microchip / Atmel ECC (I2C) driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/crypto/atmel-i2c.c b/drivers/crypto/atmel-i2c.c index 81ce09bedda8..55bff1e13142 100644 --- a/drivers/crypto/atmel-i2c.c +++ b/drivers/crypto/atmel-i2c.c @@ -3,7 +3,7 @@ * Microchip / Atmel ECC (I2C) driver. * * Copyright (c) 2017, Microchip Technology Inc. - * Author: Tudor Ambarus <tudor.ambarus@microchip.com> + * Author: Tudor Ambarus */ #include <linux/bitrev.h> @@ -390,6 +390,6 @@ static void __exit atmel_i2c_exit(void) module_init(atmel_i2c_init); module_exit(atmel_i2c_exit); -MODULE_AUTHOR("Tudor Ambarus <tudor.ambarus@microchip.com>"); +MODULE_AUTHOR("Tudor Ambarus"); MODULE_DESCRIPTION("Microchip / Atmel ECC (I2C) driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/crypto/atmel-i2c.h b/drivers/crypto/atmel-i2c.h index 48929efe2a5b..35f7857a7f7c 100644 --- a/drivers/crypto/atmel-i2c.h +++ b/drivers/crypto/atmel-i2c.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2017, Microchip Technology Inc. - * Author: Tudor Ambarus <tudor.ambarus@microchip.com> + * Author: Tudor Ambarus */ #ifndef __ATMEL_I2C_H__ diff --git a/drivers/crypto/caam/blob_gen.c b/drivers/crypto/caam/blob_gen.c index 1f65df489847..f46b161d2cda 100644 --- a/drivers/crypto/caam/blob_gen.c +++ b/drivers/crypto/caam/blob_gen.c @@ -104,7 +104,7 @@ int caam_process_blob(struct caam_blob_priv *priv, } ctrlpriv = dev_get_drvdata(jrdev->parent); - moo = FIELD_GET(CSTA_MOO, ioread32(&ctrlpriv->ctrl->perfmon.status)); + moo = FIELD_GET(CSTA_MOO, rd_reg32(&ctrlpriv->ctrl->perfmon.status)); if (moo != CSTA_MOO_SECURE && moo != CSTA_MOO_TRUSTED) dev_warn(jrdev, "using insecure test key, enable HAB to use unique device key!\n"); diff --git a/drivers/crypto/virtio/virtio_crypto_skcipher_algs.c b/drivers/crypto/virtio/virtio_crypto_skcipher_algs.c index e553ccadbcbc..e5876286828b 100644 --- a/drivers/crypto/virtio/virtio_crypto_skcipher_algs.c +++ b/drivers/crypto/virtio/virtio_crypto_skcipher_algs.c @@ -239,7 +239,8 @@ static int virtio_crypto_alg_skcipher_close_session( pr_err("virtio_crypto: Close session failed status: %u, session_id: 0x%llx\n", ctrl_status->status, destroy_session->session_id); - return -EINVAL; + err = -EINVAL; + goto out; } err = 0; diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c index ad0849af42d7..13cde44c6086 100644 --- a/drivers/cxl/acpi.c +++ b/drivers/cxl/acpi.c @@ -736,4 +736,3 @@ module_exit(cxl_acpi_exit); MODULE_LICENSE("GPL v2"); MODULE_IMPORT_NS(CXL); MODULE_IMPORT_NS(ACPI); -MODULE_SOFTDEP("pre: cxl_pmem"); diff --git a/drivers/cxl/core/pmem.c b/drivers/cxl/core/pmem.c index f3d2169b6731..c2e4b1093788 100644 --- a/drivers/cxl/core/pmem.c +++ b/drivers/cxl/core/pmem.c @@ -227,34 +227,16 @@ static struct cxl_nvdimm *cxl_nvdimm_alloc(struct cxl_nvdimm_bridge *cxl_nvb, return cxl_nvd; } -static void cxl_nvd_unregister(void *_cxl_nvd) +static void cxlmd_release_nvdimm(void *_cxlmd) { - struct cxl_nvdimm *cxl_nvd = _cxl_nvd; - struct cxl_memdev *cxlmd = cxl_nvd->cxlmd; + struct cxl_memdev *cxlmd = _cxlmd; + struct cxl_nvdimm *cxl_nvd = cxlmd->cxl_nvd; struct cxl_nvdimm_bridge *cxl_nvb = cxlmd->cxl_nvb; - /* - * Either the bridge is in ->remove() context under the device_lock(), - * or cxlmd_release_nvdimm() is cancelling the bridge's release action - * for @cxl_nvd and doing it itself (while manually holding the bridge - * lock). - */ - device_lock_assert(&cxl_nvb->dev); cxl_nvd->cxlmd = NULL; cxlmd->cxl_nvd = NULL; + cxlmd->cxl_nvb = NULL; device_unregister(&cxl_nvd->dev); -} - -static void cxlmd_release_nvdimm(void *_cxlmd) -{ - struct cxl_memdev *cxlmd = _cxlmd; - struct cxl_nvdimm_bridge *cxl_nvb = cxlmd->cxl_nvb; - - device_lock(&cxl_nvb->dev); - if (cxlmd->cxl_nvd) - devm_release_action(&cxl_nvb->dev, cxl_nvd_unregister, - cxlmd->cxl_nvd); - device_unlock(&cxl_nvb->dev); put_device(&cxl_nvb->dev); } @@ -293,22 +275,6 @@ int devm_cxl_add_nvdimm(struct cxl_memdev *cxlmd) dev_dbg(&cxlmd->dev, "register %s\n", dev_name(dev)); - /* - * The two actions below arrange for @cxl_nvd to be deleted when either - * the top-level PMEM bridge goes down, or the endpoint device goes - * through ->remove(). - */ - device_lock(&cxl_nvb->dev); - if (cxl_nvb->dev.driver) - rc = devm_add_action_or_reset(&cxl_nvb->dev, cxl_nvd_unregister, - cxl_nvd); - else - rc = -ENXIO; - device_unlock(&cxl_nvb->dev); - - if (rc) - goto err_alloc; - /* @cxlmd carries a reference on @cxl_nvb until cxlmd_release_nvdimm */ return devm_add_action_or_reset(&cxlmd->dev, cxlmd_release_nvdimm, cxlmd); diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c index 33083a522fd1..258004f34281 100644 --- a/drivers/cxl/pci.c +++ b/drivers/cxl/pci.c @@ -554,8 +554,11 @@ static bool cxl_report_and_clear(struct cxl_dev_state *cxlds) /* If multiple errors, log header points to first error from ctrl reg */ if (hweight32(status) > 1) { - addr = cxlds->regs.ras + CXL_RAS_CAP_CONTROL_OFFSET; - fe = BIT(FIELD_GET(CXL_RAS_CAP_CONTROL_FE_MASK, readl(addr))); + void __iomem *rcc_addr = + cxlds->regs.ras + CXL_RAS_CAP_CONTROL_OFFSET; + + fe = BIT(FIELD_GET(CXL_RAS_CAP_CONTROL_FE_MASK, + readl(rcc_addr))); } else { fe = status; } diff --git a/drivers/cxl/pmem.c b/drivers/cxl/pmem.c index eedefebc4283..08bbbac9a6d0 100644 --- a/drivers/cxl/pmem.c +++ b/drivers/cxl/pmem.c @@ -225,11 +225,35 @@ static int cxl_pmem_ctl(struct nvdimm_bus_descriptor *nd_desc, return cxl_pmem_nvdimm_ctl(nvdimm, cmd, buf, buf_len); } +static int detach_nvdimm(struct device *dev, void *data) +{ + struct cxl_nvdimm *cxl_nvd; + bool release = false; + + if (!is_cxl_nvdimm(dev)) + return 0; + + device_lock(dev); + if (!dev->driver) + goto out; + + cxl_nvd = to_cxl_nvdimm(dev); + if (cxl_nvd->cxlmd && cxl_nvd->cxlmd->cxl_nvb == data) + release = true; +out: + device_unlock(dev); + if (release) + device_release_driver(dev); + return 0; +} + static void unregister_nvdimm_bus(void *_cxl_nvb) { struct cxl_nvdimm_bridge *cxl_nvb = _cxl_nvb; struct nvdimm_bus *nvdimm_bus = cxl_nvb->nvdimm_bus; + bus_for_each_dev(&cxl_bus_type, NULL, cxl_nvb, detach_nvdimm); + cxl_nvb->nvdimm_bus = NULL; nvdimm_bus_unregister(nvdimm_bus); } diff --git a/drivers/dma-buf/dma-buf-sysfs-stats.c b/drivers/dma-buf/dma-buf-sysfs-stats.c index f69d68122b9b..fbf725fae7c1 100644 --- a/drivers/dma-buf/dma-buf-sysfs-stats.c +++ b/drivers/dma-buf/dma-buf-sysfs-stats.c @@ -168,14 +168,11 @@ void dma_buf_uninit_sysfs_statistics(void) kset_unregister(dma_buf_stats_kset); } -int dma_buf_stats_setup(struct dma_buf *dmabuf) +int dma_buf_stats_setup(struct dma_buf *dmabuf, struct file *file) { struct dma_buf_sysfs_entry *sysfs_entry; int ret; - if (!dmabuf || !dmabuf->file) - return -EINVAL; - if (!dmabuf->exp_name) { pr_err("exporter name must not be empty if stats needed\n"); return -EINVAL; @@ -192,7 +189,7 @@ int dma_buf_stats_setup(struct dma_buf *dmabuf) /* create the directory for buffer stats */ ret = kobject_init_and_add(&sysfs_entry->kobj, &dma_buf_ktype, NULL, - "%lu", file_inode(dmabuf->file)->i_ino); + "%lu", file_inode(file)->i_ino); if (ret) goto err_sysfs_dmabuf; diff --git a/drivers/dma-buf/dma-buf-sysfs-stats.h b/drivers/dma-buf/dma-buf-sysfs-stats.h index a49c6e2650cc..7a8a995b75ba 100644 --- a/drivers/dma-buf/dma-buf-sysfs-stats.h +++ b/drivers/dma-buf/dma-buf-sysfs-stats.h @@ -13,7 +13,7 @@ int dma_buf_init_sysfs_statistics(void); void dma_buf_uninit_sysfs_statistics(void); -int dma_buf_stats_setup(struct dma_buf *dmabuf); +int dma_buf_stats_setup(struct dma_buf *dmabuf, struct file *file); void dma_buf_stats_teardown(struct dma_buf *dmabuf); #else @@ -25,7 +25,7 @@ static inline int dma_buf_init_sysfs_statistics(void) static inline void dma_buf_uninit_sysfs_statistics(void) {} -static inline int dma_buf_stats_setup(struct dma_buf *dmabuf) +static inline int dma_buf_stats_setup(struct dma_buf *dmabuf, struct file *file) { return 0; } diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index 24e656a3ee74..757c0fb77a6c 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -95,10 +95,11 @@ static int dma_buf_file_release(struct inode *inode, struct file *file) return -EINVAL; dmabuf = file->private_data; - - mutex_lock(&db_list.lock); - list_del(&dmabuf->list_node); - mutex_unlock(&db_list.lock); + if (dmabuf) { + mutex_lock(&db_list.lock); + list_del(&dmabuf->list_node); + mutex_unlock(&db_list.lock); + } return 0; } @@ -528,17 +529,17 @@ static inline int is_dma_buf_file(struct file *file) return file->f_op == &dma_buf_fops; } -static struct file *dma_buf_getfile(struct dma_buf *dmabuf, int flags) +static struct file *dma_buf_getfile(size_t size, int flags) { static atomic64_t dmabuf_inode = ATOMIC64_INIT(0); - struct file *file; struct inode *inode = alloc_anon_inode(dma_buf_mnt->mnt_sb); + struct file *file; if (IS_ERR(inode)) return ERR_CAST(inode); - inode->i_size = dmabuf->size; - inode_set_bytes(inode, dmabuf->size); + inode->i_size = size; + inode_set_bytes(inode, size); /* * The ->i_ino acquired from get_next_ino() is not unique thus @@ -552,8 +553,6 @@ static struct file *dma_buf_getfile(struct dma_buf *dmabuf, int flags) flags, &dma_buf_fops); if (IS_ERR(file)) goto err_alloc_file; - file->private_data = dmabuf; - file->f_path.dentry->d_fsdata = dmabuf; return file; @@ -619,19 +618,11 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info) size_t alloc_size = sizeof(struct dma_buf); int ret; - if (!exp_info->resv) - alloc_size += sizeof(struct dma_resv); - else - /* prevent &dma_buf[1] == dma_buf->resv */ - alloc_size += 1; - - if (WARN_ON(!exp_info->priv - || !exp_info->ops - || !exp_info->ops->map_dma_buf - || !exp_info->ops->unmap_dma_buf - || !exp_info->ops->release)) { + if (WARN_ON(!exp_info->priv || !exp_info->ops + || !exp_info->ops->map_dma_buf + || !exp_info->ops->unmap_dma_buf + || !exp_info->ops->release)) return ERR_PTR(-EINVAL); - } if (WARN_ON(exp_info->ops->cache_sgt_mapping && (exp_info->ops->pin || exp_info->ops->unpin))) @@ -643,10 +634,21 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info) if (!try_module_get(exp_info->owner)) return ERR_PTR(-ENOENT); + file = dma_buf_getfile(exp_info->size, exp_info->flags); + if (IS_ERR(file)) { + ret = PTR_ERR(file); + goto err_module; + } + + if (!exp_info->resv) + alloc_size += sizeof(struct dma_resv); + else + /* prevent &dma_buf[1] == dma_buf->resv */ + alloc_size += 1; dmabuf = kzalloc(alloc_size, GFP_KERNEL); if (!dmabuf) { ret = -ENOMEM; - goto err_module; + goto err_file; } dmabuf->priv = exp_info->priv; @@ -658,43 +660,35 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info) init_waitqueue_head(&dmabuf->poll); dmabuf->cb_in.poll = dmabuf->cb_out.poll = &dmabuf->poll; dmabuf->cb_in.active = dmabuf->cb_out.active = 0; + INIT_LIST_HEAD(&dmabuf->attachments); if (!resv) { - resv = (struct dma_resv *)&dmabuf[1]; - dma_resv_init(resv); + dmabuf->resv = (struct dma_resv *)&dmabuf[1]; + dma_resv_init(dmabuf->resv); + } else { + dmabuf->resv = resv; } - dmabuf->resv = resv; - file = dma_buf_getfile(dmabuf, exp_info->flags); - if (IS_ERR(file)) { - ret = PTR_ERR(file); + ret = dma_buf_stats_setup(dmabuf, file); + if (ret) goto err_dmabuf; - } + file->private_data = dmabuf; + file->f_path.dentry->d_fsdata = dmabuf; dmabuf->file = file; - INIT_LIST_HEAD(&dmabuf->attachments); - mutex_lock(&db_list.lock); list_add(&dmabuf->list_node, &db_list.head); mutex_unlock(&db_list.lock); - ret = dma_buf_stats_setup(dmabuf); - if (ret) - goto err_sysfs; - return dmabuf; -err_sysfs: - /* - * Set file->f_path.dentry->d_fsdata to NULL so that when - * dma_buf_release() gets invoked by dentry_ops, it exits - * early before calling the release() dma_buf op. - */ - file->f_path.dentry->d_fsdata = NULL; - fput(file); err_dmabuf: + if (!resv) + dma_resv_fini(dmabuf->resv); kfree(dmabuf); +err_file: + fput(file); err_module: module_put(exp_info->owner); return ERR_PTR(ret); diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index c741b6431958..8a6e6b60d66f 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -451,7 +451,8 @@ static int dma_chan_get(struct dma_chan *chan) /* The channel is already in use, update client count */ if (chan->client_count) { __module_get(owner); - goto out; + chan->client_count++; + return 0; } if (!try_module_get(owner)) @@ -470,11 +471,11 @@ static int dma_chan_get(struct dma_chan *chan) goto err_out; } + chan->client_count++; + if (!dma_has_cap(DMA_PRIVATE, chan->device->cap_mask)) balance_ref_count(chan); -out: - chan->client_count++; return 0; err_out: diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c index a183d93bd7e2..bf85aa0979ec 100644 --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c @@ -1018,6 +1018,11 @@ static noinline void axi_chan_handle_err(struct axi_dma_chan *chan, u32 status) /* The bad descriptor currently is in the head of vc list */ vd = vchan_next_desc(&chan->vc); + if (!vd) { + dev_err(chan2dev(chan), "BUG: %s, IRQ with no descriptors\n", + axi_chan_name(chan)); + goto out; + } /* Remove the completed descriptor from issued list */ list_del(&vd->node); @@ -1032,6 +1037,7 @@ static noinline void axi_chan_handle_err(struct axi_dma_chan *chan, u32 status) /* Try to restart the controller */ axi_chan_start_first_queued(chan); +out: spin_unlock_irqrestore(&chan->vc.lock, flags); } diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c index 06f5d3783d77..29dbb0f52e18 100644 --- a/drivers/dma/idxd/device.c +++ b/drivers/dma/idxd/device.c @@ -1172,8 +1172,19 @@ static void idxd_flush_pending_descs(struct idxd_irq_entry *ie) spin_unlock(&ie->list_lock); list_for_each_entry_safe(desc, itr, &flist, list) { + struct dma_async_tx_descriptor *tx; + list_del(&desc->list); ctype = desc->completion->status ? IDXD_COMPLETE_NORMAL : IDXD_COMPLETE_ABORT; + /* + * wq is being disabled. Any remaining descriptors are + * likely to be stuck and can be dropped. callback could + * point to code that is no longer accessible, for example + * if dmatest module has been unloaded. + */ + tx = &desc->txd; + tx->callback = NULL; + tx->callback_result = NULL; idxd_dma_complete_txd(desc, ctype, true); } } @@ -1390,8 +1401,7 @@ err_res_alloc: err_irq: idxd_wq_unmap_portal(wq); err_map_portal: - rc = idxd_wq_disable(wq, false); - if (rc < 0) + if (idxd_wq_disable(wq, false)) dev_dbg(dev, "wq %s disable failed\n", dev_name(wq_confdev(wq))); err: return rc; @@ -1408,11 +1418,11 @@ void drv_disable_wq(struct idxd_wq *wq) dev_warn(dev, "Clients has claim on wq %d: %d\n", wq->id, idxd_wq_refcount(wq)); - idxd_wq_free_resources(wq); idxd_wq_unmap_portal(wq); idxd_wq_drain(wq); idxd_wq_free_irq(wq); idxd_wq_reset(wq); + idxd_wq_free_resources(wq); percpu_ref_exit(&wq->wq_active); wq->type = IDXD_WQT_NONE; wq->client_count = 0; diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index fbea5f62dd98..b926abe4fa43 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -1521,10 +1521,12 @@ static struct sdma_desc *sdma_transfer_init(struct sdma_channel *sdmac, sdma_config_ownership(sdmac, false, true, false); if (sdma_load_context(sdmac)) - goto err_desc_out; + goto err_bd_out; return desc; +err_bd_out: + sdma_free_bd(desc); err_desc_out: kfree(desc); err_out: diff --git a/drivers/dma/lgm/lgm-dma.c b/drivers/dma/lgm/lgm-dma.c index 9b9184f964be..1709d159af7e 100644 --- a/drivers/dma/lgm/lgm-dma.c +++ b/drivers/dma/lgm/lgm-dma.c @@ -914,7 +914,7 @@ static void ldma_dev_init(struct ldma_dev *d) } } -static int ldma_cfg_init(struct ldma_dev *d) +static int ldma_parse_dt(struct ldma_dev *d) { struct fwnode_handle *fwnode = dev_fwnode(d->dev); struct ldma_port *p; @@ -1661,10 +1661,6 @@ static int intel_ldma_probe(struct platform_device *pdev) p->ldev = d; } - ret = ldma_cfg_init(d); - if (ret) - return ret; - dma_dev->dev = &pdev->dev; ch_mask = (unsigned long)d->channels_mask; @@ -1675,6 +1671,10 @@ static int intel_ldma_probe(struct platform_device *pdev) ldma_dma_init_v3X(j, d); } + ret = ldma_parse_dt(d); + if (ret) + return ret; + dma_dev->device_alloc_chan_resources = ldma_alloc_chan_resources; dma_dev->device_free_chan_resources = ldma_free_chan_resources; dma_dev->device_terminate_all = ldma_terminate_all; diff --git a/drivers/dma/ptdma/ptdma-dev.c b/drivers/dma/ptdma/ptdma-dev.c index 377da23012ac..a2bf13ff18b6 100644 --- a/drivers/dma/ptdma/ptdma-dev.c +++ b/drivers/dma/ptdma/ptdma-dev.c @@ -71,12 +71,13 @@ static int pt_core_execute_cmd(struct ptdma_desc *desc, struct pt_cmd_queue *cmd bool soc = FIELD_GET(DWORD0_SOC, desc->dw0); u8 *q_desc = (u8 *)&cmd_q->qbase[cmd_q->qidx]; u32 tail; + unsigned long flags; if (soc) { desc->dw0 |= FIELD_PREP(DWORD0_IOC, desc->dw0); desc->dw0 &= ~DWORD0_SOC; } - mutex_lock(&cmd_q->q_mutex); + spin_lock_irqsave(&cmd_q->q_lock, flags); /* Copy 32-byte command descriptor to hw queue. */ memcpy(q_desc, desc, 32); @@ -91,7 +92,7 @@ static int pt_core_execute_cmd(struct ptdma_desc *desc, struct pt_cmd_queue *cmd /* Turn the queue back on using our cached control register */ pt_start_queue(cmd_q); - mutex_unlock(&cmd_q->q_mutex); + spin_unlock_irqrestore(&cmd_q->q_lock, flags); return 0; } @@ -199,7 +200,7 @@ int pt_core_init(struct pt_device *pt) cmd_q->pt = pt; cmd_q->dma_pool = dma_pool; - mutex_init(&cmd_q->q_mutex); + spin_lock_init(&cmd_q->q_lock); /* Page alignment satisfies our needs for N <= 128 */ cmd_q->qsize = Q_SIZE(Q_DESC_SIZE); diff --git a/drivers/dma/ptdma/ptdma.h b/drivers/dma/ptdma/ptdma.h index d093c43b7d13..21b4bf895200 100644 --- a/drivers/dma/ptdma/ptdma.h +++ b/drivers/dma/ptdma/ptdma.h @@ -196,7 +196,7 @@ struct pt_cmd_queue { struct ptdma_desc *qbase; /* Aligned queue start address (per requirement) */ - struct mutex q_mutex ____cacheline_aligned; + spinlock_t q_lock ____cacheline_aligned; unsigned int qidx; unsigned int qsize; diff --git a/drivers/dma/qcom/gpi.c b/drivers/dma/qcom/gpi.c index 061add832295..59a36cbf9b5f 100644 --- a/drivers/dma/qcom/gpi.c +++ b/drivers/dma/qcom/gpi.c @@ -1756,6 +1756,7 @@ static int gpi_create_spi_tre(struct gchan *chan, struct gpi_desc *desc, tre->dword[3] = u32_encode_bits(TRE_TYPE_GO, TRE_FLAGS_TYPE); if (spi->cmd == SPI_RX) { tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_IEOB); + tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_LINK); } else if (spi->cmd == SPI_TX) { tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_CHAIN); } else { /* SPI_DUPLEX */ diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c index 1d1180db6d4e..8f67f453a492 100644 --- a/drivers/dma/tegra186-gpc-dma.c +++ b/drivers/dma/tegra186-gpc-dma.c @@ -711,6 +711,7 @@ static int tegra_dma_terminate_all(struct dma_chan *dc) return err; } + vchan_terminate_vdesc(&tdc->dma_desc->vd); tegra_dma_disable(tdc); tdc->dma_desc = NULL; } diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c index ae39b52012b2..79da93cc77b6 100644 --- a/drivers/dma/tegra210-adma.c +++ b/drivers/dma/tegra210-adma.c @@ -221,7 +221,7 @@ static int tegra_adma_init(struct tegra_adma *tdma) int ret; /* Clear any interrupts */ - tdma_write(tdma, tdma->cdata->global_int_clear, 0x1); + tdma_write(tdma, tdma->cdata->ch_base_offset + tdma->cdata->global_int_clear, 0x1); /* Assert soft reset */ tdma_write(tdma, ADMA_GLOBAL_SOFT_RESET, 0x1); diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c index ce8b80bb34d7..4c62274e0b33 100644 --- a/drivers/dma/ti/k3-udma.c +++ b/drivers/dma/ti/k3-udma.c @@ -762,11 +762,12 @@ static void udma_decrement_byte_counters(struct udma_chan *uc, u32 val) if (uc->desc->dir == DMA_DEV_TO_MEM) { udma_rchanrt_write(uc, UDMA_CHAN_RT_BCNT_REG, val); udma_rchanrt_write(uc, UDMA_CHAN_RT_SBCNT_REG, val); - udma_rchanrt_write(uc, UDMA_CHAN_RT_PEER_BCNT_REG, val); + if (uc->config.ep_type != PSIL_EP_NATIVE) + udma_rchanrt_write(uc, UDMA_CHAN_RT_PEER_BCNT_REG, val); } else { udma_tchanrt_write(uc, UDMA_CHAN_RT_BCNT_REG, val); udma_tchanrt_write(uc, UDMA_CHAN_RT_SBCNT_REG, val); - if (!uc->bchan) + if (!uc->bchan && uc->config.ep_type != PSIL_EP_NATIVE) udma_tchanrt_write(uc, UDMA_CHAN_RT_PEER_BCNT_REG, val); } } diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c index a8d23cdf883e..ac09f0e5f58d 100644 --- a/drivers/dma/xilinx/xilinx_dma.c +++ b/drivers/dma/xilinx/xilinx_dma.c @@ -3143,8 +3143,10 @@ static int xilinx_dma_probe(struct platform_device *pdev) /* Initialize the channels */ for_each_child_of_node(node, child) { err = xilinx_dma_child_probe(xdev, child); - if (err < 0) + if (err < 0) { + of_node_put(child); goto error; + } } if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) { diff --git a/drivers/edac/edac_device.c b/drivers/edac/edac_device.c index 19522c568aa5..0689e1510721 100644 --- a/drivers/edac/edac_device.c +++ b/drivers/edac/edac_device.c @@ -34,6 +34,9 @@ static DEFINE_MUTEX(device_ctls_mutex); static LIST_HEAD(edac_device_list); +/* Default workqueue processing interval on this instance, in msecs */ +#define DEFAULT_POLL_INTERVAL 1000 + #ifdef CONFIG_EDAC_DEBUG static void edac_device_dump_device(struct edac_device_ctl_info *edac_dev) { @@ -336,7 +339,7 @@ static void edac_device_workq_function(struct work_struct *work_req) * whole one second to save timers firing all over the period * between integral seconds */ - if (edac_dev->poll_msec == 1000) + if (edac_dev->poll_msec == DEFAULT_POLL_INTERVAL) edac_queue_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay)); else edac_queue_work(&edac_dev->work, edac_dev->delay); @@ -366,7 +369,7 @@ static void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev, * timers firing on sub-second basis, while they are happy * to fire together on the 1 second exactly */ - if (edac_dev->poll_msec == 1000) + if (edac_dev->poll_msec == DEFAULT_POLL_INTERVAL) edac_queue_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay)); else edac_queue_work(&edac_dev->work, edac_dev->delay); @@ -394,17 +397,16 @@ static void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev) * Then restart the workq on the new delay */ void edac_device_reset_delay_period(struct edac_device_ctl_info *edac_dev, - unsigned long value) + unsigned long msec) { - unsigned long jiffs = msecs_to_jiffies(value); - - if (value == 1000) - jiffs = round_jiffies_relative(value); - - edac_dev->poll_msec = value; - edac_dev->delay = jiffs; + edac_dev->poll_msec = msec; + edac_dev->delay = msecs_to_jiffies(msec); - edac_mod_work(&edac_dev->work, jiffs); + /* See comment in edac_device_workq_setup() above */ + if (edac_dev->poll_msec == DEFAULT_POLL_INTERVAL) + edac_mod_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay)); + else + edac_mod_work(&edac_dev->work, edac_dev->delay); } int edac_device_alloc_index(void) @@ -443,11 +445,7 @@ int edac_device_add_device(struct edac_device_ctl_info *edac_dev) /* This instance is NOW RUNNING */ edac_dev->op_state = OP_RUNNING_POLL; - /* - * enable workq processing on this instance, - * default = 1000 msec - */ - edac_device_workq_setup(edac_dev, 1000); + edac_device_workq_setup(edac_dev, edac_dev->poll_msec ?: DEFAULT_POLL_INTERVAL); } else { edac_dev->op_state = OP_RUNNING_INTERRUPT; } diff --git a/drivers/edac/edac_module.h b/drivers/edac/edac_module.h index 763c076d96f2..47593afdc234 100644 --- a/drivers/edac/edac_module.h +++ b/drivers/edac/edac_module.h @@ -53,7 +53,7 @@ bool edac_stop_work(struct delayed_work *work); bool edac_mod_work(struct delayed_work *work, unsigned long delay); extern void edac_device_reset_delay_period(struct edac_device_ctl_info - *edac_dev, unsigned long value); + *edac_dev, unsigned long msec); extern void edac_mc_reset_delay_period(unsigned long value); /* diff --git a/drivers/edac/highbank_mc_edac.c b/drivers/edac/highbank_mc_edac.c index 61b76ec226af..19fba258ae10 100644 --- a/drivers/edac/highbank_mc_edac.c +++ b/drivers/edac/highbank_mc_edac.c @@ -174,8 +174,10 @@ static int highbank_mc_probe(struct platform_device *pdev) drvdata = mci->pvt_info; platform_set_drvdata(pdev, mci); - if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) - return -ENOMEM; + if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) { + res = -ENOMEM; + goto free; + } r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r) { @@ -243,6 +245,7 @@ err2: edac_mc_del_mc(&pdev->dev); err: devres_release_group(&pdev->dev, NULL); +free: edac_mc_free(mci); return res; } diff --git a/drivers/edac/qcom_edac.c b/drivers/edac/qcom_edac.c index 97a27e42dd61..c45519f59dc1 100644 --- a/drivers/edac/qcom_edac.c +++ b/drivers/edac/qcom_edac.c @@ -252,7 +252,7 @@ clear: static int dump_syn_reg(struct edac_device_ctl_info *edev_ctl, int err_type, u32 bank) { - struct llcc_drv_data *drv = edev_ctl->pvt_info; + struct llcc_drv_data *drv = edev_ctl->dev->platform_data; int ret; ret = dump_syn_reg_values(drv, bank, err_type); @@ -289,7 +289,7 @@ static irqreturn_t llcc_ecc_irq_handler(int irq, void *edev_ctl) { struct edac_device_ctl_info *edac_dev_ctl = edev_ctl; - struct llcc_drv_data *drv = edac_dev_ctl->pvt_info; + struct llcc_drv_data *drv = edac_dev_ctl->dev->platform_data; irqreturn_t irq_rc = IRQ_NONE; u32 drp_error, trp_error, i; int ret; @@ -358,7 +358,6 @@ static int qcom_llcc_edac_probe(struct platform_device *pdev) edev_ctl->dev_name = dev_name(dev); edev_ctl->ctl_name = "llcc"; edev_ctl->panic_on_ue = LLCC_ERP_PANIC_ON_UE; - edev_ctl->pvt_info = llcc_driv_data; rc = edac_device_add_device(edev_ctl); if (rc) diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index f818d00bb2c6..ffdad59ec81f 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -910,6 +910,8 @@ static int do_xfer(const struct scmi_protocol_handle *ph, xfer->hdr.protocol_id, xfer->hdr.seq, xfer->hdr.poll_completion); + /* Clear any stale status */ + xfer->hdr.status = SCMI_SUCCESS; xfer->state = SCMI_XFER_SENT_OK; /* * Even though spinlocking is not needed here since no race is possible diff --git a/drivers/firmware/arm_scmi/shmem.c b/drivers/firmware/arm_scmi/shmem.c index 1dfe534b8518..87b4f4d35f06 100644 --- a/drivers/firmware/arm_scmi/shmem.c +++ b/drivers/firmware/arm_scmi/shmem.c @@ -81,10 +81,11 @@ u32 shmem_read_header(struct scmi_shared_mem __iomem *shmem) void shmem_fetch_response(struct scmi_shared_mem __iomem *shmem, struct scmi_xfer *xfer) { + size_t len = ioread32(&shmem->length); + xfer->hdr.status = ioread32(shmem->msg_payload); /* Skip the length of header and status in shmem area i.e 8 bytes */ - xfer->rx.len = min_t(size_t, xfer->rx.len, - ioread32(&shmem->length) - 8); + xfer->rx.len = min_t(size_t, xfer->rx.len, len > 8 ? len - 8 : 0); /* Take a copy to the rx buffer.. */ memcpy_fromio(xfer->rx.buf, shmem->msg_payload + 4, xfer->rx.len); @@ -93,8 +94,10 @@ void shmem_fetch_response(struct scmi_shared_mem __iomem *shmem, void shmem_fetch_notification(struct scmi_shared_mem __iomem *shmem, size_t max_len, struct scmi_xfer *xfer) { + size_t len = ioread32(&shmem->length); + /* Skip only the length of header in shmem area i.e 4 bytes */ - xfer->rx.len = min_t(size_t, max_len, ioread32(&shmem->length) - 4); + xfer->rx.len = min_t(size_t, max_len, len > 4 ? len - 4 : 0); /* Take a copy to the rx buffer.. */ memcpy_fromio(xfer->rx.buf, shmem->msg_payload, xfer->rx.len); diff --git a/drivers/firmware/arm_scmi/virtio.c b/drivers/firmware/arm_scmi/virtio.c index 33c9b81a55cd..1db975c08896 100644 --- a/drivers/firmware/arm_scmi/virtio.c +++ b/drivers/firmware/arm_scmi/virtio.c @@ -160,7 +160,6 @@ static void scmi_vio_channel_cleanup_sync(struct scmi_vio_channel *vioch) } vioch->shutdown_done = &vioch_shutdown_done; - virtio_break_device(vioch->vqueue->vdev); if (!vioch->is_rx && vioch->deferred_tx_wq) /* Cannot be kicked anymore after this...*/ vioch->deferred_tx_wq = NULL; @@ -482,6 +481,12 @@ static int virtio_chan_free(int id, void *p, void *data) struct scmi_chan_info *cinfo = p; struct scmi_vio_channel *vioch = cinfo->transport_info; + /* + * Break device to inhibit further traffic flowing while shutting down + * the channels: doing it later holding vioch->lock creates unsafe + * locking dependency chains as reported by LOCKDEP. + */ + virtio_break_device(vioch->vqueue->vdev); scmi_vio_channel_cleanup_sync(vioch); scmi_free_channel(cinfo, data, id); diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 09716eebe8ac..a2b0cbc8741c 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -394,8 +394,8 @@ static int __init efisubsys_init(void) efi_kobj = kobject_create_and_add("efi", firmware_kobj); if (!efi_kobj) { pr_err("efi: Firmware registration failed.\n"); - destroy_workqueue(efi_rts_wq); - return -ENOMEM; + error = -ENOMEM; + goto err_destroy_wq; } if (efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE | @@ -443,7 +443,10 @@ err_unregister: err_put: kobject_put(efi_kobj); efi_kobj = NULL; - destroy_workqueue(efi_rts_wq); +err_destroy_wq: + if (efi_rts_wq) + destroy_workqueue(efi_rts_wq); + return error; } diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c index 7feee3d9c2bf..1fba4e09cdcf 100644 --- a/drivers/firmware/efi/runtime-wrappers.c +++ b/drivers/firmware/efi/runtime-wrappers.c @@ -62,6 +62,7 @@ struct efi_runtime_work efi_rts_work; \ if (!efi_enabled(EFI_RUNTIME_SERVICES)) { \ pr_warn_once("EFI Runtime Services are disabled!\n"); \ + efi_rts_work.status = EFI_DEVICE_ERROR; \ goto exit; \ } \ \ diff --git a/drivers/firmware/google/coreboot_table.c b/drivers/firmware/google/coreboot_table.c index 2652c396c423..33ae94745aef 100644 --- a/drivers/firmware/google/coreboot_table.c +++ b/drivers/firmware/google/coreboot_table.c @@ -93,14 +93,19 @@ static int coreboot_table_populate(struct device *dev, void *ptr) for (i = 0; i < header->table_entries; i++) { entry = ptr_entry; - device = kzalloc(sizeof(struct device) + entry->size, GFP_KERNEL); + if (entry->size < sizeof(*entry)) { + dev_warn(dev, "coreboot table entry too small!\n"); + return -EINVAL; + } + + device = kzalloc(sizeof(device->dev) + entry->size, GFP_KERNEL); if (!device) return -ENOMEM; device->dev.parent = dev; device->dev.bus = &coreboot_bus_type; device->dev.release = coreboot_device_release; - memcpy(&device->entry, ptr_entry, entry->size); + memcpy(device->raw, ptr_entry, entry->size); switch (device->entry.tag) { case LB_TAG_CBMEM_ENTRY: diff --git a/drivers/firmware/google/coreboot_table.h b/drivers/firmware/google/coreboot_table.h index 37f4d335a606..d814dca33a08 100644 --- a/drivers/firmware/google/coreboot_table.h +++ b/drivers/firmware/google/coreboot_table.h @@ -79,6 +79,7 @@ struct coreboot_device { struct lb_cbmem_ref cbmem_ref; struct lb_cbmem_entry cbmem_entry; struct lb_framebuffer framebuffer; + DECLARE_FLEX_ARRAY(u8, raw); }; }; diff --git a/drivers/firmware/google/gsmi.c b/drivers/firmware/google/gsmi.c index 4e2575dfeb90..871bedf533a8 100644 --- a/drivers/firmware/google/gsmi.c +++ b/drivers/firmware/google/gsmi.c @@ -361,9 +361,10 @@ static efi_status_t gsmi_get_variable(efi_char16_t *name, memcpy(data, gsmi_dev.data_buf->start, *data_size); /* All variables are have the following attributes */ - *attr = EFI_VARIABLE_NON_VOLATILE | - EFI_VARIABLE_BOOTSERVICE_ACCESS | - EFI_VARIABLE_RUNTIME_ACCESS; + if (attr) + *attr = EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS; } spin_unlock_irqrestore(&gsmi_dev.lock, flags); diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c index e7bcfca4159f..447ee4ea5c90 100644 --- a/drivers/firmware/psci/psci.c +++ b/drivers/firmware/psci/psci.c @@ -440,6 +440,9 @@ static const struct file_operations psci_debugfs_ops = { static int __init psci_debugfs_init(void) { + if (!invoke_psci_fn || !psci_ops.get_version) + return 0; + return PTR_ERR_OR_ZERO(debugfs_create_file("psci", 0444, NULL, NULL, &psci_debugfs_ops)); } diff --git a/drivers/gpio/gpio-eic-sprd.c b/drivers/gpio/gpio-eic-sprd.c index 8d722e026e9c..84352a6f4973 100644 --- a/drivers/gpio/gpio-eic-sprd.c +++ b/drivers/gpio/gpio-eic-sprd.c @@ -91,7 +91,6 @@ enum sprd_eic_type { struct sprd_eic { struct gpio_chip chip; - struct irq_chip intc; void __iomem *base[SPRD_EIC_MAX_BANK]; enum sprd_eic_type type; spinlock_t lock; @@ -255,6 +254,8 @@ static void sprd_eic_irq_mask(struct irq_data *data) default: dev_err(chip->parent, "Unsupported EIC type.\n"); } + + gpiochip_disable_irq(chip, offset); } static void sprd_eic_irq_unmask(struct irq_data *data) @@ -263,6 +264,8 @@ static void sprd_eic_irq_unmask(struct irq_data *data) struct sprd_eic *sprd_eic = gpiochip_get_data(chip); u32 offset = irqd_to_hwirq(data); + gpiochip_enable_irq(chip, offset); + switch (sprd_eic->type) { case SPRD_EIC_DEBOUNCE: sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IE, 1); @@ -564,6 +567,15 @@ static void sprd_eic_irq_handler(struct irq_desc *desc) chained_irq_exit(ic, desc); } +static const struct irq_chip sprd_eic_irq = { + .name = "sprd-eic", + .irq_ack = sprd_eic_irq_ack, + .irq_mask = sprd_eic_irq_mask, + .irq_unmask = sprd_eic_irq_unmask, + .irq_set_type = sprd_eic_irq_set_type, + .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; static int sprd_eic_probe(struct platform_device *pdev) { const struct sprd_eic_variant_data *pdata; @@ -626,15 +638,8 @@ static int sprd_eic_probe(struct platform_device *pdev) break; } - sprd_eic->intc.name = dev_name(&pdev->dev); - sprd_eic->intc.irq_ack = sprd_eic_irq_ack; - sprd_eic->intc.irq_mask = sprd_eic_irq_mask; - sprd_eic->intc.irq_unmask = sprd_eic_irq_unmask; - sprd_eic->intc.irq_set_type = sprd_eic_irq_set_type; - sprd_eic->intc.flags = IRQCHIP_SKIP_SET_WAKE; - irq = &sprd_eic->chip.irq; - irq->chip = &sprd_eic->intc; + gpio_irq_chip_set_chip(irq, &sprd_eic_irq); irq->handler = handle_bad_irq; irq->default_type = IRQ_TYPE_NONE; irq->parent_handler = sprd_eic_irq_handler; diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c index 2e1779709113..6cedf46efec6 100644 --- a/drivers/gpio/gpio-ep93xx.c +++ b/drivers/gpio/gpio-ep93xx.c @@ -17,6 +17,7 @@ #include <linux/slab.h> #include <linux/gpio/driver.h> #include <linux/bitops.h> +#include <linux/seq_file.h> #define EP93XX_GPIO_F_INT_STATUS 0x5c #define EP93XX_GPIO_A_INT_STATUS 0xa0 @@ -40,7 +41,6 @@ #define EP93XX_GPIO_F_IRQ_BASE 80 struct ep93xx_gpio_irq_chip { - struct irq_chip ic; u8 irq_offset; u8 int_unmasked; u8 int_enabled; @@ -148,7 +148,7 @@ static void ep93xx_gpio_f_irq_handler(struct irq_desc *desc) */ struct irq_chip *irqchip = irq_desc_get_chip(desc); unsigned int irq = irq_desc_get_irq(desc); - int port_f_idx = ((irq + 1) & 7) ^ 4; /* {19..22,47..50} -> {0..7} */ + int port_f_idx = (irq & 7) ^ 4; /* {20..23,48..51} -> {0..7} */ int gpio_irq = EP93XX_GPIO_F_IRQ_BASE + port_f_idx; chained_irq_enter(irqchip, desc); @@ -185,6 +185,7 @@ static void ep93xx_gpio_irq_mask_ack(struct irq_data *d) ep93xx_gpio_update_int_params(epg, eic); writeb(port_mask, epg->base + eic->irq_offset + EP93XX_INT_EOI_OFFSET); + gpiochip_disable_irq(gc, irqd_to_hwirq(d)); } static void ep93xx_gpio_irq_mask(struct irq_data *d) @@ -195,6 +196,7 @@ static void ep93xx_gpio_irq_mask(struct irq_data *d) eic->int_unmasked &= ~BIT(d->irq & 7); ep93xx_gpio_update_int_params(epg, eic); + gpiochip_disable_irq(gc, irqd_to_hwirq(d)); } static void ep93xx_gpio_irq_unmask(struct irq_data *d) @@ -203,6 +205,7 @@ static void ep93xx_gpio_irq_unmask(struct irq_data *d) struct ep93xx_gpio_irq_chip *eic = to_ep93xx_gpio_irq_chip(gc); struct ep93xx_gpio *epg = gpiochip_get_data(gc); + gpiochip_enable_irq(gc, irqd_to_hwirq(d)); eic->int_unmasked |= BIT(d->irq & 7); ep93xx_gpio_update_int_params(epg, eic); } @@ -320,15 +323,25 @@ static int ep93xx_gpio_set_config(struct gpio_chip *gc, unsigned offset, return 0; } -static void ep93xx_init_irq_chip(struct device *dev, struct irq_chip *ic) +static void ep93xx_irq_print_chip(struct irq_data *data, struct seq_file *p) { - ic->irq_ack = ep93xx_gpio_irq_ack; - ic->irq_mask_ack = ep93xx_gpio_irq_mask_ack; - ic->irq_mask = ep93xx_gpio_irq_mask; - ic->irq_unmask = ep93xx_gpio_irq_unmask; - ic->irq_set_type = ep93xx_gpio_irq_type; + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + + seq_printf(p, dev_name(gc->parent)); } +static const struct irq_chip gpio_eic_irq_chip = { + .name = "ep93xx-gpio-eic", + .irq_ack = ep93xx_gpio_irq_ack, + .irq_mask = ep93xx_gpio_irq_mask, + .irq_unmask = ep93xx_gpio_irq_unmask, + .irq_mask_ack = ep93xx_gpio_irq_mask_ack, + .irq_set_type = ep93xx_gpio_irq_type, + .irq_print_chip = ep93xx_irq_print_chip, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + static int ep93xx_gpio_add_bank(struct ep93xx_gpio_chip *egc, struct platform_device *pdev, struct ep93xx_gpio *epg, @@ -350,8 +363,6 @@ static int ep93xx_gpio_add_bank(struct ep93xx_gpio_chip *egc, girq = &gc->irq; if (bank->has_irq || bank->has_hierarchical_irq) { - struct irq_chip *ic; - gc->set_config = ep93xx_gpio_set_config; egc->eic = devm_kcalloc(dev, 1, sizeof(*egc->eic), @@ -359,12 +370,7 @@ static int ep93xx_gpio_add_bank(struct ep93xx_gpio_chip *egc, if (!egc->eic) return -ENOMEM; egc->eic->irq_offset = bank->irq; - ic = &egc->eic->ic; - ic->name = devm_kasprintf(dev, GFP_KERNEL, "gpio-irq-%s", bank->label); - if (!ic->name) - return -ENOMEM; - ep93xx_init_irq_chip(dev, ic); - girq->chip = ic; + gpio_irq_chip_set_chip(girq, &gpio_eic_irq_chip); } if (bank->has_irq) { diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index d5626c572d24..9d0cec4b82a3 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -18,6 +18,7 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/slab.h> +#include <linux/spinlock.h> #include <linux/syscore_ops.h> #include <linux/gpio/driver.h> #include <linux/of.h> @@ -159,6 +160,7 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type) { struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct mxc_gpio_port *port = gc->private; + unsigned long flags; u32 bit, val; u32 gpio_idx = d->hwirq; int edge; @@ -197,6 +199,8 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type) return -EINVAL; } + raw_spin_lock_irqsave(&port->gc.bgpio_lock, flags); + if (GPIO_EDGE_SEL >= 0) { val = readl(port->base + GPIO_EDGE_SEL); if (edge == GPIO_INT_BOTH_EDGES) @@ -217,15 +221,20 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type) writel(1 << gpio_idx, port->base + GPIO_ISR); port->pad_type[gpio_idx] = type; - return 0; + raw_spin_unlock_irqrestore(&port->gc.bgpio_lock, flags); + + return port->gc.direction_input(&port->gc, gpio_idx); } static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio) { void __iomem *reg = port->base; + unsigned long flags; u32 bit, val; int edge; + raw_spin_lock_irqsave(&port->gc.bgpio_lock, flags); + reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */ bit = gpio & 0xf; val = readl(reg); @@ -240,9 +249,12 @@ static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio) } else { pr_err("mxc: invalid configuration for GPIO %d: %x\n", gpio, edge); - return; + goto unlock; } writel(val | (edge << (bit << 1)), reg); + +unlock: + raw_spin_unlock_irqrestore(&port->gc.bgpio_lock, flags); } /* handle 32 interrupts in one status register */ diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index a59d61cd44b2..5299e5bb76d6 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -474,6 +474,9 @@ static u8 pcal6534_recalc_addr(struct pca953x_chip *chip, int reg, int off) case PCAL6524_DEBOUNCE: pinctrl = ((reg & PCAL_PINCTRL_MASK) >> 1) + 0x1c; break; + default: + pinctrl = 0; + break; } return pinctrl + addr + (off / BANK_SZ); diff --git a/drivers/gpio/gpio-pmic-eic-sprd.c b/drivers/gpio/gpio-pmic-eic-sprd.c index e518490c4b68..c3e4d90f6b18 100644 --- a/drivers/gpio/gpio-pmic-eic-sprd.c +++ b/drivers/gpio/gpio-pmic-eic-sprd.c @@ -47,7 +47,6 @@ enum { /** * struct sprd_pmic_eic - PMIC EIC controller * @chip: the gpio_chip structure. - * @intc: the irq_chip structure. * @map: the regmap from the parent device. * @offset: the EIC controller's offset address of the PMIC. * @reg: the array to cache the EIC registers. @@ -56,7 +55,6 @@ enum { */ struct sprd_pmic_eic { struct gpio_chip chip; - struct irq_chip intc; struct regmap *map; u32 offset; u8 reg[CACHE_NR_REGS]; @@ -151,15 +149,21 @@ static void sprd_pmic_eic_irq_mask(struct irq_data *data) { struct gpio_chip *chip = irq_data_get_irq_chip_data(data); struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip); + u32 offset = irqd_to_hwirq(data); pmic_eic->reg[REG_IE] = 0; pmic_eic->reg[REG_TRIG] = 0; + + gpiochip_disable_irq(chip, offset); } static void sprd_pmic_eic_irq_unmask(struct irq_data *data) { struct gpio_chip *chip = irq_data_get_irq_chip_data(data); struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip); + u32 offset = irqd_to_hwirq(data); + + gpiochip_enable_irq(chip, offset); pmic_eic->reg[REG_IE] = 1; pmic_eic->reg[REG_TRIG] = 1; @@ -292,6 +296,17 @@ static irqreturn_t sprd_pmic_eic_irq_handler(int irq, void *data) return IRQ_HANDLED; } +static const struct irq_chip pmic_eic_irq_chip = { + .name = "sprd-pmic-eic", + .irq_mask = sprd_pmic_eic_irq_mask, + .irq_unmask = sprd_pmic_eic_irq_unmask, + .irq_set_type = sprd_pmic_eic_irq_set_type, + .irq_bus_lock = sprd_pmic_eic_bus_lock, + .irq_bus_sync_unlock = sprd_pmic_eic_bus_sync_unlock, + .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + static int sprd_pmic_eic_probe(struct platform_device *pdev) { struct gpio_irq_chip *irq; @@ -338,16 +353,8 @@ static int sprd_pmic_eic_probe(struct platform_device *pdev) pmic_eic->chip.set = sprd_pmic_eic_set; pmic_eic->chip.get = sprd_pmic_eic_get; - pmic_eic->intc.name = dev_name(&pdev->dev); - pmic_eic->intc.irq_mask = sprd_pmic_eic_irq_mask; - pmic_eic->intc.irq_unmask = sprd_pmic_eic_irq_unmask; - pmic_eic->intc.irq_set_type = sprd_pmic_eic_irq_set_type; - pmic_eic->intc.irq_bus_lock = sprd_pmic_eic_bus_lock; - pmic_eic->intc.irq_bus_sync_unlock = sprd_pmic_eic_bus_sync_unlock; - pmic_eic->intc.flags = IRQCHIP_SKIP_SET_WAKE; - irq = &pmic_eic->chip.irq; - irq->chip = &pmic_eic->intc; + gpio_irq_chip_set_chip(irq, &pmic_eic_irq_chip); irq->threaded = true; ret = devm_gpiochip_add_data(&pdev->dev, &pmic_eic->chip, pmic_eic); diff --git a/drivers/gpio/gpio-sifive.c b/drivers/gpio/gpio-sifive.c index 238f3210970c..bc5660f61c57 100644 --- a/drivers/gpio/gpio-sifive.c +++ b/drivers/gpio/gpio-sifive.c @@ -215,6 +215,7 @@ static int sifive_gpio_probe(struct platform_device *pdev) return -ENODEV; } parent = irq_find_host(irq_parent); + of_node_put(irq_parent); if (!parent) { dev_err(dev, "no IRQ parent domain\n"); return -ENODEV; diff --git a/drivers/gpio/gpio-sprd.c b/drivers/gpio/gpio-sprd.c index 9bff63990eee..072b4e653216 100644 --- a/drivers/gpio/gpio-sprd.c +++ b/drivers/gpio/gpio-sprd.c @@ -120,6 +120,7 @@ static void sprd_gpio_irq_mask(struct irq_data *data) u32 offset = irqd_to_hwirq(data); sprd_gpio_update(chip, offset, SPRD_GPIO_IE, 0); + gpiochip_disable_irq(chip, offset); } static void sprd_gpio_irq_ack(struct irq_data *data) @@ -136,6 +137,7 @@ static void sprd_gpio_irq_unmask(struct irq_data *data) u32 offset = irqd_to_hwirq(data); sprd_gpio_update(chip, offset, SPRD_GPIO_IE, 1); + gpiochip_enable_irq(chip, offset); } static int sprd_gpio_irq_set_type(struct irq_data *data, @@ -205,13 +207,14 @@ static void sprd_gpio_irq_handler(struct irq_desc *desc) chained_irq_exit(ic, desc); } -static struct irq_chip sprd_gpio_irqchip = { +static const struct irq_chip sprd_gpio_irqchip = { .name = "sprd-gpio", .irq_ack = sprd_gpio_irq_ack, .irq_mask = sprd_gpio_irq_mask, .irq_unmask = sprd_gpio_irq_unmask, .irq_set_type = sprd_gpio_irq_set_type, - .flags = IRQCHIP_SKIP_SET_WAKE, + .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, }; static int sprd_gpio_probe(struct platform_device *pdev) @@ -245,7 +248,7 @@ static int sprd_gpio_probe(struct platform_device *pdev) sprd_gpio->chip.direction_output = sprd_gpio_direction_output; irq = &sprd_gpio->chip.irq; - irq->chip = &sprd_gpio_irqchip; + gpio_irq_chip_set_chip(irq, &sprd_gpio_irqchip); irq->handler = handle_bad_irq; irq->default_type = IRQ_TYPE_NONE; irq->parent_handler = sprd_gpio_irq_handler; diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index bed0380c5136..17c53f484280 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -385,7 +385,7 @@ err: } static bool acpi_gpio_irq_is_wake(struct device *parent, - struct acpi_resource_gpio *agpio) + const struct acpi_resource_gpio *agpio) { unsigned int pin = agpio->pin_table[0]; @@ -778,7 +778,7 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data) lookup->info.pin_config = agpio->pin_config; lookup->info.debounce = agpio->debounce_timeout; lookup->info.gpioint = gpioint; - lookup->info.wake_capable = agpio->wake_capable == ACPI_WAKE_CAPABLE; + lookup->info.wake_capable = acpi_gpio_irq_is_wake(&lookup->info.adev->dev, agpio); /* * Polarity and triggering are only specified for GpioInt @@ -1104,7 +1104,8 @@ int acpi_dev_gpio_irq_wake_get_by(struct acpi_device *adev, const char *name, in dev_dbg(&adev->dev, "IRQ %d already in use\n", irq); } - if (wake_capable) + /* avoid suspend issues with GPIOs when systems are using S3 */ + if (wake_capable && acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0) *wake_capable = info.wake_capable; return irq; @@ -1623,6 +1624,19 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] __initconst = { .ignore_interrupt = "AMDI0030:00@18", }, }, + { + /* + * Spurious wakeups from TP_ATTN# pin + * Found in BIOS 1.7.8 + * https://gitlab.freedesktop.org/drm/amd/-/issues/1722#note_1720627 + */ + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"), + }, + .driver_data = &(struct acpi_gpiolib_dmi_quirk) { + .ignore_wake = "ELAN0415:00@9", + }, + }, {} /* Terminating entry */ }; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 5a66d9616d7c..939c776b9488 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -3905,8 +3905,8 @@ static struct gpio_desc *gpiod_find_and_request(struct device *consumer, const char *label, bool platform_lookup_allowed) { + unsigned long lookupflags = GPIO_LOOKUP_FLAGS_DEFAULT; struct gpio_desc *desc = ERR_PTR(-ENOENT); - unsigned long lookupflags; int ret; if (!IS_ERR_OR_NULL(fwnode)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 8b7a09b392ac..0f4cb41078c1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -63,6 +63,8 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, amdgpu_ctx_put(p->ctx); return -ECANCELED; } + + amdgpu_sync_create(&p->sync); return 0; } @@ -454,18 +456,6 @@ static int amdgpu_syncobj_lookup_and_add(struct amdgpu_cs_parser *p, } r = amdgpu_sync_fence(&p->sync, fence); - if (r) - goto error; - - /* - * When we have an explicit dependency it might be necessary to insert a - * pipeline sync to make sure that all caches etc are flushed and the - * next job actually sees the results from the previous one. - */ - if (fence->context == p->gang_leader->base.entity->fence_context) - r = amdgpu_sync_fence(&p->gang_leader->explicit_sync, fence); - -error: dma_fence_put(fence); return r; } @@ -1190,10 +1180,19 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p) static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p) { struct amdgpu_fpriv *fpriv = p->filp->driver_priv; + struct drm_gpu_scheduler *sched; struct amdgpu_bo_list_entry *e; + struct dma_fence *fence; unsigned int i; int r; + r = amdgpu_ctx_wait_prev_fence(p->ctx, p->entities[p->gang_leader_idx]); + if (r) { + if (r != -ERESTARTSYS) + DRM_ERROR("amdgpu_ctx_wait_prev_fence failed.\n"); + return r; + } + list_for_each_entry(e, &p->validated, tv.head) { struct amdgpu_bo *bo = ttm_to_amdgpu_bo(e->tv.bo); struct dma_resv *resv = bo->tbo.base.resv; @@ -1213,10 +1212,24 @@ static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p) return r; } - r = amdgpu_ctx_wait_prev_fence(p->ctx, p->entities[p->gang_leader_idx]); - if (r && r != -ERESTARTSYS) - DRM_ERROR("amdgpu_ctx_wait_prev_fence failed.\n"); - return r; + sched = p->gang_leader->base.entity->rq->sched; + while ((fence = amdgpu_sync_get_fence(&p->sync))) { + struct drm_sched_fence *s_fence = to_drm_sched_fence(fence); + + /* + * When we have an dependency it might be necessary to insert a + * pipeline sync to make sure that all caches etc are flushed and the + * next job actually sees the results from the previous one + * before we start executing on the same scheduler ring. + */ + if (!s_fence || s_fence->sched != sched) + continue; + + r = amdgpu_sync_fence(&p->gang_leader->explicit_sync, fence); + if (r) + return r; + } + return 0; } static void amdgpu_cs_post_dependencies(struct amdgpu_cs_parser *p) @@ -1256,9 +1269,12 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, continue; fence = &p->jobs[i]->base.s_fence->scheduled; + dma_fence_get(fence); r = drm_sched_job_add_dependency(&leader->base, fence); - if (r) + if (r) { + dma_fence_put(fence); goto error_cleanup; + } } if (p->gang_size > 1) { @@ -1346,6 +1362,7 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser) { unsigned i; + amdgpu_sync_free(&parser->sync); for (i = 0; i < parser->num_post_deps; i++) { drm_syncobj_put(parser->post_deps[i].syncobj); kfree(parser->post_deps[i].chain); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 1257745fb202..5bee3ff62344 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3038,6 +3038,18 @@ static int amdgpu_device_ip_suspend_phase2(struct amdgpu_device *adev) (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SDMA)) continue; + /* Once swPSP provides the IMU, RLC FW binaries to TOS during cold-boot. + * These are in TMR, hence are expected to be reused by PSP-TOS to reload + * from this location and RLC Autoload automatically also gets loaded + * from here based on PMFW -> PSP message during re-init sequence. + * Therefore, the psp suspend & resume should be skipped to avoid destroy + * the TMR and reload FWs again for IMU enabled APU ASICs. + */ + if (amdgpu_in_reset(adev) && + (adev->flags & AMD_IS_APU) && adev->gfx.imu.funcs && + adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP) + continue; + /* XXX handle errors */ r = adev->ip_blocks[i].version->funcs->suspend(adev); /* XXX handle errors */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 44c57f4a84c4..32fe05c810c6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -549,8 +549,8 @@ struct amdgpu_mst_connector { struct drm_dp_mst_topology_mgr mst_mgr; struct amdgpu_dm_dp_aux dm_dp_aux; - struct drm_dp_mst_port *port; - struct amdgpu_connector *mst_port; + struct drm_dp_mst_port *mst_output_port; + struct amdgpu_connector *mst_root; bool is_mst_connector; struct amdgpu_encoder *mst_encoder; }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c index bac7976975bd..dcd8c066bc1f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c @@ -391,8 +391,10 @@ int amdgpu_sync_push_to_job(struct amdgpu_sync *sync, struct amdgpu_job *job) dma_fence_get(f); r = drm_sched_job_add_dependency(&job->base, f); - if (r) + if (r) { + dma_fence_put(f); return r; + } } return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c b/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c index ed0d368149aa..4ab90c7852c3 100644 --- a/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c @@ -35,6 +35,7 @@ MODULE_FIRMWARE("amdgpu/gc_11_0_0_imu.bin"); MODULE_FIRMWARE("amdgpu/gc_11_0_1_imu.bin"); MODULE_FIRMWARE("amdgpu/gc_11_0_2_imu.bin"); MODULE_FIRMWARE("amdgpu/gc_11_0_3_imu.bin"); +MODULE_FIRMWARE("amdgpu/gc_11_0_4_imu.bin"); static int imu_v11_0_init_microcode(struct amdgpu_device *adev) { diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c index bfa305079bfc..62cdd2113135 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c @@ -40,6 +40,8 @@ MODULE_FIRMWARE("amdgpu/gc_11_0_2_mes.bin"); MODULE_FIRMWARE("amdgpu/gc_11_0_2_mes1.bin"); MODULE_FIRMWARE("amdgpu/gc_11_0_3_mes.bin"); MODULE_FIRMWARE("amdgpu/gc_11_0_3_mes1.bin"); +MODULE_FIRMWARE("amdgpu/gc_11_0_4_mes.bin"); +MODULE_FIRMWARE("amdgpu/gc_11_0_4_mes1.bin"); static int mes_v11_0_hw_fini(void *handle); static int mes_v11_0_kiq_hw_init(struct amdgpu_device *adev); @@ -196,7 +198,6 @@ static int mes_v11_0_add_hw_queue(struct amdgpu_mes *mes, mes_add_queue_pkt.trap_handler_addr = input->tba_addr; mes_add_queue_pkt.tma_addr = input->tma_addr; mes_add_queue_pkt.is_kfd_process = input->is_kfd_process; - mes_add_queue_pkt.trap_en = 1; /* For KFD, gds_size is re-used for queue size (needed in MES for AQL queues) */ mes_add_queue_pkt.is_aql_queue = input->is_aql_queue; diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index 9c4a29d50f1c..e03cf7f766c5 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -52,6 +52,7 @@ static const struct amdgpu_video_codec_info vcn_4_0_0_video_codecs_encode_array_ { {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2304, 0)}, {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 2304, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)}, }; static const struct amdgpu_video_codec_info vcn_4_0_0_video_codecs_encode_array_vcn1[] = diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c index efb22d0975b3..22a41766a8c7 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c @@ -1710,7 +1710,7 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job, create = ptr + addr + offset - start; - /* H246, HEVC and VP9 can run on any instance */ + /* H264, HEVC and VP9 can run on any instance */ if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11) continue; @@ -1724,7 +1724,29 @@ out: return r; } -#define RADEON_VCN_ENGINE_TYPE_DECODE (0x00000003) +#define RADEON_VCN_ENGINE_TYPE_ENCODE (0x00000002) +#define RADEON_VCN_ENGINE_TYPE_DECODE (0x00000003) + +#define RADEON_VCN_ENGINE_INFO (0x30000001) +#define RADEON_VCN_ENGINE_INFO_MAX_OFFSET 16 + +#define RENCODE_ENCODE_STANDARD_AV1 2 +#define RENCODE_IB_PARAM_SESSION_INIT 0x00000003 +#define RENCODE_IB_PARAM_SESSION_INIT_MAX_OFFSET 64 + +/* return the offset in ib if id is found, -1 otherwise + * to speed up the searching we only search upto max_offset + */ +static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int max_offset) +{ + int i; + + for (i = 0; i < ib->length_dw && i < max_offset && ib->ptr[i] >= 8; i += ib->ptr[i]/4) { + if (ib->ptr[i + 1] == id) + return i; + } + return -1; +} static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p, struct amdgpu_job *job, @@ -1734,27 +1756,35 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p, struct amdgpu_vcn_decode_buffer *decode_buffer; uint64_t addr; uint32_t val; + int idx; /* The first instance can decode anything */ if (!ring->me) return 0; - /* unified queue ib header has 8 double words. */ - if (ib->length_dw < 8) - return 0; - - val = amdgpu_ib_get_value(ib, 6); //RADEON_VCN_ENGINE_TYPE - if (val != RADEON_VCN_ENGINE_TYPE_DECODE) - return 0; - - decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[10]; - - if (!(decode_buffer->valid_buf_flag & 0x1)) + /* RADEON_VCN_ENGINE_INFO is at the top of ib block */ + idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, + RADEON_VCN_ENGINE_INFO_MAX_OFFSET); + if (idx < 0) /* engine info is missing */ return 0; - addr = ((u64)decode_buffer->msg_buffer_address_hi) << 32 | - decode_buffer->msg_buffer_address_lo; - return vcn_v4_0_dec_msg(p, job, addr); + val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */ + if (val == RADEON_VCN_ENGINE_TYPE_DECODE) { + decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[idx + 6]; + + if (!(decode_buffer->valid_buf_flag & 0x1)) + return 0; + + addr = ((u64)decode_buffer->msg_buffer_address_hi) << 32 | + decode_buffer->msg_buffer_address_lo; + return vcn_v4_0_dec_msg(p, job, addr); + } else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) { + idx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, + RENCODE_IB_PARAM_SESSION_INIT_MAX_OFFSET); + if (idx >= 0 && ib->ptr[idx + 2] == RENCODE_ENCODE_STANDARD_AV1) + return vcn_v4_0_limit_sched(p, job); + } + return 0; } static const struct amdgpu_ring_funcs vcn_v4_0_unified_ring_vm_funcs = { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 8e4b668faa35..e1d63826927a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -28,7 +28,6 @@ #include "dm_services_types.h" #include "dc.h" -#include "dc_link_dp.h" #include "link_enc_cfg.h" #include "dc/inc/core_types.h" #include "dal_asic_id.h" @@ -39,6 +38,9 @@ #include "dc/dc_edid_parser.h" #include "dc/dc_stat.h" #include "amdgpu_dm_trace.h" +#include "dpcd_defs.h" +#include "link/protocols/link_dpcd.h" +#include "link_service_types.h" #include "vid.h" #include "amdgpu.h" @@ -1225,10 +1227,25 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_ pa_config->gart_config.page_table_end_addr = page_table_end.quad_part << 12; pa_config->gart_config.page_table_base_addr = page_table_base.quad_part; - pa_config->is_hvm_enabled = 0; + pa_config->is_hvm_enabled = adev->mode_info.gpu_vm_support; } +static void force_connector_state( + struct amdgpu_dm_connector *aconnector, + enum drm_connector_force force_state) +{ + struct drm_connector *connector = &aconnector->base; + + mutex_lock(&connector->dev->mode_config.mutex); + aconnector->base.force = force_state; + mutex_unlock(&connector->dev->mode_config.mutex); + + mutex_lock(&aconnector->hpd_lock); + drm_kms_helper_connector_hotplug_event(connector); + mutex_unlock(&aconnector->hpd_lock); +} + static void dm_handle_hpd_rx_offload_work(struct work_struct *work) { struct hpd_rx_irq_offload_work *offload_work; @@ -1237,6 +1254,9 @@ static void dm_handle_hpd_rx_offload_work(struct work_struct *work) struct amdgpu_device *adev; enum dc_connection_type new_connection_type = dc_connection_none; unsigned long flags; + union test_response test_response; + + memset(&test_response, 0, sizeof(test_response)); offload_work = container_of(work, struct hpd_rx_irq_offload_work, work); aconnector = offload_work->offload_wq->aconnector; @@ -1261,10 +1281,26 @@ static void dm_handle_hpd_rx_offload_work(struct work_struct *work) goto skip; mutex_lock(&adev->dm.dc_lock); - if (offload_work->data.bytes.device_service_irq.bits.AUTOMATED_TEST) + if (offload_work->data.bytes.device_service_irq.bits.AUTOMATED_TEST) { dc_link_dp_handle_automated_test(dc_link); + + if (aconnector->timing_changed) { + /* force connector disconnect and reconnect */ + force_connector_state(aconnector, DRM_FORCE_OFF); + msleep(100); + force_connector_state(aconnector, DRM_FORCE_UNSPECIFIED); + } + + test_response.bits.ACK = 1; + + core_link_write_dpcd( + dc_link, + DP_TEST_RESPONSE, + &test_response.raw, + sizeof(test_response)); + } else if ((dc_link->connector_signal != SIGNAL_TYPE_EDP) && - hpd_rx_irq_check_link_loss_status(dc_link, &offload_work->data) && + dc_link_check_link_loss_status(dc_link, &offload_work->data) && dc_link_dp_allow_hpd_rx_irq(dc_link)) { dc_link_dp_handle_link_loss(dc_link); spin_lock_irqsave(&offload_work->offload_wq->offload_lock, flags); @@ -2197,7 +2233,7 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend) drm_for_each_connector_iter(connector, &iter) { aconnector = to_amdgpu_dm_connector(connector); if (aconnector->dc_link->type != dc_connection_mst_branch || - aconnector->mst_port) + aconnector->mst_root) continue; mgr = &aconnector->mst_mgr; @@ -2987,6 +3023,10 @@ void amdgpu_dm_update_connector_after_detect( aconnector->edid); } + aconnector->timing_requested = kzalloc(sizeof(struct dc_crtc_timing), GFP_KERNEL); + if (!aconnector->timing_requested) + dm_error("%s: failed to create aconnector->requested_timing\n", __func__); + drm_connector_update_edid_property(connector, aconnector->edid); amdgpu_dm_update_freesync_caps(connector, aconnector->edid); update_connector_ext_caps(aconnector); @@ -2998,6 +3038,8 @@ void amdgpu_dm_update_connector_after_detect( dc_sink_release(aconnector->dc_sink); aconnector->dc_sink = NULL; aconnector->edid = NULL; + kfree(aconnector->timing_requested); + aconnector->timing_requested = NULL; #ifdef CONFIG_DRM_AMD_DC_HDCP /* Set CP to DESIRED if it was ENABLED, so we can re-enable it again on hotplug */ if (connector->state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED) @@ -3042,6 +3084,8 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector) if (aconnector->fake_enable) aconnector->fake_enable = false; + aconnector->timing_changed = false; + if (!dc_link_detect_sink(aconnector->dc_link, &new_connection_type)) DRM_ERROR("KMS: Failed to detect connector\n"); @@ -5888,6 +5932,14 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, stream, &mode, &aconnector->base, con_state, old_stream, requested_bpc); + if (aconnector->timing_changed) { + DC_LOG_DEBUG("%s: overriding timing for automated test, bpc %d, changing to %d\n", + __func__, + stream->timing.display_color_depth, + aconnector->timing_requested->display_color_depth); + stream->timing = *aconnector->timing_requested; + } + #if defined(CONFIG_DRM_AMD_DC_DCN) /* SST DSC determination policy */ update_dsc_caps(aconnector, sink, stream, &dsc_caps); @@ -6580,11 +6632,11 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder, int clock, bpp = 0; bool is_y420 = false; - if (!aconnector->port || !aconnector->dc_sink) + if (!aconnector->mst_output_port || !aconnector->dc_sink) return 0; - mst_port = aconnector->port; - mst_mgr = &aconnector->mst_port->mst_mgr; + mst_port = aconnector->mst_output_port; + mst_mgr = &aconnector->mst_root->mst_mgr; if (!crtc_state->connectors_changed && !crtc_state->mode_changed) return 0; @@ -6594,7 +6646,7 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder, return PTR_ERR(mst_state); if (!mst_state->pbn_div) - mst_state->pbn_div = dm_mst_get_pbn_divider(aconnector->mst_port->dc_link); + mst_state->pbn_div = dm_mst_get_pbn_divider(aconnector->mst_root->dc_link); if (!state->duplicated) { int max_bpc = conn_state->max_requested_bpc; @@ -6640,7 +6692,7 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state, aconnector = to_amdgpu_dm_connector(connector); - if (!aconnector->port) + if (!aconnector->mst_output_port) continue; if (!new_con_state || !new_con_state->crtc) @@ -6680,7 +6732,7 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state, dm_conn_state->pbn = pbn; dm_conn_state->vcpi_slots = slot_num; - ret = drm_dp_mst_atomic_enable_dsc(state, aconnector->port, + ret = drm_dp_mst_atomic_enable_dsc(state, aconnector->mst_output_port, dm_conn_state->pbn, false); if (ret < 0) return ret; @@ -6688,7 +6740,7 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state, continue; } - vcpi = drm_dp_mst_atomic_enable_dsc(state, aconnector->port, pbn, true); + vcpi = drm_dp_mst_atomic_enable_dsc(state, aconnector->mst_output_port, pbn, true); if (vcpi < 0) return vcpi; @@ -7102,7 +7154,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, adev->mode_info.underscan_vborder_property, 0); - if (!aconnector->mst_port) + if (!aconnector->mst_root) drm_connector_attach_max_bpc_property(&aconnector->base, 8, 16); /* This defaults to the max in the range, but we want 8bpc for non-edp. */ @@ -7120,7 +7172,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, connector_type == DRM_MODE_CONNECTOR_eDP) { drm_connector_attach_hdr_output_metadata_property(&aconnector->base); - if (!aconnector->mst_port) + if (!aconnector->mst_root) drm_connector_attach_vrr_capable_property(&aconnector->base); #ifdef CONFIG_DRM_AMD_DC_HDCP @@ -7604,6 +7656,7 @@ static void update_freesync_state_on_stream( new_crtc_state->vrr_infopacket = vrr_infopacket; new_stream->vrr_infopacket = vrr_infopacket; + new_stream->allow_freesync = mod_freesync_get_freesync_enabled(&vrr_params); if (new_crtc_state->freesync_vrr_info_changed) DRM_DEBUG_KMS("VRR packet update: crtc=%u enabled=%d state=%d", @@ -8818,22 +8871,15 @@ static void get_freesync_config_for_crtc( struct drm_display_mode *mode = &new_crtc_state->base.mode; int vrefresh = drm_mode_vrefresh(mode); bool fs_vid_mode = false; - bool drr_active = false; new_crtc_state->vrr_supported = new_con_state->freesync_capable && vrefresh >= aconnector->min_vfreq && vrefresh <= aconnector->max_vfreq; - drr_active = new_crtc_state->vrr_supported && - new_crtc_state->freesync_config.state != VRR_STATE_DISABLED && - new_crtc_state->freesync_config.state != VRR_STATE_INACTIVE && - new_crtc_state->freesync_config.state != VRR_STATE_UNSUPPORTED; - - if (drr_active) - new_crtc_state->stream->ignore_msa_timing_param = true; - if (new_crtc_state->vrr_supported) { + new_crtc_state->stream->ignore_msa_timing_param = true; fs_vid_mode = new_crtc_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED; + config.min_refresh_in_uhz = aconnector->min_vfreq * 1000000; config.max_refresh_in_uhz = aconnector->max_vfreq * 1000000; config.vsif_supported = true; @@ -9032,6 +9078,13 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, if (!dm_old_crtc_state->stream) goto skip_modeset; + /* Unset freesync video if it was active before */ + if (dm_old_crtc_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED) { + dm_new_crtc_state->freesync_config.state = VRR_STATE_INACTIVE; + dm_new_crtc_state->freesync_config.fixed_refresh_in_uhz = 0; + } + + /* Now check if we should set freesync video mode */ if (amdgpu_freesync_vid_mode && dm_new_crtc_state->stream && is_timing_unchanged_for_freesync(new_crtc_state, old_crtc_state)) { @@ -9593,7 +9646,7 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm continue; aconnector = to_amdgpu_dm_connector(connector); - if (!aconnector->port || !aconnector->mst_port) + if (!aconnector->mst_output_port || !aconnector->mst_root) aconnector = NULL; else break; @@ -9602,7 +9655,7 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm if (!aconnector) return 0; - return drm_dp_mst_add_affected_dsc_crtcs(state, &aconnector->mst_port->mst_mgr); + return drm_dp_mst_add_affected_dsc_crtcs(state, &aconnector->mst_root->mst_mgr); } #endif @@ -9648,6 +9701,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, bool lock_and_validation_needed = false; struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state; #if defined(CONFIG_DRM_AMD_DC_DCN) + struct drm_dp_mst_topology_mgr *mgr; + struct drm_dp_mst_topology_state *mst_state; struct dsc_mst_fairness_vars vars[MAX_PIPES]; #endif @@ -9896,6 +9951,28 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, lock_and_validation_needed = true; } +#if defined(CONFIG_DRM_AMD_DC_DCN) + /* set the slot info for each mst_state based on the link encoding format */ + for_each_new_mst_mgr_in_state(state, mgr, mst_state, i) { + struct amdgpu_dm_connector *aconnector; + struct drm_connector *connector; + struct drm_connector_list_iter iter; + u8 link_coding_cap; + + drm_connector_list_iter_begin(dev, &iter); + drm_for_each_connector_iter(connector, &iter) { + if (connector->index == mst_state->mgr->conn_base_id) { + aconnector = to_amdgpu_dm_connector(connector); + link_coding_cap = dc_link_dp_mst_decide_link_encoding_format(aconnector->dc_link); + drm_dp_mst_update_slots(mst_state, link_coding_cap); + + break; + } + } + drm_connector_list_iter_end(&iter); + } +#endif + /** * Streams and planes are reset when there are changes that affect * bandwidth. Anything that affects bandwidth needs to go through @@ -10165,11 +10242,15 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector, struct amdgpu_hdmi_vsdb_info *vsdb_info) { struct amdgpu_device *adev = drm_to_adev(aconnector->base.dev); + bool ret; + mutex_lock(&adev->dm.dc_lock); if (adev->dm.dmub_srv) - return parse_edid_cea_dmub(&adev->dm, edid_ext, len, vsdb_info); + ret = parse_edid_cea_dmub(&adev->dm, edid_ext, len, vsdb_info); else - return parse_edid_cea_dmcu(&adev->dm, edid_ext, len, vsdb_info); + ret = parse_edid_cea_dmcu(&adev->dm, edid_ext, len, vsdb_info); + mutex_unlock(&adev->dm.dc_lock); + return ret; } static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector, @@ -10445,6 +10526,7 @@ int amdgpu_dm_process_dmub_aux_transfer_sync( ret = p_notify->aux_reply.length; *operation_result = p_notify->result; out: + reinit_completion(&adev->dm.dmub_aux_transfer_done); mutex_unlock(&adev->dm.dpia_aux_lock); return ret; } @@ -10472,6 +10554,8 @@ int amdgpu_dm_process_dmub_set_config_sync( *operation_result = SET_CONFIG_UNKNOWN_ERROR; } + if (!is_cmd_complete) + reinit_completion(&adev->dm.dmub_aux_transfer_done); mutex_unlock(&adev->dm.dpia_aux_lock); return ret; } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index abbbb3813c1e..d89f2eaf9117 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -31,6 +31,7 @@ #include <drm/drm_connector.h> #include <drm/drm_crtc.h> #include <drm/drm_plane.h> +#include "link_service_types.h" /* * This file contains the definition for amdgpu_display_manager @@ -604,8 +605,8 @@ struct amdgpu_dm_connector { /* DM only */ struct drm_dp_mst_topology_mgr mst_mgr; struct amdgpu_dm_dp_aux dm_dp_aux; - struct drm_dp_mst_port *port; - struct amdgpu_dm_connector *mst_port; + struct drm_dp_mst_port *mst_output_port; + struct amdgpu_dm_connector *mst_root; struct drm_dp_aux *dsc_aux; /* TODO see if we can merge with ddc_bus or make a dm_connector */ struct amdgpu_i2c_adapter *i2c; @@ -644,6 +645,10 @@ struct amdgpu_dm_connector { /* Record progress status of mst*/ uint8_t mst_status; + + /* Automated testing */ + bool timing_changed; + struct dc_crtc_timing *timing_requested; }; static inline void amdgpu_dm_set_mst_status(uint8_t *status, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c index 8873ecada27c..27711743c22c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c @@ -344,7 +344,7 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name) goto cleanup; } - aux = (aconn->port) ? &aconn->port->aux : &aconn->dm_dp_aux.aux; + aux = (aconn->mst_output_port) ? &aconn->mst_output_port->aux : &aconn->dm_dp_aux.aux; if (!aux) { DRM_DEBUG_DRIVER("No dp aux for amd connector\n"); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 704860e6ba84..e783082a4eef 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -34,8 +34,6 @@ #include "dmub/dmub_srv.h" #include "resource.h" #include "dsc.h" -#include "dc_link_dp.h" -#include "dc_link.h" #include "link_hwss.h" #include "dc/dc_dmub_srv.h" @@ -1193,7 +1191,7 @@ static int dp_dsc_fec_support_show(struct seq_file *m, void *data) break; } dpcd_caps = aconnector->dc_link->dpcd_caps; - if (aconnector->port) { + if (aconnector->mst_output_port) { /* aconnector sets dsc_aux during get_modes call * if MST connector has it means it can either * enable DSC on the sink device or on MST branch @@ -1280,7 +1278,7 @@ static ssize_t trigger_hotplug(struct file *f, const char __user *buf, mutex_lock(&aconnector->hpd_lock); /* Don't support for mst end device*/ - if (aconnector->mst_port) { + if (aconnector->mst_root) { mutex_unlock(&aconnector->hpd_lock); return -EINVAL; } @@ -2539,13 +2537,13 @@ static int dp_is_mst_connector_show(struct seq_file *m, void *unused) if (aconnector->mst_mgr.mst_state) { role = "root"; - } else if (aconnector->mst_port && - aconnector->mst_port->mst_mgr.mst_state) { + } else if (aconnector->mst_root && + aconnector->mst_root->mst_mgr.mst_state) { role = "end"; - mgr = &aconnector->mst_port->mst_mgr; - port = aconnector->port; + mgr = &aconnector->mst_root->mst_mgr; + port = aconnector->mst_output_port; drm_modeset_lock(&mgr->base.lock, NULL); if (port->pdt == DP_PEER_DEVICE_MST_BRANCHING && @@ -3392,12 +3390,12 @@ static int trigger_hpd_mst_set(void *data, u64 val) if (!aconnector->dc_link) continue; - if (!aconnector->mst_port) + if (!aconnector->mst_root) continue; link = aconnector->dc_link; dc_link_dp_receiver_power_ctrl(link, false); - drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_port->mst_mgr, false); + drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_root->mst_mgr, false); link->mst_stream_alloc_table.stream_count = 0; memset(link->mst_stream_alloc_table.stream_allocations, 0, sizeof(link->mst_stream_alloc_table.stream_allocations)); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 6994c9a1ed85..a50319fc42b1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -38,6 +38,8 @@ #include "amdgpu_dm.h" #include "amdgpu_dm_irq.h" #include "amdgpu_dm_mst_types.h" +#include "dpcd_defs.h" +#include "dc/inc/core_types.h" #include "dm_helpers.h" #include "ddc_service_types.h" @@ -120,23 +122,50 @@ enum dc_edid_status dm_helpers_parse_edid_caps( } static void -fill_dc_mst_payload_table_from_drm(struct drm_dp_mst_topology_state *mst_state, - struct amdgpu_dm_connector *aconnector, +fill_dc_mst_payload_table_from_drm(struct dc_link *link, + bool enable, + struct drm_dp_mst_atomic_payload *target_payload, struct dc_dp_mst_stream_allocation_table *table) { struct dc_dp_mst_stream_allocation_table new_table = { 0 }; struct dc_dp_mst_stream_allocation *sa; - struct drm_dp_mst_atomic_payload *payload; + struct link_mst_stream_allocation_table copy_of_link_table = + link->mst_stream_alloc_table; - /* Fill payload info*/ - list_for_each_entry(payload, &mst_state->payloads, next) { - if (payload->delete) - continue; + int i; + int current_hw_table_stream_cnt = copy_of_link_table.stream_count; + struct link_mst_stream_allocation *dc_alloc; - sa = &new_table.stream_allocations[new_table.stream_count]; - sa->slot_count = payload->time_slots; - sa->vcp_id = payload->vcpi; - new_table.stream_count++; + /* TODO: refactor to set link->mst_stream_alloc_table directly if possible.*/ + if (enable) { + dc_alloc = + ©_of_link_table.stream_allocations[current_hw_table_stream_cnt]; + dc_alloc->vcp_id = target_payload->vcpi; + dc_alloc->slot_count = target_payload->time_slots; + } else { + for (i = 0; i < copy_of_link_table.stream_count; i++) { + dc_alloc = + ©_of_link_table.stream_allocations[i]; + + if (dc_alloc->vcp_id == target_payload->vcpi) { + dc_alloc->vcp_id = 0; + dc_alloc->slot_count = 0; + break; + } + } + ASSERT(i != copy_of_link_table.stream_count); + } + + /* Fill payload info*/ + for (i = 0; i < MAX_CONTROLLER_NUM; i++) { + dc_alloc = + ©_of_link_table.stream_allocations[i]; + if (dc_alloc->vcp_id > 0 && dc_alloc->slot_count > 0) { + sa = &new_table.stream_allocations[new_table.stream_count]; + sa->slot_count = dc_alloc->slot_count; + sa->vcp_id = dc_alloc->vcp_id; + new_table.stream_count++; + } } /* Overwrite the old table */ @@ -168,14 +197,14 @@ bool dm_helpers_dp_mst_write_payload_allocation_table( * that blocks before commit guaranteeing that the state * is not gonna be swapped while still in use in commit tail */ - if (!aconnector || !aconnector->mst_port) + if (!aconnector || !aconnector->mst_root) return false; - mst_mgr = &aconnector->mst_port->mst_mgr; + mst_mgr = &aconnector->mst_root->mst_mgr; mst_state = to_drm_dp_mst_topology_state(mst_mgr->base.state); /* It's OK for this to fail */ - payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->port); + payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->mst_output_port); if (enable) drm_dp_add_payload_part1(mst_mgr, mst_state, payload); else @@ -185,7 +214,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table( * AUX message. The sequence is slot 1-63 allocated sequence for each * stream. AMD ASIC stream slot allocation should follow the same * sequence. copy DRM MST allocation to dc */ - fill_dc_mst_payload_table_from_drm(mst_state, aconnector, proposed_table); + fill_dc_mst_payload_table_from_drm(stream->link, enable, payload, proposed_table); return true; } @@ -220,10 +249,10 @@ enum act_return_status dm_helpers_dp_mst_poll_for_allocation_change_trigger( aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; - if (!aconnector || !aconnector->mst_port) + if (!aconnector || !aconnector->mst_root) return ACT_FAILED; - mst_mgr = &aconnector->mst_port->mst_mgr; + mst_mgr = &aconnector->mst_root->mst_mgr; if (!mst_mgr->mst_state) return ACT_FAILED; @@ -247,22 +276,27 @@ bool dm_helpers_dp_mst_send_payload_allocation( struct drm_dp_mst_atomic_payload *payload; enum mst_progress_status set_flag = MST_ALLOCATE_NEW_PAYLOAD; enum mst_progress_status clr_flag = MST_CLEAR_ALLOCATED_PAYLOAD; + int ret = 0; aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; - if (!aconnector || !aconnector->mst_port) + if (!aconnector || !aconnector->mst_root) return false; - mst_mgr = &aconnector->mst_port->mst_mgr; + mst_mgr = &aconnector->mst_root->mst_mgr; mst_state = to_drm_dp_mst_topology_state(mst_mgr->base.state); - payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->port); + payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->mst_output_port); + if (!enable) { set_flag = MST_CLEAR_ALLOCATED_PAYLOAD; clr_flag = MST_ALLOCATE_NEW_PAYLOAD; } - if (enable && drm_dp_add_payload_part2(mst_mgr, mst_state->base.state, payload)) { + if (enable) + ret = drm_dp_add_payload_part2(mst_mgr, mst_state->base.state, payload); + + if (ret) { amdgpu_dm_set_mst_status(&aconnector->mst_status, set_flag, false); } else { @@ -683,7 +717,7 @@ bool dm_helpers_dp_write_dsc_enable( aconnector->dsc_aux, stream, enable_dsc); #endif - port = aconnector->port; + port = aconnector->mst_output_port; if (enable) { if (port->passthrough_aux) { @@ -960,6 +994,128 @@ void dm_helpers_mst_enable_stream_features(const struct dc_stream_state *stream) sizeof(new_downspread)); } +bool dm_helpers_dp_handle_test_pattern_request( + struct dc_context *ctx, + const struct dc_link *link, + union link_test_pattern dpcd_test_pattern, + union test_misc dpcd_test_params) +{ + enum dp_test_pattern test_pattern; + enum dp_test_pattern_color_space test_pattern_color_space = + DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED; + enum dc_color_depth requestColorDepth = COLOR_DEPTH_UNDEFINED; + enum dc_pixel_encoding requestPixelEncoding = PIXEL_ENCODING_UNDEFINED; + struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx; + struct pipe_ctx *pipe_ctx = NULL; + struct amdgpu_dm_connector *aconnector = link->priv; + int i; + + for (i = 0; i < MAX_PIPES; i++) { + if (pipes[i].stream == NULL) + continue; + + if (pipes[i].stream->link == link && !pipes[i].top_pipe && + !pipes[i].prev_odm_pipe) { + pipe_ctx = &pipes[i]; + break; + } + } + + if (pipe_ctx == NULL) + return false; + + switch (dpcd_test_pattern.bits.PATTERN) { + case LINK_TEST_PATTERN_COLOR_RAMP: + test_pattern = DP_TEST_PATTERN_COLOR_RAMP; + break; + case LINK_TEST_PATTERN_VERTICAL_BARS: + test_pattern = DP_TEST_PATTERN_VERTICAL_BARS; + break; /* black and white */ + case LINK_TEST_PATTERN_COLOR_SQUARES: + test_pattern = (dpcd_test_params.bits.DYN_RANGE == + TEST_DYN_RANGE_VESA ? + DP_TEST_PATTERN_COLOR_SQUARES : + DP_TEST_PATTERN_COLOR_SQUARES_CEA); + break; + default: + test_pattern = DP_TEST_PATTERN_VIDEO_MODE; + break; + } + + if (dpcd_test_params.bits.CLR_FORMAT == 0) + test_pattern_color_space = DP_TEST_PATTERN_COLOR_SPACE_RGB; + else + test_pattern_color_space = dpcd_test_params.bits.YCBCR_COEFS ? + DP_TEST_PATTERN_COLOR_SPACE_YCBCR709 : + DP_TEST_PATTERN_COLOR_SPACE_YCBCR601; + + switch (dpcd_test_params.bits.BPC) { + case 0: // 6 bits + requestColorDepth = COLOR_DEPTH_666; + break; + case 1: // 8 bits + requestColorDepth = COLOR_DEPTH_888; + break; + case 2: // 10 bits + requestColorDepth = COLOR_DEPTH_101010; + break; + case 3: // 12 bits + requestColorDepth = COLOR_DEPTH_121212; + break; + default: + break; + } + + switch (dpcd_test_params.bits.CLR_FORMAT) { + case 0: + requestPixelEncoding = PIXEL_ENCODING_RGB; + break; + case 1: + requestPixelEncoding = PIXEL_ENCODING_YCBCR422; + break; + case 2: + requestPixelEncoding = PIXEL_ENCODING_YCBCR444; + break; + default: + requestPixelEncoding = PIXEL_ENCODING_RGB; + break; + } + + if ((requestColorDepth != COLOR_DEPTH_UNDEFINED + && pipe_ctx->stream->timing.display_color_depth != requestColorDepth) + || (requestPixelEncoding != PIXEL_ENCODING_UNDEFINED + && pipe_ctx->stream->timing.pixel_encoding != requestPixelEncoding)) { + DC_LOG_DEBUG("%s: original bpc %d pix encoding %d, changing to %d %d\n", + __func__, + pipe_ctx->stream->timing.display_color_depth, + pipe_ctx->stream->timing.pixel_encoding, + requestColorDepth, + requestPixelEncoding); + pipe_ctx->stream->timing.display_color_depth = requestColorDepth; + pipe_ctx->stream->timing.pixel_encoding = requestPixelEncoding; + + dp_update_dsc_config(pipe_ctx); + + aconnector->timing_changed = true; + /* store current timing */ + if (aconnector->timing_requested) + *aconnector->timing_requested = pipe_ctx->stream->timing; + else + DC_LOG_ERROR("%s: timing storage failed\n", __func__); + + } + + dc_link_dp_set_test_pattern( + (struct dc_link *) link, + test_pattern, + test_pattern_color_space, + NULL, + NULL, + 0); + + return false; +} + void dm_set_phyd32clk(struct dc_context *ctx, int freq_khz) { // TODO diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 5fa9bab95038..0bff2cc20b02 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -39,7 +39,6 @@ #include "dc.h" #include "dm_helpers.h" -#include "dc_link_dp.h" #include "ddc_service_types.h" #include "dpcd_defs.h" @@ -134,7 +133,7 @@ dm_dp_mst_connector_destroy(struct drm_connector *connector) kfree(aconnector->edid); drm_connector_cleanup(connector); - drm_dp_mst_put_port_malloc(aconnector->port); + drm_dp_mst_put_port_malloc(aconnector->mst_output_port); kfree(aconnector); } @@ -146,7 +145,7 @@ amdgpu_dm_mst_connector_late_register(struct drm_connector *connector) int r; r = drm_dp_mst_connector_late_register(connector, - amdgpu_dm_connector->port); + amdgpu_dm_connector->mst_output_port); if (r < 0) return r; @@ -162,8 +161,8 @@ amdgpu_dm_mst_connector_early_unregister(struct drm_connector *connector) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); - struct drm_dp_mst_port *port = aconnector->port; - struct amdgpu_dm_connector *root = aconnector->mst_port; + struct drm_dp_mst_port *port = aconnector->mst_output_port; + struct amdgpu_dm_connector *root = aconnector->mst_root; struct dc_link *dc_link = aconnector->dc_link; struct dc_sink *dc_sink = aconnector->dc_sink; @@ -213,7 +212,7 @@ bool needs_dsc_aux_workaround(struct dc_link *link) static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnector) { struct dc_sink *dc_sink = aconnector->dc_sink; - struct drm_dp_mst_port *port = aconnector->port; + struct drm_dp_mst_port *port = aconnector->mst_output_port; u8 dsc_caps[16] = { 0 }; u8 dsc_branch_dec_caps_raw[3] = { 0 }; // DSC branch decoder caps 0xA0 ~ 0xA2 u8 *dsc_branch_dec_caps = NULL; @@ -231,7 +230,7 @@ static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnecto */ if (!aconnector->dsc_aux && !port->parent->port_parent && needs_dsc_aux_workaround(aconnector->dc_link)) - aconnector->dsc_aux = &aconnector->mst_port->dm_dp_aux.aux; + aconnector->dsc_aux = &aconnector->mst_root->dm_dp_aux.aux; if (!aconnector->dsc_aux) return false; @@ -281,7 +280,7 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector) if (!aconnector->edid) { struct edid *edid; - edid = drm_dp_mst_get_edid(connector, &aconnector->mst_port->mst_mgr, aconnector->port); + edid = drm_dp_mst_get_edid(connector, &aconnector->mst_root->mst_mgr, aconnector->mst_output_port); if (!edid) { amdgpu_dm_set_mst_status(&aconnector->mst_status, @@ -410,15 +409,15 @@ dm_dp_mst_detect(struct drm_connector *connector, struct drm_modeset_acquire_ctx *ctx, bool force) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); - struct amdgpu_dm_connector *master = aconnector->mst_port; - struct drm_dp_mst_port *port = aconnector->port; + struct amdgpu_dm_connector *master = aconnector->mst_root; + struct drm_dp_mst_port *port = aconnector->mst_output_port; int connection_status; if (drm_connector_is_unregistered(connector)) return connector_status_disconnected; connection_status = drm_dp_mst_detect_port(connector, ctx, &master->mst_mgr, - aconnector->port); + aconnector->mst_output_port); if (port->pdt != DP_PEER_DEVICE_NONE && !port->dpcd_rev) { uint8_t dpcd_rev; @@ -475,8 +474,8 @@ static int dm_dp_mst_atomic_check(struct drm_connector *connector, struct drm_atomic_state *state) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); - struct drm_dp_mst_topology_mgr *mst_mgr = &aconnector->mst_port->mst_mgr; - struct drm_dp_mst_port *mst_port = aconnector->port; + struct drm_dp_mst_topology_mgr *mst_mgr = &aconnector->mst_root->mst_mgr; + struct drm_dp_mst_port *mst_port = aconnector->mst_output_port; return drm_dp_atomic_release_time_slots(state, mst_mgr, mst_port); } @@ -538,8 +537,8 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, return NULL; connector = &aconnector->base; - aconnector->port = port; - aconnector->mst_port = master; + aconnector->mst_output_port = port; + aconnector->mst_root = master; amdgpu_dm_set_mst_status(&aconnector->mst_status, MST_PROBE, true); @@ -927,11 +926,6 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, if (IS_ERR(mst_state)) return PTR_ERR(mst_state); - mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link); -#if defined(CONFIG_DRM_AMD_DC_DCN) - drm_dp_mst_update_slots(mst_state, dc_link_dp_mst_decide_link_encoding_format(dc_link)); -#endif - /* Set up params */ for (i = 0; i < dc_state->stream_count; i++) { struct dc_dsc_policy dsc_policy = {0}; @@ -945,7 +939,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, if (!aconnector) continue; - if (!aconnector->port) + if (!aconnector->mst_output_port) continue; stream->timing.flags.DSC = 0; @@ -953,7 +947,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, params[count].timing = &stream->timing; params[count].sink = stream->sink; params[count].aconnector = aconnector; - params[count].port = aconnector->port; + params[count].port = aconnector->mst_output_port; params[count].clock_force_enable = aconnector->dsc_settings.dsc_force_enable; if (params[count].clock_force_enable == DSC_CLK_FORCE_ENABLE) debugfs_overwrite = true; @@ -1162,7 +1156,7 @@ int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state, aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; - if (!aconnector || !aconnector->dc_sink || !aconnector->port) + if (!aconnector || !aconnector->dc_sink || !aconnector->mst_output_port) continue; if (!aconnector->dc_sink->dsc_caps.dsc_dec_caps.is_dsc_supported) @@ -1177,7 +1171,7 @@ int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state, if (!is_dsc_need_re_compute(state, dc_state, stream->link)) continue; - mst_mgr = aconnector->port->mgr; + mst_mgr = aconnector->mst_output_port->mgr; ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars, mst_mgr, &link_vars_start_index); if (ret != 0) @@ -1223,7 +1217,7 @@ static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state, aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; - if (!aconnector || !aconnector->dc_sink || !aconnector->port) + if (!aconnector || !aconnector->dc_sink || !aconnector->mst_output_port) continue; if (!aconnector->dc_sink->dsc_caps.dsc_dec_caps.is_dsc_supported) @@ -1235,7 +1229,7 @@ static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state, if (!is_dsc_need_re_compute(state, dc_state, stream->link)) continue; - mst_mgr = aconnector->port->mgr; + mst_mgr = aconnector->mst_output_port->mgr; ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars, mst_mgr, &link_vars_start_index); if (ret != 0) @@ -1450,8 +1444,8 @@ enum dc_status dm_dp_mst_is_port_support_mode( * with DSC enabled. */ if (is_dsc_common_config_possible(stream, &bw_range) && - aconnector->port->passthrough_aux) { - mst_mgr = aconnector->port->mgr; + aconnector->mst_output_port->passthrough_aux) { + mst_mgr = aconnector->mst_output_port->mgr; mutex_lock(&mst_mgr->lock); cur_link_settings = stream->link->verified_link_cap; @@ -1459,7 +1453,7 @@ enum dc_status dm_dp_mst_is_port_support_mode( upper_link_bw_in_kbps = dc_link_bandwidth_kbps(aconnector->dc_link, &cur_link_settings ); - down_link_bw_in_kbps = kbps_from_pbn(aconnector->port->full_pbn); + down_link_bw_in_kbps = kbps_from_pbn(aconnector->mst_output_port->full_pbn); /* pick the bottleneck */ end_to_end_bw_in_kbps = min(upper_link_bw_in_kbps, @@ -1483,7 +1477,7 @@ enum dc_status dm_dp_mst_is_port_support_mode( bpp = convert_dc_color_depth_into_bpc(stream->timing.display_color_depth) * 3; pbn = drm_dp_calc_pbn_mode(stream->timing.pix_clk_100hz / 10, bpp, false); - if (pbn > aconnector->port->full_pbn) + if (pbn > aconnector->mst_output_port->full_pbn) return DC_FAIL_BANDWIDTH_VALIDATE; #if defined(CONFIG_DRM_AMD_DC_DCN) } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c index 872d06fe1436..d647f68fd563 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c @@ -122,7 +122,7 @@ bool amdgpu_dm_link_setup_psr(struct dc_stream_state *stream) psr_config.allow_multi_disp_optimizations = (amdgpu_dc_feature_mask & DC_PSR_ALLOW_MULTI_DISP_OPT); - if (!psr_su_set_y_granularity(dc, link, stream, &psr_config)) + if (!psr_su_set_dsc_slice_height(dc, link, stream, &psr_config)) return false; ret = dc_link_setup_psr(link, stream, &psr_config, &psr_context); diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile index 98c508313350..fec32e20f854 100644 --- a/drivers/gpu/drm/amd/display/dc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -65,8 +65,7 @@ AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/dc/,$(DC_LI include $(AMD_DC) DISPLAY_CORE = dc.o dc_stat.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_sink.o \ -dc_surface.o dc_link_dp.o dc_debug.o dc_stream.o \ -dc_link_enc_cfg.o +dc_surface.o dc_debug.o dc_stream.o dc_link_enc_cfg.o DISPLAY_CORE += dc_vm_helper.o diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c index f276abb63bcd..69691daf4dbb 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c @@ -29,6 +29,7 @@ #include "dc_types.h" #include "dccg.h" #include "clk_mgr_internal.h" +#include "link.h" #include "dce100/dce_clk_mgr.h" #include "dce110/dce110_clk_mgr.h" diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c index 1c0569b1dc8f..f9e2e0c3095e 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c @@ -47,6 +47,7 @@ #include "dcn30/dcn30_clk_mgr.h" #include "dc_dmub_srv.h" +#include "link.h" #include "logger_types.h" #undef DC_LOGGER diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c index 20a06c04e4a1..89df7244b272 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c @@ -48,7 +48,7 @@ #include "dcn31/dcn31_clk_mgr.h" #include "dc_dmub_srv.h" -#include "dc_link_dp.h" +#include "link.h" #include "dcn314_smu.h" diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c index 07edd9777edf..8c368bcc8e7e 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c @@ -46,7 +46,7 @@ #define DC_LOGGER \ clk_mgr->base.base.ctx->logger -#include "dc_link_dp.h" +#include "link.h" #define TO_CLK_MGR_DCN315(clk_mgr)\ container_of(clk_mgr, struct clk_mgr_dcn315, base) @@ -87,6 +87,16 @@ static int dcn315_get_active_display_cnt_wa( return display_count; } +bool should_disable_otg(struct pipe_ctx *pipe) +{ + bool ret = true; + + if (pipe->stream->link->link_enc && pipe->stream->link->link_enc->funcs->is_dig_enabled && + pipe->stream->link->link_enc->funcs->is_dig_enabled(pipe->stream->link->link_enc)) + ret = false; + return ret; +} + static void dcn315_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool disable) { struct dc *dc = clk_mgr_base->ctx->dc; @@ -98,12 +108,16 @@ static void dcn315_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state if (pipe->top_pipe || pipe->prev_odm_pipe) continue; if (pipe->stream && (pipe->stream->dpms_off || pipe->plane_state == NULL || - dc_is_virtual_signal(pipe->stream->signal))) { - if (disable) { - pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg); - reset_sync_context_for_pipe(dc, context, i); - } else - pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg); + dc_is_virtual_signal(pipe->stream->signal))) { + + /* This w/a should not trigger when we have a dig active */ + if (should_disable_otg(pipe)) { + if (disable) { + pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg); + reset_sync_context_for_pipe(dc, context, i); + } else + pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg); + } } } } diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c index 3edc81e2d417..93db4dbee713 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c @@ -39,7 +39,7 @@ #include "dcn316_smu.h" #include "dm_helpers.h" #include "dc_dmub_srv.h" -#include "dc_link_dp.h" +#include "link.h" // DCN316 this is CLK1 instance #define MAX_INSTANCE 7 diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c index 352c977d1495..61768bf726f8 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c @@ -33,7 +33,6 @@ #include "reg_helper.h" #include "core_types.h" #include "dm_helpers.h" -#include "dc_link_dp.h" #include "link.h" #include "atomfirmware.h" diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 53e586fc1501..f11bc8d9d0c4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -58,7 +58,6 @@ #include "dm_helpers.h" #include "mem_input.h" -#include "dc_link_dp.h" #include "dc_dmub_srv.h" #include "dsc.h" @@ -1659,7 +1658,7 @@ bool dc_validate_boot_timing(const struct dc *dc, return false; } - if (is_edp_ilr_optimization_required(link, crtc_timing)) { + if (link_is_edp_ilr_optimization_required(link, crtc_timing)) { DC_LOG_EVENT_LINK_TRAINING("Seamless boot disabled to optimize eDP link rate\n"); return false; } @@ -2960,6 +2959,9 @@ static void copy_stream_update_to_stream(struct dc *dc, if (update->vsp_infopacket) stream->vsp_infopacket = *update->vsp_infopacket; + if (update->adaptive_sync_infopacket) + stream->adaptive_sync_infopacket = *update->adaptive_sync_infopacket; + if (update->dither_option) stream->dither_option = *update->dither_option; @@ -3165,6 +3167,7 @@ static void commit_planes_do_stream_update(struct dc *dc, stream_update->vsc_infopacket || stream_update->vsp_infopacket || stream_update->hfvsif_infopacket || + stream_update->adaptive_sync_infopacket || stream_update->vtem_infopacket) { resource_build_info_frame(pipe_ctx); dc->hwss.update_info_frame(pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index d9e490eca10f..6475664baa8a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -32,9 +32,8 @@ #include "grph_object_id.h" #include "gpio_service_interface.h" #include "core_status.h" -#include "dc_link_dp.h" -#include "link/link_dp_dpia.h" -#include "link/link_ddc.h" +#include "link/protocols/link_dp_dpia.h" +#include "link/protocols/link_ddc.h" #include "link_hwss.h" #include "link.h" #include "opp.h" @@ -46,17 +45,20 @@ #include "fixed31_32.h" #include "dpcd_defs.h" #include "dmcu.h" +#include "dsc.h" +#include "opp.h" #include "hw/clk_mgr.h" #include "dce/dmub_psr.h" #include "dmub/dmub_srv.h" #include "inc/hw/panel_cntl.h" #include "inc/link_enc_cfg.h" -#include "link/link_dpcd.h" -#include "link/link_dp_trace.h" -#include "link/link_hpd.h" -#include "link/link_dp_training.h" -#include "link/link_dp_phy.h" -#include "link/link_dp_capability.h" +#include "link/protocols/link_dpcd.h" +#include "link/accessories/link_dp_trace.h" +#include "link/protocols/link_hpd.h" +#include "link/protocols/link_dp_training.h" +#include "link/protocols/link_dp_phy.h" +#include "link/protocols/link_dp_capability.h" +#include "link/protocols/link_edp_panel_control.h" #include "dc/dcn30/dcn30_vpg.h" @@ -107,17 +109,6 @@ static void dc_link_destruct(struct dc_link *link) dc_sink_release(link->remote_sinks[i]); } -bool dc_link_wait_for_t12(struct dc_link *link) -{ - if (link->connector_signal == SIGNAL_TYPE_EDP && link->dc->hwss.edp_wait_for_T12) { - link->dc->hwss.edp_wait_for_T12(link); - - return true; - } - - return false; -} - /** * dc_link_detect_sink() - Determine if there is a sink connected * @@ -1094,7 +1085,7 @@ static bool detect_link_and_local_sink(struct dc_link *link, (link->dpcd_sink_ext_caps.bits.oled == 1)) { dpcd_set_source_specific_data(link); msleep(post_oui_delay); - dc_link_set_default_brightness_aux(link); + set_default_brightness_aux(link); //TODO: use cached } @@ -2067,10 +2058,10 @@ static enum dc_status enable_link_dp(struct dc_state *state, if (link->dpcd_sink_ext_caps.bits.oled == 1 || link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1 || link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1) { - dc_link_set_default_brightness_aux(link); // TODO: use cached if known + set_default_brightness_aux(link); // TODO: use cached if known if (link->dpcd_sink_ext_caps.bits.oled == 1) msleep(bl_oled_enable_delay); - dc_link_backlight_enable_aux(link, true); + link_backlight_enable_aux(link, true); } return status; @@ -2740,22 +2731,6 @@ static void enable_link_lvds(struct pipe_ctx *pipe_ctx) } -bool dc_power_alpm_dpcd_enable(struct dc_link *link, bool enable) -{ - bool ret = false; - union dpcd_alpm_configuration alpm_config; - - if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) { - memset(&alpm_config, 0, sizeof(alpm_config)); - - alpm_config.bits.ENABLE = (enable ? true : false); - ret = dm_helpers_dp_write_dpcd(link->ctx, link, - DP_RECEIVER_ALPM_CONFIG, &alpm_config.raw, - sizeof(alpm_config.raw)); - } - return ret; -} - /****************************enable_link***********************************/ static enum dc_status enable_link( struct dc_state *state, @@ -3035,436 +3010,6 @@ enum dc_status dc_link_validate_mode_timing( return DC_OK; } -static struct abm *get_abm_from_stream_res(const struct dc_link *link) -{ - int i; - struct dc *dc = NULL; - struct abm *abm = NULL; - - if (!link || !link->ctx) - return NULL; - - dc = link->ctx->dc; - - for (i = 0; i < MAX_PIPES; i++) { - struct pipe_ctx pipe_ctx = dc->current_state->res_ctx.pipe_ctx[i]; - struct dc_stream_state *stream = pipe_ctx.stream; - - if (stream && stream->link == link) { - abm = pipe_ctx.stream_res.abm; - break; - } - } - return abm; -} - -int dc_link_get_backlight_level(const struct dc_link *link) -{ - struct abm *abm = get_abm_from_stream_res(link); - struct panel_cntl *panel_cntl = link->panel_cntl; - struct dc *dc = link->ctx->dc; - struct dmcu *dmcu = dc->res_pool->dmcu; - bool fw_set_brightness = true; - - if (dmcu) - fw_set_brightness = dmcu->funcs->is_dmcu_initialized(dmcu); - - if (!fw_set_brightness && panel_cntl->funcs->get_current_backlight) - return panel_cntl->funcs->get_current_backlight(panel_cntl); - else if (abm != NULL && abm->funcs->get_current_backlight != NULL) - return (int) abm->funcs->get_current_backlight(abm); - else - return DC_ERROR_UNEXPECTED; -} - -int dc_link_get_target_backlight_pwm(const struct dc_link *link) -{ - struct abm *abm = get_abm_from_stream_res(link); - - if (abm == NULL || abm->funcs->get_target_backlight == NULL) - return DC_ERROR_UNEXPECTED; - - return (int) abm->funcs->get_target_backlight(abm); -} - -static struct pipe_ctx *get_pipe_from_link(const struct dc_link *link) -{ - int i; - struct dc *dc = link->ctx->dc; - struct pipe_ctx *pipe_ctx = NULL; - - for (i = 0; i < MAX_PIPES; i++) { - if (dc->current_state->res_ctx.pipe_ctx[i].stream) { - if (dc->current_state->res_ctx.pipe_ctx[i].stream->link == link) { - pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; - break; - } - } - } - - return pipe_ctx; -} - -bool dc_link_set_backlight_level(const struct dc_link *link, - uint32_t backlight_pwm_u16_16, - uint32_t frame_ramp) -{ - struct dc *dc = link->ctx->dc; - - DC_LOGGER_INIT(link->ctx->logger); - DC_LOG_BACKLIGHT("New Backlight level: %d (0x%X)\n", - backlight_pwm_u16_16, backlight_pwm_u16_16); - - if (dc_is_embedded_signal(link->connector_signal)) { - struct pipe_ctx *pipe_ctx = get_pipe_from_link(link); - - if (pipe_ctx) { - /* Disable brightness ramping when the display is blanked - * as it can hang the DMCU - */ - if (pipe_ctx->plane_state == NULL) - frame_ramp = 0; - } else { - return false; - } - - dc->hwss.set_backlight_level( - pipe_ctx, - backlight_pwm_u16_16, - frame_ramp); - } - return true; -} - -bool dc_link_set_psr_allow_active(struct dc_link *link, const bool *allow_active, - bool wait, bool force_static, const unsigned int *power_opts) -{ - struct dc *dc = link->ctx->dc; - struct dmcu *dmcu = dc->res_pool->dmcu; - struct dmub_psr *psr = dc->res_pool->psr; - unsigned int panel_inst; - - if (psr == NULL && force_static) - return false; - - if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst)) - return false; - - if ((allow_active != NULL) && (*allow_active == true) && (link->type == dc_connection_none)) { - // Don't enter PSR if panel is not connected - return false; - } - - /* Set power optimization flag */ - if (power_opts && link->psr_settings.psr_power_opt != *power_opts) { - link->psr_settings.psr_power_opt = *power_opts; - - if (psr != NULL && link->psr_settings.psr_feature_enabled && psr->funcs->psr_set_power_opt) - psr->funcs->psr_set_power_opt(psr, link->psr_settings.psr_power_opt, panel_inst); - } - - if (psr != NULL && link->psr_settings.psr_feature_enabled && - force_static && psr->funcs->psr_force_static) - psr->funcs->psr_force_static(psr, panel_inst); - - /* Enable or Disable PSR */ - if (allow_active && link->psr_settings.psr_allow_active != *allow_active) { - link->psr_settings.psr_allow_active = *allow_active; - - if (!link->psr_settings.psr_allow_active) - dc_z10_restore(dc); - - if (psr != NULL && link->psr_settings.psr_feature_enabled) { - psr->funcs->psr_enable(psr, link->psr_settings.psr_allow_active, wait, panel_inst); - } else if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu)) && - link->psr_settings.psr_feature_enabled) - dmcu->funcs->set_psr_enable(dmcu, link->psr_settings.psr_allow_active, wait); - else - return false; - } - - return true; -} - -bool dc_link_get_psr_state(const struct dc_link *link, enum dc_psr_state *state) -{ - struct dc *dc = link->ctx->dc; - struct dmcu *dmcu = dc->res_pool->dmcu; - struct dmub_psr *psr = dc->res_pool->psr; - unsigned int panel_inst; - - if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst)) - return false; - - if (psr != NULL && link->psr_settings.psr_feature_enabled) - psr->funcs->psr_get_state(psr, state, panel_inst); - else if (dmcu != NULL && link->psr_settings.psr_feature_enabled) - dmcu->funcs->get_psr_state(dmcu, state); - - return true; -} - -static inline enum physical_phy_id -transmitter_to_phy_id(enum transmitter transmitter_value) -{ - switch (transmitter_value) { - case TRANSMITTER_UNIPHY_A: - return PHYLD_0; - case TRANSMITTER_UNIPHY_B: - return PHYLD_1; - case TRANSMITTER_UNIPHY_C: - return PHYLD_2; - case TRANSMITTER_UNIPHY_D: - return PHYLD_3; - case TRANSMITTER_UNIPHY_E: - return PHYLD_4; - case TRANSMITTER_UNIPHY_F: - return PHYLD_5; - case TRANSMITTER_NUTMEG_CRT: - return PHYLD_6; - case TRANSMITTER_TRAVIS_CRT: - return PHYLD_7; - case TRANSMITTER_TRAVIS_LCD: - return PHYLD_8; - case TRANSMITTER_UNIPHY_G: - return PHYLD_9; - case TRANSMITTER_COUNT: - return PHYLD_COUNT; - case TRANSMITTER_UNKNOWN: - return PHYLD_UNKNOWN; - default: - WARN_ONCE(1, "Unknown transmitter value %d\n", - transmitter_value); - return PHYLD_UNKNOWN; - } -} - -bool dc_link_setup_psr(struct dc_link *link, - const struct dc_stream_state *stream, struct psr_config *psr_config, - struct psr_context *psr_context) -{ - struct dc *dc; - struct dmcu *dmcu; - struct dmub_psr *psr; - int i; - unsigned int panel_inst; - /* updateSinkPsrDpcdConfig*/ - union dpcd_psr_configuration psr_configuration; - union dpcd_sink_active_vtotal_control_mode vtotal_control = {0}; - - psr_context->controllerId = CONTROLLER_ID_UNDEFINED; - - if (!link) - return false; - - dc = link->ctx->dc; - dmcu = dc->res_pool->dmcu; - psr = dc->res_pool->psr; - - if (!dmcu && !psr) - return false; - - if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst)) - return false; - - - memset(&psr_configuration, 0, sizeof(psr_configuration)); - - psr_configuration.bits.ENABLE = 1; - psr_configuration.bits.CRC_VERIFICATION = 1; - psr_configuration.bits.FRAME_CAPTURE_INDICATION = - psr_config->psr_frame_capture_indication_req; - - /* Check for PSR v2*/ - if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) { - /* For PSR v2 selective update. - * Indicates whether sink should start capturing - * immediately following active scan line, - * or starting with the 2nd active scan line. - */ - psr_configuration.bits.LINE_CAPTURE_INDICATION = 0; - /*For PSR v2, determines whether Sink should generate - * IRQ_HPD when CRC mismatch is detected. - */ - psr_configuration.bits.IRQ_HPD_WITH_CRC_ERROR = 1; - /* For PSR v2, set the bit when the Source device will - * be enabling PSR2 operation. - */ - psr_configuration.bits.ENABLE_PSR2 = 1; - /* For PSR v2, the Sink device must be able to receive - * SU region updates early in the frame time. - */ - psr_configuration.bits.EARLY_TRANSPORT_ENABLE = 1; - } - - dm_helpers_dp_write_dpcd( - link->ctx, - link, - 368, - &psr_configuration.raw, - sizeof(psr_configuration.raw)); - - if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) { - dc_power_alpm_dpcd_enable(link, true); - psr_context->su_granularity_required = - psr_config->su_granularity_required; - psr_context->su_y_granularity = - psr_config->su_y_granularity; - psr_context->line_time_in_us = - psr_config->line_time_in_us; - - if (link->psr_settings.psr_vtotal_control_support) { - psr_context->rate_control_caps = psr_config->rate_control_caps; - vtotal_control.bits.ENABLE = true; - core_link_write_dpcd(link, DP_SINK_PSR_ACTIVE_VTOTAL_CONTROL_MODE, - &vtotal_control.raw, sizeof(vtotal_control.raw)); - } - } - - psr_context->channel = link->ddc->ddc_pin->hw_info.ddc_channel; - psr_context->transmitterId = link->link_enc->transmitter; - psr_context->engineId = link->link_enc->preferred_engine; - - for (i = 0; i < MAX_PIPES; i++) { - if (dc->current_state->res_ctx.pipe_ctx[i].stream - == stream) { - /* dmcu -1 for all controller id values, - * therefore +1 here - */ - psr_context->controllerId = - dc->current_state->res_ctx. - pipe_ctx[i].stream_res.tg->inst + 1; - break; - } - } - - /* Hardcoded for now. Can be Pcie or Uniphy (or Unknown)*/ - psr_context->phyType = PHY_TYPE_UNIPHY; - /*PhyId is associated with the transmitter id*/ - psr_context->smuPhyId = - transmitter_to_phy_id(link->link_enc->transmitter); - - psr_context->crtcTimingVerticalTotal = stream->timing.v_total; - psr_context->vsync_rate_hz = div64_u64(div64_u64((stream-> - timing.pix_clk_100hz * 100), - stream->timing.v_total), - stream->timing.h_total); - - psr_context->psrSupportedDisplayConfig = true; - psr_context->psrExitLinkTrainingRequired = - psr_config->psr_exit_link_training_required; - psr_context->sdpTransmitLineNumDeadline = - psr_config->psr_sdp_transmit_line_num_deadline; - psr_context->psrFrameCaptureIndicationReq = - psr_config->psr_frame_capture_indication_req; - - psr_context->skipPsrWaitForPllLock = 0; /* only = 1 in KV */ - - psr_context->numberOfControllers = - link->dc->res_pool->timing_generator_count; - - psr_context->rfb_update_auto_en = true; - - /* 2 frames before enter PSR. */ - psr_context->timehyst_frames = 2; - /* half a frame - * (units in 100 lines, i.e. a value of 1 represents 100 lines) - */ - psr_context->hyst_lines = stream->timing.v_total / 2 / 100; - psr_context->aux_repeats = 10; - - psr_context->psr_level.u32all = 0; - - /*skip power down the single pipe since it blocks the cstate*/ -#if defined(CONFIG_DRM_AMD_DC_DCN) - if (link->ctx->asic_id.chip_family >= FAMILY_RV) { - switch(link->ctx->asic_id.chip_family) { - case FAMILY_YELLOW_CARP: - case AMDGPU_FAMILY_GC_10_3_6: - case AMDGPU_FAMILY_GC_11_0_1: - if (dc->debug.disable_z10 || dc->debug.psr_skip_crtc_disable) - psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true; - break; - default: - psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true; - break; - } - } -#else - if (link->ctx->asic_id.chip_family >= FAMILY_RV) - psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true; -#endif - - /* SMU will perform additional powerdown sequence. - * For unsupported ASICs, set psr_level flag to skip PSR - * static screen notification to SMU. - * (Always set for DAL2, did not check ASIC) - */ - psr_context->allow_smu_optimizations = psr_config->allow_smu_optimizations; - psr_context->allow_multi_disp_optimizations = psr_config->allow_multi_disp_optimizations; - - /* Complete PSR entry before aborting to prevent intermittent - * freezes on certain eDPs - */ - psr_context->psr_level.bits.DISABLE_PSR_ENTRY_ABORT = 1; - - /* enable ALPM */ - psr_context->psr_level.bits.DISABLE_ALPM = 0; - psr_context->psr_level.bits.ALPM_DEFAULT_PD_MODE = 1; - - /* Controls additional delay after remote frame capture before - * continuing power down, default = 0 - */ - psr_context->frame_delay = 0; - - if (psr) { - link->psr_settings.psr_feature_enabled = psr->funcs->psr_copy_settings(psr, - link, psr_context, panel_inst); - link->psr_settings.psr_power_opt = 0; - link->psr_settings.psr_allow_active = 0; - } - else - link->psr_settings.psr_feature_enabled = dmcu->funcs->setup_psr(dmcu, link, psr_context); - - /* psr_enabled == 0 indicates setup_psr did not succeed, but this - * should not happen since firmware should be running at this point - */ - if (link->psr_settings.psr_feature_enabled == 0) - ASSERT(0); - - return true; - -} - -void dc_link_get_psr_residency(const struct dc_link *link, uint32_t *residency) -{ - struct dc *dc = link->ctx->dc; - struct dmub_psr *psr = dc->res_pool->psr; - unsigned int panel_inst; - - if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst)) - return; - - /* PSR residency measurements only supported on DMCUB */ - if (psr != NULL && link->psr_settings.psr_feature_enabled) - psr->funcs->psr_get_residency(psr, residency, panel_inst); - else - *residency = 0; -} - -bool dc_link_set_sink_vtotal_in_psr_active(const struct dc_link *link, uint16_t psr_vtotal_idle, uint16_t psr_vtotal_su) -{ - struct dc *dc = link->ctx->dc; - struct dmub_psr *psr = dc->res_pool->psr; - - if (psr == NULL || !link->psr_settings.psr_feature_enabled || !link->psr_settings.psr_vtotal_control_support) - return false; - - psr->funcs->psr_set_sink_vtotal_in_psr_active(psr, psr_vtotal_idle, psr_vtotal_su); - - return true; -} - const struct dc_link_status *dc_link_get_status(const struct dc_link *link) { return &link->link_status; @@ -3999,10 +3544,13 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) struct fixed31_32 avg_time_slots_per_mtp = dc_fixpt_from_int(0); int i; bool mst_mode = (link->type == dc_connection_mst_branch); + /* adjust for drm changes*/ + bool update_drm_mst_state = true; const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); const struct dc_link_settings empty_link_settings = {0}; DC_LOGGER_INIT(link->ctx->logger); + /* deallocate_mst_payload is called before disable link. When mode or * disable/enable monitor, new stream is created which is not in link * stream[] yet. For this, payload is not allocated yet, so de-alloc @@ -4018,7 +3566,7 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) &empty_link_settings, avg_time_slots_per_mtp); - if (mst_mode) { + if (mst_mode || update_drm_mst_state) { /* when link is in mst mode, reply on mst manager to remove * payload */ @@ -4081,11 +3629,18 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) stream->ctx, stream); + if (!update_drm_mst_state) + dm_helpers_dp_mst_send_payload_allocation( + stream->ctx, + stream, + false); + } + + if (update_drm_mst_state) dm_helpers_dp_mst_send_payload_allocation( stream->ctx, stream, false); - } return DC_OK; } @@ -4541,110 +4096,6 @@ void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) dc->hwss.set_avmute(pipe_ctx, enable); } -void dc_link_set_drive_settings(struct dc *dc, - struct link_training_settings *lt_settings, - const struct dc_link *link) -{ - - int i; - struct link_resource link_res; - - for (i = 0; i < dc->link_count; i++) - if (dc->links[i] == link) - break; - - if (i >= dc->link_count) - ASSERT_CRITICAL(false); - - dc_link_get_cur_link_res(link, &link_res); - dc_link_dp_set_drive_settings(dc->links[i], &link_res, lt_settings); -} - -void dc_link_set_preferred_link_settings(struct dc *dc, - struct dc_link_settings *link_setting, - struct dc_link *link) -{ - int i; - struct pipe_ctx *pipe; - struct dc_stream_state *link_stream; - struct dc_link_settings store_settings = *link_setting; - - link->preferred_link_setting = store_settings; - - /* Retrain with preferred link settings only relevant for - * DP signal type - * Check for non-DP signal or if passive dongle present - */ - if (!dc_is_dp_signal(link->connector_signal) || - link->dongle_max_pix_clk > 0) - return; - - for (i = 0; i < MAX_PIPES; i++) { - pipe = &dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe->stream && pipe->stream->link) { - if (pipe->stream->link == link) { - link_stream = pipe->stream; - break; - } - } - } - - /* Stream not found */ - if (i == MAX_PIPES) - return; - - /* Cannot retrain link if backend is off */ - if (link_stream->dpms_off) - return; - - if (link_decide_link_settings(link_stream, &store_settings)) - dp_retrain_link_dp_test(link, &store_settings, false); -} - -void dc_link_set_preferred_training_settings(struct dc *dc, - struct dc_link_settings *link_setting, - struct dc_link_training_overrides *lt_overrides, - struct dc_link *link, - bool skip_immediate_retrain) -{ - if (lt_overrides != NULL) - link->preferred_training_settings = *lt_overrides; - else - memset(&link->preferred_training_settings, 0, sizeof(link->preferred_training_settings)); - - if (link_setting != NULL) { - link->preferred_link_setting = *link_setting; - } else { - link->preferred_link_setting.lane_count = LANE_COUNT_UNKNOWN; - link->preferred_link_setting.link_rate = LINK_RATE_UNKNOWN; - } - - if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT && - link->type == dc_connection_mst_branch) - dm_helpers_dp_mst_update_branch_bandwidth(dc->ctx, link); - - /* Retrain now, or wait until next stream update to apply */ - if (skip_immediate_retrain == false) - dc_link_set_preferred_link_settings(dc, &link->preferred_link_setting, link); -} - -void dc_link_set_test_pattern(struct dc_link *link, - enum dp_test_pattern test_pattern, - enum dp_test_pattern_color_space test_pattern_color_space, - const struct link_training_settings *p_link_settings, - const unsigned char *p_custom_pattern, - unsigned int cust_pattern_size) -{ - if (link != NULL) - dc_link_dp_set_test_pattern( - link, - test_pattern, - test_pattern_color_space, - p_link_settings, - p_custom_pattern, - cust_pattern_size); -} - uint32_t dc_link_bandwidth_kbps( const struct dc_link *link, const struct dc_link_settings *link_setting) @@ -4854,3 +4305,591 @@ void dc_restore_link_res_map(const struct dc *dc, uint32_t *map) } } } + +bool dp_validate_mode_timing( + struct dc_link *link, + const struct dc_crtc_timing *timing) +{ + uint32_t req_bw; + uint32_t max_bw; + + const struct dc_link_settings *link_setting; + + /* According to spec, VSC SDP should be used if pixel format is YCbCr420 */ + if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420 && + !link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED && + dal_graphics_object_id_get_connector_id(link->link_id) != CONNECTOR_ID_VIRTUAL) + return false; + + /*always DP fail safe mode*/ + if ((timing->pix_clk_100hz / 10) == (uint32_t) 25175 && + timing->h_addressable == (uint32_t) 640 && + timing->v_addressable == (uint32_t) 480) + return true; + + link_setting = dc_link_get_link_cap(link); + + /* TODO: DYNAMIC_VALIDATION needs to be implemented */ + /*if (flags.DYNAMIC_VALIDATION == 1 && + link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN) + link_setting = &link->verified_link_cap; + */ + + req_bw = dc_bandwidth_in_kbps_from_timing(timing); + max_bw = dc_link_bandwidth_kbps(link, link_setting); + + if (req_bw <= max_bw) { + /* remember the biggest mode here, during + * initial link training (to get + * verified_link_cap), LS sends event about + * cannot train at reported cap to upper + * layer and upper layer will re-enumerate modes. + * this is not necessary if the lower + * verified_link_cap is enough to drive + * all the modes */ + + /* TODO: DYNAMIC_VALIDATION needs to be implemented */ + /* if (flags.DYNAMIC_VALIDATION == 1) + dpsst->max_req_bw_for_verified_linkcap = dal_max( + dpsst->max_req_bw_for_verified_linkcap, req_bw); */ + return true; + } else + return false; +} + +void dp_enable_mst_on_sink(struct dc_link *link, bool enable) +{ + unsigned char mstmCntl; + + core_link_read_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1); + if (enable) + mstmCntl |= DP_MST_EN; + else + mstmCntl &= (~DP_MST_EN); + + core_link_write_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1); +} + +enum dc_status dp_set_fec_ready(struct dc_link *link, const struct link_resource *link_res, bool ready) +{ + /* FEC has to be "set ready" before the link training. + * The policy is to always train with FEC + * if the sink supports it and leave it enabled on link. + * If FEC is not supported, disable it. + */ + struct link_encoder *link_enc = NULL; + enum dc_status status = DC_OK; + uint8_t fec_config = 0; + + link_enc = link_enc_cfg_get_link_enc(link); + ASSERT(link_enc); + + if (!dc_link_should_enable_fec(link)) + return status; + + if (link_enc->funcs->fec_set_ready && + link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) { + if (ready) { + fec_config = 1; + status = core_link_write_dpcd(link, + DP_FEC_CONFIGURATION, + &fec_config, + sizeof(fec_config)); + if (status == DC_OK) { + link_enc->funcs->fec_set_ready(link_enc, true); + link->fec_state = dc_link_fec_ready; + } else { + link_enc->funcs->fec_set_ready(link_enc, false); + link->fec_state = dc_link_fec_not_ready; + dm_error("dpcd write failed to set fec_ready"); + } + } else if (link->fec_state == dc_link_fec_ready) { + fec_config = 0; + status = core_link_write_dpcd(link, + DP_FEC_CONFIGURATION, + &fec_config, + sizeof(fec_config)); + link_enc->funcs->fec_set_ready(link_enc, false); + link->fec_state = dc_link_fec_not_ready; + } + } + + return status; +} + +void dp_set_fec_enable(struct dc_link *link, bool enable) +{ + struct link_encoder *link_enc = NULL; + + link_enc = link_enc_cfg_get_link_enc(link); + ASSERT(link_enc); + + if (!dc_link_should_enable_fec(link)) + return; + + if (link_enc->funcs->fec_set_enable && + link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) { + if (link->fec_state == dc_link_fec_ready && enable) { + /* Accord to DP spec, FEC enable sequence can first + * be transmitted anytime after 1000 LL codes have + * been transmitted on the link after link training + * completion. Using 1 lane RBR should have the maximum + * time for transmitting 1000 LL codes which is 6.173 us. + * So use 7 microseconds delay instead. + */ + udelay(7); + link_enc->funcs->fec_set_enable(link_enc, true); + link->fec_state = dc_link_fec_enabled; + } else if (link->fec_state == dc_link_fec_enabled && !enable) { + link_enc->funcs->fec_set_enable(link_enc, false); + link->fec_state = dc_link_fec_ready; + } + } +} + +// TODO - DP2.0 Link: Fix get_lane_status to handle LTTPR offset (SST and MST) +static void get_lane_status( + struct dc_link *link, + uint32_t lane_count, + union lane_status *status, + union lane_align_status_updated *status_updated) +{ + unsigned int lane; + uint8_t dpcd_buf[3] = {0}; + + if (status == NULL || status_updated == NULL) { + return; + } + + core_link_read_dpcd( + link, + DP_LANE0_1_STATUS, + dpcd_buf, + sizeof(dpcd_buf)); + + for (lane = 0; lane < lane_count; lane++) { + status[lane].raw = dp_get_nibble_at_index(&dpcd_buf[0], lane); + } + + status_updated->raw = dpcd_buf[2]; +} + +bool dpcd_write_128b_132b_sst_payload_allocation_table( + const struct dc_stream_state *stream, + struct dc_link *link, + struct link_mst_stream_allocation_table *proposed_table, + bool allocate) +{ + const uint8_t vc_id = 1; /// VC ID always 1 for SST + const uint8_t start_time_slot = 0; /// Always start at time slot 0 for SST + bool result = false; + uint8_t req_slot_count = 0; + struct fixed31_32 avg_time_slots_per_mtp = { 0 }; + union payload_table_update_status update_status = { 0 }; + const uint32_t max_retries = 30; + uint32_t retries = 0; + DC_LOGGER_INIT(link->ctx->logger); + + if (allocate) { + avg_time_slots_per_mtp = calculate_sst_avg_time_slots_per_mtp(stream, link); + req_slot_count = dc_fixpt_ceil(avg_time_slots_per_mtp); + /// Validation should filter out modes that exceed link BW + ASSERT(req_slot_count <= MAX_MTP_SLOT_COUNT); + if (req_slot_count > MAX_MTP_SLOT_COUNT) + return false; + } else { + /// Leave req_slot_count = 0 if allocate is false. + } + + proposed_table->stream_count = 1; /// Always 1 stream for SST + proposed_table->stream_allocations[0].slot_count = req_slot_count; + proposed_table->stream_allocations[0].vcp_id = vc_id; + + if (link->aux_access_disabled) + return true; + + /// Write DPCD 2C0 = 1 to start updating + update_status.bits.VC_PAYLOAD_TABLE_UPDATED = 1; + core_link_write_dpcd( + link, + DP_PAYLOAD_TABLE_UPDATE_STATUS, + &update_status.raw, + 1); + + /// Program the changes in DPCD 1C0 - 1C2 + ASSERT(vc_id == 1); + core_link_write_dpcd( + link, + DP_PAYLOAD_ALLOCATE_SET, + &vc_id, + 1); + + ASSERT(start_time_slot == 0); + core_link_write_dpcd( + link, + DP_PAYLOAD_ALLOCATE_START_TIME_SLOT, + &start_time_slot, + 1); + + core_link_write_dpcd( + link, + DP_PAYLOAD_ALLOCATE_TIME_SLOT_COUNT, + &req_slot_count, + 1); + + /// Poll till DPCD 2C0 read 1 + /// Try for at least 150ms (30 retries, with 5ms delay after each attempt) + + while (retries < max_retries) { + if (core_link_read_dpcd( + link, + DP_PAYLOAD_TABLE_UPDATE_STATUS, + &update_status.raw, + 1) == DC_OK) { + if (update_status.bits.VC_PAYLOAD_TABLE_UPDATED == 1) { + DC_LOG_DP2("SST Update Payload: downstream payload table updated."); + result = true; + break; + } + } else { + union dpcd_rev dpcdRev; + + if (core_link_read_dpcd( + link, + DP_DPCD_REV, + &dpcdRev.raw, + 1) != DC_OK) { + DC_LOG_ERROR("SST Update Payload: Unable to read DPCD revision " + "of sink while polling payload table " + "updated status bit."); + break; + } + } + retries++; + msleep(5); + } + + if (!result && retries == max_retries) { + DC_LOG_ERROR("SST Update Payload: Payload table not updated after retries, " + "continue on. Something is wrong with the branch."); + // TODO - DP2.0 Payload: Read and log the payload table from downstream branch + } + + return result; +} + +bool dpcd_poll_for_allocation_change_trigger(struct dc_link *link) +{ + /* + * wait for ACT handled + */ + int i; + const int act_retries = 30; + enum act_return_status result = ACT_FAILED; + union payload_table_update_status update_status = {0}; + union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX]; + union lane_align_status_updated lane_status_updated; + DC_LOGGER_INIT(link->ctx->logger); + + if (link->aux_access_disabled) + return true; + for (i = 0; i < act_retries; i++) { + get_lane_status(link, link->cur_link_settings.lane_count, dpcd_lane_status, &lane_status_updated); + + if (!dp_is_cr_done(link->cur_link_settings.lane_count, dpcd_lane_status) || + !dp_is_ch_eq_done(link->cur_link_settings.lane_count, dpcd_lane_status) || + !dp_is_symbol_locked(link->cur_link_settings.lane_count, dpcd_lane_status) || + !dp_is_interlane_aligned(lane_status_updated)) { + DC_LOG_ERROR("SST Update Payload: Link loss occurred while " + "polling for ACT handled."); + result = ACT_LINK_LOST; + break; + } + core_link_read_dpcd( + link, + DP_PAYLOAD_TABLE_UPDATE_STATUS, + &update_status.raw, + 1); + + if (update_status.bits.ACT_HANDLED == 1) { + DC_LOG_DP2("SST Update Payload: ACT handled by downstream."); + result = ACT_SUCCESS; + break; + } + + msleep(5); + } + + if (result == ACT_FAILED) { + DC_LOG_ERROR("SST Update Payload: ACT still not handled after retries, " + "continue on. Something is wrong with the branch."); + } + + return (result == ACT_SUCCESS); +} + +struct fixed31_32 calculate_sst_avg_time_slots_per_mtp( + const struct dc_stream_state *stream, + const struct dc_link *link) +{ + struct fixed31_32 link_bw_effective = + dc_fixpt_from_int( + dc_link_bandwidth_kbps(link, &link->cur_link_settings)); + struct fixed31_32 timeslot_bw_effective = + dc_fixpt_div_int(link_bw_effective, MAX_MTP_SLOT_COUNT); + struct fixed31_32 timing_bw = + dc_fixpt_from_int( + dc_bandwidth_in_kbps_from_timing(&stream->timing)); + struct fixed31_32 avg_time_slots_per_mtp = + dc_fixpt_div(timing_bw, timeslot_bw_effective); + + return avg_time_slots_per_mtp; +} + +void dc_link_clear_dprx_states(struct dc_link *link) +{ + memset(&link->dprx_states, 0, sizeof(link->dprx_states)); +} + +void dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode) +{ + if (link != NULL && link->dc->debug.enable_driver_sequence_debug) + core_link_write_dpcd(link, DP_SOURCE_SEQUENCE, + &dp_test_mode, sizeof(dp_test_mode)); +} + +static void dsc_optc_config_log(struct display_stream_compressor *dsc, + struct dsc_optc_config *config) +{ + uint32_t precision = 1 << 28; + uint32_t bytes_per_pixel_int = config->bytes_per_pixel / precision; + uint32_t bytes_per_pixel_mod = config->bytes_per_pixel % precision; + uint64_t ll_bytes_per_pix_fraq = bytes_per_pixel_mod; + DC_LOGGER_INIT(dsc->ctx->logger); + + /* 7 fractional digits decimal precision for bytes per pixel is enough because DSC + * bits per pixel precision is 1/16th of a pixel, which means bytes per pixel precision is + * 1/16/8 = 1/128 of a byte, or 0.0078125 decimal + */ + ll_bytes_per_pix_fraq *= 10000000; + ll_bytes_per_pix_fraq /= precision; + + DC_LOG_DSC("\tbytes_per_pixel 0x%08x (%d.%07d)", + config->bytes_per_pixel, bytes_per_pixel_int, (uint32_t)ll_bytes_per_pix_fraq); + DC_LOG_DSC("\tis_pixel_format_444 %d", config->is_pixel_format_444); + DC_LOG_DSC("\tslice_width %d", config->slice_width); +} + +bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable) +{ + struct dc *dc = pipe_ctx->stream->ctx->dc; + struct dc_stream_state *stream = pipe_ctx->stream; + bool result = false; + + if (dc_is_virtual_signal(stream->signal) || IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) + result = true; + else + result = dm_helpers_dp_write_dsc_enable(dc->ctx, stream, enable); + return result; +} + +/* The stream with these settings can be sent (unblanked) only after DSC was enabled on RX first, + * i.e. after dp_enable_dsc_on_rx() had been called + */ +void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) +{ + struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; + struct dc *dc = pipe_ctx->stream->ctx->dc; + struct dc_stream_state *stream = pipe_ctx->stream; + struct pipe_ctx *odm_pipe; + int opp_cnt = 1; + DC_LOGGER_INIT(dsc->ctx->logger); + + for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) + opp_cnt++; + + if (enable) { + struct dsc_config dsc_cfg; + struct dsc_optc_config dsc_optc_cfg; + enum optc_dsc_mode optc_dsc_mode; + + /* Enable DSC hw block */ + dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt; + dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom; + dsc_cfg.pixel_encoding = stream->timing.pixel_encoding; + dsc_cfg.color_depth = stream->timing.display_color_depth; + dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false; + dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg; + ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0); + dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt; + + dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg); + dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst); + for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) { + struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc; + + odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg); + odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst); + } + dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt; + dsc_cfg.pic_width *= opp_cnt; + + optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED; + + /* Enable DSC in encoder */ + if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) + && !link_is_dp_128b_132b_signal(pipe_ctx)) { + DC_LOG_DSC("Setting stream encoder DSC config for engine %d:", (int)pipe_ctx->stream_res.stream_enc->id); + dsc_optc_config_log(dsc, &dsc_optc_cfg); + pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc, + optc_dsc_mode, + dsc_optc_cfg.bytes_per_pixel, + dsc_optc_cfg.slice_width); + + /* PPS SDP is set elsewhere because it has to be done after DIG FE is connected to DIG BE */ + } + + /* Enable DSC in OPTC */ + DC_LOG_DSC("Setting optc DSC config for tg instance %d:", pipe_ctx->stream_res.tg->inst); + dsc_optc_config_log(dsc, &dsc_optc_cfg); + pipe_ctx->stream_res.tg->funcs->set_dsc_config(pipe_ctx->stream_res.tg, + optc_dsc_mode, + dsc_optc_cfg.bytes_per_pixel, + dsc_optc_cfg.slice_width); + } else { + /* disable DSC in OPTC */ + pipe_ctx->stream_res.tg->funcs->set_dsc_config( + pipe_ctx->stream_res.tg, + OPTC_DSC_DISABLED, 0, 0); + + /* disable DSC in stream encoder */ + if (dc_is_dp_signal(stream->signal)) { + if (link_is_dp_128b_132b_signal(pipe_ctx)) + pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet( + pipe_ctx->stream_res.hpo_dp_stream_enc, + false, + NULL, + true); + else if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config( + pipe_ctx->stream_res.stream_enc, + OPTC_DSC_DISABLED, 0, 0); + pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( + pipe_ctx->stream_res.stream_enc, false, NULL, true); + } + } + + /* disable DSC block */ + pipe_ctx->stream_res.dsc->funcs->dsc_disable(pipe_ctx->stream_res.dsc); + for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) + odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc); + } +} + +bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable) +{ + struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; + bool result = false; + + if (!pipe_ctx->stream->timing.flags.DSC) + goto out; + if (!dsc) + goto out; + + if (enable) { + { + dp_set_dsc_on_stream(pipe_ctx, true); + result = true; + } + } else { + dp_set_dsc_on_rx(pipe_ctx, false); + dp_set_dsc_on_stream(pipe_ctx, false); + result = true; + } +out: + return result; +} + +/* + * For dynamic bpp change case, dsc is programmed with MASTER_UPDATE_LOCK enabled; + * hence PPS info packet update need to use frame update instead of immediate update. + * Added parameter immediate_update for this purpose. + * The decision to use frame update is hard-coded in function dp_update_dsc_config(), + * which is the only place where a "false" would be passed in for param immediate_update. + * + * immediate_update is only applicable when DSC is enabled. + */ +bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable, bool immediate_update) +{ + struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; + struct dc_stream_state *stream = pipe_ctx->stream; + DC_LOGGER_INIT(dsc->ctx->logger); + + if (!pipe_ctx->stream->timing.flags.DSC || !dsc) + return false; + + if (enable) { + struct dsc_config dsc_cfg; + uint8_t dsc_packed_pps[128]; + + memset(&dsc_cfg, 0, sizeof(dsc_cfg)); + memset(dsc_packed_pps, 0, 128); + + /* Enable DSC hw block */ + dsc_cfg.pic_width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right; + dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom; + dsc_cfg.pixel_encoding = stream->timing.pixel_encoding; + dsc_cfg.color_depth = stream->timing.display_color_depth; + dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false; + dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg; + + dsc->funcs->dsc_get_packed_pps(dsc, &dsc_cfg, &dsc_packed_pps[0]); + memcpy(&stream->dsc_packed_pps[0], &dsc_packed_pps[0], sizeof(stream->dsc_packed_pps)); + if (dc_is_dp_signal(stream->signal)) { + DC_LOG_DSC("Setting stream encoder DSC PPS SDP for engine %d\n", (int)pipe_ctx->stream_res.stream_enc->id); + if (link_is_dp_128b_132b_signal(pipe_ctx)) + pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet( + pipe_ctx->stream_res.hpo_dp_stream_enc, + true, + &dsc_packed_pps[0], + immediate_update); + else + pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( + pipe_ctx->stream_res.stream_enc, + true, + &dsc_packed_pps[0], + immediate_update); + } + } else { + /* disable DSC PPS in stream encoder */ + memset(&stream->dsc_packed_pps[0], 0, sizeof(stream->dsc_packed_pps)); + if (dc_is_dp_signal(stream->signal)) { + if (link_is_dp_128b_132b_signal(pipe_ctx)) + pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet( + pipe_ctx->stream_res.hpo_dp_stream_enc, + false, + NULL, + true); + else + pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( + pipe_ctx->stream_res.stream_enc, false, NULL, true); + } + } + + return true; +} + + +bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx) +{ + struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; + + if (!pipe_ctx->stream->timing.flags.DSC) + return false; + if (!dsc) + return false; + + dp_set_dsc_on_stream(pipe_ctx, true); + dp_set_dsc_pps_sdp(pipe_ctx, true, false); + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c deleted file mode 100644 index 6747e4b199de..000000000000 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ /dev/null @@ -1,2375 +0,0 @@ -/* - * Copyright 2015 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - */ -#include "dm_services.h" -#include "dc.h" -#include "dc_link_dp.h" -#include "dm_helpers.h" -#include "opp.h" -#include "dsc.h" -#include "resource.h" - -#include "inc/core_types.h" -#include "link_hwss.h" -#include "link/link_ddc.h" -#include "core_status.h" -#include "dpcd_defs.h" - -#include "dc_dmub_srv.h" -#include "dce/dmub_hw_lock_mgr.h" -#include "link/link_dp_dpia.h" -#include "inc/link_enc_cfg.h" -#include "clk_mgr.h" -#include "link/link_dp_trace.h" -#include "link/link_dp_training.h" -#include "link/link_dp_training_fixed_vs_pe_retimer.h" -#include "link/link_dp_training_dpia.h" -#include "link/link_dp_training_auxless.h" -#include "link/link_dp_phy.h" -#include "link/link_dp_capability.h" -#define DC_LOGGER \ - link->ctx->logger - -#define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */ -#include "link/link_dpcd.h" - -static uint8_t get_nibble_at_index(const uint8_t *buf, - uint32_t index) -{ - uint8_t nibble; - nibble = buf[index / 2]; - - if (index % 2) - nibble >>= 4; - else - nibble &= 0x0F; - - return nibble; -} - -enum dc_status read_hpd_rx_irq_data( - struct dc_link *link, - union hpd_irq_data *irq_data) -{ - static enum dc_status retval; - - /* The HW reads 16 bytes from 200h on HPD, - * but if we get an AUX_DEFER, the HW cannot retry - * and this causes the CTS tests 4.3.2.1 - 3.2.4 to - * fail, so we now explicitly read 6 bytes which is - * the req from the above mentioned test cases. - * - * For DP 1.4 we need to read those from 2002h range. - */ - if (link->dpcd_caps.dpcd_rev.raw < DPCD_REV_14) - retval = core_link_read_dpcd( - link, - DP_SINK_COUNT, - irq_data->raw, - sizeof(union hpd_irq_data)); - else { - /* Read 14 bytes in a single read and then copy only the required fields. - * This is more efficient than doing it in two separate AUX reads. */ - - uint8_t tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI + 1]; - - retval = core_link_read_dpcd( - link, - DP_SINK_COUNT_ESI, - tmp, - sizeof(tmp)); - - if (retval != DC_OK) - return retval; - - irq_data->bytes.sink_cnt.raw = tmp[DP_SINK_COUNT_ESI - DP_SINK_COUNT_ESI]; - irq_data->bytes.device_service_irq.raw = tmp[DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0 - DP_SINK_COUNT_ESI]; - irq_data->bytes.lane01_status.raw = tmp[DP_LANE0_1_STATUS_ESI - DP_SINK_COUNT_ESI]; - irq_data->bytes.lane23_status.raw = tmp[DP_LANE2_3_STATUS_ESI - DP_SINK_COUNT_ESI]; - irq_data->bytes.lane_status_updated.raw = tmp[DP_LANE_ALIGN_STATUS_UPDATED_ESI - DP_SINK_COUNT_ESI]; - irq_data->bytes.sink_status.raw = tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI]; - } - - return retval; -} - -bool hpd_rx_irq_check_link_loss_status( - struct dc_link *link, - union hpd_irq_data *hpd_irq_dpcd_data) -{ - uint8_t irq_reg_rx_power_state = 0; - enum dc_status dpcd_result = DC_ERROR_UNEXPECTED; - union lane_status lane_status; - uint32_t lane; - bool sink_status_changed; - bool return_code; - - sink_status_changed = false; - return_code = false; - - if (link->cur_link_settings.lane_count == 0) - return return_code; - - /*1. Check that Link Status changed, before re-training.*/ - - /*parse lane status*/ - for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) { - /* check status of lanes 0,1 - * changed DpcdAddress_Lane01Status (0x202) - */ - lane_status.raw = get_nibble_at_index( - &hpd_irq_dpcd_data->bytes.lane01_status.raw, - lane); - - if (!lane_status.bits.CHANNEL_EQ_DONE_0 || - !lane_status.bits.CR_DONE_0 || - !lane_status.bits.SYMBOL_LOCKED_0) { - /* if one of the channel equalization, clock - * recovery or symbol lock is dropped - * consider it as (link has been - * dropped) dp sink status has changed - */ - sink_status_changed = true; - break; - } - } - - /* Check interlane align.*/ - if (sink_status_changed || - !hpd_irq_dpcd_data->bytes.lane_status_updated.bits.INTERLANE_ALIGN_DONE) { - - DC_LOG_HW_HPD_IRQ("%s: Link Status changed.\n", __func__); - - return_code = true; - - /*2. Check that we can handle interrupt: Not in FS DOS, - * Not in "Display Timeout" state, Link is trained. - */ - dpcd_result = core_link_read_dpcd(link, - DP_SET_POWER, - &irq_reg_rx_power_state, - sizeof(irq_reg_rx_power_state)); - - if (dpcd_result != DC_OK) { - DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain power state.\n", - __func__); - } else { - if (irq_reg_rx_power_state != DP_SET_POWER_D0) - return_code = false; - } - } - - return return_code; -} - -bool dp_validate_mode_timing( - struct dc_link *link, - const struct dc_crtc_timing *timing) -{ - uint32_t req_bw; - uint32_t max_bw; - - const struct dc_link_settings *link_setting; - - /* According to spec, VSC SDP should be used if pixel format is YCbCr420 */ - if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420 && - !link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED && - dal_graphics_object_id_get_connector_id(link->link_id) != CONNECTOR_ID_VIRTUAL) - return false; - - /*always DP fail safe mode*/ - if ((timing->pix_clk_100hz / 10) == (uint32_t) 25175 && - timing->h_addressable == (uint32_t) 640 && - timing->v_addressable == (uint32_t) 480) - return true; - - link_setting = dc_link_get_link_cap(link); - - /* TODO: DYNAMIC_VALIDATION needs to be implemented */ - /*if (flags.DYNAMIC_VALIDATION == 1 && - link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN) - link_setting = &link->verified_link_cap; - */ - - req_bw = dc_bandwidth_in_kbps_from_timing(timing); - max_bw = dc_link_bandwidth_kbps(link, link_setting); - - if (req_bw <= max_bw) { - /* remember the biggest mode here, during - * initial link training (to get - * verified_link_cap), LS sends event about - * cannot train at reported cap to upper - * layer and upper layer will re-enumerate modes. - * this is not necessary if the lower - * verified_link_cap is enough to drive - * all the modes */ - - /* TODO: DYNAMIC_VALIDATION needs to be implemented */ - /* if (flags.DYNAMIC_VALIDATION == 1) - dpsst->max_req_bw_for_verified_linkcap = dal_max( - dpsst->max_req_bw_for_verified_linkcap, req_bw); */ - return true; - } else - return false; -} - -/*************************Short Pulse IRQ***************************/ -bool dc_link_dp_allow_hpd_rx_irq(const struct dc_link *link) -{ - /* - * Don't handle RX IRQ unless one of following is met: - * 1) The link is established (cur_link_settings != unknown) - * 2) We know we're dealing with a branch device, SST or MST - */ - - if ((link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) || - is_dp_branch_device(link)) - return true; - - return false; -} - -static bool handle_hpd_irq_psr_sink(struct dc_link *link) -{ - union dpcd_psr_configuration psr_configuration; - - if (!link->psr_settings.psr_feature_enabled) - return false; - - dm_helpers_dp_read_dpcd( - link->ctx, - link, - 368,/*DpcdAddress_PSR_Enable_Cfg*/ - &psr_configuration.raw, - sizeof(psr_configuration.raw)); - - if (psr_configuration.bits.ENABLE) { - unsigned char dpcdbuf[3] = {0}; - union psr_error_status psr_error_status; - union psr_sink_psr_status psr_sink_psr_status; - - dm_helpers_dp_read_dpcd( - link->ctx, - link, - 0x2006, /*DpcdAddress_PSR_Error_Status*/ - (unsigned char *) dpcdbuf, - sizeof(dpcdbuf)); - - /*DPCD 2006h ERROR STATUS*/ - psr_error_status.raw = dpcdbuf[0]; - /*DPCD 2008h SINK PANEL SELF REFRESH STATUS*/ - psr_sink_psr_status.raw = dpcdbuf[2]; - - if (psr_error_status.bits.LINK_CRC_ERROR || - psr_error_status.bits.RFB_STORAGE_ERROR || - psr_error_status.bits.VSC_SDP_ERROR) { - bool allow_active; - - /* Acknowledge and clear error bits */ - dm_helpers_dp_write_dpcd( - link->ctx, - link, - 8198,/*DpcdAddress_PSR_Error_Status*/ - &psr_error_status.raw, - sizeof(psr_error_status.raw)); - - /* PSR error, disable and re-enable PSR */ - if (link->psr_settings.psr_allow_active) { - allow_active = false; - dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL); - allow_active = true; - dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL); - } - - return true; - } else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS == - PSR_SINK_STATE_ACTIVE_DISPLAY_FROM_SINK_RFB){ - /* No error is detect, PSR is active. - * We should return with IRQ_HPD handled without - * checking for loss of sync since PSR would have - * powered down main link. - */ - return true; - } - } - return false; -} - -static enum dc_link_rate get_link_rate_from_test_link_rate(uint8_t test_rate) -{ - switch (test_rate) { - case DP_TEST_LINK_RATE_RBR: - return LINK_RATE_LOW; - case DP_TEST_LINK_RATE_HBR: - return LINK_RATE_HIGH; - case DP_TEST_LINK_RATE_HBR2: - return LINK_RATE_HIGH2; - case DP_TEST_LINK_RATE_HBR3: - return LINK_RATE_HIGH3; - case DP_TEST_LINK_RATE_UHBR10: - return LINK_RATE_UHBR10; - case DP_TEST_LINK_RATE_UHBR20: - return LINK_RATE_UHBR20; - case DP_TEST_LINK_RATE_UHBR13_5: - return LINK_RATE_UHBR13_5; - default: - return LINK_RATE_UNKNOWN; - } -} - -static void dp_test_send_link_training(struct dc_link *link) -{ - struct dc_link_settings link_settings = {0}; - uint8_t test_rate = 0; - - core_link_read_dpcd( - link, - DP_TEST_LANE_COUNT, - (unsigned char *)(&link_settings.lane_count), - 1); - core_link_read_dpcd( - link, - DP_TEST_LINK_RATE, - &test_rate, - 1); - link_settings.link_rate = get_link_rate_from_test_link_rate(test_rate); - - /* Set preferred link settings */ - link->verified_link_cap.lane_count = link_settings.lane_count; - link->verified_link_cap.link_rate = link_settings.link_rate; - - dp_retrain_link_dp_test(link, &link_settings, false); -} - -static bool is_dp_phy_sqaure_pattern(enum dp_test_pattern test_pattern) -{ - return (DP_TEST_PATTERN_SQUARE_BEGIN <= test_pattern && - test_pattern <= DP_TEST_PATTERN_SQUARE_END); -} - -/* TODO Raven hbr2 compliance eye output is unstable - * (toggling on and off) with debugger break - * This caueses intermittent PHY automation failure - * Need to look into the root cause */ -static void dp_test_send_phy_test_pattern(struct dc_link *link) -{ - union phy_test_pattern dpcd_test_pattern; - union lane_adjust dpcd_lane_adjustment[2]; - unsigned char dpcd_post_cursor_2_adjustment = 0; - unsigned char test_pattern_buffer[ - (DP_TEST_264BIT_CUSTOM_PATTERN_263_256 - - DP_TEST_264BIT_CUSTOM_PATTERN_7_0)+1] = {0}; - unsigned int test_pattern_size = 0; - enum dp_test_pattern test_pattern; - union lane_adjust dpcd_lane_adjust; - unsigned int lane; - struct link_training_settings link_training_settings; - unsigned char no_preshoot = 0; - unsigned char no_deemphasis = 0; - - dpcd_test_pattern.raw = 0; - memset(dpcd_lane_adjustment, 0, sizeof(dpcd_lane_adjustment)); - memset(&link_training_settings, 0, sizeof(link_training_settings)); - - /* get phy test pattern and pattern parameters from DP receiver */ - core_link_read_dpcd( - link, - DP_PHY_TEST_PATTERN, - &dpcd_test_pattern.raw, - sizeof(dpcd_test_pattern)); - core_link_read_dpcd( - link, - DP_ADJUST_REQUEST_LANE0_1, - &dpcd_lane_adjustment[0].raw, - sizeof(dpcd_lane_adjustment)); - - /* prepare link training settings */ - link_training_settings.link_settings = link->cur_link_settings; - - link_training_settings.lttpr_mode = dc_link_decide_lttpr_mode(link, &link->cur_link_settings); - - if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && - link_training_settings.lttpr_mode == LTTPR_MODE_TRANSPARENT) - dp_fixed_vs_pe_read_lane_adjust( - link, - link_training_settings.dpcd_lane_settings); - - /*get post cursor 2 parameters - * For DP 1.1a or eariler, this DPCD register's value is 0 - * For DP 1.2 or later: - * Bits 1:0 = POST_CURSOR2_LANE0; Bits 3:2 = POST_CURSOR2_LANE1 - * Bits 5:4 = POST_CURSOR2_LANE2; Bits 7:6 = POST_CURSOR2_LANE3 - */ - core_link_read_dpcd( - link, - DP_ADJUST_REQUEST_POST_CURSOR2, - &dpcd_post_cursor_2_adjustment, - sizeof(dpcd_post_cursor_2_adjustment)); - - /* translate request */ - switch (dpcd_test_pattern.bits.PATTERN) { - case PHY_TEST_PATTERN_D10_2: - test_pattern = DP_TEST_PATTERN_D102; - break; - case PHY_TEST_PATTERN_SYMBOL_ERROR: - test_pattern = DP_TEST_PATTERN_SYMBOL_ERROR; - break; - case PHY_TEST_PATTERN_PRBS7: - test_pattern = DP_TEST_PATTERN_PRBS7; - break; - case PHY_TEST_PATTERN_80BIT_CUSTOM: - test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM; - break; - case PHY_TEST_PATTERN_CP2520_1: - /* CP2520 pattern is unstable, temporarily use TPS4 instead */ - test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ? - DP_TEST_PATTERN_TRAINING_PATTERN4 : - DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE; - break; - case PHY_TEST_PATTERN_CP2520_2: - /* CP2520 pattern is unstable, temporarily use TPS4 instead */ - test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ? - DP_TEST_PATTERN_TRAINING_PATTERN4 : - DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE; - break; - case PHY_TEST_PATTERN_CP2520_3: - test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4; - break; - case PHY_TEST_PATTERN_128b_132b_TPS1: - test_pattern = DP_TEST_PATTERN_128b_132b_TPS1; - break; - case PHY_TEST_PATTERN_128b_132b_TPS2: - test_pattern = DP_TEST_PATTERN_128b_132b_TPS2; - break; - case PHY_TEST_PATTERN_PRBS9: - test_pattern = DP_TEST_PATTERN_PRBS9; - break; - case PHY_TEST_PATTERN_PRBS11: - test_pattern = DP_TEST_PATTERN_PRBS11; - break; - case PHY_TEST_PATTERN_PRBS15: - test_pattern = DP_TEST_PATTERN_PRBS15; - break; - case PHY_TEST_PATTERN_PRBS23: - test_pattern = DP_TEST_PATTERN_PRBS23; - break; - case PHY_TEST_PATTERN_PRBS31: - test_pattern = DP_TEST_PATTERN_PRBS31; - break; - case PHY_TEST_PATTERN_264BIT_CUSTOM: - test_pattern = DP_TEST_PATTERN_264BIT_CUSTOM; - break; - case PHY_TEST_PATTERN_SQUARE: - test_pattern = DP_TEST_PATTERN_SQUARE; - break; - case PHY_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED: - test_pattern = DP_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED; - no_preshoot = 1; - break; - case PHY_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED: - test_pattern = DP_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED; - no_deemphasis = 1; - break; - case PHY_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED: - test_pattern = DP_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED; - no_preshoot = 1; - no_deemphasis = 1; - break; - default: - test_pattern = DP_TEST_PATTERN_VIDEO_MODE; - break; - } - - if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM) { - test_pattern_size = (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 - - DP_TEST_80BIT_CUSTOM_PATTERN_7_0) + 1; - core_link_read_dpcd( - link, - DP_TEST_80BIT_CUSTOM_PATTERN_7_0, - test_pattern_buffer, - test_pattern_size); - } - - if (is_dp_phy_sqaure_pattern(test_pattern)) { - test_pattern_size = 1; // Square pattern data is 1 byte (DP spec) - core_link_read_dpcd( - link, - DP_PHY_SQUARE_PATTERN, - test_pattern_buffer, - test_pattern_size); - } - - if (test_pattern == DP_TEST_PATTERN_264BIT_CUSTOM) { - test_pattern_size = (DP_TEST_264BIT_CUSTOM_PATTERN_263_256- - DP_TEST_264BIT_CUSTOM_PATTERN_7_0) + 1; - core_link_read_dpcd( - link, - DP_TEST_264BIT_CUSTOM_PATTERN_7_0, - test_pattern_buffer, - test_pattern_size); - } - - for (lane = 0; lane < - (unsigned int)(link->cur_link_settings.lane_count); - lane++) { - dpcd_lane_adjust.raw = - get_nibble_at_index(&dpcd_lane_adjustment[0].raw, lane); - if (link_dp_get_encoding_format(&link->cur_link_settings) == - DP_8b_10b_ENCODING) { - link_training_settings.hw_lane_settings[lane].VOLTAGE_SWING = - (enum dc_voltage_swing) - (dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE); - link_training_settings.hw_lane_settings[lane].PRE_EMPHASIS = - (enum dc_pre_emphasis) - (dpcd_lane_adjust.bits.PRE_EMPHASIS_LANE); - link_training_settings.hw_lane_settings[lane].POST_CURSOR2 = - (enum dc_post_cursor2) - ((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03); - } else if (link_dp_get_encoding_format(&link->cur_link_settings) == - DP_128b_132b_ENCODING) { - link_training_settings.hw_lane_settings[lane].FFE_PRESET.settings.level = - dpcd_lane_adjust.tx_ffe.PRESET_VALUE; - link_training_settings.hw_lane_settings[lane].FFE_PRESET.settings.no_preshoot = no_preshoot; - link_training_settings.hw_lane_settings[lane].FFE_PRESET.settings.no_deemphasis = no_deemphasis; - } - } - - dp_hw_to_dpcd_lane_settings(&link_training_settings, - link_training_settings.hw_lane_settings, - link_training_settings.dpcd_lane_settings); - /*Usage: Measure DP physical lane signal - * by DP SI test equipment automatically. - * PHY test pattern request is generated by equipment via HPD interrupt. - * HPD needs to be active all the time. HPD should be active - * all the time. Do not touch it. - * forward request to DS - */ - dc_link_dp_set_test_pattern( - link, - test_pattern, - DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED, - &link_training_settings, - test_pattern_buffer, - test_pattern_size); -} - -static void dp_test_send_link_test_pattern(struct dc_link *link) -{ - union link_test_pattern dpcd_test_pattern; - union test_misc dpcd_test_params; - enum dp_test_pattern test_pattern; - enum dp_test_pattern_color_space test_pattern_color_space = - DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED; - enum dc_color_depth requestColorDepth = COLOR_DEPTH_UNDEFINED; - struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx; - struct pipe_ctx *pipe_ctx = NULL; - int i; - - memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern)); - memset(&dpcd_test_params, 0, sizeof(dpcd_test_params)); - - for (i = 0; i < MAX_PIPES; i++) { - if (pipes[i].stream == NULL) - continue; - - if (pipes[i].stream->link == link && !pipes[i].top_pipe && !pipes[i].prev_odm_pipe) { - pipe_ctx = &pipes[i]; - break; - } - } - - if (pipe_ctx == NULL) - return; - - /* get link test pattern and pattern parameters */ - core_link_read_dpcd( - link, - DP_TEST_PATTERN, - &dpcd_test_pattern.raw, - sizeof(dpcd_test_pattern)); - core_link_read_dpcd( - link, - DP_TEST_MISC0, - &dpcd_test_params.raw, - sizeof(dpcd_test_params)); - - switch (dpcd_test_pattern.bits.PATTERN) { - case LINK_TEST_PATTERN_COLOR_RAMP: - test_pattern = DP_TEST_PATTERN_COLOR_RAMP; - break; - case LINK_TEST_PATTERN_VERTICAL_BARS: - test_pattern = DP_TEST_PATTERN_VERTICAL_BARS; - break; /* black and white */ - case LINK_TEST_PATTERN_COLOR_SQUARES: - test_pattern = (dpcd_test_params.bits.DYN_RANGE == - TEST_DYN_RANGE_VESA ? - DP_TEST_PATTERN_COLOR_SQUARES : - DP_TEST_PATTERN_COLOR_SQUARES_CEA); - break; - default: - test_pattern = DP_TEST_PATTERN_VIDEO_MODE; - break; - } - - if (dpcd_test_params.bits.CLR_FORMAT == 0) - test_pattern_color_space = DP_TEST_PATTERN_COLOR_SPACE_RGB; - else - test_pattern_color_space = dpcd_test_params.bits.YCBCR_COEFS ? - DP_TEST_PATTERN_COLOR_SPACE_YCBCR709 : - DP_TEST_PATTERN_COLOR_SPACE_YCBCR601; - - switch (dpcd_test_params.bits.BPC) { - case 0: // 6 bits - requestColorDepth = COLOR_DEPTH_666; - break; - case 1: // 8 bits - requestColorDepth = COLOR_DEPTH_888; - break; - case 2: // 10 bits - requestColorDepth = COLOR_DEPTH_101010; - break; - case 3: // 12 bits - requestColorDepth = COLOR_DEPTH_121212; - break; - default: - break; - } - - switch (dpcd_test_params.bits.CLR_FORMAT) { - case 0: - pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_RGB; - break; - case 1: - pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_YCBCR422; - break; - case 2: - pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_YCBCR444; - break; - default: - pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_RGB; - break; - } - - - if (requestColorDepth != COLOR_DEPTH_UNDEFINED - && pipe_ctx->stream->timing.display_color_depth != requestColorDepth) { - DC_LOG_DEBUG("%s: original bpc %d, changing to %d\n", - __func__, - pipe_ctx->stream->timing.display_color_depth, - requestColorDepth); - pipe_ctx->stream->timing.display_color_depth = requestColorDepth; - } - - dp_update_dsc_config(pipe_ctx); - - dc_link_dp_set_test_pattern( - link, - test_pattern, - test_pattern_color_space, - NULL, - NULL, - 0); -} - -static void dp_test_get_audio_test_data(struct dc_link *link, bool disable_video) -{ - union audio_test_mode dpcd_test_mode = {0}; - struct audio_test_pattern_type dpcd_pattern_type = {0}; - union audio_test_pattern_period dpcd_pattern_period[AUDIO_CHANNELS_COUNT] = {0}; - enum dp_test_pattern test_pattern = DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED; - - struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx; - struct pipe_ctx *pipe_ctx = &pipes[0]; - unsigned int channel_count; - unsigned int channel = 0; - unsigned int modes = 0; - unsigned int sampling_rate_in_hz = 0; - - // get audio test mode and test pattern parameters - core_link_read_dpcd( - link, - DP_TEST_AUDIO_MODE, - &dpcd_test_mode.raw, - sizeof(dpcd_test_mode)); - - core_link_read_dpcd( - link, - DP_TEST_AUDIO_PATTERN_TYPE, - &dpcd_pattern_type.value, - sizeof(dpcd_pattern_type)); - - channel_count = min(dpcd_test_mode.bits.channel_count + 1, AUDIO_CHANNELS_COUNT); - - // read pattern periods for requested channels when sawTooth pattern is requested - if (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH || - dpcd_pattern_type.value == AUDIO_TEST_PATTERN_OPERATOR_DEFINED) { - - test_pattern = (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH) ? - DP_TEST_PATTERN_AUDIO_SAWTOOTH : DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED; - // read period for each channel - for (channel = 0; channel < channel_count; channel++) { - core_link_read_dpcd( - link, - DP_TEST_AUDIO_PERIOD_CH1 + channel, - &dpcd_pattern_period[channel].raw, - sizeof(dpcd_pattern_period[channel])); - } - } - - // translate sampling rate - switch (dpcd_test_mode.bits.sampling_rate) { - case AUDIO_SAMPLING_RATE_32KHZ: - sampling_rate_in_hz = 32000; - break; - case AUDIO_SAMPLING_RATE_44_1KHZ: - sampling_rate_in_hz = 44100; - break; - case AUDIO_SAMPLING_RATE_48KHZ: - sampling_rate_in_hz = 48000; - break; - case AUDIO_SAMPLING_RATE_88_2KHZ: - sampling_rate_in_hz = 88200; - break; - case AUDIO_SAMPLING_RATE_96KHZ: - sampling_rate_in_hz = 96000; - break; - case AUDIO_SAMPLING_RATE_176_4KHZ: - sampling_rate_in_hz = 176400; - break; - case AUDIO_SAMPLING_RATE_192KHZ: - sampling_rate_in_hz = 192000; - break; - default: - sampling_rate_in_hz = 0; - break; - } - - link->audio_test_data.flags.test_requested = 1; - link->audio_test_data.flags.disable_video = disable_video; - link->audio_test_data.sampling_rate = sampling_rate_in_hz; - link->audio_test_data.channel_count = channel_count; - link->audio_test_data.pattern_type = test_pattern; - - if (test_pattern == DP_TEST_PATTERN_AUDIO_SAWTOOTH) { - for (modes = 0; modes < pipe_ctx->stream->audio_info.mode_count; modes++) { - link->audio_test_data.pattern_period[modes] = dpcd_pattern_period[modes].bits.pattern_period; - } - } -} - -void dc_link_dp_handle_automated_test(struct dc_link *link) -{ - union test_request test_request; - union test_response test_response; - - memset(&test_request, 0, sizeof(test_request)); - memset(&test_response, 0, sizeof(test_response)); - - core_link_read_dpcd( - link, - DP_TEST_REQUEST, - &test_request.raw, - sizeof(union test_request)); - if (test_request.bits.LINK_TRAINING) { - /* ACK first to let DP RX test box monitor LT sequence */ - test_response.bits.ACK = 1; - core_link_write_dpcd( - link, - DP_TEST_RESPONSE, - &test_response.raw, - sizeof(test_response)); - dp_test_send_link_training(link); - /* no acknowledge request is needed again */ - test_response.bits.ACK = 0; - } - if (test_request.bits.LINK_TEST_PATTRN) { - dp_test_send_link_test_pattern(link); - test_response.bits.ACK = 1; - } - - if (test_request.bits.AUDIO_TEST_PATTERN) { - dp_test_get_audio_test_data(link, test_request.bits.TEST_AUDIO_DISABLED_VIDEO); - test_response.bits.ACK = 1; - } - - if (test_request.bits.PHY_TEST_PATTERN) { - dp_test_send_phy_test_pattern(link); - test_response.bits.ACK = 1; - } - - /* send request acknowledgment */ - if (test_response.bits.ACK) - core_link_write_dpcd( - link, - DP_TEST_RESPONSE, - &test_response.raw, - sizeof(test_response)); -} - -void dc_link_dp_handle_link_loss(struct dc_link *link) -{ - int i; - struct pipe_ctx *pipe_ctx; - - for (i = 0; i < MAX_PIPES; i++) { - pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->link == link) - break; - } - - if (pipe_ctx == NULL || pipe_ctx->stream == NULL) - return; - - for (i = 0; i < MAX_PIPES; i++) { - pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off && - pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) - core_link_disable_stream(pipe_ctx); - } - - for (i = 0; i < MAX_PIPES; i++) { - pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off - && pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) { - // Always use max settings here for DP 1.4a LL Compliance CTS - if (link->is_automated) { - pipe_ctx->link_config.dp_link_settings.lane_count = - link->verified_link_cap.lane_count; - pipe_ctx->link_config.dp_link_settings.link_rate = - link->verified_link_cap.link_rate; - pipe_ctx->link_config.dp_link_settings.link_spread = - link->verified_link_cap.link_spread; - } - core_link_enable_stream(link->dc->current_state, pipe_ctx); - } - } -} - -bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd_irq_dpcd_data, bool *out_link_loss, - bool defer_handling, bool *has_left_work) -{ - union hpd_irq_data hpd_irq_dpcd_data = {0}; - union device_service_irq device_service_clear = {0}; - enum dc_status result; - bool status = false; - - if (out_link_loss) - *out_link_loss = false; - - if (has_left_work) - *has_left_work = false; - /* For use cases related to down stream connection status change, - * PSR and device auto test, refer to function handle_sst_hpd_irq - * in DAL2.1*/ - - DC_LOG_HW_HPD_IRQ("%s: Got short pulse HPD on link %d\n", - __func__, link->link_index); - - - /* All the "handle_hpd_irq_xxx()" methods - * should be called only after - * dal_dpsst_ls_read_hpd_irq_data - * Order of calls is important too - */ - result = read_hpd_rx_irq_data(link, &hpd_irq_dpcd_data); - if (out_hpd_irq_dpcd_data) - *out_hpd_irq_dpcd_data = hpd_irq_dpcd_data; - - if (result != DC_OK) { - DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain irq data\n", - __func__); - return false; - } - - if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.AUTOMATED_TEST) { - // Workaround for DP 1.4a LL Compliance CTS as USB4 has to share encoders unlike DP and USBC - link->is_automated = true; - device_service_clear.bits.AUTOMATED_TEST = 1; - core_link_write_dpcd( - link, - DP_DEVICE_SERVICE_IRQ_VECTOR, - &device_service_clear.raw, - sizeof(device_service_clear.raw)); - device_service_clear.raw = 0; - if (defer_handling && has_left_work) - *has_left_work = true; - else - dc_link_dp_handle_automated_test(link); - return false; - } - - if (!dc_link_dp_allow_hpd_rx_irq(link)) { - DC_LOG_HW_HPD_IRQ("%s: skipping HPD handling on %d\n", - __func__, link->link_index); - return false; - } - - if (handle_hpd_irq_psr_sink(link)) - /* PSR-related error was detected and handled */ - return true; - - /* If PSR-related error handled, Main link may be off, - * so do not handle as a normal sink status change interrupt. - */ - - if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY) { - if (defer_handling && has_left_work) - *has_left_work = true; - return true; - } - - /* check if we have MST msg and return since we poll for it */ - if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) { - if (defer_handling && has_left_work) - *has_left_work = true; - return false; - } - - /* For now we only handle 'Downstream port status' case. - * If we got sink count changed it means - * Downstream port status changed, - * then DM should call DC to do the detection. - * NOTE: Do not handle link loss on eDP since it is internal link*/ - if ((link->connector_signal != SIGNAL_TYPE_EDP) && - hpd_rx_irq_check_link_loss_status( - link, - &hpd_irq_dpcd_data)) { - /* Connectivity log: link loss */ - CONN_DATA_LINK_LOSS(link, - hpd_irq_dpcd_data.raw, - sizeof(hpd_irq_dpcd_data), - "Status: "); - - if (defer_handling && has_left_work) - *has_left_work = true; - else - dc_link_dp_handle_link_loss(link); - - status = false; - if (out_link_loss) - *out_link_loss = true; - - dp_trace_link_loss_increment(link); - } - - if (link->type == dc_connection_sst_branch && - hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT - != link->dpcd_sink_count) - status = true; - - /* reasons for HPD RX: - * 1. Link Loss - ie Re-train the Link - * 2. MST sideband message - * 3. Automated Test - ie. Internal Commit - * 4. CP (copy protection) - (not interesting for DM???) - * 5. DRR - * 6. Downstream Port status changed - * -ie. Detect - this the only one - * which is interesting for DM because - * it must call dc_link_detect. - */ - return status; -} - -static bool is_dp_phy_pattern(enum dp_test_pattern test_pattern) -{ - if ((DP_TEST_PATTERN_PHY_PATTERN_BEGIN <= test_pattern && - test_pattern <= DP_TEST_PATTERN_PHY_PATTERN_END) || - test_pattern == DP_TEST_PATTERN_VIDEO_MODE) - return true; - else - return false; -} - -static void set_crtc_test_pattern(struct dc_link *link, - struct pipe_ctx *pipe_ctx, - enum dp_test_pattern test_pattern, - enum dp_test_pattern_color_space test_pattern_color_space) -{ - enum controller_dp_test_pattern controller_test_pattern; - enum dc_color_depth color_depth = pipe_ctx-> - stream->timing.display_color_depth; - struct bit_depth_reduction_params params; - struct output_pixel_processor *opp = pipe_ctx->stream_res.opp; - int width = pipe_ctx->stream->timing.h_addressable + - pipe_ctx->stream->timing.h_border_left + - pipe_ctx->stream->timing.h_border_right; - int height = pipe_ctx->stream->timing.v_addressable + - pipe_ctx->stream->timing.v_border_bottom + - pipe_ctx->stream->timing.v_border_top; - - memset(¶ms, 0, sizeof(params)); - - switch (test_pattern) { - case DP_TEST_PATTERN_COLOR_SQUARES: - controller_test_pattern = - CONTROLLER_DP_TEST_PATTERN_COLORSQUARES; - break; - case DP_TEST_PATTERN_COLOR_SQUARES_CEA: - controller_test_pattern = - CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA; - break; - case DP_TEST_PATTERN_VERTICAL_BARS: - controller_test_pattern = - CONTROLLER_DP_TEST_PATTERN_VERTICALBARS; - break; - case DP_TEST_PATTERN_HORIZONTAL_BARS: - controller_test_pattern = - CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS; - break; - case DP_TEST_PATTERN_COLOR_RAMP: - controller_test_pattern = - CONTROLLER_DP_TEST_PATTERN_COLORRAMP; - break; - default: - controller_test_pattern = - CONTROLLER_DP_TEST_PATTERN_VIDEOMODE; - break; - } - - switch (test_pattern) { - case DP_TEST_PATTERN_COLOR_SQUARES: - case DP_TEST_PATTERN_COLOR_SQUARES_CEA: - case DP_TEST_PATTERN_VERTICAL_BARS: - case DP_TEST_PATTERN_HORIZONTAL_BARS: - case DP_TEST_PATTERN_COLOR_RAMP: - { - /* disable bit depth reduction */ - pipe_ctx->stream->bit_depth_params = params; - opp->funcs->opp_program_bit_depth_reduction(opp, ¶ms); - if (pipe_ctx->stream_res.tg->funcs->set_test_pattern) - pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg, - controller_test_pattern, color_depth); - else if (link->dc->hwss.set_disp_pattern_generator) { - struct pipe_ctx *odm_pipe; - enum controller_dp_color_space controller_color_space; - int opp_cnt = 1; - int offset = 0; - int dpg_width = width; - - switch (test_pattern_color_space) { - case DP_TEST_PATTERN_COLOR_SPACE_RGB: - controller_color_space = CONTROLLER_DP_COLOR_SPACE_RGB; - break; - case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601: - controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR601; - break; - case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709: - controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR709; - break; - case DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED: - default: - controller_color_space = CONTROLLER_DP_COLOR_SPACE_UDEFINED; - DC_LOG_ERROR("%s: Color space must be defined for test pattern", __func__); - ASSERT(0); - break; - } - - for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) - opp_cnt++; - dpg_width = width / opp_cnt; - offset = dpg_width; - - link->dc->hwss.set_disp_pattern_generator(link->dc, - pipe_ctx, - controller_test_pattern, - controller_color_space, - color_depth, - NULL, - dpg_width, - height, - 0); - - for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) { - struct output_pixel_processor *odm_opp = odm_pipe->stream_res.opp; - - odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, ¶ms); - link->dc->hwss.set_disp_pattern_generator(link->dc, - odm_pipe, - controller_test_pattern, - controller_color_space, - color_depth, - NULL, - dpg_width, - height, - offset); - offset += offset; - } - } - } - break; - case DP_TEST_PATTERN_VIDEO_MODE: - { - /* restore bitdepth reduction */ - resource_build_bit_depth_reduction_params(pipe_ctx->stream, ¶ms); - pipe_ctx->stream->bit_depth_params = params; - opp->funcs->opp_program_bit_depth_reduction(opp, ¶ms); - if (pipe_ctx->stream_res.tg->funcs->set_test_pattern) - pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg, - CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, - color_depth); - else if (link->dc->hwss.set_disp_pattern_generator) { - struct pipe_ctx *odm_pipe; - int opp_cnt = 1; - int dpg_width; - - for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) - opp_cnt++; - - dpg_width = width / opp_cnt; - for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) { - struct output_pixel_processor *odm_opp = odm_pipe->stream_res.opp; - - odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, ¶ms); - link->dc->hwss.set_disp_pattern_generator(link->dc, - odm_pipe, - CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, - CONTROLLER_DP_COLOR_SPACE_UDEFINED, - color_depth, - NULL, - dpg_width, - height, - 0); - } - link->dc->hwss.set_disp_pattern_generator(link->dc, - pipe_ctx, - CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, - CONTROLLER_DP_COLOR_SPACE_UDEFINED, - color_depth, - NULL, - dpg_width, - height, - 0); - } - } - break; - - default: - break; - } -} - -bool dc_link_dp_set_test_pattern( - struct dc_link *link, - enum dp_test_pattern test_pattern, - enum dp_test_pattern_color_space test_pattern_color_space, - const struct link_training_settings *p_link_settings, - const unsigned char *p_custom_pattern, - unsigned int cust_pattern_size) -{ - struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx; - struct pipe_ctx *pipe_ctx = NULL; - unsigned int lane; - unsigned int i; - unsigned char link_qual_pattern[LANE_COUNT_DP_MAX] = {0}; - union dpcd_training_pattern training_pattern; - enum dpcd_phy_test_patterns pattern; - - memset(&training_pattern, 0, sizeof(training_pattern)); - - for (i = 0; i < MAX_PIPES; i++) { - if (pipes[i].stream == NULL) - continue; - - if (pipes[i].stream->link == link && !pipes[i].top_pipe && !pipes[i].prev_odm_pipe) { - pipe_ctx = &pipes[i]; - break; - } - } - - if (pipe_ctx == NULL) - return false; - - /* Reset CRTC Test Pattern if it is currently running and request is VideoMode */ - if (link->test_pattern_enabled && test_pattern == - DP_TEST_PATTERN_VIDEO_MODE) { - /* Set CRTC Test Pattern */ - set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space); - dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern, - (uint8_t *)p_custom_pattern, - (uint32_t)cust_pattern_size); - - /* Unblank Stream */ - link->dc->hwss.unblank_stream( - pipe_ctx, - &link->verified_link_cap); - /* TODO:m_pHwss->MuteAudioEndpoint - * (pPathMode->pDisplayPath, false); - */ - - /* Reset Test Pattern state */ - link->test_pattern_enabled = false; - - return true; - } - - /* Check for PHY Test Patterns */ - if (is_dp_phy_pattern(test_pattern)) { - /* Set DPCD Lane Settings before running test pattern */ - if (p_link_settings != NULL) { - if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && - p_link_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT) { - dp_fixed_vs_pe_set_retimer_lane_settings( - link, - p_link_settings->dpcd_lane_settings, - p_link_settings->link_settings.lane_count); - } else { - dp_set_hw_lane_settings(link, &pipe_ctx->link_res, p_link_settings, DPRX); - } - dpcd_set_lane_settings(link, p_link_settings, DPRX); - } - - /* Blank stream if running test pattern */ - if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) { - /*TODO: - * m_pHwss-> - * MuteAudioEndpoint(pPathMode->pDisplayPath, true); - */ - /* Blank stream */ - link->dc->hwss.blank_stream(pipe_ctx); - } - - dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern, - (uint8_t *)p_custom_pattern, - (uint32_t)cust_pattern_size); - - if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) { - /* Set Test Pattern state */ - link->test_pattern_enabled = true; - if (p_link_settings != NULL) - dpcd_set_link_settings(link, - p_link_settings); - } - - switch (test_pattern) { - case DP_TEST_PATTERN_VIDEO_MODE: - pattern = PHY_TEST_PATTERN_NONE; - break; - case DP_TEST_PATTERN_D102: - pattern = PHY_TEST_PATTERN_D10_2; - break; - case DP_TEST_PATTERN_SYMBOL_ERROR: - pattern = PHY_TEST_PATTERN_SYMBOL_ERROR; - break; - case DP_TEST_PATTERN_PRBS7: - pattern = PHY_TEST_PATTERN_PRBS7; - break; - case DP_TEST_PATTERN_80BIT_CUSTOM: - pattern = PHY_TEST_PATTERN_80BIT_CUSTOM; - break; - case DP_TEST_PATTERN_CP2520_1: - pattern = PHY_TEST_PATTERN_CP2520_1; - break; - case DP_TEST_PATTERN_CP2520_2: - pattern = PHY_TEST_PATTERN_CP2520_2; - break; - case DP_TEST_PATTERN_CP2520_3: - pattern = PHY_TEST_PATTERN_CP2520_3; - break; - case DP_TEST_PATTERN_128b_132b_TPS1: - pattern = PHY_TEST_PATTERN_128b_132b_TPS1; - break; - case DP_TEST_PATTERN_128b_132b_TPS2: - pattern = PHY_TEST_PATTERN_128b_132b_TPS2; - break; - case DP_TEST_PATTERN_PRBS9: - pattern = PHY_TEST_PATTERN_PRBS9; - break; - case DP_TEST_PATTERN_PRBS11: - pattern = PHY_TEST_PATTERN_PRBS11; - break; - case DP_TEST_PATTERN_PRBS15: - pattern = PHY_TEST_PATTERN_PRBS15; - break; - case DP_TEST_PATTERN_PRBS23: - pattern = PHY_TEST_PATTERN_PRBS23; - break; - case DP_TEST_PATTERN_PRBS31: - pattern = PHY_TEST_PATTERN_PRBS31; - break; - case DP_TEST_PATTERN_264BIT_CUSTOM: - pattern = PHY_TEST_PATTERN_264BIT_CUSTOM; - break; - case DP_TEST_PATTERN_SQUARE: - pattern = PHY_TEST_PATTERN_SQUARE; - break; - case DP_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED: - pattern = PHY_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED; - break; - case DP_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED: - pattern = PHY_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED; - break; - case DP_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED: - pattern = PHY_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED; - break; - default: - return false; - } - - if (test_pattern == DP_TEST_PATTERN_VIDEO_MODE - /*TODO:&& !pPathMode->pDisplayPath->IsTargetPoweredOn()*/) - return false; - - if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) { - if (is_dp_phy_sqaure_pattern(test_pattern)) - core_link_write_dpcd(link, - DP_LINK_SQUARE_PATTERN, - p_custom_pattern, - 1); - - /* tell receiver that we are sending qualification - * pattern DP 1.2 or later - DP receiver's link quality - * pattern is set using DPCD LINK_QUAL_LANEx_SET - * register (0x10B~0x10E)\ - */ - for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) - link_qual_pattern[lane] = - (unsigned char)(pattern); - - core_link_write_dpcd(link, - DP_LINK_QUAL_LANE0_SET, - link_qual_pattern, - sizeof(link_qual_pattern)); - } else if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_10 || - link->dpcd_caps.dpcd_rev.raw == 0) { - /* tell receiver that we are sending qualification - * pattern DP 1.1a or earlier - DP receiver's link - * quality pattern is set using - * DPCD TRAINING_PATTERN_SET -> LINK_QUAL_PATTERN_SET - * register (0x102). We will use v_1.3 when we are - * setting test pattern for DP 1.1. - */ - core_link_read_dpcd(link, DP_TRAINING_PATTERN_SET, - &training_pattern.raw, - sizeof(training_pattern)); - training_pattern.v1_3.LINK_QUAL_PATTERN_SET = pattern; - core_link_write_dpcd(link, DP_TRAINING_PATTERN_SET, - &training_pattern.raw, - sizeof(training_pattern)); - } - } else { - enum dc_color_space color_space = COLOR_SPACE_UNKNOWN; - - switch (test_pattern_color_space) { - case DP_TEST_PATTERN_COLOR_SPACE_RGB: - color_space = COLOR_SPACE_SRGB; - if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA) - color_space = COLOR_SPACE_SRGB_LIMITED; - break; - - case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601: - color_space = COLOR_SPACE_YCBCR601; - if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA) - color_space = COLOR_SPACE_YCBCR601_LIMITED; - break; - case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709: - color_space = COLOR_SPACE_YCBCR709; - if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA) - color_space = COLOR_SPACE_YCBCR709_LIMITED; - break; - default: - break; - } - - if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable) { - if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) { - union dmub_hw_lock_flags hw_locks = { 0 }; - struct dmub_hw_lock_inst_flags inst_flags = { 0 }; - - hw_locks.bits.lock_dig = 1; - inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst; - - dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv, - true, - &hw_locks, - &inst_flags); - } else - pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable( - pipe_ctx->stream_res.tg); - } - - pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg); - /* update MSA to requested color space */ - pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute(pipe_ctx->stream_res.stream_enc, - &pipe_ctx->stream->timing, - color_space, - pipe_ctx->stream->use_vsc_sdp_for_colorimetry, - link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP); - - if (pipe_ctx->stream->use_vsc_sdp_for_colorimetry) { - if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA) - pipe_ctx->stream->vsc_infopacket.sb[17] |= (1 << 7); // sb17 bit 7 Dynamic Range: 0 = VESA range, 1 = CTA range - else - pipe_ctx->stream->vsc_infopacket.sb[17] &= ~(1 << 7); - resource_build_info_frame(pipe_ctx); - link->dc->hwss.update_info_frame(pipe_ctx); - } - - /* CRTC Patterns */ - set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space); - pipe_ctx->stream_res.tg->funcs->unlock(pipe_ctx->stream_res.tg); - pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, - CRTC_STATE_VACTIVE); - pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, - CRTC_STATE_VBLANK); - pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, - CRTC_STATE_VACTIVE); - - if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable) { - if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) { - union dmub_hw_lock_flags hw_locks = { 0 }; - struct dmub_hw_lock_inst_flags inst_flags = { 0 }; - - hw_locks.bits.lock_dig = 1; - inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst; - - dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv, - false, - &hw_locks, - &inst_flags); - } else - pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable( - pipe_ctx->stream_res.tg); - } - - /* Set Test Pattern state */ - link->test_pattern_enabled = true; - } - - return true; -} - -void dp_enable_mst_on_sink(struct dc_link *link, bool enable) -{ - unsigned char mstmCntl; - - core_link_read_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1); - if (enable) - mstmCntl |= DP_MST_EN; - else - mstmCntl &= (~DP_MST_EN); - - core_link_write_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1); -} - -void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode) -{ - union dpcd_edp_config edp_config_set; - bool panel_mode_edp = false; - - memset(&edp_config_set, '\0', sizeof(union dpcd_edp_config)); - - if (panel_mode != DP_PANEL_MODE_DEFAULT) { - - switch (panel_mode) { - case DP_PANEL_MODE_EDP: - case DP_PANEL_MODE_SPECIAL: - panel_mode_edp = true; - break; - - default: - break; - } - - /*set edp panel mode in receiver*/ - core_link_read_dpcd( - link, - DP_EDP_CONFIGURATION_SET, - &edp_config_set.raw, - sizeof(edp_config_set.raw)); - - if (edp_config_set.bits.PANEL_MODE_EDP - != panel_mode_edp) { - enum dc_status result; - - edp_config_set.bits.PANEL_MODE_EDP = - panel_mode_edp; - result = core_link_write_dpcd( - link, - DP_EDP_CONFIGURATION_SET, - &edp_config_set.raw, - sizeof(edp_config_set.raw)); - - ASSERT(result == DC_OK); - } - } - DC_LOG_DETECTION_DP_CAPS("Link: %d eDP panel mode supported: %d " - "eDP panel mode enabled: %d \n", - link->link_index, - link->dpcd_caps.panel_mode_edp, - panel_mode_edp); -} - -enum dp_panel_mode dp_get_panel_mode(struct dc_link *link) -{ - /* We need to explicitly check that connector - * is not DP. Some Travis_VGA get reported - * by video bios as DP. - */ - if (link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) { - - switch (link->dpcd_caps.branch_dev_id) { - case DP_BRANCH_DEVICE_ID_0022B9: - /* alternate scrambler reset is required for Travis - * for the case when external chip does not - * provide sink device id, alternate scrambler - * scheme will be overriden later by querying - * Encoder features - */ - if (strncmp( - link->dpcd_caps.branch_dev_name, - DP_VGA_LVDS_CONVERTER_ID_2, - sizeof( - link->dpcd_caps. - branch_dev_name)) == 0) { - return DP_PANEL_MODE_SPECIAL; - } - break; - case DP_BRANCH_DEVICE_ID_00001A: - /* alternate scrambler reset is required for Travis - * for the case when external chip does not provide - * sink device id, alternate scrambler scheme will - * be overriden later by querying Encoder feature - */ - if (strncmp(link->dpcd_caps.branch_dev_name, - DP_VGA_LVDS_CONVERTER_ID_3, - sizeof( - link->dpcd_caps. - branch_dev_name)) == 0) { - return DP_PANEL_MODE_SPECIAL; - } - break; - default: - break; - } - } - - if (link->dpcd_caps.panel_mode_edp && - (link->connector_signal == SIGNAL_TYPE_EDP || - (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT && - link->is_internal_display))) { - return DP_PANEL_MODE_EDP; - } - - return DP_PANEL_MODE_DEFAULT; -} - -enum dc_status dp_set_fec_ready(struct dc_link *link, const struct link_resource *link_res, bool ready) -{ - /* FEC has to be "set ready" before the link training. - * The policy is to always train with FEC - * if the sink supports it and leave it enabled on link. - * If FEC is not supported, disable it. - */ - struct link_encoder *link_enc = NULL; - enum dc_status status = DC_OK; - uint8_t fec_config = 0; - - link_enc = link_enc_cfg_get_link_enc(link); - ASSERT(link_enc); - - if (!dc_link_should_enable_fec(link)) - return status; - - if (link_enc->funcs->fec_set_ready && - link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) { - if (ready) { - fec_config = 1; - status = core_link_write_dpcd(link, - DP_FEC_CONFIGURATION, - &fec_config, - sizeof(fec_config)); - if (status == DC_OK) { - link_enc->funcs->fec_set_ready(link_enc, true); - link->fec_state = dc_link_fec_ready; - } else { - link_enc->funcs->fec_set_ready(link_enc, false); - link->fec_state = dc_link_fec_not_ready; - dm_error("dpcd write failed to set fec_ready"); - } - } else if (link->fec_state == dc_link_fec_ready) { - fec_config = 0; - status = core_link_write_dpcd(link, - DP_FEC_CONFIGURATION, - &fec_config, - sizeof(fec_config)); - link_enc->funcs->fec_set_ready(link_enc, false); - link->fec_state = dc_link_fec_not_ready; - } - } - - return status; -} - -void dp_set_fec_enable(struct dc_link *link, bool enable) -{ - struct link_encoder *link_enc = NULL; - - link_enc = link_enc_cfg_get_link_enc(link); - ASSERT(link_enc); - - if (!dc_link_should_enable_fec(link)) - return; - - if (link_enc->funcs->fec_set_enable && - link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) { - if (link->fec_state == dc_link_fec_ready && enable) { - /* Accord to DP spec, FEC enable sequence can first - * be transmitted anytime after 1000 LL codes have - * been transmitted on the link after link training - * completion. Using 1 lane RBR should have the maximum - * time for transmitting 1000 LL codes which is 6.173 us. - * So use 7 microseconds delay instead. - */ - udelay(7); - link_enc->funcs->fec_set_enable(link_enc, true); - link->fec_state = dc_link_fec_enabled; - } else if (link->fec_state == dc_link_fec_enabled && !enable) { - link_enc->funcs->fec_set_enable(link_enc, false); - link->fec_state = dc_link_fec_ready; - } - } -} - -bool dc_link_set_backlight_level_nits(struct dc_link *link, - bool isHDR, - uint32_t backlight_millinits, - uint32_t transition_time_in_ms) -{ - struct dpcd_source_backlight_set dpcd_backlight_set; - uint8_t backlight_control = isHDR ? 1 : 0; - - if (!link || (link->connector_signal != SIGNAL_TYPE_EDP && - link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT)) - return false; - - // OLEDs have no PWM, they can only use AUX - if (link->dpcd_sink_ext_caps.bits.oled == 1) - backlight_control = 1; - - *(uint32_t *)&dpcd_backlight_set.backlight_level_millinits = backlight_millinits; - *(uint16_t *)&dpcd_backlight_set.backlight_transition_time_ms = (uint16_t)transition_time_in_ms; - - - if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL, - (uint8_t *)(&dpcd_backlight_set), - sizeof(dpcd_backlight_set)) != DC_OK) - return false; - - if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_CONTROL, - &backlight_control, 1) != DC_OK) - return false; - - return true; -} - -bool dc_link_get_backlight_level_nits(struct dc_link *link, - uint32_t *backlight_millinits_avg, - uint32_t *backlight_millinits_peak) -{ - union dpcd_source_backlight_get dpcd_backlight_get; - - memset(&dpcd_backlight_get, 0, sizeof(union dpcd_source_backlight_get)); - - if (!link || (link->connector_signal != SIGNAL_TYPE_EDP && - link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT)) - return false; - - if (!core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_CURRENT_PEAK, - dpcd_backlight_get.raw, - sizeof(union dpcd_source_backlight_get))) - return false; - - *backlight_millinits_avg = - dpcd_backlight_get.bytes.backlight_millinits_avg; - *backlight_millinits_peak = - dpcd_backlight_get.bytes.backlight_millinits_peak; - - /* On non-supported panels dpcd_read usually succeeds with 0 returned */ - if (*backlight_millinits_avg == 0 || - *backlight_millinits_avg > *backlight_millinits_peak) - return false; - - return true; -} - -bool dc_link_backlight_enable_aux(struct dc_link *link, bool enable) -{ - uint8_t backlight_enable = enable ? 1 : 0; - - if (!link || (link->connector_signal != SIGNAL_TYPE_EDP && - link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT)) - return false; - - if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_ENABLE, - &backlight_enable, 1) != DC_OK) - return false; - - return true; -} - -// we read default from 0x320 because we expect BIOS wrote it there -// regular get_backlight_nit reads from panel set at 0x326 -bool dc_link_read_default_bl_aux(struct dc_link *link, uint32_t *backlight_millinits) -{ - if (!link || (link->connector_signal != SIGNAL_TYPE_EDP && - link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT)) - return false; - - if (!core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL, - (uint8_t *) backlight_millinits, - sizeof(uint32_t))) - return false; - - return true; -} - -bool dc_link_set_default_brightness_aux(struct dc_link *link) -{ - uint32_t default_backlight; - - if (link && link->dpcd_sink_ext_caps.bits.oled == 1) { - if (!dc_link_read_default_bl_aux(link, &default_backlight)) - default_backlight = 150000; - // if < 5 nits or > 5000, it might be wrong readback - if (default_backlight < 5000 || default_backlight > 5000000) - default_backlight = 150000; // - - return dc_link_set_backlight_level_nits(link, true, - default_backlight, 0); - } - return false; -} - -bool is_edp_ilr_optimization_required(struct dc_link *link, struct dc_crtc_timing *crtc_timing) -{ - struct dc_link_settings link_setting; - uint8_t link_bw_set; - uint8_t link_rate_set; - uint32_t req_bw; - union lane_count_set lane_count_set = {0}; - - ASSERT(link || crtc_timing); // invalid input - - if (link->dpcd_caps.edp_supported_link_rates_count == 0 || - !link->panel_config.ilr.optimize_edp_link_rate) - return false; - - - // Read DPCD 00100h to find if standard link rates are set - core_link_read_dpcd(link, DP_LINK_BW_SET, - &link_bw_set, sizeof(link_bw_set)); - - if (link_bw_set) { - DC_LOG_EVENT_LINK_TRAINING("eDP ILR: Optimization required, VBIOS used link_bw_set\n"); - return true; - } - - // Read DPCD 00115h to find the edp link rate set used - core_link_read_dpcd(link, DP_LINK_RATE_SET, - &link_rate_set, sizeof(link_rate_set)); - - // Read DPCD 00101h to find out the number of lanes currently set - core_link_read_dpcd(link, DP_LANE_COUNT_SET, - &lane_count_set.raw, sizeof(lane_count_set)); - - req_bw = dc_bandwidth_in_kbps_from_timing(crtc_timing); - - if (!crtc_timing->flags.DSC) - dc_link_decide_edp_link_settings(link, &link_setting, req_bw); - else - decide_edp_link_settings_with_dsc(link, &link_setting, req_bw, LINK_RATE_UNKNOWN); - - if (link->dpcd_caps.edp_supported_link_rates[link_rate_set] != link_setting.link_rate || - lane_count_set.bits.LANE_COUNT_SET != link_setting.lane_count) { - DC_LOG_EVENT_LINK_TRAINING("eDP ILR: Optimization required, VBIOS link_rate_set not optimal\n"); - return true; - } - - DC_LOG_EVENT_LINK_TRAINING("eDP ILR: No optimization required, VBIOS set optimal link_rate_set\n"); - return false; -} - - -// TODO - DP2.0 Link: Fix get_lane_status to handle LTTPR offset (SST and MST) -static void get_lane_status( - struct dc_link *link, - uint32_t lane_count, - union lane_status *status, - union lane_align_status_updated *status_updated) -{ - unsigned int lane; - uint8_t dpcd_buf[3] = {0}; - - if (status == NULL || status_updated == NULL) { - return; - } - - core_link_read_dpcd( - link, - DP_LANE0_1_STATUS, - dpcd_buf, - sizeof(dpcd_buf)); - - for (lane = 0; lane < lane_count; lane++) { - status[lane].raw = get_nibble_at_index(&dpcd_buf[0], lane); - } - - status_updated->raw = dpcd_buf[2]; -} - -bool dpcd_write_128b_132b_sst_payload_allocation_table( - const struct dc_stream_state *stream, - struct dc_link *link, - struct link_mst_stream_allocation_table *proposed_table, - bool allocate) -{ - const uint8_t vc_id = 1; /// VC ID always 1 for SST - const uint8_t start_time_slot = 0; /// Always start at time slot 0 for SST - bool result = false; - uint8_t req_slot_count = 0; - struct fixed31_32 avg_time_slots_per_mtp = { 0 }; - union payload_table_update_status update_status = { 0 }; - const uint32_t max_retries = 30; - uint32_t retries = 0; - - if (allocate) { - avg_time_slots_per_mtp = calculate_sst_avg_time_slots_per_mtp(stream, link); - req_slot_count = dc_fixpt_ceil(avg_time_slots_per_mtp); - /// Validation should filter out modes that exceed link BW - ASSERT(req_slot_count <= MAX_MTP_SLOT_COUNT); - if (req_slot_count > MAX_MTP_SLOT_COUNT) - return false; - } else { - /// Leave req_slot_count = 0 if allocate is false. - } - - proposed_table->stream_count = 1; /// Always 1 stream for SST - proposed_table->stream_allocations[0].slot_count = req_slot_count; - proposed_table->stream_allocations[0].vcp_id = vc_id; - - if (link->aux_access_disabled) - return true; - - /// Write DPCD 2C0 = 1 to start updating - update_status.bits.VC_PAYLOAD_TABLE_UPDATED = 1; - core_link_write_dpcd( - link, - DP_PAYLOAD_TABLE_UPDATE_STATUS, - &update_status.raw, - 1); - - /// Program the changes in DPCD 1C0 - 1C2 - ASSERT(vc_id == 1); - core_link_write_dpcd( - link, - DP_PAYLOAD_ALLOCATE_SET, - &vc_id, - 1); - - ASSERT(start_time_slot == 0); - core_link_write_dpcd( - link, - DP_PAYLOAD_ALLOCATE_START_TIME_SLOT, - &start_time_slot, - 1); - - core_link_write_dpcd( - link, - DP_PAYLOAD_ALLOCATE_TIME_SLOT_COUNT, - &req_slot_count, - 1); - - /// Poll till DPCD 2C0 read 1 - /// Try for at least 150ms (30 retries, with 5ms delay after each attempt) - - while (retries < max_retries) { - if (core_link_read_dpcd( - link, - DP_PAYLOAD_TABLE_UPDATE_STATUS, - &update_status.raw, - 1) == DC_OK) { - if (update_status.bits.VC_PAYLOAD_TABLE_UPDATED == 1) { - DC_LOG_DP2("SST Update Payload: downstream payload table updated."); - result = true; - break; - } - } else { - union dpcd_rev dpcdRev; - - if (core_link_read_dpcd( - link, - DP_DPCD_REV, - &dpcdRev.raw, - 1) != DC_OK) { - DC_LOG_ERROR("SST Update Payload: Unable to read DPCD revision " - "of sink while polling payload table " - "updated status bit."); - break; - } - } - retries++; - msleep(5); - } - - if (!result && retries == max_retries) { - DC_LOG_ERROR("SST Update Payload: Payload table not updated after retries, " - "continue on. Something is wrong with the branch."); - // TODO - DP2.0 Payload: Read and log the payload table from downstream branch - } - - return result; -} - -bool dpcd_poll_for_allocation_change_trigger(struct dc_link *link) -{ - /* - * wait for ACT handled - */ - int i; - const int act_retries = 30; - enum act_return_status result = ACT_FAILED; - union payload_table_update_status update_status = {0}; - union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX]; - union lane_align_status_updated lane_status_updated; - - if (link->aux_access_disabled) - return true; - for (i = 0; i < act_retries; i++) { - get_lane_status(link, link->cur_link_settings.lane_count, dpcd_lane_status, &lane_status_updated); - - if (!dp_is_cr_done(link->cur_link_settings.lane_count, dpcd_lane_status) || - !dp_is_ch_eq_done(link->cur_link_settings.lane_count, dpcd_lane_status) || - !dp_is_symbol_locked(link->cur_link_settings.lane_count, dpcd_lane_status) || - !dp_is_interlane_aligned(lane_status_updated)) { - DC_LOG_ERROR("SST Update Payload: Link loss occurred while " - "polling for ACT handled."); - result = ACT_LINK_LOST; - break; - } - core_link_read_dpcd( - link, - DP_PAYLOAD_TABLE_UPDATE_STATUS, - &update_status.raw, - 1); - - if (update_status.bits.ACT_HANDLED == 1) { - DC_LOG_DP2("SST Update Payload: ACT handled by downstream."); - result = ACT_SUCCESS; - break; - } - - msleep(5); - } - - if (result == ACT_FAILED) { - DC_LOG_ERROR("SST Update Payload: ACT still not handled after retries, " - "continue on. Something is wrong with the branch."); - } - - return (result == ACT_SUCCESS); -} - -struct fixed31_32 calculate_sst_avg_time_slots_per_mtp( - const struct dc_stream_state *stream, - const struct dc_link *link) -{ - struct fixed31_32 link_bw_effective = - dc_fixpt_from_int( - dc_link_bandwidth_kbps(link, &link->cur_link_settings)); - struct fixed31_32 timeslot_bw_effective = - dc_fixpt_div_int(link_bw_effective, MAX_MTP_SLOT_COUNT); - struct fixed31_32 timing_bw = - dc_fixpt_from_int( - dc_bandwidth_in_kbps_from_timing(&stream->timing)); - struct fixed31_32 avg_time_slots_per_mtp = - dc_fixpt_div(timing_bw, timeslot_bw_effective); - - return avg_time_slots_per_mtp; -} - -void edp_panel_backlight_power_on(struct dc_link *link, bool wait_for_hpd) -{ - if (link->connector_signal != SIGNAL_TYPE_EDP) - return; - - link->dc->hwss.edp_power_control(link, true); - if (wait_for_hpd) - link->dc->hwss.edp_wait_for_hpd_ready(link, true); - if (link->dc->hwss.edp_backlight_control) - link->dc->hwss.edp_backlight_control(link, true); -} - -void dc_link_clear_dprx_states(struct dc_link *link) -{ - memset(&link->dprx_states, 0, sizeof(link->dprx_states)); -} - -void dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode) -{ - if (link != NULL && link->dc->debug.enable_driver_sequence_debug) - core_link_write_dpcd(link, DP_SOURCE_SEQUENCE, - &dp_test_mode, sizeof(dp_test_mode)); -} - -void edp_add_delay_for_T9(struct dc_link *link) -{ - if (link && link->panel_config.pps.extra_delay_backlight_off > 0) - udelay(link->panel_config.pps.extra_delay_backlight_off * 1000); -} - -bool edp_receiver_ready_T9(struct dc_link *link) -{ - unsigned int tries = 0; - unsigned char sinkstatus = 0; - unsigned char edpRev = 0; - enum dc_status result = DC_OK; - - result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev)); - - /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/ - if (result == DC_OK && edpRev >= DP_EDP_12) { - do { - sinkstatus = 1; - result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus)); - if (sinkstatus == 0) - break; - if (result != DC_OK) - break; - udelay(100); //MAx T9 - } while (++tries < 50); - } - - return result; -} -bool edp_receiver_ready_T7(struct dc_link *link) -{ - unsigned char sinkstatus = 0; - unsigned char edpRev = 0; - enum dc_status result = DC_OK; - - /* use absolute time stamp to constrain max T7*/ - unsigned long long enter_timestamp = 0; - unsigned long long finish_timestamp = 0; - unsigned long long time_taken_in_ns = 0; - - result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev)); - - if (result == DC_OK && edpRev >= DP_EDP_12) { - /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/ - enter_timestamp = dm_get_timestamp(link->ctx); - do { - sinkstatus = 0; - result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus)); - if (sinkstatus == 1) - break; - if (result != DC_OK) - break; - udelay(25); - finish_timestamp = dm_get_timestamp(link->ctx); - time_taken_in_ns = dm_get_elapse_time_in_ns(link->ctx, finish_timestamp, enter_timestamp); - } while (time_taken_in_ns < 50 * 1000000); //MAx T7 is 50ms - } - - if (link && link->panel_config.pps.extra_t7_ms > 0) - udelay(link->panel_config.pps.extra_t7_ms * 1000); - - return result; -} - -void dp_retrain_link_dp_test(struct dc_link *link, - struct dc_link_settings *link_setting, - bool skip_video_pattern) -{ - struct pipe_ctx *pipe; - unsigned int i; - - udelay(100); - - for (i = 0; i < MAX_PIPES; i++) { - pipe = &link->dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe->stream != NULL && - pipe->stream->link == link && - !pipe->stream->dpms_off && - !pipe->top_pipe && !pipe->prev_odm_pipe) { - core_link_disable_stream(pipe); - pipe->link_config.dp_link_settings = *link_setting; - update_dp_encoder_resources_for_test_harness( - link->dc, - pipe->stream->ctx->dc->current_state, - pipe); - } - } - - for (i = 0; i < MAX_PIPES; i++) { - pipe = &link->dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe->stream != NULL && - pipe->stream->link == link && - !pipe->stream->dpms_off && - !pipe->top_pipe && !pipe->prev_odm_pipe) { - core_link_enable_stream( - pipe->stream->ctx->dc->current_state, - pipe); - } - } -} - -#undef DC_LOGGER -#define DC_LOGGER \ - dsc->ctx->logger -static void dsc_optc_config_log(struct display_stream_compressor *dsc, - struct dsc_optc_config *config) -{ - uint32_t precision = 1 << 28; - uint32_t bytes_per_pixel_int = config->bytes_per_pixel / precision; - uint32_t bytes_per_pixel_mod = config->bytes_per_pixel % precision; - uint64_t ll_bytes_per_pix_fraq = bytes_per_pixel_mod; - - /* 7 fractional digits decimal precision for bytes per pixel is enough because DSC - * bits per pixel precision is 1/16th of a pixel, which means bytes per pixel precision is - * 1/16/8 = 1/128 of a byte, or 0.0078125 decimal - */ - ll_bytes_per_pix_fraq *= 10000000; - ll_bytes_per_pix_fraq /= precision; - - DC_LOG_DSC("\tbytes_per_pixel 0x%08x (%d.%07d)", - config->bytes_per_pixel, bytes_per_pixel_int, (uint32_t)ll_bytes_per_pix_fraq); - DC_LOG_DSC("\tis_pixel_format_444 %d", config->is_pixel_format_444); - DC_LOG_DSC("\tslice_width %d", config->slice_width); -} - -bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable) -{ - struct dc *dc = pipe_ctx->stream->ctx->dc; - struct dc_stream_state *stream = pipe_ctx->stream; - bool result = false; - - if (dc_is_virtual_signal(stream->signal) || IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) - result = true; - else - result = dm_helpers_dp_write_dsc_enable(dc->ctx, stream, enable); - return result; -} - -/* The stream with these settings can be sent (unblanked) only after DSC was enabled on RX first, - * i.e. after dp_enable_dsc_on_rx() had been called - */ -void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) -{ - struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; - struct dc *dc = pipe_ctx->stream->ctx->dc; - struct dc_stream_state *stream = pipe_ctx->stream; - struct pipe_ctx *odm_pipe; - int opp_cnt = 1; - - for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) - opp_cnt++; - - if (enable) { - struct dsc_config dsc_cfg; - struct dsc_optc_config dsc_optc_cfg; - enum optc_dsc_mode optc_dsc_mode; - - /* Enable DSC hw block */ - dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt; - dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom; - dsc_cfg.pixel_encoding = stream->timing.pixel_encoding; - dsc_cfg.color_depth = stream->timing.display_color_depth; - dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false; - dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg; - ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0); - dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt; - - dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg); - dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst); - for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) { - struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc; - - odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg); - odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst); - } - dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt; - dsc_cfg.pic_width *= opp_cnt; - - optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED; - - /* Enable DSC in encoder */ - if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) - && !link_is_dp_128b_132b_signal(pipe_ctx)) { - DC_LOG_DSC("Setting stream encoder DSC config for engine %d:", (int)pipe_ctx->stream_res.stream_enc->id); - dsc_optc_config_log(dsc, &dsc_optc_cfg); - pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc, - optc_dsc_mode, - dsc_optc_cfg.bytes_per_pixel, - dsc_optc_cfg.slice_width); - - /* PPS SDP is set elsewhere because it has to be done after DIG FE is connected to DIG BE */ - } - - /* Enable DSC in OPTC */ - DC_LOG_DSC("Setting optc DSC config for tg instance %d:", pipe_ctx->stream_res.tg->inst); - dsc_optc_config_log(dsc, &dsc_optc_cfg); - pipe_ctx->stream_res.tg->funcs->set_dsc_config(pipe_ctx->stream_res.tg, - optc_dsc_mode, - dsc_optc_cfg.bytes_per_pixel, - dsc_optc_cfg.slice_width); - } else { - /* disable DSC in OPTC */ - pipe_ctx->stream_res.tg->funcs->set_dsc_config( - pipe_ctx->stream_res.tg, - OPTC_DSC_DISABLED, 0, 0); - - /* disable DSC in stream encoder */ - if (dc_is_dp_signal(stream->signal)) { - if (link_is_dp_128b_132b_signal(pipe_ctx)) - pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet( - pipe_ctx->stream_res.hpo_dp_stream_enc, - false, - NULL, - true); - else if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { - pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config( - pipe_ctx->stream_res.stream_enc, - OPTC_DSC_DISABLED, 0, 0); - pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( - pipe_ctx->stream_res.stream_enc, false, NULL, true); - } - } - - /* disable DSC block */ - pipe_ctx->stream_res.dsc->funcs->dsc_disable(pipe_ctx->stream_res.dsc); - for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) - odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc); - } -} - -bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable) -{ - struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; - bool result = false; - - if (!pipe_ctx->stream->timing.flags.DSC) - goto out; - if (!dsc) - goto out; - - if (enable) { - { - dp_set_dsc_on_stream(pipe_ctx, true); - result = true; - } - } else { - dp_set_dsc_on_rx(pipe_ctx, false); - dp_set_dsc_on_stream(pipe_ctx, false); - result = true; - } -out: - return result; -} - -/* - * For dynamic bpp change case, dsc is programmed with MASTER_UPDATE_LOCK enabled; - * hence PPS info packet update need to use frame update instead of immediate update. - * Added parameter immediate_update for this purpose. - * The decision to use frame update is hard-coded in function dp_update_dsc_config(), - * which is the only place where a "false" would be passed in for param immediate_update. - * - * immediate_update is only applicable when DSC is enabled. - */ -bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable, bool immediate_update) -{ - struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; - struct dc_stream_state *stream = pipe_ctx->stream; - - if (!pipe_ctx->stream->timing.flags.DSC || !dsc) - return false; - - if (enable) { - struct dsc_config dsc_cfg; - uint8_t dsc_packed_pps[128]; - - memset(&dsc_cfg, 0, sizeof(dsc_cfg)); - memset(dsc_packed_pps, 0, 128); - - /* Enable DSC hw block */ - dsc_cfg.pic_width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right; - dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom; - dsc_cfg.pixel_encoding = stream->timing.pixel_encoding; - dsc_cfg.color_depth = stream->timing.display_color_depth; - dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false; - dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg; - - dsc->funcs->dsc_get_packed_pps(dsc, &dsc_cfg, &dsc_packed_pps[0]); - memcpy(&stream->dsc_packed_pps[0], &dsc_packed_pps[0], sizeof(stream->dsc_packed_pps)); - if (dc_is_dp_signal(stream->signal)) { - DC_LOG_DSC("Setting stream encoder DSC PPS SDP for engine %d\n", (int)pipe_ctx->stream_res.stream_enc->id); - if (link_is_dp_128b_132b_signal(pipe_ctx)) - pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet( - pipe_ctx->stream_res.hpo_dp_stream_enc, - true, - &dsc_packed_pps[0], - immediate_update); - else - pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( - pipe_ctx->stream_res.stream_enc, - true, - &dsc_packed_pps[0], - immediate_update); - } - } else { - /* disable DSC PPS in stream encoder */ - memset(&stream->dsc_packed_pps[0], 0, sizeof(stream->dsc_packed_pps)); - if (dc_is_dp_signal(stream->signal)) { - if (link_is_dp_128b_132b_signal(pipe_ctx)) - pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet( - pipe_ctx->stream_res.hpo_dp_stream_enc, - false, - NULL, - true); - else - pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( - pipe_ctx->stream_res.stream_enc, false, NULL, true); - } - } - - return true; -} - - -bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx) -{ - struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; - - if (!pipe_ctx->stream->timing.flags.DSC) - return false; - if (!dsc) - return false; - - dp_set_dsc_on_stream(pipe_ctx, true); - dp_set_dsc_pps_sdp(pipe_ctx, true, false); - return true; -} - -#undef DC_LOGGER -#define DC_LOGGER \ - link->ctx->logger diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c index fa2ba3fc683b..74e465ba158d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c @@ -24,7 +24,6 @@ #include "link_enc_cfg.h" #include "resource.h" -#include "dc_link_dp.h" #include "link.h" #define DC_LOGGER dc->ctx->logger diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index a5b5f8592c1b..e41bbcbc7146 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -40,12 +40,11 @@ #include "virtual/virtual_stream_encoder.h" #include "dpcd_defs.h" #include "link_enc_cfg.h" -#include "dc_link_dp.h" #include "link.h" #include "virtual/virtual_link_hwss.h" -#include "link/link_hwss_dio.h" -#include "link/link_hwss_dpia.h" -#include "link/link_hwss_hpo_dp.h" +#include "link/hwss/link_hwss_dio.h" +#include "link/hwss/link_hwss_dpia.h" +#include "link/hwss/link_hwss_hpo_dp.h" #if defined(CONFIG_DRM_AMD_DC_SI) #include "dce60/dce60_resource.h" @@ -3270,6 +3269,50 @@ static void set_hfvs_info_packet( *info_packet = stream->hfvsif_infopacket; } +static void adaptive_sync_override_dp_info_packets_sdp_line_num( + const struct dc_crtc_timing *timing, + struct enc_sdp_line_num *sdp_line_num, + struct _vcs_dpi_display_pipe_dest_params_st *pipe_dlg_param) +{ + uint32_t asic_blank_start = 0; + uint32_t asic_blank_end = 0; + uint32_t v_update = 0; + + const struct dc_crtc_timing *tg = timing; + + /* blank_start = frame end - front porch */ + asic_blank_start = tg->v_total - tg->v_front_porch; + + /* blank_end = blank_start - active */ + asic_blank_end = (asic_blank_start - tg->v_border_bottom - + tg->v_addressable - tg->v_border_top); + + if (pipe_dlg_param->vstartup_start > asic_blank_end) { + v_update = (tg->v_total - (pipe_dlg_param->vstartup_start - asic_blank_end)); + sdp_line_num->adaptive_sync_line_num_valid = true; + sdp_line_num->adaptive_sync_line_num = (tg->v_total - v_update - 1); + } else { + sdp_line_num->adaptive_sync_line_num_valid = false; + sdp_line_num->adaptive_sync_line_num = 0; + } +} + +static void set_adaptive_sync_info_packet( + struct dc_info_packet *info_packet, + const struct dc_stream_state *stream, + struct encoder_info_frame *info_frame, + struct _vcs_dpi_display_pipe_dest_params_st *pipe_dlg_param) +{ + if (!stream->adaptive_sync_infopacket.valid) + return; + + adaptive_sync_override_dp_info_packets_sdp_line_num( + &stream->timing, + &info_frame->sdp_line_num, + pipe_dlg_param); + + *info_packet = stream->adaptive_sync_infopacket; +} static void set_vtem_info_packet( struct dc_info_packet *info_packet, @@ -3362,6 +3405,7 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx) info->vsc.valid = false; info->hfvsif.valid = false; info->vtem.valid = false; + info->adaptive_sync.valid = false; signal = pipe_ctx->stream->signal; /* HDMi and DP have different info packets*/ @@ -3382,6 +3426,10 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx) set_spd_info_packet(&info->spd, pipe_ctx->stream); set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream); + set_adaptive_sync_info_packet(&info->adaptive_sync, + pipe_ctx->stream, + info, + &pipe_ctx->pipe_dlg_param); } patch_gamut_packet_checksum(&info->gamut); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 22e754ad22c8..42ce45306483 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -47,7 +47,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.218" +#define DC_VER "3.2.220" #define MAX_SURFACES 3 #define MAX_PLANES 6 @@ -1414,6 +1414,7 @@ struct dpcd_caps { union dpcd_fec_capability fec_cap; struct dpcd_dsc_capabilities dsc_caps; struct dc_lttpr_caps lttpr_caps; + struct adaptive_sync_caps adaptive_sync_caps; struct dpcd_usb4_dp_tunneling_info usb4_dp_tun_info; union dp_128b_132b_supported_link_rates dp_128b_132b_supported_link_rates; diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index 84da54358922..184583807d45 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -502,7 +502,11 @@ union down_spread_ctrl { 1 = Main link signal is downspread <= 0.5% with frequency in the range of 30kHz ~ 33kHz*/ uint8_t SPREAD_AMP:1; - uint8_t RESERVED2:2;/*Bit 6:5 = RESERVED. Read all 0s*/ + uint8_t RESERVED2:1;/*Bit 5 = RESERVED. Read all 0s*/ + /* Bit 6 = FIXED_VTOTAL_AS_SDP_EN_IN_PR_ACTIVE. + 0 = FIXED_VTOTAL_AS_SDP_EN_IN_PR_ACTIVE is not enabled by the Source device (default) + 1 = FIXED_VTOTAL_AS_SDP_EN_IN_PR_ACTIVE is enabled by Source device */ + uint8_t FIXED_VTOTAL_AS_SDP_EN_IN_PR_ACTIVE:1; /*Bit 7 = MSA_TIMING_PAR_IGNORE_EN 0 = Source device will send valid data for the MSA Timing Params 1 = Source device may send invalid data for these MSA Timing Params*/ @@ -858,6 +862,21 @@ struct psr_caps { unsigned int psr_power_opt_flag; }; +union dpcd_dprx_feature_enumeration_list_cont_1 { + struct { + uint8_t ADAPTIVE_SYNC_SDP_SUPPORT:1; + uint8_t AS_SDP_FIRST_HALF_LINE_OR_3840_PIXEL_CYCLE_WINDOW_NOT_SUPPORTED: 1; + uint8_t RESERVED0: 2; + uint8_t VSC_EXT_SDP_VER1_SUPPORT: 1; + uint8_t RESERVED1: 3; + } bits; + uint8_t raw; +}; + +struct adaptive_sync_caps { + union dpcd_dprx_feature_enumeration_list_cont_1 dp_adap_sync_caps; +}; + /* Length of router topology ID read from DPCD in bytes. */ #define DPCD_USB4_TOPOLOGY_ID_LEN 5 diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index 48f6a5b09336..1927eacbfa71 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -280,6 +280,7 @@ struct dc_link { bool dp_keep_receiver_powered; bool dp_skip_DID2; bool dp_skip_reset_segment; + bool dp_skip_fs_144hz; bool dp_mot_reset_segment; /* Some USB4 docks do not handle turning off MST DSC once it has been enabled. */ bool dpia_mst_dsc_always_on; @@ -370,11 +371,6 @@ bool dc_link_get_backlight_level_nits(struct dc_link *link, uint32_t *backlight_millinits, uint32_t *backlight_millinits_peak); -bool dc_link_backlight_enable_aux(struct dc_link *link, bool enable); - -bool dc_link_read_default_bl_aux(struct dc_link *link, uint32_t *backlight_millinits); -bool dc_link_set_default_brightness_aux(struct dc_link *link); - int dc_link_get_backlight_level(const struct dc_link *dc_link); int dc_link_get_target_backlight_pwm(const struct dc_link *link); @@ -388,16 +384,10 @@ bool dc_link_setup_psr(struct dc_link *dc_link, const struct dc_stream_state *stream, struct psr_config *psr_config, struct psr_context *psr_context); -bool dc_power_alpm_dpcd_enable(struct dc_link *link, bool enable); - -void dc_link_get_psr_residency(const struct dc_link *link, uint32_t *residency); - void dc_link_blank_all_dp_displays(struct dc *dc); void dc_link_blank_all_edp_displays(struct dc *dc); void dc_link_blank_dp_stream(struct dc_link *link, bool hw_init); -bool dc_link_set_sink_vtotal_in_psr_active(const struct dc_link *link, - uint16_t psr_vtotal_idle, uint16_t psr_vtotal_su); /* Request DC to detect if there is a Panel connected. * boot - If this call is during initial boot. @@ -441,7 +431,8 @@ bool dc_link_wait_for_t12(struct dc_link *link); void dc_link_dp_handle_automated_test(struct dc_link *link); void dc_link_dp_handle_link_loss(struct dc_link *link); bool dc_link_dp_allow_hpd_rx_irq(const struct dc_link *link); - +bool dc_link_check_link_loss_status(struct dc_link *link, + union hpd_irq_data *hpd_irq_dpcd_data); struct dc_sink_init_data; struct dc_sink *dc_link_add_remote_sink( @@ -456,11 +447,6 @@ void dc_link_remove_remote_sink( /* Used by diagnostics for virtual link at the moment */ -void dc_link_dp_set_drive_settings( - struct dc_link *link, - const struct link_resource *link_res, - struct link_training_settings *lt_settings); - bool dc_link_dp_set_test_pattern( struct dc_link *link, enum dp_test_pattern test_pattern, @@ -589,4 +575,56 @@ void dc_link_dp_receiver_power_ctrl(struct dc_link *link, bool on); bool dc_link_decide_edp_link_settings(struct dc_link *link, struct dc_link_settings *link_setting, uint32_t req_bw); +void dc_link_edp_panel_backlight_power_on(struct dc_link *link, + bool wait_for_hpd); + +#define LINK_TRAINING_ATTEMPTS 4 +#define LINK_TRAINING_RETRY_DELAY 50 /* ms */ +#define MAX_MTP_SLOT_COUNT 64 +#define TRAINING_AUX_RD_INTERVAL 100 //us +#define LINK_AUX_WAKE_TIMEOUT_MS 1500 // Timeout when trying to wake unresponsive DPRX. + +struct dc_link; +struct dc_stream_state; +struct dc_link_settings; + +enum { + /* + * Some receivers fail to train on first try and are good + * on subsequent tries. 2 retries should be plenty. If we + * don't have a successful training then we don't expect to + * ever get one. + */ + LINK_TRAINING_MAX_VERIFY_RETRY = 2, + PEAK_FACTOR_X1000 = 1006, +}; + +bool dp_validate_mode_timing( + struct dc_link *link, + const struct dc_crtc_timing *timing); + +void dp_enable_mst_on_sink(struct dc_link *link, bool enable); + +enum dc_status dp_set_fec_ready(struct dc_link *link, const struct link_resource *link_res, bool ready); +void dp_set_fec_enable(struct dc_link *link, bool enable); +bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable); +bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable, bool immediate_update); +void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable); +bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx); +bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable); + +bool dpcd_write_128b_132b_sst_payload_allocation_table( + const struct dc_stream_state *stream, + struct dc_link *link, + struct link_mst_stream_allocation_table *proposed_table, + bool allocate); + +bool dpcd_poll_for_allocation_change_trigger(struct dc_link *link); + +struct fixed31_32 calculate_sst_avg_time_slots_per_mtp( + const struct dc_stream_state *stream, + const struct dc_link *link); +void setup_dp_hpo_stream(struct pipe_ctx *pipe_ctx, bool enable); +void dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode); + #endif /* DC_LINK_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index ef33d7d8a2bf..567452599659 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -190,6 +190,7 @@ struct dc_stream_state { struct dc_info_packet vsp_infopacket; struct dc_info_packet hfvsif_infopacket; struct dc_info_packet vtem_infopacket; + struct dc_info_packet adaptive_sync_infopacket; uint8_t dsc_packed_pps[128]; struct rect src; /* composition area */ struct rect dst; /* stream addressable area */ @@ -313,6 +314,7 @@ struct dc_stream_update { struct dc_info_packet *vsp_infopacket; struct dc_info_packet *hfvsif_infopacket; struct dc_info_packet *vtem_infopacket; + struct dc_info_packet *adaptive_sync_infopacket; bool *dpms_off; bool integer_scaling_update; bool *allow_freesync; diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index c73a655bd687..f653eca09ba7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -691,6 +691,7 @@ struct psr_config { uint8_t su_y_granularity; unsigned int line_time_in_us; uint8_t rate_control_caps; + uint16_t dsc_slice_height; }; union dmcu_psr_level { @@ -802,6 +803,7 @@ struct psr_context { uint8_t su_y_granularity; unsigned int line_time_in_us; uint8_t rate_control_caps; + uint16_t dsc_slice_height; }; struct colorspace_transform { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c index 2d3201b77d6a..1e2d2cbe2c37 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c @@ -417,6 +417,7 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub, copy_settings_data->relock_delay_frame_cnt = 0; if (link->dpcd_caps.sink_dev_id == DP_BRANCH_DEVICE_ID_001CF8) copy_settings_data->relock_delay_frame_cnt = 2; + copy_settings_data->dsc_slice_height = psr_context->dsc_slice_height; dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); dc_dmub_srv_cmd_execute(dc->dmub_srv); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index a51bd21a796f..adb36be8190e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -47,7 +47,6 @@ #include "link_enc_cfg.h" #include "link_hwss.h" #include "link.h" -#include "dc_link_dp.h" #include "dccg.h" #include "clock_source.h" #include "clk_mgr.h" @@ -65,7 +64,6 @@ #include "dcn10/dcn10_hw_sequencer.h" -#include "link/link_dp_trace.h" #include "dce110_hw_sequencer.h" #define GAMMA_HW_POINTS_NUM 256 @@ -653,10 +651,16 @@ void dce110_update_info_frame(struct pipe_ctx *pipe_ctx) pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets( pipe_ctx->stream_res.stream_enc, &pipe_ctx->stream_res.encoder_info_frame); - else + else { + if (pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets_sdp_line_num) + pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets_sdp_line_num( + pipe_ctx->stream_res.stream_enc, + &pipe_ctx->stream_res.encoder_info_frame); + pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets( pipe_ctx->stream_res.stream_enc, &pipe_ctx->stream_res.encoder_info_frame); + } } void dce110_enable_stream(struct pipe_ctx *pipe_ctx) @@ -807,19 +811,19 @@ void dce110_edp_power_control( div64_u64(dm_get_elapse_time_in_ns( ctx, current_ts, - dp_trace_get_edp_poweroff_timestamp(link)), 1000000); + link_dp_trace_get_edp_poweroff_timestamp(link)), 1000000); unsigned long long time_since_edp_poweron_ms = div64_u64(dm_get_elapse_time_in_ns( ctx, current_ts, - dp_trace_get_edp_poweron_timestamp(link)), 1000000); + link_dp_trace_get_edp_poweron_timestamp(link)), 1000000); DC_LOG_HW_RESUME_S3( "%s: transition: power_up=%d current_ts=%llu edp_poweroff=%llu edp_poweron=%llu time_since_edp_poweroff_ms=%llu time_since_edp_poweron_ms=%llu", __func__, power_up, current_ts, - dp_trace_get_edp_poweroff_timestamp(link), - dp_trace_get_edp_poweron_timestamp(link), + link_dp_trace_get_edp_poweroff_timestamp(link), + link_dp_trace_get_edp_poweron_timestamp(link), time_since_edp_poweroff_ms, time_since_edp_poweron_ms); @@ -834,7 +838,7 @@ void dce110_edp_power_control( link->panel_config.pps.extra_t12_ms; /* Adjust remaining_min_edp_poweroff_time_ms if this is not the first time. */ - if (dp_trace_get_edp_poweroff_timestamp(link) != 0) { + if (link_dp_trace_get_edp_poweroff_timestamp(link) != 0) { if (time_since_edp_poweroff_ms < remaining_min_edp_poweroff_time_ms) remaining_min_edp_poweroff_time_ms = remaining_min_edp_poweroff_time_ms - time_since_edp_poweroff_ms; @@ -894,13 +898,13 @@ void dce110_edp_power_control( __func__, (power_up ? "On":"Off"), bp_result); - dp_trace_set_edp_power_timestamp(link, power_up); + link_dp_trace_set_edp_power_timestamp(link, power_up); DC_LOG_HW_RESUME_S3( "%s: updated values: edp_poweroff=%llu edp_poweron=%llu\n", __func__, - dp_trace_get_edp_poweroff_timestamp(link), - dp_trace_get_edp_poweron_timestamp(link)); + link_dp_trace_get_edp_poweroff_timestamp(link), + link_dp_trace_get_edp_poweron_timestamp(link)); if (bp_result != BP_RESULT_OK) DC_LOG_ERROR( @@ -928,14 +932,14 @@ void dce110_edp_wait_for_T12( return; if (!link->panel_cntl->funcs->is_panel_powered_on(link->panel_cntl) && - dp_trace_get_edp_poweroff_timestamp(link) != 0) { + link_dp_trace_get_edp_poweroff_timestamp(link) != 0) { unsigned int t12_duration = 500; // Default T12 as per spec unsigned long long current_ts = dm_get_timestamp(ctx); unsigned long long time_since_edp_poweroff_ms = div64_u64(dm_get_elapse_time_in_ns( ctx, current_ts, - dp_trace_get_edp_poweroff_timestamp(link)), 1000000); + link_dp_trace_get_edp_poweroff_timestamp(link)), 1000000); t12_duration += link->panel_config.pps.extra_t12_ms; // Add extra T12 @@ -1016,7 +1020,7 @@ void dce110_edp_backlight_control( * we shouldn't be doing power-sequencing, hence we can skip * waiting for T7-ready. */ - edp_receiver_ready_T7(link); + link_edp_receiver_ready_T7(link); else DC_LOG_DC("edp_receiver_ready_T7 skipped\n"); } @@ -1047,7 +1051,7 @@ void dce110_edp_backlight_control( if (link->dpcd_sink_ext_caps.bits.oled || link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1 || link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1) - dc_link_backlight_enable_aux(link, enable); + link_backlight_enable_aux(link, enable); /*edp 1.2*/ if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_OFF) { @@ -1059,7 +1063,7 @@ void dce110_edp_backlight_control( * we shouldn't be doing power-sequencing, hence we can skip * waiting for T9-ready. */ - edp_add_delay_for_T9(link); + link_edp_add_delay_for_T9(link); else DC_LOG_DC("edp_receiver_ready_T9 skipped\n"); } @@ -1243,7 +1247,7 @@ void dce110_blank_stream(struct pipe_ctx *pipe_ctx) * we shouldn't be doing power-sequencing, hence we can skip * waiting for T9-ready. */ - edp_receiver_ready_T9(link); + link_edp_receiver_ready_T9(link); } } } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 0a0c930c1626..bb155734ac93 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -45,7 +45,6 @@ #include "dcn10_hubp.h" #include "dcn10_hubbub.h" #include "dcn10_cm_common.h" -#include "dc_link_dp.h" #include "dccg.h" #include "clk_mgr.h" #include "link_hwss.h" @@ -56,7 +55,6 @@ #include "dce/dmub_hw_lock_mgr.h" #include "dc_trace.h" #include "dce/dmub_outbox.h" -#include "inc/dc_link_dp.h" #include "link.h" #define DC_LOGGER_INIT(logger) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c index 1527c3b4fb19..a1e32b938050 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c @@ -28,7 +28,7 @@ #include "dcn10_stream_encoder.h" #include "reg_helper.h" #include "hw_shared.h" -#include "dc_link_dp.h" +#include "link.h" #include "dpcd_defs.h" #include "dcn30/dcn30_afmt.h" @@ -753,12 +753,19 @@ void enc1_stream_encoder_update_dp_info_packets( * use other packetIndex (such as 5,6) for other info packet */ + if (info_frame->adaptive_sync.valid) + enc1_update_generic_info_packet( + enc1, + 5, /* packetIndex */ + &info_frame->adaptive_sync); + /* enable/disable transmission of packet(s). * If enabled, packet transmission begins on the next frame */ REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, info_frame->vsc.valid); REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, info_frame->spd.valid); REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, info_frame->hdrsmd.valid); + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, info_frame->adaptive_sync.valid); /* This bit is the master enable bit. * When enabling secondary stream engine, diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index 6bfa16d9135f..916dceecd3de 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -46,7 +46,6 @@ #include "dchubbub.h" #include "reg_helper.h" #include "dcn10/dcn10_cm_common.h" -#include "dc_link_dp.h" #include "vm_helper.h" #include "dccg.h" #include "dc_dmub_srv.h" @@ -2023,8 +2022,11 @@ void dcn20_prepare_bandwidth( } } - /* program dchubbub watermarks */ - dc->wm_optimized_required = hubbub->funcs->program_watermarks(hubbub, + /* program dchubbub watermarks: + * For assigning wm_optimized_required, use |= operator since we don't want + * to clear the value if the optimize has not happened yet + */ + dc->wm_optimized_required |= hubbub->funcs->program_watermarks(hubbub, &context->bw_ctx.bw.dcn.watermarks, dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000, false); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c index cacf3f5298b0..48f662b031eb 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c @@ -29,7 +29,7 @@ #include "dcn20_stream_encoder.h" #include "reg_helper.h" #include "hw_shared.h" -#include "dc_link_dp.h" +#include "link.h" #include "dpcd_defs.h" #define DC_LOGGER \ @@ -423,6 +423,22 @@ void enc2_set_dynamic_metadata(struct stream_encoder *enc, } } +static void enc2_stream_encoder_update_dp_info_packets_sdp_line_num( + struct stream_encoder *enc, + struct encoder_info_frame *info_frame) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (info_frame->adaptive_sync.valid == true && + info_frame->sdp_line_num.adaptive_sync_line_num_valid == true) { + //00: REFER_TO_DP_SOF, 01: REFER_TO_OTG_SOF + REG_UPDATE(DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, 1); + + REG_UPDATE(DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM, + info_frame->sdp_line_num.adaptive_sync_line_num); + } +} + static void enc2_stream_encoder_update_dp_info_packets( struct stream_encoder *enc, const struct encoder_info_frame *info_frame) @@ -587,6 +603,8 @@ static const struct stream_encoder_funcs dcn20_str_enc_funcs = { enc2_stream_encoder_update_hdmi_info_packets, .stop_hdmi_info_packets = enc2_stream_encoder_stop_hdmi_info_packets, + .update_dp_info_packets_sdp_line_num = + enc2_stream_encoder_update_dp_info_packets_sdp_line_num, .update_dp_info_packets = enc2_stream_encoder_update_dp_info_packets, .send_immediate_sdp_message = diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c index 17df53793c92..5f9079d3943a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c @@ -404,6 +404,22 @@ static void enc3_read_state(struct stream_encoder *enc, struct enc_state *s) } } +void enc3_stream_encoder_update_dp_info_packets_sdp_line_num( + struct stream_encoder *enc, + struct encoder_info_frame *info_frame) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (info_frame->adaptive_sync.valid == true && + info_frame->sdp_line_num.adaptive_sync_line_num_valid == true) { + //00: REFER_TO_DP_SOF, 01: REFER_TO_OTG_SOF + REG_UPDATE(DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, 1); + + REG_UPDATE(DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM, + info_frame->sdp_line_num.adaptive_sync_line_num); + } +} + void enc3_stream_encoder_update_dp_info_packets( struct stream_encoder *enc, const struct encoder_info_frame *info_frame) @@ -452,12 +468,20 @@ void enc3_stream_encoder_update_dp_info_packets( * use other packetIndex (such as 5,6) for other info packet */ + if (info_frame->adaptive_sync.valid) + enc->vpg->funcs->update_generic_info_packet( + enc->vpg, + 5, /* packetIndex */ + &info_frame->adaptive_sync, + true); + /* enable/disable transmission of packet(s). * If enabled, packet transmission begins on the next frame */ REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, info_frame->vsc.valid); REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, info_frame->spd.valid); REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, info_frame->hdrsmd.valid); + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, info_frame->adaptive_sync.valid); /* This bit is the master enable bit. * When enabling secondary stream engine, @@ -803,6 +827,8 @@ static const struct stream_encoder_funcs dcn30_str_enc_funcs = { enc3_stream_encoder_update_hdmi_info_packets, .stop_hdmi_info_packets = enc3_stream_encoder_stop_hdmi_info_packets, + .update_dp_info_packets_sdp_line_num = + enc3_stream_encoder_update_dp_info_packets_sdp_line_num, .update_dp_info_packets = enc3_stream_encoder_update_dp_info_packets, .stop_dp_info_packets = diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h index 54ee230e7f98..06310973ded2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h @@ -292,6 +292,10 @@ void enc3_stream_encoder_update_hdmi_info_packets( void enc3_stream_encoder_stop_hdmi_info_packets( struct stream_encoder *enc); +void enc3_stream_encoder_update_dp_info_packets_sdp_line_num( + struct stream_encoder *enc, + struct encoder_info_frame *info_frame); + void enc3_stream_encoder_update_dp_info_packets( struct stream_encoder *enc, const struct encoder_info_frame *info_frame); diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c index 7360b3ce4283..444f9fad3de6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c @@ -50,7 +50,7 @@ #include "dpcd_defs.h" #include "../dcn20/dcn20_hwseq.h" #include "dcn30_resource.h" -#include "inc/dc_link_dp.h" +#include "link.h" @@ -674,10 +674,16 @@ void dcn30_update_info_frame(struct pipe_ctx *pipe_ctx) pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets( pipe_ctx->stream_res.stream_enc, &pipe_ctx->stream_res.encoder_info_frame); - else + else { + if (pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets_sdp_line_num) + pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets_sdp_line_num( + pipe_ctx->stream_res.stream_enc, + &pipe_ctx->stream_res.encoder_info_frame); + pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets( pipe_ctx->stream_res.stream_enc, &pipe_ctx->stream_res.encoder_info_frame); + } } void dcn30_program_dmdata_engine(struct pipe_ctx *pipe_ctx) diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c index 16639bd03adf..d76f55a12eb4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c @@ -430,6 +430,22 @@ static void dcn31_hpo_dp_stream_enc_set_stream_attribute( MSA_DATA_LANE_3, 0); } +static void dcn31_hpo_dp_stream_enc_update_dp_info_packets_sdp_line_num( + struct hpo_dp_stream_encoder *enc, + struct encoder_info_frame *info_frame) +{ + struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); + + if (info_frame->adaptive_sync.valid == true && + info_frame->sdp_line_num.adaptive_sync_line_num_valid == true) { + //00: REFER_TO_DP_SOF, 01: REFER_TO_OTG_SOF + REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL5, GSP_SOF_REFERENCE, 1); + + REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL5, GSP_TRANSMISSION_LINE_NUMBER, + info_frame->sdp_line_num.adaptive_sync_line_num); + } +} + static void dcn31_hpo_dp_stream_enc_update_dp_info_packets( struct hpo_dp_stream_encoder *enc, const struct encoder_info_frame *info_frame) @@ -458,12 +474,20 @@ static void dcn31_hpo_dp_stream_enc_update_dp_info_packets( &info_frame->hdrsmd, true); + if (info_frame->adaptive_sync.valid) + enc->vpg->funcs->update_generic_info_packet( + enc->vpg, + 5, /* packetIndex */ + &info_frame->adaptive_sync, + true); + /* enable/disable transmission of packet(s). * If enabled, packet transmission begins on the next frame */ REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL0, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, info_frame->vsc.valid); REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL2, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, info_frame->spd.valid); REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL3, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, info_frame->hdrsmd.valid); + REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL5, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, info_frame->adaptive_sync.valid); /* check if dynamic metadata packet transmission is enabled */ REG_GET(DP_SYM32_ENC_SDP_METADATA_PACKET_CONTROL, @@ -714,6 +738,7 @@ static const struct hpo_dp_stream_encoder_funcs dcn30_str_enc_funcs = { .dp_blank = dcn31_hpo_dp_stream_enc_dp_blank, .disable = dcn31_hpo_dp_stream_enc_disable, .set_stream_attribute = dcn31_hpo_dp_stream_enc_set_stream_attribute, + .update_dp_info_packets_sdp_line_num = dcn31_hpo_dp_stream_enc_update_dp_info_packets_sdp_line_num, .update_dp_info_packets = dcn31_hpo_dp_stream_enc_update_dp_info_packets, .stop_dp_info_packets = dcn31_hpo_dp_stream_enc_stop_dp_info_packets, .dp_set_dsc_pps_info_packet = dcn31_hpo_dp_stream_enc_set_dsc_pps_info_packet, diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c index 0e1949d9ea58..9871f9e189d3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c @@ -45,7 +45,6 @@ #include "link_hwss.h" #include "dpcd_defs.h" #include "dce/dmub_outbox.h" -#include "dc_link_dp.h" #include "link.h" #include "dcn10/dcn10_hw_sequencer.h" #include "inc/link_enc_cfg.h" @@ -421,6 +420,11 @@ void dcn31_update_info_frame(struct pipe_ctx *pipe_ctx) &pipe_ctx->stream_res.encoder_info_frame); return; } else { + if (pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets_sdp_line_num) + pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets_sdp_line_num( + pipe_ctx->stream_res.stream_enc, + &pipe_ctx->stream_res.encoder_info_frame); + pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets( pipe_ctx->stream_res.stream_enc, &pipe_ctx->stream_res.encoder_info_frame); diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c index 67f4589f3e23..b818ebe7d06d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c @@ -30,7 +30,7 @@ #include "dcn314_dio_stream_encoder.h" #include "reg_helper.h" #include "hw_shared.h" -#include "dc_link_dp.h" +#include "link.h" #include "dpcd_defs.h" #define DC_LOGGER \ @@ -429,6 +429,8 @@ static const struct stream_encoder_funcs dcn314_str_enc_funcs = { enc3_stream_encoder_update_hdmi_info_packets, .stop_hdmi_info_packets = enc3_stream_encoder_stop_hdmi_info_packets, + .update_dp_info_packets_sdp_line_num = + enc3_stream_encoder_update_dp_info_packets_sdp_line_num, .update_dp_info_packets = enc3_stream_encoder_update_dp_info_packets, .stop_dp_info_packets = diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.h index 33dfdf8b4100..ed0772387903 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.h @@ -280,6 +280,10 @@ void enc3_stream_encoder_update_hdmi_info_packets( void enc3_stream_encoder_stop_hdmi_info_packets( struct stream_encoder *enc); +void enc3_stream_encoder_update_dp_info_packets_sdp_line_num( + struct stream_encoder *enc, + struct encoder_info_frame *info_frame); + void enc3_stream_encoder_update_dp_info_packets( struct stream_encoder *enc, const struct encoder_info_frame *info_frame); diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c index 7980462e3abe..d725260336fe 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c @@ -46,9 +46,7 @@ #include "link_hwss.h" #include "dpcd_defs.h" #include "dce/dmub_outbox.h" -#include "dc_link_dp.h" #include "link.h" -#include "inc/dc_link_dp.h" #include "dcn10/dcn10_hw_sequencer.h" #include "inc/link_enc_cfg.h" #include "dcn30/dcn30_vpg.h" diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c index f01968f6d182..3c0ce9404699 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c @@ -29,7 +29,7 @@ #include "dcn32_dio_stream_encoder.h" #include "reg_helper.h" #include "hw_shared.h" -#include "dc_link_dp.h" +#include "link.h" #include "dpcd_defs.h" #define DC_LOGGER \ @@ -463,6 +463,8 @@ static const struct stream_encoder_funcs dcn32_str_enc_funcs = { enc3_stream_encoder_update_hdmi_info_packets, .stop_hdmi_info_packets = enc3_stream_encoder_stop_hdmi_info_packets, + .update_dp_info_packets_sdp_line_num = + enc3_stream_encoder_update_dp_info_packets_sdp_line_num, .update_dp_info_packets = enc3_stream_encoder_update_dp_info_packets, .stop_dp_info_packets = diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c index 3b44006e1a80..addfde594622 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c @@ -51,7 +51,6 @@ #include "dce/dmub_hw_lock_mgr.h" #include "dcn32_resource.h" #include "link.h" -#include "dc_link_dp.h" #include "dmub/inc/dmub_subvp_state.h" #define DC_LOGGER_INIT(logger) @@ -247,6 +246,13 @@ bool dcn32_apply_idle_power_optimizations(struct dc *dc, bool enable) if (!dc->ctx->dmub_srv) return false; + for (i = 0; i < dc->current_state->stream_count; i++) { + /* MALL SS messaging is not supported with PSR at this time */ + if (dc->current_state->streams[i] != NULL && + dc->current_state->streams[i]->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED) + return false; + } + if (enable) { if (dc->current_state) { @@ -689,6 +695,7 @@ static void dcn32_initialize_min_clocks(struct dc *dc) { struct dc_clocks *clocks = &dc->current_state->bw_ctx.bw.dcn.clk; + clocks->dcfclk_deep_sleep_khz = DCN3_2_DCFCLK_DS_INIT_KHZ; clocks->dcfclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dcfclk_mhz * 1000; clocks->socclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].socclk_mhz * 1000; clocks->dramclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].memclk_mhz * 1000; @@ -800,6 +807,16 @@ void dcn32_init_hw(struct dc *dc) !dc->res_pool->hubbub->ctx->dc->debug.disable_stutter); dcn32_initialize_min_clocks(dc); + + /* On HW init, allow idle optimizations after pipes have been turned off. + * + * In certain D3 cases (i.e. BOCO / BOMACO) it's possible that hardware state + * is reset (i.e. not in idle at the time hw init is called), but software state + * still has idle_optimizations = true, so we must disable idle optimizations first + * (i.e. set false), then re-enable (set true). + */ + dc_allow_idle_optimizations(dc, false); + dc_allow_idle_optimizations(dc, true); } /* In headless boot cases, DIG may be turned diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c index 47dc96acdacb..74e50c09bb62 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c @@ -57,7 +57,6 @@ #include "dcn31/dcn31_hpo_dp_stream_encoder.h" #include "dcn31/dcn31_hpo_dp_link_encoder.h" #include "dcn32/dcn32_hpo_dp_link_encoder.h" -#include "dc_link_dp.h" #include "dcn31/dcn31_apg.h" #include "dcn31/dcn31_dio_link_encoder.h" #include "dcn32/dcn32_dio_link_encoder.h" @@ -2150,13 +2149,19 @@ static bool dcn32_resource_construct( dc->caps.max_cursor_size = 64; dc->caps.min_horizontal_blanking_period = 80; dc->caps.dmdata_alloc_size = 2048; - dc->caps.mall_size_per_mem_channel = 0; + dc->caps.mall_size_per_mem_channel = 4; dc->caps.mall_size_total = 0; dc->caps.cursor_cache_size = dc->caps.max_cursor_size * dc->caps.max_cursor_size * 8; dc->caps.cache_line_size = 64; dc->caps.cache_num_ways = 16; - dc->caps.max_cab_allocation_bytes = 67108864; // 64MB = 1024 * 1024 * 64 + + /* Calculate the available MALL space */ + dc->caps.max_cab_allocation_bytes = dcn32_calc_num_avail_chans_for_mall( + dc, dc->ctx->dc_bios->vram_info.num_chans) * + dc->caps.mall_size_per_mem_channel * 1024 * 1024; + dc->caps.mall_size_total = dc->caps.max_cab_allocation_bytes; + dc->caps.subvp_fw_processing_delay_us = 15; dc->caps.subvp_drr_max_vblank_margin_us = 40; dc->caps.subvp_prefetch_end_to_mall_start_us = 15; @@ -2593,3 +2598,55 @@ struct pipe_ctx *dcn32_acquire_idle_pipe_for_head_pipe_in_layer( return idle_pipe; } + +unsigned int dcn32_calc_num_avail_chans_for_mall(struct dc *dc, int num_chans) +{ + /* + * DCN32 and DCN321 SKUs may have different sizes for MALL + * but we may not be able to access all the MALL space. + * If the num_chans is power of 2, then we can access all + * of the available MALL space. Otherwise, we can only + * access: + * + * max_cab_size_in_bytes = total_cache_size_in_bytes * + * ((2^floor(log2(num_chans)))/num_chans) + * + * Calculating the MALL sizes for all available SKUs, we + * have come up with the follow simplified check. + * - we have max_chans which provides the max MALL size. + * Each chans supports 4MB of MALL so: + * + * total_cache_size_in_bytes = max_chans * 4 MB + * + * - we have avail_chans which shows the number of channels + * we can use if we can't access the entire MALL space. + * It is generally half of max_chans + * - so we use the following checks: + * + * if (num_chans == max_chans), return max_chans + * if (num_chans < max_chans), return avail_chans + * + * - exception is GC_11_0_0 where we can't access max_chans, + * so we define max_avail_chans as the maximum available + * MALL space + * + */ + int gc_11_0_0_max_chans = 48; + int gc_11_0_0_max_avail_chans = 32; + int gc_11_0_0_avail_chans = 16; + int gc_11_0_3_max_chans = 16; + int gc_11_0_3_avail_chans = 8; + int gc_11_0_2_max_chans = 8; + int gc_11_0_2_avail_chans = 4; + + if (ASICREV_IS_GC_11_0_0(dc->ctx->asic_id.hw_internal_rev)) { + return (num_chans == gc_11_0_0_max_chans) ? + gc_11_0_0_max_avail_chans : gc_11_0_0_avail_chans; + } else if (ASICREV_IS_GC_11_0_2(dc->ctx->asic_id.hw_internal_rev)) { + return (num_chans == gc_11_0_2_max_chans) ? + gc_11_0_2_max_chans : gc_11_0_2_avail_chans; + } else { // if (ASICREV_IS_GC_11_0_3(dc->ctx->asic_id.hw_internal_rev)) { + return (num_chans == gc_11_0_3_max_chans) ? + gc_11_0_3_max_chans : gc_11_0_3_avail_chans; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h index b07d3b0e6a5c..a09db7c63a04 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h @@ -38,6 +38,7 @@ #define DCN3_2_MBLK_HEIGHT_4BPE 128 #define DCN3_2_MBLK_HEIGHT_8BPE 64 #define DCN3_2_VMIN_DISPCLK_HZ 717000000 +#define DCN3_2_DCFCLK_DS_INIT_KHZ 10000 // Choose 10Mhz for init DCFCLK DS freq #define TO_DCN32_RES_POOL(pool)\ container_of(pool, struct dcn32_resource_pool, base) @@ -122,6 +123,7 @@ bool dcn32_mpo_in_use(struct dc_state *context); bool dcn32_any_surfaces_rotated(struct dc *dc, struct dc_state *context); bool dcn32_is_center_timing(struct pipe_ctx *pipe); +bool dcn32_is_psr_capable(struct pipe_ctx *pipe); struct pipe_ctx *dcn32_acquire_idle_pipe_for_head_pipe_in_layer( struct dc_state *state, @@ -146,6 +148,8 @@ void dcn32_restore_mall_state(struct dc *dc, bool dcn32_allow_subvp_with_active_margin(struct pipe_ctx *pipe); +unsigned int dcn32_calc_num_avail_chans_for_mall(struct dc *dc, int num_chans); + /* definitions for run time init of reg offsets */ /* CLK SRC */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c index 0fc79d75ce76..3a2d7bcc4b6d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c @@ -251,6 +251,16 @@ bool dcn32_is_center_timing(struct pipe_ctx *pipe) return is_center_timing; } +bool dcn32_is_psr_capable(struct pipe_ctx *pipe) +{ + bool psr_capable = false; + + if (pipe->stream && pipe->stream->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED) { + psr_capable = true; + } + return psr_capable; +} + /** * ******************************************************************************************* * dcn32_determine_det_override: Determine DET allocation for each pipe diff --git a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c index 260d71ca0205..fd57e0167737 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c @@ -60,7 +60,6 @@ #include "dcn31/dcn31_hpo_dp_stream_encoder.h" #include "dcn31/dcn31_hpo_dp_link_encoder.h" #include "dcn32/dcn32_hpo_dp_link_encoder.h" -#include "dc_link_dp.h" #include "dcn31/dcn31_apg.h" #include "dcn31/dcn31_dio_link_encoder.h" #include "dcn32/dcn32_dio_link_encoder.h" @@ -1703,11 +1702,18 @@ static bool dcn321_resource_construct( dc->caps.max_cursor_size = 64; dc->caps.min_horizontal_blanking_period = 80; dc->caps.dmdata_alloc_size = 2048; - dc->caps.mall_size_per_mem_channel = 0; + dc->caps.mall_size_per_mem_channel = 4; dc->caps.mall_size_total = 0; dc->caps.cursor_cache_size = dc->caps.max_cursor_size * dc->caps.max_cursor_size * 8; dc->caps.cache_line_size = 64; dc->caps.cache_num_ways = 16; + + /* Calculate the available MALL space */ + dc->caps.max_cab_allocation_bytes = dcn32_calc_num_avail_chans_for_mall( + dc, dc->ctx->dc_bios->vram_info.num_chans) * + dc->caps.mall_size_per_mem_channel * 1024 * 1024; + dc->caps.mall_size_total = dc->caps.max_cab_allocation_bytes; + dc->caps.max_cab_allocation_bytes = 33554432; // 32MB = 1024 * 1024 * 32 dc->caps.subvp_fw_processing_delay_us = 15; dc->caps.subvp_drr_max_vblank_margin_us = 40; diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index af1c50ed905a..c624c768cc3d 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -161,6 +161,12 @@ enum dc_edid_status dm_helpers_read_local_edid( struct dc_link *link, struct dc_sink *sink); +bool dm_helpers_dp_handle_test_pattern_request( + struct dc_context *ctx, + const struct dc_link *link, + union link_test_pattern dpcd_test_pattern, + union test_misc dpcd_test_params); + void dm_set_dcn_clocks( struct dc_context *ctx, struct dc_clocks *clks); diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c index d2b89c50be2a..197df404761a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c @@ -26,7 +26,6 @@ #include "resource.h" #include "clk_mgr.h" -#include "dc_link_dp.h" #include "dchubbub.h" #include "dcn20/dcn20_resource.h" #include "dcn21/dcn21_resource.h" @@ -1004,6 +1003,39 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc } } +static void dcn20_adjust_freesync_v_startup( + const struct dc_crtc_timing *dc_crtc_timing, int *vstartup_start) +{ + struct dc_crtc_timing patched_crtc_timing; + uint32_t asic_blank_end = 0; + uint32_t asic_blank_start = 0; + uint32_t newVstartup = 0; + + patched_crtc_timing = *dc_crtc_timing; + + if (patched_crtc_timing.flags.INTERLACE == 1) { + if (patched_crtc_timing.v_front_porch < 2) + patched_crtc_timing.v_front_porch = 2; + } else { + if (patched_crtc_timing.v_front_porch < 1) + patched_crtc_timing.v_front_porch = 1; + } + + /* blank_start = frame end - front porch */ + asic_blank_start = patched_crtc_timing.v_total - + patched_crtc_timing.v_front_porch; + + /* blank_end = blank_start - active */ + asic_blank_end = asic_blank_start - + patched_crtc_timing.v_border_bottom - + patched_crtc_timing.v_addressable - + patched_crtc_timing.v_border_top; + + newVstartup = asic_blank_end + (patched_crtc_timing.v_total - asic_blank_start); + + *vstartup_start = ((newVstartup > *vstartup_start) ? newVstartup : *vstartup_start); +} + void dcn20_calculate_dlg_params( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, @@ -1063,6 +1095,11 @@ void dcn20_calculate_dlg_params( context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz = pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000; context->res_ctx.pipe_ctx[i].pipe_dlg_param = pipes[pipe_idx].pipe.dest; + if (context->res_ctx.pipe_ctx[i].stream->adaptive_sync_infopacket.valid) + dcn20_adjust_freesync_v_startup( + &context->res_ctx.pipe_ctx[i].stream->timing, + &context->res_ctx.pipe_ctx[i].pipe_dlg_param.vstartup_start); + pipe_idx++; } /*save a original dppclock copy*/ diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index 7feb8759e475..0dc1a03999b6 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -24,7 +24,6 @@ * */ #include "dcn32_fpu.h" -#include "dc_link_dp.h" #include "dcn32/dcn32_resource.h" #include "dcn20/dcn20_resource.h" #include "display_mode_vba_util_32.h" @@ -692,7 +691,7 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc, * to combine this with SubVP can cause issues with the scheduling). * - Not TMZ surface */ - if (pipe->plane_state && !pipe->top_pipe && !dcn32_is_center_timing(pipe) && + if (pipe->plane_state && !pipe->top_pipe && !dcn32_is_center_timing(pipe) && !dcn32_is_psr_capable(pipe) && pipe->stream->mall_stream_config.type == SUBVP_NONE && refresh_rate < 120 && !pipe->plane_state->address.tmz_surface && (vba->ActiveDRAMClockChangeLatencyMarginPerState[vba->VoltageLevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]] <= 0 || (vba->ActiveDRAMClockChangeLatencyMarginPerState[vba->VoltageLevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]] > 0 && @@ -1272,6 +1271,38 @@ static bool is_dtbclk_required(struct dc *dc, struct dc_state *context) return false; } +static void dcn20_adjust_freesync_v_startup(const struct dc_crtc_timing *dc_crtc_timing, int *vstartup_start) +{ + struct dc_crtc_timing patched_crtc_timing; + uint32_t asic_blank_end = 0; + uint32_t asic_blank_start = 0; + uint32_t newVstartup = 0; + + patched_crtc_timing = *dc_crtc_timing; + + if (patched_crtc_timing.flags.INTERLACE == 1) { + if (patched_crtc_timing.v_front_porch < 2) + patched_crtc_timing.v_front_porch = 2; + } else { + if (patched_crtc_timing.v_front_porch < 1) + patched_crtc_timing.v_front_porch = 1; + } + + /* blank_start = frame end - front porch */ + asic_blank_start = patched_crtc_timing.v_total - + patched_crtc_timing.v_front_porch; + + /* blank_end = blank_start - active */ + asic_blank_end = asic_blank_start - + patched_crtc_timing.v_border_bottom - + patched_crtc_timing.v_addressable - + patched_crtc_timing.v_border_top; + + newVstartup = asic_blank_end + (patched_crtc_timing.v_total - asic_blank_start); + + *vstartup_start = ((newVstartup > *vstartup_start) ? newVstartup : *vstartup_start); +} + static void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, int pipe_cnt, int vlevel) @@ -1375,6 +1406,11 @@ static void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context, } } + if (context->res_ctx.pipe_ctx[i].stream->adaptive_sync_infopacket.valid) + dcn20_adjust_freesync_v_startup( + &context->res_ctx.pipe_ctx[i].stream->timing, + &context->res_ctx.pipe_ctx[i].pipe_dlg_param.vstartup_start); + pipe_idx++; } /* If DCN isn't making memory requests we can allow pstate change and lower clocks */ @@ -1601,16 +1637,12 @@ bool dcn32_internal_validate_bw(struct dc *dc, * to support with Prefetch mode 1 (dm_prefetch_support_fclk_and_stutter == 2) */ context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final = - dm_prefetch_support_fclk_and_stutter; + dm_prefetch_support_none; + context->bw_ctx.dml.validate_max_state = fast_validate; vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); - /* Last attempt with Prefetch mode 2 (dm_prefetch_support_stutter == 3) */ - if (vlevel == context->bw_ctx.dml.soc.num_states) { - context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final = - dm_prefetch_support_stutter; - vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); - } + context->bw_ctx.dml.validate_max_state = false; if (vlevel < context->bw_ctx.dml.soc.num_states) { memset(split, 0, sizeof(split)); @@ -2499,8 +2531,11 @@ void dcn32_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_pa } /* Override from VBIOS for num_chan */ - if (dc->ctx->dc_bios->vram_info.num_chans) + if (dc->ctx->dc_bios->vram_info.num_chans) { dcn3_2_soc.num_chans = dc->ctx->dc_bios->vram_info.num_chans; + dcn3_2_soc.mall_allocated_for_dcn_mbytes = (double)(dcn32_calc_num_avail_chans_for_mall(dc, + dc->ctx->dc_bios->vram_info.num_chans) * dc->caps.mall_size_per_mem_channel); + } if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes) dcn3_2_soc.dram_channel_width_bytes = dc->ctx->dc_bios->vram_info.dram_channel_width_bytes; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c index 6c5ab5c26b38..23e50d15e9ae 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c @@ -1639,9 +1639,14 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman static void mode_support_configuration(struct vba_vars_st *v, struct display_mode_lib *mode_lib) { - int i, j; + int i, j, start_state; - for (i = v->soc.num_states - 1; i >= 0; i--) { + if (mode_lib->validate_max_state) + start_state = v->soc.num_states - 1; + else + start_state = 0; + + for (i = v->soc.num_states - 1; i >= start_state; i--) { for (j = 0; j < 2; j++) { if (mode_lib->vba.ScaleRatioAndTapsSupport == true && mode_lib->vba.SourceFormatPixelAndScanSupport == true @@ -1710,7 +1715,7 @@ static void mode_support_configuration(struct vba_vars_st *v, void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_lib) { struct vba_vars_st *v = &mode_lib->vba; - int i, j; + int i, j, start_state; unsigned int k, m; unsigned int MaximumMPCCombine; unsigned int NumberOfNonCombinedSurfaceOfMaximumBandwidth; @@ -1723,6 +1728,10 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l #endif /*MODE SUPPORT, VOLTAGE STATE AND SOC CONFIGURATION*/ + if (mode_lib->validate_max_state) + start_state = v->soc.num_states - 1; + else + start_state = 0; /*Scale Ratio, taps Support Check*/ @@ -2012,7 +2021,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l mode_lib->vba.MPCCombineMethodIncompatible = v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.MPCCombineMethodAsNeededForPStateChangeAndVoltage && v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.MPCCombineMethodAsPossible; - for (i = 0; i < v->soc.num_states; i++) { + for (i = start_state; i < v->soc.num_states; i++) { for (j = 0; j < 2; j++) { mode_lib->vba.TotalNumberOfActiveDPP[i][j] = 0; mode_lib->vba.TotalAvailablePipesSupport[i][j] = true; @@ -2289,7 +2298,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l } } - for (i = 0; i < v->soc.num_states; ++i) { + for (i = start_state; i < v->soc.num_states; ++i) { mode_lib->vba.ExceededMultistreamSlots[i] = false; for (k = 0; k < mode_lib->vba.NumberOfActiveSurfaces; ++k) { if (mode_lib->vba.OutputMultistreamEn[k] == true && mode_lib->vba.OutputMultistreamId[k] == k) { @@ -2389,7 +2398,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l } } - for (i = 0; i < v->soc.num_states; ++i) { + for (i = start_state; i < v->soc.num_states; ++i) { mode_lib->vba.DTBCLKRequiredMoreThanSupported[i] = false; for (k = 0; k < mode_lib->vba.NumberOfActiveSurfaces; ++k) { if (mode_lib->vba.BlendingAndTiming[k] == k @@ -2406,7 +2415,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l } } - for (i = 0; i < v->soc.num_states; ++i) { + for (i = start_state; i < v->soc.num_states; ++i) { mode_lib->vba.ODMCombine2To1SupportCheckOK[i] = true; mode_lib->vba.ODMCombine4To1SupportCheckOK[i] = true; for (k = 0; k < mode_lib->vba.NumberOfActiveSurfaces; ++k) { @@ -2424,7 +2433,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l } } - for (i = 0; i < v->soc.num_states; i++) { + for (i = start_state; i < v->soc.num_states; i++) { mode_lib->vba.DSCCLKRequiredMoreThanSupported[i] = false; for (k = 0; k <= mode_lib->vba.NumberOfActiveSurfaces - 1; k++) { if (mode_lib->vba.BlendingAndTiming[k] == k) { @@ -2461,7 +2470,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l /* Check DSC Unit and Slices Support */ v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.TotalDSCUnitsRequired = 0; - for (i = 0; i < v->soc.num_states; ++i) { + for (i = start_state; i < v->soc.num_states; ++i) { mode_lib->vba.NotEnoughDSCUnits[i] = false; mode_lib->vba.NotEnoughDSCSlices[i] = false; v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.TotalDSCUnitsRequired = 0; @@ -2496,7 +2505,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l } /*DSC Delay per state*/ - for (i = 0; i < v->soc.num_states; ++i) { + for (i = start_state; i < v->soc.num_states; ++i) { for (k = 0; k < mode_lib->vba.NumberOfActiveSurfaces; ++k) { mode_lib->vba.DSCDelayPerState[i][k] = dml32_DSCDelayRequirement( mode_lib->vba.RequiresDSC[i][k], mode_lib->vba.ODMCombineEnablePerState[i][k], @@ -2523,7 +2532,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l //Calculate Swath, DET Configuration, DCFCLKDeepSleep // - for (i = 0; i < (int) v->soc.num_states; ++i) { + for (i = start_state; i < (int) v->soc.num_states; ++i) { for (j = 0; j <= 1; ++j) { for (k = 0; k < mode_lib->vba.NumberOfActiveSurfaces; ++k) { mode_lib->vba.RequiredDPPCLKThisState[k] = mode_lib->vba.RequiredDPPCLK[i][j][k]; @@ -2661,7 +2670,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l mode_lib->vba.SurfaceSizeInMALL, &mode_lib->vba.ExceededMALLSize); - for (i = 0; i < v->soc.num_states; i++) { + for (i = start_state; i < v->soc.num_states; i++) { for (j = 0; j < 2; j++) { for (k = 0; k <= mode_lib->vba.NumberOfActiveSurfaces - 1; k++) { mode_lib->vba.swath_width_luma_ub_this_state[k] = @@ -2888,7 +2897,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l } //Calculate Return BW - for (i = 0; i < (int) v->soc.num_states; ++i) { + for (i = start_state; i < (int) v->soc.num_states; ++i) { for (j = 0; j <= 1; ++j) { for (k = 0; k <= mode_lib->vba.NumberOfActiveSurfaces - 1; k++) { if (mode_lib->vba.BlendingAndTiming[k] == k) { @@ -2967,7 +2976,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l &mode_lib->vba.MinPrefetchMode, &mode_lib->vba.MaxPrefetchMode); - for (i = 0; i < (int) v->soc.num_states; ++i) { + for (i = start_state; i < (int) v->soc.num_states; ++i) { for (j = 0; j <= 1; ++j) mode_lib->vba.DCFCLKState[i][j] = mode_lib->vba.DCFCLKPerState[i]; } @@ -3089,7 +3098,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l mode_lib->vba.DCFCLKState); } // UseMinimumRequiredDCFCLK == true - for (i = 0; i < (int) v->soc.num_states; ++i) { + for (i = start_state; i < (int) v->soc.num_states; ++i) { for (j = 0; j <= 1; ++j) { mode_lib->vba.ReturnBWPerState[i][j] = dml32_get_return_bw_mbps(&mode_lib->vba.soc, i, mode_lib->vba.HostVMEnable, mode_lib->vba.DCFCLKState[i][j], @@ -3098,7 +3107,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l } //Re-ordering Buffer Support Check - for (i = 0; i < (int) v->soc.num_states; ++i) { + for (i = start_state; i < (int) v->soc.num_states; ++i) { for (j = 0; j <= 1; ++j) { if ((mode_lib->vba.ROBBufferSizeInKByte - mode_lib->vba.PixelChunkSizeInKByte) * 1024 / mode_lib->vba.ReturnBWPerState[i][j] @@ -3120,7 +3129,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l + mode_lib->vba.ReadBandwidthChroma[k]; } - for (i = 0; i < (int) v->soc.num_states; ++i) { + for (i = start_state; i < (int) v->soc.num_states; ++i) { for (j = 0; j <= 1; ++j) { mode_lib->vba.MaxTotalVerticalActiveAvailableBandwidth[i][j] = dml_min3(mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLKState[i][j] @@ -3144,7 +3153,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l /* Prefetch Check */ - for (i = 0; i < (int) v->soc.num_states; ++i) { + for (i = start_state; i < (int) v->soc.num_states; ++i) { for (j = 0; j <= 1; ++j) { mode_lib->vba.TimeCalc = 24 / mode_lib->vba.ProjectedDCFCLKDeepSleep[i][j]; @@ -3662,7 +3671,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l MaximumMPCCombine = 0; - for (i = v->soc.num_states; i >= 0; i--) { + for (i = v->soc.num_states; i >= start_state; i--) { if (i == v->soc.num_states || mode_lib->vba.ModeSupport[i][0] == true || mode_lib->vba.ModeSupport[i][1] == true) { mode_lib->vba.VoltageLevel = i; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c index 0ea406145c1d..b80cef70fa60 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c @@ -534,8 +534,11 @@ void dcn321_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p } /* Override from VBIOS for num_chan */ - if (dc->ctx->dc_bios->vram_info.num_chans) + if (dc->ctx->dc_bios->vram_info.num_chans) { dcn3_21_soc.num_chans = dc->ctx->dc_bios->vram_info.num_chans; + dcn3_21_soc.mall_allocated_for_dcn_mbytes = (double)(dcn32_calc_num_avail_chans_for_mall(dc, + dc->ctx->dc_bios->vram_info.num_chans) * dc->caps.mall_size_per_mem_channel); + } if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes) dcn3_21_soc.dram_channel_width_bytes = dc->ctx->dc_bios->vram_info.dram_channel_width_bytes; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h index 3d643d50c3eb..a9d49ef58fb5 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h @@ -91,6 +91,7 @@ struct display_mode_lib { struct dal_logger *logger; struct dml_funcs funcs; struct _vcs_dpi_display_e2e_pipe_params_st dml_pipe_state[6]; + bool validate_max_state; }; void dml_init_instance(struct display_mode_lib *lib, diff --git a/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c b/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c index 906a43e85f6d..e1422e5e86c9 100644 --- a/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c +++ b/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c @@ -32,7 +32,7 @@ #include "core_types.h" #include "link.h" #include "link_hwss.h" -#include "link/link_dpcd.h" +#include "link/protocols/link_dpcd.h" #define DC_LOGGER \ link->ctx->logger diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h deleted file mode 100644 index 52e1aad1fce8..000000000000 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2015 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_LINK_DP_H__ -#define __DC_LINK_DP_H__ - -#define LINK_TRAINING_ATTEMPTS 4 -#define LINK_TRAINING_RETRY_DELAY 50 /* ms */ -#define MAX_MTP_SLOT_COUNT 64 -#define TRAINING_AUX_RD_INTERVAL 100 //us -#define LINK_AUX_WAKE_TIMEOUT_MS 1500 // Timeout when trying to wake unresponsive DPRX. - -struct dc_link; -struct dc_stream_state; -struct dc_link_settings; - -enum { - /* - * Some receivers fail to train on first try and are good - * on subsequent tries. 2 retries should be plenty. If we - * don't have a successful training then we don't expect to - * ever get one. - */ - LINK_TRAINING_MAX_VERIFY_RETRY = 2, - PEAK_FACTOR_X1000 = 1006, -}; - - -bool dp_verify_link_cap_with_retries( - struct dc_link *link, - struct dc_link_settings *known_limit_link_setting, - int attempts); - -bool dp_validate_mode_timing( - struct dc_link *link, - const struct dc_crtc_timing *timing); - -bool hpd_rx_irq_check_link_loss_status(struct dc_link *link, - union hpd_irq_data *hpd_irq_dpcd_data); -enum dc_status read_hpd_rx_irq_data( - struct dc_link *link, - union hpd_irq_data *irq_data); - -bool is_edp_ilr_optimization_required(struct dc_link *link, struct dc_crtc_timing *crtc_timing); - -void dp_enable_mst_on_sink(struct dc_link *link, bool enable); - -enum dp_panel_mode dp_get_panel_mode(struct dc_link *link); -void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode); - -void dpcd_write_cable_id_to_dprx(struct dc_link *link); - -enum dc_status dp_set_fec_ready(struct dc_link *link, const struct link_resource *link_res, bool ready); -void dp_set_fec_enable(struct dc_link *link, bool enable); -bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable); -bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable, bool immediate_update); -void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable); -bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx); -bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable); - -/* Initialize output parameter lt_settings. */ -void dp_decide_training_settings( - struct dc_link *link, - const struct dc_link_settings *link_setting, - struct link_training_settings *lt_settings); - -bool dpcd_write_128b_132b_sst_payload_allocation_table( - const struct dc_stream_state *stream, - struct dc_link *link, - struct link_mst_stream_allocation_table *proposed_table, - bool allocate); - -bool dpcd_poll_for_allocation_change_trigger(struct dc_link *link); - -struct fixed31_32 calculate_sst_avg_time_slots_per_mtp( - const struct dc_stream_state *stream, - const struct dc_link *link); -void enable_dp_hpo_output(struct dc_link *link, - const struct link_resource *link_res, - const struct dc_link_settings *link_settings); -void disable_dp_hpo_output(struct dc_link *link, - const struct link_resource *link_res, - enum signal_type signal); -void setup_dp_hpo_stream(struct pipe_ctx *pipe_ctx, bool enable); -void edp_panel_backlight_power_on(struct dc_link *link, bool wait_for_hpd); -void dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode); -void edp_add_delay_for_T9(struct dc_link *link); -bool edp_receiver_ready_T9(struct dc_link *link); -bool edp_receiver_ready_T7(struct dc_link *link); - -void dp_retrain_link_dp_test(struct dc_link *link, - struct dc_link_settings *link_setting, - bool skip_video_pattern); - -#endif /* __DC_LINK_DP_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index 42db4b7b79fd..bb5ad70d4266 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -72,6 +72,12 @@ enum dynamic_metadata_mode { dmdata_dolby_vision }; +struct enc_sdp_line_num { + /* Adaptive Sync SDP */ + bool adaptive_sync_line_num_valid; + uint32_t adaptive_sync_line_num; +}; + struct encoder_info_frame { /* auxiliary video information */ struct dc_info_packet avi; @@ -85,6 +91,9 @@ struct encoder_info_frame { struct dc_info_packet vsc; /* HDR Static MetaData */ struct dc_info_packet hdrsmd; + /* Adaptive Sync SDP*/ + struct dc_info_packet adaptive_sync; + struct enc_sdp_line_num sdp_line_num; }; struct encoder_unblank_param { @@ -154,6 +163,10 @@ struct stream_encoder_funcs { void (*stop_hdmi_info_packets)( struct stream_encoder *enc); + void (*update_dp_info_packets_sdp_line_num)( + struct stream_encoder *enc, + struct encoder_info_frame *info_frame); + void (*update_dp_info_packets)( struct stream_encoder *enc, const struct encoder_info_frame *info_frame); @@ -302,6 +315,10 @@ struct hpo_dp_stream_encoder_funcs { bool compressed_format, bool double_buffer_en); + void (*update_dp_info_packets_sdp_line_num)( + struct hpo_dp_stream_encoder *enc, + struct encoder_info_frame *info_frame); + void (*update_dp_info_packets)( struct hpo_dp_stream_encoder *enc, const struct encoder_info_frame *info_frame); diff --git a/drivers/gpu/drm/amd/display/dc/inc/link.h b/drivers/gpu/drm/amd/display/dc/inc/link.h index 3945522fb798..d4cebf49e5d4 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link.h @@ -89,4 +89,21 @@ bool link_decide_link_settings( struct dc_stream_state *stream, struct dc_link_settings *link_setting); +void link_dp_trace_set_edp_power_timestamp(struct dc_link *link, + bool power_up); +uint64_t link_dp_trace_get_edp_poweron_timestamp(struct dc_link *link); +uint64_t link_dp_trace_get_edp_poweroff_timestamp(struct dc_link *link); + +bool link_is_edp_ilr_optimization_required(struct dc_link *link, + struct dc_crtc_timing *crtc_timing); + +bool link_backlight_enable_aux(struct dc_link *link, bool enable); +void link_edp_add_delay_for_T9(struct dc_link *link); +bool link_edp_receiver_ready_T9(struct dc_link *link); +bool link_edp_receiver_ready_T7(struct dc_link *link); +bool link_power_alpm_dpcd_enable(struct dc_link *link, bool enable); +bool link_set_sink_vtotal_in_psr_active(const struct dc_link *link, + uint16_t psr_vtotal_idle, uint16_t psr_vtotal_su); +void link_get_psr_residency(const struct dc_link *link, uint32_t *residency); + #endif /* __DC_LINK_HPD_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/Makefile b/drivers/gpu/drm/amd/display/dc/link/Makefile index 4dee0e6248b1..0f642cbac3d5 100644 --- a/drivers/gpu/drm/amd/display/dc/link/Makefile +++ b/drivers/gpu/drm/amd/display/dc/link/Makefile @@ -23,12 +23,34 @@ # It abstracts the control and status of back end pipe such as DIO, HPO, DPIA, # PHY, HPD, DDC and etc). -LINK = link_hwss_dio.o link_hwss_dpia.o link_hwss_hpo_dp.o link_dp_trace.o \ -link_hpd.o link_ddc.o link_dpcd.o link_dp_dpia.o link_dp_training.o \ -link_dp_training_8b_10b.o link_dp_training_128b_132b.o link_dp_training_dpia.o \ -link_dp_training_auxless.o link_dp_training_fixed_vs_pe_retimer.o link_dp_phy.o \ -link_dp_capability.o +############################################################################### +# accessories +############################################################################### +LINK_ACCESSORIES = link_dp_trace.o link_dp_cts.o -AMD_DAL_LINK = $(addprefix $(AMDDALPATH)/dc/link/,$(LINK)) +AMD_DAL_LINK_ACCESSORIES = $(addprefix $(AMDDALPATH)/dc/link/accessories/, \ +$(LINK_ACCESSORIES)) -AMD_DISPLAY_FILES += $(AMD_DAL_LINK) +AMD_DISPLAY_FILES += $(AMD_DAL_LINK_ACCESSORIES) +############################################################################### +# hwss +############################################################################### +LINK_HWSS = link_hwss_dio.o link_hwss_dpia.o link_hwss_hpo_dp.o + +AMD_DAL_LINK_HWSS = $(addprefix $(AMDDALPATH)/dc/link/hwss/, \ +$(LINK_HWSS)) + +AMD_DISPLAY_FILES += $(AMD_DAL_LINK_HWSS) +############################################################################### +# protocols +############################################################################### +LINK_PROTOCOLS = link_hpd.o link_ddc.o link_dpcd.o link_dp_dpia.o \ +link_dp_training.o link_dp_training_8b_10b.o link_dp_training_128b_132b.o \ +link_dp_training_dpia.o link_dp_training_auxless.o \ +link_dp_training_fixed_vs_pe_retimer.o link_dp_phy.o link_dp_capability.o \ +link_edp_panel_control.o link_dp_irq_handler.o + +AMD_DAL_LINK_PROTOCOLS = $(addprefix $(AMDDALPATH)/dc/link/protocols/, \ +$(LINK_PROTOCOLS)) + +AMD_DISPLAY_FILES += $(AMD_DAL_LINK_PROTOCOLS)
\ No newline at end of file diff --git a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c new file mode 100644 index 000000000000..7fb2c0b4c4bb --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c @@ -0,0 +1,1055 @@ +/* + * Copyright 2022 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "link_dp_cts.h" +#include "link/protocols/link_dpcd.h" +#include "link/protocols/link_dp_training.h" +#include "link/protocols/link_dp_phy.h" +#include "link/protocols/link_dp_training_fixed_vs_pe_retimer.h" +#include "resource.h" +#include "dm_helpers.h" +#include "dc_dmub_srv.h" +#include "dce/dmub_hw_lock_mgr.h" + +#define DC_LOGGER \ + link->ctx->logger + +static enum dc_link_rate get_link_rate_from_test_link_rate(uint8_t test_rate) +{ + switch (test_rate) { + case DP_TEST_LINK_RATE_RBR: + return LINK_RATE_LOW; + case DP_TEST_LINK_RATE_HBR: + return LINK_RATE_HIGH; + case DP_TEST_LINK_RATE_HBR2: + return LINK_RATE_HIGH2; + case DP_TEST_LINK_RATE_HBR3: + return LINK_RATE_HIGH3; + case DP_TEST_LINK_RATE_UHBR10: + return LINK_RATE_UHBR10; + case DP_TEST_LINK_RATE_UHBR20: + return LINK_RATE_UHBR20; + case DP_TEST_LINK_RATE_UHBR13_5: + return LINK_RATE_UHBR13_5; + default: + return LINK_RATE_UNKNOWN; + } +} + +static bool is_dp_phy_sqaure_pattern(enum dp_test_pattern test_pattern) +{ + return (DP_TEST_PATTERN_SQUARE_BEGIN <= test_pattern && + test_pattern <= DP_TEST_PATTERN_SQUARE_END); +} + +static bool is_dp_phy_pattern(enum dp_test_pattern test_pattern) +{ + if ((DP_TEST_PATTERN_PHY_PATTERN_BEGIN <= test_pattern && + test_pattern <= DP_TEST_PATTERN_PHY_PATTERN_END) || + test_pattern == DP_TEST_PATTERN_VIDEO_MODE) + return true; + else + return false; +} + +void dp_retrain_link_dp_test(struct dc_link *link, + struct dc_link_settings *link_setting, + bool skip_video_pattern) +{ + struct pipe_ctx *pipe; + unsigned int i; + + udelay(100); + + for (i = 0; i < MAX_PIPES; i++) { + pipe = &link->dc->current_state->res_ctx.pipe_ctx[i]; + if (pipe->stream != NULL && + pipe->stream->link == link && + !pipe->stream->dpms_off && + !pipe->top_pipe && !pipe->prev_odm_pipe) { + core_link_disable_stream(pipe); + pipe->link_config.dp_link_settings = *link_setting; + update_dp_encoder_resources_for_test_harness( + link->dc, + pipe->stream->ctx->dc->current_state, + pipe); + } + } + + for (i = 0; i < MAX_PIPES; i++) { + pipe = &link->dc->current_state->res_ctx.pipe_ctx[i]; + if (pipe->stream != NULL && + pipe->stream->link == link && + !pipe->stream->dpms_off && + !pipe->top_pipe && !pipe->prev_odm_pipe) { + core_link_enable_stream( + pipe->stream->ctx->dc->current_state, + pipe); + } + } +} + +static void dp_test_send_link_training(struct dc_link *link) +{ + struct dc_link_settings link_settings = {0}; + uint8_t test_rate = 0; + + core_link_read_dpcd( + link, + DP_TEST_LANE_COUNT, + (unsigned char *)(&link_settings.lane_count), + 1); + core_link_read_dpcd( + link, + DP_TEST_LINK_RATE, + &test_rate, + 1); + link_settings.link_rate = get_link_rate_from_test_link_rate(test_rate); + + /* Set preferred link settings */ + link->verified_link_cap.lane_count = link_settings.lane_count; + link->verified_link_cap.link_rate = link_settings.link_rate; + + dp_retrain_link_dp_test(link, &link_settings, false); +} + +static void dp_test_get_audio_test_data(struct dc_link *link, bool disable_video) +{ + union audio_test_mode dpcd_test_mode = {0}; + struct audio_test_pattern_type dpcd_pattern_type = {0}; + union audio_test_pattern_period dpcd_pattern_period[AUDIO_CHANNELS_COUNT] = {0}; + enum dp_test_pattern test_pattern = DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED; + + struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx; + struct pipe_ctx *pipe_ctx = &pipes[0]; + unsigned int channel_count; + unsigned int channel = 0; + unsigned int modes = 0; + unsigned int sampling_rate_in_hz = 0; + + // get audio test mode and test pattern parameters + core_link_read_dpcd( + link, + DP_TEST_AUDIO_MODE, + &dpcd_test_mode.raw, + sizeof(dpcd_test_mode)); + + core_link_read_dpcd( + link, + DP_TEST_AUDIO_PATTERN_TYPE, + &dpcd_pattern_type.value, + sizeof(dpcd_pattern_type)); + + channel_count = min(dpcd_test_mode.bits.channel_count + 1, AUDIO_CHANNELS_COUNT); + + // read pattern periods for requested channels when sawTooth pattern is requested + if (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH || + dpcd_pattern_type.value == AUDIO_TEST_PATTERN_OPERATOR_DEFINED) { + + test_pattern = (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH) ? + DP_TEST_PATTERN_AUDIO_SAWTOOTH : DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED; + // read period for each channel + for (channel = 0; channel < channel_count; channel++) { + core_link_read_dpcd( + link, + DP_TEST_AUDIO_PERIOD_CH1 + channel, + &dpcd_pattern_period[channel].raw, + sizeof(dpcd_pattern_period[channel])); + } + } + + // translate sampling rate + switch (dpcd_test_mode.bits.sampling_rate) { + case AUDIO_SAMPLING_RATE_32KHZ: + sampling_rate_in_hz = 32000; + break; + case AUDIO_SAMPLING_RATE_44_1KHZ: + sampling_rate_in_hz = 44100; + break; + case AUDIO_SAMPLING_RATE_48KHZ: + sampling_rate_in_hz = 48000; + break; + case AUDIO_SAMPLING_RATE_88_2KHZ: + sampling_rate_in_hz = 88200; + break; + case AUDIO_SAMPLING_RATE_96KHZ: + sampling_rate_in_hz = 96000; + break; + case AUDIO_SAMPLING_RATE_176_4KHZ: + sampling_rate_in_hz = 176400; + break; + case AUDIO_SAMPLING_RATE_192KHZ: + sampling_rate_in_hz = 192000; + break; + default: + sampling_rate_in_hz = 0; + break; + } + + link->audio_test_data.flags.test_requested = 1; + link->audio_test_data.flags.disable_video = disable_video; + link->audio_test_data.sampling_rate = sampling_rate_in_hz; + link->audio_test_data.channel_count = channel_count; + link->audio_test_data.pattern_type = test_pattern; + + if (test_pattern == DP_TEST_PATTERN_AUDIO_SAWTOOTH) { + for (modes = 0; modes < pipe_ctx->stream->audio_info.mode_count; modes++) { + link->audio_test_data.pattern_period[modes] = dpcd_pattern_period[modes].bits.pattern_period; + } + } +} + +/* TODO Raven hbr2 compliance eye output is unstable + * (toggling on and off) with debugger break + * This caueses intermittent PHY automation failure + * Need to look into the root cause */ +static void dp_test_send_phy_test_pattern(struct dc_link *link) +{ + union phy_test_pattern dpcd_test_pattern; + union lane_adjust dpcd_lane_adjustment[2]; + unsigned char dpcd_post_cursor_2_adjustment = 0; + unsigned char test_pattern_buffer[ + (DP_TEST_264BIT_CUSTOM_PATTERN_263_256 - + DP_TEST_264BIT_CUSTOM_PATTERN_7_0)+1] = {0}; + unsigned int test_pattern_size = 0; + enum dp_test_pattern test_pattern; + union lane_adjust dpcd_lane_adjust; + unsigned int lane; + struct link_training_settings link_training_settings; + unsigned char no_preshoot = 0; + unsigned char no_deemphasis = 0; + + dpcd_test_pattern.raw = 0; + memset(dpcd_lane_adjustment, 0, sizeof(dpcd_lane_adjustment)); + memset(&link_training_settings, 0, sizeof(link_training_settings)); + + /* get phy test pattern and pattern parameters from DP receiver */ + core_link_read_dpcd( + link, + DP_PHY_TEST_PATTERN, + &dpcd_test_pattern.raw, + sizeof(dpcd_test_pattern)); + core_link_read_dpcd( + link, + DP_ADJUST_REQUEST_LANE0_1, + &dpcd_lane_adjustment[0].raw, + sizeof(dpcd_lane_adjustment)); + + /* prepare link training settings */ + link_training_settings.link_settings = link->cur_link_settings; + + link_training_settings.lttpr_mode = dc_link_decide_lttpr_mode(link, &link->cur_link_settings); + + if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && + link_training_settings.lttpr_mode == LTTPR_MODE_TRANSPARENT) + dp_fixed_vs_pe_read_lane_adjust( + link, + link_training_settings.dpcd_lane_settings); + + /*get post cursor 2 parameters + * For DP 1.1a or eariler, this DPCD register's value is 0 + * For DP 1.2 or later: + * Bits 1:0 = POST_CURSOR2_LANE0; Bits 3:2 = POST_CURSOR2_LANE1 + * Bits 5:4 = POST_CURSOR2_LANE2; Bits 7:6 = POST_CURSOR2_LANE3 + */ + core_link_read_dpcd( + link, + DP_ADJUST_REQUEST_POST_CURSOR2, + &dpcd_post_cursor_2_adjustment, + sizeof(dpcd_post_cursor_2_adjustment)); + + /* translate request */ + switch (dpcd_test_pattern.bits.PATTERN) { + case PHY_TEST_PATTERN_D10_2: + test_pattern = DP_TEST_PATTERN_D102; + break; + case PHY_TEST_PATTERN_SYMBOL_ERROR: + test_pattern = DP_TEST_PATTERN_SYMBOL_ERROR; + break; + case PHY_TEST_PATTERN_PRBS7: + test_pattern = DP_TEST_PATTERN_PRBS7; + break; + case PHY_TEST_PATTERN_80BIT_CUSTOM: + test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM; + break; + case PHY_TEST_PATTERN_CP2520_1: + /* CP2520 pattern is unstable, temporarily use TPS4 instead */ + test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ? + DP_TEST_PATTERN_TRAINING_PATTERN4 : + DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE; + break; + case PHY_TEST_PATTERN_CP2520_2: + /* CP2520 pattern is unstable, temporarily use TPS4 instead */ + test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ? + DP_TEST_PATTERN_TRAINING_PATTERN4 : + DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE; + break; + case PHY_TEST_PATTERN_CP2520_3: + test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4; + break; + case PHY_TEST_PATTERN_128b_132b_TPS1: + test_pattern = DP_TEST_PATTERN_128b_132b_TPS1; + break; + case PHY_TEST_PATTERN_128b_132b_TPS2: + test_pattern = DP_TEST_PATTERN_128b_132b_TPS2; + break; + case PHY_TEST_PATTERN_PRBS9: + test_pattern = DP_TEST_PATTERN_PRBS9; + break; + case PHY_TEST_PATTERN_PRBS11: + test_pattern = DP_TEST_PATTERN_PRBS11; + break; + case PHY_TEST_PATTERN_PRBS15: + test_pattern = DP_TEST_PATTERN_PRBS15; + break; + case PHY_TEST_PATTERN_PRBS23: + test_pattern = DP_TEST_PATTERN_PRBS23; + break; + case PHY_TEST_PATTERN_PRBS31: + test_pattern = DP_TEST_PATTERN_PRBS31; + break; + case PHY_TEST_PATTERN_264BIT_CUSTOM: + test_pattern = DP_TEST_PATTERN_264BIT_CUSTOM; + break; + case PHY_TEST_PATTERN_SQUARE: + test_pattern = DP_TEST_PATTERN_SQUARE; + break; + case PHY_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED: + test_pattern = DP_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED; + no_preshoot = 1; + break; + case PHY_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED: + test_pattern = DP_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED; + no_deemphasis = 1; + break; + case PHY_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED: + test_pattern = DP_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED; + no_preshoot = 1; + no_deemphasis = 1; + break; + default: + test_pattern = DP_TEST_PATTERN_VIDEO_MODE; + break; + } + + if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM) { + test_pattern_size = (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 - + DP_TEST_80BIT_CUSTOM_PATTERN_7_0) + 1; + core_link_read_dpcd( + link, + DP_TEST_80BIT_CUSTOM_PATTERN_7_0, + test_pattern_buffer, + test_pattern_size); + } + + if (is_dp_phy_sqaure_pattern(test_pattern)) { + test_pattern_size = 1; // Square pattern data is 1 byte (DP spec) + core_link_read_dpcd( + link, + DP_PHY_SQUARE_PATTERN, + test_pattern_buffer, + test_pattern_size); + } + + if (test_pattern == DP_TEST_PATTERN_264BIT_CUSTOM) { + test_pattern_size = (DP_TEST_264BIT_CUSTOM_PATTERN_263_256- + DP_TEST_264BIT_CUSTOM_PATTERN_7_0) + 1; + core_link_read_dpcd( + link, + DP_TEST_264BIT_CUSTOM_PATTERN_7_0, + test_pattern_buffer, + test_pattern_size); + } + + for (lane = 0; lane < + (unsigned int)(link->cur_link_settings.lane_count); + lane++) { + dpcd_lane_adjust.raw = + dp_get_nibble_at_index(&dpcd_lane_adjustment[0].raw, lane); + if (link_dp_get_encoding_format(&link->cur_link_settings) == + DP_8b_10b_ENCODING) { + link_training_settings.hw_lane_settings[lane].VOLTAGE_SWING = + (enum dc_voltage_swing) + (dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE); + link_training_settings.hw_lane_settings[lane].PRE_EMPHASIS = + (enum dc_pre_emphasis) + (dpcd_lane_adjust.bits.PRE_EMPHASIS_LANE); + link_training_settings.hw_lane_settings[lane].POST_CURSOR2 = + (enum dc_post_cursor2) + ((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03); + } else if (link_dp_get_encoding_format(&link->cur_link_settings) == + DP_128b_132b_ENCODING) { + link_training_settings.hw_lane_settings[lane].FFE_PRESET.settings.level = + dpcd_lane_adjust.tx_ffe.PRESET_VALUE; + link_training_settings.hw_lane_settings[lane].FFE_PRESET.settings.no_preshoot = no_preshoot; + link_training_settings.hw_lane_settings[lane].FFE_PRESET.settings.no_deemphasis = no_deemphasis; + } + } + + dp_hw_to_dpcd_lane_settings(&link_training_settings, + link_training_settings.hw_lane_settings, + link_training_settings.dpcd_lane_settings); + /*Usage: Measure DP physical lane signal + * by DP SI test equipment automatically. + * PHY test pattern request is generated by equipment via HPD interrupt. + * HPD needs to be active all the time. HPD should be active + * all the time. Do not touch it. + * forward request to DS + */ + dc_link_dp_set_test_pattern( + link, + test_pattern, + DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED, + &link_training_settings, + test_pattern_buffer, + test_pattern_size); +} + +static void set_crtc_test_pattern(struct dc_link *link, + struct pipe_ctx *pipe_ctx, + enum dp_test_pattern test_pattern, + enum dp_test_pattern_color_space test_pattern_color_space) +{ + enum controller_dp_test_pattern controller_test_pattern; + enum dc_color_depth color_depth = pipe_ctx-> + stream->timing.display_color_depth; + struct bit_depth_reduction_params params; + struct output_pixel_processor *opp = pipe_ctx->stream_res.opp; + int width = pipe_ctx->stream->timing.h_addressable + + pipe_ctx->stream->timing.h_border_left + + pipe_ctx->stream->timing.h_border_right; + int height = pipe_ctx->stream->timing.v_addressable + + pipe_ctx->stream->timing.v_border_bottom + + pipe_ctx->stream->timing.v_border_top; + + memset(¶ms, 0, sizeof(params)); + + switch (test_pattern) { + case DP_TEST_PATTERN_COLOR_SQUARES: + controller_test_pattern = + CONTROLLER_DP_TEST_PATTERN_COLORSQUARES; + break; + case DP_TEST_PATTERN_COLOR_SQUARES_CEA: + controller_test_pattern = + CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA; + break; + case DP_TEST_PATTERN_VERTICAL_BARS: + controller_test_pattern = + CONTROLLER_DP_TEST_PATTERN_VERTICALBARS; + break; + case DP_TEST_PATTERN_HORIZONTAL_BARS: + controller_test_pattern = + CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS; + break; + case DP_TEST_PATTERN_COLOR_RAMP: + controller_test_pattern = + CONTROLLER_DP_TEST_PATTERN_COLORRAMP; + break; + default: + controller_test_pattern = + CONTROLLER_DP_TEST_PATTERN_VIDEOMODE; + break; + } + + switch (test_pattern) { + case DP_TEST_PATTERN_COLOR_SQUARES: + case DP_TEST_PATTERN_COLOR_SQUARES_CEA: + case DP_TEST_PATTERN_VERTICAL_BARS: + case DP_TEST_PATTERN_HORIZONTAL_BARS: + case DP_TEST_PATTERN_COLOR_RAMP: + { + /* disable bit depth reduction */ + pipe_ctx->stream->bit_depth_params = params; + opp->funcs->opp_program_bit_depth_reduction(opp, ¶ms); + if (pipe_ctx->stream_res.tg->funcs->set_test_pattern) + pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg, + controller_test_pattern, color_depth); + else if (link->dc->hwss.set_disp_pattern_generator) { + struct pipe_ctx *odm_pipe; + enum controller_dp_color_space controller_color_space; + int opp_cnt = 1; + int offset = 0; + int dpg_width = width; + + switch (test_pattern_color_space) { + case DP_TEST_PATTERN_COLOR_SPACE_RGB: + controller_color_space = CONTROLLER_DP_COLOR_SPACE_RGB; + break; + case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601: + controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR601; + break; + case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709: + controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR709; + break; + case DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED: + default: + controller_color_space = CONTROLLER_DP_COLOR_SPACE_UDEFINED; + DC_LOG_ERROR("%s: Color space must be defined for test pattern", __func__); + ASSERT(0); + break; + } + + for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) + opp_cnt++; + dpg_width = width / opp_cnt; + offset = dpg_width; + + link->dc->hwss.set_disp_pattern_generator(link->dc, + pipe_ctx, + controller_test_pattern, + controller_color_space, + color_depth, + NULL, + dpg_width, + height, + 0); + + for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) { + struct output_pixel_processor *odm_opp = odm_pipe->stream_res.opp; + + odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, ¶ms); + link->dc->hwss.set_disp_pattern_generator(link->dc, + odm_pipe, + controller_test_pattern, + controller_color_space, + color_depth, + NULL, + dpg_width, + height, + offset); + offset += offset; + } + } + } + break; + case DP_TEST_PATTERN_VIDEO_MODE: + { + /* restore bitdepth reduction */ + resource_build_bit_depth_reduction_params(pipe_ctx->stream, ¶ms); + pipe_ctx->stream->bit_depth_params = params; + opp->funcs->opp_program_bit_depth_reduction(opp, ¶ms); + if (pipe_ctx->stream_res.tg->funcs->set_test_pattern) + pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg, + CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, + color_depth); + else if (link->dc->hwss.set_disp_pattern_generator) { + struct pipe_ctx *odm_pipe; + int opp_cnt = 1; + int dpg_width; + + for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) + opp_cnt++; + + dpg_width = width / opp_cnt; + for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) { + struct output_pixel_processor *odm_opp = odm_pipe->stream_res.opp; + + odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, ¶ms); + link->dc->hwss.set_disp_pattern_generator(link->dc, + odm_pipe, + CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, + CONTROLLER_DP_COLOR_SPACE_UDEFINED, + color_depth, + NULL, + dpg_width, + height, + 0); + } + link->dc->hwss.set_disp_pattern_generator(link->dc, + pipe_ctx, + CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, + CONTROLLER_DP_COLOR_SPACE_UDEFINED, + color_depth, + NULL, + dpg_width, + height, + 0); + } + } + break; + + default: + break; + } +} + +void dc_link_dp_handle_automated_test(struct dc_link *link) +{ + union test_request test_request; + union test_response test_response; + + memset(&test_request, 0, sizeof(test_request)); + memset(&test_response, 0, sizeof(test_response)); + + core_link_read_dpcd( + link, + DP_TEST_REQUEST, + &test_request.raw, + sizeof(union test_request)); + if (test_request.bits.LINK_TRAINING) { + /* ACK first to let DP RX test box monitor LT sequence */ + test_response.bits.ACK = 1; + core_link_write_dpcd( + link, + DP_TEST_RESPONSE, + &test_response.raw, + sizeof(test_response)); + dp_test_send_link_training(link); + /* no acknowledge request is needed again */ + test_response.bits.ACK = 0; + } + if (test_request.bits.LINK_TEST_PATTRN) { + union test_misc dpcd_test_params; + union link_test_pattern dpcd_test_pattern; + + memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern)); + memset(&dpcd_test_params, 0, sizeof(dpcd_test_params)); + + /* get link test pattern and pattern parameters */ + core_link_read_dpcd( + link, + DP_TEST_PATTERN, + &dpcd_test_pattern.raw, + sizeof(dpcd_test_pattern)); + core_link_read_dpcd( + link, + DP_TEST_MISC0, + &dpcd_test_params.raw, + sizeof(dpcd_test_params)); + test_response.bits.ACK = dm_helpers_dp_handle_test_pattern_request(link->ctx, link, + dpcd_test_pattern, dpcd_test_params) ? 1 : 0; + } + + if (test_request.bits.AUDIO_TEST_PATTERN) { + dp_test_get_audio_test_data(link, test_request.bits.TEST_AUDIO_DISABLED_VIDEO); + test_response.bits.ACK = 1; + } + + if (test_request.bits.PHY_TEST_PATTERN) { + dp_test_send_phy_test_pattern(link); + test_response.bits.ACK = 1; + } + + /* send request acknowledgment */ + if (test_response.bits.ACK) + core_link_write_dpcd( + link, + DP_TEST_RESPONSE, + &test_response.raw, + sizeof(test_response)); +} + +bool dc_link_dp_set_test_pattern( + struct dc_link *link, + enum dp_test_pattern test_pattern, + enum dp_test_pattern_color_space test_pattern_color_space, + const struct link_training_settings *p_link_settings, + const unsigned char *p_custom_pattern, + unsigned int cust_pattern_size) +{ + struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx; + struct pipe_ctx *pipe_ctx = NULL; + unsigned int lane; + unsigned int i; + unsigned char link_qual_pattern[LANE_COUNT_DP_MAX] = {0}; + union dpcd_training_pattern training_pattern; + enum dpcd_phy_test_patterns pattern; + + memset(&training_pattern, 0, sizeof(training_pattern)); + + for (i = 0; i < MAX_PIPES; i++) { + if (pipes[i].stream == NULL) + continue; + + if (pipes[i].stream->link == link && !pipes[i].top_pipe && !pipes[i].prev_odm_pipe) { + pipe_ctx = &pipes[i]; + break; + } + } + + if (pipe_ctx == NULL) + return false; + + /* Reset CRTC Test Pattern if it is currently running and request is VideoMode */ + if (link->test_pattern_enabled && test_pattern == + DP_TEST_PATTERN_VIDEO_MODE) { + /* Set CRTC Test Pattern */ + set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space); + dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern, + (uint8_t *)p_custom_pattern, + (uint32_t)cust_pattern_size); + + /* Unblank Stream */ + link->dc->hwss.unblank_stream( + pipe_ctx, + &link->verified_link_cap); + /* TODO:m_pHwss->MuteAudioEndpoint + * (pPathMode->pDisplayPath, false); + */ + + /* Reset Test Pattern state */ + link->test_pattern_enabled = false; + + return true; + } + + /* Check for PHY Test Patterns */ + if (is_dp_phy_pattern(test_pattern)) { + /* Set DPCD Lane Settings before running test pattern */ + if (p_link_settings != NULL) { + if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && + p_link_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT) { + dp_fixed_vs_pe_set_retimer_lane_settings( + link, + p_link_settings->dpcd_lane_settings, + p_link_settings->link_settings.lane_count); + } else { + dp_set_hw_lane_settings(link, &pipe_ctx->link_res, p_link_settings, DPRX); + } + dpcd_set_lane_settings(link, p_link_settings, DPRX); + } + + /* Blank stream if running test pattern */ + if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) { + /*TODO: + * m_pHwss-> + * MuteAudioEndpoint(pPathMode->pDisplayPath, true); + */ + /* Blank stream */ + link->dc->hwss.blank_stream(pipe_ctx); + } + + dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern, + (uint8_t *)p_custom_pattern, + (uint32_t)cust_pattern_size); + + if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) { + /* Set Test Pattern state */ + link->test_pattern_enabled = true; + if (p_link_settings != NULL) + dpcd_set_link_settings(link, + p_link_settings); + } + + switch (test_pattern) { + case DP_TEST_PATTERN_VIDEO_MODE: + pattern = PHY_TEST_PATTERN_NONE; + break; + case DP_TEST_PATTERN_D102: + pattern = PHY_TEST_PATTERN_D10_2; + break; + case DP_TEST_PATTERN_SYMBOL_ERROR: + pattern = PHY_TEST_PATTERN_SYMBOL_ERROR; + break; + case DP_TEST_PATTERN_PRBS7: + pattern = PHY_TEST_PATTERN_PRBS7; + break; + case DP_TEST_PATTERN_80BIT_CUSTOM: + pattern = PHY_TEST_PATTERN_80BIT_CUSTOM; + break; + case DP_TEST_PATTERN_CP2520_1: + pattern = PHY_TEST_PATTERN_CP2520_1; + break; + case DP_TEST_PATTERN_CP2520_2: + pattern = PHY_TEST_PATTERN_CP2520_2; + break; + case DP_TEST_PATTERN_CP2520_3: + pattern = PHY_TEST_PATTERN_CP2520_3; + break; + case DP_TEST_PATTERN_128b_132b_TPS1: + pattern = PHY_TEST_PATTERN_128b_132b_TPS1; + break; + case DP_TEST_PATTERN_128b_132b_TPS2: + pattern = PHY_TEST_PATTERN_128b_132b_TPS2; + break; + case DP_TEST_PATTERN_PRBS9: + pattern = PHY_TEST_PATTERN_PRBS9; + break; + case DP_TEST_PATTERN_PRBS11: + pattern = PHY_TEST_PATTERN_PRBS11; + break; + case DP_TEST_PATTERN_PRBS15: + pattern = PHY_TEST_PATTERN_PRBS15; + break; + case DP_TEST_PATTERN_PRBS23: + pattern = PHY_TEST_PATTERN_PRBS23; + break; + case DP_TEST_PATTERN_PRBS31: + pattern = PHY_TEST_PATTERN_PRBS31; + break; + case DP_TEST_PATTERN_264BIT_CUSTOM: + pattern = PHY_TEST_PATTERN_264BIT_CUSTOM; + break; + case DP_TEST_PATTERN_SQUARE: + pattern = PHY_TEST_PATTERN_SQUARE; + break; + case DP_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED: + pattern = PHY_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED; + break; + case DP_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED: + pattern = PHY_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED; + break; + case DP_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED: + pattern = PHY_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED; + break; + default: + return false; + } + + if (test_pattern == DP_TEST_PATTERN_VIDEO_MODE + /*TODO:&& !pPathMode->pDisplayPath->IsTargetPoweredOn()*/) + return false; + + if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) { + if (is_dp_phy_sqaure_pattern(test_pattern)) + core_link_write_dpcd(link, + DP_LINK_SQUARE_PATTERN, + p_custom_pattern, + 1); + + /* tell receiver that we are sending qualification + * pattern DP 1.2 or later - DP receiver's link quality + * pattern is set using DPCD LINK_QUAL_LANEx_SET + * register (0x10B~0x10E)\ + */ + for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) + link_qual_pattern[lane] = + (unsigned char)(pattern); + + core_link_write_dpcd(link, + DP_LINK_QUAL_LANE0_SET, + link_qual_pattern, + sizeof(link_qual_pattern)); + } else if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_10 || + link->dpcd_caps.dpcd_rev.raw == 0) { + /* tell receiver that we are sending qualification + * pattern DP 1.1a or earlier - DP receiver's link + * quality pattern is set using + * DPCD TRAINING_PATTERN_SET -> LINK_QUAL_PATTERN_SET + * register (0x102). We will use v_1.3 when we are + * setting test pattern for DP 1.1. + */ + core_link_read_dpcd(link, DP_TRAINING_PATTERN_SET, + &training_pattern.raw, + sizeof(training_pattern)); + training_pattern.v1_3.LINK_QUAL_PATTERN_SET = pattern; + core_link_write_dpcd(link, DP_TRAINING_PATTERN_SET, + &training_pattern.raw, + sizeof(training_pattern)); + } + } else { + enum dc_color_space color_space = COLOR_SPACE_UNKNOWN; + + switch (test_pattern_color_space) { + case DP_TEST_PATTERN_COLOR_SPACE_RGB: + color_space = COLOR_SPACE_SRGB; + if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA) + color_space = COLOR_SPACE_SRGB_LIMITED; + break; + + case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601: + color_space = COLOR_SPACE_YCBCR601; + if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA) + color_space = COLOR_SPACE_YCBCR601_LIMITED; + break; + case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709: + color_space = COLOR_SPACE_YCBCR709; + if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA) + color_space = COLOR_SPACE_YCBCR709_LIMITED; + break; + default: + break; + } + + if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable) { + if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) { + union dmub_hw_lock_flags hw_locks = { 0 }; + struct dmub_hw_lock_inst_flags inst_flags = { 0 }; + + hw_locks.bits.lock_dig = 1; + inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst; + + dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv, + true, + &hw_locks, + &inst_flags); + } else + pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable( + pipe_ctx->stream_res.tg); + } + + pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg); + /* update MSA to requested color space */ + pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute(pipe_ctx->stream_res.stream_enc, + &pipe_ctx->stream->timing, + color_space, + pipe_ctx->stream->use_vsc_sdp_for_colorimetry, + link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP); + + if (pipe_ctx->stream->use_vsc_sdp_for_colorimetry) { + if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA) + pipe_ctx->stream->vsc_infopacket.sb[17] |= (1 << 7); // sb17 bit 7 Dynamic Range: 0 = VESA range, 1 = CTA range + else + pipe_ctx->stream->vsc_infopacket.sb[17] &= ~(1 << 7); + resource_build_info_frame(pipe_ctx); + link->dc->hwss.update_info_frame(pipe_ctx); + } + + /* CRTC Patterns */ + set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space); + pipe_ctx->stream_res.tg->funcs->unlock(pipe_ctx->stream_res.tg); + pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, + CRTC_STATE_VACTIVE); + pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, + CRTC_STATE_VBLANK); + pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, + CRTC_STATE_VACTIVE); + + if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable) { + if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) { + union dmub_hw_lock_flags hw_locks = { 0 }; + struct dmub_hw_lock_inst_flags inst_flags = { 0 }; + + hw_locks.bits.lock_dig = 1; + inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst; + + dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv, + false, + &hw_locks, + &inst_flags); + } else + pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable( + pipe_ctx->stream_res.tg); + } + + /* Set Test Pattern state */ + link->test_pattern_enabled = true; + } + + return true; +} + +void dc_link_set_drive_settings(struct dc *dc, + struct link_training_settings *lt_settings, + const struct dc_link *link) +{ + + int i; + struct link_resource link_res; + + for (i = 0; i < dc->link_count; i++) + if (dc->links[i] == link) + break; + + if (i >= dc->link_count) + ASSERT_CRITICAL(false); + + dc_link_get_cur_link_res(link, &link_res); + dp_set_drive_settings(dc->links[i], &link_res, lt_settings); +} + +void dc_link_set_preferred_link_settings(struct dc *dc, + struct dc_link_settings *link_setting, + struct dc_link *link) +{ + int i; + struct pipe_ctx *pipe; + struct dc_stream_state *link_stream; + struct dc_link_settings store_settings = *link_setting; + + link->preferred_link_setting = store_settings; + + /* Retrain with preferred link settings only relevant for + * DP signal type + * Check for non-DP signal or if passive dongle present + */ + if (!dc_is_dp_signal(link->connector_signal) || + link->dongle_max_pix_clk > 0) + return; + + for (i = 0; i < MAX_PIPES; i++) { + pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + if (pipe->stream && pipe->stream->link) { + if (pipe->stream->link == link) { + link_stream = pipe->stream; + break; + } + } + } + + /* Stream not found */ + if (i == MAX_PIPES) + return; + + /* Cannot retrain link if backend is off */ + if (link_stream->dpms_off) + return; + + if (link_decide_link_settings(link_stream, &store_settings)) + dp_retrain_link_dp_test(link, &store_settings, false); +} + +void dc_link_set_preferred_training_settings(struct dc *dc, + struct dc_link_settings *link_setting, + struct dc_link_training_overrides *lt_overrides, + struct dc_link *link, + bool skip_immediate_retrain) +{ + if (lt_overrides != NULL) + link->preferred_training_settings = *lt_overrides; + else + memset(&link->preferred_training_settings, 0, sizeof(link->preferred_training_settings)); + + if (link_setting != NULL) { + link->preferred_link_setting = *link_setting; + } else { + link->preferred_link_setting.lane_count = LANE_COUNT_UNKNOWN; + link->preferred_link_setting.link_rate = LINK_RATE_UNKNOWN; + } + + if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT && + link->type == dc_connection_mst_branch) + dm_helpers_dp_mst_update_branch_bandwidth(dc->ctx, link); + + /* Retrain now, or wait until next stream update to apply */ + if (skip_immediate_retrain == false) + dc_link_set_preferred_link_settings(dc, &link->preferred_link_setting, link); +} + +void dc_link_set_test_pattern(struct dc_link *link, + enum dp_test_pattern test_pattern, + enum dp_test_pattern_color_space test_pattern_color_space, + const struct link_training_settings *p_link_settings, + const unsigned char *p_custom_pattern, + unsigned int cust_pattern_size) +{ + if (link != NULL) + dc_link_dp_set_test_pattern( + link, + test_pattern, + test_pattern_color_space, + p_link_settings, + p_custom_pattern, + cust_pattern_size); +} diff --git a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.h b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.h new file mode 100644 index 000000000000..7f17838b653b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.h @@ -0,0 +1,33 @@ +/* + * Copyright 2023 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __LINK_DP_CTS_H__ +#define __LINK_DP_CTS_H__ +#include "link.h" + +void dp_retrain_link_dp_test(struct dc_link *link, + struct dc_link_settings *link_setting, + bool skip_video_pattern); + +#endif /* __LINK_DP_CTS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dp_trace.c b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.c index 2c1a3bfcdb50..04838a31e513 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dp_trace.c +++ b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.c @@ -145,7 +145,7 @@ unsigned int dc_dp_trace_get_link_loss_count(struct dc_link *link) return link->dp_trace.link_loss_count; } -void dp_trace_set_edp_power_timestamp(struct dc_link *link, +void link_dp_trace_set_edp_power_timestamp(struct dc_link *link, bool power_up) { if (!power_up) @@ -155,12 +155,12 @@ void dp_trace_set_edp_power_timestamp(struct dc_link *link, link->dp_trace.edp_trace_power_timestamps.poweron = dm_get_timestamp(link->dc->ctx); } -uint64_t dp_trace_get_edp_poweron_timestamp(struct dc_link *link) +uint64_t link_dp_trace_get_edp_poweron_timestamp(struct dc_link *link) { return link->dp_trace.edp_trace_power_timestamps.poweron; } -uint64_t dp_trace_get_edp_poweroff_timestamp(struct dc_link *link) +uint64_t link_dp_trace_get_edp_poweroff_timestamp(struct dc_link *link) { return link->dp_trace.edp_trace_power_timestamps.poweroff; -}
\ No newline at end of file +} diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dp_trace.h b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.h index 26700e3cd65e..702f97c6ead0 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dp_trace.h +++ b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.h @@ -54,9 +54,4 @@ struct dp_trace_lt_counts *dc_dp_trace_get_lt_counts(struct dc_link *link, bool in_detection); unsigned int dc_dp_trace_get_link_loss_count(struct dc_link *link); -void dp_trace_set_edp_power_timestamp(struct dc_link *link, - bool power_up); -uint64_t dp_trace_get_edp_poweron_timestamp(struct dc_link *link); -uint64_t dp_trace_get_edp_poweroff_timestamp(struct dc_link *link); - #endif /* __LINK_DP_TRACE_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c index 33148b753c03..841a23da5dd3 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.c +++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c @@ -24,7 +24,6 @@ */ #include "link_hwss_dio.h" #include "core_types.h" -#include "dc_link_dp.h" #include "link_enc_cfg.h" void set_dio_throttled_vcp_size(struct pipe_ctx *pipe_ctx, diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.h b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.h index 9a108c3d7831..8b8a099feeb0 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.h +++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.h @@ -26,6 +26,7 @@ #define __LINK_HWSS_DIO_H__ #include "link_hwss.h" +#include "link.h" const struct link_hwss *get_dio_link_hwss(void); bool can_use_dio_link_hwss(const struct dc_link *link, diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.c index 861f3cd5b356..861f3cd5b356 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.c +++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.c diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.h b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.h index ad16ec5d9bb7..ad16ec5d9bb7 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.h +++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.h diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c index 164d631e8809..d8947f3233f3 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c +++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c @@ -26,7 +26,6 @@ #include "dm_helpers.h" #include "core_types.h" #include "dccg.h" -#include "dc_link_dp.h" #include "clk_mgr.h" static enum phyd32clk_clock_source get_phyd32clk_src(struct dc_link *link) diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.h b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.h index 57d447ec27b8..3cbb94b41a23 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.h +++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.h @@ -26,6 +26,7 @@ #define __LINK_HWSS_HPO_DP_H__ #include "link_hwss.h" +#include "link.h" bool can_use_hpo_dp_link_hwss(const struct dc_link *link, const struct link_resource *link_res); diff --git a/drivers/gpu/drm/amd/display/dc/link/link_ddc.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c index 5269125bc2a4..5269125bc2a4 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c diff --git a/drivers/gpu/drm/amd/display/dc/link/link_ddc.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.h index 86e9d2e886d6..86e9d2e886d6 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_ddc.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.h diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c index e72ad1b8330f..138e5684c7fd 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dp_capability.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c @@ -39,12 +39,13 @@ #include "link_dpcd.h" #include "link_dp_dpia.h" #include "link_dp_phy.h" -#include "link_dp_trace.h" +#include "link_edp_panel_control.h" +#include "link_dp_irq_handler.h" +#include "link/accessories/link_dp_trace.h" #include "link_dp_training.h" #include "atomfirmware.h" #include "resource.h" #include "link_enc_cfg.h" -#include "dc_link_dp.h" #include "dc_dmub_srv.h" #define DC_LOGGER \ @@ -1462,7 +1463,7 @@ enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link) bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware; if (!vbios_lttpr_interop || !link->dc->caps.extended_aux_timeout_support) - return DC_ERROR_UNEXPECTED; + return DC_NOT_SUPPORTED; /* By reading LTTPR capability, RX assumes that we will enable * LTTPR extended aux timeout if LTTPR is present. @@ -1645,6 +1646,22 @@ static bool retrieve_link_cap(struct dc_link *link) if (status != DC_OK) dm_error("%s: Read DPRX caps data failed.\n", __func__); + + /* AdaptiveSyncCapability */ + dpcd_dprx_data = 0; + for (i = 0; i < read_dpcd_retry_cnt; i++) { + status = core_link_read_dpcd( + link, DP_DPRX_FEATURE_ENUMERATION_LIST_CONT_1, + &dpcd_dprx_data, sizeof(dpcd_dprx_data)); + if (status == DC_OK) + break; + } + + link->dpcd_caps.adaptive_sync_caps.dp_adap_sync_caps.raw = dpcd_dprx_data; + + if (status != DC_OK) + dm_error("%s: Read DPRX caps data failed. Addr:%#x\n", + __func__, DP_DPRX_FEATURE_ENUMERATION_LIST_CONT_1); } else { @@ -1925,7 +1942,7 @@ void detect_edp_sink_caps(struct dc_link *link) link->dpcd_caps.set_power_state_capable_edp = (general_edp_cap & DP_EDP_SET_POWER_CAP) ? true:false; - dc_link_set_default_brightness_aux(link); + set_default_brightness_aux(link); core_link_read_dpcd(link, DP_EDP_DPCD_REV, &link->dpcd_caps.edp_rev, @@ -2110,8 +2127,8 @@ static bool dp_verify_link_cap( if (status == LINK_TRAINING_SUCCESS) { success = true; udelay(1000); - if (read_hpd_rx_irq_data(link, &irq_data) == DC_OK && - hpd_rx_irq_check_link_loss_status( + if (dp_read_hpd_rx_irq_data(link, &irq_data) == DC_OK && + dc_link_check_link_loss_status( link, &irq_data)) (*fail_count)++; diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dp_capability.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.h index 5500744d2e47..f79e4a4a9db6 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dp_capability.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.h @@ -46,6 +46,15 @@ bool is_dp_active_dongle(const struct dc_link *link); bool is_dp_branch_device(const struct dc_link *link); +void dpcd_write_cable_id_to_dprx(struct dc_link *link); + +/* Initialize output parameter lt_settings. */ +void dp_decide_training_settings( + struct dc_link *link, + const struct dc_link_settings *link_setting, + struct link_training_settings *lt_settings); + + bool decide_edp_link_settings_with_dsc(struct dc_link *link, struct dc_link_settings *link_setting, uint32_t req_bw, @@ -62,5 +71,9 @@ bool decide_fallback_link_setting( struct dc_link_settings *cur, enum link_training_result training_result); +bool dp_verify_link_cap_with_retries( + struct dc_link *link, + struct dc_link_settings *known_limit_link_setting, + int attempts); #endif /* __DC_LINK_DP_CAPABILITY_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dp_dpia.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c index 6136db392548..a57a2be2eba0 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dp_dpia.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c @@ -27,7 +27,6 @@ #include "dc.h" #include "inc/core_status.h" #include "dc_link.h" -#include "dc_link_dp.h" #include "dpcd_defs.h" #include "link_dp_dpia.h" @@ -104,4 +103,3 @@ bool dc_link_dpia_query_hpd_status(struct dc_link *link) return is_hpd_high; } - diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dp_dpia.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.h index 98935cc10bb7..98935cc10bb7 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dp_dpia.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.h diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dp_dpia_bw.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c index 801a95b34e8c..801a95b34e8c 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dp_dpia_bw.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dp_dpia_bw.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.h index 58eb7b581093..58eb7b581093 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dp_dpia_bw.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.h diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c new file mode 100644 index 000000000000..9a832a9ea42d --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c @@ -0,0 +1,401 @@ +/* + * Copyright 2022 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +/* FILE POLICY AND INTENDED USAGE: + * + * + */ + +#include "link_dp_irq_handler.h" +#include "link_dpcd.h" +#include "link_dp_training.h" +#include "link_dp_capability.h" +#include "link/accessories/link_dp_trace.h" +#include "dm_helpers.h" + +#define DC_LOGGER_INIT(logger) + +bool dc_link_check_link_loss_status( + struct dc_link *link, + union hpd_irq_data *hpd_irq_dpcd_data) +{ + uint8_t irq_reg_rx_power_state = 0; + enum dc_status dpcd_result = DC_ERROR_UNEXPECTED; + union lane_status lane_status; + uint32_t lane; + bool sink_status_changed; + bool return_code; + + sink_status_changed = false; + return_code = false; + + if (link->cur_link_settings.lane_count == 0) + return return_code; + + /*1. Check that Link Status changed, before re-training.*/ + + /*parse lane status*/ + for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) { + /* check status of lanes 0,1 + * changed DpcdAddress_Lane01Status (0x202) + */ + lane_status.raw = dp_get_nibble_at_index( + &hpd_irq_dpcd_data->bytes.lane01_status.raw, + lane); + + if (!lane_status.bits.CHANNEL_EQ_DONE_0 || + !lane_status.bits.CR_DONE_0 || + !lane_status.bits.SYMBOL_LOCKED_0) { + /* if one of the channel equalization, clock + * recovery or symbol lock is dropped + * consider it as (link has been + * dropped) dp sink status has changed + */ + sink_status_changed = true; + break; + } + } + + /* Check interlane align.*/ + if (sink_status_changed || + !hpd_irq_dpcd_data->bytes.lane_status_updated.bits.INTERLANE_ALIGN_DONE) { + + DC_LOG_HW_HPD_IRQ("%s: Link Status changed.\n", __func__); + + return_code = true; + + /*2. Check that we can handle interrupt: Not in FS DOS, + * Not in "Display Timeout" state, Link is trained. + */ + dpcd_result = core_link_read_dpcd(link, + DP_SET_POWER, + &irq_reg_rx_power_state, + sizeof(irq_reg_rx_power_state)); + + if (dpcd_result != DC_OK) { + DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain power state.\n", + __func__); + } else { + if (irq_reg_rx_power_state != DP_SET_POWER_D0) + return_code = false; + } + } + + return return_code; +} + +static bool handle_hpd_irq_psr_sink(struct dc_link *link) +{ + union dpcd_psr_configuration psr_configuration; + + if (!link->psr_settings.psr_feature_enabled) + return false; + + dm_helpers_dp_read_dpcd( + link->ctx, + link, + 368,/*DpcdAddress_PSR_Enable_Cfg*/ + &psr_configuration.raw, + sizeof(psr_configuration.raw)); + + if (psr_configuration.bits.ENABLE) { + unsigned char dpcdbuf[3] = {0}; + union psr_error_status psr_error_status; + union psr_sink_psr_status psr_sink_psr_status; + + dm_helpers_dp_read_dpcd( + link->ctx, + link, + 0x2006, /*DpcdAddress_PSR_Error_Status*/ + (unsigned char *) dpcdbuf, + sizeof(dpcdbuf)); + + /*DPCD 2006h ERROR STATUS*/ + psr_error_status.raw = dpcdbuf[0]; + /*DPCD 2008h SINK PANEL SELF REFRESH STATUS*/ + psr_sink_psr_status.raw = dpcdbuf[2]; + + if (psr_error_status.bits.LINK_CRC_ERROR || + psr_error_status.bits.RFB_STORAGE_ERROR || + psr_error_status.bits.VSC_SDP_ERROR) { + bool allow_active; + + /* Acknowledge and clear error bits */ + dm_helpers_dp_write_dpcd( + link->ctx, + link, + 8198,/*DpcdAddress_PSR_Error_Status*/ + &psr_error_status.raw, + sizeof(psr_error_status.raw)); + + /* PSR error, disable and re-enable PSR */ + if (link->psr_settings.psr_allow_active) { + allow_active = false; + dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL); + allow_active = true; + dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL); + } + + return true; + } else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS == + PSR_SINK_STATE_ACTIVE_DISPLAY_FROM_SINK_RFB){ + /* No error is detect, PSR is active. + * We should return with IRQ_HPD handled without + * checking for loss of sync since PSR would have + * powered down main link. + */ + return true; + } + } + return false; +} + +void dc_link_dp_handle_link_loss(struct dc_link *link) +{ + int i; + struct pipe_ctx *pipe_ctx; + + for (i = 0; i < MAX_PIPES; i++) { + pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i]; + if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->link == link) + break; + } + + if (pipe_ctx == NULL || pipe_ctx->stream == NULL) + return; + + for (i = 0; i < MAX_PIPES; i++) { + pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i]; + if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off && + pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) + core_link_disable_stream(pipe_ctx); + } + + for (i = 0; i < MAX_PIPES; i++) { + pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i]; + if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off + && pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) { + // Always use max settings here for DP 1.4a LL Compliance CTS + if (link->is_automated) { + pipe_ctx->link_config.dp_link_settings.lane_count = + link->verified_link_cap.lane_count; + pipe_ctx->link_config.dp_link_settings.link_rate = + link->verified_link_cap.link_rate; + pipe_ctx->link_config.dp_link_settings.link_spread = + link->verified_link_cap.link_spread; + } + core_link_enable_stream(link->dc->current_state, pipe_ctx); + } + } +} + +enum dc_status dp_read_hpd_rx_irq_data( + struct dc_link *link, + union hpd_irq_data *irq_data) +{ + static enum dc_status retval; + + /* The HW reads 16 bytes from 200h on HPD, + * but if we get an AUX_DEFER, the HW cannot retry + * and this causes the CTS tests 4.3.2.1 - 3.2.4 to + * fail, so we now explicitly read 6 bytes which is + * the req from the above mentioned test cases. + * + * For DP 1.4 we need to read those from 2002h range. + */ + if (link->dpcd_caps.dpcd_rev.raw < DPCD_REV_14) + retval = core_link_read_dpcd( + link, + DP_SINK_COUNT, + irq_data->raw, + sizeof(union hpd_irq_data)); + else { + /* Read 14 bytes in a single read and then copy only the required fields. + * This is more efficient than doing it in two separate AUX reads. */ + + uint8_t tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI + 1]; + + retval = core_link_read_dpcd( + link, + DP_SINK_COUNT_ESI, + tmp, + sizeof(tmp)); + + if (retval != DC_OK) + return retval; + + irq_data->bytes.sink_cnt.raw = tmp[DP_SINK_COUNT_ESI - DP_SINK_COUNT_ESI]; + irq_data->bytes.device_service_irq.raw = tmp[DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0 - DP_SINK_COUNT_ESI]; + irq_data->bytes.lane01_status.raw = tmp[DP_LANE0_1_STATUS_ESI - DP_SINK_COUNT_ESI]; + irq_data->bytes.lane23_status.raw = tmp[DP_LANE2_3_STATUS_ESI - DP_SINK_COUNT_ESI]; + irq_data->bytes.lane_status_updated.raw = tmp[DP_LANE_ALIGN_STATUS_UPDATED_ESI - DP_SINK_COUNT_ESI]; + irq_data->bytes.sink_status.raw = tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI]; + } + + return retval; +} + +/*************************Short Pulse IRQ***************************/ +bool dc_link_dp_allow_hpd_rx_irq(const struct dc_link *link) +{ + /* + * Don't handle RX IRQ unless one of following is met: + * 1) The link is established (cur_link_settings != unknown) + * 2) We know we're dealing with a branch device, SST or MST + */ + + if ((link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) || + is_dp_branch_device(link)) + return true; + + return false; +} + +bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd_irq_dpcd_data, bool *out_link_loss, + bool defer_handling, bool *has_left_work) +{ + union hpd_irq_data hpd_irq_dpcd_data = {0}; + union device_service_irq device_service_clear = {0}; + enum dc_status result; + bool status = false; + + if (out_link_loss) + *out_link_loss = false; + + if (has_left_work) + *has_left_work = false; + /* For use cases related to down stream connection status change, + * PSR and device auto test, refer to function handle_sst_hpd_irq + * in DAL2.1*/ + + DC_LOG_HW_HPD_IRQ("%s: Got short pulse HPD on link %d\n", + __func__, link->link_index); + + + /* All the "handle_hpd_irq_xxx()" methods + * should be called only after + * dal_dpsst_ls_read_hpd_irq_data + * Order of calls is important too + */ + result = dp_read_hpd_rx_irq_data(link, &hpd_irq_dpcd_data); + if (out_hpd_irq_dpcd_data) + *out_hpd_irq_dpcd_data = hpd_irq_dpcd_data; + + if (result != DC_OK) { + DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain irq data\n", + __func__); + return false; + } + + if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.AUTOMATED_TEST) { + // Workaround for DP 1.4a LL Compliance CTS as USB4 has to share encoders unlike DP and USBC + link->is_automated = true; + device_service_clear.bits.AUTOMATED_TEST = 1; + core_link_write_dpcd( + link, + DP_DEVICE_SERVICE_IRQ_VECTOR, + &device_service_clear.raw, + sizeof(device_service_clear.raw)); + device_service_clear.raw = 0; + if (defer_handling && has_left_work) + *has_left_work = true; + else + dc_link_dp_handle_automated_test(link); + return false; + } + + if (!dc_link_dp_allow_hpd_rx_irq(link)) { + DC_LOG_HW_HPD_IRQ("%s: skipping HPD handling on %d\n", + __func__, link->link_index); + return false; + } + + if (handle_hpd_irq_psr_sink(link)) + /* PSR-related error was detected and handled */ + return true; + + /* If PSR-related error handled, Main link may be off, + * so do not handle as a normal sink status change interrupt. + */ + + if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY) { + if (defer_handling && has_left_work) + *has_left_work = true; + return true; + } + + /* check if we have MST msg and return since we poll for it */ + if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) { + if (defer_handling && has_left_work) + *has_left_work = true; + return false; + } + + /* For now we only handle 'Downstream port status' case. + * If we got sink count changed it means + * Downstream port status changed, + * then DM should call DC to do the detection. + * NOTE: Do not handle link loss on eDP since it is internal link*/ + if ((link->connector_signal != SIGNAL_TYPE_EDP) && + dc_link_check_link_loss_status( + link, + &hpd_irq_dpcd_data)) { + /* Connectivity log: link loss */ + CONN_DATA_LINK_LOSS(link, + hpd_irq_dpcd_data.raw, + sizeof(hpd_irq_dpcd_data), + "Status: "); + + if (defer_handling && has_left_work) + *has_left_work = true; + else + dc_link_dp_handle_link_loss(link); + + status = false; + if (out_link_loss) + *out_link_loss = true; + + dp_trace_link_loss_increment(link); + } + + if (link->type == dc_connection_sst_branch && + hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT + != link->dpcd_sink_count) + status = true; + + /* reasons for HPD RX: + * 1. Link Loss - ie Re-train the Link + * 2. MST sideband message + * 3. Automated Test - ie. Internal Commit + * 4. CP (copy protection) - (not interesting for DM???) + * 5. DRR + * 6. Downstream Port status changed + * -ie. Detect - this the only one + * which is interesting for DM because + * it must call dc_link_detect. + */ + return status; +} + diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_frl.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.h index ea8d9760132f..cac7acd33511 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_frl.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.h @@ -22,13 +22,14 @@ * Authors: AMD * */ -#ifndef __LINK_HWSS_HPO_FRL_H__ -#define __LINK_HWSS_HPO_FRL_H__ -#include "link_hwss.h" +#ifndef __DC_LINK_DP_IRQ_HANDLER_H__ +#define __DC_LINK_DP_IRQ_HANDLER_H__ -bool can_use_hpo_frl_link_hwss(const struct dc_link *link, - const struct link_resource *link_res); -const struct link_hwss *get_hpo_frl_link_hwss(void); +#include "link.h" -#endif /* __LINK_HWSS_HPO_FRL_H__ */ +enum dc_status dp_read_hpd_rx_irq_data( + struct dc_link *link, + union hpd_irq_data *irq_data); + +#endif /* __DC_LINK_DP_IRQ_HANDLER_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dp_phy.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c index afe3b21335c2..5e531620926f 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dp_phy.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c @@ -36,27 +36,10 @@ #include "link_dp_capability.h" #include "clk_mgr.h" #include "resource.h" -#include "dc_link_dp.h" #define DC_LOGGER \ link->ctx->logger -void dc_link_dp_set_drive_settings( - struct dc_link *link, - const struct link_resource *link_res, - struct link_training_settings *lt_settings) -{ - /* program ASIC PHY settings*/ - dp_set_hw_lane_settings(link, link_res, lt_settings, DPRX); - - dp_hw_to_dpcd_lane_settings(lt_settings, - lt_settings->hw_lane_settings, - lt_settings->dpcd_lane_settings); - - /* Notify DP sink the PHY settings from source */ - dpcd_set_lane_settings(link, lt_settings, DPRX); -} - void dc_link_dp_receiver_power_ctrl(struct dc_link *link, bool on) { uint8_t state; @@ -143,3 +126,19 @@ void dp_set_hw_lane_settings( link_settings->hw_lane_settings, sizeof(link->cur_lane_setting)); } + +void dp_set_drive_settings( + struct dc_link *link, + const struct link_resource *link_res, + struct link_training_settings *lt_settings) +{ + /* program ASIC PHY settings*/ + dp_set_hw_lane_settings(link, link_res, lt_settings, DPRX); + + dp_hw_to_dpcd_lane_settings(lt_settings, + lt_settings->hw_lane_settings, + lt_settings->dpcd_lane_settings); + + /* Notify DP sink the PHY settings from source */ + dpcd_set_lane_settings(link, lt_settings, DPRX); +} diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dp_phy.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.h index 717e078fd564..850da64c9005 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dp_phy.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.h @@ -48,4 +48,9 @@ void dp_set_hw_lane_settings( const struct link_training_settings *link_settings, uint32_t offset); +void dp_set_drive_settings( + struct dc_link *link, + const struct link_resource *link_res, + struct link_training_settings *lt_settings); + #endif /* __DC_LINK_DP_PHY_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dp_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c index e49e0258a1bd..18ec09b5a8ba 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dp_training.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c @@ -37,10 +37,10 @@ #include "link_dp_training_dpia.h" #include "link_dp_training_fixed_vs_pe_retimer.h" #include "link_dpcd.h" -#include "link_dp_trace.h" +#include "link/accessories/link_dp_trace.h" #include "link_dp_phy.h" #include "link_dp_capability.h" -#include "dc_link_dp.h" +#include "link_edp_panel_control.h" #include "atomfirmware.h" #include "link_enc_cfg.h" #include "resource.h" @@ -239,7 +239,7 @@ enum dpcd_training_patterns return dpcd_tr_pattern; } -static uint8_t get_nibble_at_index(const uint8_t *buf, +uint8_t dp_get_nibble_at_index(const uint8_t *buf, uint32_t index) { uint8_t nibble; @@ -519,7 +519,7 @@ enum link_training_result dp_check_link_loss_status( /* * check lanes status */ - lane_status.raw = get_nibble_at_index(&dpcd_buf[2], lane); + lane_status.raw = dp_get_nibble_at_index(&dpcd_buf[2], lane); if (!lane_status.bits.CHANNEL_EQ_DONE_0 || !lane_status.bits.CR_DONE_0 || @@ -578,9 +578,9 @@ enum dc_status dp_get_lane_status_and_lane_adjust( lane++) { ln_status[lane].raw = - get_nibble_at_index(&dpcd_buf[0], lane); + dp_get_nibble_at_index(&dpcd_buf[0], lane); ln_adjust[lane].raw = - get_nibble_at_index(&dpcd_buf[lane_adjust_offset], lane); + dp_get_nibble_at_index(&dpcd_buf[lane_adjust_offset], lane); } ln_align->raw = dpcd_buf[2]; @@ -1389,7 +1389,7 @@ static bool perform_post_lt_adj_req_sequence( dp_decide_lane_settings(lt_settings, dpcd_lane_adjust, lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings); - dc_link_dp_set_drive_settings(link, + dp_set_drive_settings(link, link_res, lt_settings); break; diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dp_training.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.h index 376d370e3bbb..a04948635369 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dp_training.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.h @@ -176,4 +176,7 @@ void dp_log_training_result( uint32_t dp_translate_training_aux_read_interval( uint32_t dpcd_aux_read_interval); + +uint8_t dp_get_nibble_at_index(const uint8_t *buf, + uint32_t index); #endif /* __DC_LINK_DP_TRAINING_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dp_training_128b_132b.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c index bfabebed5868..23d380f09a21 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dp_training_128b_132b.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c @@ -32,7 +32,6 @@ #include "link_dpcd.h" #include "link_dp_phy.h" #include "link_dp_capability.h" -#include "dc_link_dp.h" #define DC_LOGGER \ link->ctx->logger diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dp_training_128b_132b.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.h index 2147f24efc8b..2147f24efc8b 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dp_training_128b_132b.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.h diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dp_training_8b_10b.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c index ec8b619d51c5..14b98e096d39 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dp_training_8b_10b.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c @@ -31,7 +31,6 @@ #include "link_dpcd.h" #include "link_dp_phy.h" #include "link_dp_capability.h" -#include "dc_link_dp.h" #define DC_LOGGER \ link->ctx->logger diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dp_training_8b_10b.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.h index d26de15ce954..d26de15ce954 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dp_training_8b_10b.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.h diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dp_training_auxless.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_auxless.c index f84b6ea53e8b..e50ec5012559 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dp_training_auxless.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_auxless.c @@ -28,7 +28,6 @@ */ #include "link_dp_training_auxless.h" #include "link_dp_phy.h" -#include "dc_link_dp.h" #define DC_LOGGER \ link->ctx->logger bool dc_link_dp_perform_link_training_skip_aux( diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dp_training_auxless.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_auxless.h index 413999cd03c4..413999cd03c4 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dp_training_auxless.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_auxless.h diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dp_training_dpia.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c index cf47db1c2141..05657627ae45 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dp_training_dpia.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c @@ -30,7 +30,6 @@ #include "dc.h" #include "inc/core_status.h" #include "dc_link.h" -#include "dc_link_dp.h" #include "dpcd_defs.h" #include "link_dp_dpia.h" diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dp_training_dpia.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.h index 0150f2916421..0150f2916421 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dp_training_dpia.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.h diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dp_training_fixed_vs_pe_retimer.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c index 860b5eea89aa..a4071d2959a0 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dp_training_fixed_vs_pe_retimer.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c @@ -36,7 +36,6 @@ #include "link_dpcd.h" #include "link_dp_phy.h" #include "link_dp_capability.h" -#include "dc_link_dp.h" #define DC_LOGGER \ link->ctx->logger diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dp_training_fixed_vs_pe_retimer.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.h index e61970e27661..e61970e27661 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dp_training_fixed_vs_pe_retimer.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.h diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpcd.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.c index 5c9a30211c10..5c9a30211c10 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dpcd.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.c diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpcd.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.h index 08d787a1e451..08d787a1e451 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dpcd.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.h diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c new file mode 100644 index 000000000000..97e02b5b21ae --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c @@ -0,0 +1,833 @@ +/* + * Copyright 2022 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +/* FILE POLICY AND INTENDED USAGE: + * This file implements retrieval and configuration of eDP panel features such + * as PSR and ABM and it also manages specs defined eDP panel power sequences. + */ + +#include "link_edp_panel_control.h" +#include "link_dpcd.h" +#include "link_dp_capability.h" +#include "dm_helpers.h" +#include "dal_asic_id.h" +#include "dce/dmub_psr.h" +#include "abm.h" +#define DC_LOGGER_INIT(logger) + +void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode) +{ + union dpcd_edp_config edp_config_set; + bool panel_mode_edp = false; + + memset(&edp_config_set, '\0', sizeof(union dpcd_edp_config)); + + if (panel_mode != DP_PANEL_MODE_DEFAULT) { + + switch (panel_mode) { + case DP_PANEL_MODE_EDP: + case DP_PANEL_MODE_SPECIAL: + panel_mode_edp = true; + break; + + default: + break; + } + + /*set edp panel mode in receiver*/ + core_link_read_dpcd( + link, + DP_EDP_CONFIGURATION_SET, + &edp_config_set.raw, + sizeof(edp_config_set.raw)); + + if (edp_config_set.bits.PANEL_MODE_EDP + != panel_mode_edp) { + enum dc_status result; + + edp_config_set.bits.PANEL_MODE_EDP = + panel_mode_edp; + result = core_link_write_dpcd( + link, + DP_EDP_CONFIGURATION_SET, + &edp_config_set.raw, + sizeof(edp_config_set.raw)); + + ASSERT(result == DC_OK); + } + } + DC_LOG_DETECTION_DP_CAPS("Link: %d eDP panel mode supported: %d " + "eDP panel mode enabled: %d \n", + link->link_index, + link->dpcd_caps.panel_mode_edp, + panel_mode_edp); +} + +enum dp_panel_mode dp_get_panel_mode(struct dc_link *link) +{ + /* We need to explicitly check that connector + * is not DP. Some Travis_VGA get reported + * by video bios as DP. + */ + if (link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) { + + switch (link->dpcd_caps.branch_dev_id) { + case DP_BRANCH_DEVICE_ID_0022B9: + /* alternate scrambler reset is required for Travis + * for the case when external chip does not + * provide sink device id, alternate scrambler + * scheme will be overriden later by querying + * Encoder features + */ + if (strncmp( + link->dpcd_caps.branch_dev_name, + DP_VGA_LVDS_CONVERTER_ID_2, + sizeof( + link->dpcd_caps. + branch_dev_name)) == 0) { + return DP_PANEL_MODE_SPECIAL; + } + break; + case DP_BRANCH_DEVICE_ID_00001A: + /* alternate scrambler reset is required for Travis + * for the case when external chip does not provide + * sink device id, alternate scrambler scheme will + * be overriden later by querying Encoder feature + */ + if (strncmp(link->dpcd_caps.branch_dev_name, + DP_VGA_LVDS_CONVERTER_ID_3, + sizeof( + link->dpcd_caps. + branch_dev_name)) == 0) { + return DP_PANEL_MODE_SPECIAL; + } + break; + default: + break; + } + } + + if (link->dpcd_caps.panel_mode_edp && + (link->connector_signal == SIGNAL_TYPE_EDP || + (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT && + link->is_internal_display))) { + return DP_PANEL_MODE_EDP; + } + + return DP_PANEL_MODE_DEFAULT; +} + +bool dc_link_set_backlight_level_nits(struct dc_link *link, + bool isHDR, + uint32_t backlight_millinits, + uint32_t transition_time_in_ms) +{ + struct dpcd_source_backlight_set dpcd_backlight_set; + uint8_t backlight_control = isHDR ? 1 : 0; + + if (!link || (link->connector_signal != SIGNAL_TYPE_EDP && + link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT)) + return false; + + // OLEDs have no PWM, they can only use AUX + if (link->dpcd_sink_ext_caps.bits.oled == 1) + backlight_control = 1; + + *(uint32_t *)&dpcd_backlight_set.backlight_level_millinits = backlight_millinits; + *(uint16_t *)&dpcd_backlight_set.backlight_transition_time_ms = (uint16_t)transition_time_in_ms; + + + if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL, + (uint8_t *)(&dpcd_backlight_set), + sizeof(dpcd_backlight_set)) != DC_OK) + return false; + + if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_CONTROL, + &backlight_control, 1) != DC_OK) + return false; + + return true; +} + +bool dc_link_get_backlight_level_nits(struct dc_link *link, + uint32_t *backlight_millinits_avg, + uint32_t *backlight_millinits_peak) +{ + union dpcd_source_backlight_get dpcd_backlight_get; + + memset(&dpcd_backlight_get, 0, sizeof(union dpcd_source_backlight_get)); + + if (!link || (link->connector_signal != SIGNAL_TYPE_EDP && + link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT)) + return false; + + if (!core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_CURRENT_PEAK, + dpcd_backlight_get.raw, + sizeof(union dpcd_source_backlight_get))) + return false; + + *backlight_millinits_avg = + dpcd_backlight_get.bytes.backlight_millinits_avg; + *backlight_millinits_peak = + dpcd_backlight_get.bytes.backlight_millinits_peak; + + /* On non-supported panels dpcd_read usually succeeds with 0 returned */ + if (*backlight_millinits_avg == 0 || + *backlight_millinits_avg > *backlight_millinits_peak) + return false; + + return true; +} + +bool link_backlight_enable_aux(struct dc_link *link, bool enable) +{ + uint8_t backlight_enable = enable ? 1 : 0; + + if (!link || (link->connector_signal != SIGNAL_TYPE_EDP && + link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT)) + return false; + + if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_ENABLE, + &backlight_enable, 1) != DC_OK) + return false; + + return true; +} + +// we read default from 0x320 because we expect BIOS wrote it there +// regular get_backlight_nit reads from panel set at 0x326 +static bool read_default_bl_aux(struct dc_link *link, uint32_t *backlight_millinits) +{ + if (!link || (link->connector_signal != SIGNAL_TYPE_EDP && + link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT)) + return false; + + if (!core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL, + (uint8_t *) backlight_millinits, + sizeof(uint32_t))) + return false; + + return true; +} + +bool set_default_brightness_aux(struct dc_link *link) +{ + uint32_t default_backlight; + + if (link && link->dpcd_sink_ext_caps.bits.oled == 1) { + if (!read_default_bl_aux(link, &default_backlight)) + default_backlight = 150000; + // if < 5 nits or > 5000, it might be wrong readback + if (default_backlight < 5000 || default_backlight > 5000000) + default_backlight = 150000; // + + return dc_link_set_backlight_level_nits(link, true, + default_backlight, 0); + } + return false; +} + +bool link_is_edp_ilr_optimization_required(struct dc_link *link, + struct dc_crtc_timing *crtc_timing) +{ + struct dc_link_settings link_setting; + uint8_t link_bw_set; + uint8_t link_rate_set; + uint32_t req_bw; + union lane_count_set lane_count_set = {0}; + + ASSERT(link || crtc_timing); // invalid input + + if (link->dpcd_caps.edp_supported_link_rates_count == 0 || + !link->panel_config.ilr.optimize_edp_link_rate) + return false; + + + // Read DPCD 00100h to find if standard link rates are set + core_link_read_dpcd(link, DP_LINK_BW_SET, + &link_bw_set, sizeof(link_bw_set)); + + if (link_bw_set) { + DC_LOG_EVENT_LINK_TRAINING("eDP ILR: Optimization required, VBIOS used link_bw_set\n"); + return true; + } + + // Read DPCD 00115h to find the edp link rate set used + core_link_read_dpcd(link, DP_LINK_RATE_SET, + &link_rate_set, sizeof(link_rate_set)); + + // Read DPCD 00101h to find out the number of lanes currently set + core_link_read_dpcd(link, DP_LANE_COUNT_SET, + &lane_count_set.raw, sizeof(lane_count_set)); + + req_bw = dc_bandwidth_in_kbps_from_timing(crtc_timing); + + if (!crtc_timing->flags.DSC) + dc_link_decide_edp_link_settings(link, &link_setting, req_bw); + else + decide_edp_link_settings_with_dsc(link, &link_setting, req_bw, LINK_RATE_UNKNOWN); + + if (link->dpcd_caps.edp_supported_link_rates[link_rate_set] != link_setting.link_rate || + lane_count_set.bits.LANE_COUNT_SET != link_setting.lane_count) { + DC_LOG_EVENT_LINK_TRAINING("eDP ILR: Optimization required, VBIOS link_rate_set not optimal\n"); + return true; + } + + DC_LOG_EVENT_LINK_TRAINING("eDP ILR: No optimization required, VBIOS set optimal link_rate_set\n"); + return false; +} + +void dc_link_edp_panel_backlight_power_on(struct dc_link *link, bool wait_for_hpd) +{ + if (link->connector_signal != SIGNAL_TYPE_EDP) + return; + + link->dc->hwss.edp_power_control(link, true); + if (wait_for_hpd) + link->dc->hwss.edp_wait_for_hpd_ready(link, true); + if (link->dc->hwss.edp_backlight_control) + link->dc->hwss.edp_backlight_control(link, true); +} + +bool dc_link_wait_for_t12(struct dc_link *link) +{ + if (link->connector_signal == SIGNAL_TYPE_EDP && link->dc->hwss.edp_wait_for_T12) { + link->dc->hwss.edp_wait_for_T12(link); + + return true; + } + + return false; +} + +void link_edp_add_delay_for_T9(struct dc_link *link) +{ + if (link && link->panel_config.pps.extra_delay_backlight_off > 0) + udelay(link->panel_config.pps.extra_delay_backlight_off * 1000); +} + +bool link_edp_receiver_ready_T9(struct dc_link *link) +{ + unsigned int tries = 0; + unsigned char sinkstatus = 0; + unsigned char edpRev = 0; + enum dc_status result = DC_OK; + + result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev)); + + /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/ + if (result == DC_OK && edpRev >= DP_EDP_12) { + do { + sinkstatus = 1; + result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus)); + if (sinkstatus == 0) + break; + if (result != DC_OK) + break; + udelay(100); //MAx T9 + } while (++tries < 50); + } + + return result; +} + +bool link_edp_receiver_ready_T7(struct dc_link *link) +{ + unsigned char sinkstatus = 0; + unsigned char edpRev = 0; + enum dc_status result = DC_OK; + + /* use absolute time stamp to constrain max T7*/ + unsigned long long enter_timestamp = 0; + unsigned long long finish_timestamp = 0; + unsigned long long time_taken_in_ns = 0; + + result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev)); + + if (result == DC_OK && edpRev >= DP_EDP_12) { + /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/ + enter_timestamp = dm_get_timestamp(link->ctx); + do { + sinkstatus = 0; + result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus)); + if (sinkstatus == 1) + break; + if (result != DC_OK) + break; + udelay(25); + finish_timestamp = dm_get_timestamp(link->ctx); + time_taken_in_ns = dm_get_elapse_time_in_ns(link->ctx, finish_timestamp, enter_timestamp); + } while (time_taken_in_ns < 50 * 1000000); //MAx T7 is 50ms + } + + if (link && link->panel_config.pps.extra_t7_ms > 0) + udelay(link->panel_config.pps.extra_t7_ms * 1000); + + return result; +} + +bool link_power_alpm_dpcd_enable(struct dc_link *link, bool enable) +{ + bool ret = false; + union dpcd_alpm_configuration alpm_config; + + if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) { + memset(&alpm_config, 0, sizeof(alpm_config)); + + alpm_config.bits.ENABLE = (enable ? true : false); + ret = dm_helpers_dp_write_dpcd(link->ctx, link, + DP_RECEIVER_ALPM_CONFIG, &alpm_config.raw, + sizeof(alpm_config.raw)); + } + return ret; +} + +static struct pipe_ctx *get_pipe_from_link(const struct dc_link *link) +{ + int i; + struct dc *dc = link->ctx->dc; + struct pipe_ctx *pipe_ctx = NULL; + + for (i = 0; i < MAX_PIPES; i++) { + if (dc->current_state->res_ctx.pipe_ctx[i].stream) { + if (dc->current_state->res_ctx.pipe_ctx[i].stream->link == link) { + pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; + break; + } + } + } + + return pipe_ctx; +} + +bool dc_link_set_backlight_level(const struct dc_link *link, + uint32_t backlight_pwm_u16_16, + uint32_t frame_ramp) +{ + struct dc *dc = link->ctx->dc; + + DC_LOGGER_INIT(link->ctx->logger); + DC_LOG_BACKLIGHT("New Backlight level: %d (0x%X)\n", + backlight_pwm_u16_16, backlight_pwm_u16_16); + + if (dc_is_embedded_signal(link->connector_signal)) { + struct pipe_ctx *pipe_ctx = get_pipe_from_link(link); + + if (pipe_ctx) { + /* Disable brightness ramping when the display is blanked + * as it can hang the DMCU + */ + if (pipe_ctx->plane_state == NULL) + frame_ramp = 0; + } else { + return false; + } + + dc->hwss.set_backlight_level( + pipe_ctx, + backlight_pwm_u16_16, + frame_ramp); + } + return true; +} + +bool dc_link_set_psr_allow_active(struct dc_link *link, const bool *allow_active, + bool wait, bool force_static, const unsigned int *power_opts) +{ + struct dc *dc = link->ctx->dc; + struct dmcu *dmcu = dc->res_pool->dmcu; + struct dmub_psr *psr = dc->res_pool->psr; + unsigned int panel_inst; + + if (psr == NULL && force_static) + return false; + + if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst)) + return false; + + if ((allow_active != NULL) && (*allow_active == true) && (link->type == dc_connection_none)) { + // Don't enter PSR if panel is not connected + return false; + } + + /* Set power optimization flag */ + if (power_opts && link->psr_settings.psr_power_opt != *power_opts) { + link->psr_settings.psr_power_opt = *power_opts; + + if (psr != NULL && link->psr_settings.psr_feature_enabled && psr->funcs->psr_set_power_opt) + psr->funcs->psr_set_power_opt(psr, link->psr_settings.psr_power_opt, panel_inst); + } + + if (psr != NULL && link->psr_settings.psr_feature_enabled && + force_static && psr->funcs->psr_force_static) + psr->funcs->psr_force_static(psr, panel_inst); + + /* Enable or Disable PSR */ + if (allow_active && link->psr_settings.psr_allow_active != *allow_active) { + link->psr_settings.psr_allow_active = *allow_active; + + if (!link->psr_settings.psr_allow_active) + dc_z10_restore(dc); + + if (psr != NULL && link->psr_settings.psr_feature_enabled) { + psr->funcs->psr_enable(psr, link->psr_settings.psr_allow_active, wait, panel_inst); + } else if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu)) && + link->psr_settings.psr_feature_enabled) + dmcu->funcs->set_psr_enable(dmcu, link->psr_settings.psr_allow_active, wait); + else + return false; + } + return true; +} + +bool dc_link_get_psr_state(const struct dc_link *link, enum dc_psr_state *state) +{ + struct dc *dc = link->ctx->dc; + struct dmcu *dmcu = dc->res_pool->dmcu; + struct dmub_psr *psr = dc->res_pool->psr; + unsigned int panel_inst; + + if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst)) + return false; + + if (psr != NULL && link->psr_settings.psr_feature_enabled) + psr->funcs->psr_get_state(psr, state, panel_inst); + else if (dmcu != NULL && link->psr_settings.psr_feature_enabled) + dmcu->funcs->get_psr_state(dmcu, state); + + return true; +} + +static inline enum physical_phy_id +transmitter_to_phy_id(struct dc_link *link) +{ + struct dc_context *dc_ctx = link->ctx; + enum transmitter transmitter_value = link->link_enc->transmitter; + + switch (transmitter_value) { + case TRANSMITTER_UNIPHY_A: + return PHYLD_0; + case TRANSMITTER_UNIPHY_B: + return PHYLD_1; + case TRANSMITTER_UNIPHY_C: + return PHYLD_2; + case TRANSMITTER_UNIPHY_D: + return PHYLD_3; + case TRANSMITTER_UNIPHY_E: + return PHYLD_4; + case TRANSMITTER_UNIPHY_F: + return PHYLD_5; + case TRANSMITTER_NUTMEG_CRT: + return PHYLD_6; + case TRANSMITTER_TRAVIS_CRT: + return PHYLD_7; + case TRANSMITTER_TRAVIS_LCD: + return PHYLD_8; + case TRANSMITTER_UNIPHY_G: + return PHYLD_9; + case TRANSMITTER_COUNT: + return PHYLD_COUNT; + case TRANSMITTER_UNKNOWN: + return PHYLD_UNKNOWN; + default: + DC_ERROR("Unknown transmitter value %d\n", transmitter_value); + return PHYLD_UNKNOWN; + } +} + +bool dc_link_setup_psr(struct dc_link *link, + const struct dc_stream_state *stream, struct psr_config *psr_config, + struct psr_context *psr_context) +{ + struct dc *dc; + struct dmcu *dmcu; + struct dmub_psr *psr; + int i; + unsigned int panel_inst; + /* updateSinkPsrDpcdConfig*/ + union dpcd_psr_configuration psr_configuration; + union dpcd_sink_active_vtotal_control_mode vtotal_control = {0}; + + psr_context->controllerId = CONTROLLER_ID_UNDEFINED; + + if (!link) + return false; + + dc = link->ctx->dc; + dmcu = dc->res_pool->dmcu; + psr = dc->res_pool->psr; + + if (!dmcu && !psr) + return false; + + if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst)) + return false; + + + memset(&psr_configuration, 0, sizeof(psr_configuration)); + + psr_configuration.bits.ENABLE = 1; + psr_configuration.bits.CRC_VERIFICATION = 1; + psr_configuration.bits.FRAME_CAPTURE_INDICATION = + psr_config->psr_frame_capture_indication_req; + + /* Check for PSR v2*/ + if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) { + /* For PSR v2 selective update. + * Indicates whether sink should start capturing + * immediately following active scan line, + * or starting with the 2nd active scan line. + */ + psr_configuration.bits.LINE_CAPTURE_INDICATION = 0; + /*For PSR v2, determines whether Sink should generate + * IRQ_HPD when CRC mismatch is detected. + */ + psr_configuration.bits.IRQ_HPD_WITH_CRC_ERROR = 1; + /* For PSR v2, set the bit when the Source device will + * be enabling PSR2 operation. + */ + psr_configuration.bits.ENABLE_PSR2 = 1; + /* For PSR v2, the Sink device must be able to receive + * SU region updates early in the frame time. + */ + psr_configuration.bits.EARLY_TRANSPORT_ENABLE = 1; + } + + dm_helpers_dp_write_dpcd( + link->ctx, + link, + 368, + &psr_configuration.raw, + sizeof(psr_configuration.raw)); + + if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) { + link_power_alpm_dpcd_enable(link, true); + psr_context->su_granularity_required = + psr_config->su_granularity_required; + psr_context->su_y_granularity = + psr_config->su_y_granularity; + psr_context->line_time_in_us = psr_config->line_time_in_us; + + /* linux must be able to expose AMD Source DPCD definition + * in order to support FreeSync PSR + */ + if (link->psr_settings.psr_vtotal_control_support) { + psr_context->rate_control_caps = psr_config->rate_control_caps; + vtotal_control.bits.ENABLE = true; + core_link_write_dpcd(link, DP_SINK_PSR_ACTIVE_VTOTAL_CONTROL_MODE, + &vtotal_control.raw, sizeof(vtotal_control.raw)); + } + } + + psr_context->channel = link->ddc->ddc_pin->hw_info.ddc_channel; + psr_context->transmitterId = link->link_enc->transmitter; + psr_context->engineId = link->link_enc->preferred_engine; + + for (i = 0; i < MAX_PIPES; i++) { + if (dc->current_state->res_ctx.pipe_ctx[i].stream + == stream) { + /* dmcu -1 for all controller id values, + * therefore +1 here + */ + psr_context->controllerId = + dc->current_state->res_ctx. + pipe_ctx[i].stream_res.tg->inst + 1; + break; + } + } + + /* Hardcoded for now. Can be Pcie or Uniphy (or Unknown)*/ + psr_context->phyType = PHY_TYPE_UNIPHY; + /*PhyId is associated with the transmitter id*/ + psr_context->smuPhyId = transmitter_to_phy_id(link); + + psr_context->crtcTimingVerticalTotal = stream->timing.v_total; + psr_context->vsync_rate_hz = div64_u64(div64_u64((stream-> + timing.pix_clk_100hz * 100), + stream->timing.v_total), + stream->timing.h_total); + + psr_context->psrSupportedDisplayConfig = true; + psr_context->psrExitLinkTrainingRequired = + psr_config->psr_exit_link_training_required; + psr_context->sdpTransmitLineNumDeadline = + psr_config->psr_sdp_transmit_line_num_deadline; + psr_context->psrFrameCaptureIndicationReq = + psr_config->psr_frame_capture_indication_req; + + psr_context->skipPsrWaitForPllLock = 0; /* only = 1 in KV */ + + psr_context->numberOfControllers = + link->dc->res_pool->timing_generator_count; + + psr_context->rfb_update_auto_en = true; + + /* 2 frames before enter PSR. */ + psr_context->timehyst_frames = 2; + /* half a frame + * (units in 100 lines, i.e. a value of 1 represents 100 lines) + */ + psr_context->hyst_lines = stream->timing.v_total / 2 / 100; + psr_context->aux_repeats = 10; + + psr_context->psr_level.u32all = 0; + + /*skip power down the single pipe since it blocks the cstate*/ +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (link->ctx->asic_id.chip_family >= FAMILY_RV) { + switch (link->ctx->asic_id.chip_family) { + case FAMILY_YELLOW_CARP: + case AMDGPU_FAMILY_GC_10_3_6: + case AMDGPU_FAMILY_GC_11_0_1: + if (dc->debug.disable_z10 || dc->debug.psr_skip_crtc_disable) + psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true; + break; + default: + psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true; + break; + } + } +#else + if (link->ctx->asic_id.chip_family >= FAMILY_RV) + psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true; +#endif + + /* SMU will perform additional powerdown sequence. + * For unsupported ASICs, set psr_level flag to skip PSR + * static screen notification to SMU. + * (Always set for DAL2, did not check ASIC) + */ + psr_context->allow_smu_optimizations = psr_config->allow_smu_optimizations; + psr_context->allow_multi_disp_optimizations = psr_config->allow_multi_disp_optimizations; + + /* Complete PSR entry before aborting to prevent intermittent + * freezes on certain eDPs + */ + psr_context->psr_level.bits.DISABLE_PSR_ENTRY_ABORT = 1; + + /* Disable ALPM first for compatible non-ALPM panel now */ + psr_context->psr_level.bits.DISABLE_ALPM = 0; + psr_context->psr_level.bits.ALPM_DEFAULT_PD_MODE = 1; + + /* Controls additional delay after remote frame capture before + * continuing power down, default = 0 + */ + psr_context->frame_delay = 0; + + psr_context->dsc_slice_height = psr_config->dsc_slice_height; + + if (psr) { + link->psr_settings.psr_feature_enabled = psr->funcs->psr_copy_settings(psr, + link, psr_context, panel_inst); + link->psr_settings.psr_power_opt = 0; + link->psr_settings.psr_allow_active = 0; + } else { + link->psr_settings.psr_feature_enabled = dmcu->funcs->setup_psr(dmcu, link, psr_context); + } + + /* psr_enabled == 0 indicates setup_psr did not succeed, but this + * should not happen since firmware should be running at this point + */ + if (link->psr_settings.psr_feature_enabled == 0) + ASSERT(0); + + return true; + +} + +void link_get_psr_residency(const struct dc_link *link, uint32_t *residency) +{ + struct dc *dc = link->ctx->dc; + struct dmub_psr *psr = dc->res_pool->psr; + unsigned int panel_inst; + + if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst)) + return; + + // PSR residency measurements only supported on DMCUB + if (psr != NULL && link->psr_settings.psr_feature_enabled) + psr->funcs->psr_get_residency(psr, residency, panel_inst); + else + *residency = 0; +} +bool link_set_sink_vtotal_in_psr_active(const struct dc_link *link, uint16_t psr_vtotal_idle, uint16_t psr_vtotal_su) +{ + struct dc *dc = link->ctx->dc; + struct dmub_psr *psr = dc->res_pool->psr; + + if (psr == NULL || !link->psr_settings.psr_feature_enabled || !link->psr_settings.psr_vtotal_control_support) + return false; + + psr->funcs->psr_set_sink_vtotal_in_psr_active(psr, psr_vtotal_idle, psr_vtotal_su); + + return true; +} + +static struct abm *get_abm_from_stream_res(const struct dc_link *link) +{ + int i; + struct dc *dc = link->ctx->dc; + struct abm *abm = NULL; + + for (i = 0; i < MAX_PIPES; i++) { + struct pipe_ctx pipe_ctx = dc->current_state->res_ctx.pipe_ctx[i]; + struct dc_stream_state *stream = pipe_ctx.stream; + + if (stream && stream->link == link) { + abm = pipe_ctx.stream_res.abm; + break; + } + } + return abm; +} + +int dc_link_get_backlight_level(const struct dc_link *link) +{ + struct abm *abm = get_abm_from_stream_res(link); + struct panel_cntl *panel_cntl = link->panel_cntl; + struct dc *dc = link->ctx->dc; + struct dmcu *dmcu = dc->res_pool->dmcu; + bool fw_set_brightness = true; + + if (dmcu) + fw_set_brightness = dmcu->funcs->is_dmcu_initialized(dmcu); + + if (!fw_set_brightness && panel_cntl->funcs->get_current_backlight) + return panel_cntl->funcs->get_current_backlight(panel_cntl); + else if (abm != NULL && abm->funcs->get_current_backlight != NULL) + return (int) abm->funcs->get_current_backlight(abm); + else + return DC_ERROR_UNEXPECTED; +} + +int dc_link_get_target_backlight_pwm(const struct dc_link *link) +{ + struct abm *abm = get_abm_from_stream_res(link); + + if (abm == NULL || abm->funcs->get_target_backlight == NULL) + return DC_ERROR_UNEXPECTED; + + return (int) abm->funcs->get_target_backlight(abm); +} diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h new file mode 100644 index 000000000000..7f91a564b089 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h @@ -0,0 +1,33 @@ +/* + * Copyright 2022 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_LINK_EDP_PANEL_CONTROL_H__ +#define __DC_LINK_EDP_PANEL_CONTROL_H__ +#include "link.h" + +enum dp_panel_mode dp_get_panel_mode(struct dc_link *link); +void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode); +bool set_default_brightness_aux(struct dc_link *link); +#endif /* __DC_LINK_EDP_POWER_CONTROL_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hpd.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.c index 5f39dfe06e9a..5f39dfe06e9a 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_hpd.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.c diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hpd.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.h index 3d122def0c88..3d122def0c88 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_hpd.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.h diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 06c553b61322..04df407092b1 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -1968,6 +1968,14 @@ struct dmub_cmd_psr_copy_settings_data { * Explicit padding to 2 byte boundary. */ uint8_t pad3; + /** + * DSC Slice height. + */ + uint16_t dsc_slice_height; + /** + * Explicit padding to 4 byte boundary. + */ + uint16_t pad; }; /** @@ -3112,7 +3120,7 @@ struct dmub_rb_cmd_panel_cntl { struct dmub_cmd_lvtma_control_data { uint8_t uc_pwr_action; /**< LVTMA_ACTION */ uint8_t bypass_panel_control_wait; - uint8_t reserved_0[2]; + uint8_t reserved_0[2]; /**< For future use */ uint8_t panel_inst; /**< LVTMA control instance */ uint8_t reserved_1[3]; /**< For future use */ }; diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h index edf5845f6a1f..91fe039c0c95 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h @@ -41,4 +41,40 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream, void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream, struct dc_info_packet *info_packet); +enum adaptive_sync_type { + ADAPTIVE_SYNC_TYPE_NONE = 0, + ADAPTIVE_SYNC_TYPE_DP = 1, + ADAPTIVE_SYNC_TYPE_PCON_IN_WHITELIST = 2, + ADAPTIVE_SYNC_TYPE_PCON_NOT_IN_WHITELIST = 3, + ADAPTIVE_SYNC_TYPE_EDP = 4, +}; + +enum adaptive_sync_sdp_version { + AS_SDP_VER_0 = 0x0, + AS_SDP_VER_1 = 0x1, + AS_SDP_VER_2 = 0x2, +}; + +#define AS_DP_SDP_LENGTH (9) + +struct frame_duration_op { + bool support; + unsigned char frame_duration_hex; +}; + +struct AS_Df_params { + bool supportMode; + struct frame_duration_op increase; + struct frame_duration_op decrease; +}; + +void mod_build_adaptive_sync_infopacket(const struct dc_stream_state *stream, + enum adaptive_sync_type asType, const struct AS_Df_params *param, + struct dc_info_packet *info_packet); + +void mod_build_adaptive_sync_infopacket_v2(const struct dc_stream_state *stream, + const struct AS_Df_params *param, struct dc_info_packet *info_packet); + +void mod_build_adaptive_sync_infopacket_v1(struct dc_info_packet *info_packet); + #endif diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c index 69691058ab89..a8a31d0a7a7f 100644 --- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c @@ -519,3 +519,58 @@ void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream, info_packet->valid = true; } +void mod_build_adaptive_sync_infopacket(const struct dc_stream_state *stream, + enum adaptive_sync_type asType, + const struct AS_Df_params *param, + struct dc_info_packet *info_packet) +{ + info_packet->valid = false; + + memset(info_packet, 0, sizeof(struct dc_info_packet)); + + switch (asType) { + case ADAPTIVE_SYNC_TYPE_DP: + if (stream != NULL) + mod_build_adaptive_sync_infopacket_v2(stream, param, info_packet); + break; + case ADAPTIVE_SYNC_TYPE_PCON_IN_WHITELIST: + mod_build_adaptive_sync_infopacket_v1(info_packet); + break; + case ADAPTIVE_SYNC_TYPE_NONE: + case ADAPTIVE_SYNC_TYPE_PCON_NOT_IN_WHITELIST: + default: + break; + } +} + +void mod_build_adaptive_sync_infopacket_v1(struct dc_info_packet *info_packet) +{ + info_packet->valid = true; + // HEADER {HB0, HB1, HB2, HB3} = {00, Type, Version, Length} + info_packet->hb0 = 0x00; + info_packet->hb1 = 0x22; + info_packet->hb2 = AS_SDP_VER_1; + info_packet->hb3 = 0x00; +} + +void mod_build_adaptive_sync_infopacket_v2(const struct dc_stream_state *stream, + const struct AS_Df_params *param, + struct dc_info_packet *info_packet) +{ + info_packet->valid = true; + // HEADER {HB0, HB1, HB2, HB3} = {00, Type, Version, Length} + info_packet->hb0 = 0x00; + info_packet->hb1 = 0x22; + info_packet->hb2 = AS_SDP_VER_2; + info_packet->hb3 = AS_DP_SDP_LENGTH; + + //Payload + info_packet->sb[0] = param->supportMode; //1: AVT; 0: FAVT + info_packet->sb[1] = (stream->timing.v_total & 0x00FF); + info_packet->sb[2] = (stream->timing.v_total & 0xFF00) >> 8; + //info_packet->sb[3] = 0x00; Target RR, not use fot AVT + info_packet->sb[4] = (param->increase.support << 6 | param->decrease.support << 7); + info_packet->sb[5] = param->increase.frame_duration_hex; + info_packet->sb[6] = param->decrease.frame_duration_hex; +} + diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c index cf4fa87c7db6..e39b133d05af 100644 --- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c +++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c @@ -917,13 +917,14 @@ bool mod_power_only_edp(const struct dc_state *context, const struct dc_stream_s return context && context->stream_count == 1 && dc_is_embedded_signal(stream->signal); } -bool psr_su_set_y_granularity(struct dc *dc, struct dc_link *link, +bool psr_su_set_dsc_slice_height(struct dc *dc, struct dc_link *link, struct dc_stream_state *stream, struct psr_config *config) { uint16_t pic_height; - uint8_t slice_height; + uint16_t slice_height; + config->dsc_slice_height = 0; if ((link->connector_signal & SIGNAL_TYPE_EDP) && (!dc->caps.edp_dsc_support || link->panel_config.dsc.disable_dsc_edp || @@ -934,6 +935,7 @@ bool psr_su_set_y_granularity(struct dc *dc, struct dc_link *link, pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom; slice_height = pic_height / stream->timing.dsc_cfg.num_slices_v; + config->dsc_slice_height = slice_height; if (slice_height) { if (config->su_y_granularity && @@ -941,8 +943,6 @@ bool psr_su_set_y_granularity(struct dc *dc, struct dc_link *link, ASSERT(0); return false; } - - config->su_y_granularity = slice_height; } return true; diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.h b/drivers/gpu/drm/amd/display/modules/power/power_helpers.h index bb16b37b83da..1d3079e56799 100644 --- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.h +++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.h @@ -59,7 +59,7 @@ void mod_power_calc_psr_configs(struct psr_config *psr_config, const struct dc_stream_state *stream); bool mod_power_only_edp(const struct dc_state *context, const struct dc_stream_state *stream); -bool psr_su_set_y_granularity(struct dc *dc, struct dc_link *link, +bool psr_su_set_dsc_slice_height(struct dc *dc, struct dc_link *link, struct dc_stream_state *stream, struct psr_config *config); #endif /* MODULES_POWER_POWER_HELPERS_H_ */ diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c index d0cdc578344d..f89ce6575b15 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c @@ -145,6 +145,7 @@ static struct cmn2asic_msg_mapping smu_v13_0_0_message_map[SMU_MSG_MAX_COUNT] = MSG_MAP(SetBadMemoryPagesRetiredFlagsPerChannel, PPSMC_MSG_SetBadMemoryPagesRetiredFlagsPerChannel, 0), MSG_MAP(AllowGpo, PPSMC_MSG_SetGpoAllow, 0), + MSG_MAP(AllowIHHostInterrupt, PPSMC_MSG_AllowIHHostInterrupt, 0), }; static struct cmn2asic_mapping smu_v13_0_0_clk_map[SMU_CLK_COUNT] = { diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index 5861b0a6247b..847c10aa2098 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -3377,6 +3377,9 @@ void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr, mgr->payload_count--; mgr->next_start_slot -= payload->time_slots; + + if (payload->delete) + drm_dp_mst_put_port_malloc(payload->port); } EXPORT_SYMBOL(drm_dp_remove_payload); @@ -4335,7 +4338,6 @@ int drm_dp_atomic_release_time_slots(struct drm_atomic_state *state, drm_dbg_atomic(mgr->dev, "[MST PORT:%p] TU %d -> 0\n", port, payload->time_slots); if (!payload->delete) { - drm_dp_mst_put_port_malloc(port); payload->pbn = 0; payload->delete = true; topology_state->payload_mask &= ~BIT(payload->vcpi - 1); diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c index 11bb59399471..3d1f50f481cf 100644 --- a/drivers/gpu/drm/drm_buddy.c +++ b/drivers/gpu/drm/drm_buddy.c @@ -38,6 +38,25 @@ static void drm_block_free(struct drm_buddy *mm, kmem_cache_free(slab_blocks, block); } +static void list_insert_sorted(struct drm_buddy *mm, + struct drm_buddy_block *block) +{ + struct drm_buddy_block *node; + struct list_head *head; + + head = &mm->free_list[drm_buddy_block_order(block)]; + if (list_empty(head)) { + list_add(&block->link, head); + return; + } + + list_for_each_entry(node, head, link) + if (drm_buddy_block_offset(block) < drm_buddy_block_offset(node)) + break; + + __list_add(&block->link, node->link.prev, &node->link); +} + static void mark_allocated(struct drm_buddy_block *block) { block->header &= ~DRM_BUDDY_HEADER_STATE; @@ -52,8 +71,7 @@ static void mark_free(struct drm_buddy *mm, block->header &= ~DRM_BUDDY_HEADER_STATE; block->header |= DRM_BUDDY_FREE; - list_add(&block->link, - &mm->free_list[drm_buddy_block_order(block)]); + list_insert_sorted(mm, block); } static void mark_split(struct drm_buddy_block *block) @@ -387,20 +405,26 @@ err_undo: } static struct drm_buddy_block * -get_maxblock(struct list_head *head) +get_maxblock(struct drm_buddy *mm, unsigned int order) { struct drm_buddy_block *max_block = NULL, *node; + unsigned int i; - max_block = list_first_entry_or_null(head, - struct drm_buddy_block, - link); - if (!max_block) - return NULL; + for (i = order; i <= mm->max_order; ++i) { + if (!list_empty(&mm->free_list[i])) { + node = list_last_entry(&mm->free_list[i], + struct drm_buddy_block, + link); + if (!max_block) { + max_block = node; + continue; + } - list_for_each_entry(node, head, link) { - if (drm_buddy_block_offset(node) > - drm_buddy_block_offset(max_block)) - max_block = node; + if (drm_buddy_block_offset(node) > + drm_buddy_block_offset(max_block)) { + max_block = node; + } + } } return max_block; @@ -412,20 +436,23 @@ alloc_from_freelist(struct drm_buddy *mm, unsigned long flags) { struct drm_buddy_block *block = NULL; - unsigned int i; + unsigned int tmp; int err; - for (i = order; i <= mm->max_order; ++i) { - if (flags & DRM_BUDDY_TOPDOWN_ALLOCATION) { - block = get_maxblock(&mm->free_list[i]); - if (block) - break; - } else { - block = list_first_entry_or_null(&mm->free_list[i], - struct drm_buddy_block, - link); - if (block) - break; + if (flags & DRM_BUDDY_TOPDOWN_ALLOCATION) { + block = get_maxblock(mm, order); + if (block) + /* Store the obtained block order */ + tmp = drm_buddy_block_order(block); + } else { + for (tmp = order; tmp <= mm->max_order; ++tmp) { + if (!list_empty(&mm->free_list[tmp])) { + block = list_last_entry(&mm->free_list[tmp], + struct drm_buddy_block, + link); + if (block) + break; + } } } @@ -434,18 +461,18 @@ alloc_from_freelist(struct drm_buddy *mm, BUG_ON(!drm_buddy_block_is_free(block)); - while (i != order) { + while (tmp != order) { err = split_block(mm, block); if (unlikely(err)) goto err_undo; block = block->right; - i--; + tmp--; } return block; err_undo: - if (i != order) + if (tmp != order) __drm_buddy_free(mm, block); return ERR_PTR(err); } diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 97b34f377fe8..28c428e9c530 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -30,7 +30,9 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/console.h> +#include <linux/pci.h> #include <linux/sysrq.h> +#include <linux/vga_switcheroo.h> #include <drm/drm_atomic.h> #include <drm/drm_drv.h> @@ -1952,6 +1954,7 @@ static int drm_fb_helper_find_sizes(struct drm_fb_helper *fb_helper, static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper) { struct drm_client_dev *client = &fb_helper->client; + struct drm_device *dev = fb_helper->dev; struct drm_fb_helper_surface_size sizes; int ret; @@ -1973,6 +1976,11 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper) return ret; strcpy(fb_helper->fb->comm, "[fbcon]"); + + /* Set the fb info for vgaswitcheroo clients. Does nothing otherwise. */ + if (dev_is_pci(dev->dev)) + vga_switcheroo_client_fb_set(to_pci_dev(dev->dev), fb_helper->info); + return 0; } diff --git a/drivers/gpu/drm/drm_fbdev_generic.c b/drivers/gpu/drm/drm_fbdev_generic.c index 43f94aa9e015..365f80717fa1 100644 --- a/drivers/gpu/drm/drm_fbdev_generic.c +++ b/drivers/gpu/drm/drm_fbdev_generic.c @@ -155,11 +155,6 @@ static const struct fb_ops drm_fbdev_fb_ops = { .fb_imageblit = drm_fbdev_fb_imageblit, }; -static struct fb_deferred_io drm_fbdev_defio = { - .delay = HZ / 20, - .deferred_io = drm_fb_helper_deferred_io, -}; - /* * This function uses the client API to create a framebuffer backed by a dumb buffer. */ @@ -206,8 +201,14 @@ static int drm_fbdev_fb_probe(struct drm_fb_helper *fb_helper, return -ENOMEM; info->flags |= FBINFO_VIRTFB | FBINFO_READS_FAST; - info->fbdefio = &drm_fbdev_defio; - fb_deferred_io_init(info); + /* Set a default deferred I/O handler */ + fb_helper->fbdefio.delay = HZ / 20; + fb_helper->fbdefio.deferred_io = drm_fb_helper_deferred_io; + + info->fbdefio = &fb_helper->fbdefio; + ret = fb_deferred_io_init(info); + if (ret) + return ret; } else { /* buffer is mapped for HW framebuffer */ ret = drm_client_buffer_vmap(fb_helper->buffer, &map); diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index ca531dbb749d..b409fe256fd0 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c @@ -316,6 +316,12 @@ static const struct dmi_system_id orientation_data[] = { DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGM"), }, .driver_data = (void *)&lcd1200x1920_rightside_up, + }, { /* Lenovo Ideapad D330-10IGL (HD) */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGL"), + }, + .driver_data = (void *)&lcd800x1280_rightside_up, }, { /* Lenovo Yoga Book X90F / X91F / X91L */ .matches = { /* Non exact match to match all versions */ diff --git a/drivers/gpu/drm/drm_vma_manager.c b/drivers/gpu/drm/drm_vma_manager.c index 7de37f8c68fd..83229a031af0 100644 --- a/drivers/gpu/drm/drm_vma_manager.c +++ b/drivers/gpu/drm/drm_vma_manager.c @@ -240,27 +240,8 @@ void drm_vma_offset_remove(struct drm_vma_offset_manager *mgr, } EXPORT_SYMBOL(drm_vma_offset_remove); -/** - * drm_vma_node_allow - Add open-file to list of allowed users - * @node: Node to modify - * @tag: Tag of file to remove - * - * Add @tag to the list of allowed open-files for this node. If @tag is - * already on this list, the ref-count is incremented. - * - * The list of allowed-users is preserved across drm_vma_offset_add() and - * drm_vma_offset_remove() calls. You may even call it if the node is currently - * not added to any offset-manager. - * - * You must remove all open-files the same number of times as you added them - * before destroying the node. Otherwise, you will leak memory. - * - * This is locked against concurrent access internally. - * - * RETURNS: - * 0 on success, negative error code on internal failure (out-of-mem) - */ -int drm_vma_node_allow(struct drm_vma_offset_node *node, struct drm_file *tag) +static int vma_node_allow(struct drm_vma_offset_node *node, + struct drm_file *tag, bool ref_counted) { struct rb_node **iter; struct rb_node *parent = NULL; @@ -282,7 +263,8 @@ int drm_vma_node_allow(struct drm_vma_offset_node *node, struct drm_file *tag) entry = rb_entry(*iter, struct drm_vma_offset_file, vm_rb); if (tag == entry->vm_tag) { - entry->vm_count++; + if (ref_counted) + entry->vm_count++; goto unlock; } else if (tag > entry->vm_tag) { iter = &(*iter)->rb_right; @@ -307,9 +289,59 @@ unlock: kfree(new); return ret; } + +/** + * drm_vma_node_allow - Add open-file to list of allowed users + * @node: Node to modify + * @tag: Tag of file to remove + * + * Add @tag to the list of allowed open-files for this node. If @tag is + * already on this list, the ref-count is incremented. + * + * The list of allowed-users is preserved across drm_vma_offset_add() and + * drm_vma_offset_remove() calls. You may even call it if the node is currently + * not added to any offset-manager. + * + * You must remove all open-files the same number of times as you added them + * before destroying the node. Otherwise, you will leak memory. + * + * This is locked against concurrent access internally. + * + * RETURNS: + * 0 on success, negative error code on internal failure (out-of-mem) + */ +int drm_vma_node_allow(struct drm_vma_offset_node *node, struct drm_file *tag) +{ + return vma_node_allow(node, tag, true); +} EXPORT_SYMBOL(drm_vma_node_allow); /** + * drm_vma_node_allow_once - Add open-file to list of allowed users + * @node: Node to modify + * @tag: Tag of file to remove + * + * Add @tag to the list of allowed open-files for this node. + * + * The list of allowed-users is preserved across drm_vma_offset_add() and + * drm_vma_offset_remove() calls. You may even call it if the node is currently + * not added to any offset-manager. + * + * This is not ref-counted unlike drm_vma_node_allow() hence drm_vma_node_revoke() + * should only be called once after this. + * + * This is locked against concurrent access internally. + * + * RETURNS: + * 0 on success, negative error code on internal failure (out-of-mem) + */ +int drm_vma_node_allow_once(struct drm_vma_offset_node *node, struct drm_file *tag) +{ + return vma_node_allow(node, tag, false); +} +EXPORT_SYMBOL(drm_vma_node_allow_once); + +/** * drm_vma_node_revoke - Remove open-file from list of allowed users * @node: Node to modify * @tag: Tag of file to remove diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index f47f00b162a4..918470a04591 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -63,6 +63,7 @@ i915-y += i915_driver.o \ # core peripheral code i915-y += \ soc/intel_dram.o \ + soc/intel_gmch.o \ soc/intel_pch.o # core library code @@ -266,6 +267,7 @@ i915-y += \ display/intel_quirks.o \ display/intel_sprite.o \ display/intel_tc.o \ + display/intel_vblank.o \ display/intel_vga.o \ display/i9xx_plane.o \ display/skl_scaler.o \ diff --git a/drivers/gpu/drm/i915/display/g4x_dp.c b/drivers/gpu/drm/i915/display/g4x_dp.c index 24ef36ec2d3d..fa754038d669 100644 --- a/drivers/gpu/drm/i915/display/g4x_dp.c +++ b/drivers/gpu/drm/i915/display/g4x_dp.c @@ -398,6 +398,8 @@ static void intel_dp_get_config(struct intel_encoder *encoder, if (intel_dp_is_edp(intel_dp)) intel_edp_fixup_vbt_bpp(encoder, pipe_config->pipe_bpp); + + intel_audio_codec_get_config(encoder, pipe_config); } static void diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.c b/drivers/gpu/drm/i915/display/g4x_hdmi.c index c3580d96765c..64c3b3990702 100644 --- a/drivers/gpu/drm/i915/display/g4x_hdmi.c +++ b/drivers/gpu/drm/i915/display/g4x_hdmi.c @@ -155,6 +155,8 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder, intel_read_infoframe(encoder, pipe_config, HDMI_INFOFRAME_TYPE_VENDOR, &pipe_config->infoframes.hdmi); + + intel_audio_codec_get_config(encoder, pipe_config); } static void g4x_hdmi_enable_port(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index ae14c794c4bc..d56d01f07bb7 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -2054,7 +2054,7 @@ void icl_dsi_init(struct drm_i915_private *dev_priv) goto err; } - intel_panel_init(intel_connector); + intel_panel_init(intel_connector, NULL); intel_backlight_setup(intel_connector, INVALID_PIPE); diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 10e1fc9d0698..1409bcfb6fd3 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -36,6 +36,7 @@ #include "gt/intel_rps.h" +#include "i915_config.h" #include "intel_atomic_plane.h" #include "intel_cdclk.h" #include "intel_display_trace.h" diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index 626c47e96a6d..a9335c856644 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -71,6 +71,8 @@ struct intel_audio_funcs { void (*audio_codec_disable)(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state); + void (*audio_codec_get_config)(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state); }; /* DP N/M table */ @@ -314,6 +316,27 @@ static int g4x_eld_buffer_size(struct drm_i915_private *i915) return REG_FIELD_GET(G4X_ELD_BUFFER_SIZE_MASK, tmp); } +static void g4x_audio_codec_get_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + u32 *eld = (u32 *)crtc_state->eld; + int eld_buffer_size, len, i; + u32 tmp; + + tmp = intel_de_read(i915, G4X_AUD_CNTL_ST); + if ((tmp & G4X_ELD_VALID) == 0) + return; + + intel_de_rmw(i915, G4X_AUD_CNTL_ST, G4X_ELD_ADDRESS_MASK, 0); + + eld_buffer_size = g4x_eld_buffer_size(i915); + len = min_t(int, sizeof(crtc_state->eld) / 4, eld_buffer_size); + + for (i = 0; i < len; i++) + eld[i] = intel_de_read(i915, G4X_HDMIW_HDMIEDID); +} + static void g4x_audio_codec_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) @@ -335,8 +358,7 @@ static void g4x_audio_codec_enable(struct intel_encoder *encoder, { struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_connector *connector = conn_state->connector; - const u32 *eld = (const u32 *)connector->eld; + const u32 *eld = (const u32 *)crtc_state->eld; int eld_buffer_size, len, i; intel_crtc_wait_for_next_vblank(crtc); @@ -345,7 +367,7 @@ static void g4x_audio_codec_enable(struct intel_encoder *encoder, G4X_ELD_VALID | G4X_ELD_ADDRESS_MASK, 0); eld_buffer_size = g4x_eld_buffer_size(i915); - len = min(drm_eld_size(connector->eld) / 4, eld_buffer_size); + len = min(drm_eld_size(crtc_state->eld) / 4, eld_buffer_size); for (i = 0; i < len; i++) intel_de_write(i915, G4X_HDMIW_HDMIEDID, eld[i]); @@ -459,17 +481,6 @@ hsw_audio_config_update(struct intel_encoder *encoder, hsw_hdmi_audio_config_update(encoder, crtc_state); } -/* ELD buffer size in dwords */ -static int hsw_eld_buffer_size(struct drm_i915_private *i915, - enum transcoder cpu_transcoder) -{ - u32 tmp; - - tmp = intel_de_read(i915, HSW_AUD_DIP_ELD_CTRL(cpu_transcoder)); - - return REG_FIELD_GET(IBX_ELD_BUFFER_SIZE_MASK, tmp); -} - static void hsw_audio_codec_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) @@ -618,10 +629,7 @@ static void hsw_audio_codec_enable(struct intel_encoder *encoder, { struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_connector *connector = conn_state->connector; enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; - const u32 *eld = (const u32 *)connector->eld; - int eld_buffer_size, len, i; mutex_lock(&i915->display.audio.mutex); @@ -639,25 +647,10 @@ static void hsw_audio_codec_enable(struct intel_encoder *encoder, intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD, AUDIO_ELD_VALID(cpu_transcoder), 0); - /* Reset ELD address */ - intel_de_rmw(i915, HSW_AUD_DIP_ELD_CTRL(cpu_transcoder), - IBX_ELD_ADDRESS_MASK, 0); - - eld_buffer_size = hsw_eld_buffer_size(i915, cpu_transcoder); - len = min(drm_eld_size(connector->eld) / 4, eld_buffer_size); - - for (i = 0; i < len; i++) - intel_de_write(i915, HSW_AUD_EDID_DATA(cpu_transcoder), eld[i]); - for (; i < eld_buffer_size; i++) - intel_de_write(i915, HSW_AUD_EDID_DATA(cpu_transcoder), 0); - - drm_WARN_ON(&i915->drm, - (intel_de_read(i915, HSW_AUD_DIP_ELD_CTRL(cpu_transcoder)) & - IBX_ELD_ADDRESS_MASK) != 0); - - /* ELD valid */ - intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD, - 0, AUDIO_ELD_VALID(cpu_transcoder)); + /* + * The audio componenent is used to convey the ELD + * instead using of the hardware ELD buffer. + */ /* Enable timestamps */ hsw_audio_config_update(encoder, crtc_state); @@ -665,47 +658,33 @@ static void hsw_audio_codec_enable(struct intel_encoder *encoder, mutex_unlock(&i915->display.audio.mutex); } -struct ilk_audio_regs { +struct ibx_audio_regs { i915_reg_t hdmiw_hdmiedid, aud_config, aud_cntl_st, aud_cntrl_st2; }; -static void ilk_audio_regs_init(struct drm_i915_private *i915, +static void ibx_audio_regs_init(struct drm_i915_private *i915, enum pipe pipe, - struct ilk_audio_regs *regs) + struct ibx_audio_regs *regs) { - if (HAS_PCH_IBX(i915)) { - regs->hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID(pipe); - regs->aud_config = IBX_AUD_CFG(pipe); - regs->aud_cntl_st = IBX_AUD_CNTL_ST(pipe); - regs->aud_cntrl_st2 = IBX_AUD_CNTL_ST2; - } else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { + if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { regs->hdmiw_hdmiedid = VLV_HDMIW_HDMIEDID(pipe); regs->aud_config = VLV_AUD_CFG(pipe); regs->aud_cntl_st = VLV_AUD_CNTL_ST(pipe); regs->aud_cntrl_st2 = VLV_AUD_CNTL_ST2; - } else { + } else if (HAS_PCH_CPT(i915)) { regs->hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID(pipe); regs->aud_config = CPT_AUD_CFG(pipe); regs->aud_cntl_st = CPT_AUD_CNTL_ST(pipe); regs->aud_cntrl_st2 = CPT_AUD_CNTRL_ST2; + } else if (HAS_PCH_IBX(i915)) { + regs->hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID(pipe); + regs->aud_config = IBX_AUD_CFG(pipe); + regs->aud_cntl_st = IBX_AUD_CNTL_ST(pipe); + regs->aud_cntrl_st2 = IBX_AUD_CNTL_ST2; } } -/* ELD buffer size in dwords */ -static int ilk_eld_buffer_size(struct drm_i915_private *i915, - enum pipe pipe) -{ - struct ilk_audio_regs regs; - u32 tmp; - - ilk_audio_regs_init(i915, pipe, ®s); - - tmp = intel_de_read(i915, regs.aud_cntl_st); - - return REG_FIELD_GET(IBX_ELD_BUFFER_SIZE_MASK, tmp); -} - -static void ilk_audio_codec_disable(struct intel_encoder *encoder, +static void ibx_audio_codec_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) { @@ -713,12 +692,12 @@ static void ilk_audio_codec_disable(struct intel_encoder *encoder, struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); enum port port = encoder->port; enum pipe pipe = crtc->pipe; - struct ilk_audio_regs regs; + struct ibx_audio_regs regs; if (drm_WARN_ON(&i915->drm, port == PORT_A)) return; - ilk_audio_regs_init(i915, pipe, ®s); + ibx_audio_regs_init(i915, pipe, ®s); mutex_lock(&i915->display.audio.mutex); @@ -741,25 +720,22 @@ static void ilk_audio_codec_disable(struct intel_encoder *encoder, intel_crtc_wait_for_next_vblank(crtc); } -static void ilk_audio_codec_enable(struct intel_encoder *encoder, +static void ibx_audio_codec_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_connector *connector = conn_state->connector; - const u32 *eld = (const u32 *)connector->eld; enum port port = encoder->port; enum pipe pipe = crtc->pipe; - int eld_buffer_size, len, i; - struct ilk_audio_regs regs; + struct ibx_audio_regs regs; if (drm_WARN_ON(&i915->drm, port == PORT_A)) return; intel_crtc_wait_for_next_vblank(crtc); - ilk_audio_regs_init(i915, pipe, ®s); + ibx_audio_regs_init(i915, pipe, ®s); mutex_lock(&i915->display.audio.mutex); @@ -767,24 +743,10 @@ static void ilk_audio_codec_enable(struct intel_encoder *encoder, intel_de_rmw(i915, regs.aud_cntrl_st2, IBX_ELD_VALID(port), 0); - /* Reset ELD address */ - intel_de_rmw(i915, regs.aud_cntl_st, - IBX_ELD_ADDRESS_MASK, 0); - - eld_buffer_size = ilk_eld_buffer_size(i915, pipe); - len = min(drm_eld_size(connector->eld) / 4, eld_buffer_size); - - for (i = 0; i < len; i++) - intel_de_write(i915, regs.hdmiw_hdmiedid, eld[i]); - for (; i < eld_buffer_size; i++) - intel_de_write(i915, regs.hdmiw_hdmiedid, 0); - - drm_WARN_ON(&i915->drm, - (intel_de_read(i915, regs.aud_cntl_st) & IBX_ELD_ADDRESS_MASK) != 0); - - /* ELD valid */ - intel_de_rmw(i915, regs.aud_cntrl_st2, - 0, IBX_ELD_VALID(port)); + /* + * The audio componenent is used to convey the ELD + * instead using of the hardware ELD buffer. + */ /* Enable timestamps */ intel_de_rmw(i915, regs.aud_config, @@ -809,6 +771,30 @@ void intel_audio_sdp_split_update(struct intel_encoder *encoder, crtc_state->sdp_split_enable ? AUD_ENABLE_SDP_SPLIT : 0); } +bool intel_audio_compute_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct drm_connector *connector = conn_state->connector; + const struct drm_display_mode *adjusted_mode = + &crtc_state->hw.adjusted_mode; + + if (!connector->eld[0]) { + drm_dbg_kms(&i915->drm, + "Bogus ELD on [CONNECTOR:%d:%s]\n", + connector->base.id, connector->name); + return false; + } + + BUILD_BUG_ON(sizeof(crtc_state->eld) != sizeof(connector->eld)); + memcpy(crtc_state->eld, connector->eld, sizeof(crtc_state->eld)); + + crtc_state->eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2; + + return true; +} + /** * intel_audio_codec_enable - Enable the audio codec for HD audio * @encoder: encoder on which to enable audio @@ -825,27 +811,19 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct i915_audio_component *acomp = i915->display.audio.component; struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_connector *connector = conn_state->connector; - const struct drm_display_mode *adjusted_mode = - &crtc_state->hw.adjusted_mode; + struct intel_connector *connector = to_intel_connector(conn_state->connector); + struct intel_audio_state *audio_state; enum port port = encoder->port; enum pipe pipe = crtc->pipe; if (!crtc_state->has_audio) return; - drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Enable audio codec on pipe %c, %u bytes ELD\n", - connector->base.id, connector->name, + drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Enable audio codec on [CRTC:%d:%s], %u bytes ELD\n", + connector->base.base.id, connector->base.name, encoder->base.base.id, encoder->base.name, - pipe_name(pipe), drm_eld_size(connector->eld)); - - /* FIXME precompute the ELD in .compute_config() */ - if (!connector->eld[0]) - drm_dbg_kms(&i915->drm, - "Bogus ELD on [CONNECTOR:%d:%s]\n", - connector->base.id, connector->name); - - connector->eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2; + crtc->base.base.id, crtc->base.name, + drm_eld_size(crtc_state->eld)); if (i915->display.funcs.audio) i915->display.funcs.audio->audio_codec_enable(encoder, @@ -853,10 +831,13 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, conn_state); mutex_lock(&i915->display.audio.mutex); - encoder->audio_connector = connector; - /* referred in audio callbacks */ - i915->display.audio.encoder_map[pipe] = encoder; + audio_state = &i915->display.audio.state[pipe]; + + audio_state->encoder = encoder; + BUILD_BUG_ON(sizeof(audio_state->eld) != sizeof(crtc_state->eld)); + memcpy(audio_state->eld, crtc_state->eld, sizeof(audio_state->eld)); + mutex_unlock(&i915->display.audio.mutex); if (acomp && acomp->base.audio_ops && @@ -868,7 +849,7 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, (int)port, (int)pipe); } - intel_lpe_audio_notify(i915, pipe, port, connector->eld, + intel_lpe_audio_notify(i915, pipe, port, crtc_state->eld, crtc_state->port_clock, intel_crtc_has_dp_encoder(crtc_state)); } @@ -889,16 +870,18 @@ void intel_audio_codec_disable(struct intel_encoder *encoder, struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct i915_audio_component *acomp = i915->display.audio.component; struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); - struct drm_connector *connector = old_conn_state->connector; + struct intel_connector *connector = to_intel_connector(old_conn_state->connector); + struct intel_audio_state *audio_state; enum port port = encoder->port; enum pipe pipe = crtc->pipe; if (!old_crtc_state->has_audio) return; - drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Disable audio codec on pipe %c\n", - connector->base.id, connector->name, - encoder->base.base.id, encoder->base.name, pipe_name(pipe)); + drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Disable audio codec on [CRTC:%d:%s]\n", + connector->base.base.id, connector->base.name, + encoder->base.base.id, encoder->base.name, + crtc->base.base.id, crtc->base.name); if (i915->display.funcs.audio) i915->display.funcs.audio->audio_codec_disable(encoder, @@ -906,8 +889,12 @@ void intel_audio_codec_disable(struct intel_encoder *encoder, old_conn_state); mutex_lock(&i915->display.audio.mutex); - encoder->audio_connector = NULL; - i915->display.audio.encoder_map[pipe] = NULL; + + audio_state = &i915->display.audio.state[pipe]; + + audio_state->encoder = NULL; + memset(audio_state->eld, 0, sizeof(audio_state->eld)); + mutex_unlock(&i915->display.audio.mutex); if (acomp && acomp->base.audio_ops && @@ -922,19 +909,52 @@ void intel_audio_codec_disable(struct intel_encoder *encoder, intel_lpe_audio_notify(i915, pipe, port, NULL, 0, false); } +static void intel_acomp_get_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct intel_audio_state *audio_state; + enum pipe pipe = crtc->pipe; + + mutex_lock(&i915->display.audio.mutex); + + audio_state = &i915->display.audio.state[pipe]; + + if (audio_state->encoder) + memcpy(crtc_state->eld, audio_state->eld, sizeof(audio_state->eld)); + + mutex_unlock(&i915->display.audio.mutex); +} + +void intel_audio_codec_get_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + + if (!crtc_state->has_audio) + return; + + if (i915->display.funcs.audio) + i915->display.funcs.audio->audio_codec_get_config(encoder, crtc_state); +} + static const struct intel_audio_funcs g4x_audio_funcs = { .audio_codec_enable = g4x_audio_codec_enable, .audio_codec_disable = g4x_audio_codec_disable, + .audio_codec_get_config = g4x_audio_codec_get_config, }; -static const struct intel_audio_funcs ilk_audio_funcs = { - .audio_codec_enable = ilk_audio_codec_enable, - .audio_codec_disable = ilk_audio_codec_disable, +static const struct intel_audio_funcs ibx_audio_funcs = { + .audio_codec_enable = ibx_audio_codec_enable, + .audio_codec_disable = ibx_audio_codec_disable, + .audio_codec_get_config = intel_acomp_get_config, }; static const struct intel_audio_funcs hsw_audio_funcs = { .audio_codec_enable = hsw_audio_codec_enable, .audio_codec_disable = hsw_audio_codec_disable, + .audio_codec_get_config = intel_acomp_get_config, }; /** @@ -945,12 +965,11 @@ void intel_audio_hooks_init(struct drm_i915_private *i915) { if (IS_G4X(i915)) i915->display.funcs.audio = &g4x_audio_funcs; - else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) - i915->display.funcs.audio = &ilk_audio_funcs; + else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915) || + HAS_PCH_CPT(i915) || HAS_PCH_IBX(i915)) + i915->display.funcs.audio = &ibx_audio_funcs; else if (IS_HASWELL(i915) || DISPLAY_VER(i915) >= 8) i915->display.funcs.audio = &hsw_audio_funcs; - else if (HAS_PCH_SPLIT(i915)) - i915->display.funcs.audio = &ilk_audio_funcs; } struct aud_ts_cdclk_m_n { @@ -1128,35 +1147,32 @@ static int i915_audio_component_get_cdclk_freq(struct device *kdev) } /* - * get the intel_encoder according to the parameter port and pipe - * intel_encoder is saved by the index of pipe - * MST & (pipe >= 0): return the audio.encoder_map[pipe], + * get the intel audio state according to the parameter port and pipe + * MST & (pipe >= 0): return the audio.state[pipe].encoder], * when port is matched * MST & (pipe < 0): this is invalid * Non-MST & (pipe >= 0): only pipe = 0 (the first device entry) * will get the right intel_encoder with port matched * Non-MST & (pipe < 0): get the right intel_encoder with port matched */ -static struct intel_encoder *get_saved_enc(struct drm_i915_private *i915, - int port, int pipe) +static struct intel_audio_state *find_audio_state(struct drm_i915_private *i915, + int port, int pipe) { /* MST */ if (pipe >= 0) { + struct intel_audio_state *audio_state; struct intel_encoder *encoder; if (drm_WARN_ON(&i915->drm, - pipe >= ARRAY_SIZE(i915->display.audio.encoder_map))) + pipe >= ARRAY_SIZE(i915->display.audio.state))) return NULL; - encoder = i915->display.audio.encoder_map[pipe]; - /* - * when bootup, audio driver may not know it is - * MST or not. So it will poll all the port & pipe - * combinations - */ + audio_state = &i915->display.audio.state[pipe]; + encoder = audio_state->encoder; + if (encoder && encoder->port == port && encoder->type == INTEL_OUTPUT_DP_MST) - return encoder; + return audio_state; } /* Non-MST */ @@ -1164,13 +1180,15 @@ static struct intel_encoder *get_saved_enc(struct drm_i915_private *i915, return NULL; for_each_pipe(i915, pipe) { + struct intel_audio_state *audio_state; struct intel_encoder *encoder; - encoder = i915->display.audio.encoder_map[pipe]; + audio_state = &i915->display.audio.state[pipe]; + encoder = audio_state->encoder; if (encoder && encoder->port == port && encoder->type != INTEL_OUTPUT_DP_MST) - return encoder; + return audio_state; } return NULL; @@ -1181,6 +1199,7 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, { struct drm_i915_private *i915 = kdev_to_i915(kdev); struct i915_audio_component *acomp = i915->display.audio.component; + const struct intel_audio_state *audio_state; struct intel_encoder *encoder; struct intel_crtc *crtc; unsigned long cookie; @@ -1192,20 +1211,22 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, cookie = i915_audio_component_get_power(kdev); mutex_lock(&i915->display.audio.mutex); - /* 1. get the pipe */ - encoder = get_saved_enc(i915, port, pipe); - if (!encoder || !encoder->base.crtc) { - drm_dbg_kms(&i915->drm, "Not valid for port %c\n", - port_name(port)); + audio_state = find_audio_state(i915, port, pipe); + if (!audio_state) { + drm_dbg_kms(&i915->drm, "Not valid for port %c\n", port_name(port)); err = -ENODEV; goto unlock; } + encoder = audio_state->encoder; + + /* FIXME stop using the legacy crtc pointer */ crtc = to_intel_crtc(encoder->base.crtc); /* port must be valid now, otherwise the pipe will be invalid */ acomp->aud_sample_rate[port] = rate; + /* FIXME get rid of the crtc->config stuff */ hsw_audio_config_update(encoder, crtc->config); unlock: @@ -1219,24 +1240,22 @@ static int i915_audio_component_get_eld(struct device *kdev, int port, unsigned char *buf, int max_bytes) { struct drm_i915_private *i915 = kdev_to_i915(kdev); - struct intel_encoder *intel_encoder; - const u8 *eld; - int ret = -EINVAL; + const struct intel_audio_state *audio_state; + int ret = 0; mutex_lock(&i915->display.audio.mutex); - intel_encoder = get_saved_enc(i915, port, pipe); - if (!intel_encoder) { - drm_dbg_kms(&i915->drm, "Not valid for port %c\n", - port_name(port)); + audio_state = find_audio_state(i915, port, pipe); + if (!audio_state) { + drm_dbg_kms(&i915->drm, "Not valid for port %c\n", port_name(port)); mutex_unlock(&i915->display.audio.mutex); - return ret; + return -EINVAL; } - ret = 0; - *enabled = intel_encoder->audio_connector != NULL; + *enabled = audio_state->encoder != NULL; if (*enabled) { - eld = intel_encoder->audio_connector->eld; + const u8 *eld = audio_state->eld; + ret = drm_eld_size(eld); memcpy(buf, eld, min(max_bytes, ret)); } diff --git a/drivers/gpu/drm/i915/display/intel_audio.h b/drivers/gpu/drm/i915/display/intel_audio.h index 1b87257c6a17..07d034a981e9 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.h +++ b/drivers/gpu/drm/i915/display/intel_audio.h @@ -6,18 +6,25 @@ #ifndef __INTEL_AUDIO_H__ #define __INTEL_AUDIO_H__ +#include <linux/types.h> + struct drm_connector_state; struct drm_i915_private; struct intel_crtc_state; struct intel_encoder; void intel_audio_hooks_init(struct drm_i915_private *dev_priv); +bool intel_audio_compute_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state, + struct drm_connector_state *conn_state); void intel_audio_codec_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state); void intel_audio_codec_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state); +void intel_audio_codec_get_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state); void intel_audio_cdclk_change_pre(struct drm_i915_private *dev_priv); void intel_audio_cdclk_change_post(struct drm_i915_private *dev_priv); void intel_audio_init(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 55544d484318..e6ca51232dcf 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -25,16 +25,15 @@ * */ -#include <drm/drm_edid.h> #include <drm/display/drm_dp_helper.h> #include <drm/display/drm_dsc_helper.h> - -#include "display/intel_display.h" -#include "display/intel_display_types.h" -#include "display/intel_gmbus.h" +#include <drm/drm_edid.h> #include "i915_drv.h" #include "i915_reg.h" +#include "intel_display.h" +#include "intel_display_types.h" +#include "intel_gmbus.h" #define _INTEL_BIOS_PRIVATE #include "intel_vbt_defs.h" @@ -620,14 +619,14 @@ static void dump_pnp_id(struct drm_i915_private *i915, static int opregion_get_panel_type(struct drm_i915_private *i915, const struct intel_bios_encoder_data *devdata, - const struct edid *edid, bool use_fallback) + const struct drm_edid *drm_edid, bool use_fallback) { return intel_opregion_get_panel_type(i915); } static int vbt_get_panel_type(struct drm_i915_private *i915, const struct intel_bios_encoder_data *devdata, - const struct edid *edid, bool use_fallback) + const struct drm_edid *drm_edid, bool use_fallback) { const struct bdb_lvds_options *lvds_options; @@ -652,12 +651,13 @@ static int vbt_get_panel_type(struct drm_i915_private *i915, static int pnpid_get_panel_type(struct drm_i915_private *i915, const struct intel_bios_encoder_data *devdata, - const struct edid *edid, bool use_fallback) + const struct drm_edid *drm_edid, bool use_fallback) { const struct bdb_lvds_lfp_data *data; const struct bdb_lvds_lfp_data_ptrs *ptrs; const struct lvds_pnp_id *edid_id; struct lvds_pnp_id edid_id_nodate; + const struct edid *edid = drm_edid_raw(drm_edid); /* FIXME */ int i, best = -1; if (!edid) @@ -701,7 +701,7 @@ static int pnpid_get_panel_type(struct drm_i915_private *i915, static int fallback_get_panel_type(struct drm_i915_private *i915, const struct intel_bios_encoder_data *devdata, - const struct edid *edid, bool use_fallback) + const struct drm_edid *drm_edid, bool use_fallback) { return use_fallback ? 0 : -1; } @@ -715,13 +715,13 @@ enum panel_type { static int get_panel_type(struct drm_i915_private *i915, const struct intel_bios_encoder_data *devdata, - const struct edid *edid, bool use_fallback) + const struct drm_edid *drm_edid, bool use_fallback) { struct { const char *name; int (*get_panel_type)(struct drm_i915_private *i915, const struct intel_bios_encoder_data *devdata, - const struct edid *edid, bool use_fallback); + const struct drm_edid *drm_edid, bool use_fallback); int panel_type; } panel_types[] = { [PANEL_TYPE_OPREGION] = { @@ -745,7 +745,7 @@ static int get_panel_type(struct drm_i915_private *i915, for (i = 0; i < ARRAY_SIZE(panel_types); i++) { panel_types[i].panel_type = panel_types[i].get_panel_type(i915, devdata, - edid, use_fallback); + drm_edid, use_fallback); drm_WARN_ON(&i915->drm, panel_types[i].panel_type > 0xf && panel_types[i].panel_type != 0xff); @@ -3187,7 +3187,7 @@ out: static void intel_bios_init_panel(struct drm_i915_private *i915, struct intel_panel *panel, const struct intel_bios_encoder_data *devdata, - const struct edid *edid, + const struct drm_edid *drm_edid, bool use_fallback) { /* already have it? */ @@ -3197,7 +3197,7 @@ static void intel_bios_init_panel(struct drm_i915_private *i915, } panel->vbt.panel_type = get_panel_type(i915, devdata, - edid, use_fallback); + drm_edid, use_fallback); if (panel->vbt.panel_type < 0) { drm_WARN_ON(&i915->drm, use_fallback); return; @@ -3228,9 +3228,9 @@ void intel_bios_init_panel_early(struct drm_i915_private *i915, void intel_bios_init_panel_late(struct drm_i915_private *i915, struct intel_panel *panel, const struct intel_bios_encoder_data *devdata, - const struct edid *edid) + const struct drm_edid *drm_edid) { - intel_bios_init_panel(i915, panel, devdata, edid, true); + intel_bios_init_panel(i915, panel, devdata, drm_edid, true); } /** diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h index ff1fdd2e0c1c..d221f784aa88 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.h +++ b/drivers/gpu/drm/i915/display/intel_bios.h @@ -32,8 +32,8 @@ #include <linux/types.h> +struct drm_edid; struct drm_i915_private; -struct edid; struct intel_bios_encoder_data; struct intel_crtc_state; struct intel_encoder; @@ -238,7 +238,7 @@ void intel_bios_init_panel_early(struct drm_i915_private *dev_priv, void intel_bios_init_panel_late(struct drm_i915_private *dev_priv, struct intel_panel *panel, const struct intel_bios_encoder_data *devdata, - const struct edid *edid); + const struct drm_edid *drm_edid); void intel_bios_fini_panel(struct intel_panel *panel); void intel_bios_driver_remove(struct drm_i915_private *dev_priv); bool intel_bios_is_valid_vbt(const void *buf, size_t size); diff --git a/drivers/gpu/drm/i915/display/intel_bw.h b/drivers/gpu/drm/i915/display/intel_bw.h index cb7ee3a24a58..f20292143745 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.h +++ b/drivers/gpu/drm/i915/display/intel_bw.h @@ -8,7 +8,7 @@ #include <drm/drm_atomic.h> -#include "intel_display.h" +#include "intel_display_limits.h" #include "intel_display_power.h" #include "intel_global_state.h" diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.h b/drivers/gpu/drm/i915/display/intel_cdclk.h index c674879a84a5..51e2f6a11ce4 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.h +++ b/drivers/gpu/drm/i915/display/intel_cdclk.h @@ -8,7 +8,7 @@ #include <linux/types.h> -#include "intel_display.h" +#include "intel_display_limits.h" #include "intel_global_state.h" struct drm_i915_private; diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index d57631b0bb9a..8d97c299e657 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -847,17 +847,6 @@ static void ilk_lut_write(const struct intel_crtc_state *crtc_state, intel_de_write_fw(i915, reg, val); } -static void ilk_lut_write_indexed(const struct intel_crtc_state *crtc_state, - i915_reg_t reg, u32 val) -{ - struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); - - if (crtc_state->dsb) - intel_dsb_indexed_reg_write(crtc_state->dsb, reg, val); - else - intel_de_write_fw(i915, reg, val); -} - static void ilk_load_lut_8(const struct intel_crtc_state *crtc_state, const struct drm_property_blob *blob) { @@ -962,8 +951,8 @@ static void bdw_load_lut_10(const struct intel_crtc_state *crtc_state, prec_index); for (i = 0; i < lut_size; i++) - ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe), - ilk_lut_10(&lut[i])); + ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_10(&lut[i])); /* * Reset the index, otherwise it prevents the legacy palette to be @@ -1093,13 +1082,13 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state, * ToDo: Extend to max 7.0. Enable 32 bit input value * as compared to just 16 to achieve this. */ - ilk_lut_write_indexed(crtc_state, PRE_CSC_GAMC_DATA(pipe), - lut[i].green); + ilk_lut_write(crtc_state, PRE_CSC_GAMC_DATA(pipe), + lut[i].green); } /* Clamp values > 1.0. */ while (i++ < glk_degamma_lut_size(i915)) - ilk_lut_write_indexed(crtc_state, PRE_CSC_GAMC_DATA(pipe), 1 << 16); + ilk_lut_write(crtc_state, PRE_CSC_GAMC_DATA(pipe), 1 << 16); ilk_lut_write(crtc_state, PRE_CSC_GAMC_INDEX(pipe), 0); } @@ -1165,10 +1154,10 @@ icl_program_gamma_superfine_segment(const struct intel_crtc_state *crtc_state) for (i = 0; i < 9; i++) { const struct drm_color_lut *entry = &lut[i]; - ilk_lut_write_indexed(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe), - ilk_lut_12p4_ldw(entry)); - ilk_lut_write_indexed(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe), - ilk_lut_12p4_udw(entry)); + ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe), + ilk_lut_12p4_ldw(entry)); + ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe), + ilk_lut_12p4_udw(entry)); } ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_INDEX(pipe), @@ -1204,10 +1193,10 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state) for (i = 1; i < 257; i++) { entry = &lut[i * 8]; - ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe), - ilk_lut_12p4_ldw(entry)); - ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe), - ilk_lut_12p4_udw(entry)); + ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_12p4_ldw(entry)); + ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_12p4_udw(entry)); } /* @@ -1225,10 +1214,10 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state) for (i = 0; i < 256; i++) { entry = &lut[i * 8 * 128]; - ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe), - ilk_lut_12p4_ldw(entry)); - ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe), - ilk_lut_12p4_udw(entry)); + ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_12p4_ldw(entry)); + ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_12p4_udw(entry)); } ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe), @@ -1391,7 +1380,7 @@ void intel_color_prepare_commit(struct intel_crtc_state *crtc_state) /* FIXME DSB has issues loading LUTs, disable it for now */ return; - crtc_state->dsb = intel_dsb_prepare(crtc); + crtc_state->dsb = intel_dsb_prepare(crtc, 1024); } void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state) diff --git a/drivers/gpu/drm/i915/display/intel_connector.c b/drivers/gpu/drm/i915/display/intel_connector.c index 562da3b741e2..257afac34839 100644 --- a/drivers/gpu/drm/i915/display/intel_connector.c +++ b/drivers/gpu/drm/i915/display/intel_connector.c @@ -95,13 +95,10 @@ void intel_connector_destroy(struct drm_connector *connector) { struct intel_connector *intel_connector = to_intel_connector(connector); - kfree(intel_connector->detect_edid); + drm_edid_free(intel_connector->detect_edid); intel_hdcp_cleanup(intel_connector); - if (!IS_ERR_OR_NULL(intel_connector->edid)) - kfree(intel_connector->edid); - intel_panel_fini(intel_connector); drm_connector_cleanup(connector); diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c index 037fc140b585..82be0fbe9934 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -28,6 +28,7 @@ #include "intel_pipe_crc.h" #include "intel_psr.h" #include "intel_sprite.h" +#include "intel_vblank.h" #include "intel_vrr.h" #include "skl_universal_plane.h" diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c index e3273fe8ddac..2422d6ef5777 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c +++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c @@ -3,6 +3,8 @@ * Copyright © 2022 Intel Corporation */ +#include <drm/drm_edid.h> + #include "i915_drv.h" #include "intel_crtc_state_dump.h" #include "intel_display_types.h" @@ -56,6 +58,17 @@ intel_dump_dp_vsc_sdp(struct drm_i915_private *i915, drm_dp_vsc_sdp_log(KERN_DEBUG, i915->drm.dev, vsc); } +static void +intel_dump_buffer(struct drm_i915_private *i915, + const char *prefix, const u8 *buf, size_t len) +{ + if (!drm_debug_enabled(DRM_UT_KMS)) + return; + + print_hex_dump(KERN_DEBUG, prefix, DUMP_PREFIX_NONE, + 16, 0, buf, len, false); +} + #define OUTPUT_TYPE(x) [INTEL_OUTPUT_ ## x] = #x static const char * const output_type_str[] = { @@ -236,6 +249,10 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, intel_hdmi_infoframe_enable(DP_SDP_VSC)) intel_dump_dp_vsc_sdp(i915, &pipe_config->infoframes.vsc); + if (pipe_config->has_audio) + intel_dump_buffer(i915, "ELD: ", pipe_config->eld, + drm_eld_size(pipe_config->eld)); + drm_dbg_kms(&i915->drm, "vrr: %s, vmin: %d, vmax: %d, pipeline full: %d, guardband: %d flipline: %d, vmin vblank: %d, vmax vblank: %d\n", str_yes_no(pipe_config->vrr.enable), pipe_config->vrr.vmin, pipe_config->vrr.vmax, diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 1f5a471a0adf..254559abedfb 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3496,6 +3496,8 @@ static void intel_ddi_get_config(struct intel_encoder *encoder, intel_read_dp_sdp(encoder, pipe_config, DP_SDP_VSC); intel_psr_get_config(encoder, pipe_config); + + intel_audio_codec_get_config(encoder, pipe_config); } void intel_ddi_get_clock(struct intel_encoder *encoder, @@ -4323,7 +4325,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) } if (intel_phy_is_snps(dev_priv, phy) && - dev_priv->snps_phy_failed_calibration & BIT(phy)) { + dev_priv->display.snps.phy_failed_calibration & BIT(phy)) { drm_dbg_kms(&dev_priv->drm, "SNPS PHY %c failed to calibrate, proceeding anyway\n", phy_name(phy)); diff --git a/drivers/gpu/drm/i915/display/intel_de.h b/drivers/gpu/drm/i915/display/intel_de.h index 3dbd76fdabd6..42552d8c151e 100644 --- a/drivers/gpu/drm/i915/display/intel_de.h +++ b/drivers/gpu/drm/i915/display/intel_de.h @@ -22,6 +22,13 @@ intel_de_read8(struct drm_i915_private *i915, i915_reg_t reg) return intel_uncore_read8(&i915->uncore, reg); } +static inline u64 +intel_de_read64_2x32(struct drm_i915_private *i915, + i915_reg_t lower_reg, i915_reg_t upper_reg) +{ + return intel_uncore_read64_2x32(&i915->uncore, lower_reg, upper_reg); +} + static inline void intel_de_posting_read(struct drm_i915_private *i915, i915_reg_t reg) { diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e75b9b2a0e01..717ca3d7890d 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -24,15 +24,15 @@ * Eric Anholt <eric@anholt.net> */ -#include <acpi/video.h> +#include <linux/dma-resv.h> #include <linux/i2c.h> #include <linux/input.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/dma-resv.h> #include <linux/slab.h> #include <linux/string_helpers.h> #include <linux/vga_switcheroo.h> +#include <acpi/video.h> #include <drm/display/drm_dp_helper.h> #include <drm/drm_atomic.h> @@ -45,28 +45,6 @@ #include <drm/drm_probe_helper.h> #include <drm/drm_rect.h> -#include "display/intel_audio.h" -#include "display/intel_crt.h" -#include "display/intel_ddi.h" -#include "display/intel_display_debugfs.h" -#include "display/intel_display_power.h" -#include "display/intel_dp.h" -#include "display/intel_dp_mst.h" -#include "display/intel_dpll.h" -#include "display/intel_dpll_mgr.h" -#include "display/intel_drrs.h" -#include "display/intel_dsi.h" -#include "display/intel_dvo.h" -#include "display/intel_fb.h" -#include "display/intel_gmbus.h" -#include "display/intel_hdmi.h" -#include "display/intel_lvds.h" -#include "display/intel_sdvo.h" -#include "display/intel_snps_phy.h" -#include "display/intel_tv.h" -#include "display/intel_vdsc.h" -#include "display/intel_vrr.h" - #include "gem/i915_gem_lmem.h" #include "gem/i915_gem_object.h" @@ -76,31 +54,48 @@ #include "i915_drv.h" #include "i915_reg.h" #include "i915_utils.h" +#include "i9xx_plane.h" #include "icl_dsi.h" #include "intel_acpi.h" #include "intel_atomic.h" #include "intel_atomic_plane.h" +#include "intel_audio.h" #include "intel_bw.h" #include "intel_cdclk.h" #include "intel_color.h" +#include "intel_crt.h" #include "intel_crtc.h" #include "intel_crtc_state_dump.h" +#include "intel_ddi.h" #include "intel_de.h" +#include "intel_display_debugfs.h" +#include "intel_display_power.h" #include "intel_display_types.h" #include "intel_dmc.h" +#include "intel_dp.h" #include "intel_dp_link_training.h" +#include "intel_dp_mst.h" #include "intel_dpio_phy.h" +#include "intel_dpll.h" +#include "intel_dpll_mgr.h" #include "intel_dpt.h" +#include "intel_drrs.h" +#include "intel_dsi.h" +#include "intel_dvo.h" +#include "intel_fb.h" #include "intel_fbc.h" #include "intel_fbdev.h" #include "intel_fdi.h" #include "intel_fifo_underrun.h" #include "intel_frontbuffer.h" +#include "intel_gmbus.h" #include "intel_hdcp.h" +#include "intel_hdmi.h" #include "intel_hotplug.h" #include "intel_hti.h" -#include "intel_modeset_verify.h" +#include "intel_lvds.h" #include "intel_modeset_setup.h" +#include "intel_modeset_verify.h" #include "intel_overlay.h" #include "intel_panel.h" #include "intel_pch_display.h" @@ -112,10 +107,15 @@ #include "intel_pps.h" #include "intel_psr.h" #include "intel_quirks.h" +#include "intel_sdvo.h" +#include "intel_snps_phy.h" #include "intel_sprite.h" #include "intel_tc.h" +#include "intel_tv.h" +#include "intel_vblank.h" +#include "intel_vdsc.h" #include "intel_vga.h" -#include "i9xx_plane.h" +#include "intel_vrr.h" #include "skl_scaler.h" #include "skl_universal_plane.h" #include "skl_watermark.h" @@ -385,41 +385,6 @@ struct intel_crtc *intel_master_crtc(const struct intel_crtc_state *crtc_state) return to_intel_crtc(crtc_state->uapi.crtc); } -static bool pipe_scanline_is_moving(struct drm_i915_private *dev_priv, - enum pipe pipe) -{ - i915_reg_t reg = PIPEDSL(pipe); - u32 line1, line2; - - line1 = intel_de_read(dev_priv, reg) & PIPEDSL_LINE_MASK; - msleep(5); - line2 = intel_de_read(dev_priv, reg) & PIPEDSL_LINE_MASK; - - return line1 != line2; -} - -static void wait_for_pipe_scanline_moving(struct intel_crtc *crtc, bool state) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum pipe pipe = crtc->pipe; - - /* Wait for the display line to settle/start moving */ - if (wait_for(pipe_scanline_is_moving(dev_priv, pipe) == state, 100)) - drm_err(&dev_priv->drm, - "pipe %c scanline %s wait timed out\n", - pipe_name(pipe), str_on_off(state)); -} - -static void intel_wait_for_pipe_scanline_stopped(struct intel_crtc *crtc) -{ - wait_for_pipe_scanline_moving(crtc, false); -} - -static void intel_wait_for_pipe_scanline_moving(struct intel_crtc *crtc) -{ - wait_for_pipe_scanline_moving(crtc, true); -} - static void intel_wait_for_pipe_off(const struct intel_crtc_state *old_crtc_state) { @@ -1095,22 +1060,6 @@ intel_get_crtc_new_encoder(const struct intel_atomic_state *state, return encoder; } -static void cpt_verify_modeset(struct drm_i915_private *dev_priv, - enum pipe pipe) -{ - i915_reg_t dslreg = PIPEDSL(pipe); - u32 temp; - - temp = intel_de_read(dev_priv, dslreg); - udelay(500); - if (wait_for(intel_de_read(dev_priv, dslreg) != temp, 5)) { - if (wait_for(intel_de_read(dev_priv, dslreg) != temp, 5)) - drm_err(&dev_priv->drm, - "mode set failed: pipe %c stuck\n", - pipe_name(pipe)); - } -} - static void ilk_pfit_enable(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -1805,7 +1754,7 @@ static void ilk_crtc_enable(struct intel_atomic_state *state, intel_encoders_enable(state, crtc); if (HAS_PCH_CPT(dev_priv)) - cpt_verify_modeset(dev_priv, pipe); + intel_wait_for_pipe_scanline_moving(crtc); /* * Must wait for vblank to avoid spurious PCH FIFO underruns. @@ -1918,6 +1867,8 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, if (drm_WARN_ON(&dev_priv->drm, crtc->active)) return; + intel_dmc_enable_pipe(dev_priv, crtc->pipe); + if (!new_crtc_state->bigjoiner_pipes) { intel_encoders_pre_pll_enable(state, crtc); @@ -2053,6 +2004,7 @@ static void hsw_crtc_disable(struct intel_atomic_state *state, { const struct intel_crtc_state *old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); /* * FIXME collapse everything to one hook. @@ -2062,6 +2014,8 @@ static void hsw_crtc_disable(struct intel_atomic_state *state, intel_encoders_disable(state, crtc); intel_encoders_post_disable(state, crtc); } + + intel_dmc_disable_pipe(i915, crtc->pipe); } static void i9xx_pfit_enable(const struct intel_crtc_state *crtc_state) @@ -3292,7 +3246,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, if (DISPLAY_VER(dev_priv) >= 4) { /* No way to read it out on pipes B and C */ if (IS_CHERRYVIEW(dev_priv) && crtc->pipe != PIPE_A) - tmp = dev_priv->chv_dpll_md[crtc->pipe]; + tmp = dev_priv->display.state.chv_dpll_md[crtc->pipe]; else tmp = intel_de_read(dev_priv, DPLL_MD(crtc->pipe)); pipe_config->pixel_multiplier = @@ -5429,6 +5383,12 @@ intel_compare_dp_vsc_sdp(const struct drm_dp_vsc_sdp *a, return memcmp(a, b, sizeof(*a)) == 0; } +static bool +intel_compare_buffer(const u8 *a, const u8 *b, size_t len) +{ + return memcmp(a, b, len) == 0; +} + static void pipe_config_infoframe_mismatch(struct drm_i915_private *dev_priv, bool fastset, const char *name, @@ -5479,6 +5439,30 @@ pipe_config_dp_vsc_sdp_mismatch(struct drm_i915_private *dev_priv, } } +static void +pipe_config_buffer_mismatch(struct drm_i915_private *dev_priv, + bool fastset, const char *name, + const u8 *a, const u8 *b, size_t len) +{ + if (fastset) { + if (!drm_debug_enabled(DRM_UT_KMS)) + return; + + drm_dbg_kms(&dev_priv->drm, + "fastset mismatch in %s buffer\n", name); + print_hex_dump(KERN_DEBUG, "expected: ", DUMP_PREFIX_NONE, + 16, 0, a, len, false); + print_hex_dump(KERN_DEBUG, "found: ", DUMP_PREFIX_NONE, + 16, 0, b, len, false); + } else { + drm_err(&dev_priv->drm, "mismatch in %s buffer\n", name); + print_hex_dump(KERN_ERR, "expected: ", DUMP_PREFIX_NONE, + 16, 0, a, len, false); + print_hex_dump(KERN_ERR, "found: ", DUMP_PREFIX_NONE, + 16, 0, b, len, false); + } +} + static void __printf(4, 5) pipe_config_mismatch(bool fastset, const struct intel_crtc *crtc, const char *name, const char *format, ...) @@ -5677,6 +5661,18 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, } \ } while (0) +#define PIPE_CONF_CHECK_BUFFER(name, len) do { \ + BUILD_BUG_ON(sizeof(current_config->name) != (len)); \ + BUILD_BUG_ON(sizeof(pipe_config->name) != (len)); \ + if (!intel_compare_buffer(current_config->name, pipe_config->name, (len))) { \ + pipe_config_buffer_mismatch(dev_priv, fastset, __stringify(name), \ + current_config->name, \ + pipe_config->name, \ + (len)); \ + ret = false; \ + } \ +} while (0) + #define PIPE_CONF_CHECK_COLOR_LUT(lut, is_pre_csc_lut) do { \ if (current_config->gamma_mode == pipe_config->gamma_mode && \ !intel_color_lut_equal(current_config, \ @@ -5748,6 +5744,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_BOOL(fec_enable); PIPE_CONF_CHECK_BOOL_INCOMPLETE(has_audio); + PIPE_CONF_CHECK_BUFFER(eld, MAX_ELD_BYTES); PIPE_CONF_CHECK_X(gmch_pfit.control); /* pfit ratios are autocomputed by the hw on gen4+ */ diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index ef73730f32b0..cb6f520cc575 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -28,6 +28,7 @@ #include <drm/drm_util.h> #include "i915_reg_defs.h" +#include "intel_display_limits.h" enum drm_scaling_filter; struct dpll; @@ -62,51 +63,9 @@ struct intel_remapped_info; struct intel_rotation_info; struct pci_dev; -/* - * Keep the pipe enum values fixed: the code assumes that PIPE_A=0, the - * rest have consecutive values and match the enum values of transcoders - * with a 1:1 transcoder -> pipe mapping. - */ -enum pipe { - INVALID_PIPE = -1, - - PIPE_A = 0, - PIPE_B, - PIPE_C, - PIPE_D, - _PIPE_EDP, - - I915_MAX_PIPES = _PIPE_EDP -}; #define pipe_name(p) ((p) + 'A') -enum transcoder { - INVALID_TRANSCODER = -1, - /* - * The following transcoders have a 1:1 transcoder -> pipe mapping, - * keep their values fixed: the code assumes that TRANSCODER_A=0, the - * rest have consecutive values and match the enum values of the pipes - * they map to. - */ - TRANSCODER_A = PIPE_A, - TRANSCODER_B = PIPE_B, - TRANSCODER_C = PIPE_C, - TRANSCODER_D = PIPE_D, - - /* - * The following transcoders can map to any pipe, their enum value - * doesn't need to stay fixed. - */ - TRANSCODER_EDP, - TRANSCODER_DSI_0, - TRANSCODER_DSI_1, - TRANSCODER_DSI_A = TRANSCODER_DSI_0, /* legacy DSI */ - TRANSCODER_DSI_C = TRANSCODER_DSI_1, /* legacy DSI */ - - I915_MAX_TRANSCODERS -}; - static inline const char *transcoder_name(enum transcoder transcoder) { switch (transcoder) { @@ -147,29 +106,6 @@ enum i9xx_plane_id { #define plane_name(p) ((p) + 'A') #define sprite_name(p, s) ((p) * RUNTIME_INFO(dev_priv)->num_sprites[(p)] + (s) + 'A') -/* - * Per-pipe plane identifier. - * I915_MAX_PLANES in the enum below is the maximum (across all platforms) - * number of planes per CRTC. Not all platforms really have this many planes, - * which means some arrays of size I915_MAX_PLANES may have unused entries - * between the topmost sprite plane and the cursor plane. - * - * This is expected to be passed to various register macros - * (eg. PLANE_CTL(), PS_PLANE_SEL(), etc.) so adjust with care. - */ -enum plane_id { - PLANE_PRIMARY, - PLANE_SPRITE0, - PLANE_SPRITE1, - PLANE_SPRITE2, - PLANE_SPRITE3, - PLANE_SPRITE4, - PLANE_SPRITE5, - PLANE_CURSOR, - - I915_MAX_PLANES, -}; - #define for_each_plane_id_on_crtc(__crtc, __p) \ for ((__p) = PLANE_PRIMARY; (__p) < I915_MAX_PLANES; (__p)++) \ for_each_if((__crtc)->plane_ids_mask & BIT(__p)) @@ -182,34 +118,6 @@ enum plane_id { for_each_dbuf_slice((__dev_priv), (__slice)) \ for_each_if((__mask) & BIT(__slice)) -enum port { - PORT_NONE = -1, - - PORT_A = 0, - PORT_B, - PORT_C, - PORT_D, - PORT_E, - PORT_F, - PORT_G, - PORT_H, - PORT_I, - - /* tgl+ */ - PORT_TC1 = PORT_D, - PORT_TC2, - PORT_TC3, - PORT_TC4, - PORT_TC5, - PORT_TC6, - - /* XE_LPD repositions D/E offsets and bitfields */ - PORT_D_XELPD = PORT_TC5, - PORT_E_XELPD, - - I915_MAX_PORTS -}; - #define port_name(p) ((p) + 'A') /* @@ -312,27 +220,6 @@ enum phy_fia { FIA3, }; -enum hpd_pin { - HPD_NONE = 0, - HPD_TV = HPD_NONE, /* TV is known to be unreliable */ - HPD_CRT, - HPD_SDVO_B, - HPD_SDVO_C, - HPD_PORT_A, - HPD_PORT_B, - HPD_PORT_C, - HPD_PORT_D, - HPD_PORT_E, - HPD_PORT_TC1, - HPD_PORT_TC2, - HPD_PORT_TC3, - HPD_PORT_TC4, - HPD_PORT_TC5, - HPD_PORT_TC6, - - HPD_NUM_PINS -}; - #define for_each_hpd_pin(__pin) \ for ((__pin) = (HPD_NONE + 1); (__pin) < HPD_NUM_PINS; (__pin)++) diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index 57ddce3ba02b..fb8670aa2932 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -17,7 +17,7 @@ #include <drm/drm_modeset_lock.h> #include "intel_cdclk.h" -#include "intel_display.h" +#include "intel_display_limits.h" #include "intel_display_power.h" #include "intel_dmc.h" #include "intel_dpll_mgr.h" @@ -87,6 +87,11 @@ struct intel_wm_funcs { int (*compute_global_watermarks)(struct intel_atomic_state *state); }; +struct intel_audio_state { + struct intel_encoder *encoder; + u8 eld[MAX_ELD_BYTES]; +}; + struct intel_audio { /* hda/i915 audio component */ struct i915_audio_component *component; @@ -96,8 +101,8 @@ struct intel_audio { int power_refcount; u32 freq_cntrl; - /* Used to save the pipe-to-encoder mapping for audio */ - struct intel_encoder *encoder_map[I915_MAX_PIPES]; + /* current audio state for the audio component hooks */ + struct intel_audio_state state[I915_MAX_PIPES]; /* necessary resource sharing with HDMI LPE audio driver. */ struct { @@ -122,6 +127,11 @@ struct intel_dpll { int nssc; int ssc; } ref_clks; + + /* + * Bitmask of PLLs using the PCH SSC, indexed using enum intel_dpll_id. + */ + u8 pch_ssc_use; }; struct intel_frontbuffer_tracking { @@ -429,6 +439,24 @@ struct intel_display { } sagv; struct { + /* + * DG2: Mask of PHYs that were not calibrated by the firmware + * and should not be used. + */ + u8 phy_failed_calibration; + } snps; + + struct { + /* + * Shadows for CHV DPLL_MD regs to keep the state + * checker somewhat working in the presence hardware + * crappiness (can't read out DPLL_MD for pipes B & C). + */ + u32 chv_dpll_md[I915_MAX_PIPES]; + u32 bxt_phy_grc; + } state; + + struct { /* ordered wq for modesets */ struct workqueue_struct *modeset; diff --git a/drivers/gpu/drm/i915/display/intel_display_limits.h b/drivers/gpu/drm/i915/display/intel_display_limits.h new file mode 100644 index 000000000000..5126d0b5ae5d --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_display_limits.h @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2022 Intel Corporation + */ + +#ifndef __INTEL_DISPLAY_LIMITS_H__ +#define __INTEL_DISPLAY_LIMITS_H__ + +/* + * Keep the pipe enum values fixed: the code assumes that PIPE_A=0, the + * rest have consecutive values and match the enum values of transcoders + * with a 1:1 transcoder -> pipe mapping. + */ +enum pipe { + INVALID_PIPE = -1, + + PIPE_A = 0, + PIPE_B, + PIPE_C, + PIPE_D, + _PIPE_EDP, + + I915_MAX_PIPES = _PIPE_EDP +}; + +enum transcoder { + INVALID_TRANSCODER = -1, + /* + * The following transcoders have a 1:1 transcoder -> pipe mapping, + * keep their values fixed: the code assumes that TRANSCODER_A=0, the + * rest have consecutive values and match the enum values of the pipes + * they map to. + */ + TRANSCODER_A = PIPE_A, + TRANSCODER_B = PIPE_B, + TRANSCODER_C = PIPE_C, + TRANSCODER_D = PIPE_D, + + /* + * The following transcoders can map to any pipe, their enum value + * doesn't need to stay fixed. + */ + TRANSCODER_EDP, + TRANSCODER_DSI_0, + TRANSCODER_DSI_1, + TRANSCODER_DSI_A = TRANSCODER_DSI_0, /* legacy DSI */ + TRANSCODER_DSI_C = TRANSCODER_DSI_1, /* legacy DSI */ + + I915_MAX_TRANSCODERS +}; + +/* + * Per-pipe plane identifier. + * I915_MAX_PLANES in the enum below is the maximum (across all platforms) + * number of planes per CRTC. Not all platforms really have this many planes, + * which means some arrays of size I915_MAX_PLANES may have unused entries + * between the topmost sprite plane and the cursor plane. + * + * This is expected to be passed to various register macros + * (eg. PLANE_CTL(), PS_PLANE_SEL(), etc.) so adjust with care. + */ +enum plane_id { + PLANE_PRIMARY, + PLANE_SPRITE0, + PLANE_SPRITE1, + PLANE_SPRITE2, + PLANE_SPRITE3, + PLANE_SPRITE4, + PLANE_SPRITE5, + PLANE_CURSOR, + + I915_MAX_PLANES, +}; + +enum port { + PORT_NONE = -1, + + PORT_A = 0, + PORT_B, + PORT_C, + PORT_D, + PORT_E, + PORT_F, + PORT_G, + PORT_H, + PORT_I, + + /* tgl+ */ + PORT_TC1 = PORT_D, + PORT_TC2, + PORT_TC3, + PORT_TC4, + PORT_TC5, + PORT_TC6, + + /* XE_LPD repositions D/E offsets and bitfields */ + PORT_D_XELPD = PORT_TC5, + PORT_E_XELPD, + + I915_MAX_PORTS +}; + +enum hpd_pin { + HPD_NONE = 0, + HPD_TV = HPD_NONE, /* TV is known to be unreliable */ + HPD_CRT, + HPD_SDVO_B, + HPD_SDVO_C, + HPD_PORT_A, + HPD_PORT_B, + HPD_PORT_C, + HPD_PORT_D, + HPD_PORT_E, + HPD_PORT_TC1, + HPD_PORT_TC2, + HPD_PORT_TC3, + HPD_PORT_TC4, + HPD_PORT_TC5, + HPD_PORT_TC6, + + HPD_NUM_PINS +}; + +#endif /* __INTEL_DISPLAY_LIMITS_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_display_power_map.c b/drivers/gpu/drm/i915/display/intel_display_power_map.c index f5d66ca85b19..6645eb1911d8 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_map.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_map.c @@ -10,6 +10,7 @@ #include "intel_display_power_map.h" #include "intel_display_power_well.h" +#include "intel_display_types.h" #define __LIST_INLINE_ELEMS(__elem_type, ...) \ ((__elem_type[]) { __VA_ARGS__ }) diff --git a/drivers/gpu/drm/i915/display/intel_display_trace.h b/drivers/gpu/drm/i915/display/intel_display_trace.h index 725aba3fa531..651ea8564e1b 100644 --- a/drivers/gpu/drm/i915/display/intel_display_trace.h +++ b/drivers/gpu/drm/i915/display/intel_display_trace.h @@ -17,6 +17,7 @@ #include "i915_irq.h" #include "intel_crtc.h" #include "intel_display_types.h" +#include "intel_vblank.h" #define __dev_name_i915(i915) dev_name((i915)->drm.dev) #define __dev_name_kms(obj) dev_name((obj)->base.dev->dev) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 32e8b2fc3cc6..54c517ca9632 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -50,6 +50,7 @@ #include "i915_vma_types.h" #include "intel_bios.h" #include "intel_display.h" +#include "intel_display_limits.h" #include "intel_display_power.h" #include "intel_dpll_mgr.h" #include "intel_pm_types.h" @@ -262,8 +263,6 @@ struct intel_encoder { enum hpd_pin hpd_pin; enum intel_display_power_domain power_domain; - /* for communication with audio component; protected by av_mutex */ - const struct drm_connector *audio_connector; /* VBT information for this encoder (may be NULL for older platforms) */ const struct intel_bios_encoder_data *devdata; @@ -351,6 +350,9 @@ struct intel_vbt_panel_data { }; struct intel_panel { + /* Fixed EDID for eDP and LVDS. May hold ERR_PTR for invalid EDID. */ + const struct drm_edid *fixed_edid; + struct list_head fixed_modes; /* backlight */ @@ -591,9 +593,8 @@ struct intel_connector { /* Panel info for eDP and LVDS */ struct intel_panel panel; - /* Cached EDID for eDP and LVDS. May hold ERR_PTR for invalid EDID. */ - struct edid *edid; - struct edid *detect_edid; + /* Cached EDID for detect. */ + const struct drm_edid *detect_edid; /* Number of times hotplug detection was tried after an HPD interrupt */ int hotplug_retries; @@ -1261,6 +1262,8 @@ struct intel_crtc_state { struct drm_dp_vsc_sdp vsc; } infoframes; + u8 eld[MAX_ELD_BYTES]; + /* HDMI scrambling status */ bool hdmi_scrambling; diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 4124b3d37110..257aa2b7cf20 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -42,51 +42,61 @@ #define DMC_VERSION_MAJOR(version) ((version) >> 16) #define DMC_VERSION_MINOR(version) ((version) & 0xffff) -#define DMC_PATH(platform, major, minor) \ - "i915/" \ - __stringify(platform) "_dmc_ver" \ - __stringify(major) "_" \ +#define DMC_PATH(platform) \ + "i915/" __stringify(platform) "_dmc.bin" + +/* + * New DMC additions should not use this. This is used solely to remain + * compatible with systems that have not yet updated DMC blobs to use + * unversioned file names. + */ +#define DMC_LEGACY_PATH(platform, major, minor) \ + "i915/" \ + __stringify(platform) "_dmc_ver" \ + __stringify(major) "_" \ __stringify(minor) ".bin" #define DISPLAY_VER13_DMC_MAX_FW_SIZE 0x20000 #define DISPLAY_VER12_DMC_MAX_FW_SIZE ICL_DMC_MAX_FW_SIZE -#define DG2_DMC_PATH DMC_PATH(dg2, 2, 08) +#define DG2_DMC_PATH DMC_LEGACY_PATH(dg2, 2, 08) MODULE_FIRMWARE(DG2_DMC_PATH); -#define ADLP_DMC_PATH DMC_PATH(adlp, 2, 16) +#define ADLP_DMC_PATH DMC_PATH(adlp) +#define ADLP_DMC_FALLBACK_PATH DMC_LEGACY_PATH(adlp, 2, 16) MODULE_FIRMWARE(ADLP_DMC_PATH); +MODULE_FIRMWARE(ADLP_DMC_FALLBACK_PATH); -#define ADLS_DMC_PATH DMC_PATH(adls, 2, 01) +#define ADLS_DMC_PATH DMC_LEGACY_PATH(adls, 2, 01) MODULE_FIRMWARE(ADLS_DMC_PATH); -#define DG1_DMC_PATH DMC_PATH(dg1, 2, 02) +#define DG1_DMC_PATH DMC_LEGACY_PATH(dg1, 2, 02) MODULE_FIRMWARE(DG1_DMC_PATH); -#define RKL_DMC_PATH DMC_PATH(rkl, 2, 03) +#define RKL_DMC_PATH DMC_LEGACY_PATH(rkl, 2, 03) MODULE_FIRMWARE(RKL_DMC_PATH); -#define TGL_DMC_PATH DMC_PATH(tgl, 2, 12) +#define TGL_DMC_PATH DMC_LEGACY_PATH(tgl, 2, 12) MODULE_FIRMWARE(TGL_DMC_PATH); -#define ICL_DMC_PATH DMC_PATH(icl, 1, 09) +#define ICL_DMC_PATH DMC_LEGACY_PATH(icl, 1, 09) #define ICL_DMC_MAX_FW_SIZE 0x6000 MODULE_FIRMWARE(ICL_DMC_PATH); -#define GLK_DMC_PATH DMC_PATH(glk, 1, 04) +#define GLK_DMC_PATH DMC_LEGACY_PATH(glk, 1, 04) #define GLK_DMC_MAX_FW_SIZE 0x4000 MODULE_FIRMWARE(GLK_DMC_PATH); -#define KBL_DMC_PATH DMC_PATH(kbl, 1, 04) +#define KBL_DMC_PATH DMC_LEGACY_PATH(kbl, 1, 04) #define KBL_DMC_MAX_FW_SIZE BXT_DMC_MAX_FW_SIZE MODULE_FIRMWARE(KBL_DMC_PATH); -#define SKL_DMC_PATH DMC_PATH(skl, 1, 27) +#define SKL_DMC_PATH DMC_LEGACY_PATH(skl, 1, 27) #define SKL_DMC_MAX_FW_SIZE BXT_DMC_MAX_FW_SIZE MODULE_FIRMWARE(SKL_DMC_PATH); -#define BXT_DMC_PATH DMC_PATH(bxt, 1, 07) +#define BXT_DMC_PATH DMC_LEGACY_PATH(bxt, 1, 07) #define BXT_DMC_MAX_FW_SIZE 0x3000 MODULE_FIRMWARE(BXT_DMC_PATH); @@ -97,6 +107,8 @@ MODULE_FIRMWARE(BXT_DMC_PATH); #define DMC_V3_MAX_MMIO_COUNT 20 #define DMC_V1_MMIO_START_RANGE 0x80000 +#define PIPE_TO_DMC_ID(pipe) (DMC_FW_PIPEA + ((pipe) - PIPE_A)) + struct intel_css_header { /* 0x09 for DMC */ u32 module_type; @@ -396,6 +408,28 @@ static void pipedmc_clock_gating_wa(struct drm_i915_private *i915, bool enable) PIPEDMC_GATING_DIS, 0); } +void intel_dmc_enable_pipe(struct drm_i915_private *i915, enum pipe pipe) +{ + if (!has_dmc_id_fw(i915, PIPE_TO_DMC_ID(pipe))) + return; + + if (DISPLAY_VER(i915) >= 14) + intel_de_rmw(i915, MTL_PIPEDMC_CONTROL, 0, PIPEDMC_ENABLE_MTL(pipe)); + else + intel_de_rmw(i915, PIPEDMC_CONTROL(pipe), 0, PIPEDMC_ENABLE); +} + +void intel_dmc_disable_pipe(struct drm_i915_private *i915, enum pipe pipe) +{ + if (!has_dmc_id_fw(i915, PIPE_TO_DMC_ID(pipe))) + return; + + if (DISPLAY_VER(i915) >= 14) + intel_de_rmw(i915, MTL_PIPEDMC_CONTROL, PIPEDMC_ENABLE_MTL(pipe), 0); + else + intel_de_rmw(i915, PIPEDMC_CONTROL(pipe), PIPEDMC_ENABLE, 0); +} + /** * intel_dmc_load_program() - write the firmware from memory to register. * @dev_priv: i915 drm device. @@ -821,16 +855,40 @@ static void intel_dmc_runtime_pm_put(struct drm_i915_private *dev_priv) intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref); } +static const char *dmc_fallback_path(struct drm_i915_private *i915) +{ + if (IS_ALDERLAKE_P(i915)) + return ADLP_DMC_FALLBACK_PATH; + + return NULL; +} + static void dmc_load_work_fn(struct work_struct *work) { struct drm_i915_private *dev_priv; struct intel_dmc *dmc; const struct firmware *fw = NULL; + const char *fallback_path; + int err; dev_priv = container_of(work, typeof(*dev_priv), display.dmc.work); dmc = &dev_priv->display.dmc; - request_firmware(&fw, dev_priv->display.dmc.fw_path, dev_priv->drm.dev); + err = request_firmware(&fw, dev_priv->display.dmc.fw_path, dev_priv->drm.dev); + + if (err == -ENOENT && !dev_priv->params.dmc_firmware_path) { + fallback_path = dmc_fallback_path(dev_priv); + if (fallback_path) { + drm_dbg_kms(&dev_priv->drm, + "%s not found, falling back to %s\n", + dmc->fw_path, + fallback_path); + err = request_firmware(&fw, fallback_path, dev_priv->drm.dev); + if (err == 0) + dev_priv->display.dmc.fw_path = fallback_path; + } + } + parse_dmc_fw(dev_priv, fw); if (intel_dmc_has_payload(dev_priv)) { diff --git a/drivers/gpu/drm/i915/display/intel_dmc.h b/drivers/gpu/drm/i915/display/intel_dmc.h index 435eab9b016b..fd1725de4289 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.h +++ b/drivers/gpu/drm/i915/display/intel_dmc.h @@ -13,6 +13,8 @@ struct drm_i915_error_state_buf; struct drm_i915_private; +enum pipe; + enum { DMC_FW_MAIN = 0, DMC_FW_PIPEA, @@ -47,6 +49,8 @@ struct intel_dmc { void intel_dmc_ucode_init(struct drm_i915_private *i915); void intel_dmc_load_program(struct drm_i915_private *i915); void intel_dmc_disable_program(struct drm_i915_private *i915); +void intel_dmc_enable_pipe(struct drm_i915_private *i915, enum pipe pipe); +void intel_dmc_disable_pipe(struct drm_i915_private *i915, enum pipe pipe); void intel_dmc_ucode_fini(struct drm_i915_private *i915); void intel_dmc_ucode_suspend(struct drm_i915_private *i915); void intel_dmc_ucode_resume(struct drm_i915_private *i915); diff --git a/drivers/gpu/drm/i915/display/intel_dmc_regs.h b/drivers/gpu/drm/i915/display/intel_dmc_regs.h index 5e5e41644ddf..cf10094acae3 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc_regs.h +++ b/drivers/gpu/drm/i915/display/intel_dmc_regs.h @@ -11,6 +11,16 @@ #define DMC_PROGRAM(addr, i) _MMIO((addr) + (i) * 4) #define DMC_SSP_BASE_ADDR_GEN9 0x00002FC0 +#define _PIPEDMC_CONTROL_A 0x45250 +#define _PIPEDMC_CONTROL_B 0x45254 +#define PIPEDMC_CONTROL(pipe) _MMIO_PIPE(pipe, \ + _PIPEDMC_CONTROL_A, \ + _PIPEDMC_CONTROL_B) +#define PIPEDMC_ENABLE REG_BIT(0) + +#define MTL_PIPEDMC_CONTROL _MMIO(0x45250) +#define PIPEDMC_ENABLE_MTL(pipe) REG_BIT(((pipe) - PIPE_A) * 4) + #define _ADLP_PIPEDMC_REG_MMIO_BASE_A 0x5f000 #define _TGL_PIPEDMC_REG_MMIO_BASE_A 0x92000 diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 80d95cec8f9d..62cbab7402e9 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2080,7 +2080,9 @@ intel_dp_compute_config(struct intel_encoder *encoder, if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv) && encoder->port != PORT_A) pipe_config->has_pch_encoder = true; - pipe_config->has_audio = intel_dp_has_audio(encoder, pipe_config, conn_state); + pipe_config->has_audio = + intel_dp_has_audio(encoder, pipe_config, conn_state) && + intel_audio_compute_config(encoder, pipe_config, conn_state); fixed_mode = intel_panel_fixed_mode(connector, adjusted_mode); if (intel_dp_is_edp(intel_dp) && fixed_mode) { @@ -3648,12 +3650,11 @@ static u8 intel_dp_autotest_edid(struct intel_dp *intel_dp) intel_dp->aux.i2c_defer_count); intel_dp->compliance.test_data.edid = INTEL_DP_RESOLUTION_FAILSAFE; } else { - struct edid *block = intel_connector->detect_edid; + /* FIXME: Get rid of drm_edid_raw() */ + const struct edid *block = drm_edid_raw(intel_connector->detect_edid); - /* We have to write the checksum - * of the last block read - */ - block += intel_connector->detect_edid->extensions; + /* We have to write the checksum of the last block read */ + block += block->extensions; if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_EDID_CHECKSUM, block->checksum) <= 0) @@ -4475,29 +4476,34 @@ bool intel_digital_port_connected(struct intel_encoder *encoder) return is_connected; } -static struct edid * +static const struct drm_edid * intel_dp_get_edid(struct intel_dp *intel_dp) { - struct intel_connector *intel_connector = intel_dp->attached_connector; + struct intel_connector *connector = intel_dp->attached_connector; + const struct drm_edid *fixed_edid = connector->panel.fixed_edid; - /* use cached edid if we have one */ - if (intel_connector->edid) { + /* Use panel fixed edid if we have one */ + if (fixed_edid) { /* invalid edid */ - if (IS_ERR(intel_connector->edid)) + if (IS_ERR(fixed_edid)) return NULL; - return drm_edid_duplicate(intel_connector->edid); - } else - return drm_get_edid(&intel_connector->base, - &intel_dp->aux.ddc); + return drm_edid_dup(fixed_edid); + } + + return drm_edid_read_ddc(&connector->base, &intel_dp->aux.ddc); } static void intel_dp_update_dfp(struct intel_dp *intel_dp, - const struct edid *edid) + const struct drm_edid *drm_edid) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); struct intel_connector *connector = intel_dp->attached_connector; + const struct edid *edid; + + /* FIXME: Get rid of drm_edid_raw() */ + edid = drm_edid_raw(drm_edid); intel_dp->dfp.max_bpc = drm_dp_downstream_max_bpc(intel_dp->dpcd, @@ -4597,21 +4603,27 @@ intel_dp_set_edid(struct intel_dp *intel_dp) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); struct intel_connector *connector = intel_dp->attached_connector; - struct edid *edid; + const struct drm_edid *drm_edid; + const struct edid *edid; bool vrr_capable; intel_dp_unset_edid(intel_dp); - edid = intel_dp_get_edid(intel_dp); - connector->detect_edid = edid; + drm_edid = intel_dp_get_edid(intel_dp); + connector->detect_edid = drm_edid; + + /* Below we depend on display info having been updated */ + drm_edid_connector_update(&connector->base, drm_edid); vrr_capable = intel_vrr_is_capable(connector); drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] VRR capable: %s\n", connector->base.base.id, connector->base.name, str_yes_no(vrr_capable)); drm_connector_set_vrr_capable_property(&connector->base, vrr_capable); - intel_dp_update_dfp(intel_dp, edid); + intel_dp_update_dfp(intel_dp, drm_edid); intel_dp_update_420(intel_dp); + /* FIXME: Get rid of drm_edid_raw() */ + edid = drm_edid_raw(drm_edid); if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) { intel_dp->has_hdmi_sink = drm_detect_hdmi_monitor(edid); intel_dp->has_audio = drm_detect_monitor_audio(edid); @@ -4626,7 +4638,7 @@ intel_dp_unset_edid(struct intel_dp *intel_dp) struct intel_connector *connector = intel_dp->attached_connector; drm_dp_cec_unset_edid(&intel_dp->aux); - kfree(connector->detect_edid); + drm_edid_free(connector->detect_edid); connector->detect_edid = NULL; intel_dp->has_hdmi_sink = false; @@ -4790,12 +4802,10 @@ intel_dp_force(struct drm_connector *connector) static int intel_dp_get_modes(struct drm_connector *connector) { struct intel_connector *intel_connector = to_intel_connector(connector); - struct edid *edid; - int num_modes = 0; + int num_modes; - edid = intel_connector->detect_edid; - if (edid) - num_modes = intel_connector_update_modes(connector, edid); + /* drm_edid_connector_update() done in ->detect() or ->force() */ + num_modes = drm_edid_connector_add_modes(connector); /* Also add fixed mode, which may or may not be present in EDID */ if (intel_dp_is_edp(intel_attached_dp(intel_connector))) @@ -4804,7 +4814,7 @@ static int intel_dp_get_modes(struct drm_connector *connector) if (num_modes) return num_modes; - if (!edid) { + if (!intel_connector->detect_edid) { struct intel_dp *intel_dp = intel_attached_dp(intel_connector); struct drm_display_mode *mode; @@ -5240,7 +5250,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, struct drm_display_mode *fixed_mode; struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; bool has_dpcd; - struct edid *edid; + const struct drm_edid *drm_edid; if (!intel_dp_is_edp(intel_dp)) return true; @@ -5287,29 +5297,28 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, } mutex_lock(&dev_priv->drm.mode_config.mutex); - edid = drm_get_edid(connector, &intel_dp->aux.ddc); - if (!edid) { + drm_edid = drm_edid_read_ddc(connector, &intel_dp->aux.ddc); + if (!drm_edid) { /* Fallback to EDID from ACPI OpRegion, if any */ - edid = intel_opregion_get_edid(intel_connector); - if (edid) + drm_edid = intel_opregion_get_edid(intel_connector); + if (drm_edid) drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s] Using OpRegion EDID\n", connector->base.id, connector->name); } - if (edid) { - if (drm_add_edid_modes(connector, edid)) { - drm_connector_update_edid_property(connector, edid); - } else { - kfree(edid); - edid = ERR_PTR(-EINVAL); + if (drm_edid) { + if (drm_edid_connector_update(connector, drm_edid) || + !drm_edid_connector_add_modes(connector)) { + drm_edid_connector_update(connector, NULL); + drm_edid_free(drm_edid); + drm_edid = ERR_PTR(-EINVAL); } } else { - edid = ERR_PTR(-ENOENT); + drm_edid = ERR_PTR(-ENOENT); } - intel_connector->edid = edid; - intel_bios_init_panel_late(dev_priv, &intel_connector->panel, - encoder->devdata, IS_ERR(edid) ? NULL : edid); + intel_bios_init_panel_late(dev_priv, &intel_connector->panel, encoder->devdata, + IS_ERR(drm_edid) ? NULL : drm_edid); intel_panel_add_edid_fixed_modes(intel_connector, true); @@ -5333,7 +5342,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, goto out_vdd_off; } - intel_panel_init(intel_connector); + intel_panel_init(intel_connector, drm_edid); intel_edp_backlight_setup(intel_dp, intel_connector); diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.c b/drivers/gpu/drm/i915/display/intel_dpio_phy.c index 7eb7440b3180..565c06de2432 100644 --- a/drivers/gpu/drm/i915/display/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.c @@ -376,7 +376,7 @@ static void _bxt_ddi_phy_init(struct drm_i915_private *dev_priv, if (bxt_ddi_phy_is_enabled(dev_priv, phy)) { /* Still read out the GRC value for state verification */ if (phy_info->rcomp_phy != -1) - dev_priv->bxt_phy_grc = bxt_get_grc(dev_priv, phy); + dev_priv->display.state.bxt_phy_grc = bxt_get_grc(dev_priv, phy); if (bxt_ddi_phy_verify_state(dev_priv, phy)) { drm_dbg(&dev_priv->drm, "DDI PHY %d already enabled, " @@ -442,8 +442,9 @@ static void _bxt_ddi_phy_init(struct drm_i915_private *dev_priv, * the corresponding calibrated value from PHY1, and disable * the automatic calibration on PHY0. */ - val = dev_priv->bxt_phy_grc = bxt_get_grc(dev_priv, - phy_info->rcomp_phy); + val = bxt_get_grc(dev_priv, phy_info->rcomp_phy); + dev_priv->display.state.bxt_phy_grc = val; + grc_code = val << GRC_CODE_FAST_SHIFT | val << GRC_CODE_SLOW_SHIFT | val; @@ -568,7 +569,7 @@ bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, "BXT_PORT_CL2CM_DW6(%d)", phy); if (phy_info->rcomp_phy != -1) { - u32 grc_code = dev_priv->bxt_phy_grc; + u32 grc_code = dev_priv->display.state.bxt_phy_grc; grc_code = grc_code << GRC_CODE_FAST_SHIFT | grc_code << GRC_CODE_SLOW_SHIFT | diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index c236aafe9be0..4e9c18be7e1f 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -1910,7 +1910,7 @@ void chv_enable_pll(const struct intel_crtc_state *crtc_state) intel_de_write(dev_priv, DPLL_MD(PIPE_B), crtc_state->dpll_hw_state.dpll_md); intel_de_write(dev_priv, CBR4_VLV, 0); - dev_priv->chv_dpll_md[pipe] = crtc_state->dpll_hw_state.dpll_md; + dev_priv->display.state.chv_dpll_md[pipe] = crtc_state->dpll_hw_state.dpll_md; /* * DPLLB VGA mode also seems to cause problems. diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 1974eb580ed1..380368eff31a 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -618,7 +618,7 @@ static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv, * Try to set up the PCH reference clock once all DPLLs * that depend on it have been shut down. */ - if (dev_priv->pch_ssc_use & BIT(id)) + if (dev_priv->display.dpll.pch_ssc_use & BIT(id)) intel_init_pch_refclk(dev_priv); } @@ -636,7 +636,7 @@ static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv, * Try to set up the PCH reference clock once all DPLLs * that depend on it have been shut down. */ - if (dev_priv->pch_ssc_use & BIT(id)) + if (dev_priv->display.dpll.pch_ssc_use & BIT(id)) intel_init_pch_refclk(dev_priv); } diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 5b9e44443814..29c6421cd666 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -374,16 +374,16 @@ out: return ret; } -DEFINE_SIMPLE_ATTRIBUTE(intel_drrs_debugfs_ctl_fops, - NULL, intel_drrs_debugfs_ctl_set, "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(intel_drrs_debugfs_ctl_fops, + NULL, intel_drrs_debugfs_ctl_set, "%llu\n"); void intel_drrs_crtc_debugfs_add(struct intel_crtc *crtc) { debugfs_create_file("i915_drrs_status", 0444, crtc->base.debugfs_entry, crtc, &intel_drrs_debugfs_status_fops); - debugfs_create_file("i915_drrs_ctl", 0644, crtc->base.debugfs_entry, - crtc, &intel_drrs_debugfs_ctl_fops); + debugfs_create_file_unsafe("i915_drrs_ctl", 0644, crtc->base.debugfs_entry, + crtc, &intel_drrs_debugfs_ctl_fops); } static int intel_drrs_debugfs_type_show(struct seq_file *m, void *unused) diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index 3d63c1bf1e4f..96bc117fd6a0 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -30,21 +30,24 @@ struct intel_dsb { struct intel_crtc *crtc; /* - * free_pos will point the first free entry position - * and help in calculating tail of command buffer. + * maximum number of dwords the buffer will hold. */ - int free_pos; + unsigned int size; /* - * ins_start_offset will help to store start address of the dsb + * free_pos will point the first free dword and + * help in calculating tail of command buffer. + */ + unsigned int free_pos; + + /* + * ins_start_offset will help to store start dword of the dsb * instuction and help in identifying the batch of auto-increment * register. */ - u32 ins_start_offset; + unsigned int ins_start_offset; }; -#define DSB_BUF_SIZE (2 * PAGE_SIZE) - /** * DOC: DSB * @@ -64,80 +67,86 @@ struct intel_dsb { /* DSB opcodes. */ #define DSB_OPCODE_SHIFT 24 +#define DSB_OPCODE_NOOP 0x0 #define DSB_OPCODE_MMIO_WRITE 0x1 +#define DSB_OPCODE_WAIT_USEC 0x2 +#define DSB_OPCODE_WAIT_LINES 0x3 +#define DSB_OPCODE_WAIT_VBLANKS 0x4 +#define DSB_OPCODE_WAIT_DSL_IN 0x5 +#define DSB_OPCODE_WAIT_DSL_OUT 0x6 +#define DSB_OPCODE_INTERRUPT 0x7 #define DSB_OPCODE_INDEXED_WRITE 0x9 +#define DSB_OPCODE_POLL 0xA #define DSB_BYTE_EN 0xF #define DSB_BYTE_EN_SHIFT 20 #define DSB_REG_VALUE_MASK 0xfffff +static bool assert_dsb_has_room(struct intel_dsb *dsb) +{ + struct intel_crtc *crtc = dsb->crtc; + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + + /* each instruction is 2 dwords */ + return !drm_WARN(&i915->drm, dsb->free_pos > dsb->size - 2, + "DSB buffer overflow\n"); +} + static bool is_dsb_busy(struct drm_i915_private *i915, enum pipe pipe, enum dsb_id id) { - return DSB_STATUS & intel_de_read(i915, DSB_CTRL(pipe, id)); + return intel_de_read(i915, DSB_CTRL(pipe, id)) & DSB_STATUS_BUSY; } -static bool intel_dsb_enable_engine(struct drm_i915_private *i915, - enum pipe pipe, enum dsb_id id) +static void intel_dsb_emit(struct intel_dsb *dsb, u32 ldw, u32 udw) { - u32 dsb_ctrl; + u32 *buf = dsb->cmd_buf; - dsb_ctrl = intel_de_read(i915, DSB_CTRL(pipe, id)); - if (DSB_STATUS & dsb_ctrl) { - drm_dbg_kms(&i915->drm, "DSB engine is busy.\n"); - return false; - } + if (!assert_dsb_has_room(dsb)) + return; - dsb_ctrl |= DSB_ENABLE; - intel_de_write(i915, DSB_CTRL(pipe, id), dsb_ctrl); + /* Every instruction should be 8 byte aligned. */ + dsb->free_pos = ALIGN(dsb->free_pos, 2); + + dsb->ins_start_offset = dsb->free_pos; - intel_de_posting_read(i915, DSB_CTRL(pipe, id)); - return true; + buf[dsb->free_pos++] = ldw; + buf[dsb->free_pos++] = udw; } -static bool intel_dsb_disable_engine(struct drm_i915_private *i915, - enum pipe pipe, enum dsb_id id) +static bool intel_dsb_prev_ins_is_write(struct intel_dsb *dsb, + u32 opcode, i915_reg_t reg) { - u32 dsb_ctrl; + const u32 *buf = dsb->cmd_buf; + u32 prev_opcode, prev_reg; - dsb_ctrl = intel_de_read(i915, DSB_CTRL(pipe, id)); - if (DSB_STATUS & dsb_ctrl) { - drm_dbg_kms(&i915->drm, "DSB engine is busy.\n"); - return false; - } + prev_opcode = buf[dsb->ins_start_offset + 1] >> DSB_OPCODE_SHIFT; + prev_reg = buf[dsb->ins_start_offset + 1] & DSB_REG_VALUE_MASK; + + return prev_opcode == opcode && prev_reg == i915_mmio_reg_offset(reg); +} - dsb_ctrl &= ~DSB_ENABLE; - intel_de_write(i915, DSB_CTRL(pipe, id), dsb_ctrl); +static bool intel_dsb_prev_ins_is_mmio_write(struct intel_dsb *dsb, i915_reg_t reg) +{ + return intel_dsb_prev_ins_is_write(dsb, DSB_OPCODE_MMIO_WRITE, reg); +} - intel_de_posting_read(i915, DSB_CTRL(pipe, id)); - return true; +static bool intel_dsb_prev_ins_is_indexed_write(struct intel_dsb *dsb, i915_reg_t reg) +{ + return intel_dsb_prev_ins_is_write(dsb, DSB_OPCODE_INDEXED_WRITE, reg); } /** - * intel_dsb_indexed_reg_write() -Write to the DSB context for auto - * increment register. + * intel_dsb_reg_write() - Emit register wriite to the DSB context * @dsb: DSB context * @reg: register address. * @val: value. * * This function is used for writing register-value pair in command - * buffer of DSB for auto-increment register. During command buffer overflow, - * a warning is thrown and rest all erroneous condition register programming - * is done through mmio write. + * buffer of DSB. */ - -void intel_dsb_indexed_reg_write(struct intel_dsb *dsb, - i915_reg_t reg, u32 val) +void intel_dsb_reg_write(struct intel_dsb *dsb, + i915_reg_t reg, u32 val) { - struct intel_crtc *crtc = dsb->crtc; - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - u32 *buf = dsb->cmd_buf; - u32 reg_val; - - if (drm_WARN_ON(&dev_priv->drm, dsb->free_pos >= DSB_BUF_SIZE)) { - drm_dbg_kms(&dev_priv->drm, "DSB buffer overflow\n"); - return; - } - /* * For example the buffer will look like below for 3 dwords for auto * increment register: @@ -154,65 +163,55 @@ void intel_dsb_indexed_reg_write(struct intel_dsb *dsb, * we are writing odd no of dwords, Zeros will be added in the end for * padding. */ - reg_val = buf[dsb->ins_start_offset + 1] & DSB_REG_VALUE_MASK; - if (reg_val != i915_mmio_reg_offset(reg)) { - /* Every instruction should be 8 byte aligned. */ - dsb->free_pos = ALIGN(dsb->free_pos, 2); + if (!intel_dsb_prev_ins_is_mmio_write(dsb, reg) && + !intel_dsb_prev_ins_is_indexed_write(dsb, reg)) { + intel_dsb_emit(dsb, val, + (DSB_OPCODE_MMIO_WRITE << DSB_OPCODE_SHIFT) | + (DSB_BYTE_EN << DSB_BYTE_EN_SHIFT) | + i915_mmio_reg_offset(reg)); + } else { + u32 *buf = dsb->cmd_buf; - dsb->ins_start_offset = dsb->free_pos; + if (!assert_dsb_has_room(dsb)) + return; - /* Update the size. */ - buf[dsb->free_pos++] = 1; + /* convert to indexed write? */ + if (intel_dsb_prev_ins_is_mmio_write(dsb, reg)) { + u32 prev_val = buf[dsb->ins_start_offset + 0]; - /* Update the opcode and reg. */ - buf[dsb->free_pos++] = (DSB_OPCODE_INDEXED_WRITE << - DSB_OPCODE_SHIFT) | - i915_mmio_reg_offset(reg); + buf[dsb->ins_start_offset + 0] = 1; /* count */ + buf[dsb->ins_start_offset + 1] = + (DSB_OPCODE_INDEXED_WRITE << DSB_OPCODE_SHIFT) | + i915_mmio_reg_offset(reg); + buf[dsb->ins_start_offset + 2] = prev_val; - /* Update the value. */ - buf[dsb->free_pos++] = val; - } else { - /* Update the new value. */ - buf[dsb->free_pos++] = val; + dsb->free_pos++; + } - /* Update the size. */ + buf[dsb->free_pos++] = val; + /* Update the count */ buf[dsb->ins_start_offset]++; - } - /* if number of data words is odd, then the last dword should be 0.*/ - if (dsb->free_pos & 0x1) - buf[dsb->free_pos] = 0; + /* if number of data words is odd, then the last dword should be 0.*/ + if (dsb->free_pos & 0x1) + buf[dsb->free_pos] = 0; + } } -/** - * intel_dsb_reg_write() -Write to the DSB context for normal - * register. - * @crtc_state: intel_crtc_state structure - * @reg: register address. - * @val: value. - * - * This function is used for writing register-value pair in command - * buffer of DSB. During command buffer overflow, a warning is thrown - * and rest all erroneous condition register programming is done - * through mmio write. - */ -void intel_dsb_reg_write(struct intel_dsb *dsb, - i915_reg_t reg, u32 val) +static u32 intel_dsb_align_tail(struct intel_dsb *dsb) { - struct intel_crtc *crtc = dsb->crtc; - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - u32 *buf = dsb->cmd_buf; + u32 aligned_tail, tail; - if (drm_WARN_ON(&dev_priv->drm, dsb->free_pos >= DSB_BUF_SIZE)) { - drm_dbg_kms(&dev_priv->drm, "DSB buffer overflow\n"); - return; - } + tail = dsb->free_pos * 4; + aligned_tail = ALIGN(tail, CACHELINE_BYTES); - dsb->ins_start_offset = dsb->free_pos; - buf[dsb->free_pos++] = val; - buf[dsb->free_pos++] = (DSB_OPCODE_MMIO_WRITE << DSB_OPCODE_SHIFT) | - (DSB_BYTE_EN << DSB_BYTE_EN_SHIFT) | - i915_mmio_reg_offset(reg); + if (aligned_tail > tail) + memset(&dsb->cmd_buf[dsb->free_pos], 0, + aligned_tail - tail); + + dsb->free_pos = aligned_tail / 4; + + return aligned_tail; } /** @@ -228,50 +227,41 @@ void intel_dsb_commit(struct intel_dsb *dsb) enum pipe pipe = crtc->pipe; u32 tail; - if (!(dsb && dsb->free_pos)) + tail = intel_dsb_align_tail(dsb); + if (tail == 0) return; - if (!intel_dsb_enable_engine(dev_priv, pipe, dsb->id)) - goto reset; - if (is_dsb_busy(dev_priv, pipe, dsb->id)) { - drm_err(&dev_priv->drm, - "HEAD_PTR write failed - dsb engine is busy.\n"); + drm_err(&dev_priv->drm, "DSB engine is busy.\n"); goto reset; } + + intel_de_write(dev_priv, DSB_CTRL(pipe, dsb->id), + DSB_ENABLE); intel_de_write(dev_priv, DSB_HEAD(pipe, dsb->id), i915_ggtt_offset(dsb->vma)); + intel_de_write(dev_priv, DSB_TAIL(pipe, dsb->id), + i915_ggtt_offset(dsb->vma) + tail); - tail = ALIGN(dsb->free_pos * 4, CACHELINE_BYTES); - if (tail > dsb->free_pos * 4) - memset(&dsb->cmd_buf[dsb->free_pos], 0, - (tail - dsb->free_pos * 4)); - - if (is_dsb_busy(dev_priv, pipe, dsb->id)) { - drm_err(&dev_priv->drm, - "TAIL_PTR write failed - dsb engine is busy.\n"); - goto reset; - } drm_dbg_kms(&dev_priv->drm, "DSB execution started - head 0x%x, tail 0x%x\n", - i915_ggtt_offset(dsb->vma), tail); - intel_de_write(dev_priv, DSB_TAIL(pipe, dsb->id), - i915_ggtt_offset(dsb->vma) + tail); - if (wait_for(!is_dsb_busy(dev_priv, pipe, dsb->id), 1)) { + i915_ggtt_offset(dsb->vma), + i915_ggtt_offset(dsb->vma) + tail); + + if (wait_for(!is_dsb_busy(dev_priv, pipe, dsb->id), 1)) drm_err(&dev_priv->drm, "Timed out waiting for DSB workload completion.\n"); - goto reset; - } reset: dsb->free_pos = 0; dsb->ins_start_offset = 0; - intel_dsb_disable_engine(dev_priv, pipe, dsb->id); + intel_de_write(dev_priv, DSB_CTRL(pipe, dsb->id), 0); } /** * intel_dsb_prepare() - Allocate, pin and map the DSB command buffer. * @crtc: the CRTC + * @max_cmds: number of commands we need to fit into command buffer * * This function prepare the command buffer which is used to store dsb * instructions with data. @@ -279,25 +269,30 @@ reset: * Returns: * DSB context, NULL on failure */ -struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc) +struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc, + unsigned int max_cmds) { struct drm_i915_private *i915 = to_i915(crtc->base.dev); - struct intel_dsb *dsb; struct drm_i915_gem_object *obj; + intel_wakeref_t wakeref; + struct intel_dsb *dsb; struct i915_vma *vma; + unsigned int size; u32 *buf; - intel_wakeref_t wakeref; if (!HAS_DSB(i915)) return NULL; - dsb = kmalloc(sizeof(*dsb), GFP_KERNEL); + dsb = kzalloc(sizeof(*dsb), GFP_KERNEL); if (!dsb) goto out; wakeref = intel_runtime_pm_get(&i915->runtime_pm); - obj = i915_gem_object_create_internal(i915, DSB_BUF_SIZE); + /* ~1 qword per instruction, full cachelines */ + size = ALIGN(max_cmds * 8, CACHELINE_BYTES); + + obj = i915_gem_object_create_internal(i915, PAGE_ALIGN(size)); if (IS_ERR(obj)) goto out_put_rpm; @@ -319,6 +314,7 @@ struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc) dsb->vma = vma; dsb->crtc = crtc; dsb->cmd_buf = buf; + dsb->size = size / 4; /* in dwords */ dsb->free_pos = 0; dsb->ins_start_offset = 0; diff --git a/drivers/gpu/drm/i915/display/intel_dsb.h b/drivers/gpu/drm/i915/display/intel_dsb.h index 25f13c4d5389..05c221b6d0a4 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.h +++ b/drivers/gpu/drm/i915/display/intel_dsb.h @@ -13,12 +13,11 @@ struct intel_crtc; struct intel_dsb; -struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc); +struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc, + unsigned int max_cmds); void intel_dsb_cleanup(struct intel_dsb *dsb); void intel_dsb_reg_write(struct intel_dsb *dsb, i915_reg_t reg, u32 val); -void intel_dsb_indexed_reg_write(struct intel_dsb *dsb, - i915_reg_t reg, u32 val); void intel_dsb_commit(struct intel_dsb *dsb); #endif diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index 4aeae0f3ac91..0be8105cb18a 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -554,6 +554,6 @@ void intel_dvo_init(struct drm_i915_private *i915) */ intel_panel_add_encoder_fixed_mode(connector, encoder); - intel_panel_init(connector); + intel_panel_init(connector, NULL); } } diff --git a/drivers/gpu/drm/i915/display/intel_dvo_dev.h b/drivers/gpu/drm/i915/display/intel_dvo_dev.h index ea8eb7dcee38..f7e98e1c6470 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo_dev.h +++ b/drivers/gpu/drm/i915/display/intel_dvo_dev.h @@ -25,7 +25,7 @@ #include "i915_reg_defs.h" -#include "intel_display.h" +#include "intel_display_limits.h" enum drm_connector_status; struct drm_display_mode; diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 5e69d3c11d21..b507ff944864 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -331,15 +331,15 @@ static void i8xx_fbc_program_cfb(struct intel_fbc *fbc) { struct drm_i915_private *i915 = fbc->i915; - GEM_BUG_ON(range_overflows_end_t(u64, i915->dsm.start, + GEM_BUG_ON(range_overflows_end_t(u64, i915->dsm.stolen.start, fbc->compressed_fb.start, U32_MAX)); - GEM_BUG_ON(range_overflows_end_t(u64, i915->dsm.start, + GEM_BUG_ON(range_overflows_end_t(u64, i915->dsm.stolen.start, fbc->compressed_llb.start, U32_MAX)); intel_de_write(i915, FBC_CFB_BASE, - i915->dsm.start + fbc->compressed_fb.start); + i915->dsm.stolen.start + fbc->compressed_fb.start); intel_de_write(i915, FBC_LL_BASE, - i915->dsm.start + fbc->compressed_llb.start); + i915->dsm.stolen.start + fbc->compressed_llb.start); } static const struct intel_fbc_funcs i8xx_fbc_funcs = { @@ -712,7 +712,7 @@ static u64 intel_fbc_stolen_end(struct drm_i915_private *i915) * underruns, even if that range is not reserved by the BIOS. */ if (IS_BROADWELL(i915) || (DISPLAY_VER(i915) == 9 && !IS_BROXTON(i915))) - end = resource_size(&i915->dsm) - 8 * 1024 * 1024; + end = resource_size(&i915->dsm.stolen) - 8 * 1024 * 1024; else end = U64_MAX; @@ -1807,10 +1807,10 @@ static int intel_fbc_debugfs_false_color_set(void *data, u64 val) return 0; } -DEFINE_SIMPLE_ATTRIBUTE(intel_fbc_debugfs_false_color_fops, - intel_fbc_debugfs_false_color_get, - intel_fbc_debugfs_false_color_set, - "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(intel_fbc_debugfs_false_color_fops, + intel_fbc_debugfs_false_color_get, + intel_fbc_debugfs_false_color_set, + "%llu\n"); static void intel_fbc_debugfs_add(struct intel_fbc *fbc, struct dentry *parent) @@ -1819,8 +1819,8 @@ static void intel_fbc_debugfs_add(struct intel_fbc *fbc, fbc, &intel_fbc_debugfs_status_fops); if (fbc->funcs->set_false_color) - debugfs_create_file("i915_fbc_false_color", 0644, parent, - fbc, &intel_fbc_debugfs_false_color_fops); + debugfs_create_file_unsafe("i915_fbc_false_color", 0644, parent, + fbc, &intel_fbc_debugfs_false_color_fops); } void intel_fbc_crtc_debugfs_add(struct intel_crtc *crtc) diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index b6f5c554b50f..ed197db5861d 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -170,7 +170,7 @@ static int intelfb_alloc(struct drm_fb_helper *helper, * important and we should probably use that space with FBC or other * features. */ - if (size * 2 < dev_priv->stolen_usable_size) + if (size * 2 < dev_priv->dsm.usable_size) obj = i915_gem_object_create_stolen(dev_priv, size); if (IS_ERR(obj)) obj = i915_gem_object_create_shmem(dev_priv, size); diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 6a2ee342eab5..c0ce6d3dc505 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -44,6 +44,7 @@ #include "i915_drv.h" #include "i915_reg.h" #include "intel_atomic.h" +#include "intel_audio.h" #include "intel_connector.h" #include "intel_ddi.h" #include "intel_de.h" @@ -537,9 +538,7 @@ void hsw_write_infoframe(struct intel_encoder *encoder, 0); /* Wa_14013475917 */ - if ((DISPLAY_VER(dev_priv) == 13 || - IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) && crtc_state->has_psr && - type == DP_SDP_VSC) + if (IS_DISPLAY_VER(dev_priv, 13, 14) && crtc_state->has_psr && type == DP_SDP_VSC) return; val |= hsw_infoframe_enable(type); @@ -2271,7 +2270,8 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder, pipe_config->pixel_multiplier = 2; pipe_config->has_audio = - intel_hdmi_has_audio(encoder, pipe_config, conn_state); + intel_hdmi_has_audio(encoder, pipe_config, conn_state) && + intel_audio_compute_config(encoder, pipe_config, conn_state); /* * Try to respect downstream TMDS clock limits first, if @@ -2360,7 +2360,7 @@ intel_hdmi_unset_edid(struct drm_connector *connector) intel_hdmi->dp_dual_mode.type = DRM_DP_DUAL_MODE_NONE; intel_hdmi->dp_dual_mode.max_tmds_clock = 0; - kfree(to_intel_connector(connector)->detect_edid); + drm_edid_free(to_intel_connector(connector)->detect_edid); to_intel_connector(connector)->detect_edid = NULL; } @@ -2421,7 +2421,8 @@ intel_hdmi_set_edid(struct drm_connector *connector) struct drm_i915_private *dev_priv = to_i915(connector->dev); struct intel_hdmi *intel_hdmi = intel_attached_hdmi(to_intel_connector(connector)); intel_wakeref_t wakeref; - struct edid *edid; + const struct drm_edid *drm_edid; + const struct edid *edid; bool connected = false; struct i2c_adapter *i2c; @@ -2429,17 +2430,23 @@ intel_hdmi_set_edid(struct drm_connector *connector) i2c = intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus); - edid = drm_get_edid(connector, i2c); + drm_edid = drm_edid_read_ddc(connector, i2c); - if (!edid && !intel_gmbus_is_forced_bit(i2c)) { + if (!drm_edid && !intel_gmbus_is_forced_bit(i2c)) { drm_dbg_kms(&dev_priv->drm, "HDMI GMBUS EDID read failed, retry using GPIO bit-banging\n"); intel_gmbus_force_bit(i2c, true); - edid = drm_get_edid(connector, i2c); + drm_edid = drm_edid_read_ddc(connector, i2c); intel_gmbus_force_bit(i2c, false); } - to_intel_connector(connector)->detect_edid = edid; + /* Below we depend on display info having been updated */ + drm_edid_connector_update(connector, drm_edid); + + to_intel_connector(connector)->detect_edid = drm_edid; + + /* FIXME: Get rid of drm_edid_raw() */ + edid = drm_edid_raw(drm_edid); if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) { intel_hdmi->has_audio = drm_detect_monitor_audio(edid); intel_hdmi->has_hdmi_sink = drm_detect_hdmi_monitor(edid); @@ -2515,13 +2522,8 @@ intel_hdmi_force(struct drm_connector *connector) static int intel_hdmi_get_modes(struct drm_connector *connector) { - struct edid *edid; - - edid = to_intel_connector(connector)->detect_edid; - if (edid == NULL) - return 0; - - return intel_connector_update_modes(connector, edid); + /* drm_edid_connector_update() done in ->detect() or ->force() */ + return drm_edid_connector_add_modes(connector); } static struct i2c_adapter * diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index aecec992cd0d..a1557d84ce0a 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -477,10 +477,14 @@ static int intel_lvds_compute_config(struct intel_encoder *intel_encoder, static int intel_lvds_get_modes(struct drm_connector *connector) { struct intel_connector *intel_connector = to_intel_connector(connector); + const struct drm_edid *fixed_edid = intel_connector->panel.fixed_edid; - /* use cached edid if we have one */ - if (!IS_ERR_OR_NULL(intel_connector->edid)) - return drm_add_edid_modes(connector, intel_connector->edid); + /* Use panel fixed edid if we have one */ + if (!IS_ERR_OR_NULL(fixed_edid)) { + drm_edid_connector_update(connector, fixed_edid); + + return drm_edid_connector_add_modes(connector); + } return intel_panel_get_modes(intel_connector); } @@ -834,7 +838,7 @@ void intel_lvds_init(struct drm_i915_private *dev_priv) struct intel_connector *intel_connector; struct drm_connector *connector; struct drm_encoder *encoder; - struct edid *edid; + const struct drm_edid *drm_edid; i915_reg_t lvds_reg; u32 lvds; u8 pin; @@ -945,27 +949,34 @@ void intel_lvds_init(struct drm_i915_private *dev_priv) * preferred mode is the right one. */ mutex_lock(&dev_priv->drm.mode_config.mutex); - if (vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC) + if (vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC) { + const struct edid *edid; + + /* FIXME: Make drm_get_edid_switcheroo() return drm_edid */ edid = drm_get_edid_switcheroo(connector, - intel_gmbus_get_adapter(dev_priv, pin)); - else - edid = drm_get_edid(connector, - intel_gmbus_get_adapter(dev_priv, pin)); - if (edid) { - if (drm_add_edid_modes(connector, edid)) { - drm_connector_update_edid_property(connector, - edid); - } else { + intel_gmbus_get_adapter(dev_priv, pin)); + if (edid) { + drm_edid = drm_edid_alloc(edid, (edid->extensions + 1) * EDID_LENGTH); kfree(edid); - edid = ERR_PTR(-EINVAL); + } else { + drm_edid = NULL; } } else { - edid = ERR_PTR(-ENOENT); + drm_edid = drm_edid_read_ddc(connector, + intel_gmbus_get_adapter(dev_priv, pin)); + } + if (drm_edid) { + if (drm_edid_connector_update(connector, drm_edid) || + !drm_edid_connector_add_modes(connector)) { + drm_edid_connector_update(connector, NULL); + drm_edid_free(drm_edid); + drm_edid = ERR_PTR(-EINVAL); + } + } else { + drm_edid = ERR_PTR(-ENOENT); } - intel_connector->edid = edid; - intel_bios_init_panel_late(dev_priv, &intel_connector->panel, NULL, - IS_ERR(edid) ? NULL : edid); + IS_ERR(drm_edid) ? NULL : drm_edid); /* Try EDID first */ intel_panel_add_edid_fixed_modes(intel_connector, true); @@ -988,7 +999,7 @@ void intel_lvds_init(struct drm_i915_private *dev_priv) if (!intel_panel_preferred_fixed_mode(intel_connector)) goto failed; - intel_panel_init(intel_connector); + intel_panel_init(intel_connector, drm_edid); intel_backlight_setup(intel_connector, INVALID_PIPE); diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c index 96395bfbd41d..52cdbd4fc2fa 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c @@ -698,8 +698,10 @@ void intel_modeset_setup_hw_state(struct drm_i915_private *i915, drm_crtc_vblank_reset(&crtc->base); - if (crtc_state->hw.active) + if (crtc_state->hw.active) { + intel_dmc_enable_pipe(i915, crtc->pipe); intel_crtc_vblank_on(crtc_state); + } } intel_fbc_sanitize(i915); diff --git a/drivers/gpu/drm/i915/display/intel_opregion.c b/drivers/gpu/drm/i915/display/intel_opregion.c index e0184745632c..b8dce0576512 100644 --- a/drivers/gpu/drm/i915/display/intel_opregion.c +++ b/drivers/gpu/drm/i915/display/intel_opregion.c @@ -1101,41 +1101,34 @@ intel_opregion_get_panel_type(struct drm_i915_private *dev_priv) * The EDID in the OpRegion, or NULL if there is none or it's invalid. * */ -struct edid *intel_opregion_get_edid(struct intel_connector *intel_connector) +const struct drm_edid *intel_opregion_get_edid(struct intel_connector *intel_connector) { struct drm_connector *connector = &intel_connector->base; struct drm_i915_private *i915 = to_i915(connector->dev); struct intel_opregion *opregion = &i915->display.opregion; - const void *in_edid; - const struct edid *edid; - struct edid *new_edid; + const struct drm_edid *drm_edid; + const void *edid; int len; if (!opregion->asle_ext) return NULL; - in_edid = opregion->asle_ext->bddc; + edid = opregion->asle_ext->bddc; /* Validity corresponds to number of 128-byte blocks */ len = (opregion->asle_ext->phed & ASLE_PHED_EDID_VALID_MASK) * 128; - if (!len || !memchr_inv(in_edid, 0, len)) + if (!len || !memchr_inv(edid, 0, len)) return NULL; - edid = in_edid; + drm_edid = drm_edid_alloc(edid, len); - if (len < EDID_LENGTH * (1 + edid->extensions)) { - drm_dbg_kms(&i915->drm, "Invalid EDID in ACPI OpRegion (Mailbox #5): too short\n"); - return NULL; - } - new_edid = drm_edid_duplicate(edid); - if (!new_edid) - return NULL; - if (!drm_edid_is_valid(new_edid)) { - kfree(new_edid); + if (!drm_edid_valid(drm_edid)) { drm_dbg_kms(&i915->drm, "Invalid EDID in ACPI OpRegion (Mailbox #5)\n"); - return NULL; + drm_edid_free(drm_edid); + drm_edid = NULL; } - return new_edid; + + return drm_edid; } bool intel_opregion_headless_sku(struct drm_i915_private *i915) diff --git a/drivers/gpu/drm/i915/display/intel_opregion.h b/drivers/gpu/drm/i915/display/intel_opregion.h index 2f261f985400..d02e6696a050 100644 --- a/drivers/gpu/drm/i915/display/intel_opregion.h +++ b/drivers/gpu/drm/i915/display/intel_opregion.h @@ -74,7 +74,7 @@ int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder, int intel_opregion_notify_adapter(struct drm_i915_private *dev_priv, pci_power_t state); int intel_opregion_get_panel_type(struct drm_i915_private *dev_priv); -struct edid *intel_opregion_get_edid(struct intel_connector *connector); +const struct drm_edid *intel_opregion_get_edid(struct intel_connector *connector); bool intel_opregion_headless_sku(struct drm_i915_private *i915); @@ -123,7 +123,7 @@ static inline int intel_opregion_get_panel_type(struct drm_i915_private *dev) return -ENODEV; } -static inline struct edid * +static inline const struct drm_edid * intel_opregion_get_edid(struct intel_connector *connector) { return NULL; diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 3b1004b019a8..42aa04bac261 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -31,6 +31,8 @@ #include <linux/kernel.h> #include <linux/pwm.h> +#include <drm/drm_edid.h> + #include "i915_reg.h" #include "intel_backlight.h" #include "intel_connector.h" @@ -670,10 +672,13 @@ void intel_panel_init_alloc(struct intel_connector *connector) INIT_LIST_HEAD(&panel->fixed_modes); } -int intel_panel_init(struct intel_connector *connector) +int intel_panel_init(struct intel_connector *connector, + const struct drm_edid *fixed_edid) { struct intel_panel *panel = &connector->panel; + panel->fixed_edid = fixed_edid; + intel_backlight_init_funcs(panel); if (!has_drrs_modes(connector)) @@ -692,6 +697,9 @@ void intel_panel_fini(struct intel_connector *connector) struct intel_panel *panel = &connector->panel; struct drm_display_mode *fixed_mode, *next; + if (!IS_ERR_OR_NULL(panel->fixed_edid)) + drm_edid_free(panel->fixed_edid); + intel_backlight_destroy(panel); intel_bios_fini_panel(panel); diff --git a/drivers/gpu/drm/i915/display/intel_panel.h b/drivers/gpu/drm/i915/display/intel_panel.h index 4b51e1c51da6..15a8c897b33f 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.h +++ b/drivers/gpu/drm/i915/display/intel_panel.h @@ -13,13 +13,15 @@ enum drrs_type; struct drm_connector; struct drm_connector_state; struct drm_display_mode; +struct drm_edid; struct drm_i915_private; struct intel_connector; struct intel_crtc_state; struct intel_encoder; void intel_panel_init_alloc(struct intel_connector *connector); -int intel_panel_init(struct intel_connector *connector); +int intel_panel_init(struct intel_connector *connector, + const struct drm_edid *fixed_edid); void intel_panel_fini(struct intel_connector *connector); enum drm_connector_status intel_panel_detect(struct drm_connector *connector, bool force); diff --git a/drivers/gpu/drm/i915/display/intel_pch_refclk.c b/drivers/gpu/drm/i915/display/intel_pch_refclk.c index 08a94365b7d1..3657b2940702 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_refclk.c +++ b/drivers/gpu/drm/i915/display/intel_pch_refclk.c @@ -467,24 +467,24 @@ static void lpt_init_pch_refclk(struct drm_i915_private *dev_priv) * clock hierarchy. That would also allow us to do * clock bending finally. */ - dev_priv->pch_ssc_use = 0; + dev_priv->display.dpll.pch_ssc_use = 0; if (spll_uses_pch_ssc(dev_priv)) { drm_dbg_kms(&dev_priv->drm, "SPLL using PCH SSC\n"); - dev_priv->pch_ssc_use |= BIT(DPLL_ID_SPLL); + dev_priv->display.dpll.pch_ssc_use |= BIT(DPLL_ID_SPLL); } if (wrpll_uses_pch_ssc(dev_priv, DPLL_ID_WRPLL1)) { drm_dbg_kms(&dev_priv->drm, "WRPLL1 using PCH SSC\n"); - dev_priv->pch_ssc_use |= BIT(DPLL_ID_WRPLL1); + dev_priv->display.dpll.pch_ssc_use |= BIT(DPLL_ID_WRPLL1); } if (wrpll_uses_pch_ssc(dev_priv, DPLL_ID_WRPLL2)) { drm_dbg_kms(&dev_priv->drm, "WRPLL2 using PCH SSC\n"); - dev_priv->pch_ssc_use |= BIT(DPLL_ID_WRPLL2); + dev_priv->display.dpll.pch_ssc_use |= BIT(DPLL_ID_WRPLL2); } - if (dev_priv->pch_ssc_use) + if (dev_priv->display.dpll.pch_ssc_use) return; if (has_fdi) { diff --git a/drivers/gpu/drm/i915/display/intel_pipe_crc.c b/drivers/gpu/drm/i915/display/intel_pipe_crc.c index e9774670e3f6..8d3ea8d7b737 100644 --- a/drivers/gpu/drm/i915/display/intel_pipe_crc.c +++ b/drivers/gpu/drm/i915/display/intel_pipe_crc.c @@ -72,14 +72,13 @@ static int i8xx_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source, return 0; } -static int i9xx_pipe_crc_auto_source(struct drm_i915_private *dev_priv, - enum pipe pipe, - enum intel_pipe_crc_source *source) +static void i9xx_pipe_crc_auto_source(struct drm_i915_private *dev_priv, + enum pipe pipe, + enum intel_pipe_crc_source *source) { struct intel_encoder *encoder; struct intel_crtc *crtc; struct intel_digital_port *dig_port; - int ret = 0; *source = INTEL_PIPE_CRC_SOURCE_PIPE; @@ -121,8 +120,6 @@ static int i9xx_pipe_crc_auto_source(struct drm_i915_private *dev_priv, } } drm_modeset_unlock_all(&dev_priv->drm); - - return ret; } static int vlv_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv, @@ -132,11 +129,8 @@ static int vlv_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv, { bool need_stable_symbols = false; - if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) { - int ret = i9xx_pipe_crc_auto_source(dev_priv, pipe, source); - if (ret) - return ret; - } + if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) + i9xx_pipe_crc_auto_source(dev_priv, pipe, source); switch (*source) { case INTEL_PIPE_CRC_SOURCE_PIPE: @@ -200,11 +194,8 @@ static int i9xx_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv, enum intel_pipe_crc_source *source, u32 *val) { - if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) { - int ret = i9xx_pipe_crc_auto_source(dev_priv, pipe, source); - if (ret) - return ret; - } + if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) + i9xx_pipe_crc_auto_source(dev_priv, pipe, source); switch (*source) { case INTEL_PIPE_CRC_SOURCE_PIPE: diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c b/drivers/gpu/drm/i915/display/intel_plane_initial.c index 76be796df255..bb6ea7de5c61 100644 --- a/drivers/gpu/drm/i915/display/intel_plane_initial.c +++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c @@ -107,7 +107,7 @@ initial_plane_vma(struct drm_i915_private *i915, */ if (IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) && mem == i915->mm.stolen_region && - size * 2 > i915->stolen_usable_size) + size * 2 > i915->dsm.usable_size) return NULL; obj = i915_gem_object_create_region_at(mem, phys_base, size, 0); diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index d0d774219cc5..7a72e15e6836 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -24,14 +24,13 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_damage_helper.h> -#include "display/intel_dp.h" - #include "i915_drv.h" #include "i915_reg.h" #include "intel_atomic.h" #include "intel_crtc.h" #include "intel_de.h" #include "intel_display_types.h" +#include "intel_dp.h" #include "intel_dp_aux.h" #include "intel_hdmi.h" #include "intel_psr.h" @@ -1112,6 +1111,8 @@ static u32 wa_16013835468_bit_get(struct intel_dp *intel_dp) return LATENCY_REPORTING_REMOVED_PIPE_B; case PIPE_C: return LATENCY_REPORTING_REMOVED_PIPE_C; + case PIPE_D: + return LATENCY_REPORTING_REMOVED_PIPE_D; default: MISSING_CASE(intel_dp->psr.pipe); return 0; @@ -1163,6 +1164,23 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, intel_dp->psr.psr2_sel_fetch_enabled ? IGNORE_PSR2_HW_TRACKING : 0); + /* + * Wa_16013835468 + * Wa_14015648006 + */ + if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0) || + IS_DISPLAY_VER(dev_priv, 12, 13)) { + u16 vtotal, vblank; + + vtotal = crtc_state->uapi.adjusted_mode.crtc_vtotal - + crtc_state->uapi.adjusted_mode.crtc_vdisplay; + vblank = crtc_state->uapi.adjusted_mode.crtc_vblank_end - + crtc_state->uapi.adjusted_mode.crtc_vblank_start; + if (vblank > vtotal) + intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1, 0, + wa_16013835468_bit_get(intel_dp)); + } + if (intel_dp->psr.psr2_enabled) { if (DISPLAY_VER(dev_priv) == 9) intel_de_rmw(dev_priv, CHICKEN_TRANS(cpu_transcoder), 0, @@ -1196,20 +1214,6 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, else if (IS_ALDERLAKE_P(dev_priv)) intel_de_rmw(dev_priv, CLKGATE_DIS_MISC, 0, CLKGATE_DIS_MISC_DMASC_GATING_DIS); - - /* Wa_16013835468:tgl[b0+], dg1 */ - if (IS_TGL_DISPLAY_STEP(dev_priv, STEP_B0, STEP_FOREVER) || - IS_DG1(dev_priv)) { - u16 vtotal, vblank; - - vtotal = crtc_state->uapi.adjusted_mode.crtc_vtotal - - crtc_state->uapi.adjusted_mode.crtc_vdisplay; - vblank = crtc_state->uapi.adjusted_mode.crtc_vblank_end - - crtc_state->uapi.adjusted_mode.crtc_vblank_start; - if (vblank > vtotal) - intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1, 0, - wa_16013835468_bit_get(intel_dp)); - } } } @@ -1362,6 +1366,15 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp) intel_de_rmw(dev_priv, CHICKEN_PAR1_1, DIS_RAM_BYPASS_PSR2_MAN_TRACK, 0); + /* + * Wa_16013835468 + * Wa_14015648006 + */ + if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0) || + IS_DISPLAY_VER(dev_priv, 12, 13)) + intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1, + wa_16013835468_bit_get(intel_dp), 0); + if (intel_dp->psr.psr2_enabled) { /* Wa_16011168373:adl-p */ if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) @@ -1377,12 +1390,6 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp) else if (IS_ALDERLAKE_P(dev_priv)) intel_de_rmw(dev_priv, CLKGATE_DIS_MISC, CLKGATE_DIS_MISC_DMASC_GATING_DIS, 0); - - /* Wa_16013835468:tgl[b0+], dg1 */ - if (IS_TGL_DISPLAY_STEP(dev_priv, STEP_B0, STEP_FOREVER) || - IS_DG1(dev_priv)) - intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1, - wa_16013835468_bit_get(intel_dp), 0); } intel_snps_phy_update_psr_power_state(dev_priv, phy, false); @@ -1835,6 +1842,12 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, if (full_update) goto skip_sel_fetch_set_loop; + /* Wa_14014971492 */ + if ((IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0) || + IS_ALDERLAKE_P(dev_priv) || IS_TIGERLAKE(dev_priv)) && + crtc_state->splitter.enable) + pipe_clip.y1 = 0; + ret = drm_atomic_add_affected_planes(&state->base, &crtc->base); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index 21805c15d5eb..e12ba458636c 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -39,6 +39,7 @@ #include "i915_drv.h" #include "i915_reg.h" #include "intel_atomic.h" +#include "intel_audio.h" #include "intel_connector.h" #include "intel_crtc.h" #include "intel_de.h" @@ -1068,7 +1069,8 @@ static ssize_t intel_sdvo_read_infoframe(struct intel_sdvo *intel_sdvo, &tx_rate, 1)) return -ENXIO; - if (tx_rate == SDVO_HBUF_TX_DISABLED) + /* TX_DISABLED doesn't mean disabled for ELD */ + if (if_index != SDVO_HBUF_INDEX_ELD && tx_rate == SDVO_HBUF_TX_DISABLED) return 0; if (!intel_sdvo_get_hbuf_size(intel_sdvo, &hbuf_size)) @@ -1185,6 +1187,28 @@ static void intel_sdvo_get_avi_infoframe(struct intel_sdvo *intel_sdvo, frame->any.type, HDMI_INFOFRAME_TYPE_AVI); } +static void intel_sdvo_get_eld(struct intel_sdvo *intel_sdvo, + struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(intel_sdvo->base.base.dev); + ssize_t len; + u8 val; + + if (!crtc_state->has_audio) + return; + + if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_AUDIO_STAT, &val, 1)) + return; + + if ((val & SDVO_AUDIO_ELD_VALID) == 0) + return; + + len = intel_sdvo_read_infoframe(intel_sdvo, SDVO_HBUF_INDEX_ELD, + crtc_state->eld, sizeof(crtc_state->eld)); + if (len < 0) + drm_dbg_kms(&i915->drm, "failed to read ELD\n"); +} + static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo, const struct drm_connector_state *conn_state) { @@ -1378,7 +1402,9 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder, pipe_config->has_hdmi_sink = intel_has_hdmi_sink(intel_sdvo, conn_state); - pipe_config->has_audio = intel_sdvo_has_audio(encoder, pipe_config, conn_state); + pipe_config->has_audio = + intel_sdvo_has_audio(encoder, pipe_config, conn_state) && + intel_audio_compute_config(encoder, pipe_config, conn_state); pipe_config->limited_color_range = intel_sdvo_limited_color_range(encoder, pipe_config, @@ -1729,9 +1755,7 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder, if (intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_AUDIO_STAT, &val, 1)) { - u8 mask = SDVO_AUDIO_ELD_VALID | SDVO_AUDIO_PRESENCE_DETECT; - - if ((val & mask) == mask) + if (val & SDVO_AUDIO_PRESENCE_DETECT) pipe_config->has_audio = true; } @@ -1742,6 +1766,8 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder, } intel_sdvo_get_avi_infoframe(intel_sdvo, pipe_config); + + intel_sdvo_get_eld(intel_sdvo, pipe_config); } static void intel_sdvo_disable_audio(struct intel_sdvo *intel_sdvo) @@ -1753,12 +1779,7 @@ static void intel_sdvo_enable_audio(struct intel_sdvo *intel_sdvo, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { - const struct drm_display_mode *adjusted_mode = - &crtc_state->hw.adjusted_mode; - struct drm_connector *connector = conn_state->connector; - u8 *eld = connector->eld; - - eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2; + const u8 *eld = crtc_state->eld; intel_sdvo_set_audio_state(intel_sdvo, 0); @@ -2903,7 +2924,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, u16 type) mutex_unlock(&i915->drm.mode_config.mutex); } - intel_panel_init(intel_connector); + intel_panel_init(intel_connector, NULL); if (!intel_panel_preferred_fixed_mode(intel_connector)) goto err; diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c index 9494cfd45519..c65c771f5c46 100644 --- a/drivers/gpu/drm/i915/display/intel_snps_phy.c +++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c @@ -40,7 +40,7 @@ void intel_snps_phy_wait_for_calibration(struct drm_i915_private *i915) */ if (intel_de_wait_for_clear(i915, DG2_PHY_MISC(phy), DG2_PHY_DP_TX_ACK_MASK, 25)) - i915->snps_phy_failed_calibration |= BIT(phy); + i915->display.snps.phy_failed_calibration |= BIT(phy); } } diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c b/drivers/gpu/drm/i915/display/intel_vblank.c new file mode 100644 index 000000000000..4c83e2320bca --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_vblank.c @@ -0,0 +1,441 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2022-2023 Intel Corporation + */ + +#include "i915_drv.h" +#include "i915_reg.h" +#include "intel_de.h" +#include "intel_display_types.h" +#include "intel_vblank.h" + +/* + * This timing diagram depicts the video signal in and + * around the vertical blanking period. + * + * Assumptions about the fictitious mode used in this example: + * vblank_start >= 3 + * vsync_start = vblank_start + 1 + * vsync_end = vblank_start + 2 + * vtotal = vblank_start + 3 + * + * start of vblank: + * latch double buffered registers + * increment frame counter (ctg+) + * generate start of vblank interrupt (gen4+) + * | + * | frame start: + * | generate frame start interrupt (aka. vblank interrupt) (gmch) + * | may be shifted forward 1-3 extra lines via PIPECONF + * | | + * | | start of vsync: + * | | generate vsync interrupt + * | | | + * ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx + * . \hs/ . \hs/ \hs/ \hs/ . \hs/ + * ----va---> <-----------------vb--------------------> <--------va------------- + * | | <----vs-----> | + * -vbs-----> <---vbs+1---> <---vbs+2---> <-----0-----> <-----1-----> <-----2--- (scanline counter gen2) + * -vbs-2---> <---vbs-1---> <---vbs-----> <---vbs+1---> <---vbs+2---> <-----0--- (scanline counter gen3+) + * -vbs-2---> <---vbs-2---> <---vbs-1---> <---vbs-----> <---vbs+1---> <---vbs+2- (scanline counter hsw+ hdmi) + * | | | + * last visible pixel first visible pixel + * | increment frame counter (gen3/4) + * pixel counter = vblank_start * htotal pixel counter = 0 (gen3/4) + * + * x = horizontal active + * _ = horizontal blanking + * hs = horizontal sync + * va = vertical active + * vb = vertical blanking + * vs = vertical sync + * vbs = vblank_start (number) + * + * Summary: + * - most events happen at the start of horizontal sync + * - frame start happens at the start of horizontal blank, 1-4 lines + * (depending on PIPECONF settings) after the start of vblank + * - gen3/4 pixel and frame counter are synchronized with the start + * of horizontal active on the first line of vertical active + */ + +/* + * Called from drm generic code, passed a 'crtc', which we use as a pipe index. + */ +u32 i915_get_vblank_counter(struct drm_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->dev); + struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[drm_crtc_index(crtc)]; + const struct drm_display_mode *mode = &vblank->hwmode; + enum pipe pipe = to_intel_crtc(crtc)->pipe; + u32 pixel, vbl_start, hsync_start, htotal; + u64 frame; + + /* + * On i965gm TV output the frame counter only works up to + * the point when we enable the TV encoder. After that the + * frame counter ceases to work and reads zero. We need a + * vblank wait before enabling the TV encoder and so we + * have to enable vblank interrupts while the frame counter + * is still in a working state. However the core vblank code + * does not like us returning non-zero frame counter values + * when we've told it that we don't have a working frame + * counter. Thus we must stop non-zero values leaking out. + */ + if (!vblank->max_vblank_count) + return 0; + + htotal = mode->crtc_htotal; + hsync_start = mode->crtc_hsync_start; + vbl_start = mode->crtc_vblank_start; + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + vbl_start = DIV_ROUND_UP(vbl_start, 2); + + /* Convert to pixel count */ + vbl_start *= htotal; + + /* Start of vblank event occurs at start of hsync */ + vbl_start -= htotal - hsync_start; + + /* + * High & low register fields aren't synchronized, so make sure + * we get a low value that's stable across two reads of the high + * register. + */ + frame = intel_de_read64_2x32(dev_priv, PIPEFRAMEPIXEL(pipe), PIPEFRAME(pipe)); + + pixel = frame & PIPE_PIXEL_MASK; + frame = (frame >> PIPE_FRAME_LOW_SHIFT) & 0xffffff; + + /* + * The frame counter increments at beginning of active. + * Cook up a vblank counter by also checking the pixel + * counter against vblank start. + */ + return (frame + (pixel >= vbl_start)) & 0xffffff; +} + +u32 g4x_get_vblank_counter(struct drm_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->dev); + struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[drm_crtc_index(crtc)]; + enum pipe pipe = to_intel_crtc(crtc)->pipe; + + if (!vblank->max_vblank_count) + return 0; + + return intel_de_read(dev_priv, PIPE_FRMCOUNT_G4X(pipe)); +} + +static u32 intel_crtc_scanlines_since_frame_timestamp(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_vblank_crtc *vblank = + &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; + const struct drm_display_mode *mode = &vblank->hwmode; + u32 htotal = mode->crtc_htotal; + u32 clock = mode->crtc_clock; + u32 scan_prev_time, scan_curr_time, scan_post_time; + + /* + * To avoid the race condition where we might cross into the + * next vblank just between the PIPE_FRMTMSTMP and TIMESTAMP_CTR + * reads. We make sure we read PIPE_FRMTMSTMP and TIMESTAMP_CTR + * during the same frame. + */ + do { + /* + * This field provides read back of the display + * pipe frame time stamp. The time stamp value + * is sampled at every start of vertical blank. + */ + scan_prev_time = intel_de_read_fw(dev_priv, + PIPE_FRMTMSTMP(crtc->pipe)); + + /* + * The TIMESTAMP_CTR register has the current + * time stamp value. + */ + scan_curr_time = intel_de_read_fw(dev_priv, IVB_TIMESTAMP_CTR); + + scan_post_time = intel_de_read_fw(dev_priv, + PIPE_FRMTMSTMP(crtc->pipe)); + } while (scan_post_time != scan_prev_time); + + return div_u64(mul_u32_u32(scan_curr_time - scan_prev_time, + clock), 1000 * htotal); +} + +/* + * On certain encoders on certain platforms, pipe + * scanline register will not work to get the scanline, + * since the timings are driven from the PORT or issues + * with scanline register updates. + * This function will use Framestamp and current + * timestamp registers to calculate the scanline. + */ +static u32 __intel_get_crtc_scanline_from_timestamp(struct intel_crtc *crtc) +{ + struct drm_vblank_crtc *vblank = + &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; + const struct drm_display_mode *mode = &vblank->hwmode; + u32 vblank_start = mode->crtc_vblank_start; + u32 vtotal = mode->crtc_vtotal; + u32 scanline; + + scanline = intel_crtc_scanlines_since_frame_timestamp(crtc); + scanline = min(scanline, vtotal - 1); + scanline = (scanline + vblank_start) % vtotal; + + return scanline; +} + +/* + * intel_de_read_fw(), only for fast reads of display block, no need for + * forcewake etc. + */ +static int __intel_get_crtc_scanline(struct intel_crtc *crtc) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + const struct drm_display_mode *mode; + struct drm_vblank_crtc *vblank; + enum pipe pipe = crtc->pipe; + int position, vtotal; + + if (!crtc->active) + return 0; + + vblank = &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; + mode = &vblank->hwmode; + + if (crtc->mode_flags & I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP) + return __intel_get_crtc_scanline_from_timestamp(crtc); + + vtotal = mode->crtc_vtotal; + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + vtotal /= 2; + + position = intel_de_read_fw(dev_priv, PIPEDSL(pipe)) & PIPEDSL_LINE_MASK; + + /* + * On HSW, the DSL reg (0x70000) appears to return 0 if we + * read it just before the start of vblank. So try it again + * so we don't accidentally end up spanning a vblank frame + * increment, causing the pipe_update_end() code to squak at us. + * + * The nature of this problem means we can't simply check the ISR + * bit and return the vblank start value; nor can we use the scanline + * debug register in the transcoder as it appears to have the same + * problem. We may need to extend this to include other platforms, + * but so far testing only shows the problem on HSW. + */ + if (HAS_DDI(dev_priv) && !position) { + int i, temp; + + for (i = 0; i < 100; i++) { + udelay(1); + temp = intel_de_read_fw(dev_priv, PIPEDSL(pipe)) & PIPEDSL_LINE_MASK; + if (temp != position) { + position = temp; + break; + } + } + } + + /* + * See update_scanline_offset() for the details on the + * scanline_offset adjustment. + */ + return (position + crtc->scanline_offset) % vtotal; +} + +static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc, + bool in_vblank_irq, + int *vpos, int *hpos, + ktime_t *stime, ktime_t *etime, + const struct drm_display_mode *mode) +{ + struct drm_device *dev = _crtc->dev; + struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_crtc *crtc = to_intel_crtc(_crtc); + enum pipe pipe = crtc->pipe; + int position; + int vbl_start, vbl_end, hsync_start, htotal, vtotal; + unsigned long irqflags; + bool use_scanline_counter = DISPLAY_VER(dev_priv) >= 5 || + IS_G4X(dev_priv) || DISPLAY_VER(dev_priv) == 2 || + crtc->mode_flags & I915_MODE_FLAG_USE_SCANLINE_COUNTER; + + if (drm_WARN_ON(&dev_priv->drm, !mode->crtc_clock)) { + drm_dbg(&dev_priv->drm, + "trying to get scanoutpos for disabled pipe %c\n", + pipe_name(pipe)); + return false; + } + + htotal = mode->crtc_htotal; + hsync_start = mode->crtc_hsync_start; + vtotal = mode->crtc_vtotal; + vbl_start = mode->crtc_vblank_start; + vbl_end = mode->crtc_vblank_end; + + if (mode->flags & DRM_MODE_FLAG_INTERLACE) { + vbl_start = DIV_ROUND_UP(vbl_start, 2); + vbl_end /= 2; + vtotal /= 2; + } + + /* + * Lock uncore.lock, as we will do multiple timing critical raw + * register reads, potentially with preemption disabled, so the + * following code must not block on uncore.lock. + */ + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + + /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ + + /* Get optional system timestamp before query. */ + if (stime) + *stime = ktime_get(); + + if (crtc->mode_flags & I915_MODE_FLAG_VRR) { + int scanlines = intel_crtc_scanlines_since_frame_timestamp(crtc); + + position = __intel_get_crtc_scanline(crtc); + + /* + * Already exiting vblank? If so, shift our position + * so it looks like we're already apporaching the full + * vblank end. This should make the generated timestamp + * more or less match when the active portion will start. + */ + if (position >= vbl_start && scanlines < position) + position = min(crtc->vmax_vblank_start + scanlines, vtotal - 1); + } else if (use_scanline_counter) { + /* No obvious pixelcount register. Only query vertical + * scanout position from Display scan line register. + */ + position = __intel_get_crtc_scanline(crtc); + } else { + /* + * Have access to pixelcount since start of frame. + * We can split this into vertical and horizontal + * scanout position. + */ + position = (intel_de_read_fw(dev_priv, PIPEFRAMEPIXEL(pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT; + + /* convert to pixel counts */ + vbl_start *= htotal; + vbl_end *= htotal; + vtotal *= htotal; + + /* + * In interlaced modes, the pixel counter counts all pixels, + * so one field will have htotal more pixels. In order to avoid + * the reported position from jumping backwards when the pixel + * counter is beyond the length of the shorter field, just + * clamp the position the length of the shorter field. This + * matches how the scanline counter based position works since + * the scanline counter doesn't count the two half lines. + */ + if (position >= vtotal) + position = vtotal - 1; + + /* + * Start of vblank interrupt is triggered at start of hsync, + * just prior to the first active line of vblank. However we + * consider lines to start at the leading edge of horizontal + * active. So, should we get here before we've crossed into + * the horizontal active of the first line in vblank, we would + * not set the DRM_SCANOUTPOS_INVBL flag. In order to fix that, + * always add htotal-hsync_start to the current pixel position. + */ + position = (position + htotal - hsync_start) % vtotal; + } + + /* Get optional system timestamp after query. */ + if (etime) + *etime = ktime_get(); + + /* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */ + + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); + + /* + * While in vblank, position will be negative + * counting up towards 0 at vbl_end. And outside + * vblank, position will be positive counting + * up since vbl_end. + */ + if (position >= vbl_start) + position -= vbl_end; + else + position += vtotal - vbl_end; + + if (use_scanline_counter) { + *vpos = position; + *hpos = 0; + } else { + *vpos = position / htotal; + *hpos = position - (*vpos * htotal); + } + + return true; +} + +bool intel_crtc_get_vblank_timestamp(struct drm_crtc *crtc, int *max_error, + ktime_t *vblank_time, bool in_vblank_irq) +{ + return drm_crtc_vblank_helper_get_vblank_timestamp_internal( + crtc, max_error, vblank_time, in_vblank_irq, + i915_get_crtc_scanoutpos); +} + +int intel_get_crtc_scanline(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + unsigned long irqflags; + int position; + + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + position = __intel_get_crtc_scanline(crtc); + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); + + return position; +} + +static bool pipe_scanline_is_moving(struct drm_i915_private *dev_priv, + enum pipe pipe) +{ + i915_reg_t reg = PIPEDSL(pipe); + u32 line1, line2; + + line1 = intel_de_read(dev_priv, reg) & PIPEDSL_LINE_MASK; + msleep(5); + line2 = intel_de_read(dev_priv, reg) & PIPEDSL_LINE_MASK; + + return line1 != line2; +} + +static void wait_for_pipe_scanline_moving(struct intel_crtc *crtc, bool state) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; + + /* Wait for the display line to settle/start moving */ + if (wait_for(pipe_scanline_is_moving(dev_priv, pipe) == state, 100)) + drm_err(&dev_priv->drm, + "pipe %c scanline %s wait timed out\n", + pipe_name(pipe), str_on_off(state)); +} + +void intel_wait_for_pipe_scanline_stopped(struct intel_crtc *crtc) +{ + wait_for_pipe_scanline_moving(crtc, false); +} + +void intel_wait_for_pipe_scanline_moving(struct intel_crtc *crtc) +{ + wait_for_pipe_scanline_moving(crtc, true); +} diff --git a/drivers/gpu/drm/i915/display/intel_vblank.h b/drivers/gpu/drm/i915/display/intel_vblank.h new file mode 100644 index 000000000000..c9fea2c2a990 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_vblank.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2022-2023 Intel Corporation + */ + +#ifndef __INTEL_VBLANK_H__ +#define __INTEL_VBLANK_H__ + +#include <linux/ktime.h> +#include <linux/types.h> + +struct drm_crtc; +struct intel_crtc; + +u32 i915_get_vblank_counter(struct drm_crtc *crtc); +u32 g4x_get_vblank_counter(struct drm_crtc *crtc); +bool intel_crtc_get_vblank_timestamp(struct drm_crtc *crtc, int *max_error, + ktime_t *vblank_time, bool in_vblank_irq); +int intel_get_crtc_scanline(struct intel_crtc *crtc); +void intel_wait_for_pipe_scanline_stopped(struct intel_crtc *crtc); +void intel_wait_for_pipe_scanline_moving(struct intel_crtc *crtc); + +#endif /* __INTEL_VBLANK_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_vga.c b/drivers/gpu/drm/i915/display/intel_vga.c index a69bfcac9a94..286a0bdd28c6 100644 --- a/drivers/gpu/drm/i915/display/intel_vga.c +++ b/drivers/gpu/drm/i915/display/intel_vga.c @@ -6,9 +6,10 @@ #include <linux/pci.h> #include <linux/vgaarb.h> -#include <drm/i915_drm.h> #include <video/vga.h> +#include "soc/intel_gmch.h" + #include "i915_drv.h" #include "i915_reg.h" #include "intel_de.h" @@ -98,39 +99,12 @@ void intel_vga_reset_io_mem(struct drm_i915_private *i915) vga_put(pdev, VGA_RSRC_LEGACY_IO); } -static int -intel_vga_set_state(struct drm_i915_private *i915, bool enable_decode) -{ - unsigned int reg = DISPLAY_VER(i915) >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL; - u16 gmch_ctrl; - - if (pci_read_config_word(i915->bridge_dev, reg, &gmch_ctrl)) { - drm_err(&i915->drm, "failed to read control word\n"); - return -EIO; - } - - if (!!(gmch_ctrl & INTEL_GMCH_VGA_DISABLE) == !enable_decode) - return 0; - - if (enable_decode) - gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE; - else - gmch_ctrl |= INTEL_GMCH_VGA_DISABLE; - - if (pci_write_config_word(i915->bridge_dev, reg, gmch_ctrl)) { - drm_err(&i915->drm, "failed to write control word\n"); - return -EIO; - } - - return 0; -} - static unsigned int intel_vga_set_decode(struct pci_dev *pdev, bool enable_decode) { struct drm_i915_private *i915 = pdev_to_i915(pdev); - intel_vga_set_state(i915, enable_decode); + intel_gmch_vga_set_state(i915, enable_decode); if (enable_decode) return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index 01e881293612..473d53610b92 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -87,6 +87,10 @@ static u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_cosited) #define ICL_MAX_SRC_H 4096 #define ICL_MAX_DST_W 5120 #define ICL_MAX_DST_H 4096 +#define TGL_MAX_SRC_W 5120 +#define TGL_MAX_SRC_H 8192 +#define TGL_MAX_DST_W 8192 +#define TGL_MAX_DST_H 8192 #define MTL_MAX_SRC_W 4096 #define MTL_MAX_SRC_H 8192 #define MTL_MAX_DST_W 8192 @@ -173,11 +177,16 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, max_src_h = SKL_MAX_SRC_H; max_dst_w = SKL_MAX_DST_W; max_dst_h = SKL_MAX_DST_H; - } else if (DISPLAY_VER(dev_priv) < 14) { + } else if (DISPLAY_VER(dev_priv) < 12) { max_src_w = ICL_MAX_SRC_W; max_src_h = ICL_MAX_SRC_H; max_dst_w = ICL_MAX_DST_W; max_dst_h = ICL_MAX_DST_H; + } else if (DISPLAY_VER(dev_priv) < 14) { + max_src_w = TGL_MAX_SRC_W; + max_src_h = TGL_MAX_SRC_H; + max_dst_w = TGL_MAX_DST_W; + max_dst_h = TGL_MAX_DST_H; } else { max_src_w = MTL_MAX_SRC_W; max_src_h = MTL_MAX_SRC_H; diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 4b79c2d2d617..9b172a1e90de 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -1627,7 +1627,7 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state) u32 offset; int ret; - if (w > max_width || w < min_width || h > max_height) { + if (w > max_width || w < min_width || h > max_height || h < 1) { drm_dbg_kms(&dev_priv->drm, "requested Y/RGB source size %dx%d outside limits (min: %dx1 max: %dx%d)\n", w, h, min_width, max_width, max_height); diff --git a/drivers/gpu/drm/i915/display/skl_watermark.h b/drivers/gpu/drm/i915/display/skl_watermark.h index 7a5a4e67cd73..37954c472070 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.h +++ b/drivers/gpu/drm/i915/display/skl_watermark.h @@ -8,7 +8,7 @@ #include <linux/types.h> -#include "intel_display.h" +#include "intel_display_limits.h" #include "intel_global_state.h" #include "intel_pm_types.h" diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index 662bdb656aa3..2289f6b1b4eb 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -1983,7 +1983,7 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv) goto err_cleanup_connector; } - intel_panel_init(intel_connector); + intel_panel_init(intel_connector, NULL); intel_backlight_setup(intel_connector, INVALID_PIPE); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c index b3b398fe689c..385ffc575b48 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c @@ -8,6 +8,7 @@ #include "display/intel_frontbuffer.h" +#include "i915_config.h" #include "i915_drv.h" #include "i915_gem_clflush.h" #include "i915_sw_fence_work.h" diff --git a/drivers/gpu/drm/i915/gem/i915_gem_create.c b/drivers/gpu/drm/i915/gem/i915_gem_create.c index 005a7f842784..e76c9703680e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_create.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_create.c @@ -5,6 +5,7 @@ #include <drm/drm_fourcc.h> +#include "display/intel_display.h" #include "gem/i915_gem_ioctls.h" #include "gem/i915_gem_lmem.h" #include "gem/i915_gem_region.h" diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c index 9969e687ad85..497de40b8e68 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c @@ -4,6 +4,7 @@ * Copyright © 2014-2016 Intel Corporation */ +#include "display/intel_display.h" #include "display/intel_frontbuffer.h" #include "gt/intel_gt.h" diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c index 4f69bff63068..2aac6bf78740 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c @@ -697,7 +697,7 @@ insert: GEM_BUG_ON(lookup_mmo(obj, mmap_type) != mmo); out: if (file) - drm_vma_node_allow(&mmo->vma_node, file); + drm_vma_node_allow_once(&mmo->vma_node, file); return mmo; err: diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c index bc9521078807..90a967374b1a 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c @@ -110,9 +110,7 @@ static int adjust_stolen(struct drm_i915_private *i915, else ggtt_start &= PGTBL_ADDRESS_LO_MASK; - ggtt_res = - (struct resource) DEFINE_RES_MEM(ggtt_start, - ggtt_total_entries(ggtt) * 4); + ggtt_res = DEFINE_RES_MEM(ggtt_start, ggtt_total_entries(ggtt) * 4); if (ggtt_res.start >= stolen[0].start && ggtt_res.start < stolen[0].end) stolen[0].end = ggtt_res.start; @@ -211,7 +209,7 @@ static void g4x_get_stolen_reserved(struct drm_i915_private *i915, IS_GM45(i915) ? CTG_STOLEN_RESERVED : ELK_STOLEN_RESERVED); - resource_size_t stolen_top = i915->dsm.end + 1; + resource_size_t stolen_top = i915->dsm.stolen.end + 1; drm_dbg(&i915->drm, "%s_STOLEN_RESERVED = %08x\n", IS_GM45(i915) ? "CTG" : "ELK", reg_val); @@ -276,7 +274,7 @@ static void vlv_get_stolen_reserved(struct drm_i915_private *i915, resource_size_t *size) { u32 reg_val = intel_uncore_read(uncore, GEN6_STOLEN_RESERVED); - resource_size_t stolen_top = i915->dsm.end + 1; + resource_size_t stolen_top = i915->dsm.stolen.end + 1; drm_dbg(&i915->drm, "GEN6_STOLEN_RESERVED = %08x\n", reg_val); @@ -365,7 +363,7 @@ static void bdw_get_stolen_reserved(struct drm_i915_private *i915, resource_size_t *size) { u32 reg_val = intel_uncore_read(uncore, GEN6_STOLEN_RESERVED); - resource_size_t stolen_top = i915->dsm.end + 1; + resource_size_t stolen_top = i915->dsm.stolen.end + 1; drm_dbg(&i915->drm, "GEN6_STOLEN_RESERVED = %08x\n", reg_val); @@ -414,7 +412,7 @@ static void icl_get_stolen_reserved(struct drm_i915_private *i915, } /* - * Initialize i915->dsm_reserved to contain the reserved space within the Data + * Initialize i915->dsm.reserved to contain the reserved space within the Data * Stolen Memory. This is a range on the top of DSM that is reserved, not to * be used by driver, so must be excluded from the region passed to the * allocator later. In the spec this is also called as WOPCM. @@ -430,7 +428,7 @@ static int init_reserved_stolen(struct drm_i915_private *i915) resource_size_t reserved_size; int ret = 0; - stolen_top = i915->dsm.end + 1; + stolen_top = i915->dsm.stolen.end + 1; reserved_base = stolen_top; reserved_size = 0; @@ -471,13 +469,12 @@ static int init_reserved_stolen(struct drm_i915_private *i915) goto bail_out; } - i915->dsm_reserved = - (struct resource)DEFINE_RES_MEM(reserved_base, reserved_size); + i915->dsm.reserved = DEFINE_RES_MEM(reserved_base, reserved_size); - if (!resource_contains(&i915->dsm, &i915->dsm_reserved)) { + if (!resource_contains(&i915->dsm.stolen, &i915->dsm.reserved)) { drm_err(&i915->drm, "Stolen reserved area %pR outside stolen memory %pR\n", - &i915->dsm_reserved, &i915->dsm); + &i915->dsm.reserved, &i915->dsm.stolen); ret = -EINVAL; goto bail_out; } @@ -485,8 +482,7 @@ static int init_reserved_stolen(struct drm_i915_private *i915) return 0; bail_out: - i915->dsm_reserved = - (struct resource)DEFINE_RES_MEM(reserved_base, 0); + i915->dsm.reserved = DEFINE_RES_MEM(reserved_base, 0); return ret; } @@ -517,27 +513,27 @@ static int i915_gem_init_stolen(struct intel_memory_region *mem) if (request_smem_stolen(i915, &mem->region)) return -ENOSPC; - i915->dsm = mem->region; + i915->dsm.stolen = mem->region; if (init_reserved_stolen(i915)) return -ENOSPC; /* Exclude the reserved region from driver use */ - mem->region.end = i915->dsm_reserved.start - 1; + mem->region.end = i915->dsm.reserved.start - 1; mem->io_size = min(mem->io_size, resource_size(&mem->region)); - i915->stolen_usable_size = resource_size(&mem->region); + i915->dsm.usable_size = resource_size(&mem->region); drm_dbg(&i915->drm, "Memory reserved for graphics device: %lluK, usable: %lluK\n", - (u64)resource_size(&i915->dsm) >> 10, - (u64)i915->stolen_usable_size >> 10); + (u64)resource_size(&i915->dsm.stolen) >> 10, + (u64)i915->dsm.usable_size >> 10); - if (i915->stolen_usable_size == 0) + if (i915->dsm.usable_size == 0) return -ENOSPC; /* Basic memrange allocator for stolen space. */ - drm_mm_init(&i915->mm.stolen, 0, i915->stolen_usable_size); + drm_mm_init(&i915->mm.stolen, 0, i915->dsm.usable_size); return 0; } @@ -587,7 +583,7 @@ i915_pages_create_for_stolen(struct drm_device *dev, struct sg_table *st; struct scatterlist *sg; - GEM_BUG_ON(range_overflows(offset, size, resource_size(&i915->dsm))); + GEM_BUG_ON(range_overflows(offset, size, resource_size(&i915->dsm.stolen))); /* We hide that we have no struct page backing our stolen object * by wrapping the contiguous physical allocation with a fake @@ -607,7 +603,7 @@ i915_pages_create_for_stolen(struct drm_device *dev, sg->offset = 0; sg->length = size; - sg_dma_address(sg) = (dma_addr_t)i915->dsm.start + offset; + sg_dma_address(sg) = (dma_addr_t)i915->dsm.stolen.start + offset; sg_dma_len(sg) = size; return st; diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c index 0c7fe360f873..842e69c7b21e 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c @@ -12,6 +12,7 @@ #include <drm/i915_drm.h> #include <drm/intel-gtt.h> +#include "display/intel_display.h" #include "gem/i915_gem_lmem.h" #include "intel_ggtt_gmch.h" @@ -885,8 +886,8 @@ static void gen6_gmch_remove(struct i915_address_space *vm) static struct resource pci_resource(struct pci_dev *pdev, int bar) { - return (struct resource)DEFINE_RES_MEM(pci_resource_start(pdev, bar), - pci_resource_len(pdev, bar)); + return DEFINE_RES_MEM(pci_resource_start(pdev, bar), + pci_resource_len(pdev, bar)); } static int gen8_gmch_probe(struct i915_ggtt *ggtt) diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c index 7ac8ed13e1fe..37d0b0fe791d 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c @@ -5,6 +5,7 @@ #include <linux/highmem.h> +#include "display/intel_display.h" #include "i915_drv.h" #include "i915_reg.h" #include "i915_scatterlist.h" diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c b/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c index 0e3630103693..77c793812eb4 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c @@ -80,7 +80,7 @@ int intel_ggtt_gmch_probe(struct i915_ggtt *ggtt) phys_addr_t gmadr_base; int ret; - ret = intel_gmch_probe(i915->bridge_dev, to_pci_dev(i915->drm.dev), NULL); + ret = intel_gmch_probe(i915->gmch.pdev, to_pci_dev(i915->drm.dev), NULL); if (!ret) { drm_err(&i915->drm, "failed to set up gmch\n"); return -EIO; @@ -88,8 +88,7 @@ int intel_ggtt_gmch_probe(struct i915_ggtt *ggtt) intel_gmch_gtt_get(&ggtt->vm.total, &gmadr_base, &ggtt->mappable_end); - ggtt->gmadr = - (struct resource)DEFINE_RES_MEM(gmadr_base, ggtt->mappable_end); + ggtt->gmadr = DEFINE_RES_MEM(gmadr_base, ggtt->mappable_end); ggtt->vm.alloc_pt_dma = alloc_pt_dma; ggtt->vm.alloc_scratch_dma = alloc_pt_dma; diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 7771a19008c6..bbeeb6dde7ae 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -288,39 +288,6 @@ static const u8 dg2_xcs_offsets[] = { END }; -static const u8 mtl_xcs_offsets[] = { - NOP(1), - LRI(13, POSTED), - REG16(0x244), - REG(0x034), - REG(0x030), - REG(0x038), - REG(0x03c), - REG(0x168), - REG(0x140), - REG(0x110), - REG(0x1c0), - REG(0x1c4), - REG(0x1c8), - REG(0x180), - REG16(0x2b4), - NOP(4), - - NOP(1), - LRI(9, POSTED), - REG16(0x3a8), - REG16(0x28c), - REG16(0x288), - REG16(0x284), - REG16(0x280), - REG16(0x27c), - REG16(0x278), - REG16(0x274), - REG16(0x270), - - END -}; - static const u8 gen8_rcs_offsets[] = { NOP(1), LRI(14, POSTED), @@ -739,9 +706,7 @@ static const u8 *reg_offsets(const struct intel_engine_cs *engine) else return gen8_rcs_offsets; } else { - if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 70)) - return mtl_xcs_offsets; - else if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 55)) + if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 55)) return dg2_xcs_offsets; else if (GRAPHICS_VER(engine->i915) >= 12) return gen12_xcs_offsets; diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c index 2ee4051e4d96..5c91622dfca4 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6.c +++ b/drivers/gpu/drm/i915/gt/intel_rc6.c @@ -301,7 +301,7 @@ static int chv_rc6_init(struct intel_rc6 *rc6) pcbr = intel_uncore_read(uncore, VLV_PCBR); if ((pcbr >> VLV_PCBR_ADDR_SHIFT) == 0) { drm_dbg(&i915->drm, "BIOS didn't set up PCBR, fixing up\n"); - paddr = i915->dsm.end + 1 - pctx_size; + paddr = i915->dsm.stolen.end + 1 - pctx_size; GEM_BUG_ON(paddr > U32_MAX); pctx_paddr = (paddr & ~4095); @@ -325,7 +325,7 @@ static int vlv_rc6_init(struct intel_rc6 *rc6) /* BIOS set it up already, grab the pre-alloc'd space */ resource_size_t pcbr_offset; - pcbr_offset = (pcbr & ~4095) - i915->dsm.start; + pcbr_offset = (pcbr & ~4095) - i915->dsm.stolen.start; pctx = i915_gem_object_create_region_at(i915->mm.stolen_region, pcbr_offset, pctx_size, @@ -354,10 +354,10 @@ static int vlv_rc6_init(struct intel_rc6 *rc6) } GEM_BUG_ON(range_overflows_end_t(u64, - i915->dsm.start, + i915->dsm.stolen.start, pctx->stolen->start, U32_MAX)); - pctx_paddr = i915->dsm.start + pctx->stolen->start; + pctx_paddr = i915->dsm.stolen.start + pctx->stolen->start; intel_uncore_write(uncore, VLV_PCBR, pctx_paddr); out: @@ -448,8 +448,8 @@ static bool bxt_check_bios_rc6_setup(struct intel_rc6 *rc6) */ rc6_ctx_base = intel_uncore_read(uncore, RC6_CTX_BASE) & RC6_CTX_BASE_MASK; - if (!(rc6_ctx_base >= i915->dsm_reserved.start && - rc6_ctx_base + PAGE_SIZE < i915->dsm_reserved.end)) { + if (!(rc6_ctx_base >= i915->dsm.reserved.start && + rc6_ctx_base + PAGE_SIZE < i915->dsm.reserved.end)) { drm_dbg(&i915->drm, "RC6 Base address not as expected.\n"); enable_rc6 = false; } diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index 9ad3bc7201cb..f5d7b5126433 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -7,6 +7,7 @@ #include <drm/i915_drm.h> +#include "display/intel_display.h" #include "i915_drv.h" #include "i915_irq.h" #include "intel_breadcrumbs.h" diff --git a/drivers/gpu/drm/i915/gt/intel_rps.h b/drivers/gpu/drm/i915/gt/intel_rps.h index 9e1cad9ba0e9..c622962c6bef 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.h +++ b/drivers/gpu/drm/i915/gt/intel_rps.h @@ -12,6 +12,9 @@ struct i915_request; struct drm_printer; +#define GT_FREQUENCY_MULTIPLIER 50 +#define GEN9_FREQ_SCALER 3 + void intel_rps_init_early(struct intel_rps *rps); void intel_rps_init(struct intel_rps *rps); void intel_rps_sanitize(struct intel_rps *rps); diff --git a/drivers/gpu/drm/i915/gt/selftest_reset.c b/drivers/gpu/drm/i915/gt/selftest_reset.c index 37c38bdd5f47..a9e0a91bc0e0 100644 --- a/drivers/gpu/drm/i915/gt/selftest_reset.c +++ b/drivers/gpu/drm/i915/gt/selftest_reset.c @@ -20,7 +20,7 @@ __igt_reset_stolen(struct intel_gt *gt, const char *msg) { struct i915_ggtt *ggtt = gt->ggtt; - const struct resource *dsm = >->i915->dsm; + const struct resource *dsm = >->i915->dsm.stolen; resource_size_t num_pages, page; struct intel_engine_cs *engine; intel_wakeref_t wakeref; diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index 0ebf5fbf0e39..3c4ae1da0d41 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -49,6 +49,7 @@ #include "i915_pvinfo.h" #include "trace.h" +#include "display/intel_display.h" #include "gem/i915_gem_context.h" #include "gem/i915_gem_pm.h" #include "gt/intel_context.h" diff --git a/drivers/gpu/drm/i915/gvt/debugfs.c b/drivers/gpu/drm/i915/gvt/debugfs.c index 9f1c209d9251..0616b73175f3 100644 --- a/drivers/gpu/drm/i915/gvt/debugfs.c +++ b/drivers/gpu/drm/i915/gvt/debugfs.c @@ -151,6 +151,22 @@ DEFINE_SIMPLE_ATTRIBUTE(vgpu_scan_nonprivbb_fops, vgpu_scan_nonprivbb_get, vgpu_scan_nonprivbb_set, "0x%llx\n"); +static int vgpu_status_get(void *data, u64 *val) +{ + struct intel_vgpu *vgpu = (struct intel_vgpu *)data; + + *val = 0; + + if (test_bit(INTEL_VGPU_STATUS_ATTACHED, vgpu->status)) + *val |= (1 << INTEL_VGPU_STATUS_ATTACHED); + if (test_bit(INTEL_VGPU_STATUS_ACTIVE, vgpu->status)) + *val |= (1 << INTEL_VGPU_STATUS_ACTIVE); + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(vgpu_status_fops, vgpu_status_get, NULL, "0x%llx\n"); + /** * intel_gvt_debugfs_add_vgpu - register debugfs entries for a vGPU * @vgpu: a vGPU @@ -162,11 +178,12 @@ void intel_gvt_debugfs_add_vgpu(struct intel_vgpu *vgpu) snprintf(name, 16, "vgpu%d", vgpu->id); vgpu->debugfs = debugfs_create_dir(name, vgpu->gvt->debugfs_root); - debugfs_create_bool("active", 0444, vgpu->debugfs, &vgpu->active); debugfs_create_file("mmio_diff", 0444, vgpu->debugfs, vgpu, &vgpu_mmio_diff_fops); debugfs_create_file("scan_nonprivbb", 0644, vgpu->debugfs, vgpu, &vgpu_scan_nonprivbb_fops); + debugfs_create_file("status", 0644, vgpu->debugfs, vgpu, + &vgpu_status_fops); } /** @@ -175,8 +192,13 @@ void intel_gvt_debugfs_add_vgpu(struct intel_vgpu *vgpu) */ void intel_gvt_debugfs_remove_vgpu(struct intel_vgpu *vgpu) { - debugfs_remove_recursive(vgpu->debugfs); - vgpu->debugfs = NULL; + struct intel_gvt *gvt = vgpu->gvt; + struct drm_minor *minor = gvt->gt->i915->drm.primary; + + if (minor->debugfs_root && gvt->debugfs_root) { + debugfs_remove_recursive(vgpu->debugfs); + vgpu->debugfs = NULL; + } } /** @@ -199,6 +221,10 @@ void intel_gvt_debugfs_init(struct intel_gvt *gvt) */ void intel_gvt_debugfs_clean(struct intel_gvt *gvt) { - debugfs_remove_recursive(gvt->debugfs_root); - gvt->debugfs_root = NULL; + struct drm_minor *minor = gvt->gt->i915->drm.primary; + + if (minor->debugfs_root) { + debugfs_remove_recursive(gvt->debugfs_root); + gvt->debugfs_root = NULL; + } } diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c index c033249e73f4..4d898b14de93 100644 --- a/drivers/gpu/drm/i915/gvt/display.c +++ b/drivers/gpu/drm/i915/gvt/display.c @@ -36,6 +36,7 @@ #include "i915_reg.h" #include "gvt.h" +#include "display/intel_display.h" #include "display/intel_dpio_phy.h" static int get_edp_pipe(struct intel_vgpu *vgpu) diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c b/drivers/gpu/drm/i915/gvt/dmabuf.c index 7af09eb24ac0..6834f9fe40cf 100644 --- a/drivers/gpu/drm/i915/gvt/dmabuf.c +++ b/drivers/gpu/drm/i915/gvt/dmabuf.c @@ -136,7 +136,8 @@ static void dmabuf_gem_object_free(struct kref *kref) struct list_head *pos; struct intel_vgpu_dmabuf_obj *dmabuf_obj; - if (vgpu && vgpu->active && !list_empty(&vgpu->dmabuf_obj_list_head)) { + if (vgpu && test_bit(INTEL_VGPU_STATUS_ACTIVE, vgpu->status) && + !list_empty(&vgpu->dmabuf_obj_list_head)) { list_for_each(pos, &vgpu->dmabuf_obj_list_head) { dmabuf_obj = list_entry(pos, struct intel_vgpu_dmabuf_obj, list); if (dmabuf_obj == obj) { diff --git a/drivers/gpu/drm/i915/gvt/fb_decoder.h b/drivers/gpu/drm/i915/gvt/fb_decoder.h index 0daa3931aef7..4eff44194439 100644 --- a/drivers/gpu/drm/i915/gvt/fb_decoder.h +++ b/drivers/gpu/drm/i915/gvt/fb_decoder.h @@ -38,7 +38,7 @@ #include <linux/types.h> -#include "display/intel_display.h" +#include "display/intel_display_limits.h" struct intel_vgpu; diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index 51e5e8fb505b..4ec85308379a 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -55,7 +55,7 @@ static bool intel_gvt_is_valid_gfn(struct intel_vgpu *vgpu, unsigned long gfn) int idx; bool ret; - if (!vgpu->attached) + if (!test_bit(INTEL_VGPU_STATUS_ATTACHED, vgpu->status)) return false; idx = srcu_read_lock(&kvm->srcu); @@ -1178,7 +1178,7 @@ static int is_2MB_gtt_possible(struct intel_vgpu *vgpu, if (!HAS_PAGE_SIZES(vgpu->gvt->gt->i915, I915_GTT_PAGE_SIZE_2M)) return 0; - if (!vgpu->attached) + if (!test_bit(INTEL_VGPU_STATUS_ATTACHED, vgpu->status)) return -EINVAL; pfn = gfn_to_pfn(vgpu->vfio_device.kvm, ops->get_pfn(entry)); if (is_error_noslot_pfn(pfn)) @@ -1209,10 +1209,8 @@ static int split_2MB_gtt_entry(struct intel_vgpu *vgpu, for_each_shadow_entry(sub_spt, &sub_se, sub_index) { ret = intel_gvt_dma_map_guest_page(vgpu, start_gfn + sub_index, PAGE_SIZE, &dma_addr); - if (ret) { - ppgtt_invalidate_spt(spt); - return ret; - } + if (ret) + goto err; sub_se.val64 = se->val64; /* Copy the PAT field from PDE. */ @@ -1231,6 +1229,17 @@ static int split_2MB_gtt_entry(struct intel_vgpu *vgpu, ops->set_pfn(se, sub_spt->shadow_page.mfn); ppgtt_set_shadow_entry(spt, se, index); return 0; +err: + /* Cancel the existing addess mappings of DMA addr. */ + for_each_present_shadow_entry(sub_spt, &sub_se, sub_index) { + gvt_vdbg_mm("invalidate 4K entry\n"); + ppgtt_invalidate_pte(sub_spt, &sub_se); + } + /* Release the new allocated spt. */ + trace_spt_change(sub_spt->vgpu->id, "release", sub_spt, + sub_spt->guest_page.gfn, sub_spt->shadow_page.type); + ppgtt_free_spt(sub_spt); + return ret; } static int split_64KB_gtt_entry(struct intel_vgpu *vgpu, diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 62823c0e13ab..2d65800d8e93 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -172,13 +172,18 @@ struct intel_vgpu_submission { #define KVMGT_DEBUGFS_FILENAME "kvmgt_nr_cache_entries" +enum { + INTEL_VGPU_STATUS_ATTACHED = 0, + INTEL_VGPU_STATUS_ACTIVE, + INTEL_VGPU_STATUS_NR_BITS, +}; + struct intel_vgpu { struct vfio_device vfio_device; struct intel_gvt *gvt; struct mutex vgpu_lock; int id; - bool active; - bool attached; + DECLARE_BITMAP(status, INTEL_VGPU_STATUS_NR_BITS); bool pv_notified; bool failsafe; unsigned int resetting_eng; @@ -467,7 +472,7 @@ void intel_vgpu_write_fence(struct intel_vgpu *vgpu, #define for_each_active_vgpu(gvt, vgpu, id) \ idr_for_each_entry((&(gvt)->vgpu_idr), (vgpu), (id)) \ - for_each_if(vgpu->active) + for_each_if(test_bit(INTEL_VGPU_STATUS_ACTIVE, vgpu->status)) static inline void intel_vgpu_write_pci_bar(struct intel_vgpu *vgpu, u32 offset, u32 val, bool low) @@ -725,7 +730,7 @@ static inline bool intel_gvt_mmio_is_cmd_write_patch( static inline int intel_gvt_read_gpa(struct intel_vgpu *vgpu, unsigned long gpa, void *buf, unsigned long len) { - if (!vgpu->attached) + if (!test_bit(INTEL_VGPU_STATUS_ATTACHED, vgpu->status)) return -ESRCH; return vfio_dma_rw(&vgpu->vfio_device, gpa, buf, len, false); } @@ -743,7 +748,7 @@ static inline int intel_gvt_read_gpa(struct intel_vgpu *vgpu, unsigned long gpa, static inline int intel_gvt_write_gpa(struct intel_vgpu *vgpu, unsigned long gpa, void *buf, unsigned long len) { - if (!vgpu->attached) + if (!test_bit(INTEL_VGPU_STATUS_ATTACHED, vgpu->status)) return -ESRCH; return vfio_dma_rw(&vgpu->vfio_device, gpa, buf, len, true); } diff --git a/drivers/gpu/drm/i915/gvt/interrupt.c b/drivers/gpu/drm/i915/gvt/interrupt.c index a6b2021b665f..68eca023bbc6 100644 --- a/drivers/gpu/drm/i915/gvt/interrupt.c +++ b/drivers/gpu/drm/i915/gvt/interrupt.c @@ -433,7 +433,7 @@ static int inject_virtual_interrupt(struct intel_vgpu *vgpu) * enabled by guest. so if msi_trigger is null, success is still * returned and don't inject interrupt into guest. */ - if (!vgpu->attached) + if (!test_bit(INTEL_VGPU_STATUS_ATTACHED, vgpu->status)) return -ESRCH; if (vgpu->msi_trigger && eventfd_signal(vgpu->msi_trigger, 1) != 1) return -EFAULT; diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c index f5451adcd489..8ae7039b3683 100644 --- a/drivers/gpu/drm/i915/gvt/kvmgt.c +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c @@ -638,7 +638,7 @@ static bool __kvmgt_vgpu_exist(struct intel_vgpu *vgpu) mutex_lock(&vgpu->gvt->lock); for_each_active_vgpu(vgpu->gvt, itr, id) { - if (!itr->attached) + if (!test_bit(INTEL_VGPU_STATUS_ATTACHED, itr->status)) continue; if (vgpu->vfio_device.kvm == itr->vfio_device.kvm) { @@ -655,9 +655,6 @@ static int intel_vgpu_open_device(struct vfio_device *vfio_dev) { struct intel_vgpu *vgpu = vfio_dev_to_vgpu(vfio_dev); - if (vgpu->attached) - return -EEXIST; - if (!vgpu->vfio_device.kvm || vgpu->vfio_device.kvm->mm != current->mm) { gvt_vgpu_err("KVM is required to use Intel vGPU\n"); @@ -667,14 +664,14 @@ static int intel_vgpu_open_device(struct vfio_device *vfio_dev) if (__kvmgt_vgpu_exist(vgpu)) return -EEXIST; - vgpu->attached = true; - vgpu->track_node.track_write = kvmgt_page_track_write; vgpu->track_node.track_flush_slot = kvmgt_page_track_flush_slot; kvm_get_kvm(vgpu->vfio_device.kvm); kvm_page_track_register_notifier(vgpu->vfio_device.kvm, &vgpu->track_node); + set_bit(INTEL_VGPU_STATUS_ATTACHED, vgpu->status); + debugfs_create_ulong(KVMGT_DEBUGFS_FILENAME, 0444, vgpu->debugfs, &vgpu->nr_cache_entries); @@ -698,11 +695,10 @@ static void intel_vgpu_close_device(struct vfio_device *vfio_dev) { struct intel_vgpu *vgpu = vfio_dev_to_vgpu(vfio_dev); - if (!vgpu->attached) - return; - intel_gvt_release_vgpu(vgpu); + clear_bit(INTEL_VGPU_STATUS_ATTACHED, vgpu->status); + debugfs_remove(debugfs_lookup(KVMGT_DEBUGFS_FILENAME, vgpu->debugfs)); kvm_page_track_unregister_notifier(vgpu->vfio_device.kvm, @@ -718,8 +714,6 @@ static void intel_vgpu_close_device(struct vfio_device *vfio_dev) vgpu->dma_addr_cache = RB_ROOT; intel_vgpu_release_msi_eventfd_ctx(vgpu); - - vgpu->attached = false; } static u64 intel_vgpu_get_bar_addr(struct intel_vgpu *vgpu, int bar) @@ -1512,9 +1506,6 @@ static void intel_vgpu_remove(struct mdev_device *mdev) { struct intel_vgpu *vgpu = dev_get_drvdata(&mdev->dev); - if (WARN_ON_ONCE(vgpu->attached)) - return; - vfio_unregister_group_dev(&vgpu->vfio_device); vfio_put_device(&vgpu->vfio_device); } @@ -1559,7 +1550,7 @@ int intel_gvt_page_track_add(struct intel_vgpu *info, u64 gfn) struct kvm_memory_slot *slot; int idx; - if (!info->attached) + if (!test_bit(INTEL_VGPU_STATUS_ATTACHED, info->status)) return -ESRCH; idx = srcu_read_lock(&kvm->srcu); @@ -1589,8 +1580,8 @@ int intel_gvt_page_track_remove(struct intel_vgpu *info, u64 gfn) struct kvm_memory_slot *slot; int idx; - if (!info->attached) - return 0; + if (!test_bit(INTEL_VGPU_STATUS_ATTACHED, info->status)) + return -ESRCH; idx = srcu_read_lock(&kvm->srcu); slot = gfn_to_memslot(kvm, gfn); @@ -1668,7 +1659,7 @@ int intel_gvt_dma_map_guest_page(struct intel_vgpu *vgpu, unsigned long gfn, struct gvt_dma *entry; int ret; - if (!vgpu->attached) + if (!test_bit(INTEL_VGPU_STATUS_ATTACHED, vgpu->status)) return -EINVAL; mutex_lock(&vgpu->cache_lock); @@ -1714,8 +1705,8 @@ int intel_gvt_dma_pin_guest_page(struct intel_vgpu *vgpu, dma_addr_t dma_addr) struct gvt_dma *entry; int ret = 0; - if (!vgpu->attached) - return -ENODEV; + if (!test_bit(INTEL_VGPU_STATUS_ATTACHED, vgpu->status)) + return -EINVAL; mutex_lock(&vgpu->cache_lock); entry = __gvt_cache_find_dma_addr(vgpu, dma_addr); @@ -1742,7 +1733,7 @@ void intel_gvt_dma_unmap_guest_page(struct intel_vgpu *vgpu, { struct gvt_dma *entry; - if (!vgpu->attached) + if (!test_bit(INTEL_VGPU_STATUS_ATTACHED, vgpu->status)) return; mutex_lock(&vgpu->cache_lock); @@ -1778,7 +1769,7 @@ static void intel_gvt_test_and_emulate_vblank(struct intel_gvt *gvt) idr_for_each_entry((&(gvt)->vgpu_idr), (vgpu), (id)) { if (test_and_clear_bit(INTEL_GVT_REQUEST_EMULATE_VBLANK + id, (void *)&gvt->service_request)) { - if (vgpu->active) + if (test_bit(INTEL_VGPU_STATUS_ACTIVE, vgpu->status)) intel_vgpu_emulate_vblank(vgpu); } } diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index 9cd8fcbf7cad..f4055804aad1 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -695,6 +695,7 @@ intel_vgpu_shadow_mm_pin(struct intel_vgpu_workload *workload) if (workload->shadow_mm->type != INTEL_GVT_MM_PPGTT || !workload->shadow_mm->ppgtt_mm.shadowed) { + intel_vgpu_unpin_mm(workload->shadow_mm); gvt_vgpu_err("workload shadow ppgtt isn't ready\n"); return -EINVAL; } @@ -865,7 +866,8 @@ pick_next_workload(struct intel_gvt *gvt, struct intel_engine_cs *engine) goto out; } - if (!scheduler->current_vgpu->active || + if (!test_bit(INTEL_VGPU_STATUS_ACTIVE, + scheduler->current_vgpu->status) || list_empty(workload_q_head(scheduler->current_vgpu, engine))) goto out; diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c index 3c529c2705dd..a5497440484f 100644 --- a/drivers/gpu/drm/i915/gvt/vgpu.c +++ b/drivers/gpu/drm/i915/gvt/vgpu.c @@ -166,9 +166,7 @@ void intel_gvt_clean_vgpu_types(struct intel_gvt *gvt) */ void intel_gvt_activate_vgpu(struct intel_vgpu *vgpu) { - mutex_lock(&vgpu->vgpu_lock); - vgpu->active = true; - mutex_unlock(&vgpu->vgpu_lock); + set_bit(INTEL_VGPU_STATUS_ACTIVE, vgpu->status); } /** @@ -183,7 +181,7 @@ void intel_gvt_deactivate_vgpu(struct intel_vgpu *vgpu) { mutex_lock(&vgpu->vgpu_lock); - vgpu->active = false; + clear_bit(INTEL_VGPU_STATUS_ACTIVE, vgpu->status); if (atomic_read(&vgpu->submission.running_workload_num)) { mutex_unlock(&vgpu->vgpu_lock); @@ -228,7 +226,8 @@ void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu) struct intel_gvt *gvt = vgpu->gvt; struct drm_i915_private *i915 = gvt->gt->i915; - drm_WARN(&i915->drm, vgpu->active, "vGPU is still active!\n"); + drm_WARN(&i915->drm, test_bit(INTEL_VGPU_STATUS_ACTIVE, vgpu->status), + "vGPU is still active!\n"); /* * remove idr first so later clean can judge if need to stop @@ -285,8 +284,7 @@ struct intel_vgpu *intel_gvt_create_idle_vgpu(struct intel_gvt *gvt) if (ret) goto out_free_vgpu; - vgpu->active = false; - + clear_bit(INTEL_VGPU_STATUS_ACTIVE, vgpu->status); return vgpu; out_free_vgpu: diff --git a/drivers/gpu/drm/i915/i915_config.c b/drivers/gpu/drm/i915/i915_config.c index afb828dab53b..24e5bb8a670e 100644 --- a/drivers/gpu/drm/i915/i915_config.c +++ b/drivers/gpu/drm/i915/i915_config.c @@ -3,7 +3,10 @@ * Copyright © 2020 Intel Corporation */ -#include "i915_drv.h" +#include <linux/kernel.h> + +#include "i915_config.h" +#include "i915_utils.h" unsigned long i915_fence_context_timeout(const struct drm_i915_private *i915, u64 context) diff --git a/drivers/gpu/drm/i915/i915_config.h b/drivers/gpu/drm/i915/i915_config.h new file mode 100644 index 000000000000..10e18b036489 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_config.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 Intel Corporation + */ + +#ifndef __I915_CONFIG_H__ +#define __I915_CONFIG_H__ + +#include <linux/types.h> +#include <linux/limits.h> + +struct drm_i915_private; + +unsigned long i915_fence_context_timeout(const struct drm_i915_private *i915, + u64 context); + +static inline unsigned long +i915_fence_timeout(const struct drm_i915_private *i915) +{ + return i915_fence_context_timeout(i915, U64_MAX); +} + +#endif /* __I915_CONFIG_H__ */ diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index a356ca490159..45773ce1deac 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -648,13 +648,14 @@ i915_drop_caches_get(void *data, u64 *val) return 0; } + static int gt_drop_caches(struct intel_gt *gt, u64 val) { int ret; if (val & DROP_RESET_ACTIVE && - wait_for(intel_engines_are_idle(gt), I915_IDLE_ENGINES_TIMEOUT)) + wait_for(intel_engines_are_idle(gt), 200)) intel_gt_set_wedged(gt); if (val & DROP_RETIRE) @@ -762,7 +763,6 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_sseu_status", i915_sseu_status, 0}, {"i915_rps_boost_info", i915_rps_boost_info, 0}, }; -#define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list) static const struct i915_debugfs_files { const char *name; @@ -795,6 +795,6 @@ void i915_debugfs_register(struct drm_i915_private *dev_priv) } drm_debugfs_create_files(i915_debugfs_list, - I915_DEBUGFS_ENTRIES, + ARRAY_SIZE(i915_debugfs_list), minor->debugfs_root, minor); } diff --git a/drivers/gpu/drm/i915/i915_debugfs_params.c b/drivers/gpu/drm/i915/i915_debugfs_params.c index 783c8676eee2..614bde321589 100644 --- a/drivers/gpu/drm/i915/i915_debugfs_params.c +++ b/drivers/gpu/drm/i915/i915_debugfs_params.c @@ -230,27 +230,16 @@ i915_debugfs_create_charp(const char *name, umode_t mode, &i915_param_charp_fops); } -static __always_inline void -_i915_param_create_file(struct dentry *parent, const char *name, - const char *type, int mode, void *value) -{ - if (!mode) - return; - - if (!__builtin_strcmp(type, "bool")) - debugfs_create_bool(name, mode, parent, value); - else if (!__builtin_strcmp(type, "int")) - i915_debugfs_create_int(name, mode, parent, value); - else if (!__builtin_strcmp(type, "unsigned int")) - i915_debugfs_create_uint(name, mode, parent, value); - else if (!__builtin_strcmp(type, "unsigned long")) - debugfs_create_ulong(name, mode, parent, value); - else if (!__builtin_strcmp(type, "char *")) - i915_debugfs_create_charp(name, mode, parent, value); - else - WARN(1, "no debugfs fops defined for param type %s (i915.%s)\n", - type, name); -} +#define _i915_param_create_file(parent, name, mode, valp) \ + do { \ + if (mode) \ + _Generic(valp, \ + bool *: debugfs_create_bool, \ + int *: i915_debugfs_create_int, \ + unsigned int *: i915_debugfs_create_uint, \ + unsigned long *: debugfs_create_ulong, \ + char **: i915_debugfs_create_charp)(name, mode, parent, valp); \ + } while(0) /* add a subdirectory with files for each i915 param */ struct dentry *i915_debugfs_params(struct drm_i915_private *i915) @@ -269,7 +258,7 @@ struct dentry *i915_debugfs_params(struct drm_i915_private *i915) * just let the generic create file fail silently with -EEXIST. */ -#define REGISTER(T, x, unused, mode, ...) _i915_param_create_file(dir, #x, #T, mode, ¶ms->x); +#define REGISTER(T, x, unused, mode, ...) _i915_param_create_file(dir, #x, mode, ¶ms->x); I915_PARAMS_FOR_EACH(REGISTER); #undef REGISTER diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index c1e427ba57ae..cf1c0970ecb4 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -34,7 +34,6 @@ #include <linux/pci.h> #include <linux/pm.h> #include <linux/pm_runtime.h> -#include <linux/pnp.h> #include <linux/slab.h> #include <linux/string_helpers.h> #include <linux/vga_switcheroo.h> @@ -78,6 +77,7 @@ #include "pxp/intel_pxp_pm.h" #include "soc/intel_dram.h" +#include "soc/intel_gmch.h" #include "i915_file_private.h" #include "i915_debugfs.h" @@ -107,141 +107,6 @@ static const struct drm_driver i915_drm_driver; -static void i915_release_bridge_dev(struct drm_device *dev, - void *bridge) -{ - pci_dev_put(bridge); -} - -static int i915_get_bridge_dev(struct drm_i915_private *dev_priv) -{ - int domain = pci_domain_nr(to_pci_dev(dev_priv->drm.dev)->bus); - - dev_priv->bridge_dev = - pci_get_domain_bus_and_slot(domain, 0, PCI_DEVFN(0, 0)); - if (!dev_priv->bridge_dev) { - drm_err(&dev_priv->drm, "bridge device not found\n"); - return -EIO; - } - - return drmm_add_action_or_reset(&dev_priv->drm, i915_release_bridge_dev, - dev_priv->bridge_dev); -} - -/* Allocate space for the MCH regs if needed, return nonzero on error */ -static int -intel_alloc_mchbar_resource(struct drm_i915_private *dev_priv) -{ - int reg = GRAPHICS_VER(dev_priv) >= 4 ? MCHBAR_I965 : MCHBAR_I915; - u32 temp_lo, temp_hi = 0; - u64 mchbar_addr; - int ret; - - if (GRAPHICS_VER(dev_priv) >= 4) - pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi); - pci_read_config_dword(dev_priv->bridge_dev, reg, &temp_lo); - mchbar_addr = ((u64)temp_hi << 32) | temp_lo; - - /* If ACPI doesn't have it, assume we need to allocate it ourselves */ -#ifdef CONFIG_PNP - if (mchbar_addr && - pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) - return 0; -#endif - - /* Get some space for it */ - dev_priv->mch_res.name = "i915 MCHBAR"; - dev_priv->mch_res.flags = IORESOURCE_MEM; - ret = pci_bus_alloc_resource(dev_priv->bridge_dev->bus, - &dev_priv->mch_res, - MCHBAR_SIZE, MCHBAR_SIZE, - PCIBIOS_MIN_MEM, - 0, pcibios_align_resource, - dev_priv->bridge_dev); - if (ret) { - drm_dbg(&dev_priv->drm, "failed bus alloc: %d\n", ret); - dev_priv->mch_res.start = 0; - return ret; - } - - if (GRAPHICS_VER(dev_priv) >= 4) - pci_write_config_dword(dev_priv->bridge_dev, reg + 4, - upper_32_bits(dev_priv->mch_res.start)); - - pci_write_config_dword(dev_priv->bridge_dev, reg, - lower_32_bits(dev_priv->mch_res.start)); - return 0; -} - -/* Setup MCHBAR if possible, return true if we should disable it again */ -static void -intel_setup_mchbar(struct drm_i915_private *dev_priv) -{ - int mchbar_reg = GRAPHICS_VER(dev_priv) >= 4 ? MCHBAR_I965 : MCHBAR_I915; - u32 temp; - bool enabled; - - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) - return; - - dev_priv->mchbar_need_disable = false; - - if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) { - pci_read_config_dword(dev_priv->bridge_dev, DEVEN, &temp); - enabled = !!(temp & DEVEN_MCHBAR_EN); - } else { - pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp); - enabled = temp & 1; - } - - /* If it's already enabled, don't have to do anything */ - if (enabled) - return; - - if (intel_alloc_mchbar_resource(dev_priv)) - return; - - dev_priv->mchbar_need_disable = true; - - /* Space is allocated or reserved, so enable it. */ - if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) { - pci_write_config_dword(dev_priv->bridge_dev, DEVEN, - temp | DEVEN_MCHBAR_EN); - } else { - pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp); - pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp | 1); - } -} - -static void -intel_teardown_mchbar(struct drm_i915_private *dev_priv) -{ - int mchbar_reg = GRAPHICS_VER(dev_priv) >= 4 ? MCHBAR_I965 : MCHBAR_I915; - - if (dev_priv->mchbar_need_disable) { - if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) { - u32 deven_val; - - pci_read_config_dword(dev_priv->bridge_dev, DEVEN, - &deven_val); - deven_val &= ~DEVEN_MCHBAR_EN; - pci_write_config_dword(dev_priv->bridge_dev, DEVEN, - deven_val); - } else { - u32 mchbar_val; - - pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, - &mchbar_val); - mchbar_val &= ~1; - pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, - mchbar_val); - } - } - - if (dev_priv->mch_res.start) - release_resource(&dev_priv->mch_res); -} - static int i915_workqueues_init(struct drm_i915_private *dev_priv) { /* @@ -447,7 +312,7 @@ static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv) if (i915_inject_probe_failure(dev_priv)) return -ENODEV; - ret = i915_get_bridge_dev(dev_priv); + ret = intel_gmch_bridge_setup(dev_priv); if (ret < 0) return ret; @@ -464,7 +329,7 @@ static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv) } /* Try to make sure MCHBAR is enabled before poking at it */ - intel_setup_mchbar(dev_priv); + intel_gmch_bar_setup(dev_priv); intel_device_info_runtime_init(dev_priv); for_each_gt(gt, dev_priv, i) { @@ -479,7 +344,7 @@ static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv) return 0; err_uncore: - intel_teardown_mchbar(dev_priv); + intel_gmch_bar_teardown(dev_priv); return ret; } @@ -490,7 +355,7 @@ err_uncore: */ static void i915_driver_mmio_release(struct drm_i915_private *dev_priv) { - intel_teardown_mchbar(dev_priv); + intel_gmch_bar_teardown(dev_priv); } /** @@ -1071,12 +936,9 @@ static int i915_driver_open(struct drm_device *dev, struct drm_file *file) */ static void i915_driver_lastclose(struct drm_device *dev) { - struct drm_i915_private *i915 = to_i915(dev); - intel_fbdev_restore_mode(dev); - if (HAS_DISPLAY(i915)) - vga_switcheroo_process_delayed_switch(); + vga_switcheroo_process_delayed_switch(); } static void i915_driver_postclose(struct drm_device *dev, struct drm_file *file) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 48fd82722f12..48c838b4ea62 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -36,7 +36,7 @@ #include <drm/ttm/ttm_device.h> -#include "display/intel_display.h" +#include "display/intel_display_limits.h" #include "display/intel_display_core.h" #include "gem/i915_gem_context_types.h" @@ -65,26 +65,41 @@ #include "intel_uncore.h" struct drm_i915_clock_gating_funcs; -struct drm_i915_gem_object; -struct drm_i915_private; -struct intel_connector; -struct intel_dp; -struct intel_encoder; -struct intel_limit; -struct intel_overlay_error_state; struct vlv_s0ix_state; struct intel_pxp; -#define I915_GEM_GPU_DOMAINS \ - (I915_GEM_DOMAIN_RENDER | \ - I915_GEM_DOMAIN_SAMPLER | \ - I915_GEM_DOMAIN_COMMAND | \ - I915_GEM_DOMAIN_INSTRUCTION | \ - I915_GEM_DOMAIN_VERTEX) +#define GEM_QUIRK_PIN_SWIZZLED_PAGES BIT(0) -#define I915_COLOR_UNEVICTABLE (-1) /* a non-vma sharing the address space */ +/* Data Stolen Memory (DSM) aka "i915 stolen memory" */ +struct i915_dsm { + /* + * The start and end of DSM which we can optionally use to create GEM + * objects backed by stolen memory. + * + * Note that usable_size tells us exactly how much of this we are + * actually allowed to use, given that some portion of it is in fact + * reserved for use by hardware functions. + */ + struct resource stolen; -#define GEM_QUIRK_PIN_SWIZZLED_PAGES BIT(0) + /* + * Reserved portion of DSM. + */ + struct resource reserved; + + /* + * Total size minus reserved ranges. + * + * DSM is segmented in hardware with different portions offlimits to + * certain functions. + * + * The drm_mm is initialised to the total accessible range, as found + * from the PCI config. On Broadwell+, this is further restricted to + * avoid the first page! The upper end of DSM is reserved for hardware + * functions and similarly removed from the accessible range. + */ + resource_size_t usable_size; +}; struct i915_suspend_saved_registers { u32 saveDSPARB; @@ -163,19 +178,6 @@ struct i915_gem_mm { u32 shrink_count; }; -#define I915_IDLE_ENGINES_TIMEOUT (200) /* in ms */ - -unsigned long i915_fence_context_timeout(const struct drm_i915_private *i915, - u64 context); - -static inline unsigned long -i915_fence_timeout(const struct drm_i915_private *i915) -{ - return i915_fence_context_timeout(i915, U64_MAX); -} - -#define HAS_HW_SAGV_WM(i915) (DISPLAY_VER(i915) >= 13 && !IS_DGFX(i915)) - struct i915_virtual_gpu { struct mutex lock; /* serialises sending of g2v_notify command pkts */ bool active; @@ -205,29 +207,7 @@ struct drm_i915_private { struct intel_runtime_info __runtime; /* Use RUNTIME_INFO() to access. */ struct intel_driver_caps caps; - /** - * Data Stolen Memory - aka "i915 stolen memory" gives us the start and - * end of stolen which we can optionally use to create GEM objects - * backed by stolen memory. Note that stolen_usable_size tells us - * exactly how much of this we are actually allowed to use, given that - * some portion of it is in fact reserved for use by hardware functions. - */ - struct resource dsm; - /** - * Reseved portion of Data Stolen Memory - */ - struct resource dsm_reserved; - - /* - * Stolen memory is segmented in hardware with different portions - * offlimits to certain functions. - * - * The drm_mm is initialised to the total accessible range, as found - * from the PCI config. On Broadwell+, this is further restricted to - * avoid the first page! The upper end of stolen memory is reserved for - * hardware functions and similarly removed from the accessible range. - */ - resource_size_t stolen_usable_size; /* Total size minus reserved ranges */ + struct i915_dsm dsm; struct intel_uncore uncore; struct intel_uncore_mmio_debug mmio_debug; @@ -236,13 +216,15 @@ struct drm_i915_private { struct intel_gvt *gvt; - struct pci_dev *bridge_dev; + struct { + struct pci_dev *pdev; + struct resource mch_res; + bool mchbar_need_disable; + } gmch; struct rb_root uabi_engines; unsigned int engine_uabi_class_count[I915_LAST_UABI_ENGINE_CLASS + 1]; - struct resource mch_res; - /* protects the irq masks */ spinlock_t irq_lock; @@ -288,8 +270,6 @@ struct drm_i915_private { struct i915_gem_mm mm; - bool mchbar_need_disable; - struct intel_l3_parity l3_parity; /* @@ -300,14 +280,6 @@ struct drm_i915_private { struct i915_gpu_error gpu_error; - /* - * Shadows for CHV DPLL_MD regs to keep the state - * checker somewhat working in the presence hardware - * crappiness (can't read out DPLL_MD for pipes B & C). - */ - u32 chv_dpll_md[I915_MAX_PIPES]; - u32 bxt_phy_grc; - u32 suspend_count; struct i915_suspend_saved_registers regfile; struct vlv_s0ix_state *vlv_s0ix_state; @@ -368,19 +340,11 @@ struct drm_i915_private { struct intel_pxp *pxp; - u8 pch_ssc_use; - /* For i915gm/i945gm vblank irq workaround */ u8 vblank_enabled; bool irq_enabled; - /* - * DG2: Mask of PHYs that were not calibrated by the firmware - * and should not be used. - */ - u8 snps_phy_failed_calibration; - struct i915_pmu pmu; struct i915_drm_clients clients; @@ -469,9 +433,6 @@ static inline struct intel_gt *to_gt(struct drm_i915_private *i915) #define INTEL_REVID(dev_priv) (to_pci_dev((dev_priv)->drm.dev)->revision) -#define HAS_DSB(dev_priv) (INTEL_INFO(dev_priv)->display.has_dsb) -#define HAS_DSC(__i915) (RUNTIME_INFO(__i915)->has_dsc) - #define INTEL_DISPLAY_STEP(__i915) (RUNTIME_INFO(__i915)->step.display_step) #define INTEL_GRAPHICS_STEP(__i915) (RUNTIME_INFO(__i915)->step.graphics_step) #define INTEL_MEDIA_STEP(__i915) (RUNTIME_INFO(__i915)->step.media_step) @@ -883,6 +844,9 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define HAS_RPS(dev_priv) (INTEL_INFO(dev_priv)->has_rps) #define HAS_DMC(dev_priv) (RUNTIME_INFO(dev_priv)->has_dmc) +#define HAS_DSB(dev_priv) (INTEL_INFO(dev_priv)->display.has_dsb) +#define HAS_DSC(__i915) (RUNTIME_INFO(__i915)->has_dsc) +#define HAS_HW_SAGV_WM(i915) (DISPLAY_VER(i915) >= 13 && !IS_DGFX(i915)) #define HAS_HECI_PXP(dev_priv) \ (INTEL_INFO(dev_priv)->has_heci_pxp) @@ -940,9 +904,6 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define NUM_L3_SLICES(dev_priv) (IS_HSW_GT3(dev_priv) ? \ 2 : HAS_L3_DPF(dev_priv)) -#define GT_FREQUENCY_MULTIPLIER 50 -#define GEN9_FREQ_SCALER 3 - #define INTEL_NUM_PIPES(dev_priv) (hweight8(RUNTIME_INFO(dev_priv)->pipe_mask)) #define HAS_DISPLAY(dev_priv) (RUNTIME_INFO(dev_priv)->pipe_mask != 0) diff --git a/drivers/gpu/drm/i915/i915_gem.h b/drivers/gpu/drm/i915/i915_gem.h index a5cdf6662d01..82e9d289398c 100644 --- a/drivers/gpu/drm/i915/i915_gem.h +++ b/drivers/gpu/drm/i915/i915_gem.h @@ -39,6 +39,13 @@ struct i915_gem_ww_ctx; struct i915_gtt_view; struct i915_vma; +#define I915_GEM_GPU_DOMAINS \ + (I915_GEM_DOMAIN_RENDER | \ + I915_GEM_DOMAIN_SAMPLER | \ + I915_GEM_DOMAIN_COMMAND | \ + I915_GEM_DOMAIN_INSTRUCTION | \ + I915_GEM_DOMAIN_VERTEX) + void i915_gem_init_early(struct drm_i915_private *i915); void i915_gem_cleanup_early(struct drm_i915_private *i915); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 243419783052..3d77679bf211 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -18,6 +18,8 @@ struct drm_i915_gem_object; struct i915_address_space; struct i915_gem_ww_ctx; +#define I915_COLOR_UNEVICTABLE (-1) /* a non-vma sharing the address space */ + int __must_check i915_gem_gtt_prepare_pages(struct drm_i915_gem_object *obj, struct sg_table *pages); void i915_gem_gtt_finish_pages(struct drm_i915_gem_object *obj, diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 54ea28cf8a1a..240d5e198904 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -614,414 +614,6 @@ static void i915_enable_asle_pipestat(struct drm_i915_private *dev_priv) spin_unlock_irq(&dev_priv->irq_lock); } -/* - * This timing diagram depicts the video signal in and - * around the vertical blanking period. - * - * Assumptions about the fictitious mode used in this example: - * vblank_start >= 3 - * vsync_start = vblank_start + 1 - * vsync_end = vblank_start + 2 - * vtotal = vblank_start + 3 - * - * start of vblank: - * latch double buffered registers - * increment frame counter (ctg+) - * generate start of vblank interrupt (gen4+) - * | - * | frame start: - * | generate frame start interrupt (aka. vblank interrupt) (gmch) - * | may be shifted forward 1-3 extra lines via PIPECONF - * | | - * | | start of vsync: - * | | generate vsync interrupt - * | | | - * ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx - * . \hs/ . \hs/ \hs/ \hs/ . \hs/ - * ----va---> <-----------------vb--------------------> <--------va------------- - * | | <----vs-----> | - * -vbs-----> <---vbs+1---> <---vbs+2---> <-----0-----> <-----1-----> <-----2--- (scanline counter gen2) - * -vbs-2---> <---vbs-1---> <---vbs-----> <---vbs+1---> <---vbs+2---> <-----0--- (scanline counter gen3+) - * -vbs-2---> <---vbs-2---> <---vbs-1---> <---vbs-----> <---vbs+1---> <---vbs+2- (scanline counter hsw+ hdmi) - * | | | - * last visible pixel first visible pixel - * | increment frame counter (gen3/4) - * pixel counter = vblank_start * htotal pixel counter = 0 (gen3/4) - * - * x = horizontal active - * _ = horizontal blanking - * hs = horizontal sync - * va = vertical active - * vb = vertical blanking - * vs = vertical sync - * vbs = vblank_start (number) - * - * Summary: - * - most events happen at the start of horizontal sync - * - frame start happens at the start of horizontal blank, 1-4 lines - * (depending on PIPECONF settings) after the start of vblank - * - gen3/4 pixel and frame counter are synchronized with the start - * of horizontal active on the first line of vertical active - */ - -/* Called from drm generic code, passed a 'crtc', which - * we use as a pipe index - */ -u32 i915_get_vblank_counter(struct drm_crtc *crtc) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->dev); - struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[drm_crtc_index(crtc)]; - const struct drm_display_mode *mode = &vblank->hwmode; - enum pipe pipe = to_intel_crtc(crtc)->pipe; - i915_reg_t high_frame, low_frame; - u32 high1, high2, low, pixel, vbl_start, hsync_start, htotal; - unsigned long irqflags; - - /* - * On i965gm TV output the frame counter only works up to - * the point when we enable the TV encoder. After that the - * frame counter ceases to work and reads zero. We need a - * vblank wait before enabling the TV encoder and so we - * have to enable vblank interrupts while the frame counter - * is still in a working state. However the core vblank code - * does not like us returning non-zero frame counter values - * when we've told it that we don't have a working frame - * counter. Thus we must stop non-zero values leaking out. - */ - if (!vblank->max_vblank_count) - return 0; - - htotal = mode->crtc_htotal; - hsync_start = mode->crtc_hsync_start; - vbl_start = mode->crtc_vblank_start; - if (mode->flags & DRM_MODE_FLAG_INTERLACE) - vbl_start = DIV_ROUND_UP(vbl_start, 2); - - /* Convert to pixel count */ - vbl_start *= htotal; - - /* Start of vblank event occurs at start of hsync */ - vbl_start -= htotal - hsync_start; - - high_frame = PIPEFRAME(pipe); - low_frame = PIPEFRAMEPIXEL(pipe); - - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - - /* - * High & low register fields aren't synchronized, so make sure - * we get a low value that's stable across two reads of the high - * register. - */ - do { - high1 = intel_de_read_fw(dev_priv, high_frame) & PIPE_FRAME_HIGH_MASK; - low = intel_de_read_fw(dev_priv, low_frame); - high2 = intel_de_read_fw(dev_priv, high_frame) & PIPE_FRAME_HIGH_MASK; - } while (high1 != high2); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); - - high1 >>= PIPE_FRAME_HIGH_SHIFT; - pixel = low & PIPE_PIXEL_MASK; - low >>= PIPE_FRAME_LOW_SHIFT; - - /* - * The frame counter increments at beginning of active. - * Cook up a vblank counter by also checking the pixel - * counter against vblank start. - */ - return (((high1 << 8) | low) + (pixel >= vbl_start)) & 0xffffff; -} - -u32 g4x_get_vblank_counter(struct drm_crtc *crtc) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->dev); - struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[drm_crtc_index(crtc)]; - enum pipe pipe = to_intel_crtc(crtc)->pipe; - - if (!vblank->max_vblank_count) - return 0; - - return intel_uncore_read(&dev_priv->uncore, PIPE_FRMCOUNT_G4X(pipe)); -} - -static u32 intel_crtc_scanlines_since_frame_timestamp(struct intel_crtc *crtc) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct drm_vblank_crtc *vblank = - &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; - const struct drm_display_mode *mode = &vblank->hwmode; - u32 htotal = mode->crtc_htotal; - u32 clock = mode->crtc_clock; - u32 scan_prev_time, scan_curr_time, scan_post_time; - - /* - * To avoid the race condition where we might cross into the - * next vblank just between the PIPE_FRMTMSTMP and TIMESTAMP_CTR - * reads. We make sure we read PIPE_FRMTMSTMP and TIMESTAMP_CTR - * during the same frame. - */ - do { - /* - * This field provides read back of the display - * pipe frame time stamp. The time stamp value - * is sampled at every start of vertical blank. - */ - scan_prev_time = intel_de_read_fw(dev_priv, - PIPE_FRMTMSTMP(crtc->pipe)); - - /* - * The TIMESTAMP_CTR register has the current - * time stamp value. - */ - scan_curr_time = intel_de_read_fw(dev_priv, IVB_TIMESTAMP_CTR); - - scan_post_time = intel_de_read_fw(dev_priv, - PIPE_FRMTMSTMP(crtc->pipe)); - } while (scan_post_time != scan_prev_time); - - return div_u64(mul_u32_u32(scan_curr_time - scan_prev_time, - clock), 1000 * htotal); -} - -/* - * On certain encoders on certain platforms, pipe - * scanline register will not work to get the scanline, - * since the timings are driven from the PORT or issues - * with scanline register updates. - * This function will use Framestamp and current - * timestamp registers to calculate the scanline. - */ -static u32 __intel_get_crtc_scanline_from_timestamp(struct intel_crtc *crtc) -{ - struct drm_vblank_crtc *vblank = - &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; - const struct drm_display_mode *mode = &vblank->hwmode; - u32 vblank_start = mode->crtc_vblank_start; - u32 vtotal = mode->crtc_vtotal; - u32 scanline; - - scanline = intel_crtc_scanlines_since_frame_timestamp(crtc); - scanline = min(scanline, vtotal - 1); - scanline = (scanline + vblank_start) % vtotal; - - return scanline; -} - -/* - * intel_de_read_fw(), only for fast reads of display block, no need for - * forcewake etc. - */ -static int __intel_get_crtc_scanline(struct intel_crtc *crtc) -{ - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); - const struct drm_display_mode *mode; - struct drm_vblank_crtc *vblank; - enum pipe pipe = crtc->pipe; - int position, vtotal; - - if (!crtc->active) - return 0; - - vblank = &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; - mode = &vblank->hwmode; - - if (crtc->mode_flags & I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP) - return __intel_get_crtc_scanline_from_timestamp(crtc); - - vtotal = mode->crtc_vtotal; - if (mode->flags & DRM_MODE_FLAG_INTERLACE) - vtotal /= 2; - - position = intel_de_read_fw(dev_priv, PIPEDSL(pipe)) & PIPEDSL_LINE_MASK; - - /* - * On HSW, the DSL reg (0x70000) appears to return 0 if we - * read it just before the start of vblank. So try it again - * so we don't accidentally end up spanning a vblank frame - * increment, causing the pipe_update_end() code to squak at us. - * - * The nature of this problem means we can't simply check the ISR - * bit and return the vblank start value; nor can we use the scanline - * debug register in the transcoder as it appears to have the same - * problem. We may need to extend this to include other platforms, - * but so far testing only shows the problem on HSW. - */ - if (HAS_DDI(dev_priv) && !position) { - int i, temp; - - for (i = 0; i < 100; i++) { - udelay(1); - temp = intel_de_read_fw(dev_priv, PIPEDSL(pipe)) & PIPEDSL_LINE_MASK; - if (temp != position) { - position = temp; - break; - } - } - } - - /* - * See update_scanline_offset() for the details on the - * scanline_offset adjustment. - */ - return (position + crtc->scanline_offset) % vtotal; -} - -static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc, - bool in_vblank_irq, - int *vpos, int *hpos, - ktime_t *stime, ktime_t *etime, - const struct drm_display_mode *mode) -{ - struct drm_device *dev = _crtc->dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *crtc = to_intel_crtc(_crtc); - enum pipe pipe = crtc->pipe; - int position; - int vbl_start, vbl_end, hsync_start, htotal, vtotal; - unsigned long irqflags; - bool use_scanline_counter = DISPLAY_VER(dev_priv) >= 5 || - IS_G4X(dev_priv) || DISPLAY_VER(dev_priv) == 2 || - crtc->mode_flags & I915_MODE_FLAG_USE_SCANLINE_COUNTER; - - if (drm_WARN_ON(&dev_priv->drm, !mode->crtc_clock)) { - drm_dbg(&dev_priv->drm, - "trying to get scanoutpos for disabled " - "pipe %c\n", pipe_name(pipe)); - return false; - } - - htotal = mode->crtc_htotal; - hsync_start = mode->crtc_hsync_start; - vtotal = mode->crtc_vtotal; - vbl_start = mode->crtc_vblank_start; - vbl_end = mode->crtc_vblank_end; - - if (mode->flags & DRM_MODE_FLAG_INTERLACE) { - vbl_start = DIV_ROUND_UP(vbl_start, 2); - vbl_end /= 2; - vtotal /= 2; - } - - /* - * Lock uncore.lock, as we will do multiple timing critical raw - * register reads, potentially with preemption disabled, so the - * following code must not block on uncore.lock. - */ - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - - /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ - - /* Get optional system timestamp before query. */ - if (stime) - *stime = ktime_get(); - - if (crtc->mode_flags & I915_MODE_FLAG_VRR) { - int scanlines = intel_crtc_scanlines_since_frame_timestamp(crtc); - - position = __intel_get_crtc_scanline(crtc); - - /* - * Already exiting vblank? If so, shift our position - * so it looks like we're already apporaching the full - * vblank end. This should make the generated timestamp - * more or less match when the active portion will start. - */ - if (position >= vbl_start && scanlines < position) - position = min(crtc->vmax_vblank_start + scanlines, vtotal - 1); - } else if (use_scanline_counter) { - /* No obvious pixelcount register. Only query vertical - * scanout position from Display scan line register. - */ - position = __intel_get_crtc_scanline(crtc); - } else { - /* Have access to pixelcount since start of frame. - * We can split this into vertical and horizontal - * scanout position. - */ - position = (intel_de_read_fw(dev_priv, PIPEFRAMEPIXEL(pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT; - - /* convert to pixel counts */ - vbl_start *= htotal; - vbl_end *= htotal; - vtotal *= htotal; - - /* - * In interlaced modes, the pixel counter counts all pixels, - * so one field will have htotal more pixels. In order to avoid - * the reported position from jumping backwards when the pixel - * counter is beyond the length of the shorter field, just - * clamp the position the length of the shorter field. This - * matches how the scanline counter based position works since - * the scanline counter doesn't count the two half lines. - */ - if (position >= vtotal) - position = vtotal - 1; - - /* - * Start of vblank interrupt is triggered at start of hsync, - * just prior to the first active line of vblank. However we - * consider lines to start at the leading edge of horizontal - * active. So, should we get here before we've crossed into - * the horizontal active of the first line in vblank, we would - * not set the DRM_SCANOUTPOS_INVBL flag. In order to fix that, - * always add htotal-hsync_start to the current pixel position. - */ - position = (position + htotal - hsync_start) % vtotal; - } - - /* Get optional system timestamp after query. */ - if (etime) - *etime = ktime_get(); - - /* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */ - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); - - /* - * While in vblank, position will be negative - * counting up towards 0 at vbl_end. And outside - * vblank, position will be positive counting - * up since vbl_end. - */ - if (position >= vbl_start) - position -= vbl_end; - else - position += vtotal - vbl_end; - - if (use_scanline_counter) { - *vpos = position; - *hpos = 0; - } else { - *vpos = position / htotal; - *hpos = position - (*vpos * htotal); - } - - return true; -} - -bool intel_crtc_get_vblank_timestamp(struct drm_crtc *crtc, int *max_error, - ktime_t *vblank_time, bool in_vblank_irq) -{ - return drm_crtc_vblank_helper_get_vblank_timestamp_internal( - crtc, max_error, vblank_time, in_vblank_irq, - i915_get_crtc_scanoutpos); -} - -int intel_get_crtc_scanline(struct intel_crtc *crtc) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - unsigned long irqflags; - int position; - - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - position = __intel_get_crtc_scanline(crtc); - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); - - return position; -} - /** * ivb_parity_work - Workqueue called when a parity error interrupt * occurred. diff --git a/drivers/gpu/drm/i915/i915_irq.h b/drivers/gpu/drm/i915/i915_irq.h index 9b004fc3444e..03ee4c8b1ed3 100644 --- a/drivers/gpu/drm/i915/i915_irq.h +++ b/drivers/gpu/drm/i915/i915_irq.h @@ -66,18 +66,12 @@ bool intel_irqs_enabled(struct drm_i915_private *dev_priv); void intel_synchronize_irq(struct drm_i915_private *i915); void intel_synchronize_hardirq(struct drm_i915_private *i915); -int intel_get_crtc_scanline(struct intel_crtc *crtc); void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, u8 pipe_mask); void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv, u8 pipe_mask); u32 gen8_de_pipe_underrun_mask(struct drm_i915_private *dev_priv); -bool intel_crtc_get_vblank_timestamp(struct drm_crtc *crtc, int *max_error, - ktime_t *vblank_time, bool in_vblank_irq); - -u32 i915_get_vblank_counter(struct drm_crtc *crtc); -u32 g4x_get_vblank_counter(struct drm_crtc *crtc); int i8xx_enable_vblank(struct drm_crtc *crtc); int i915gm_enable_vblank(struct drm_crtc *crtc); diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index d634bd3f641a..ade744cccfea 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -222,27 +222,44 @@ i915_param_named_unsafe(lmem_size, uint, 0400, i915_param_named_unsafe(lmem_bar_size, uint, 0400, "Set the lmem bar size(in MiB)."); -static __always_inline void _print_param(struct drm_printer *p, - const char *name, - const char *type, - const void *x) +static void _param_print_bool(struct drm_printer *p, const char *name, + bool val) { - if (!__builtin_strcmp(type, "bool")) - drm_printf(p, "i915.%s=%s\n", name, - str_yes_no(*(const bool *)x)); - else if (!__builtin_strcmp(type, "int")) - drm_printf(p, "i915.%s=%d\n", name, *(const int *)x); - else if (!__builtin_strcmp(type, "unsigned int")) - drm_printf(p, "i915.%s=%u\n", name, *(const unsigned int *)x); - else if (!__builtin_strcmp(type, "unsigned long")) - drm_printf(p, "i915.%s=%lu\n", name, *(const unsigned long *)x); - else if (!__builtin_strcmp(type, "char *")) - drm_printf(p, "i915.%s=%s\n", name, *(const char **)x); - else - WARN_ONCE(1, "no printer defined for param type %s (i915.%s)\n", - type, name); + drm_printf(p, "i915.%s=%s\n", name, str_yes_no(val)); } +static void _param_print_int(struct drm_printer *p, const char *name, + int val) +{ + drm_printf(p, "i915.%s=%d\n", name, val); +} + +static void _param_print_uint(struct drm_printer *p, const char *name, + unsigned int val) +{ + drm_printf(p, "i915.%s=%u\n", name, val); +} + +static void _param_print_ulong(struct drm_printer *p, const char *name, + unsigned long val) +{ + drm_printf(p, "i915.%s=%lu\n", name, val); +} + +static void _param_print_charp(struct drm_printer *p, const char *name, + const char *val) +{ + drm_printf(p, "i915.%s=%s\n", name, val); +} + +#define _param_print(p, name, val) \ + _Generic(val, \ + bool: _param_print_bool, \ + int: _param_print_int, \ + unsigned int: _param_print_uint, \ + unsigned long: _param_print_ulong, \ + char *: _param_print_charp)(p, name, val) + /** * i915_params_dump - dump i915 modparams * @params: i915 modparams @@ -252,37 +269,48 @@ static __always_inline void _print_param(struct drm_printer *p, */ void i915_params_dump(const struct i915_params *params, struct drm_printer *p) { -#define PRINT(T, x, ...) _print_param(p, #x, #T, ¶ms->x); +#define PRINT(T, x, ...) _param_print(p, #x, params->x); I915_PARAMS_FOR_EACH(PRINT); #undef PRINT } -static __always_inline void dup_param(const char *type, void *x) +static void _param_dup_charp(char **valp) { - if (!__builtin_strcmp(type, "char *")) - *(void **)x = kstrdup(*(void **)x, GFP_ATOMIC); + *valp = kstrdup(*valp, GFP_ATOMIC); } +static void _param_nop(void *valp) +{ +} + +#define _param_dup(valp) \ + _Generic(valp, \ + char **: _param_dup_charp, \ + default: _param_nop)(valp) + void i915_params_copy(struct i915_params *dest, const struct i915_params *src) { *dest = *src; -#define DUP(T, x, ...) dup_param(#T, &dest->x); +#define DUP(T, x, ...) _param_dup(&dest->x); I915_PARAMS_FOR_EACH(DUP); #undef DUP } -static __always_inline void free_param(const char *type, void *x) +static void _param_free_charp(char **valp) { - if (!__builtin_strcmp(type, "char *")) { - kfree(*(void **)x); - *(void **)x = NULL; - } + kfree(*valp); + *valp = NULL; } +#define _param_free(valp) \ + _Generic(valp, \ + char **: _param_free_charp, \ + default: _param_nop)(valp) + /* free the allocated members, *not* the passed in params itself */ void i915_params_free(struct i915_params *params) { -#define FREE(T, x, ...) free_param(#T, ¶ms->x); +#define FREE(T, x, ...) _param_free(¶ms->x); I915_PARAMS_FOR_EACH(FREE); #undef FREE } diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 6b4a66734e09..a8d942b16223 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -26,6 +26,7 @@ #include <drm/drm_drv.h> #include <drm/i915_pciids.h> +#include "display/intel_display.h" #include "gt/intel_gt_regs.h" #include "gt/intel_sa_media.h" diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 8b2cf980f323..bad36a67d873 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5737,6 +5737,7 @@ #define RESET_PCH_HANDSHAKE_ENABLE REG_BIT(4) #define GEN8_CHICKEN_DCPR_1 _MMIO(0x46430) +#define LATENCY_REPORTING_REMOVED_PIPE_D REG_BIT(31) #define SKL_SELECT_ALTERNATE_DC_EXIT REG_BIT(30) #define LATENCY_REPORTING_REMOVED_PIPE_C REG_BIT(25) #define LATENCY_REPORTING_REMOVED_PIPE_B REG_BIT(24) @@ -8105,7 +8106,7 @@ enum skl_power_gate { #define DSB_TAIL(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x4) #define DSB_CTRL(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x8) #define DSB_ENABLE (1 << 31) -#define DSB_STATUS (1 << 0) +#define DSB_STATUS_BUSY (1 << 0) #define CLKREQ_POLICY _MMIO(0x101038) #define CLKREQ_POLICY_MEM_UP_OVRD REG_BIT(1) diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index f949a9495758..7503dcb9043b 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -43,6 +43,7 @@ #include "gt/intel_rps.h" #include "i915_active.h" +#include "i915_config.h" #include "i915_deps.h" #include "i915_driver.h" #include "i915_drv.h" diff --git a/drivers/gpu/drm/i915/i915_switcheroo.c b/drivers/gpu/drm/i915/i915_switcheroo.c index 23777d500cdf..f45bd6b6cede 100644 --- a/drivers/gpu/drm/i915/i915_switcheroo.c +++ b/drivers/gpu/drm/i915/i915_switcheroo.c @@ -19,6 +19,10 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, dev_err(&pdev->dev, "DRM not initialized, aborting switch.\n"); return; } + if (!HAS_DISPLAY(i915)) { + dev_err(&pdev->dev, "Device state not initialized, aborting switch.\n"); + return; + } if (state == VGA_SWITCHEROO_ON) { drm_info(&i915->drm, "switched on\n"); @@ -44,7 +48,7 @@ static bool i915_switcheroo_can_switch(struct pci_dev *pdev) * locking inversion with the driver load path. And the access here is * completely racy anyway. So don't bother with locking for now. */ - return i915 && atomic_read(&i915->drm.open_count) == 0; + return i915 && HAS_DISPLAY(i915) && atomic_read(&i915->drm.open_count) == 0; } static const struct vga_switcheroo_client_ops i915_switcheroo_ops = { diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 5272e2be990e..f51fd9fd4c89 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -26,6 +26,7 @@ #include <linux/dma-fence-array.h> #include <drm/drm_gem.h> +#include "display/intel_display.h" #include "display/intel_frontbuffer.h" #include "gem/i915_gem_lmem.h" #include "gem/i915_gem_tiling.h" diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index 05e90d09b208..98769e5f2c3d 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -29,6 +29,7 @@ #include "display/intel_cdclk.h" #include "display/intel_de.h" +#include "display/intel_display.h" #include "gt/intel_gt_regs.h" #include "i915_drv.h" #include "i915_reg.h" diff --git a/drivers/gpu/drm/i915/intel_device_info.h b/drivers/gpu/drm/i915/intel_device_info.h index d588e5fd2eea..80bda653d61b 100644 --- a/drivers/gpu/drm/i915/intel_device_info.h +++ b/drivers/gpu/drm/i915/intel_device_info.h @@ -29,7 +29,7 @@ #include "intel_step.h" -#include "display/intel_display.h" +#include "display/intel_display_limits.h" #include "gt/intel_engine_types.h" #include "gt/intel_context_types.h" diff --git a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c index ce6b3c3b636a..1f4805aa2b08 100644 --- a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c +++ b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c @@ -5,6 +5,7 @@ #include "display/intel_audio_regs.h" #include "display/intel_backlight_regs.h" +#include "display/intel_display_types.h" #include "display/intel_dmc_regs.h" #include "display/intel_dpio_phy.h" #include "display/vlv_dsi_pll_regs.h" diff --git a/drivers/gpu/drm/i915/intel_memory_region.c b/drivers/gpu/drm/i915/intel_memory_region.c index b9a164efd6ae..3d1fdea9811d 100644 --- a/drivers/gpu/drm/i915/intel_memory_region.c +++ b/drivers/gpu/drm/i915/intel_memory_region.c @@ -235,7 +235,7 @@ intel_memory_region_create(struct drm_i915_private *i915, return ERR_PTR(-ENOMEM); mem->i915 = i915; - mem->region = (struct resource)DEFINE_RES_MEM(start, size); + mem->region = DEFINE_RES_MEM(start, size); mem->io_start = io_start; mem->io_size = io_size; mem->min_page_size = min_page_size; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 73c88b1c9545..3fc65bd12cc1 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -26,6 +26,7 @@ */ #include "display/intel_de.h" +#include "display/intel_display.h" #include "display/intel_display_trace.h" #include "display/skl_watermark.h" diff --git a/drivers/gpu/drm/i915/intel_pm_types.h b/drivers/gpu/drm/i915/intel_pm_types.h index 211632f58751..93152537b420 100644 --- a/drivers/gpu/drm/i915/intel_pm_types.h +++ b/drivers/gpu/drm/i915/intel_pm_types.h @@ -8,7 +8,7 @@ #include <linux/types.h> -#include "display/intel_display.h" +#include "display/intel_display_limits.h" enum intel_ddb_partitioning { INTEL_DDB_PART_1_2, diff --git a/drivers/gpu/drm/i915/selftests/i915_gem.c b/drivers/gpu/drm/i915/selftests/i915_gem.c index 2535b9684bd1..d91d0ade8abd 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem.c @@ -44,7 +44,7 @@ static void trash_stolen(struct drm_i915_private *i915) { struct i915_ggtt *ggtt = to_gt(i915)->ggtt; const u64 slot = ggtt->error_capture.start; - const resource_size_t size = resource_size(&i915->dsm); + const resource_size_t size = resource_size(&i915->dsm.stolen); unsigned long page; u32 prng = 0x12345678; @@ -53,7 +53,7 @@ static void trash_stolen(struct drm_i915_private *i915) return; for (page = 0; page < size; page += PAGE_SIZE) { - const dma_addr_t dma = i915->dsm.start + page; + const dma_addr_t dma = i915->dsm.stolen.start + page; u32 __iomem *s; int x; diff --git a/drivers/gpu/drm/i915/selftests/intel_scheduler_helpers.c b/drivers/gpu/drm/i915/selftests/intel_scheduler_helpers.c index 310fb83c527e..2990dd4d4a0d 100644 --- a/drivers/gpu/drm/i915/selftests/intel_scheduler_helpers.c +++ b/drivers/gpu/drm/i915/selftests/intel_scheduler_helpers.c @@ -28,8 +28,7 @@ struct intel_engine_cs *intel_selftest_find_any_engine(struct intel_gt *gt) int intel_selftest_modify_policy(struct intel_engine_cs *engine, struct intel_selftest_saved_policy *saved, - u32 modify_type) - + enum selftest_scheduler_modify modify_type) { int err; diff --git a/drivers/gpu/drm/i915/selftests/mock_gtt.c b/drivers/gpu/drm/i915/selftests/mock_gtt.c index 568840e7ca66..ece97e4faacb 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gtt.c +++ b/drivers/gpu/drm/i915/selftests/mock_gtt.c @@ -112,7 +112,7 @@ void mock_init_ggtt(struct intel_gt *gt) ggtt->vm.i915 = gt->i915; ggtt->vm.is_ggtt = true; - ggtt->gmadr = (struct resource) DEFINE_RES_MEM(0, 2048 * PAGE_SIZE); + ggtt->gmadr = DEFINE_RES_MEM(0, 2048 * PAGE_SIZE); ggtt->mappable_end = resource_size(&ggtt->gmadr); ggtt->vm.total = 4096 * PAGE_SIZE; diff --git a/drivers/gpu/drm/i915/soc/intel_gmch.c b/drivers/gpu/drm/i915/soc/intel_gmch.c new file mode 100644 index 000000000000..6d0204942f7a --- /dev/null +++ b/drivers/gpu/drm/i915/soc/intel_gmch.c @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2023 Intel Corporation + */ + +#include <linux/pci.h> +#include <linux/pnp.h> + +#include <drm/drm_managed.h> +#include <drm/i915_drm.h> + +#include "i915_drv.h" +#include "intel_gmch.h" +#include "intel_pci_config.h" + +static void intel_gmch_bridge_release(struct drm_device *dev, void *bridge) +{ + pci_dev_put(bridge); +} + +int intel_gmch_bridge_setup(struct drm_i915_private *i915) +{ + int domain = pci_domain_nr(to_pci_dev(i915->drm.dev)->bus); + + i915->gmch.pdev = pci_get_domain_bus_and_slot(domain, 0, PCI_DEVFN(0, 0)); + if (!i915->gmch.pdev) { + drm_err(&i915->drm, "bridge device not found\n"); + return -EIO; + } + + return drmm_add_action_or_reset(&i915->drm, intel_gmch_bridge_release, + i915->gmch.pdev); +} + +/* Allocate space for the MCH regs if needed, return nonzero on error */ +static int +intel_alloc_mchbar_resource(struct drm_i915_private *i915) +{ + int reg = GRAPHICS_VER(i915) >= 4 ? MCHBAR_I965 : MCHBAR_I915; + u32 temp_lo, temp_hi = 0; + u64 mchbar_addr; + int ret; + + if (GRAPHICS_VER(i915) >= 4) + pci_read_config_dword(i915->gmch.pdev, reg + 4, &temp_hi); + pci_read_config_dword(i915->gmch.pdev, reg, &temp_lo); + mchbar_addr = ((u64)temp_hi << 32) | temp_lo; + + /* If ACPI doesn't have it, assume we need to allocate it ourselves */ +#ifdef CONFIG_PNP + if (mchbar_addr && + pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) + return 0; +#endif + + /* Get some space for it */ + i915->gmch.mch_res.name = "i915 MCHBAR"; + i915->gmch.mch_res.flags = IORESOURCE_MEM; + ret = pci_bus_alloc_resource(i915->gmch.pdev->bus, + &i915->gmch.mch_res, + MCHBAR_SIZE, MCHBAR_SIZE, + PCIBIOS_MIN_MEM, + 0, pcibios_align_resource, + i915->gmch.pdev); + if (ret) { + drm_dbg(&i915->drm, "failed bus alloc: %d\n", ret); + i915->gmch.mch_res.start = 0; + return ret; + } + + if (GRAPHICS_VER(i915) >= 4) + pci_write_config_dword(i915->gmch.pdev, reg + 4, + upper_32_bits(i915->gmch.mch_res.start)); + + pci_write_config_dword(i915->gmch.pdev, reg, + lower_32_bits(i915->gmch.mch_res.start)); + return 0; +} + +/* Setup MCHBAR if possible, return true if we should disable it again */ +void intel_gmch_bar_setup(struct drm_i915_private *i915) +{ + int mchbar_reg = GRAPHICS_VER(i915) >= 4 ? MCHBAR_I965 : MCHBAR_I915; + u32 temp; + bool enabled; + + if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) + return; + + i915->gmch.mchbar_need_disable = false; + + if (IS_I915G(i915) || IS_I915GM(i915)) { + pci_read_config_dword(i915->gmch.pdev, DEVEN, &temp); + enabled = !!(temp & DEVEN_MCHBAR_EN); + } else { + pci_read_config_dword(i915->gmch.pdev, mchbar_reg, &temp); + enabled = temp & 1; + } + + /* If it's already enabled, don't have to do anything */ + if (enabled) + return; + + if (intel_alloc_mchbar_resource(i915)) + return; + + i915->gmch.mchbar_need_disable = true; + + /* Space is allocated or reserved, so enable it. */ + if (IS_I915G(i915) || IS_I915GM(i915)) { + pci_write_config_dword(i915->gmch.pdev, DEVEN, + temp | DEVEN_MCHBAR_EN); + } else { + pci_read_config_dword(i915->gmch.pdev, mchbar_reg, &temp); + pci_write_config_dword(i915->gmch.pdev, mchbar_reg, temp | 1); + } +} + +void intel_gmch_bar_teardown(struct drm_i915_private *i915) +{ + int mchbar_reg = GRAPHICS_VER(i915) >= 4 ? MCHBAR_I965 : MCHBAR_I915; + + if (i915->gmch.mchbar_need_disable) { + if (IS_I915G(i915) || IS_I915GM(i915)) { + u32 deven_val; + + pci_read_config_dword(i915->gmch.pdev, DEVEN, + &deven_val); + deven_val &= ~DEVEN_MCHBAR_EN; + pci_write_config_dword(i915->gmch.pdev, DEVEN, + deven_val); + } else { + u32 mchbar_val; + + pci_read_config_dword(i915->gmch.pdev, mchbar_reg, + &mchbar_val); + mchbar_val &= ~1; + pci_write_config_dword(i915->gmch.pdev, mchbar_reg, + mchbar_val); + } + } + + if (i915->gmch.mch_res.start) + release_resource(&i915->gmch.mch_res); +} + +int intel_gmch_vga_set_state(struct drm_i915_private *i915, bool enable_decode) +{ + unsigned int reg = DISPLAY_VER(i915) >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL; + u16 gmch_ctrl; + + if (pci_read_config_word(i915->gmch.pdev, reg, &gmch_ctrl)) { + drm_err(&i915->drm, "failed to read control word\n"); + return -EIO; + } + + if (!!(gmch_ctrl & INTEL_GMCH_VGA_DISABLE) == !enable_decode) + return 0; + + if (enable_decode) + gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE; + else + gmch_ctrl |= INTEL_GMCH_VGA_DISABLE; + + if (pci_write_config_word(i915->gmch.pdev, reg, gmch_ctrl)) { + drm_err(&i915->drm, "failed to write control word\n"); + return -EIO; + } + + return 0; +} diff --git a/drivers/gpu/drm/i915/soc/intel_gmch.h b/drivers/gpu/drm/i915/soc/intel_gmch.h new file mode 100644 index 000000000000..d0133eedc720 --- /dev/null +++ b/drivers/gpu/drm/i915/soc/intel_gmch.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 Intel Corporation + */ + +#ifndef __INTEL_GMCH_H__ +#define __INTEL_GMCH_H__ + +#include <linux/types.h> + +struct drm_i915_private; + +int intel_gmch_bridge_setup(struct drm_i915_private *i915); +void intel_gmch_bar_setup(struct drm_i915_private *i915); +void intel_gmch_bar_teardown(struct drm_i915_private *i915); +int intel_gmch_vga_set_state(struct drm_i915_private *i915, bool enable_decode); + +#endif /* __INTEL_GMCH_H__ */ diff --git a/drivers/gpu/drm/i915/vlv_sideband.c b/drivers/gpu/drm/i915/vlv_sideband.c index 6eea6e1a99c0..b98dec3ad817 100644 --- a/drivers/gpu/drm/i915/vlv_sideband.c +++ b/drivers/gpu/drm/i915/vlv_sideband.c @@ -9,6 +9,7 @@ #include "vlv_sideband.h" #include "display/intel_dpio_phy.h" +#include "display/intel_display_types.h" /* * IOSF sideband, see VLV2_SidebandMsg_HAS.docx and diff --git a/drivers/gpu/drm/meson/meson_viu.c b/drivers/gpu/drm/meson/meson_viu.c index d4b907889a21..cd399b0b7181 100644 --- a/drivers/gpu/drm/meson/meson_viu.c +++ b/drivers/gpu/drm/meson/meson_viu.c @@ -436,15 +436,14 @@ void meson_viu_init(struct meson_drm *priv) /* Initialize OSD1 fifo control register */ reg = VIU_OSD_DDR_PRIORITY_URGENT | - VIU_OSD_HOLD_FIFO_LINES(31) | VIU_OSD_FIFO_DEPTH_VAL(32) | /* fifo_depth_val: 32*8=256 */ VIU_OSD_WORDS_PER_BURST(4) | /* 4 words in 1 burst */ VIU_OSD_FIFO_LIMITS(2); /* fifo_lim: 2*16=32 */ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) - reg |= VIU_OSD_BURST_LENGTH_32; + reg |= (VIU_OSD_BURST_LENGTH_32 | VIU_OSD_HOLD_FIFO_LINES(31)); else - reg |= VIU_OSD_BURST_LENGTH_64; + reg |= (VIU_OSD_BURST_LENGTH_64 | VIU_OSD_HOLD_FIFO_LINES(4)); writel_relaxed(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT)); writel_relaxed(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT)); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index 6484b97c5344..f3c9600221d4 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -876,7 +876,8 @@ static void a6xx_gmu_rpmh_off(struct a6xx_gmu *gmu) #define GBIF_CLIENT_HALT_MASK BIT(0) #define GBIF_ARB_HALT_MASK BIT(1) -static void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu) +static void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu, + bool gx_off) { struct msm_gpu *gpu = &adreno_gpu->base; @@ -889,9 +890,11 @@ static void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu) return; } - /* Halt the gx side of GBIF */ - gpu_write(gpu, REG_A6XX_RBBM_GBIF_HALT, 1); - spin_until(gpu_read(gpu, REG_A6XX_RBBM_GBIF_HALT_ACK) & 1); + if (gx_off) { + /* Halt the gx side of GBIF */ + gpu_write(gpu, REG_A6XX_RBBM_GBIF_HALT, 1); + spin_until(gpu_read(gpu, REG_A6XX_RBBM_GBIF_HALT_ACK) & 1); + } /* Halt new client requests on GBIF */ gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_CLIENT_HALT_MASK); @@ -929,7 +932,7 @@ static void a6xx_gmu_force_off(struct a6xx_gmu *gmu) /* Halt the gmu cm3 core */ gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 1); - a6xx_bus_clear_pending_transactions(adreno_gpu); + a6xx_bus_clear_pending_transactions(adreno_gpu, true); /* Reset GPU core blocks */ gpu_write(gpu, REG_A6XX_RBBM_SW_RESET_CMD, 1); @@ -1083,7 +1086,7 @@ static void a6xx_gmu_shutdown(struct a6xx_gmu *gmu) return; } - a6xx_bus_clear_pending_transactions(adreno_gpu); + a6xx_bus_clear_pending_transactions(adreno_gpu, a6xx_gpu->hung); /* tell the GMU we want to slumber */ ret = a6xx_gmu_notify_slumber(gmu); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 36c8fb699b56..3be0f2928b57 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -1270,6 +1270,12 @@ static void a6xx_recover(struct msm_gpu *gpu) if (hang_debug) a6xx_dump(gpu); + /* + * To handle recovery specific sequences during the rpm suspend we are + * about to trigger + */ + a6xx_gpu->hung = true; + /* Halt SQE first */ gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 3); @@ -1312,6 +1318,7 @@ static void a6xx_recover(struct msm_gpu *gpu) mutex_unlock(&gpu->active_lock); msm_gpu_hw_init(gpu); + a6xx_gpu->hung = false; } static const char *a6xx_uche_fault_block(struct msm_gpu *gpu, u32 mid) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h index ab853f61db63..eea2e60ce3b7 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h @@ -32,6 +32,7 @@ struct a6xx_gpu { void *llc_slice; void *htw_llc_slice; bool have_mmu500; + bool hung; }; #define to_a6xx_gpu(x) container_of(x, struct a6xx_gpu, base) diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c index 628806423f7d..36f062c7582f 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_device.c +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c @@ -551,13 +551,14 @@ static int adreno_bind(struct device *dev, struct device *master, void *data) return 0; } +static int adreno_system_suspend(struct device *dev); static void adreno_unbind(struct device *dev, struct device *master, void *data) { struct msm_drm_private *priv = dev_get_drvdata(master); struct msm_gpu *gpu = dev_to_gpu(dev); - pm_runtime_force_suspend(dev); + WARN_ON_ONCE(adreno_system_suspend(dev)); gpu->funcs->destroy(gpu); priv->gpu_pdev = NULL; @@ -609,7 +610,7 @@ static int adreno_remove(struct platform_device *pdev) static void adreno_shutdown(struct platform_device *pdev) { - pm_runtime_force_suspend(&pdev->dev); + WARN_ON_ONCE(adreno_system_suspend(&pdev->dev)); } static const struct of_device_id dt_match[] = { diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 57586c794b84..3605f095b2de 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -352,6 +352,8 @@ int adreno_set_param(struct msm_gpu *gpu, struct msm_file_private *ctx, /* Ensure string is null terminated: */ str[len] = '\0'; + mutex_lock(&gpu->lock); + if (param == MSM_PARAM_COMM) { paramp = &ctx->comm; } else { @@ -361,6 +363,8 @@ int adreno_set_param(struct msm_gpu *gpu, struct msm_file_private *ctx, kfree(*paramp); *paramp = str; + mutex_unlock(&gpu->lock); + return 0; } case MSM_PARAM_SYSPROF: diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h index 5d4b1c95033f..b4f9b1343d63 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h @@ -29,11 +29,9 @@ enum { ADRENO_FW_MAX, }; -enum adreno_quirks { - ADRENO_QUIRK_TWO_PASS_USE_WFI = 1, - ADRENO_QUIRK_FAULT_DETECT_MASK = 2, - ADRENO_QUIRK_LMLOADKILL_DISABLE = 3, -}; +#define ADRENO_QUIRK_TWO_PASS_USE_WFI BIT(0) +#define ADRENO_QUIRK_FAULT_DETECT_MASK BIT(1) +#define ADRENO_QUIRK_LMLOADKILL_DISABLE BIT(2) struct adreno_rev { uint8_t core; @@ -65,7 +63,7 @@ struct adreno_info { const char *name; const char *fw[ADRENO_FW_MAX]; uint32_t gmem; - enum adreno_quirks quirks; + u64 quirks; struct msm_gpu *(*init)(struct drm_device *dev); const char *zapfw; u32 inactive_period; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c index 7cbcef6efe17..62f6ff6abf41 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c @@ -132,7 +132,6 @@ static void dpu_encoder_phys_wb_set_qos(struct dpu_encoder_phys *phys_enc) * dpu_encoder_phys_wb_setup_fb - setup output framebuffer * @phys_enc: Pointer to physical encoder * @fb: Pointer to output framebuffer - * @wb_roi: Pointer to output region of interest */ static void dpu_encoder_phys_wb_setup_fb(struct dpu_encoder_phys *phys_enc, struct drm_framebuffer *fb) @@ -692,7 +691,7 @@ static void dpu_encoder_phys_wb_init_ops(struct dpu_encoder_phys_ops *ops) /** * dpu_encoder_phys_wb_init - initialize writeback encoder - * @init: Pointer to init info structure with initialization params + * @p: Pointer to init info structure with initialization params */ struct dpu_encoder_phys *dpu_encoder_phys_wb_init( struct dpu_enc_phys_init_params *p) diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c index d030a93a08c3..cc3efed593aa 100644 --- a/drivers/gpu/drm/msm/dp/dp_aux.c +++ b/drivers/gpu/drm/msm/dp/dp_aux.c @@ -423,6 +423,10 @@ void dp_aux_isr(struct drm_dp_aux *dp_aux) isr = dp_catalog_aux_get_irq(aux->catalog); + /* no interrupts pending, return immediately */ + if (!isr) + return; + if (!aux->cmd_busy) return; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index c373a40bef37..f1f01db699d3 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -530,11 +530,19 @@ static int msm_hdmi_dev_probe(struct platform_device *pdev) ret = devm_pm_runtime_enable(&pdev->dev); if (ret) - return ret; + goto err_put_phy; platform_set_drvdata(pdev, hdmi); - return component_add(&pdev->dev, &msm_hdmi_ops); + ret = component_add(&pdev->dev, &msm_hdmi_ops); + if (ret) + goto err_put_phy; + + return 0; + +err_put_phy: + msm_hdmi_put_phy(hdmi); + return ret; } static int msm_hdmi_dev_remove(struct platform_device *pdev) diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 8b0b0ac74a6f..45e81eb148a8 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -1278,7 +1278,7 @@ void msm_drv_shutdown(struct platform_device *pdev) * msm_drm_init, drm_dev->registered is used as an indicator that the * shutdown will be successful. */ - if (drm && drm->registered) + if (drm && drm->registered && priv->kms) drm_atomic_helper_shutdown(drm); } diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 30ed45af76ad..380249500325 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -335,6 +335,8 @@ static void get_comm_cmdline(struct msm_gem_submit *submit, char **comm, char ** struct msm_file_private *ctx = submit->queue->ctx; struct task_struct *task; + WARN_ON(!mutex_is_locked(&submit->gpu->lock)); + /* Note that kstrdup will return NULL if argument is NULL: */ *comm = kstrdup(ctx->comm, GFP_KERNEL); *cmd = kstrdup(ctx->cmdline, GFP_KERNEL); diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index 651786bc55e5..732295e25683 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -376,10 +376,18 @@ struct msm_file_private { */ int sysprof; - /** comm: Overridden task comm, see MSM_PARAM_COMM */ + /** + * comm: Overridden task comm, see MSM_PARAM_COMM + * + * Accessed under msm_gpu::lock + */ char *comm; - /** cmdline: Overridden task cmdline, see MSM_PARAM_CMDLINE */ + /** + * cmdline: Overridden task cmdline, see MSM_PARAM_CMDLINE + * + * Accessed under msm_gpu::lock + */ char *cmdline; /** diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c index 86b28add1fff..2527afef9c19 100644 --- a/drivers/gpu/drm/msm/msm_mdss.c +++ b/drivers/gpu/drm/msm/msm_mdss.c @@ -47,15 +47,17 @@ struct msm_mdss { static int msm_mdss_parse_data_bus_icc_path(struct device *dev, struct msm_mdss *msm_mdss) { - struct icc_path *path0 = of_icc_get(dev, "mdp0-mem"); - struct icc_path *path1 = of_icc_get(dev, "mdp1-mem"); + struct icc_path *path0; + struct icc_path *path1; + path0 = of_icc_get(dev, "mdp0-mem"); if (IS_ERR_OR_NULL(path0)) return PTR_ERR_OR_ZERO(path0); msm_mdss->path[0] = path0; msm_mdss->num_paths = 1; + path1 = of_icc_get(dev, "mdp1-mem"); if (!IS_ERR_OR_NULL(path1)) { msm_mdss->path[1] = path1; msm_mdss->num_paths++; diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c deleted file mode 100644 index e87de7906f78..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ /dev/null @@ -1,613 +0,0 @@ -/* - * Copyright © 2007 David Airlie - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * David Airlie - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/tty.h> -#include <linux/sysrq.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/screen_info.h> -#include <linux/vga_switcheroo.h> -#include <linux/console.h> - -#include <drm/drm_crtc.h> -#include <drm/drm_crtc_helper.h> -#include <drm/drm_probe_helper.h> -#include <drm/drm_fb_helper.h> -#include <drm/drm_fourcc.h> -#include <drm/drm_atomic.h> - -#include "nouveau_drv.h" -#include "nouveau_gem.h" -#include "nouveau_bo.h" -#include "nouveau_fbcon.h" -#include "nouveau_chan.h" -#include "nouveau_vmm.h" - -#include "nouveau_crtc.h" - -MODULE_PARM_DESC(nofbaccel, "Disable fbcon acceleration"); -int nouveau_nofbaccel = 0; -module_param_named(nofbaccel, nouveau_nofbaccel, int, 0400); - -MODULE_PARM_DESC(fbcon_bpp, "fbcon bits-per-pixel (default: auto)"); -static int nouveau_fbcon_bpp; -module_param_named(fbcon_bpp, nouveau_fbcon_bpp, int, 0400); - -static void -nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) -{ - struct nouveau_fbdev *fbcon = info->par; - struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev); - struct nvif_device *device = &drm->client.device; - int ret; - - if (info->state != FBINFO_STATE_RUNNING) - return; - - ret = -ENODEV; - if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) && - mutex_trylock(&drm->client.mutex)) { - if (device->info.family < NV_DEVICE_INFO_V0_TESLA) - ret = nv04_fbcon_fillrect(info, rect); - else - if (device->info.family < NV_DEVICE_INFO_V0_FERMI) - ret = nv50_fbcon_fillrect(info, rect); - else - ret = nvc0_fbcon_fillrect(info, rect); - mutex_unlock(&drm->client.mutex); - } - - if (ret == 0) - return; - - if (ret != -ENODEV) - nouveau_fbcon_gpu_lockup(info); - drm_fb_helper_cfb_fillrect(info, rect); -} - -static void -nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image) -{ - struct nouveau_fbdev *fbcon = info->par; - struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev); - struct nvif_device *device = &drm->client.device; - int ret; - - if (info->state != FBINFO_STATE_RUNNING) - return; - - ret = -ENODEV; - if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) && - mutex_trylock(&drm->client.mutex)) { - if (device->info.family < NV_DEVICE_INFO_V0_TESLA) - ret = nv04_fbcon_copyarea(info, image); - else - if (device->info.family < NV_DEVICE_INFO_V0_FERMI) - ret = nv50_fbcon_copyarea(info, image); - else - ret = nvc0_fbcon_copyarea(info, image); - mutex_unlock(&drm->client.mutex); - } - - if (ret == 0) - return; - - if (ret != -ENODEV) - nouveau_fbcon_gpu_lockup(info); - drm_fb_helper_cfb_copyarea(info, image); -} - -static void -nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) -{ - struct nouveau_fbdev *fbcon = info->par; - struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev); - struct nvif_device *device = &drm->client.device; - int ret; - - if (info->state != FBINFO_STATE_RUNNING) - return; - - ret = -ENODEV; - if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) && - mutex_trylock(&drm->client.mutex)) { - if (device->info.family < NV_DEVICE_INFO_V0_TESLA) - ret = nv04_fbcon_imageblit(info, image); - else - if (device->info.family < NV_DEVICE_INFO_V0_FERMI) - ret = nv50_fbcon_imageblit(info, image); - else - ret = nvc0_fbcon_imageblit(info, image); - mutex_unlock(&drm->client.mutex); - } - - if (ret == 0) - return; - - if (ret != -ENODEV) - nouveau_fbcon_gpu_lockup(info); - drm_fb_helper_cfb_imageblit(info, image); -} - -static int -nouveau_fbcon_sync(struct fb_info *info) -{ - struct nouveau_fbdev *fbcon = info->par; - struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev); - struct nouveau_channel *chan = drm->channel; - int ret; - - if (!chan || !chan->accel_done || in_interrupt() || - info->state != FBINFO_STATE_RUNNING || - info->flags & FBINFO_HWACCEL_DISABLED) - return 0; - - if (!mutex_trylock(&drm->client.mutex)) - return 0; - - ret = nouveau_channel_idle(chan); - mutex_unlock(&drm->client.mutex); - if (ret) { - nouveau_fbcon_gpu_lockup(info); - return 0; - } - - chan->accel_done = false; - return 0; -} - -static int -nouveau_fbcon_open(struct fb_info *info, int user) -{ - struct nouveau_fbdev *fbcon = info->par; - struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev); - int ret = pm_runtime_get_sync(drm->dev->dev); - if (ret < 0 && ret != -EACCES) { - pm_runtime_put(drm->dev->dev); - return ret; - } - return 0; -} - -static int -nouveau_fbcon_release(struct fb_info *info, int user) -{ - struct nouveau_fbdev *fbcon = info->par; - struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev); - pm_runtime_put(drm->dev->dev); - return 0; -} - -static const struct fb_ops nouveau_fbcon_ops = { - .owner = THIS_MODULE, - DRM_FB_HELPER_DEFAULT_OPS, - .fb_open = nouveau_fbcon_open, - .fb_release = nouveau_fbcon_release, - .fb_fillrect = nouveau_fbcon_fillrect, - .fb_copyarea = nouveau_fbcon_copyarea, - .fb_imageblit = nouveau_fbcon_imageblit, - .fb_sync = nouveau_fbcon_sync, -}; - -static const struct fb_ops nouveau_fbcon_sw_ops = { - .owner = THIS_MODULE, - DRM_FB_HELPER_DEFAULT_OPS, - .fb_open = nouveau_fbcon_open, - .fb_release = nouveau_fbcon_release, - .fb_fillrect = drm_fb_helper_cfb_fillrect, - .fb_copyarea = drm_fb_helper_cfb_copyarea, - .fb_imageblit = drm_fb_helper_cfb_imageblit, -}; - -void -nouveau_fbcon_accel_save_disable(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_drm(dev); - if (drm->fbcon && drm->fbcon->helper.info) { - drm->fbcon->saved_flags = drm->fbcon->helper.info->flags; - drm->fbcon->helper.info->flags |= FBINFO_HWACCEL_DISABLED; - } -} - -void -nouveau_fbcon_accel_restore(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_drm(dev); - if (drm->fbcon && drm->fbcon->helper.info) - drm->fbcon->helper.info->flags = drm->fbcon->saved_flags; -} - -static void -nouveau_fbcon_accel_fini(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_fbdev *fbcon = drm->fbcon; - if (fbcon && drm->channel) { - console_lock(); - if (fbcon->helper.info) - fbcon->helper.info->flags |= FBINFO_HWACCEL_DISABLED; - console_unlock(); - nouveau_channel_idle(drm->channel); - nvif_object_dtor(&fbcon->twod); - nvif_object_dtor(&fbcon->blit); - nvif_object_dtor(&fbcon->gdi); - nvif_object_dtor(&fbcon->patt); - nvif_object_dtor(&fbcon->rop); - nvif_object_dtor(&fbcon->clip); - nvif_object_dtor(&fbcon->surf2d); - } -} - -static void -nouveau_fbcon_accel_init(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_fbdev *fbcon = drm->fbcon; - struct fb_info *info = fbcon->helper.info; - int ret; - - if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA) - ret = nv04_fbcon_accel_init(info); - else - if (drm->client.device.info.family < NV_DEVICE_INFO_V0_FERMI) - ret = nv50_fbcon_accel_init(info); - else - ret = nvc0_fbcon_accel_init(info); - - if (ret == 0) - info->fbops = &nouveau_fbcon_ops; -} - -static void -nouveau_fbcon_zfill(struct drm_device *dev, struct nouveau_fbdev *fbcon) -{ - struct fb_info *info = fbcon->helper.info; - struct fb_fillrect rect; - - /* Clear the entire fbcon. The drm will program every connector - * with it's preferred mode. If the sizes differ, one display will - * quite likely have garbage around the console. - */ - rect.dx = rect.dy = 0; - rect.width = info->var.xres_virtual; - rect.height = info->var.yres_virtual; - rect.color = 0; - rect.rop = ROP_COPY; - info->fbops->fb_fillrect(info, &rect); -} - -static int -nouveau_fbcon_create(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes) -{ - struct nouveau_fbdev *fbcon = - container_of(helper, struct nouveau_fbdev, helper); - struct drm_device *dev = fbcon->helper.dev; - struct nouveau_drm *drm = nouveau_drm(dev); - struct nvif_device *device = &drm->client.device; - struct fb_info *info; - struct drm_framebuffer *fb; - struct nouveau_channel *chan; - struct nouveau_bo *nvbo; - struct drm_mode_fb_cmd2 mode_cmd = {}; - int ret; - - mode_cmd.width = sizes->surface_width; - mode_cmd.height = sizes->surface_height; - - mode_cmd.pitches[0] = mode_cmd.width * (sizes->surface_bpp >> 3); - mode_cmd.pitches[0] = roundup(mode_cmd.pitches[0], 256); - - mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, - sizes->surface_depth); - - ret = nouveau_gem_new(&drm->client, mode_cmd.pitches[0] * - mode_cmd.height, 0, NOUVEAU_GEM_DOMAIN_VRAM, - 0, 0x0000, &nvbo); - if (ret) { - NV_ERROR(drm, "failed to allocate framebuffer\n"); - goto out; - } - - ret = nouveau_framebuffer_new(dev, &mode_cmd, &nvbo->bo.base, &fb); - if (ret) - goto out_unref; - - ret = nouveau_bo_pin(nvbo, NOUVEAU_GEM_DOMAIN_VRAM, false); - if (ret) { - NV_ERROR(drm, "failed to pin fb: %d\n", ret); - goto out_unref; - } - - ret = nouveau_bo_map(nvbo); - if (ret) { - NV_ERROR(drm, "failed to map fb: %d\n", ret); - goto out_unpin; - } - - chan = nouveau_nofbaccel ? NULL : drm->channel; - if (chan && device->info.family >= NV_DEVICE_INFO_V0_TESLA) { - ret = nouveau_vma_new(nvbo, chan->vmm, &fbcon->vma); - if (ret) { - NV_ERROR(drm, "failed to map fb into chan: %d\n", ret); - chan = NULL; - } - } - - info = drm_fb_helper_alloc_info(helper); - if (IS_ERR(info)) { - ret = PTR_ERR(info); - goto out_unlock; - } - - /* setup helper */ - fbcon->helper.fb = fb; - - if (!chan) - info->flags = FBINFO_HWACCEL_DISABLED; - else - info->flags = FBINFO_HWACCEL_COPYAREA | - FBINFO_HWACCEL_FILLRECT | - FBINFO_HWACCEL_IMAGEBLIT; - info->fbops = &nouveau_fbcon_sw_ops; - info->fix.smem_start = nvbo->bo.resource->bus.offset; - info->fix.smem_len = nvbo->bo.base.size; - - info->screen_base = nvbo_kmap_obj_iovirtual(nvbo); - info->screen_size = nvbo->bo.base.size; - - drm_fb_helper_fill_info(info, &fbcon->helper, sizes); - - /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ - - if (chan) - nouveau_fbcon_accel_init(dev); - nouveau_fbcon_zfill(dev, fbcon); - - /* To allow resizeing without swapping buffers */ - NV_INFO(drm, "allocated %dx%d fb: 0x%llx, bo %p\n", - fb->width, fb->height, nvbo->offset, nvbo); - - if (dev_is_pci(dev->dev)) - vga_switcheroo_client_fb_set(to_pci_dev(dev->dev), info); - - return 0; - -out_unlock: - if (chan) - nouveau_vma_del(&fbcon->vma); - nouveau_bo_unmap(nvbo); -out_unpin: - nouveau_bo_unpin(nvbo); -out_unref: - nouveau_bo_ref(NULL, &nvbo); -out: - return ret; -} - -static int -nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon) -{ - struct drm_framebuffer *fb = fbcon->helper.fb; - struct nouveau_bo *nvbo; - - drm_fb_helper_unregister_info(&fbcon->helper); - drm_fb_helper_fini(&fbcon->helper); - - if (fb && fb->obj[0]) { - nvbo = nouveau_gem_object(fb->obj[0]); - nouveau_vma_del(&fbcon->vma); - nouveau_bo_unmap(nvbo); - nouveau_bo_unpin(nvbo); - drm_framebuffer_put(fb); - } - - return 0; -} - -void nouveau_fbcon_gpu_lockup(struct fb_info *info) -{ - struct nouveau_fbdev *fbcon = info->par; - struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev); - - NV_ERROR(drm, "GPU lockup - switching to software fbcon\n"); - info->flags |= FBINFO_HWACCEL_DISABLED; -} - -static const struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = { - .fb_probe = nouveau_fbcon_create, -}; - -static void -nouveau_fbcon_set_suspend_work(struct work_struct *work) -{ - struct nouveau_drm *drm = container_of(work, typeof(*drm), fbcon_work); - int state = READ_ONCE(drm->fbcon_new_state); - - if (state == FBINFO_STATE_RUNNING) - pm_runtime_get_sync(drm->dev->dev); - - console_lock(); - if (state == FBINFO_STATE_RUNNING) - nouveau_fbcon_accel_restore(drm->dev); - drm_fb_helper_set_suspend(&drm->fbcon->helper, state); - if (state != FBINFO_STATE_RUNNING) - nouveau_fbcon_accel_save_disable(drm->dev); - console_unlock(); - - if (state == FBINFO_STATE_RUNNING) { - nouveau_fbcon_hotplug_resume(drm->fbcon); - pm_runtime_mark_last_busy(drm->dev->dev); - pm_runtime_put_autosuspend(drm->dev->dev); - } -} - -void -nouveau_fbcon_set_suspend(struct drm_device *dev, int state) -{ - struct nouveau_drm *drm = nouveau_drm(dev); - - if (!drm->fbcon) - return; - - drm->fbcon_new_state = state; - /* Since runtime resume can happen as a result of a sysfs operation, - * it's possible we already have the console locked. So handle fbcon - * init/deinit from a seperate work thread - */ - schedule_work(&drm->fbcon_work); -} - -void -nouveau_fbcon_output_poll_changed(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_fbdev *fbcon = drm->fbcon; - int ret; - - if (!fbcon) - return; - - mutex_lock(&fbcon->hotplug_lock); - - ret = pm_runtime_get(dev->dev); - if (ret == 1 || ret == -EACCES) { - drm_fb_helper_hotplug_event(&fbcon->helper); - - pm_runtime_mark_last_busy(dev->dev); - pm_runtime_put_autosuspend(dev->dev); - } else if (ret == 0) { - /* If the GPU was already in the process of suspending before - * this event happened, then we can't block here as we'll - * deadlock the runtime pmops since they wait for us to - * finish. So, just defer this event for when we runtime - * resume again. It will be handled by fbcon_work. - */ - NV_DEBUG(drm, "fbcon HPD event deferred until runtime resume\n"); - fbcon->hotplug_waiting = true; - pm_runtime_put_noidle(drm->dev->dev); - } else { - DRM_WARN("fbcon HPD event lost due to RPM failure: %d\n", - ret); - } - - mutex_unlock(&fbcon->hotplug_lock); -} - -void -nouveau_fbcon_hotplug_resume(struct nouveau_fbdev *fbcon) -{ - struct nouveau_drm *drm; - - if (!fbcon) - return; - drm = nouveau_drm(fbcon->helper.dev); - - mutex_lock(&fbcon->hotplug_lock); - if (fbcon->hotplug_waiting) { - fbcon->hotplug_waiting = false; - - NV_DEBUG(drm, "Handling deferred fbcon HPD events\n"); - drm_fb_helper_hotplug_event(&fbcon->helper); - } - mutex_unlock(&fbcon->hotplug_lock); -} - -int -nouveau_fbcon_init(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_fbdev *fbcon; - int preferred_bpp = nouveau_fbcon_bpp; - int ret; - - if (!dev->mode_config.num_crtc || - (to_pci_dev(dev->dev)->class >> 8) != PCI_CLASS_DISPLAY_VGA) - return 0; - - fbcon = kzalloc(sizeof(struct nouveau_fbdev), GFP_KERNEL); - if (!fbcon) - return -ENOMEM; - - drm->fbcon = fbcon; - INIT_WORK(&drm->fbcon_work, nouveau_fbcon_set_suspend_work); - mutex_init(&fbcon->hotplug_lock); - - drm_fb_helper_prepare(dev, &fbcon->helper, &nouveau_fbcon_helper_funcs); - - ret = drm_fb_helper_init(dev, &fbcon->helper); - if (ret) - goto free; - - if (preferred_bpp != 8 && preferred_bpp != 16 && preferred_bpp != 32) { - if (drm->client.device.info.ram_size <= 32 * 1024 * 1024) - preferred_bpp = 8; - else - if (drm->client.device.info.ram_size <= 64 * 1024 * 1024) - preferred_bpp = 16; - else - preferred_bpp = 32; - } - - /* disable all the possible outputs/crtcs before entering KMS mode */ - if (!drm_drv_uses_atomic_modeset(dev)) - drm_helper_disable_unused_functions(dev); - - ret = drm_fb_helper_initial_config(&fbcon->helper, preferred_bpp); - if (ret) - goto fini; - - if (fbcon->helper.info) - fbcon->helper.info->pixmap.buf_align = 4; - return 0; - -fini: - drm_fb_helper_fini(&fbcon->helper); -free: - kfree(fbcon); - drm->fbcon = NULL; - return ret; -} - -void -nouveau_fbcon_fini(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_drm(dev); - - if (!drm->fbcon) - return; - - drm_kms_helper_poll_fini(dev); - nouveau_fbcon_accel_fini(dev); - nouveau_fbcon_destroy(dev, drm->fbcon); - kfree(drm->fbcon); - drm->fbcon = NULL; -} diff --git a/drivers/gpu/drm/panfrost/Kconfig b/drivers/gpu/drm/panfrost/Kconfig index 079600328be1..e6403a9d66ad 100644 --- a/drivers/gpu/drm/panfrost/Kconfig +++ b/drivers/gpu/drm/panfrost/Kconfig @@ -3,7 +3,8 @@ config DRM_PANFROST tristate "Panfrost (DRM support for ARM Mali Midgard/Bifrost GPUs)" depends on DRM - depends on ARM || ARM64 || (COMPILE_TEST && !GENERIC_ATOMIC64) + depends on ARM || ARM64 || COMPILE_TEST + depends on !GENERIC_ATOMIC64 # for IOMMU_IO_PGTABLE_LPAE depends on MMU select DRM_SCHED select IOMMU_SUPPORT diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c index fa619fe72086..abb0dadd8f63 100644 --- a/drivers/gpu/drm/panfrost/panfrost_drv.c +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c @@ -82,6 +82,7 @@ static int panfrost_ioctl_create_bo(struct drm_device *dev, void *data, struct panfrost_gem_object *bo; struct drm_panfrost_create_bo *args = data; struct panfrost_gem_mapping *mapping; + int ret; if (!args->size || args->pad || (args->flags & ~(PANFROST_BO_NOEXEC | PANFROST_BO_HEAP))) @@ -92,21 +93,29 @@ static int panfrost_ioctl_create_bo(struct drm_device *dev, void *data, !(args->flags & PANFROST_BO_NOEXEC)) return -EINVAL; - bo = panfrost_gem_create_with_handle(file, dev, args->size, args->flags, - &args->handle); + bo = panfrost_gem_create(dev, args->size, args->flags); if (IS_ERR(bo)) return PTR_ERR(bo); + ret = drm_gem_handle_create(file, &bo->base.base, &args->handle); + if (ret) + goto out; + mapping = panfrost_gem_mapping_get(bo, priv); - if (!mapping) { - drm_gem_object_put(&bo->base.base); - return -EINVAL; + if (mapping) { + args->offset = mapping->mmnode.start << PAGE_SHIFT; + panfrost_gem_mapping_put(mapping); + } else { + /* This can only happen if the handle from + * drm_gem_handle_create() has already been guessed and freed + * by user space + */ + ret = -EINVAL; } - args->offset = mapping->mmnode.start << PAGE_SHIFT; - panfrost_gem_mapping_put(mapping); - - return 0; +out: + drm_gem_object_put(&bo->base.base); + return ret; } /** diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.c b/drivers/gpu/drm/panfrost/panfrost_gem.c index 293e799e2fe8..3c812fbd126f 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gem.c +++ b/drivers/gpu/drm/panfrost/panfrost_gem.c @@ -235,12 +235,8 @@ struct drm_gem_object *panfrost_gem_create_object(struct drm_device *dev, size_t } struct panfrost_gem_object * -panfrost_gem_create_with_handle(struct drm_file *file_priv, - struct drm_device *dev, size_t size, - u32 flags, - uint32_t *handle) +panfrost_gem_create(struct drm_device *dev, size_t size, u32 flags) { - int ret; struct drm_gem_shmem_object *shmem; struct panfrost_gem_object *bo; @@ -256,16 +252,6 @@ panfrost_gem_create_with_handle(struct drm_file *file_priv, bo->noexec = !!(flags & PANFROST_BO_NOEXEC); bo->is_heap = !!(flags & PANFROST_BO_HEAP); - /* - * Allocate an id of idr table where the obj is registered - * and handle has the id what user can see. - */ - ret = drm_gem_handle_create(file_priv, &shmem->base, handle); - /* drop reference from allocate - handle holds it now. */ - drm_gem_object_put(&shmem->base); - if (ret) - return ERR_PTR(ret); - return bo; } diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.h b/drivers/gpu/drm/panfrost/panfrost_gem.h index 8088d5fd8480..ad2877eeeccd 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gem.h +++ b/drivers/gpu/drm/panfrost/panfrost_gem.h @@ -69,10 +69,7 @@ panfrost_gem_prime_import_sg_table(struct drm_device *dev, struct sg_table *sgt); struct panfrost_gem_object * -panfrost_gem_create_with_handle(struct drm_file *file_priv, - struct drm_device *dev, size_t size, - u32 flags, - uint32_t *handle); +panfrost_gem_create(struct drm_device *dev, size_t size, u32 flags); int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_priv); void panfrost_gem_close(struct drm_gem_object *obj, diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig index b2bddbeca878..53c356aed5d5 100644 --- a/drivers/gpu/drm/rcar-du/Kconfig +++ b/drivers/gpu/drm/rcar-du/Kconfig @@ -25,6 +25,7 @@ config DRM_RCAR_CMM config DRM_RCAR_DW_HDMI tristate "R-Car Gen3 and RZ/G2 DU HDMI Encoder Support" depends on DRM && OF + depends on DRM_RCAR_DU || COMPILE_TEST select DRM_DW_HDMI help Enable support for R-Car Gen3 or RZ/G2 internal HDMI encoder. @@ -32,6 +33,7 @@ config DRM_RCAR_DW_HDMI config DRM_RCAR_USE_LVDS bool "R-Car DU LVDS Encoder Support" depends on DRM_BRIDGE && OF + depends on DRM_RCAR_DU || COMPILE_TEST default DRM_RCAR_DU help Enable support for the R-Car Display Unit embedded LVDS encoders. @@ -39,12 +41,15 @@ config DRM_RCAR_USE_LVDS config DRM_RCAR_LVDS def_tristate DRM_RCAR_DU depends on DRM_RCAR_USE_LVDS + depends on PM select DRM_KMS_HELPER select DRM_PANEL + select RESET_CONTROLLER config DRM_RCAR_USE_MIPI_DSI bool "R-Car DU MIPI DSI Encoder Support" depends on DRM_BRIDGE && OF + depends on DRM_RCAR_DU || COMPILE_TEST default DRM_RCAR_DU help Enable support for the R-Car Display Unit embedded MIPI DSI encoders. @@ -53,6 +58,7 @@ config DRM_RCAR_MIPI_DSI def_tristate DRM_RCAR_DU depends on DRM_RCAR_USE_MIPI_DSI select DRM_MIPI_DSI + select RESET_CONTROLLER config DRM_RZG2L_MIPI_DSI tristate "RZ/G2L MIPI DSI Encoder Support" diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 3619e1ddeb62..008e172ed43b 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -10,7 +10,6 @@ #include <linux/clk.h> #include <linux/mutex.h> #include <linux/platform_device.h> -#include <linux/sys_soc.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> @@ -204,11 +203,6 @@ static void rcar_du_escr_divider(struct clk *clk, unsigned long target, } } -static const struct soc_device_attribute rcar_du_r8a7795_es1[] = { - { .soc_id = "r8a7795", .revision = "ES1.*" }, - { /* sentinel */ } -}; - static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc) { const struct drm_display_mode *mode = &rcrtc->crtc.state->adjusted_mode; @@ -238,7 +232,7 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc) * no post-divider when a display PLL is present (as shown by * the workaround breaking HDMI output on M3-W during testing). */ - if (soc_device_match(rcar_du_r8a7795_es1)) { + if (rcdu->info->quirks & RCAR_DU_QUIRK_H3_ES1_PCLK_STABILITY) { target *= 2; div = 1; } @@ -251,13 +245,30 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc) | DPLLCR_N(dpll.n) | DPLLCR_M(dpll.m) | DPLLCR_STBY; - if (rcrtc->index == 1) + if (rcrtc->index == 1) { dpllcr |= DPLLCR_PLCS1 | DPLLCR_INCS_DOTCLKIN1; - else - dpllcr |= DPLLCR_PLCS0 + } else { + dpllcr |= DPLLCR_PLCS0_PLL | DPLLCR_INCS_DOTCLKIN0; + /* + * On ES2.x we have a single mux controlled via bit 21, + * which selects between DCLKIN source (bit 21 = 0) and + * a PLL source (bit 21 = 1), where the PLL is always + * PLL1. + * + * On ES1.x we have an additional mux, controlled + * via bit 20, for choosing between PLL0 (bit 20 = 0) + * and PLL1 (bit 20 = 1). We always want to use PLL1, + * so on ES1.x, in addition to setting bit 21, we need + * to set the bit 20. + */ + + if (rcdu->info->quirks & RCAR_DU_QUIRK_H3_ES1_PLL) + dpllcr |= DPLLCR_PLCS0_H3ES1X_PLL1; + } + rcar_du_group_write(rcrtc->group, DPLLCR, dpllcr); escr = ESCR_DCLKSEL_DCLKIN | div; @@ -287,10 +298,12 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc) escr = params.escr; } - dev_dbg(rcrtc->dev->dev, "%s: ESCR 0x%08x\n", __func__, escr); + if (rcdu->info->gen < 4) { + dev_dbg(rcrtc->dev->dev, "%s: ESCR 0x%08x\n", __func__, escr); - rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? ESCR13 : ESCR02, escr); - rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? OTAR13 : OTAR02, 0); + rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? ESCR13 : ESCR02, escr); + rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? OTAR13 : OTAR02, 0); + } /* Signal polarities */ dsmr = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? DSMR_VSL : 0) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index eeec1e02446f..b9a94c5260e9 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -16,6 +16,7 @@ #include <linux/platform_device.h> #include <linux/pm.h> #include <linux/slab.h> +#include <linux/sys_soc.h> #include <linux/wait.h> #include <drm/drm_atomic_helper.h> @@ -386,6 +387,43 @@ static const struct rcar_du_device_info rcar_du_r8a7795_info = { .dpll_mask = BIT(2) | BIT(1), }; +static const struct rcar_du_device_info rcar_du_r8a7795_es1_info = { + .gen = 3, + .features = RCAR_DU_FEATURE_CRTC_IRQ + | RCAR_DU_FEATURE_CRTC_CLOCK + | RCAR_DU_FEATURE_VSP1_SOURCE + | RCAR_DU_FEATURE_INTERLACED + | RCAR_DU_FEATURE_TVM_SYNC, + .quirks = RCAR_DU_QUIRK_H3_ES1_PCLK_STABILITY + | RCAR_DU_QUIRK_H3_ES1_PLL, + .channels_mask = BIT(3) | BIT(2) | BIT(1) | BIT(0), + .routes = { + /* + * R8A7795 has one RGB output, two HDMI outputs and one + * LVDS output. + */ + [RCAR_DU_OUTPUT_DPAD0] = { + .possible_crtcs = BIT(3), + .port = 0, + }, + [RCAR_DU_OUTPUT_HDMI0] = { + .possible_crtcs = BIT(1), + .port = 1, + }, + [RCAR_DU_OUTPUT_HDMI1] = { + .possible_crtcs = BIT(2), + .port = 2, + }, + [RCAR_DU_OUTPUT_LVDS0] = { + .possible_crtcs = BIT(0), + .port = 3, + }, + }, + .num_lvds = 1, + .num_rpf = 5, + .dpll_mask = BIT(2) | BIT(1), +}; + static const struct rcar_du_device_info rcar_du_r8a7796_info = { .gen = 3, .features = RCAR_DU_FEATURE_CRTC_IRQ @@ -504,7 +542,7 @@ static const struct rcar_du_device_info rcar_du_r8a7799x_info = { }; static const struct rcar_du_device_info rcar_du_r8a779a0_info = { - .gen = 3, + .gen = 4, .features = RCAR_DU_FEATURE_CRTC_IRQ | RCAR_DU_FEATURE_VSP1_SOURCE | RCAR_DU_FEATURE_NO_BLENDING, @@ -524,6 +562,27 @@ static const struct rcar_du_device_info rcar_du_r8a779a0_info = { .dsi_clk_mask = BIT(1) | BIT(0), }; +static const struct rcar_du_device_info rcar_du_r8a779g0_info = { + .gen = 4, + .features = RCAR_DU_FEATURE_CRTC_IRQ + | RCAR_DU_FEATURE_VSP1_SOURCE + | RCAR_DU_FEATURE_NO_BLENDING, + .channels_mask = BIT(1) | BIT(0), + .routes = { + /* R8A779G0 has two MIPI DSI outputs. */ + [RCAR_DU_OUTPUT_DSI0] = { + .possible_crtcs = BIT(0), + .port = 0, + }, + [RCAR_DU_OUTPUT_DSI1] = { + .possible_crtcs = BIT(1), + .port = 1, + }, + }, + .num_rpf = 5, + .dsi_clk_mask = BIT(1) | BIT(0), +}; + static const struct of_device_id rcar_du_of_table[] = { { .compatible = "renesas,du-r8a7742", .data = &rcar_du_r8a7790_info }, { .compatible = "renesas,du-r8a7743", .data = &rzg1_du_r8a7743_info }, @@ -549,11 +608,17 @@ static const struct of_device_id rcar_du_of_table[] = { { .compatible = "renesas,du-r8a77990", .data = &rcar_du_r8a7799x_info }, { .compatible = "renesas,du-r8a77995", .data = &rcar_du_r8a7799x_info }, { .compatible = "renesas,du-r8a779a0", .data = &rcar_du_r8a779a0_info }, + { .compatible = "renesas,du-r8a779g0", .data = &rcar_du_r8a779g0_info }, { } }; MODULE_DEVICE_TABLE(of, rcar_du_of_table); +static const struct soc_device_attribute rcar_du_soc_table[] = { + { .soc_id = "r8a7795", .revision = "ES1.*", .data = &rcar_du_r8a7795_es1_info }, + { /* sentinel */ } +}; + const char *rcar_du_output_name(enum rcar_du_output output) { static const char * const names[] = { @@ -642,6 +707,7 @@ static void rcar_du_shutdown(struct platform_device *pdev) static int rcar_du_probe(struct platform_device *pdev) { + const struct soc_device_attribute *soc_attr; struct rcar_du_device *rcdu; unsigned int mask; int ret; @@ -656,8 +722,13 @@ static int rcar_du_probe(struct platform_device *pdev) return PTR_ERR(rcdu); rcdu->dev = &pdev->dev; + rcdu->info = of_device_get_match_data(rcdu->dev); + soc_attr = soc_device_match(rcar_du_soc_table); + if (soc_attr) + rcdu->info = soc_attr->data; + platform_set_drvdata(pdev, rcdu); /* I/O resources */ diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h index 5cfa2bb7ad93..acc3673fefe1 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h @@ -34,6 +34,8 @@ struct rcar_du_device; #define RCAR_DU_FEATURE_NO_BLENDING BIT(5) /* PnMR.SPIM does not have ALP nor EOR bits */ #define RCAR_DU_QUIRK_ALIGN_128B BIT(0) /* Align pitches to 128 bytes */ +#define RCAR_DU_QUIRK_H3_ES1_PCLK_STABILITY BIT(1) /* H3 ES1 has pclk stability issue */ +#define RCAR_DU_QUIRK_H3_ES1_PLL BIT(2) /* H3 ES1 PLL setup differs from non-ES1 */ enum rcar_du_output { RCAR_DU_OUTPUT_DPAD0, diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c index 1fe8581577ed..152602236377 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c @@ -107,7 +107,7 @@ static void rcar_du_group_setup_didsr(struct rcar_du_group *rgrp) */ rcrtc = rcdu->crtcs; num_crtcs = rcdu->num_crtcs; - } else if (rcdu->info->gen == 3 && rgrp->num_crtcs > 1) { + } else if (rcdu->info->gen >= 3 && rgrp->num_crtcs > 1) { /* * On Gen3 dot clocks are setup through per-group registers, * only available when the group has two channels. @@ -148,19 +148,23 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp) } rcar_du_group_write(rgrp, DEFR5, DEFR5_CODE | DEFR5_DEFE5); - rcar_du_group_setup_pins(rgrp); + if (rcdu->info->gen < 4) + rcar_du_group_setup_pins(rgrp); - /* - * TODO: Handle routing of the DU output to CMM dynamically, as we - * should bypass CMM completely when no color management feature is - * used. - */ - defr7 |= (rgrp->cmms_mask & BIT(1) ? DEFR7_CMME1 : 0) | - (rgrp->cmms_mask & BIT(0) ? DEFR7_CMME0 : 0); - rcar_du_group_write(rgrp, DEFR7, defr7); + if (rcdu->info->gen < 4) { + /* + * TODO: Handle routing of the DU output to CMM dynamically, as + * we should bypass CMM completely when no color management + * feature is used. + */ + defr7 |= (rgrp->cmms_mask & BIT(1) ? DEFR7_CMME1 : 0) | + (rgrp->cmms_mask & BIT(0) ? DEFR7_CMME0 : 0); + rcar_du_group_write(rgrp, DEFR7, defr7); + } if (rcdu->info->gen >= 2) { - rcar_du_group_setup_defr8(rgrp); + if (rcdu->info->gen < 4) + rcar_du_group_setup_defr8(rgrp); rcar_du_group_setup_didsr(rgrp); } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index 8c2719efda2a..adfb36b0e815 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -260,6 +260,24 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = { .planes = 1, .hsub = 1, }, { + .fourcc = DRM_FORMAT_RGBX1010102, + .v4l2 = V4L2_PIX_FMT_RGBX1010102, + .bpp = 32, + .planes = 1, + .hsub = 1, + }, { + .fourcc = DRM_FORMAT_RGBA1010102, + .v4l2 = V4L2_PIX_FMT_RGBA1010102, + .bpp = 32, + .planes = 1, + .hsub = 1, + }, { + .fourcc = DRM_FORMAT_ARGB2101010, + .v4l2 = V4L2_PIX_FMT_ARGB2101010, + .bpp = 32, + .planes = 1, + .hsub = 1, + }, { .fourcc = DRM_FORMAT_YVYU, .v4l2 = V4L2_PIX_FMT_YVYU, .bpp = 16, @@ -307,6 +325,18 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = { .bpp = 24, .planes = 3, .hsub = 1, + }, { + .fourcc = DRM_FORMAT_Y210, + .v4l2 = V4L2_PIX_FMT_Y210, + .bpp = 32, + .planes = 1, + .hsub = 2, + }, { + .fourcc = DRM_FORMAT_Y212, + .v4l2 = V4L2_PIX_FMT_Y212, + .bpp = 32, + .planes = 1, + .hsub = 2, }, }; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/rcar-du/rcar_du_regs.h index c1bcb0e8b5b4..789ae9285108 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h @@ -283,12 +283,8 @@ #define DPLLCR 0x20044 #define DPLLCR_CODE (0x95 << 24) #define DPLLCR_PLCS1 (1 << 23) -/* - * PLCS0 is bit 21, but H3 ES1.x requires bit 20 to be set as well. As bit 20 - * isn't implemented by other SoC in the Gen3 family it can safely be set - * unconditionally. - */ -#define DPLLCR_PLCS0 (3 << 20) +#define DPLLCR_PLCS0_PLL (1 << 21) +#define DPLLCR_PLCS0_H3ES1X_PLL1 (1 << 20) #define DPLLCR_CLKE (1 << 18) #define DPLLCR_FDPLL(n) ((n) << 12) #define DPLLCR_N(n) ((n) << 5) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index e465aef41585..fe90be51d64e 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -139,6 +139,43 @@ static const u32 rcar_du_vsp_formats[] = { DRM_FORMAT_YVU444, }; +/* + * Gen4 supports the same formats as above, and additionally 2-10-10-10 RGB + * formats and Y210 & Y212 formats. + */ +static const u32 rcar_du_vsp_formats_gen4[] = { + DRM_FORMAT_RGB332, + DRM_FORMAT_ARGB4444, + DRM_FORMAT_XRGB4444, + DRM_FORMAT_ARGB1555, + DRM_FORMAT_XRGB1555, + DRM_FORMAT_RGB565, + DRM_FORMAT_BGR888, + DRM_FORMAT_RGB888, + DRM_FORMAT_BGRA8888, + DRM_FORMAT_BGRX8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGBX1010102, + DRM_FORMAT_RGBA1010102, + DRM_FORMAT_ARGB2101010, + DRM_FORMAT_UYVY, + DRM_FORMAT_YUYV, + DRM_FORMAT_YVYU, + DRM_FORMAT_NV12, + DRM_FORMAT_NV21, + DRM_FORMAT_NV16, + DRM_FORMAT_NV61, + DRM_FORMAT_YUV420, + DRM_FORMAT_YVU420, + DRM_FORMAT_YUV422, + DRM_FORMAT_YVU422, + DRM_FORMAT_YUV444, + DRM_FORMAT_YVU444, + DRM_FORMAT_Y210, + DRM_FORMAT_Y212, +}; + static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane) { struct rcar_du_vsp_plane_state *state = @@ -436,14 +473,23 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp, struct device_node *np, ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; struct rcar_du_vsp_plane *plane = &vsp->planes[i]; + unsigned int num_formats; + const u32 *formats; + + if (rcdu->info->gen < 4) { + num_formats = ARRAY_SIZE(rcar_du_vsp_formats); + formats = rcar_du_vsp_formats; + } else { + num_formats = ARRAY_SIZE(rcar_du_vsp_formats_gen4); + formats = rcar_du_vsp_formats_gen4; + } plane->vsp = vsp; plane->index = i; ret = drm_universal_plane_init(&rcdu->ddev, &plane->plane, crtcs, &rcar_du_vsp_plane_funcs, - rcar_du_vsp_formats, - ARRAY_SIZE(rcar_du_vsp_formats), + formats, num_formats, NULL, type, NULL); if (ret < 0) return ret; diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c index 81a060c2fe3f..260ea5d8624e 100644 --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c @@ -16,6 +16,8 @@ #include <linux/of_device.h> #include <linux/of_graph.h> #include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/reset.h> #include <linux/slab.h> #include <linux/sys_soc.h> @@ -60,6 +62,7 @@ struct rcar_lvds_device_info { struct rcar_lvds { struct device *dev; const struct rcar_lvds_device_info *info; + struct reset_control *rstc; struct drm_bridge bridge; @@ -80,6 +83,11 @@ struct rcar_lvds { #define bridge_to_rcar_lvds(b) \ container_of(b, struct rcar_lvds, bridge) +static u32 rcar_lvds_read(struct rcar_lvds *lvds, u32 reg) +{ + return ioread32(lvds->mmio + reg); +} + static void rcar_lvds_write(struct rcar_lvds *lvds, u32 reg, u32 data) { iowrite32(data, lvds->mmio + reg); @@ -316,8 +324,8 @@ int rcar_lvds_pclk_enable(struct drm_bridge *bridge, unsigned long freq) dev_dbg(lvds->dev, "enabling LVDS PLL, freq=%luHz\n", freq); - ret = clk_prepare_enable(lvds->clocks.mod); - if (ret < 0) + ret = pm_runtime_resume_and_get(lvds->dev); + if (ret) return ret; __rcar_lvds_pll_setup_d3_e3(lvds, freq, true); @@ -337,7 +345,7 @@ void rcar_lvds_pclk_disable(struct drm_bridge *bridge) rcar_lvds_write(lvds, LVDPLLCR, 0); - clk_disable_unprepare(lvds->clocks.mod); + pm_runtime_put_sync(lvds->dev); } EXPORT_SYMBOL_GPL(rcar_lvds_pclk_disable); @@ -396,8 +404,8 @@ static void __rcar_lvds_atomic_enable(struct drm_bridge *bridge, u32 lvdcr0; int ret; - ret = clk_prepare_enable(lvds->clocks.mod); - if (ret < 0) + ret = pm_runtime_resume_and_get(lvds->dev); + if (ret) return; /* Enable the companion LVDS encoder in dual-link mode. */ @@ -541,6 +549,32 @@ static void rcar_lvds_atomic_disable(struct drm_bridge *bridge, struct drm_bridge_state *old_bridge_state) { struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge); + u32 lvdcr0; + + /* + * Clear the LVDCR0 bits in the order specified by the hardware + * documentation, ending with a write of 0 to the full register to + * clear all remaining bits. + */ + lvdcr0 = rcar_lvds_read(lvds, LVDCR0); + + lvdcr0 &= ~LVDCR0_LVRES; + rcar_lvds_write(lvds, LVDCR0, lvdcr0); + + if (lvds->info->quirks & RCAR_LVDS_QUIRK_GEN3_LVEN) { + lvdcr0 &= ~LVDCR0_LVEN; + rcar_lvds_write(lvds, LVDCR0, lvdcr0); + } + + if (lvds->info->quirks & RCAR_LVDS_QUIRK_PWD) { + lvdcr0 &= ~LVDCR0_PWD; + rcar_lvds_write(lvds, LVDCR0, lvdcr0); + } + + if (!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)) { + lvdcr0 &= ~LVDCR0_PLLON; + rcar_lvds_write(lvds, LVDCR0, lvdcr0); + } rcar_lvds_write(lvds, LVDCR0, 0); rcar_lvds_write(lvds, LVDCR1, 0); @@ -551,7 +585,7 @@ static void rcar_lvds_atomic_disable(struct drm_bridge *bridge, lvds->companion->funcs->atomic_disable(lvds->companion, old_bridge_state); - clk_disable_unprepare(lvds->clocks.mod); + pm_runtime_put_sync(lvds->dev); } static bool rcar_lvds_mode_fixup(struct drm_bridge *bridge, @@ -844,6 +878,13 @@ static int rcar_lvds_probe(struct platform_device *pdev) if (ret < 0) return ret; + lvds->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); + if (IS_ERR(lvds->rstc)) + return dev_err_probe(&pdev->dev, PTR_ERR(lvds->rstc), + "failed to get cpg reset\n"); + + pm_runtime_enable(&pdev->dev); + drm_bridge_add(&lvds->bridge); return 0; @@ -855,6 +896,8 @@ static int rcar_lvds_remove(struct platform_device *pdev) drm_bridge_remove(&lvds->bridge); + pm_runtime_disable(&pdev->dev); + return 0; } @@ -913,11 +956,48 @@ static const struct of_device_id rcar_lvds_of_table[] = { MODULE_DEVICE_TABLE(of, rcar_lvds_of_table); +static int rcar_lvds_runtime_suspend(struct device *dev) +{ + struct rcar_lvds *lvds = dev_get_drvdata(dev); + + clk_disable_unprepare(lvds->clocks.mod); + + reset_control_assert(lvds->rstc); + + return 0; +} + +static int rcar_lvds_runtime_resume(struct device *dev) +{ + struct rcar_lvds *lvds = dev_get_drvdata(dev); + int ret; + + ret = reset_control_deassert(lvds->rstc); + if (ret) + return ret; + + ret = clk_prepare_enable(lvds->clocks.mod); + if (ret < 0) + goto err_reset_assert; + + return 0; + +err_reset_assert: + reset_control_assert(lvds->rstc); + + return ret; +} + +static const struct dev_pm_ops rcar_lvds_pm_ops = { + SET_RUNTIME_PM_OPS(rcar_lvds_runtime_suspend, rcar_lvds_runtime_resume, NULL) +}; + static struct platform_driver rcar_lvds_platform_driver = { .probe = rcar_lvds_probe, .remove = rcar_lvds_remove, .driver = { .name = "rcar-lvds", + .pm = &rcar_lvds_pm_ops, .of_match_table = rcar_lvds_of_table, }, }; diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c index a7f2b7f66a17..e10e4d4b89a2 100644 --- a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c +++ b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c @@ -9,6 +9,7 @@ #include <linux/delay.h> #include <linux/io.h> #include <linux/iopoll.h> +#include <linux/math64.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_device.h> @@ -28,6 +29,31 @@ #include "rcar_mipi_dsi.h" #include "rcar_mipi_dsi_regs.h" +#define MHZ(v) ((u32)((v) * 1000000U)) + +enum rcar_mipi_dsi_hw_model { + RCAR_DSI_V3U, + RCAR_DSI_V4H, +}; + +struct rcar_mipi_dsi_device_info { + enum rcar_mipi_dsi_hw_model model; + + const struct dsi_clk_config *clk_cfg; + + u8 clockset2_m_offset; + + u8 n_min; + u8 n_max; + u8 n_mul; + unsigned long fpfd_min; + unsigned long fpfd_max; + u16 m_min; + u16 m_max; + unsigned long fout_min; + unsigned long fout_max; +}; + struct rcar_mipi_dsi { struct device *dev; const struct rcar_mipi_dsi_device_info *info; @@ -50,6 +76,17 @@ struct rcar_mipi_dsi { unsigned int lanes; }; +struct dsi_setup_info { + unsigned long hsfreq; + u16 hsfreqrange; + + unsigned long fout; + u16 m; + u16 n; + u16 vclk_divider; + const struct dsi_clk_config *clkset; +}; + static inline struct rcar_mipi_dsi * bridge_to_rcar_mipi_dsi(struct drm_bridge *bridge) { @@ -62,65 +99,78 @@ host_to_rcar_mipi_dsi(struct mipi_dsi_host *host) return container_of(host, struct rcar_mipi_dsi, host); } -static const u32 phtw[] = { - 0x01020114, 0x01600115, /* General testing */ - 0x01030116, 0x0102011d, /* General testing */ - 0x011101a4, 0x018601a4, /* 1Gbps testing */ - 0x014201a0, 0x010001a3, /* 1Gbps testing */ - 0x0101011f, /* 1Gbps testing */ -}; - -static const u32 phtw2[] = { - 0x010c0130, 0x010c0140, /* General testing */ - 0x010c0150, 0x010c0180, /* General testing */ - 0x010c0190, - 0x010a0160, 0x010a0170, - 0x01800164, 0x01800174, /* 1Gbps testing */ -}; - static const u32 hsfreqrange_table[][2] = { - { 80000000U, 0x00 }, { 90000000U, 0x10 }, { 100000000U, 0x20 }, - { 110000000U, 0x30 }, { 120000000U, 0x01 }, { 130000000U, 0x11 }, - { 140000000U, 0x21 }, { 150000000U, 0x31 }, { 160000000U, 0x02 }, - { 170000000U, 0x12 }, { 180000000U, 0x22 }, { 190000000U, 0x32 }, - { 205000000U, 0x03 }, { 220000000U, 0x13 }, { 235000000U, 0x23 }, - { 250000000U, 0x33 }, { 275000000U, 0x04 }, { 300000000U, 0x14 }, - { 325000000U, 0x25 }, { 350000000U, 0x35 }, { 400000000U, 0x05 }, - { 450000000U, 0x16 }, { 500000000U, 0x26 }, { 550000000U, 0x37 }, - { 600000000U, 0x07 }, { 650000000U, 0x18 }, { 700000000U, 0x28 }, - { 750000000U, 0x39 }, { 800000000U, 0x09 }, { 850000000U, 0x19 }, - { 900000000U, 0x29 }, { 950000000U, 0x3a }, { 1000000000U, 0x0a }, - { 1050000000U, 0x1a }, { 1100000000U, 0x2a }, { 1150000000U, 0x3b }, - { 1200000000U, 0x0b }, { 1250000000U, 0x1b }, { 1300000000U, 0x2b }, - { 1350000000U, 0x3c }, { 1400000000U, 0x0c }, { 1450000000U, 0x1c }, - { 1500000000U, 0x2c }, { 1550000000U, 0x3d }, { 1600000000U, 0x0d }, - { 1650000000U, 0x1d }, { 1700000000U, 0x2e }, { 1750000000U, 0x3e }, - { 1800000000U, 0x0e }, { 1850000000U, 0x1e }, { 1900000000U, 0x2f }, - { 1950000000U, 0x3f }, { 2000000000U, 0x0f }, { 2050000000U, 0x40 }, - { 2100000000U, 0x41 }, { 2150000000U, 0x42 }, { 2200000000U, 0x43 }, - { 2250000000U, 0x44 }, { 2300000000U, 0x45 }, { 2350000000U, 0x46 }, - { 2400000000U, 0x47 }, { 2450000000U, 0x48 }, { 2500000000U, 0x49 }, + { MHZ(80), 0x00 }, { MHZ(90), 0x10 }, { MHZ(100), 0x20 }, + { MHZ(110), 0x30 }, { MHZ(120), 0x01 }, { MHZ(130), 0x11 }, + { MHZ(140), 0x21 }, { MHZ(150), 0x31 }, { MHZ(160), 0x02 }, + { MHZ(170), 0x12 }, { MHZ(180), 0x22 }, { MHZ(190), 0x32 }, + { MHZ(205), 0x03 }, { MHZ(220), 0x13 }, { MHZ(235), 0x23 }, + { MHZ(250), 0x33 }, { MHZ(275), 0x04 }, { MHZ(300), 0x14 }, + { MHZ(325), 0x25 }, { MHZ(350), 0x35 }, { MHZ(400), 0x05 }, + { MHZ(450), 0x16 }, { MHZ(500), 0x26 }, { MHZ(550), 0x37 }, + { MHZ(600), 0x07 }, { MHZ(650), 0x18 }, { MHZ(700), 0x28 }, + { MHZ(750), 0x39 }, { MHZ(800), 0x09 }, { MHZ(850), 0x19 }, + { MHZ(900), 0x29 }, { MHZ(950), 0x3a }, { MHZ(1000), 0x0a }, + { MHZ(1050), 0x1a }, { MHZ(1100), 0x2a }, { MHZ(1150), 0x3b }, + { MHZ(1200), 0x0b }, { MHZ(1250), 0x1b }, { MHZ(1300), 0x2b }, + { MHZ(1350), 0x3c }, { MHZ(1400), 0x0c }, { MHZ(1450), 0x1c }, + { MHZ(1500), 0x2c }, { MHZ(1550), 0x3d }, { MHZ(1600), 0x0d }, + { MHZ(1650), 0x1d }, { MHZ(1700), 0x2e }, { MHZ(1750), 0x3e }, + { MHZ(1800), 0x0e }, { MHZ(1850), 0x1e }, { MHZ(1900), 0x2f }, + { MHZ(1950), 0x3f }, { MHZ(2000), 0x0f }, { MHZ(2050), 0x40 }, + { MHZ(2100), 0x41 }, { MHZ(2150), 0x42 }, { MHZ(2200), 0x43 }, + { MHZ(2250), 0x44 }, { MHZ(2300), 0x45 }, { MHZ(2350), 0x46 }, + { MHZ(2400), 0x47 }, { MHZ(2450), 0x48 }, { MHZ(2500), 0x49 }, { /* sentinel */ }, }; -struct vco_cntrl_value { +struct dsi_clk_config { u32 min_freq; u32 max_freq; - u16 value; + u8 vco_cntrl; + u8 cpbias_cntrl; + u8 gmp_cntrl; + u8 int_cntrl; + u8 prop_cntrl; }; -static const struct vco_cntrl_value vco_cntrl_table[] = { - { .min_freq = 40000000U, .max_freq = 55000000U, .value = 0x3f }, - { .min_freq = 52500000U, .max_freq = 80000000U, .value = 0x39 }, - { .min_freq = 80000000U, .max_freq = 110000000U, .value = 0x2f }, - { .min_freq = 105000000U, .max_freq = 160000000U, .value = 0x29 }, - { .min_freq = 160000000U, .max_freq = 220000000U, .value = 0x1f }, - { .min_freq = 210000000U, .max_freq = 320000000U, .value = 0x19 }, - { .min_freq = 320000000U, .max_freq = 440000000U, .value = 0x0f }, - { .min_freq = 420000000U, .max_freq = 660000000U, .value = 0x09 }, - { .min_freq = 630000000U, .max_freq = 1149000000U, .value = 0x03 }, - { .min_freq = 1100000000U, .max_freq = 1152000000U, .value = 0x01 }, - { .min_freq = 1150000000U, .max_freq = 1250000000U, .value = 0x01 }, +static const struct dsi_clk_config dsi_clk_cfg_v3u[] = { + { MHZ(40), MHZ(55), 0x3f, 0x10, 0x01, 0x00, 0x0b }, + { MHZ(52.5), MHZ(80), 0x39, 0x10, 0x01, 0x00, 0x0b }, + { MHZ(80), MHZ(110), 0x2f, 0x10, 0x01, 0x00, 0x0b }, + { MHZ(105), MHZ(160), 0x29, 0x10, 0x01, 0x00, 0x0b }, + { MHZ(160), MHZ(220), 0x1f, 0x10, 0x01, 0x00, 0x0b }, + { MHZ(210), MHZ(320), 0x19, 0x10, 0x01, 0x00, 0x0b }, + { MHZ(320), MHZ(440), 0x0f, 0x10, 0x01, 0x00, 0x0b }, + { MHZ(420), MHZ(660), 0x09, 0x10, 0x01, 0x00, 0x0b }, + { MHZ(630), MHZ(1149), 0x03, 0x10, 0x01, 0x00, 0x0b }, + { MHZ(1100), MHZ(1152), 0x01, 0x10, 0x01, 0x00, 0x0b }, + { MHZ(1150), MHZ(1250), 0x01, 0x10, 0x01, 0x00, 0x0c }, + { /* sentinel */ }, +}; + +static const struct dsi_clk_config dsi_clk_cfg_v4h[] = { + { MHZ(40), MHZ(45.31), 0x2b, 0x00, 0x00, 0x08, 0x0a }, + { MHZ(45.31), MHZ(54.66), 0x28, 0x00, 0x00, 0x08, 0x0a }, + { MHZ(54.66), MHZ(62.5), 0x28, 0x00, 0x00, 0x08, 0x0a }, + { MHZ(62.5), MHZ(75), 0x27, 0x00, 0x00, 0x08, 0x0a }, + { MHZ(75), MHZ(90.63), 0x23, 0x00, 0x00, 0x08, 0x0a }, + { MHZ(90.63), MHZ(109.37), 0x20, 0x00, 0x00, 0x08, 0x0a }, + { MHZ(109.37), MHZ(125), 0x20, 0x00, 0x00, 0x08, 0x0a }, + { MHZ(125), MHZ(150), 0x1f, 0x00, 0x00, 0x08, 0x0a }, + { MHZ(150), MHZ(181.25), 0x1b, 0x00, 0x00, 0x08, 0x0a }, + { MHZ(181.25), MHZ(218.75), 0x18, 0x00, 0x00, 0x08, 0x0a }, + { MHZ(218.75), MHZ(250), 0x18, 0x00, 0x00, 0x08, 0x0a }, + { MHZ(250), MHZ(300), 0x17, 0x00, 0x00, 0x08, 0x0a }, + { MHZ(300), MHZ(362.5), 0x13, 0x00, 0x00, 0x08, 0x0a }, + { MHZ(362.5), MHZ(455.48), 0x10, 0x00, 0x00, 0x08, 0x0a }, + { MHZ(455.48), MHZ(500), 0x10, 0x00, 0x00, 0x08, 0x0a }, + { MHZ(500), MHZ(600), 0x0f, 0x00, 0x00, 0x08, 0x0a }, + { MHZ(600), MHZ(725), 0x0b, 0x00, 0x00, 0x08, 0x0a }, + { MHZ(725), MHZ(875), 0x08, 0x00, 0x00, 0x08, 0x0a }, + { MHZ(875), MHZ(1000), 0x08, 0x00, 0x00, 0x08, 0x0a }, + { MHZ(1000), MHZ(1200), 0x07, 0x00, 0x00, 0x08, 0x0a }, + { MHZ(1200), MHZ(1250), 0x03, 0x00, 0x00, 0x08, 0x0a }, { /* sentinel */ }, }; @@ -144,7 +194,7 @@ static void rcar_mipi_dsi_set(struct rcar_mipi_dsi *dsi, u32 reg, u32 set) rcar_mipi_dsi_write(dsi, reg, rcar_mipi_dsi_read(dsi, reg) | set); } -static int rcar_mipi_dsi_phtw_test(struct rcar_mipi_dsi *dsi, u32 phtw) +static int rcar_mipi_dsi_write_phtw(struct rcar_mipi_dsi *dsi, u32 phtw) { u32 status; int ret; @@ -163,32 +213,181 @@ static int rcar_mipi_dsi_phtw_test(struct rcar_mipi_dsi *dsi, u32 phtw) return ret; } +static int rcar_mipi_dsi_write_phtw_arr(struct rcar_mipi_dsi *dsi, + const u32 *phtw, unsigned int size) +{ + for (unsigned int i = 0; i < size; i++) { + int ret = rcar_mipi_dsi_write_phtw(dsi, phtw[i]); + + if (ret < 0) + return ret; + } + + return 0; +} + +#define WRITE_PHTW(...) \ + ({ \ + static const u32 phtw[] = { __VA_ARGS__ }; \ + int ret; \ + ret = rcar_mipi_dsi_write_phtw_arr(dsi, phtw, \ + ARRAY_SIZE(phtw)); \ + ret; \ + }) + +static int rcar_mipi_dsi_init_phtw_v3u(struct rcar_mipi_dsi *dsi) +{ + return WRITE_PHTW(0x01020114, 0x01600115, 0x01030116, 0x0102011d, + 0x011101a4, 0x018601a4, 0x014201a0, 0x010001a3, + 0x0101011f); +} + +static int rcar_mipi_dsi_post_init_phtw_v3u(struct rcar_mipi_dsi *dsi) +{ + return WRITE_PHTW(0x010c0130, 0x010c0140, 0x010c0150, 0x010c0180, + 0x010c0190, 0x010a0160, 0x010a0170, 0x01800164, + 0x01800174); +} + +static int rcar_mipi_dsi_init_phtw_v4h(struct rcar_mipi_dsi *dsi, + const struct dsi_setup_info *setup_info) +{ + int ret; + + if (setup_info->hsfreq < MHZ(450)) { + ret = WRITE_PHTW(0x01010100, 0x011b01ac); + if (ret) + return ret; + } + + ret = WRITE_PHTW(0x01010100, 0x01030173, 0x01000174, 0x01500175, + 0x01030176, 0x01040166, 0x010201ad); + if (ret) + return ret; + + if (setup_info->hsfreq <= MHZ(1000)) + ret = WRITE_PHTW(0x01020100, 0x01910170, 0x01020171, + 0x01110172); + else if (setup_info->hsfreq <= MHZ(1500)) + ret = WRITE_PHTW(0x01020100, 0x01980170, 0x01030171, + 0x01100172); + else if (setup_info->hsfreq <= MHZ(2500)) + ret = WRITE_PHTW(0x01020100, 0x0144016b, 0x01000172); + else + return -EINVAL; + + if (ret) + return ret; + + if (dsi->lanes <= 1) { + ret = WRITE_PHTW(0x01070100, 0x010e010b); + if (ret) + return ret; + } + + if (dsi->lanes <= 2) { + ret = WRITE_PHTW(0x01090100, 0x010e010b); + if (ret) + return ret; + } + + if (dsi->lanes <= 3) { + ret = WRITE_PHTW(0x010b0100, 0x010e010b); + if (ret) + return ret; + } + + if (setup_info->hsfreq <= MHZ(1500)) { + ret = WRITE_PHTW(0x01010100, 0x01c0016e); + if (ret) + return ret; + } + + return 0; +} + +static int +rcar_mipi_dsi_post_init_phtw_v4h(struct rcar_mipi_dsi *dsi, + const struct dsi_setup_info *setup_info) +{ + u32 status; + int ret; + + if (setup_info->hsfreq <= MHZ(1500)) { + WRITE_PHTW(0x01020100, 0x00000180); + + ret = read_poll_timeout(rcar_mipi_dsi_read, status, + status & PHTR_TEST, 2000, 10000, false, + dsi, PHTR); + if (ret < 0) { + dev_err(dsi->dev, "failed to test PHTR\n"); + return ret; + } + + WRITE_PHTW(0x01010100, 0x0100016e); + } + + return 0; +} + /* ----------------------------------------------------------------------------- * Hardware Setup */ -struct dsi_setup_info { - unsigned long fout; - u16 vco_cntrl; - u16 prop_cntrl; - u16 hsfreqrange; - u16 div; - unsigned int m; - unsigned int n; -}; +static void rcar_mipi_dsi_pll_calc(struct rcar_mipi_dsi *dsi, + unsigned long fin_rate, + unsigned long fout_target, + struct dsi_setup_info *setup_info) +{ + unsigned int best_err = -1; + const struct rcar_mipi_dsi_device_info *info = dsi->info; + + for (unsigned int n = info->n_min; n <= info->n_max; n++) { + unsigned long fpfd; + + fpfd = fin_rate / n; + + if (fpfd < info->fpfd_min || fpfd > info->fpfd_max) + continue; + + for (unsigned int m = info->m_min; m <= info->m_max; m++) { + unsigned int err; + u64 fout; + + fout = div64_u64((u64)fpfd * m, dsi->info->n_mul); + + if (fout < info->fout_min || fout > info->fout_max) + continue; + + fout = div64_u64(fout, setup_info->vclk_divider); + + if (fout < setup_info->clkset->min_freq || + fout > setup_info->clkset->max_freq) + continue; + + err = abs((long)(fout - fout_target) * 10000 / + (long)fout_target); + if (err < best_err) { + setup_info->m = m; + setup_info->n = n; + setup_info->fout = (unsigned long)fout; + best_err = err; + + if (err == 0) + return; + } + } + } +} static void rcar_mipi_dsi_parameters_calc(struct rcar_mipi_dsi *dsi, struct clk *clk, unsigned long target, struct dsi_setup_info *setup_info) { - const struct vco_cntrl_value *vco_cntrl; + const struct dsi_clk_config *clk_cfg; unsigned long fout_target; - unsigned long fin, fout; - unsigned long hsfreq; - unsigned int best_err = -1; - unsigned int divider; - unsigned int n; + unsigned long fin_rate; unsigned int i; unsigned int err; @@ -198,70 +397,53 @@ static void rcar_mipi_dsi_parameters_calc(struct rcar_mipi_dsi *dsi, */ fout_target = target * mipi_dsi_pixel_format_to_bpp(dsi->format) / (2 * dsi->lanes); - if (fout_target < 40000000 || fout_target > 1250000000) + if (fout_target < MHZ(40) || fout_target > MHZ(1250)) return; - /* Find vco_cntrl */ - for (vco_cntrl = vco_cntrl_table; vco_cntrl->min_freq != 0; vco_cntrl++) { - if (fout_target > vco_cntrl->min_freq && - fout_target <= vco_cntrl->max_freq) { - setup_info->vco_cntrl = vco_cntrl->value; - if (fout_target >= 1150000000) - setup_info->prop_cntrl = 0x0c; - else - setup_info->prop_cntrl = 0x0b; + /* Find PLL settings */ + for (clk_cfg = dsi->info->clk_cfg; clk_cfg->min_freq != 0; clk_cfg++) { + if (fout_target > clk_cfg->min_freq && + fout_target <= clk_cfg->max_freq) { + setup_info->clkset = clk_cfg; break; } } - /* Add divider */ - setup_info->div = (setup_info->vco_cntrl & 0x30) >> 4; + fin_rate = clk_get_rate(clk); + + switch (dsi->info->model) { + case RCAR_DSI_V3U: + default: + setup_info->vclk_divider = 1 << ((clk_cfg->vco_cntrl >> 4) & 0x3); + break; + + case RCAR_DSI_V4H: + setup_info->vclk_divider = 1 << (((clk_cfg->vco_cntrl >> 3) & 0x7) + 1); + break; + } + + rcar_mipi_dsi_pll_calc(dsi, fin_rate, fout_target, setup_info); /* Find hsfreqrange */ - hsfreq = fout_target * 2; + setup_info->hsfreq = setup_info->fout * 2; for (i = 0; i < ARRAY_SIZE(hsfreqrange_table); i++) { - if (hsfreqrange_table[i][0] >= hsfreq) { + if (hsfreqrange_table[i][0] >= setup_info->hsfreq) { setup_info->hsfreqrange = hsfreqrange_table[i][1]; break; } } - /* - * Calculate n and m for PLL clock - * Following the HW manual the ranges of n and m are - * n = [3-8] and m = [64-625] - */ - fin = clk_get_rate(clk); - divider = 1 << setup_info->div; - for (n = 3; n < 9; n++) { - unsigned long fpfd; - unsigned int m; - - fpfd = fin / n; - - for (m = 64; m < 626; m++) { - fout = fpfd * m / divider; - err = abs((long)(fout - fout_target) * 10000 / - (long)fout_target); - if (err < best_err) { - setup_info->m = m - 2; - setup_info->n = n - 1; - setup_info->fout = fout; - best_err = err; - if (err == 0) - goto done; - } - } - } + err = abs((long)(setup_info->fout - fout_target) * 10000 / (long)fout_target); -done: dev_dbg(dsi->dev, - "%pC %lu Hz -> Fout %lu Hz (target %lu Hz, error %d.%02u%%), PLL M/N/DIV %u/%u/%u\n", - clk, fin, setup_info->fout, fout_target, best_err / 100, - best_err % 100, setup_info->m, setup_info->n, setup_info->div); + "Fout = %u * %lu / (%u * %u * %u) = %lu (target %lu Hz, error %d.%02u%%)\n", + setup_info->m, fin_rate, dsi->info->n_mul, setup_info->n, + setup_info->vclk_divider, setup_info->fout, fout_target, + err / 100, err % 100); + dev_dbg(dsi->dev, "vco_cntrl = 0x%x\tprop_cntrl = 0x%x\thsfreqrange = 0x%x\n", - setup_info->vco_cntrl, setup_info->prop_cntrl, + clk_cfg->vco_cntrl, clk_cfg->prop_cntrl, setup_info->hsfreqrange); } @@ -324,7 +506,7 @@ static int rcar_mipi_dsi_startup(struct rcar_mipi_dsi *dsi, { struct dsi_setup_info setup_info = {}; unsigned int timeout; - int ret, i; + int ret; int dsi_format; u32 phy_setup; u32 clockset2, clockset3; @@ -360,10 +542,19 @@ static int rcar_mipi_dsi_startup(struct rcar_mipi_dsi *dsi, phy_setup |= PHYSETUP_HSFREQRANGE(setup_info.hsfreqrange); rcar_mipi_dsi_write(dsi, PHYSETUP, phy_setup); - for (i = 0; i < ARRAY_SIZE(phtw); i++) { - ret = rcar_mipi_dsi_phtw_test(dsi, phtw[i]); + switch (dsi->info->model) { + case RCAR_DSI_V3U: + default: + ret = rcar_mipi_dsi_init_phtw_v3u(dsi); if (ret < 0) return ret; + break; + + case RCAR_DSI_V4H: + ret = rcar_mipi_dsi_init_phtw_v4h(dsi, &setup_info); + if (ret < 0) + return ret; + break; } /* PLL Clock Setting */ @@ -371,12 +562,13 @@ static int rcar_mipi_dsi_startup(struct rcar_mipi_dsi *dsi, rcar_mipi_dsi_set(dsi, CLOCKSET1, CLOCKSET1_SHADOW_CLEAR); rcar_mipi_dsi_clr(dsi, CLOCKSET1, CLOCKSET1_SHADOW_CLEAR); - clockset2 = CLOCKSET2_M(setup_info.m) | CLOCKSET2_N(setup_info.n) - | CLOCKSET2_VCO_CNTRL(setup_info.vco_cntrl); - clockset3 = CLOCKSET3_PROP_CNTRL(setup_info.prop_cntrl) - | CLOCKSET3_INT_CNTRL(0) - | CLOCKSET3_CPBIAS_CNTRL(0x10) - | CLOCKSET3_GMP_CNTRL(1); + clockset2 = CLOCKSET2_M(setup_info.m - dsi->info->clockset2_m_offset) + | CLOCKSET2_N(setup_info.n - 1) + | CLOCKSET2_VCO_CNTRL(setup_info.clkset->vco_cntrl); + clockset3 = CLOCKSET3_PROP_CNTRL(setup_info.clkset->prop_cntrl) + | CLOCKSET3_INT_CNTRL(setup_info.clkset->int_cntrl) + | CLOCKSET3_CPBIAS_CNTRL(setup_info.clkset->cpbias_cntrl) + | CLOCKSET3_GMP_CNTRL(setup_info.clkset->gmp_cntrl); rcar_mipi_dsi_write(dsi, CLOCKSET2, clockset2); rcar_mipi_dsi_write(dsi, CLOCKSET3, clockset3); @@ -407,10 +599,19 @@ static int rcar_mipi_dsi_startup(struct rcar_mipi_dsi *dsi, return -ETIMEDOUT; } - for (i = 0; i < ARRAY_SIZE(phtw2); i++) { - ret = rcar_mipi_dsi_phtw_test(dsi, phtw2[i]); + switch (dsi->info->model) { + case RCAR_DSI_V3U: + default: + ret = rcar_mipi_dsi_post_init_phtw_v3u(dsi); + if (ret < 0) + return ret; + break; + + case RCAR_DSI_V4H: + ret = rcar_mipi_dsi_post_init_phtw_v4h(dsi, &setup_info); if (ret < 0) return ret; + break; } /* Enable DOT clock */ @@ -427,8 +628,19 @@ static int rcar_mipi_dsi_startup(struct rcar_mipi_dsi *dsi, dev_warn(dsi->dev, "unsupported format"); return -EINVAL; } - vclkset |= VCLKSET_COLOR_RGB | VCLKSET_DIV(setup_info.div) - | VCLKSET_LANE(dsi->lanes - 1); + + vclkset |= VCLKSET_COLOR_RGB | VCLKSET_LANE(dsi->lanes - 1); + + switch (dsi->info->model) { + case RCAR_DSI_V3U: + default: + vclkset |= VCLKSET_DIV_V3U(__ffs(setup_info.vclk_divider)); + break; + + case RCAR_DSI_V4H: + vclkset |= VCLKSET_DIV_V4H(__ffs(setup_info.vclk_divider) - 1); + break; + } rcar_mipi_dsi_write(dsi, VCLKSET, vclkset); @@ -841,8 +1053,39 @@ static int rcar_mipi_dsi_remove(struct platform_device *pdev) return 0; } +static const struct rcar_mipi_dsi_device_info v3u_data = { + .model = RCAR_DSI_V3U, + .clk_cfg = dsi_clk_cfg_v3u, + .clockset2_m_offset = 2, + .n_min = 3, + .n_max = 8, + .n_mul = 1, + .fpfd_min = MHZ(2), + .fpfd_max = MHZ(8), + .m_min = 64, + .m_max = 625, + .fout_min = MHZ(320), + .fout_max = MHZ(1250), +}; + +static const struct rcar_mipi_dsi_device_info v4h_data = { + .model = RCAR_DSI_V4H, + .clk_cfg = dsi_clk_cfg_v4h, + .clockset2_m_offset = 0, + .n_min = 1, + .n_max = 8, + .n_mul = 2, + .fpfd_min = MHZ(8), + .fpfd_max = MHZ(24), + .m_min = 167, + .m_max = 1000, + .fout_min = MHZ(2000), + .fout_max = MHZ(4000), +}; + static const struct of_device_id rcar_mipi_dsi_of_table[] = { - { .compatible = "renesas,r8a779a0-dsi-csi2-tx" }, + { .compatible = "renesas,r8a779a0-dsi-csi2-tx", .data = &v3u_data }, + { .compatible = "renesas,r8a779g0-dsi-csi2-tx", .data = &v4h_data }, { } }; diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h index 2eaca54636f3..f8114d11f2d1 100644 --- a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h +++ b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h @@ -122,7 +122,8 @@ #define VCLKSET_CKEN (1 << 16) #define VCLKSET_COLOR_RGB (0 << 8) #define VCLKSET_COLOR_YCC (1 << 8) -#define VCLKSET_DIV(x) (((x) & 0x3) << 4) +#define VCLKSET_DIV_V3U(x) (((x) & 0x3) << 4) +#define VCLKSET_DIV_V4H(x) (((x) & 0x7) << 4) #define VCLKSET_BPP_16 (0 << 2) #define VCLKSET_BPP_18 (1 << 2) #define VCLKSET_BPP_18L (2 << 2) @@ -166,6 +167,9 @@ #define PHTW_CWEN (1 << 8) #define PHTW_TESTDIN_CODE(x) (((x) & 0xff) << 0) +#define PHTR 0x1038 +#define PHTR_TEST (1 << 16) + #define PHTC 0x103c #define PHTC_TESTCLR (1 << 0) diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c index 7dc681e2ee90..3c84e73d5051 100644 --- a/drivers/gpu/drm/tegra/dpaux.c +++ b/drivers/gpu/drm/tegra/dpaux.c @@ -598,7 +598,6 @@ static int tegra_dpaux_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM static int tegra_dpaux_suspend(struct device *dev) { struct tegra_dpaux *dpaux = dev_get_drvdata(dev); @@ -657,10 +656,9 @@ disable_clk: clk_disable_unprepare(dpaux->clk); return err; } -#endif static const struct dev_pm_ops tegra_dpaux_pm_ops = { - SET_RUNTIME_PM_OPS(tegra_dpaux_suspend, tegra_dpaux_resume, NULL) + RUNTIME_PM_OPS(tegra_dpaux_suspend, tegra_dpaux_resume, NULL) }; static const struct tegra_dpaux_soc tegra124_dpaux_soc = { @@ -694,7 +692,7 @@ struct platform_driver tegra_dpaux_driver = { .driver = { .name = "tegra-dpaux", .of_match_table = tegra_dpaux_of_match, - .pm = &tegra_dpaux_pm_ops, + .pm = pm_ptr(&tegra_dpaux_pm_ops), }, .probe = tegra_dpaux_probe, .remove = tegra_dpaux_remove, diff --git a/drivers/gpu/drm/tegra/firewall.c b/drivers/gpu/drm/tegra/firewall.c index 1824d2db0e2c..d53f890fa689 100644 --- a/drivers/gpu/drm/tegra/firewall.c +++ b/drivers/gpu/drm/tegra/firewall.c @@ -97,6 +97,9 @@ static int fw_check_regs_imm(struct tegra_drm_firewall *fw, u32 offset) { bool is_addr; + if (!fw->client->ops->is_addr_reg) + return 0; + is_addr = fw->client->ops->is_addr_reg(fw->client->base.dev, fw->class, offset); if (is_addr) diff --git a/drivers/gpu/drm/tegra/nvdec.c b/drivers/gpu/drm/tegra/nvdec.c index 10fd21517281..86c5818ac27b 100644 --- a/drivers/gpu/drm/tegra/nvdec.c +++ b/drivers/gpu/drm/tegra/nvdec.c @@ -67,26 +67,18 @@ static inline void nvdec_writel(struct nvdec *nvdec, u32 value, static int nvdec_boot_falcon(struct nvdec *nvdec) { -#ifdef CONFIG_IOMMU_API - struct iommu_fwspec *spec = dev_iommu_fwspec_get(nvdec->dev); -#endif + u32 stream_id; int err; -#ifdef CONFIG_IOMMU_API - if (nvdec->config->supports_sid && spec) { + if (nvdec->config->supports_sid && tegra_dev_iommu_get_stream_id(nvdec->dev, &stream_id)) { u32 value; value = TRANSCFG_ATT(1, TRANSCFG_SID_FALCON) | TRANSCFG_ATT(0, TRANSCFG_SID_HW); nvdec_writel(nvdec, value, NVDEC_TFBIF_TRANSCFG); - if (spec->num_ids > 0) { - value = spec->ids[0] & 0xffff; - - nvdec_writel(nvdec, value, VIC_THI_STREAMID0); - nvdec_writel(nvdec, value, VIC_THI_STREAMID1); - } + nvdec_writel(nvdec, stream_id, VIC_THI_STREAMID0); + nvdec_writel(nvdec, stream_id, VIC_THI_STREAMID1); } -#endif err = falcon_boot(&nvdec->falcon); if (err < 0) diff --git a/drivers/gpu/drm/tegra/submit.c b/drivers/gpu/drm/tegra/submit.c index 066f88564169..2430fcc97448 100644 --- a/drivers/gpu/drm/tegra/submit.c +++ b/drivers/gpu/drm/tegra/submit.c @@ -609,21 +609,13 @@ int tegra_drm_ioctl_channel_submit(struct drm_device *drm, void *data, host1x_memory_context_get(job->memory_context); } } else if (context->client->ops->get_streamid_offset) { -#ifdef CONFIG_IOMMU_API - struct iommu_fwspec *spec; - /* * Job submission will need to temporarily change stream ID, * so need to tell it what to change it back to. */ - spec = dev_iommu_fwspec_get(context->client->base.dev); - if (spec && spec->num_ids > 0) - job->engine_fallback_streamid = spec->ids[0] & 0xffff; - else - job->engine_fallback_streamid = 0x7f; -#else - job->engine_fallback_streamid = 0x7f; -#endif + if (!tegra_dev_iommu_get_stream_id(context->client->base.dev, + &job->engine_fallback_streamid)) + job->engine_fallback_streamid = TEGRA_STREAM_ID_BYPASS; } /* Boot engine. */ @@ -654,7 +646,7 @@ int tegra_drm_ioctl_channel_submit(struct drm_device *drm, void *data, args->syncpt.value = job->syncpt_end; if (syncobj) { - struct dma_fence *fence = host1x_fence_create(job->syncpt, job->syncpt_end); + struct dma_fence *fence = host1x_fence_create(job->syncpt, job->syncpt_end, true); if (IS_ERR(fence)) { err = PTR_ERR(fence); SUBMIT_ERR(context, "failed to create postfence: %d", err); @@ -680,8 +672,7 @@ free_job_data: kfree(job_data->used_mappings); } - if (job_data) - kfree(job_data); + kfree(job_data); put_bo: gather_bo_put(&bo->base); unlock: diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c index 7382ee132eb7..531a71c72061 100644 --- a/drivers/gpu/drm/tegra/vic.c +++ b/drivers/gpu/drm/tegra/vic.c @@ -56,41 +56,30 @@ static void vic_writel(struct vic *vic, u32 value, unsigned int offset) static int vic_boot(struct vic *vic) { -#ifdef CONFIG_IOMMU_API - struct iommu_fwspec *spec = dev_iommu_fwspec_get(vic->dev); -#endif - u32 fce_ucode_size, fce_bin_data_offset; + u32 fce_ucode_size, fce_bin_data_offset, stream_id; void *hdr; int err = 0; -#ifdef CONFIG_IOMMU_API - if (vic->config->supports_sid && spec) { + if (vic->config->supports_sid && tegra_dev_iommu_get_stream_id(vic->dev, &stream_id)) { u32 value; value = TRANSCFG_ATT(1, TRANSCFG_SID_FALCON) | TRANSCFG_ATT(0, TRANSCFG_SID_HW); vic_writel(vic, value, VIC_TFBIF_TRANSCFG); - if (spec->num_ids > 0) { - value = spec->ids[0] & 0xffff; - - /* - * STREAMID0 is used for input/output buffers. - * Initialize it to SID_VIC in case context isolation - * is not enabled, and SID_VIC is used for both firmware - * and data buffers. - * - * If context isolation is enabled, it will be - * overridden by the SETSTREAMID opcode as part of - * each job. - */ - vic_writel(vic, value, VIC_THI_STREAMID0); - - /* STREAMID1 is used for firmware loading. */ - vic_writel(vic, value, VIC_THI_STREAMID1); - } + /* + * STREAMID0 is used for input/output buffers. Initialize it to SID_VIC in case + * context isolation is not enabled, and SID_VIC is used for both firmware and + * data buffers. + * + * If context isolation is enabled, it will be overridden by the SETSTREAMID + * opcode as part of each job. + */ + vic_writel(vic, stream_id, VIC_THI_STREAMID0); + + /* STREAMID1 is used for firmware loading. */ + vic_writel(vic, stream_id, VIC_THI_STREAMID1); } -#endif /* setup clockgating registers */ vic_writel(vic, CG_IDLE_CG_DLY_CNT(4) | diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile index aaf357e29c65..bca726a8f483 100644 --- a/drivers/gpu/drm/tests/Makefile +++ b/drivers/gpu/drm/tests/Makefile @@ -18,3 +18,5 @@ obj-$(CONFIG_DRM_KUNIT_TEST) += \ drm_plane_helper_test.o \ drm_probe_helper_test.o \ drm_rect_test.o + +CFLAGS_drm_mm_test.o := $(DISABLE_STRUCTLEAK_PLUGIN) diff --git a/drivers/gpu/drm/tests/drm_mm_test.c b/drivers/gpu/drm/tests/drm_mm_test.c index 89f12d3b4a21..186b28dc7038 100644 --- a/drivers/gpu/drm/tests/drm_mm_test.c +++ b/drivers/gpu/drm/tests/drm_mm_test.c @@ -298,9 +298,9 @@ static bool expect_reserve_fail(struct kunit *test, struct drm_mm *mm, struct dr return false; } -static bool check_reserve_boundaries(struct kunit *test, struct drm_mm *mm, - unsigned int count, - u64 size) +static bool noinline_for_stack check_reserve_boundaries(struct kunit *test, struct drm_mm *mm, + unsigned int count, + u64 size) { const struct boundary { u64 start, size; diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index fca8b0e0e30a..7635d7d6b13b 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -184,7 +184,7 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, clear = src_iter->ops->maps_tt && (!ttm || !ttm_tt_is_populated(ttm)); if (!(clear && ttm && !(ttm->page_flags & TTM_TT_FLAG_ZERO_ALLOC))) - ttm_move_memcpy(clear, ttm->num_pages, dst_iter, src_iter); + ttm_move_memcpy(clear, PFN_UP(dst_mem->size), dst_iter, src_iter); if (!src_iter->ops->maps_tt) ttm_kmap_iter_linear_io_fini(&_src_iter.io, bdev, src_mem); diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c index c2b7573bd92b..86d629e45307 100644 --- a/drivers/gpu/drm/vc4/vc4_bo.c +++ b/drivers/gpu/drm/vc4/vc4_bo.c @@ -179,6 +179,7 @@ static void vc4_bo_destroy(struct vc4_bo *bo) bo->validated_shader = NULL; } + mutex_destroy(&bo->madv_lock); drm_gem_dma_free(&bo->base); } @@ -394,7 +395,6 @@ struct drm_gem_object *vc4_create_object(struct drm_device *dev, size_t size) { struct vc4_dev *vc4 = to_vc4_dev(dev); struct vc4_bo *bo; - int ret; if (WARN_ON_ONCE(vc4->is_vc5)) return ERR_PTR(-ENODEV); @@ -406,9 +406,7 @@ struct drm_gem_object *vc4_create_object(struct drm_device *dev, size_t size) bo->madv = VC4_MADV_WILLNEED; refcount_set(&bo->usecnt, 0); - ret = drmm_mutex_init(dev, &bo->madv_lock); - if (ret) - return ERR_PTR(ret); + mutex_init(&bo->madv_lock); mutex_lock(&vc4->bo_lock); bo->label = VC4_BO_TYPE_KERNEL; diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c index 5d05093014ac..9f4a90493aea 100644 --- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c +++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c @@ -358,10 +358,18 @@ static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data, drm_gem_object_release(obj); return ret; } - drm_gem_object_put(obj); rc->res_handle = qobj->hw_res_handle; /* similiar to a VM address */ rc->bo_handle = handle; + + /* + * The handle owns the reference now. But we must drop our + * remaining reference *after* we no longer need to dereference + * the obj. Otherwise userspace could guess the handle and + * race closing it from another thread. + */ + drm_gem_object_put(obj); + return 0; } @@ -723,11 +731,18 @@ static int virtio_gpu_resource_create_blob_ioctl(struct drm_device *dev, drm_gem_object_release(obj); return ret; } - drm_gem_object_put(obj); rc_blob->res_handle = bo->hw_res_handle; rc_blob->bo_handle = handle; + /* + * The handle owns the reference now. But we must drop our + * remaining reference *after* we no longer need to dereference + * the obj. Otherwise userspace could guess the handle and + * race closing it from another thread. + */ + drm_gem_object_put(obj); + return 0; } diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c index 8d7728181de0..c7e74cf13022 100644 --- a/drivers/gpu/drm/virtio/virtgpu_object.c +++ b/drivers/gpu/drm/virtio/virtgpu_object.c @@ -184,7 +184,7 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev, struct virtio_gpu_object_array *objs = NULL; struct drm_gem_shmem_object *shmem_obj; struct virtio_gpu_object *bo; - struct virtio_gpu_mem_entry *ents; + struct virtio_gpu_mem_entry *ents = NULL; unsigned int nents; int ret; @@ -210,7 +210,7 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev, ret = -ENOMEM; objs = virtio_gpu_array_alloc(1); if (!objs) - goto err_put_id; + goto err_free_entry; virtio_gpu_array_add_obj(objs, &bo->base.base); ret = virtio_gpu_array_lock_resv(objs); @@ -239,6 +239,8 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev, err_put_objs: virtio_gpu_array_put_free(objs); +err_free_entry: + kvfree(ents); err_put_id: virtio_gpu_resource_id_put(vgdev, bo->hw_res_handle); err_free_gem: diff --git a/drivers/gpu/drm/vmwgfx/ttm_object.c b/drivers/gpu/drm/vmwgfx/ttm_object.c index 932b125ebf3d..ddf8373c1d77 100644 --- a/drivers/gpu/drm/vmwgfx/ttm_object.c +++ b/drivers/gpu/drm/vmwgfx/ttm_object.c @@ -254,40 +254,6 @@ void ttm_base_object_unref(struct ttm_base_object **p_base) kref_put(&base->refcount, ttm_release_base); } -/** - * ttm_base_object_noref_lookup - look up a base object without reference - * @tfile: The struct ttm_object_file the object is registered with. - * @key: The object handle. - * - * This function looks up a ttm base object and returns a pointer to it - * without refcounting the pointer. The returned pointer is only valid - * until ttm_base_object_noref_release() is called, and the object - * pointed to by the returned pointer may be doomed. Any persistent usage - * of the object requires a refcount to be taken using kref_get_unless_zero(). - * Iff this function returns successfully it needs to be paired with - * ttm_base_object_noref_release() and no sleeping- or scheduling functions - * may be called inbetween these function callse. - * - * Return: A pointer to the object if successful or NULL otherwise. - */ -struct ttm_base_object * -ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint64_t key) -{ - struct vmwgfx_hash_item *hash; - int ret; - - rcu_read_lock(); - ret = ttm_tfile_find_ref_rcu(tfile, key, &hash); - if (ret) { - rcu_read_unlock(); - return NULL; - } - - __release(RCU); - return hlist_entry(hash, struct ttm_ref_object, hash)->obj; -} -EXPORT_SYMBOL(ttm_base_object_noref_lookup); - struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile, uint64_t key) { @@ -295,15 +261,16 @@ struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile, struct vmwgfx_hash_item *hash; int ret; - rcu_read_lock(); - ret = ttm_tfile_find_ref_rcu(tfile, key, &hash); + spin_lock(&tfile->lock); + ret = ttm_tfile_find_ref(tfile, key, &hash); if (likely(ret == 0)) { base = hlist_entry(hash, struct ttm_ref_object, hash)->obj; if (!kref_get_unless_zero(&base->refcount)) base = NULL; } - rcu_read_unlock(); + spin_unlock(&tfile->lock); + return base; } diff --git a/drivers/gpu/drm/vmwgfx/ttm_object.h b/drivers/gpu/drm/vmwgfx/ttm_object.h index 95a9679f9d39..e6b77ee33e55 100644 --- a/drivers/gpu/drm/vmwgfx/ttm_object.h +++ b/drivers/gpu/drm/vmwgfx/ttm_object.h @@ -309,21 +309,6 @@ extern int ttm_prime_handle_to_fd(struct ttm_object_file *tfile, #define ttm_prime_object_kfree(__obj, __prime) \ kfree_rcu(__obj, __prime.base.rhead) -struct ttm_base_object * -ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint64_t key); - -/** - * ttm_base_object_noref_release - release a base object pointer looked up - * without reference - * - * Releases a base object pointer looked up with ttm_base_object_noref_lookup(). - */ -static inline void ttm_base_object_noref_release(void) -{ - __acquire(RCU); - rcu_read_unlock(); -} - static inline int ttm_bo_wait(struct ttm_buffer_object *bo, bool intr, bool no_wait) { diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c index 321c551784a1..aa1cd5126a32 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c @@ -716,44 +716,6 @@ int vmw_user_bo_lookup(struct drm_file *filp, } /** - * vmw_user_bo_noref_lookup - Look up a vmw user buffer object without reference - * @filp: The TTM object file the handle is registered with. - * @handle: The user buffer object handle. - * - * This function looks up a struct vmw_bo and returns a pointer to the - * struct vmw_buffer_object it derives from without refcounting the pointer. - * The returned pointer is only valid until vmw_user_bo_noref_release() is - * called, and the object pointed to by the returned pointer may be doomed. - * Any persistent usage of the object requires a refcount to be taken using - * ttm_bo_reference_unless_doomed(). Iff this function returns successfully it - * needs to be paired with vmw_user_bo_noref_release() and no sleeping- - * or scheduling functions may be called in between these function calls. - * - * Return: A struct vmw_buffer_object pointer if successful or negative - * error pointer on failure. - */ -struct vmw_buffer_object * -vmw_user_bo_noref_lookup(struct drm_file *filp, u32 handle) -{ - struct vmw_buffer_object *vmw_bo; - struct ttm_buffer_object *bo; - struct drm_gem_object *gobj = drm_gem_object_lookup(filp, handle); - - if (!gobj) { - DRM_ERROR("Invalid buffer object handle 0x%08lx.\n", - (unsigned long)handle); - return ERR_PTR(-ESRCH); - } - vmw_bo = gem_to_vmw_bo(gobj); - bo = ttm_bo_get_unless_zero(&vmw_bo->base); - vmw_bo = vmw_buffer_object(bo); - drm_gem_object_put(gobj); - - return vmw_bo; -} - - -/** * vmw_bo_fence_single - Utility function to fence a single TTM buffer * object without unreserving it. * diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 4b612fc9758c..203fa32cd4c1 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -832,12 +832,7 @@ extern int vmw_user_resource_lookup_handle( uint32_t handle, const struct vmw_user_resource_conv *converter, struct vmw_resource **p_res); -extern struct vmw_resource * -vmw_user_resource_noref_lookup_handle(struct vmw_private *dev_priv, - struct ttm_object_file *tfile, - uint32_t handle, - const struct vmw_user_resource_conv * - converter); + extern int vmw_stream_claim_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int vmw_stream_unref_ioctl(struct drm_device *dev, void *data, @@ -877,15 +872,6 @@ static inline bool vmw_resource_mob_attached(const struct vmw_resource *res) } /** - * vmw_user_resource_noref_release - release a user resource pointer looked up - * without reference - */ -static inline void vmw_user_resource_noref_release(void) -{ - ttm_base_object_noref_release(); -} - -/** * Buffer object helper functions - vmwgfx_bo.c */ extern int vmw_bo_pin_in_placement(struct vmw_private *vmw_priv, @@ -936,8 +922,6 @@ extern void vmw_bo_unmap(struct vmw_buffer_object *vbo); extern void vmw_bo_move_notify(struct ttm_buffer_object *bo, struct ttm_resource *mem); extern void vmw_bo_swap_notify(struct ttm_buffer_object *bo); -extern struct vmw_buffer_object * -vmw_user_bo_noref_lookup(struct drm_file *filp, u32 handle); /** * vmw_bo_adjust_prio - Adjust the buffer object eviction priority diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 43cec8e37e4d..9359e8dfbac2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -290,20 +290,26 @@ static void vmw_execbuf_rcache_update(struct vmw_res_cache_entry *rcache, rcache->valid_handle = 0; } +enum vmw_val_add_flags { + vmw_val_add_flag_none = 0, + vmw_val_add_flag_noctx = 1 << 0, +}; + /** - * vmw_execbuf_res_noref_val_add - Add a resource described by an unreferenced - * rcu-protected pointer to the validation list. + * vmw_execbuf_res_val_add - Add a resource to the validation list. * * @sw_context: Pointer to the software context. * @res: Unreferenced rcu-protected pointer to the resource. * @dirty: Whether to change dirty status. + * @flags: specifies whether to use the context or not * * Returns: 0 on success. Negative error code on failure. Typical error codes * are %-EINVAL on inconsistency and %-ESRCH if the resource was doomed. */ -static int vmw_execbuf_res_noref_val_add(struct vmw_sw_context *sw_context, - struct vmw_resource *res, - u32 dirty) +static int vmw_execbuf_res_val_add(struct vmw_sw_context *sw_context, + struct vmw_resource *res, + u32 dirty, + u32 flags) { struct vmw_private *dev_priv = res->dev_priv; int ret; @@ -318,24 +324,30 @@ static int vmw_execbuf_res_noref_val_add(struct vmw_sw_context *sw_context, if (dirty) vmw_validation_res_set_dirty(sw_context->ctx, rcache->private, dirty); - vmw_user_resource_noref_release(); return 0; } - priv_size = vmw_execbuf_res_size(dev_priv, res_type); - ret = vmw_validation_add_resource(sw_context->ctx, res, priv_size, - dirty, (void **)&ctx_info, - &first_usage); - vmw_user_resource_noref_release(); - if (ret) - return ret; + if ((flags & vmw_val_add_flag_noctx) != 0) { + ret = vmw_validation_add_resource(sw_context->ctx, res, 0, dirty, + (void **)&ctx_info, NULL); + if (ret) + return ret; - if (priv_size && first_usage) { - ret = vmw_cmd_ctx_first_setup(dev_priv, sw_context, res, - ctx_info); - if (ret) { - VMW_DEBUG_USER("Failed first usage context setup.\n"); + } else { + priv_size = vmw_execbuf_res_size(dev_priv, res_type); + ret = vmw_validation_add_resource(sw_context->ctx, res, priv_size, + dirty, (void **)&ctx_info, + &first_usage); + if (ret) return ret; + + if (priv_size && first_usage) { + ret = vmw_cmd_ctx_first_setup(dev_priv, sw_context, res, + ctx_info); + if (ret) { + VMW_DEBUG_USER("Failed first usage context setup.\n"); + return ret; + } } } @@ -344,43 +356,6 @@ static int vmw_execbuf_res_noref_val_add(struct vmw_sw_context *sw_context, } /** - * vmw_execbuf_res_noctx_val_add - Add a non-context resource to the resource - * validation list if it's not already on it - * - * @sw_context: Pointer to the software context. - * @res: Pointer to the resource. - * @dirty: Whether to change dirty status. - * - * Returns: Zero on success. Negative error code on failure. - */ -static int vmw_execbuf_res_noctx_val_add(struct vmw_sw_context *sw_context, - struct vmw_resource *res, - u32 dirty) -{ - struct vmw_res_cache_entry *rcache; - enum vmw_res_type res_type = vmw_res_type(res); - void *ptr; - int ret; - - rcache = &sw_context->res_cache[res_type]; - if (likely(rcache->valid && rcache->res == res)) { - if (dirty) - vmw_validation_res_set_dirty(sw_context->ctx, - rcache->private, dirty); - return 0; - } - - ret = vmw_validation_add_resource(sw_context->ctx, res, 0, dirty, - &ptr, NULL); - if (ret) - return ret; - - vmw_execbuf_rcache_update(rcache, res, ptr); - - return 0; -} - -/** * vmw_view_res_val_add - Add a view and the surface it's pointing to to the * validation list * @@ -398,13 +373,13 @@ static int vmw_view_res_val_add(struct vmw_sw_context *sw_context, * First add the resource the view is pointing to, otherwise it may be * swapped out when the view is validated. */ - ret = vmw_execbuf_res_noctx_val_add(sw_context, vmw_view_srf(view), - vmw_view_dirtying(view)); + ret = vmw_execbuf_res_val_add(sw_context, vmw_view_srf(view), + vmw_view_dirtying(view), vmw_val_add_flag_noctx); if (ret) return ret; - return vmw_execbuf_res_noctx_val_add(sw_context, view, - VMW_RES_DIRTY_NONE); + return vmw_execbuf_res_val_add(sw_context, view, VMW_RES_DIRTY_NONE, + vmw_val_add_flag_noctx); } /** @@ -475,8 +450,9 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv, if (IS_ERR(res)) continue; - ret = vmw_execbuf_res_noctx_val_add(sw_context, res, - VMW_RES_DIRTY_SET); + ret = vmw_execbuf_res_val_add(sw_context, res, + VMW_RES_DIRTY_SET, + vmw_val_add_flag_noctx); if (unlikely(ret != 0)) return ret; } @@ -490,9 +466,9 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv, if (vmw_res_type(entry->res) == vmw_res_view) ret = vmw_view_res_val_add(sw_context, entry->res); else - ret = vmw_execbuf_res_noctx_val_add - (sw_context, entry->res, - vmw_binding_dirtying(entry->bt)); + ret = vmw_execbuf_res_val_add(sw_context, entry->res, + vmw_binding_dirtying(entry->bt), + vmw_val_add_flag_noctx); if (unlikely(ret != 0)) break; } @@ -658,7 +634,8 @@ vmw_cmd_res_check(struct vmw_private *dev_priv, { struct vmw_res_cache_entry *rcache = &sw_context->res_cache[res_type]; struct vmw_resource *res; - int ret; + int ret = 0; + bool needs_unref = false; if (p_res) *p_res = NULL; @@ -683,17 +660,18 @@ vmw_cmd_res_check(struct vmw_private *dev_priv, if (ret) return ret; - res = vmw_user_resource_noref_lookup_handle - (dev_priv, sw_context->fp->tfile, *id_loc, converter); - if (IS_ERR(res)) { + ret = vmw_user_resource_lookup_handle + (dev_priv, sw_context->fp->tfile, *id_loc, converter, &res); + if (ret != 0) { VMW_DEBUG_USER("Could not find/use resource 0x%08x.\n", (unsigned int) *id_loc); - return PTR_ERR(res); + return ret; } + needs_unref = true; - ret = vmw_execbuf_res_noref_val_add(sw_context, res, dirty); + ret = vmw_execbuf_res_val_add(sw_context, res, dirty, vmw_val_add_flag_none); if (unlikely(ret != 0)) - return ret; + goto res_check_done; if (rcache->valid && rcache->res == res) { rcache->valid_handle = true; @@ -708,7 +686,11 @@ vmw_cmd_res_check(struct vmw_private *dev_priv, if (p_res) *p_res = res; - return 0; +res_check_done: + if (needs_unref) + vmw_resource_unreference(&res); + + return ret; } /** @@ -1171,9 +1153,9 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, int ret; vmw_validation_preload_bo(sw_context->ctx); - vmw_bo = vmw_user_bo_noref_lookup(sw_context->filp, handle); - if (IS_ERR(vmw_bo)) { - VMW_DEBUG_USER("Could not find or use MOB buffer.\n"); + ret = vmw_user_bo_lookup(sw_context->filp, handle, &vmw_bo); + if (ret != 0) { + drm_dbg(&dev_priv->drm, "Could not find or use MOB buffer.\n"); return PTR_ERR(vmw_bo); } ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, true, false); @@ -1225,9 +1207,9 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, int ret; vmw_validation_preload_bo(sw_context->ctx); - vmw_bo = vmw_user_bo_noref_lookup(sw_context->filp, handle); - if (IS_ERR(vmw_bo)) { - VMW_DEBUG_USER("Could not find or use GMR region.\n"); + ret = vmw_user_bo_lookup(sw_context->filp, handle, &vmw_bo); + if (ret != 0) { + drm_dbg(&dev_priv->drm, "Could not find or use GMR region.\n"); return PTR_ERR(vmw_bo); } ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, false, false); @@ -2025,8 +2007,9 @@ static int vmw_cmd_set_shader(struct vmw_private *dev_priv, res = vmw_shader_lookup(vmw_context_res_man(ctx), cmd->body.shid, cmd->body.type); if (!IS_ERR(res)) { - ret = vmw_execbuf_res_noctx_val_add(sw_context, res, - VMW_RES_DIRTY_NONE); + ret = vmw_execbuf_res_val_add(sw_context, res, + VMW_RES_DIRTY_NONE, + vmw_val_add_flag_noctx); if (unlikely(ret != 0)) return ret; @@ -2273,8 +2256,9 @@ static int vmw_cmd_dx_set_shader(struct vmw_private *dev_priv, return PTR_ERR(res); } - ret = vmw_execbuf_res_noctx_val_add(sw_context, res, - VMW_RES_DIRTY_NONE); + ret = vmw_execbuf_res_val_add(sw_context, res, + VMW_RES_DIRTY_NONE, + vmw_val_add_flag_noctx); if (ret) return ret; } @@ -2777,8 +2761,8 @@ static int vmw_cmd_dx_bind_shader(struct vmw_private *dev_priv, return PTR_ERR(res); } - ret = vmw_execbuf_res_noctx_val_add(sw_context, res, - VMW_RES_DIRTY_NONE); + ret = vmw_execbuf_res_val_add(sw_context, res, VMW_RES_DIRTY_NONE, + vmw_val_add_flag_noctx); if (ret) { VMW_DEBUG_USER("Error creating resource validation node.\n"); return ret; @@ -3098,8 +3082,8 @@ static int vmw_cmd_dx_bind_streamoutput(struct vmw_private *dev_priv, vmw_dx_streamoutput_set_size(res, cmd->body.sizeInBytes); - ret = vmw_execbuf_res_noctx_val_add(sw_context, res, - VMW_RES_DIRTY_NONE); + ret = vmw_execbuf_res_val_add(sw_context, res, VMW_RES_DIRTY_NONE, + vmw_val_add_flag_noctx); if (ret) { DRM_ERROR("Error creating resource validation node.\n"); return ret; @@ -3148,8 +3132,8 @@ static int vmw_cmd_dx_set_streamoutput(struct vmw_private *dev_priv, return 0; } - ret = vmw_execbuf_res_noctx_val_add(sw_context, res, - VMW_RES_DIRTY_NONE); + ret = vmw_execbuf_res_val_add(sw_context, res, VMW_RES_DIRTY_NONE, + vmw_val_add_flag_noctx); if (ret) { DRM_ERROR("Error creating resource validation node.\n"); return ret; @@ -4066,22 +4050,26 @@ static int vmw_execbuf_tie_context(struct vmw_private *dev_priv, if (ret) return ret; - res = vmw_user_resource_noref_lookup_handle + ret = vmw_user_resource_lookup_handle (dev_priv, sw_context->fp->tfile, handle, - user_context_converter); - if (IS_ERR(res)) { + user_context_converter, &res); + if (ret != 0) { VMW_DEBUG_USER("Could not find or user DX context 0x%08x.\n", (unsigned int) handle); - return PTR_ERR(res); + return ret; } - ret = vmw_execbuf_res_noref_val_add(sw_context, res, VMW_RES_DIRTY_SET); - if (unlikely(ret != 0)) + ret = vmw_execbuf_res_val_add(sw_context, res, VMW_RES_DIRTY_SET, + vmw_val_add_flag_none); + if (unlikely(ret != 0)) { + vmw_resource_unreference(&res); return ret; + } sw_context->dx_ctx_node = vmw_execbuf_info_from_res(sw_context, res); sw_context->man = vmw_context_res_man(res); + vmw_resource_unreference(&res); return 0; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h b/drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h index 4f40167ad61f..4f40167ad61f 100755..100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index f66caa540e14..c7d645e5ec7b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -281,39 +281,6 @@ out_bad_resource: return ret; } -/** - * vmw_user_resource_noref_lookup_handle - lookup a struct resource from a - * TTM user-space handle and perform basic type checks - * - * @dev_priv: Pointer to a device private struct - * @tfile: Pointer to a struct ttm_object_file identifying the caller - * @handle: The TTM user-space handle - * @converter: Pointer to an object describing the resource type - * - * If the handle can't be found or is associated with an incorrect resource - * type, -EINVAL will be returned. - */ -struct vmw_resource * -vmw_user_resource_noref_lookup_handle(struct vmw_private *dev_priv, - struct ttm_object_file *tfile, - uint32_t handle, - const struct vmw_user_resource_conv - *converter) -{ - struct ttm_base_object *base; - - base = ttm_base_object_noref_lookup(tfile, handle); - if (!base) - return ERR_PTR(-ESRCH); - - if (unlikely(ttm_base_object_type(base) != converter->object_type)) { - ttm_base_object_noref_release(); - return ERR_PTR(-EINVAL); - } - - return converter->base_obj_to_res(base); -} - /* * Helper function that looks either a surface or bo. * diff --git a/drivers/gpu/drm/xen/xen_drm_front.c b/drivers/gpu/drm/xen/xen_drm_front.c index 0d8e6bd1ccbf..90996c108146 100644 --- a/drivers/gpu/drm/xen/xen_drm_front.c +++ b/drivers/gpu/drm/xen/xen_drm_front.c @@ -717,7 +717,7 @@ static int xen_drv_probe(struct xenbus_device *xb_dev, return xenbus_switch_state(xb_dev, XenbusStateInitialising); } -static int xen_drv_remove(struct xenbus_device *dev) +static void xen_drv_remove(struct xenbus_device *dev) { struct xen_drm_front_info *front_info = dev_get_drvdata(&dev->dev); int to = 100; @@ -751,7 +751,6 @@ static int xen_drv_remove(struct xenbus_device *dev) xen_drm_drv_fini(front_info); xenbus_frontend_closed(dev); - return 0; } static const struct xenbus_device_id xen_driver_ids[] = { diff --git a/drivers/gpu/host1x/cdma.c b/drivers/gpu/host1x/cdma.c index 103fda055394..bc821b0ed908 100644 --- a/drivers/gpu/host1x/cdma.c +++ b/drivers/gpu/host1x/cdma.c @@ -490,6 +490,15 @@ resume: host1x_hw_cdma_resume(host1x, cdma, restart_addr); } +static void cdma_update_work(struct work_struct *work) +{ + struct host1x_cdma *cdma = container_of(work, struct host1x_cdma, update_work); + + mutex_lock(&cdma->lock); + update_cdma_locked(cdma); + mutex_unlock(&cdma->lock); +} + /* * Create a cdma */ @@ -499,6 +508,7 @@ int host1x_cdma_init(struct host1x_cdma *cdma) mutex_init(&cdma->lock); init_completion(&cdma->complete); + INIT_WORK(&cdma->update_work, cdma_update_work); INIT_LIST_HEAD(&cdma->sync_queue); @@ -679,7 +689,5 @@ void host1x_cdma_end(struct host1x_cdma *cdma, */ void host1x_cdma_update(struct host1x_cdma *cdma) { - mutex_lock(&cdma->lock); - update_cdma_locked(cdma); - mutex_unlock(&cdma->lock); + schedule_work(&cdma->update_work); } diff --git a/drivers/gpu/host1x/cdma.h b/drivers/gpu/host1x/cdma.h index 12c4327c4df0..7fd8168af4f9 100644 --- a/drivers/gpu/host1x/cdma.h +++ b/drivers/gpu/host1x/cdma.h @@ -11,6 +11,7 @@ #include <linux/sched.h> #include <linux/completion.h> #include <linux/list.h> +#include <linux/workqueue.h> struct host1x_syncpt; struct host1x_userctx_timeout; @@ -69,6 +70,7 @@ struct host1x_cdma { struct buffer_timeout timeout; /* channel's timeout state/wq */ bool running; bool torndown; + struct work_struct update_work; }; #define cdma_to_channel(cdma) container_of(cdma, struct host1x_channel, cdma) diff --git a/drivers/gpu/host1x/context.c b/drivers/gpu/host1x/context.c index c8e7994c2c9c..8beedcf080ab 100644 --- a/drivers/gpu/host1x/context.c +++ b/drivers/gpu/host1x/context.c @@ -35,8 +35,6 @@ int host1x_memory_context_list_init(struct host1x *host1x) cdl->len = err / 4; for (i = 0; i < cdl->len; i++) { - struct iommu_fwspec *fwspec; - ctx = &cdl->devs[i]; ctx->host = host1x; @@ -70,14 +68,12 @@ int host1x_memory_context_list_init(struct host1x *host1x) goto del_devices; } - fwspec = dev_iommu_fwspec_get(&ctx->dev); - if (!fwspec || !device_iommu_mapped(&ctx->dev)) { + if (!tegra_dev_iommu_get_stream_id(&ctx->dev, &ctx->stream_id) || + !device_iommu_mapped(&ctx->dev)) { dev_err(host1x->dev, "Context device %d has no IOMMU!\n", i); device_del(&ctx->dev); goto del_devices; } - - ctx->stream_id = fwspec->ids[0] & 0xffff; } return 0; diff --git a/drivers/gpu/host1x/debug.c b/drivers/gpu/host1x/debug.c index 6649b04b7131..a18cc8d8caf5 100644 --- a/drivers/gpu/host1x/debug.c +++ b/drivers/gpu/host1x/debug.c @@ -77,6 +77,7 @@ static int show_channel(struct host1x_channel *ch, void *data, bool show_fifo) static void show_syncpts(struct host1x *m, struct output *o, bool show_all) { + unsigned long irqflags; struct list_head *pos; unsigned int i; int err; @@ -92,10 +93,10 @@ static void show_syncpts(struct host1x *m, struct output *o, bool show_all) u32 min = host1x_syncpt_load(m->syncpt + i); unsigned int waiters = 0; - spin_lock(&m->syncpt[i].intr.lock); - list_for_each(pos, &m->syncpt[i].intr.wait_head) + spin_lock_irqsave(&m->syncpt[i].fences.lock, irqflags); + list_for_each(pos, &m->syncpt[i].fences.list) waiters++; - spin_unlock(&m->syncpt[i].intr.lock); + spin_unlock_irqrestore(&m->syncpt[i].fences.lock, irqflags); if (!kref_read(&m->syncpt[i].ref)) continue; diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index f31039aca03c..4872d183d860 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c @@ -516,7 +516,7 @@ static int host1x_probe(struct platform_device *pdev) return PTR_ERR(host->regs); } - syncpt_irq = platform_get_irq(pdev, 0); + host->syncpt_irq = platform_get_irq(pdev, 0); if (syncpt_irq < 0) return syncpt_irq; @@ -578,7 +578,7 @@ static int host1x_probe(struct platform_device *pdev) goto free_contexts; } - err = host1x_intr_init(host, syncpt_irq); + err = host1x_intr_init(host); if (err) { dev_err(&pdev->dev, "failed to initialize interrupts\n"); goto deinit_syncpt; diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h index 920e5548cfbc..75de50fe03d0 100644 --- a/drivers/gpu/host1x/dev.h +++ b/drivers/gpu/host1x/dev.h @@ -74,8 +74,7 @@ struct host1x_syncpt_ops { }; struct host1x_intr_ops { - int (*init_host_sync)(struct host1x *host, u32 cpm, - void (*syncpt_thresh_work)(struct work_struct *work)); + int (*init_host_sync)(struct host1x *host, u32 cpm); void (*set_syncpt_threshold)( struct host1x *host, unsigned int id, u32 thresh); void (*enable_syncpt_intr)(struct host1x *host, unsigned int id); @@ -125,6 +124,7 @@ struct host1x { void __iomem *regs; void __iomem *hv_regs; /* hypervisor region */ void __iomem *common_regs; + int syncpt_irq; struct host1x_syncpt *syncpt; struct host1x_syncpt_base *bases; struct device *dev; @@ -138,7 +138,6 @@ struct host1x { dma_addr_t iova_end; struct mutex intr_mutex; - int intr_syncpt_irq; const struct host1x_syncpt_ops *syncpt_op; const struct host1x_intr_ops *intr_op; @@ -216,10 +215,9 @@ static inline void host1x_hw_syncpt_enable_protection(struct host1x *host) return host->syncpt_op->enable_protection(host); } -static inline int host1x_hw_intr_init_host_sync(struct host1x *host, u32 cpm, - void (*syncpt_thresh_work)(struct work_struct *)) +static inline int host1x_hw_intr_init_host_sync(struct host1x *host, u32 cpm) { - return host->intr_op->init_host_sync(host, cpm, syncpt_thresh_work); + return host->intr_op->init_host_sync(host, cpm); } static inline void host1x_hw_intr_set_syncpt_threshold(struct host1x *host, diff --git a/drivers/gpu/host1x/fence.c b/drivers/gpu/host1x/fence.c index df428bcbae69..139ad1afd935 100644 --- a/drivers/gpu/host1x/fence.c +++ b/drivers/gpu/host1x/fence.c @@ -15,22 +15,6 @@ #include "intr.h" #include "syncpt.h" -static DEFINE_SPINLOCK(lock); - -struct host1x_syncpt_fence { - struct dma_fence base; - - atomic_t signaling; - - struct host1x_syncpt *sp; - u32 threshold; - - struct host1x_waitlist *waiter; - void *waiter_ref; - - struct delayed_work timeout_work; -}; - static const char *host1x_syncpt_fence_get_driver_name(struct dma_fence *f) { return "host1x"; @@ -49,11 +33,11 @@ static struct host1x_syncpt_fence *to_host1x_fence(struct dma_fence *f) static bool host1x_syncpt_fence_enable_signaling(struct dma_fence *f) { struct host1x_syncpt_fence *sf = to_host1x_fence(f); - int err; if (host1x_syncpt_is_expired(sf->sp, sf->threshold)) return false; + /* Reference for interrupt path. */ dma_fence_get(f); /* @@ -61,24 +45,17 @@ static bool host1x_syncpt_fence_enable_signaling(struct dma_fence *f) * reference to any fences for which 'enable_signaling' has been * called (and that have not been signalled). * - * We provide a userspace API to create arbitrary syncpoint fences, - * so we cannot normally guarantee that all fences get signalled. - * As such, setup a timeout, so that long-lasting fences will get - * reaped eventually. + * We cannot currently always guarantee that all fences get signalled + * or cancelled. As such, for such situations, set up a timeout, so + * that long-lasting fences will get reaped eventually. */ - schedule_delayed_work(&sf->timeout_work, msecs_to_jiffies(30000)); - - err = host1x_intr_add_action(sf->sp->host, sf->sp, sf->threshold, - HOST1X_INTR_ACTION_SIGNAL_FENCE, f, - sf->waiter, &sf->waiter_ref); - if (err) { - cancel_delayed_work_sync(&sf->timeout_work); - dma_fence_put(f); - return false; + if (sf->timeout) { + /* Reference for timeout path. */ + dma_fence_get(f); + schedule_delayed_work(&sf->timeout_work, msecs_to_jiffies(30000)); } - /* intr framework takes ownership of waiter */ - sf->waiter = NULL; + host1x_intr_add_fence_locked(sf->sp->host, sf); /* * The fence may get signalled at any time after the above call, @@ -89,37 +66,32 @@ static bool host1x_syncpt_fence_enable_signaling(struct dma_fence *f) return true; } -static void host1x_syncpt_fence_release(struct dma_fence *f) -{ - struct host1x_syncpt_fence *sf = to_host1x_fence(f); - - if (sf->waiter) - kfree(sf->waiter); - - dma_fence_free(f); -} - static const struct dma_fence_ops host1x_syncpt_fence_ops = { .get_driver_name = host1x_syncpt_fence_get_driver_name, .get_timeline_name = host1x_syncpt_fence_get_timeline_name, .enable_signaling = host1x_syncpt_fence_enable_signaling, - .release = host1x_syncpt_fence_release, }; void host1x_fence_signal(struct host1x_syncpt_fence *f) { - if (atomic_xchg(&f->signaling, 1)) + if (atomic_xchg(&f->signaling, 1)) { + /* + * Already on timeout path, but we removed the fence before + * timeout path could, so drop interrupt path reference. + */ + dma_fence_put(&f->base); return; + } - /* - * Cancel pending timeout work - if it races, it will - * not get 'f->signaling' and return. - */ - cancel_delayed_work_sync(&f->timeout_work); - - host1x_intr_put_ref(f->sp->host, f->sp->id, f->waiter_ref, false); + if (f->timeout && cancel_delayed_work(&f->timeout_work)) { + /* + * We know that the timeout path will not be entered. + * Safe to drop the timeout path's reference now. + */ + dma_fence_put(&f->base); + } - dma_fence_signal(&f->base); + dma_fence_signal_locked(&f->base); dma_fence_put(&f->base); } @@ -129,21 +101,29 @@ static void do_fence_timeout(struct work_struct *work) struct host1x_syncpt_fence *f = container_of(dwork, struct host1x_syncpt_fence, timeout_work); - if (atomic_xchg(&f->signaling, 1)) + if (atomic_xchg(&f->signaling, 1)) { + /* Already on interrupt path, drop timeout path reference if any. */ + if (f->timeout) + dma_fence_put(&f->base); return; + } - /* - * Cancel pending timeout work - if it races, it will - * not get 'f->signaling' and return. - */ - host1x_intr_put_ref(f->sp->host, f->sp->id, f->waiter_ref, true); + if (host1x_intr_remove_fence(f->sp->host, f)) { + /* + * Managed to remove fence from queue, so it's safe to drop + * the interrupt path's reference. + */ + dma_fence_put(&f->base); + } dma_fence_set_error(&f->base, -ETIMEDOUT); dma_fence_signal(&f->base); - dma_fence_put(&f->base); + if (f->timeout) + dma_fence_put(&f->base); } -struct dma_fence *host1x_fence_create(struct host1x_syncpt *sp, u32 threshold) +struct dma_fence *host1x_fence_create(struct host1x_syncpt *sp, u32 threshold, + bool timeout) { struct host1x_syncpt_fence *fence; @@ -151,16 +131,11 @@ struct dma_fence *host1x_fence_create(struct host1x_syncpt *sp, u32 threshold) if (!fence) return ERR_PTR(-ENOMEM); - fence->waiter = kzalloc(sizeof(*fence->waiter), GFP_KERNEL); - if (!fence->waiter) { - kfree(fence); - return ERR_PTR(-ENOMEM); - } - fence->sp = sp; fence->threshold = threshold; + fence->timeout = timeout; - dma_fence_init(&fence->base, &host1x_syncpt_fence_ops, &lock, + dma_fence_init(&fence->base, &host1x_syncpt_fence_ops, &sp->fences.lock, dma_fence_context_alloc(1), 0); INIT_DELAYED_WORK(&fence->timeout_work, do_fence_timeout); @@ -168,3 +143,12 @@ struct dma_fence *host1x_fence_create(struct host1x_syncpt *sp, u32 threshold) return &fence->base; } EXPORT_SYMBOL(host1x_fence_create); + +void host1x_fence_cancel(struct dma_fence *f) +{ + struct host1x_syncpt_fence *sf = to_host1x_fence(f); + + schedule_delayed_work(&sf->timeout_work, 0); + flush_delayed_work(&sf->timeout_work); +} +EXPORT_SYMBOL(host1x_fence_cancel); diff --git a/drivers/gpu/host1x/fence.h b/drivers/gpu/host1x/fence.h index 70c91de82f14..f3c644c73cad 100644 --- a/drivers/gpu/host1x/fence.h +++ b/drivers/gpu/host1x/fence.h @@ -6,7 +6,24 @@ #ifndef HOST1X_FENCE_H #define HOST1X_FENCE_H -struct host1x_syncpt_fence; +struct host1x_syncpt_fence { + struct dma_fence base; + + atomic_t signaling; + + struct host1x_syncpt *sp; + u32 threshold; + bool timeout; + + struct delayed_work timeout_work; + + struct list_head list; +}; + +struct host1x_fence_list { + spinlock_t lock; + struct list_head list; +}; void host1x_fence_signal(struct host1x_syncpt_fence *fence); diff --git a/drivers/gpu/host1x/hw/channel_hw.c b/drivers/gpu/host1x/hw/channel_hw.c index 732abe0750ff..d44b8de890be 100644 --- a/drivers/gpu/host1x/hw/channel_hw.c +++ b/drivers/gpu/host1x/hw/channel_hw.c @@ -179,14 +179,12 @@ static inline void synchronize_syncpt_base(struct host1x_job *job) static void host1x_channel_set_streamid(struct host1x_channel *channel) { #if HOST1X_HW >= 6 - u32 sid = 0x7f; -#ifdef CONFIG_IOMMU_API - struct iommu_fwspec *spec = dev_iommu_fwspec_get(channel->dev->parent); - if (spec) - sid = spec->ids[0] & 0xffff; -#endif + u32 stream_id; + + if (!tegra_dev_iommu_get_stream_id(channel->dev->parent, &stream_id)) + stream_id = TEGRA_STREAM_ID_BYPASS; - host1x_ch_writel(channel, sid, HOST1X_CHANNEL_SMMU_STREAMID); + host1x_ch_writel(channel, stream_id, HOST1X_CHANNEL_SMMU_STREAMID); #endif } @@ -278,6 +276,14 @@ static void channel_program_cdma(struct host1x_job *job) #endif } +static void job_complete_callback(struct dma_fence *fence, struct dma_fence_cb *cb) +{ + struct host1x_job *job = container_of(cb, struct host1x_job, fence_cb); + + /* Schedules CDMA update. */ + host1x_cdma_update(&job->channel->cdma); +} + static int channel_submit(struct host1x_job *job) { struct host1x_channel *ch = job->channel; @@ -285,7 +291,6 @@ static int channel_submit(struct host1x_job *job) u32 prev_max = 0; u32 syncval; int err; - struct host1x_waitlist *completed_waiter = NULL; struct host1x *host = dev_get_drvdata(ch->dev->parent); trace_host1x_channel_submit(dev_name(ch->dev), @@ -298,14 +303,7 @@ static int channel_submit(struct host1x_job *job) /* get submit lock */ err = mutex_lock_interruptible(&ch->submitlock); if (err) - goto error; - - completed_waiter = kzalloc(sizeof(*completed_waiter), GFP_KERNEL); - if (!completed_waiter) { - mutex_unlock(&ch->submitlock); - err = -ENOMEM; - goto error; - } + return err; host1x_channel_set_streamid(ch); host1x_enable_gather_filter(ch); @@ -315,31 +313,37 @@ static int channel_submit(struct host1x_job *job) err = host1x_cdma_begin(&ch->cdma, job); if (err) { mutex_unlock(&ch->submitlock); - goto error; + return err; } channel_program_cdma(job); syncval = host1x_syncpt_read_max(sp); + /* + * Create fence before submitting job to HW to avoid job completing + * before the fence is set up. + */ + job->fence = host1x_fence_create(sp, syncval, true); + if (WARN(IS_ERR(job->fence), "Failed to create submit complete fence")) { + job->fence = NULL; + } else { + err = dma_fence_add_callback(job->fence, &job->fence_cb, + job_complete_callback); + } + /* end CDMA submit & stash pinned hMems into sync queue */ host1x_cdma_end(&ch->cdma, job); trace_host1x_channel_submitted(dev_name(ch->dev), prev_max, syncval); - /* schedule a submit complete interrupt */ - err = host1x_intr_add_action(host, sp, syncval, - HOST1X_INTR_ACTION_SUBMIT_COMPLETE, ch, - completed_waiter, &job->waiter); - completed_waiter = NULL; - WARN(err, "Failed to set submit complete interrupt"); - mutex_unlock(&ch->submitlock); - return 0; + if (err == -ENOENT) + host1x_cdma_update(&ch->cdma); + else + WARN(err, "Failed to set submit complete interrupt"); -error: - kfree(completed_waiter); - return err; + return 0; } static int host1x_channel_init(struct host1x_channel *ch, struct host1x *dev, diff --git a/drivers/gpu/host1x/hw/hw_host1x06_uclass.h b/drivers/gpu/host1x/hw/hw_host1x06_uclass.h index 5f831438d19b..50c32de452fb 100644 --- a/drivers/gpu/host1x/hw/hw_host1x06_uclass.h +++ b/drivers/gpu/host1x/hw/hw_host1x06_uclass.h @@ -53,7 +53,7 @@ static inline u32 host1x_uclass_incr_syncpt_cond_f(u32 v) host1x_uclass_incr_syncpt_cond_f(v) static inline u32 host1x_uclass_incr_syncpt_indx_f(u32 v) { - return (v & 0xff) << 0; + return (v & 0x3ff) << 0; } #define HOST1X_UCLASS_INCR_SYNCPT_INDX_F(v) \ host1x_uclass_incr_syncpt_indx_f(v) diff --git a/drivers/gpu/host1x/hw/hw_host1x07_uclass.h b/drivers/gpu/host1x/hw/hw_host1x07_uclass.h index 8cd2ef087d5d..887b878f92f7 100644 --- a/drivers/gpu/host1x/hw/hw_host1x07_uclass.h +++ b/drivers/gpu/host1x/hw/hw_host1x07_uclass.h @@ -53,7 +53,7 @@ static inline u32 host1x_uclass_incr_syncpt_cond_f(u32 v) host1x_uclass_incr_syncpt_cond_f(v) static inline u32 host1x_uclass_incr_syncpt_indx_f(u32 v) { - return (v & 0xff) << 0; + return (v & 0x3ff) << 0; } #define HOST1X_UCLASS_INCR_SYNCPT_INDX_F(v) \ host1x_uclass_incr_syncpt_indx_f(v) diff --git a/drivers/gpu/host1x/hw/hw_host1x08_uclass.h b/drivers/gpu/host1x/hw/hw_host1x08_uclass.h index 724cccd71aa1..4fb1d090edae 100644 --- a/drivers/gpu/host1x/hw/hw_host1x08_uclass.h +++ b/drivers/gpu/host1x/hw/hw_host1x08_uclass.h @@ -53,7 +53,7 @@ static inline u32 host1x_uclass_incr_syncpt_cond_f(u32 v) host1x_uclass_incr_syncpt_cond_f(v) static inline u32 host1x_uclass_incr_syncpt_indx_f(u32 v) { - return (v & 0xff) << 0; + return (v & 0x3ff) << 0; } #define HOST1X_UCLASS_INCR_SYNCPT_INDX_F(v) \ host1x_uclass_incr_syncpt_indx_f(v) diff --git a/drivers/gpu/host1x/hw/intr_hw.c b/drivers/gpu/host1x/hw/intr_hw.c index 9acccdb139e6..b915ef7d0348 100644 --- a/drivers/gpu/host1x/hw/intr_hw.c +++ b/drivers/gpu/host1x/hw/intr_hw.c @@ -13,23 +13,6 @@ #include "../intr.h" #include "../dev.h" -/* - * Sync point threshold interrupt service function - * Handles sync point threshold triggers, in interrupt context - */ -static void host1x_intr_syncpt_handle(struct host1x_syncpt *syncpt) -{ - unsigned int id = syncpt->id; - struct host1x *host = syncpt->host; - - host1x_sync_writel(host, BIT(id % 32), - HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(id / 32)); - host1x_sync_writel(host, BIT(id % 32), - HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(id / 32)); - - schedule_work(&syncpt->intr.work); -} - static irqreturn_t syncpt_thresh_isr(int irq, void *dev_id) { struct host1x *host = dev_id; @@ -39,17 +22,20 @@ static irqreturn_t syncpt_thresh_isr(int irq, void *dev_id) for (i = 0; i < DIV_ROUND_UP(host->info->nb_pts, 32); i++) { reg = host1x_sync_readl(host, HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(i)); - for_each_set_bit(id, ®, 32) { - struct host1x_syncpt *syncpt = - host->syncpt + (i * 32 + id); - host1x_intr_syncpt_handle(syncpt); - } + + host1x_sync_writel(host, reg, + HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(i)); + host1x_sync_writel(host, reg, + HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(i)); + + for_each_set_bit(id, ®, 32) + host1x_intr_handle_interrupt(host, i * 32 + id); } return IRQ_HANDLED; } -static void _host1x_intr_disable_all_syncpt_intrs(struct host1x *host) +static void host1x_intr_disable_all_syncpt_intrs(struct host1x *host) { unsigned int i; @@ -90,45 +76,38 @@ static void intr_hw_init(struct host1x *host, u32 cpm) } static int -_host1x_intr_init_host_sync(struct host1x *host, u32 cpm, - void (*syncpt_thresh_work)(struct work_struct *)) +host1x_intr_init_host_sync(struct host1x *host, u32 cpm) { - unsigned int i; int err; host1x_hw_intr_disable_all_syncpt_intrs(host); - for (i = 0; i < host->info->nb_pts; i++) - INIT_WORK(&host->syncpt[i].intr.work, syncpt_thresh_work); - - err = devm_request_irq(host->dev, host->intr_syncpt_irq, + err = devm_request_irq(host->dev, host->syncpt_irq, syncpt_thresh_isr, IRQF_SHARED, "host1x_syncpt", host); - if (err < 0) { - WARN_ON(1); + if (err < 0) return err; - } intr_hw_init(host, cpm); return 0; } -static void _host1x_intr_set_syncpt_threshold(struct host1x *host, +static void host1x_intr_set_syncpt_threshold(struct host1x *host, unsigned int id, u32 thresh) { host1x_sync_writel(host, thresh, HOST1X_SYNC_SYNCPT_INT_THRESH(id)); } -static void _host1x_intr_enable_syncpt_intr(struct host1x *host, +static void host1x_intr_enable_syncpt_intr(struct host1x *host, unsigned int id) { host1x_sync_writel(host, BIT(id % 32), HOST1X_SYNC_SYNCPT_THRESH_INT_ENABLE_CPU0(id / 32)); } -static void _host1x_intr_disable_syncpt_intr(struct host1x *host, +static void host1x_intr_disable_syncpt_intr(struct host1x *host, unsigned int id) { host1x_sync_writel(host, BIT(id % 32), @@ -137,23 +116,10 @@ static void _host1x_intr_disable_syncpt_intr(struct host1x *host, HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(id / 32)); } -static int _host1x_free_syncpt_irq(struct host1x *host) -{ - unsigned int i; - - devm_free_irq(host->dev, host->intr_syncpt_irq, host); - - for (i = 0; i < host->info->nb_pts; i++) - cancel_work_sync(&host->syncpt[i].intr.work); - - return 0; -} - static const struct host1x_intr_ops host1x_intr_ops = { - .init_host_sync = _host1x_intr_init_host_sync, - .set_syncpt_threshold = _host1x_intr_set_syncpt_threshold, - .enable_syncpt_intr = _host1x_intr_enable_syncpt_intr, - .disable_syncpt_intr = _host1x_intr_disable_syncpt_intr, - .disable_all_syncpt_intrs = _host1x_intr_disable_all_syncpt_intrs, - .free_syncpt_irq = _host1x_free_syncpt_irq, + .init_host_sync = host1x_intr_init_host_sync, + .set_syncpt_threshold = host1x_intr_set_syncpt_threshold, + .enable_syncpt_intr = host1x_intr_enable_syncpt_intr, + .disable_syncpt_intr = host1x_intr_disable_syncpt_intr, + .disable_all_syncpt_intrs = host1x_intr_disable_all_syncpt_intrs, }; diff --git a/drivers/gpu/host1x/hw/syncpt_hw.c b/drivers/gpu/host1x/hw/syncpt_hw.c index dd39d67ccec3..8cf35b2eff3d 100644 --- a/drivers/gpu/host1x/hw/syncpt_hw.c +++ b/drivers/gpu/host1x/hw/syncpt_hw.c @@ -106,9 +106,6 @@ static void syncpt_assign_to_channel(struct host1x_syncpt *sp, #if HOST1X_HW >= 6 struct host1x *host = sp->host; - if (!host->hv_regs) - return; - host1x_sync_writel(host, HOST1X_SYNC_SYNCPT_CH_APP_CH(ch ? ch->id : 0xff), HOST1X_SYNC_SYNCPT_CH_APP(sp->id)); diff --git a/drivers/gpu/host1x/intr.c b/drivers/gpu/host1x/intr.c index 965ba21818b1..995bfa980837 100644 --- a/drivers/gpu/host1x/intr.c +++ b/drivers/gpu/host1x/intr.c @@ -2,299 +2,113 @@ /* * Tegra host1x Interrupt Management * - * Copyright (c) 2010-2013, NVIDIA Corporation. + * Copyright (c) 2010-2021, NVIDIA Corporation. */ #include <linux/clk.h> -#include <linux/interrupt.h> -#include <linux/slab.h> -#include <linux/irq.h> -#include <trace/events/host1x.h> -#include "channel.h" #include "dev.h" #include "fence.h" #include "intr.h" -/* Wait list management */ - -enum waitlist_state { - WLS_PENDING, - WLS_REMOVED, - WLS_CANCELLED, - WLS_HANDLED -}; - -static void waiter_release(struct kref *kref) -{ - kfree(container_of(kref, struct host1x_waitlist, refcount)); -} - -/* - * add a waiter to a waiter queue, sorted by threshold - * returns true if it was added at the head of the queue - */ -static bool add_waiter_to_queue(struct host1x_waitlist *waiter, - struct list_head *queue) -{ - struct host1x_waitlist *pos; - u32 thresh = waiter->thresh; - - list_for_each_entry_reverse(pos, queue, list) - if ((s32)(pos->thresh - thresh) <= 0) { - list_add(&waiter->list, &pos->list); - return false; - } - - list_add(&waiter->list, queue); - return true; -} - -/* - * run through a waiter queue for a single sync point ID - * and gather all completed waiters into lists by actions - */ -static void remove_completed_waiters(struct list_head *head, u32 sync, - struct list_head completed[HOST1X_INTR_ACTION_COUNT]) +static void host1x_intr_add_fence_to_list(struct host1x_fence_list *list, + struct host1x_syncpt_fence *fence) { - struct list_head *dest; - struct host1x_waitlist *waiter, *next, *prev; - - list_for_each_entry_safe(waiter, next, head, list) { - if ((s32)(waiter->thresh - sync) > 0) - break; + struct host1x_syncpt_fence *fence_in_list; - dest = completed + waiter->action; - - /* consolidate submit cleanups */ - if (waiter->action == HOST1X_INTR_ACTION_SUBMIT_COMPLETE && - !list_empty(dest)) { - prev = list_entry(dest->prev, - struct host1x_waitlist, list); - if (prev->data == waiter->data) { - prev->count++; - dest = NULL; - } + list_for_each_entry_reverse(fence_in_list, &list->list, list) { + if ((s32)(fence_in_list->threshold - fence->threshold) <= 0) { + /* Fence in list is before us, we can insert here */ + list_add(&fence->list, &fence_in_list->list); + return; } - - /* PENDING->REMOVED or CANCELLED->HANDLED */ - if (atomic_inc_return(&waiter->state) == WLS_HANDLED || !dest) { - list_del(&waiter->list); - kref_put(&waiter->refcount, waiter_release); - } else - list_move_tail(&waiter->list, dest); } -} - -static void reset_threshold_interrupt(struct host1x *host, - struct list_head *head, - unsigned int id) -{ - u32 thresh = - list_first_entry(head, struct host1x_waitlist, list)->thresh; - - host1x_hw_intr_set_syncpt_threshold(host, id, thresh); - host1x_hw_intr_enable_syncpt_intr(host, id); -} - -static void action_submit_complete(struct host1x_waitlist *waiter) -{ - struct host1x_channel *channel = waiter->data; - - host1x_cdma_update(&channel->cdma); - - /* Add nr_completed to trace */ - trace_host1x_channel_submit_complete(dev_name(channel->dev), - waiter->count, waiter->thresh); -} -static void action_wakeup(struct host1x_waitlist *waiter) -{ - wait_queue_head_t *wq = waiter->data; - - wake_up(wq); -} - -static void action_wakeup_interruptible(struct host1x_waitlist *waiter) -{ - wait_queue_head_t *wq = waiter->data; - - wake_up_interruptible(wq); + /* Add as first in list */ + list_add(&fence->list, &list->list); } -static void action_signal_fence(struct host1x_waitlist *waiter) +static void host1x_intr_update_hw_state(struct host1x *host, struct host1x_syncpt *sp) { - struct host1x_syncpt_fence *f = waiter->data; - - host1x_fence_signal(f); -} + struct host1x_syncpt_fence *fence; -typedef void (*action_handler)(struct host1x_waitlist *waiter); + if (!list_empty(&sp->fences.list)) { + fence = list_first_entry(&sp->fences.list, struct host1x_syncpt_fence, list); -static const action_handler action_handlers[HOST1X_INTR_ACTION_COUNT] = { - action_submit_complete, - action_wakeup, - action_wakeup_interruptible, - action_signal_fence, -}; - -static void run_handlers(struct list_head completed[HOST1X_INTR_ACTION_COUNT]) -{ - struct list_head *head = completed; - unsigned int i; - - for (i = 0; i < HOST1X_INTR_ACTION_COUNT; ++i, ++head) { - action_handler handler = action_handlers[i]; - struct host1x_waitlist *waiter, *next; - - list_for_each_entry_safe(waiter, next, head, list) { - list_del(&waiter->list); - handler(waiter); - WARN_ON(atomic_xchg(&waiter->state, WLS_HANDLED) != - WLS_REMOVED); - kref_put(&waiter->refcount, waiter_release); - } + host1x_hw_intr_set_syncpt_threshold(host, sp->id, fence->threshold); + host1x_hw_intr_enable_syncpt_intr(host, sp->id); + } else { + host1x_hw_intr_disable_syncpt_intr(host, sp->id); } } -/* - * Remove & handle all waiters that have completed for the given syncpt - */ -static int process_wait_list(struct host1x *host, - struct host1x_syncpt *syncpt, - u32 threshold) +void host1x_intr_add_fence_locked(struct host1x *host, struct host1x_syncpt_fence *fence) { - struct list_head completed[HOST1X_INTR_ACTION_COUNT]; - unsigned int i; - int empty; - - for (i = 0; i < HOST1X_INTR_ACTION_COUNT; ++i) - INIT_LIST_HEAD(completed + i); - - spin_lock(&syncpt->intr.lock); - - remove_completed_waiters(&syncpt->intr.wait_head, threshold, - completed); - - empty = list_empty(&syncpt->intr.wait_head); - if (empty) - host1x_hw_intr_disable_syncpt_intr(host, syncpt->id); - else - reset_threshold_interrupt(host, &syncpt->intr.wait_head, - syncpt->id); - - spin_unlock(&syncpt->intr.lock); - - run_handlers(completed); - - return empty; -} + struct host1x_fence_list *fence_list = &fence->sp->fences; -/* - * Sync point threshold interrupt service thread function - * Handles sync point threshold triggers, in thread context - */ + INIT_LIST_HEAD(&fence->list); -static void syncpt_thresh_work(struct work_struct *work) -{ - struct host1x_syncpt_intr *syncpt_intr = - container_of(work, struct host1x_syncpt_intr, work); - struct host1x_syncpt *syncpt = - container_of(syncpt_intr, struct host1x_syncpt, intr); - unsigned int id = syncpt->id; - struct host1x *host = syncpt->host; - - (void)process_wait_list(host, syncpt, - host1x_syncpt_load(host->syncpt + id)); + host1x_intr_add_fence_to_list(fence_list, fence); + host1x_intr_update_hw_state(host, fence->sp); } -int host1x_intr_add_action(struct host1x *host, struct host1x_syncpt *syncpt, - u32 thresh, enum host1x_intr_action action, - void *data, struct host1x_waitlist *waiter, - void **ref) +bool host1x_intr_remove_fence(struct host1x *host, struct host1x_syncpt_fence *fence) { - int queue_was_empty; - - if (waiter == NULL) { - pr_warn("%s: NULL waiter\n", __func__); - return -EINVAL; - } - - /* initialize a new waiter */ - INIT_LIST_HEAD(&waiter->list); - kref_init(&waiter->refcount); - if (ref) - kref_get(&waiter->refcount); - waiter->thresh = thresh; - waiter->action = action; - atomic_set(&waiter->state, WLS_PENDING); - waiter->data = data; - waiter->count = 1; - - spin_lock(&syncpt->intr.lock); + struct host1x_fence_list *fence_list = &fence->sp->fences; + unsigned long irqflags; - queue_was_empty = list_empty(&syncpt->intr.wait_head); + spin_lock_irqsave(&fence_list->lock, irqflags); - if (add_waiter_to_queue(waiter, &syncpt->intr.wait_head)) { - /* added at head of list - new threshold value */ - host1x_hw_intr_set_syncpt_threshold(host, syncpt->id, thresh); - - /* added as first waiter - enable interrupt */ - if (queue_was_empty) - host1x_hw_intr_enable_syncpt_intr(host, syncpt->id); + if (list_empty(&fence->list)) { + spin_unlock_irqrestore(&fence_list->lock, irqflags); + return false; } - if (ref) - *ref = waiter; + list_del_init(&fence->list); + host1x_intr_update_hw_state(host, fence->sp); - spin_unlock(&syncpt->intr.lock); + spin_unlock_irqrestore(&fence_list->lock, irqflags); - return 0; + return true; } -void host1x_intr_put_ref(struct host1x *host, unsigned int id, void *ref, - bool flush) +void host1x_intr_handle_interrupt(struct host1x *host, unsigned int id) { - struct host1x_waitlist *waiter = ref; - struct host1x_syncpt *syncpt; + struct host1x_syncpt *sp = &host->syncpt[id]; + struct host1x_syncpt_fence *fence, *tmp; + unsigned int value; - atomic_cmpxchg(&waiter->state, WLS_PENDING, WLS_CANCELLED); + value = host1x_syncpt_load(sp); - syncpt = host->syncpt + id; + spin_lock(&sp->fences.lock); - spin_lock(&syncpt->intr.lock); - if (atomic_cmpxchg(&waiter->state, WLS_CANCELLED, WLS_HANDLED) == - WLS_CANCELLED) { - list_del(&waiter->list); - kref_put(&waiter->refcount, waiter_release); - } - spin_unlock(&syncpt->intr.lock); + list_for_each_entry_safe(fence, tmp, &sp->fences.list, list) { + if (((value - fence->threshold) & 0x80000000U) != 0U) { + /* Fence is not yet expired, we are done */ + break; + } - if (flush) { - /* Wait until any concurrently executing handler has finished. */ - while (atomic_read(&waiter->state) != WLS_HANDLED) - schedule(); + list_del_init(&fence->list); + host1x_fence_signal(fence); } - kref_put(&waiter->refcount, waiter_release); + /* Re-enable interrupt if necessary */ + host1x_intr_update_hw_state(host, sp); + + spin_unlock(&sp->fences.lock); } -int host1x_intr_init(struct host1x *host, unsigned int irq_sync) +int host1x_intr_init(struct host1x *host) { unsigned int id; - u32 nb_pts = host1x_syncpt_nb_pts(host); mutex_init(&host->intr_mutex); - host->intr_syncpt_irq = irq_sync; - for (id = 0; id < nb_pts; ++id) { - struct host1x_syncpt *syncpt = host->syncpt + id; + for (id = 0; id < host1x_syncpt_nb_pts(host); ++id) { + struct host1x_syncpt *syncpt = &host->syncpt[id]; - spin_lock_init(&syncpt->intr.lock); - INIT_LIST_HEAD(&syncpt->intr.wait_head); - snprintf(syncpt->intr.thresh_irq_name, - sizeof(syncpt->intr.thresh_irq_name), - "host1x_sp_%02u", id); + spin_lock_init(&syncpt->fences.lock); + INIT_LIST_HEAD(&syncpt->fences.list); } return 0; @@ -310,8 +124,7 @@ void host1x_intr_start(struct host1x *host) int err; mutex_lock(&host->intr_mutex); - err = host1x_hw_intr_init_host_sync(host, DIV_ROUND_UP(hz, 1000000), - syncpt_thresh_work); + err = host1x_hw_intr_init_host_sync(host, DIV_ROUND_UP(hz, 1000000)); if (err) { mutex_unlock(&host->intr_mutex); return; @@ -321,36 +134,5 @@ void host1x_intr_start(struct host1x *host) void host1x_intr_stop(struct host1x *host) { - unsigned int id; - struct host1x_syncpt *syncpt = host->syncpt; - u32 nb_pts = host1x_syncpt_nb_pts(host); - - mutex_lock(&host->intr_mutex); - host1x_hw_intr_disable_all_syncpt_intrs(host); - - for (id = 0; id < nb_pts; ++id) { - struct host1x_waitlist *waiter, *next; - - list_for_each_entry_safe(waiter, next, - &syncpt[id].intr.wait_head, list) { - if (atomic_cmpxchg(&waiter->state, - WLS_CANCELLED, WLS_HANDLED) == WLS_CANCELLED) { - list_del(&waiter->list); - kref_put(&waiter->refcount, waiter_release); - } - } - - if (!list_empty(&syncpt[id].intr.wait_head)) { - /* output diagnostics */ - mutex_unlock(&host->intr_mutex); - pr_warn("%s cannot stop syncpt intr id=%u\n", - __func__, id); - return; - } - } - - host1x_hw_intr_free_syncpt_irq(host); - - mutex_unlock(&host->intr_mutex); } diff --git a/drivers/gpu/host1x/intr.h b/drivers/gpu/host1x/intr.h index e4c346099273..3b5610b525e5 100644 --- a/drivers/gpu/host1x/intr.h +++ b/drivers/gpu/host1x/intr.h @@ -2,87 +2,17 @@ /* * Tegra host1x Interrupt Management * - * Copyright (c) 2010-2013, NVIDIA Corporation. + * Copyright (c) 2010-2021, NVIDIA Corporation. */ #ifndef __HOST1X_INTR_H #define __HOST1X_INTR_H -#include <linux/interrupt.h> -#include <linux/workqueue.h> - -struct host1x_syncpt; struct host1x; - -enum host1x_intr_action { - /* - * Perform cleanup after a submit has completed. - * 'data' points to a channel - */ - HOST1X_INTR_ACTION_SUBMIT_COMPLETE = 0, - - /* - * Wake up a task. - * 'data' points to a wait_queue_head_t - */ - HOST1X_INTR_ACTION_WAKEUP, - - /* - * Wake up a interruptible task. - * 'data' points to a wait_queue_head_t - */ - HOST1X_INTR_ACTION_WAKEUP_INTERRUPTIBLE, - - HOST1X_INTR_ACTION_SIGNAL_FENCE, - - HOST1X_INTR_ACTION_COUNT -}; - -struct host1x_syncpt_intr { - spinlock_t lock; - struct list_head wait_head; - char thresh_irq_name[12]; - struct work_struct work; -}; - -struct host1x_waitlist { - struct list_head list; - struct kref refcount; - u32 thresh; - enum host1x_intr_action action; - atomic_t state; - void *data; - int count; -}; - -/* - * Schedule an action to be taken when a sync point reaches the given threshold. - * - * @id the sync point - * @thresh the threshold - * @action the action to take - * @data a pointer to extra data depending on action, see above - * @waiter waiter structure - assumes ownership - * @ref must be passed if cancellation is possible, else NULL - * - * This is a non-blocking api. - */ -int host1x_intr_add_action(struct host1x *host, struct host1x_syncpt *syncpt, - u32 thresh, enum host1x_intr_action action, - void *data, struct host1x_waitlist *waiter, - void **ref); - -/* - * Unreference an action submitted to host1x_intr_add_action(). - * You must call this if you passed non-NULL as ref. - * @ref the ref returned from host1x_intr_add_action() - * @flush wait until any pending handlers have completed before returning. - */ -void host1x_intr_put_ref(struct host1x *host, unsigned int id, void *ref, - bool flush); +struct host1x_syncpt_fence; /* Initialize host1x sync point interrupt */ -int host1x_intr_init(struct host1x *host, unsigned int irq_sync); +int host1x_intr_init(struct host1x *host); /* Deinitialize host1x sync point interrupt */ void host1x_intr_deinit(struct host1x *host); @@ -93,5 +23,10 @@ void host1x_intr_start(struct host1x *host); /* Disable host1x sync point interrupt */ void host1x_intr_stop(struct host1x *host); -irqreturn_t host1x_syncpt_thresh_fn(void *dev_id); +void host1x_intr_handle_interrupt(struct host1x *host, unsigned int id); + +void host1x_intr_add_fence_locked(struct host1x *host, struct host1x_syncpt_fence *fence); + +bool host1x_intr_remove_fence(struct host1x *host, struct host1x_syncpt_fence *fence); + #endif diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c index b2761aa03b95..3ed49e1fd933 100644 --- a/drivers/gpu/host1x/job.c +++ b/drivers/gpu/host1x/job.c @@ -88,9 +88,15 @@ static void job_free(struct kref *ref) if (job->release) job->release(job); - if (job->waiter) - host1x_intr_put_ref(job->syncpt->host, job->syncpt->id, - job->waiter, false); + if (job->fence) { + /* + * remove_callback is atomic w.r.t. fence signaling, so + * after the call returns, we know that the callback is not + * in execution, and the fence can be safely freed. + */ + dma_fence_remove_callback(job->fence, &job->fence_cb); + dma_fence_put(job->fence); + } if (job->syncpt) host1x_syncpt_put(job->syncpt); diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c index f87a8705f518..2d2007760eac 100644 --- a/drivers/gpu/host1x/syncpt.c +++ b/drivers/gpu/host1x/syncpt.c @@ -7,6 +7,7 @@ #include <linux/module.h> #include <linux/device.h> +#include <linux/dma-fence.h> #include <linux/slab.h> #include <trace/events/host1x.h> @@ -209,17 +210,6 @@ int host1x_syncpt_incr(struct host1x_syncpt *sp) } EXPORT_SYMBOL(host1x_syncpt_incr); -/* - * Updated sync point form hardware, and returns true if syncpoint is expired, - * false if we may need to wait - */ -static bool syncpt_load_min_is_expired(struct host1x_syncpt *sp, u32 thresh) -{ - host1x_hw_syncpt_load(sp->host, sp); - - return host1x_syncpt_is_expired(sp, thresh); -} - /** * host1x_syncpt_wait() - wait for a syncpoint to reach a given value * @sp: host1x syncpoint @@ -230,10 +220,10 @@ static bool syncpt_load_min_is_expired(struct host1x_syncpt *sp, u32 thresh) int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout, u32 *value) { - DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); - void *ref; - struct host1x_waitlist *waiter; - int err = 0, check_count = 0; + struct dma_fence *fence; + long wait_err; + + host1x_hw_syncpt_load(sp->host, sp); if (value) *value = host1x_syncpt_load(sp); @@ -241,73 +231,29 @@ int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout, if (host1x_syncpt_is_expired(sp, thresh)) return 0; - if (!timeout) { - err = -EAGAIN; - goto done; - } - - /* allocate a waiter */ - waiter = kzalloc(sizeof(*waiter), GFP_KERNEL); - if (!waiter) { - err = -ENOMEM; - goto done; - } - - /* schedule a wakeup when the syncpoint value is reached */ - err = host1x_intr_add_action(sp->host, sp, thresh, - HOST1X_INTR_ACTION_WAKEUP_INTERRUPTIBLE, - &wq, waiter, &ref); - if (err) - goto done; - - err = -EAGAIN; - /* Caller-specified timeout may be impractically low */ if (timeout < 0) timeout = LONG_MAX; + else if (timeout == 0) + return -EAGAIN; - /* wait for the syncpoint, or timeout, or signal */ - while (timeout) { - long check = min_t(long, SYNCPT_CHECK_PERIOD, timeout); - int remain; - - remain = wait_event_interruptible_timeout(wq, - syncpt_load_min_is_expired(sp, thresh), - check); - if (remain > 0 || host1x_syncpt_is_expired(sp, thresh)) { - if (value) - *value = host1x_syncpt_load(sp); + fence = host1x_fence_create(sp, thresh, false); + if (IS_ERR(fence)) + return PTR_ERR(fence); - err = 0; + wait_err = dma_fence_wait_timeout(fence, true, timeout); + if (wait_err == 0) + host1x_fence_cancel(fence); + dma_fence_put(fence); - break; - } - - if (remain < 0) { - err = remain; - break; - } - - timeout -= check; - - if (timeout && check_count <= MAX_STUCK_CHECK_COUNT) { - dev_warn(sp->host->dev, - "%s: syncpoint id %u (%s) stuck waiting %d, timeout=%ld\n", - current->comm, sp->id, sp->name, - thresh, timeout); - - host1x_debug_dump_syncpts(sp->host); - - if (check_count == MAX_STUCK_CHECK_COUNT) - host1x_debug_dump(sp->host); - - check_count++; - } - } - - host1x_intr_put_ref(sp->host, sp->id, ref, true); + if (value) + *value = host1x_syncpt_load(sp); -done: - return err; + if (wait_err == 0) + return -EAGAIN; + else if (wait_err < 0) + return wait_err; + else + return 0; } EXPORT_SYMBOL(host1x_syncpt_wait); diff --git a/drivers/gpu/host1x/syncpt.h b/drivers/gpu/host1x/syncpt.h index 95cd29b79d6d..4c3f3b2f0e9c 100644 --- a/drivers/gpu/host1x/syncpt.h +++ b/drivers/gpu/host1x/syncpt.h @@ -14,6 +14,7 @@ #include <linux/kref.h> #include <linux/sched.h> +#include "fence.h" #include "intr.h" struct host1x; @@ -39,7 +40,7 @@ struct host1x_syncpt { struct host1x_syncpt_base *base; /* interrupt data */ - struct host1x_syncpt_intr intr; + struct host1x_fence_list fences; /* * If a submission incrementing this syncpoint fails, lock it so that diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_client.c b/drivers/hid/amd-sfh-hid/amd_sfh_client.c index ab125f79408f..1fb0f7105fb2 100644 --- a/drivers/hid/amd-sfh-hid/amd_sfh_client.c +++ b/drivers/hid/amd-sfh-hid/amd_sfh_client.c @@ -282,7 +282,7 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata) } rc = mp2_ops->get_rep_desc(cl_idx, cl_data->report_descr[i]); if (rc) - return rc; + goto cleanup; mp2_ops->start(privdata, info); status = amd_sfh_wait_for_response (privdata, cl_data->sensor_idx[i], SENSOR_ENABLED); diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c index 4da2f9f62aba..a1d6e08fab7d 100644 --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c @@ -160,7 +160,7 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata) } rc = mp2_ops->get_rep_desc(cl_idx, cl_data->report_descr[i]); if (rc) - return rc; + goto cleanup; writel(0, privdata->mmio + AMD_P2C_MSG(0)); mp2_ops->start(privdata, info); diff --git a/drivers/hid/hid-betopff.c b/drivers/hid/hid-betopff.c index 467d789f9bc2..25ed7b9a917e 100644 --- a/drivers/hid/hid-betopff.c +++ b/drivers/hid/hid-betopff.c @@ -60,7 +60,6 @@ static int betopff_init(struct hid_device *hid) struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct input_dev *dev; - int field_count = 0; int error; int i, j; @@ -86,19 +85,21 @@ static int betopff_init(struct hid_device *hid) * ----------------------------------------- * Do init them with default value. */ + if (report->maxfield < 4) { + hid_err(hid, "not enough fields in the report: %d\n", + report->maxfield); + return -ENODEV; + } for (i = 0; i < report->maxfield; i++) { + if (report->field[i]->report_count < 1) { + hid_err(hid, "no values in the field\n"); + return -ENODEV; + } for (j = 0; j < report->field[i]->report_count; j++) { report->field[i]->value[j] = 0x00; - field_count++; } } - if (field_count < 4) { - hid_err(hid, "not enough fields in the report: %d\n", - field_count); - return -ENODEV; - } - betopff = kzalloc(sizeof(*betopff), GFP_KERNEL); if (!betopff) return -ENOMEM; diff --git a/drivers/hid/hid-bigbenff.c b/drivers/hid/hid-bigbenff.c index e8c5e3ac9fff..e8b16665860d 100644 --- a/drivers/hid/hid-bigbenff.c +++ b/drivers/hid/hid-bigbenff.c @@ -344,6 +344,11 @@ static int bigben_probe(struct hid_device *hid, } report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; + if (list_empty(report_list)) { + hid_err(hid, "no output report found\n"); + error = -ENODEV; + goto error_hw_stop; + } bigben->report = list_entry(report_list->next, struct hid_report, list); diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index bd47628da6be..3e1803592bd4 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -993,8 +993,8 @@ struct hid_report *hid_validate_values(struct hid_device *hid, * Validating on id 0 means we should examine the first * report in the list. */ - report = list_entry( - hid->report_enum[type].report_list.next, + report = list_first_entry_or_null( + &hid->report_enum[type].report_list, struct hid_report, list); } else { report = hid->report_enum[type].report_id_hash[id]; diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 82713ef3aaa6..0f8c11842a3a 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -274,7 +274,6 @@ #define USB_DEVICE_ID_CH_AXIS_295 0x001c #define USB_VENDOR_ID_CHERRY 0x046a -#define USB_DEVICE_ID_CHERRY_MOUSE_000C 0x000c #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 #define USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR 0x0027 @@ -1295,6 +1294,7 @@ #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540 0x0075 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640 0x0094 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01 0x0042 +#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01_V2 0x0905 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L 0x0935 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S 0x0909 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06 0x0078 diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index f399bf0d3c8c..27c40894acab 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -944,6 +944,7 @@ ATTRIBUTE_GROUPS(ps_device); static int dualsense_get_calibration_data(struct dualsense *ds) { + struct hid_device *hdev = ds->base.hdev; short gyro_pitch_bias, gyro_pitch_plus, gyro_pitch_minus; short gyro_yaw_bias, gyro_yaw_plus, gyro_yaw_minus; short gyro_roll_bias, gyro_roll_plus, gyro_roll_minus; @@ -954,6 +955,7 @@ static int dualsense_get_calibration_data(struct dualsense *ds) int speed_2x; int range_2g; int ret = 0; + int i; uint8_t *buf; buf = kzalloc(DS_FEATURE_REPORT_CALIBRATION_SIZE, GFP_KERNEL); @@ -1006,6 +1008,21 @@ static int dualsense_get_calibration_data(struct dualsense *ds) ds->gyro_calib_data[2].sens_denom = gyro_roll_plus - gyro_roll_minus; /* + * Sanity check gyro calibration data. This is needed to prevent crashes + * during report handling of virtual, clone or broken devices not implementing + * calibration data properly. + */ + for (i = 0; i < ARRAY_SIZE(ds->gyro_calib_data); i++) { + if (ds->gyro_calib_data[i].sens_denom == 0) { + hid_warn(hdev, "Invalid gyro calibration data for axis (%d), disabling calibration.", + ds->gyro_calib_data[i].abs_code); + ds->gyro_calib_data[i].bias = 0; + ds->gyro_calib_data[i].sens_numer = DS_GYRO_RANGE; + ds->gyro_calib_data[i].sens_denom = S16_MAX; + } + } + + /* * Set accelerometer calibration and normalization parameters. * Data values will be normalized to 1/DS_ACC_RES_PER_G g. */ @@ -1027,6 +1044,21 @@ static int dualsense_get_calibration_data(struct dualsense *ds) ds->accel_calib_data[2].sens_numer = 2*DS_ACC_RES_PER_G; ds->accel_calib_data[2].sens_denom = range_2g; + /* + * Sanity check accelerometer calibration data. This is needed to prevent crashes + * during report handling of virtual, clone or broken devices not implementing calibration + * data properly. + */ + for (i = 0; i < ARRAY_SIZE(ds->accel_calib_data); i++) { + if (ds->accel_calib_data[i].sens_denom == 0) { + hid_warn(hdev, "Invalid accelerometer calibration data for axis (%d), disabling calibration.", + ds->accel_calib_data[i].abs_code); + ds->accel_calib_data[i].bias = 0; + ds->accel_calib_data[i].sens_numer = DS_ACC_RANGE; + ds->accel_calib_data[i].sens_denom = S16_MAX; + } + } + err_free: kfree(buf); return ret; @@ -1737,6 +1769,7 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4) int speed_2x; int range_2g; int ret = 0; + int i; uint8_t *buf; if (ds4->base.hdev->bus == BUS_USB) { @@ -1831,6 +1864,21 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4) ds4->gyro_calib_data[2].sens_denom = gyro_roll_plus - gyro_roll_minus; /* + * Sanity check gyro calibration data. This is needed to prevent crashes + * during report handling of virtual, clone or broken devices not implementing + * calibration data properly. + */ + for (i = 0; i < ARRAY_SIZE(ds4->gyro_calib_data); i++) { + if (ds4->gyro_calib_data[i].sens_denom == 0) { + hid_warn(hdev, "Invalid gyro calibration data for axis (%d), disabling calibration.", + ds4->gyro_calib_data[i].abs_code); + ds4->gyro_calib_data[i].bias = 0; + ds4->gyro_calib_data[i].sens_numer = DS4_GYRO_RANGE; + ds4->gyro_calib_data[i].sens_denom = S16_MAX; + } + } + + /* * Set accelerometer calibration and normalization parameters. * Data values will be normalized to 1/DS4_ACC_RES_PER_G g. */ @@ -1852,6 +1900,21 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4) ds4->accel_calib_data[2].sens_numer = 2*DS4_ACC_RES_PER_G; ds4->accel_calib_data[2].sens_denom = range_2g; + /* + * Sanity check accelerometer calibration data. This is needed to prevent crashes + * during report handling of virtual, clone or broken devices not implementing calibration + * data properly. + */ + for (i = 0; i < ARRAY_SIZE(ds4->accel_calib_data); i++) { + if (ds4->accel_calib_data[i].sens_denom == 0) { + hid_warn(hdev, "Invalid accelerometer calibration data for axis (%d), disabling calibration.", + ds4->accel_calib_data[i].abs_code); + ds4->accel_calib_data[i].bias = 0; + ds4->accel_calib_data[i].sens_numer = DS4_ACC_RANGE; + ds4->accel_calib_data[i].sens_denom = S16_MAX; + } + } + err_free: kfree(buf); return ret; diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c index 0e9702c7f7d6..be3ad02573de 100644 --- a/drivers/hid/hid-quirks.c +++ b/drivers/hid/hid-quirks.c @@ -54,7 +54,6 @@ static const struct hid_device_id hid_quirks[] = { { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE), HID_QUIRK_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_PEDALS), HID_QUIRK_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_THROTTLE), HID_QUIRK_NOGET }, - { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_MOUSE_000C), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB), HID_QUIRK_NO_INIT_REPORTS }, { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB_RAPIDFIRE), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70RGB), HID_QUIRK_NO_INIT_REPORTS }, diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c index 7fa6fe04f1b2..cfbbc39807a6 100644 --- a/drivers/hid/hid-uclogic-core.c +++ b/drivers/hid/hid-uclogic-core.c @@ -526,6 +526,8 @@ static const struct hid_device_id uclogic_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01) }, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, + USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01_V2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L) }, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S) }, diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c index cd1233d7e253..3c5eea3df328 100644 --- a/drivers/hid/hid-uclogic-params.c +++ b/drivers/hid/hid-uclogic-params.c @@ -1656,6 +1656,8 @@ int uclogic_params_init(struct uclogic_params *params, case VID_PID(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_PARBLO_A610_PRO): case VID_PID(USB_VENDOR_ID_UGEE, + USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01_V2): + case VID_PID(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L): case VID_PID(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S): diff --git a/drivers/hid/intel-ish-hid/ishtp/dma-if.c b/drivers/hid/intel-ish-hid/ishtp/dma-if.c index 40554c8daca0..00046cbfd4ed 100644 --- a/drivers/hid/intel-ish-hid/ishtp/dma-if.c +++ b/drivers/hid/intel-ish-hid/ishtp/dma-if.c @@ -104,6 +104,11 @@ void *ishtp_cl_get_dma_send_buf(struct ishtp_device *dev, int required_slots = (size / DMA_SLOT_SIZE) + 1 * (size % DMA_SLOT_SIZE != 0); + if (!dev->ishtp_dma_tx_map) { + dev_err(dev->devc, "Fail to allocate Tx map\n"); + return NULL; + } + spin_lock_irqsave(&dev->ishtp_dma_tx_lock, flags); for (i = 0; i <= (dev->ishtp_dma_num_slots - required_slots); i++) { free = 1; @@ -150,6 +155,11 @@ void ishtp_cl_release_dma_acked_mem(struct ishtp_device *dev, return; } + if (!dev->ishtp_dma_tx_map) { + dev_err(dev->devc, "Fail to allocate Tx map\n"); + return; + } + i = (msg_addr - dev->ishtp_host_dma_tx_buf) / DMA_SLOT_SIZE; spin_lock_irqsave(&dev->ishtp_dma_tx_lock, flags); for (j = 0; j < acked_slots; j++) { diff --git a/drivers/i2c/busses/i2c-axxia.c b/drivers/i2c/busses/i2c-axxia.c index bdf3b50de8ad..c1c74ce08407 100644 --- a/drivers/i2c/busses/i2c-axxia.c +++ b/drivers/i2c/busses/i2c-axxia.c @@ -118,7 +118,7 @@ #define SDA_HOLD_TIME 0x90 /** - * axxia_i2c_dev - I2C device context + * struct axxia_i2c_dev - I2C device context * @base: pointer to register struct * @msg: pointer to current message * @msg_r: pointer to current read message (sequence transfer) diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c index a3240ece55b2..581e02cc979a 100644 --- a/drivers/i2c/busses/i2c-designware-common.c +++ b/drivers/i2c/busses/i2c-designware-common.c @@ -351,7 +351,8 @@ u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset) * * If your hardware is free from tHD;STA issue, try this one. */ - return DIV_ROUND_CLOSEST(ic_clk * tSYMBOL, MICRO) - 8 + offset; + return DIV_ROUND_CLOSEST_ULL((u64)ic_clk * tSYMBOL, MICRO) - + 8 + offset; else /* * Conditional expression: @@ -367,7 +368,8 @@ u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset) * The reason why we need to take into account "tf" here, * is the same as described in i2c_dw_scl_lcnt(). */ - return DIV_ROUND_CLOSEST(ic_clk * (tSYMBOL + tf), MICRO) - 3 + offset; + return DIV_ROUND_CLOSEST_ULL((u64)ic_clk * (tSYMBOL + tf), MICRO) - + 3 + offset; } u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset) @@ -383,7 +385,8 @@ u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset) * account the fall time of SCL signal (tf). Default tf value * should be 0.3 us, for safety. */ - return DIV_ROUND_CLOSEST(ic_clk * (tLOW + tf), MICRO) - 1 + offset; + return DIV_ROUND_CLOSEST_ULL((u64)ic_clk * (tLOW + tf), MICRO) - + 1 + offset; } int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev) diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c index e499f96506c5..782fe1ef3ca1 100644 --- a/drivers/i2c/busses/i2c-designware-pcidrv.c +++ b/drivers/i2c/busses/i2c-designware-pcidrv.c @@ -396,6 +396,8 @@ static const struct pci_device_id i2_designware_pci_ids[] = { { PCI_VDEVICE(ATI, 0x73a4), navi_amd }, { PCI_VDEVICE(ATI, 0x73e4), navi_amd }, { PCI_VDEVICE(ATI, 0x73c4), navi_amd }, + { PCI_VDEVICE(ATI, 0x7444), navi_amd }, + { PCI_VDEVICE(ATI, 0x7464), navi_amd }, { 0,} }; MODULE_DEVICE_TABLE(pci, i2_designware_pci_ids); diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index ba043b547393..74182db03a88 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -351,13 +351,11 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) if (dev->flags & ACCESS_NO_IRQ_SUSPEND) { dev_pm_set_driver_flags(&pdev->dev, - DPM_FLAG_SMART_PREPARE | - DPM_FLAG_MAY_SKIP_RESUME); + DPM_FLAG_SMART_PREPARE); } else { dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_SMART_PREPARE | - DPM_FLAG_SMART_SUSPEND | - DPM_FLAG_MAY_SKIP_RESUME); + DPM_FLAG_SMART_SUSPEND); } device_enable_async_suspend(&pdev->dev); @@ -419,21 +417,8 @@ static int dw_i2c_plat_prepare(struct device *dev) */ return !has_acpi_companion(dev); } - -static void dw_i2c_plat_complete(struct device *dev) -{ - /* - * The device can only be in runtime suspend at this point if it has not - * been resumed throughout the ending system suspend/resume cycle, so if - * the platform firmware might mess up with it, request the runtime PM - * framework to resume it. - */ - if (pm_runtime_suspended(dev) && pm_resume_via_firmware()) - pm_request_resume(dev); -} #else #define dw_i2c_plat_prepare NULL -#define dw_i2c_plat_complete NULL #endif #ifdef CONFIG_PM @@ -483,7 +468,6 @@ static int __maybe_unused dw_i2c_plat_resume(struct device *dev) static const struct dev_pm_ops dw_i2c_dev_pm_ops = { .prepare = dw_i2c_plat_prepare, - .complete = dw_i2c_plat_complete, SET_LATE_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume) SET_RUNTIME_PM_OPS(dw_i2c_plat_runtime_suspend, dw_i2c_plat_runtime_resume, NULL) }; diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 5af5cffc444e..d113bed79545 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -826,8 +826,8 @@ static int mxs_i2c_probe(struct platform_device *pdev) /* Setup the DMA */ i2c->dmach = dma_request_chan(dev, "rx-tx"); if (IS_ERR(i2c->dmach)) { - dev_err(dev, "Failed to request dma\n"); - return PTR_ERR(i2c->dmach); + return dev_err_probe(dev, PTR_ERR(i2c->dmach), + "Failed to request dma\n"); } platform_set_drvdata(pdev, i2c); diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c index d1658ed76562..b31cf4f18f85 100644 --- a/drivers/i2c/busses/i2c-rk3x.c +++ b/drivers/i2c/busses/i2c-rk3x.c @@ -80,7 +80,7 @@ enum { #define DEFAULT_SCL_RATE (100 * 1000) /* Hz */ /** - * struct i2c_spec_values: + * struct i2c_spec_values - I2C specification values for various modes * @min_hold_start_ns: min hold time (repeated) START condition * @min_low_ns: min LOW period of the SCL clock * @min_high_ns: min HIGH period of the SCL cloc @@ -136,7 +136,7 @@ static const struct i2c_spec_values fast_mode_plus_spec = { }; /** - * struct rk3x_i2c_calced_timings: + * struct rk3x_i2c_calced_timings - calculated V1 timings * @div_low: Divider output for low * @div_high: Divider output for high * @tuning: Used to adjust setup/hold data time, @@ -159,7 +159,7 @@ enum rk3x_i2c_state { }; /** - * struct rk3x_i2c_soc_data: + * struct rk3x_i2c_soc_data - SOC-specific data * @grf_offset: offset inside the grf regmap for setting the i2c type * @calc_timings: Callback function for i2c timing information calculated */ @@ -239,7 +239,8 @@ static inline void rk3x_i2c_clean_ipd(struct rk3x_i2c *i2c) } /** - * Generate a START condition, which triggers a REG_INT_START interrupt. + * rk3x_i2c_start - Generate a START condition, which triggers a REG_INT_START interrupt. + * @i2c: target controller data */ static void rk3x_i2c_start(struct rk3x_i2c *i2c) { @@ -258,8 +259,8 @@ static void rk3x_i2c_start(struct rk3x_i2c *i2c) } /** - * Generate a STOP condition, which triggers a REG_INT_STOP interrupt. - * + * rk3x_i2c_stop - Generate a STOP condition, which triggers a REG_INT_STOP interrupt. + * @i2c: target controller data * @error: Error code to return in rk3x_i2c_xfer */ static void rk3x_i2c_stop(struct rk3x_i2c *i2c, int error) @@ -298,7 +299,8 @@ static void rk3x_i2c_stop(struct rk3x_i2c *i2c, int error) } /** - * Setup a read according to i2c->msg + * rk3x_i2c_prepare_read - Setup a read according to i2c->msg + * @i2c: target controller data */ static void rk3x_i2c_prepare_read(struct rk3x_i2c *i2c) { @@ -329,7 +331,8 @@ static void rk3x_i2c_prepare_read(struct rk3x_i2c *i2c) } /** - * Fill the transmit buffer with data from i2c->msg + * rk3x_i2c_fill_transmit_buf - Fill the transmit buffer with data from i2c->msg + * @i2c: target controller data */ static void rk3x_i2c_fill_transmit_buf(struct rk3x_i2c *i2c) { @@ -532,11 +535,10 @@ out: } /** - * Get timing values of I2C specification - * + * rk3x_i2c_get_spec - Get timing values of I2C specification * @speed: Desired SCL frequency * - * Returns: Matched i2c spec values. + * Return: Matched i2c_spec_values. */ static const struct i2c_spec_values *rk3x_i2c_get_spec(unsigned int speed) { @@ -549,13 +551,12 @@ static const struct i2c_spec_values *rk3x_i2c_get_spec(unsigned int speed) } /** - * Calculate divider values for desired SCL frequency - * + * rk3x_i2c_v0_calc_timings - Calculate divider values for desired SCL frequency * @clk_rate: I2C input clock rate * @t: Known I2C timing information * @t_calc: Caculated rk3x private timings that would be written into regs * - * Returns: 0 on success, -EINVAL if the goal SCL rate is too slow. In that case + * Return: %0 on success, -%EINVAL if the goal SCL rate is too slow. In that case * a best-effort divider value is returned in divs. If the target rate is * too high, we silently use the highest possible rate. */ @@ -710,13 +711,12 @@ static int rk3x_i2c_v0_calc_timings(unsigned long clk_rate, } /** - * Calculate timing values for desired SCL frequency - * + * rk3x_i2c_v1_calc_timings - Calculate timing values for desired SCL frequency * @clk_rate: I2C input clock rate * @t: Known I2C timing information * @t_calc: Caculated rk3x private timings that would be written into regs * - * Returns: 0 on success, -EINVAL if the goal SCL rate is too slow. In that case + * Return: %0 on success, -%EINVAL if the goal SCL rate is too slow. In that case * a best-effort divider value is returned in divs. If the target rate is * too high, we silently use the highest possible rate. * The following formulas are v1's method to calculate timings. @@ -960,14 +960,14 @@ static int rk3x_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long } /** - * Setup I2C registers for an I2C operation specified by msgs, num. - * - * Must be called with i2c->lock held. - * + * rk3x_i2c_setup - Setup I2C registers for an I2C operation specified by msgs, num. + * @i2c: target controller data * @msgs: I2C msgs to process * @num: Number of msgs * - * returns: Number of I2C msgs processed or negative in case of error + * Must be called with i2c->lock held. + * + * Return: Number of I2C msgs processed or negative in case of error */ static int rk3x_i2c_setup(struct rk3x_i2c *i2c, struct i2c_msg *msgs, int num) { diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index 26b021f43ba4..11b1c1603aeb 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c @@ -2957,15 +2957,18 @@ EXPORT_SYMBOL(__rdma_block_iter_start); bool __rdma_block_iter_next(struct ib_block_iter *biter) { unsigned int block_offset; + unsigned int sg_delta; if (!biter->__sg_nents || !biter->__sg) return false; biter->__dma_addr = sg_dma_address(biter->__sg) + biter->__sg_advance; block_offset = biter->__dma_addr & (BIT_ULL(biter->__pg_bit) - 1); - biter->__sg_advance += BIT_ULL(biter->__pg_bit) - block_offset; + sg_delta = BIT_ULL(biter->__pg_bit) - block_offset; - if (biter->__sg_advance >= sg_dma_len(biter->__sg)) { + if (sg_dma_len(biter->__sg) - biter->__sg_advance > sg_delta) { + biter->__sg_advance += sg_delta; + } else { biter->__sg_advance = 0; biter->__sg = sg_next(biter->__sg); biter->__sg_nents--; diff --git a/drivers/infiniband/hw/hfi1/user_exp_rcv.c b/drivers/infiniband/hw/hfi1/user_exp_rcv.c index 186d30291260..b02f2f0809c8 100644 --- a/drivers/infiniband/hw/hfi1/user_exp_rcv.c +++ b/drivers/infiniband/hw/hfi1/user_exp_rcv.c @@ -23,18 +23,25 @@ static void cacheless_tid_rb_remove(struct hfi1_filedata *fdata, static bool tid_rb_invalidate(struct mmu_interval_notifier *mni, const struct mmu_notifier_range *range, unsigned long cur_seq); +static bool tid_cover_invalidate(struct mmu_interval_notifier *mni, + const struct mmu_notifier_range *range, + unsigned long cur_seq); static int program_rcvarray(struct hfi1_filedata *fd, struct tid_user_buf *, struct tid_group *grp, unsigned int start, u16 count, u32 *tidlist, unsigned int *tididx, unsigned int *pmapped); -static int unprogram_rcvarray(struct hfi1_filedata *fd, u32 tidinfo, - struct tid_group **grp); +static int unprogram_rcvarray(struct hfi1_filedata *fd, u32 tidinfo); +static void __clear_tid_node(struct hfi1_filedata *fd, + struct tid_rb_node *node); static void clear_tid_node(struct hfi1_filedata *fd, struct tid_rb_node *node); static const struct mmu_interval_notifier_ops tid_mn_ops = { .invalidate = tid_rb_invalidate, }; +static const struct mmu_interval_notifier_ops tid_cover_ops = { + .invalidate = tid_cover_invalidate, +}; /* * Initialize context and file private data needed for Expected @@ -253,53 +260,65 @@ int hfi1_user_exp_rcv_setup(struct hfi1_filedata *fd, tididx = 0, mapped, mapped_pages = 0; u32 *tidlist = NULL; struct tid_user_buf *tidbuf; + unsigned long mmu_seq = 0; if (!PAGE_ALIGNED(tinfo->vaddr)) return -EINVAL; + if (tinfo->length == 0) + return -EINVAL; tidbuf = kzalloc(sizeof(*tidbuf), GFP_KERNEL); if (!tidbuf) return -ENOMEM; + mutex_init(&tidbuf->cover_mutex); tidbuf->vaddr = tinfo->vaddr; tidbuf->length = tinfo->length; tidbuf->psets = kcalloc(uctxt->expected_count, sizeof(*tidbuf->psets), GFP_KERNEL); if (!tidbuf->psets) { - kfree(tidbuf); - return -ENOMEM; + ret = -ENOMEM; + goto fail_release_mem; + } + + if (fd->use_mn) { + ret = mmu_interval_notifier_insert( + &tidbuf->notifier, current->mm, + tidbuf->vaddr, tidbuf->npages * PAGE_SIZE, + &tid_cover_ops); + if (ret) + goto fail_release_mem; + mmu_seq = mmu_interval_read_begin(&tidbuf->notifier); } pinned = pin_rcv_pages(fd, tidbuf); if (pinned <= 0) { - kfree(tidbuf->psets); - kfree(tidbuf); - return pinned; + ret = (pinned < 0) ? pinned : -ENOSPC; + goto fail_unpin; } /* Find sets of physically contiguous pages */ tidbuf->n_psets = find_phys_blocks(tidbuf, pinned); - /* - * We don't need to access this under a lock since tid_used is per - * process and the same process cannot be in hfi1_user_exp_rcv_clear() - * and hfi1_user_exp_rcv_setup() at the same time. - */ + /* Reserve the number of expected tids to be used. */ spin_lock(&fd->tid_lock); if (fd->tid_used + tidbuf->n_psets > fd->tid_limit) pageset_count = fd->tid_limit - fd->tid_used; else pageset_count = tidbuf->n_psets; + fd->tid_used += pageset_count; spin_unlock(&fd->tid_lock); - if (!pageset_count) - goto bail; + if (!pageset_count) { + ret = -ENOSPC; + goto fail_unreserve; + } ngroups = pageset_count / dd->rcv_entries.group_size; tidlist = kcalloc(pageset_count, sizeof(*tidlist), GFP_KERNEL); if (!tidlist) { ret = -ENOMEM; - goto nomem; + goto fail_unreserve; } tididx = 0; @@ -395,43 +414,78 @@ int hfi1_user_exp_rcv_setup(struct hfi1_filedata *fd, } unlock: mutex_unlock(&uctxt->exp_mutex); -nomem: hfi1_cdbg(TID, "total mapped: tidpairs:%u pages:%u (%d)", tididx, mapped_pages, ret); - if (tididx) { - spin_lock(&fd->tid_lock); - fd->tid_used += tididx; - spin_unlock(&fd->tid_lock); - tinfo->tidcnt = tididx; - tinfo->length = mapped_pages * PAGE_SIZE; - - if (copy_to_user(u64_to_user_ptr(tinfo->tidlist), - tidlist, sizeof(tidlist[0]) * tididx)) { - /* - * On failure to copy to the user level, we need to undo - * everything done so far so we don't leak resources. - */ - tinfo->tidlist = (unsigned long)&tidlist; - hfi1_user_exp_rcv_clear(fd, tinfo); - tinfo->tidlist = 0; - ret = -EFAULT; - goto bail; + + /* fail if nothing was programmed, set error if none provided */ + if (tididx == 0) { + if (ret >= 0) + ret = -ENOSPC; + goto fail_unreserve; + } + + /* adjust reserved tid_used to actual count */ + spin_lock(&fd->tid_lock); + fd->tid_used -= pageset_count - tididx; + spin_unlock(&fd->tid_lock); + + /* unpin all pages not covered by a TID */ + unpin_rcv_pages(fd, tidbuf, NULL, mapped_pages, pinned - mapped_pages, + false); + + if (fd->use_mn) { + /* check for an invalidate during setup */ + bool fail = false; + + mutex_lock(&tidbuf->cover_mutex); + fail = mmu_interval_read_retry(&tidbuf->notifier, mmu_seq); + mutex_unlock(&tidbuf->cover_mutex); + + if (fail) { + ret = -EBUSY; + goto fail_unprogram; } } - /* - * If not everything was mapped (due to insufficient RcvArray entries, - * for example), unpin all unmapped pages so we can pin them nex time. - */ - if (mapped_pages != pinned) - unpin_rcv_pages(fd, tidbuf, NULL, mapped_pages, - (pinned - mapped_pages), false); -bail: + tinfo->tidcnt = tididx; + tinfo->length = mapped_pages * PAGE_SIZE; + + if (copy_to_user(u64_to_user_ptr(tinfo->tidlist), + tidlist, sizeof(tidlist[0]) * tididx)) { + ret = -EFAULT; + goto fail_unprogram; + } + + if (fd->use_mn) + mmu_interval_notifier_remove(&tidbuf->notifier); + kfree(tidbuf->pages); kfree(tidbuf->psets); + kfree(tidbuf); kfree(tidlist); + return 0; + +fail_unprogram: + /* unprogram, unmap, and unpin all allocated TIDs */ + tinfo->tidlist = (unsigned long)tidlist; + hfi1_user_exp_rcv_clear(fd, tinfo); + tinfo->tidlist = 0; + pinned = 0; /* nothing left to unpin */ + pageset_count = 0; /* nothing left reserved */ +fail_unreserve: + spin_lock(&fd->tid_lock); + fd->tid_used -= pageset_count; + spin_unlock(&fd->tid_lock); +fail_unpin: + if (fd->use_mn) + mmu_interval_notifier_remove(&tidbuf->notifier); + if (pinned > 0) + unpin_rcv_pages(fd, tidbuf, NULL, 0, pinned, false); +fail_release_mem: kfree(tidbuf->pages); + kfree(tidbuf->psets); kfree(tidbuf); - return ret > 0 ? 0 : ret; + kfree(tidlist); + return ret; } int hfi1_user_exp_rcv_clear(struct hfi1_filedata *fd, @@ -452,7 +506,7 @@ int hfi1_user_exp_rcv_clear(struct hfi1_filedata *fd, mutex_lock(&uctxt->exp_mutex); for (tididx = 0; tididx < tinfo->tidcnt; tididx++) { - ret = unprogram_rcvarray(fd, tidinfo[tididx], NULL); + ret = unprogram_rcvarray(fd, tidinfo[tididx]); if (ret) { hfi1_cdbg(TID, "Failed to unprogram rcv array %d", ret); @@ -706,6 +760,7 @@ static int set_rcvarray_entry(struct hfi1_filedata *fd, } node->fdata = fd; + mutex_init(&node->invalidate_mutex); node->phys = page_to_phys(pages[0]); node->npages = npages; node->rcventry = rcventry; @@ -721,11 +776,6 @@ static int set_rcvarray_entry(struct hfi1_filedata *fd, &tid_mn_ops); if (ret) goto out_unmap; - /* - * FIXME: This is in the wrong order, the notifier should be - * established before the pages are pinned by pin_rcv_pages. - */ - mmu_interval_read_begin(&node->notifier); } fd->entry_to_rb[node->rcventry - uctxt->expected_base] = node; @@ -745,8 +795,7 @@ out_unmap: return -EFAULT; } -static int unprogram_rcvarray(struct hfi1_filedata *fd, u32 tidinfo, - struct tid_group **grp) +static int unprogram_rcvarray(struct hfi1_filedata *fd, u32 tidinfo) { struct hfi1_ctxtdata *uctxt = fd->uctxt; struct hfi1_devdata *dd = uctxt->dd; @@ -769,9 +818,6 @@ static int unprogram_rcvarray(struct hfi1_filedata *fd, u32 tidinfo, if (!node || node->rcventry != (uctxt->expected_base + rcventry)) return -EBADF; - if (grp) - *grp = node->grp; - if (fd->use_mn) mmu_interval_notifier_remove(&node->notifier); cacheless_tid_rb_remove(fd, node); @@ -779,23 +825,34 @@ static int unprogram_rcvarray(struct hfi1_filedata *fd, u32 tidinfo, return 0; } -static void clear_tid_node(struct hfi1_filedata *fd, struct tid_rb_node *node) +static void __clear_tid_node(struct hfi1_filedata *fd, struct tid_rb_node *node) { struct hfi1_ctxtdata *uctxt = fd->uctxt; struct hfi1_devdata *dd = uctxt->dd; + mutex_lock(&node->invalidate_mutex); + if (node->freed) + goto done; + node->freed = true; + trace_hfi1_exp_tid_unreg(uctxt->ctxt, fd->subctxt, node->rcventry, node->npages, node->notifier.interval_tree.start, node->phys, node->dma_addr); - /* - * Make sure device has seen the write before we unpin the - * pages. - */ + /* Make sure device has seen the write before pages are unpinned */ hfi1_put_tid(dd, node->rcventry, PT_INVALID_FLUSH, 0, 0); unpin_rcv_pages(fd, NULL, node, 0, node->npages, true); +done: + mutex_unlock(&node->invalidate_mutex); +} + +static void clear_tid_node(struct hfi1_filedata *fd, struct tid_rb_node *node) +{ + struct hfi1_ctxtdata *uctxt = fd->uctxt; + + __clear_tid_node(fd, node); node->grp->used--; node->grp->map &= ~(1 << (node->rcventry - node->grp->base)); @@ -854,10 +911,16 @@ static bool tid_rb_invalidate(struct mmu_interval_notifier *mni, if (node->freed) return true; + /* take action only if unmapping */ + if (range->event != MMU_NOTIFY_UNMAP) + return true; + trace_hfi1_exp_tid_inval(uctxt->ctxt, fdata->subctxt, node->notifier.interval_tree.start, node->rcventry, node->npages, node->dma_addr); - node->freed = true; + + /* clear the hardware rcvarray entry */ + __clear_tid_node(fdata, node); spin_lock(&fdata->invalid_lock); if (fdata->invalid_tid_idx < uctxt->expected_count) { @@ -887,6 +950,23 @@ static bool tid_rb_invalidate(struct mmu_interval_notifier *mni, return true; } +static bool tid_cover_invalidate(struct mmu_interval_notifier *mni, + const struct mmu_notifier_range *range, + unsigned long cur_seq) +{ + struct tid_user_buf *tidbuf = + container_of(mni, struct tid_user_buf, notifier); + + /* take action only if unmapping */ + if (range->event == MMU_NOTIFY_UNMAP) { + mutex_lock(&tidbuf->cover_mutex); + mmu_interval_set_seq(mni, cur_seq); + mutex_unlock(&tidbuf->cover_mutex); + } + + return true; +} + static void cacheless_tid_rb_remove(struct hfi1_filedata *fdata, struct tid_rb_node *tnode) { diff --git a/drivers/infiniband/hw/hfi1/user_exp_rcv.h b/drivers/infiniband/hw/hfi1/user_exp_rcv.h index 8c53e416bf84..f8ee997d0050 100644 --- a/drivers/infiniband/hw/hfi1/user_exp_rcv.h +++ b/drivers/infiniband/hw/hfi1/user_exp_rcv.h @@ -16,6 +16,8 @@ struct tid_pageset { }; struct tid_user_buf { + struct mmu_interval_notifier notifier; + struct mutex cover_mutex; unsigned long vaddr; unsigned long length; unsigned int npages; @@ -27,6 +29,7 @@ struct tid_user_buf { struct tid_rb_node { struct mmu_interval_notifier notifier; struct hfi1_filedata *fdata; + struct mutex invalidate_mutex; /* covers hw removal */ unsigned long phys; struct tid_group *grp; u32 rcventry; diff --git a/drivers/infiniband/hw/mlx5/counters.c b/drivers/infiniband/hw/mlx5/counters.c index 945758f39523..3e1272695d99 100644 --- a/drivers/infiniband/hw/mlx5/counters.c +++ b/drivers/infiniband/hw/mlx5/counters.c @@ -278,7 +278,6 @@ static int do_get_hw_stats(struct ib_device *ibdev, const struct mlx5_ib_counters *cnts = get_counters(dev, port_num - 1); struct mlx5_core_dev *mdev; int ret, num_counters; - u32 mdev_port_num; if (!stats) return -EINVAL; @@ -299,8 +298,9 @@ static int do_get_hw_stats(struct ib_device *ibdev, } if (MLX5_CAP_GEN(dev->mdev, cc_query_allowed)) { - mdev = mlx5_ib_get_native_port_mdev(dev, port_num, - &mdev_port_num); + if (!port_num) + port_num = 1; + mdev = mlx5_ib_get_native_port_mdev(dev, port_num, NULL); if (!mdev) { /* If port is not affiliated yet, its in down state * which doesn't have any counters yet, so it would be diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c index 40d9410ec303..cf953d23d18d 100644 --- a/drivers/infiniband/hw/mlx5/qp.c +++ b/drivers/infiniband/hw/mlx5/qp.c @@ -4502,6 +4502,40 @@ static bool mlx5_ib_modify_qp_allowed(struct mlx5_ib_dev *dev, return false; } +static int validate_rd_atomic(struct mlx5_ib_dev *dev, struct ib_qp_attr *attr, + int attr_mask, enum ib_qp_type qp_type) +{ + int log_max_ra_res; + int log_max_ra_req; + + if (qp_type == MLX5_IB_QPT_DCI) { + log_max_ra_res = 1 << MLX5_CAP_GEN(dev->mdev, + log_max_ra_res_dc); + log_max_ra_req = 1 << MLX5_CAP_GEN(dev->mdev, + log_max_ra_req_dc); + } else { + log_max_ra_res = 1 << MLX5_CAP_GEN(dev->mdev, + log_max_ra_res_qp); + log_max_ra_req = 1 << MLX5_CAP_GEN(dev->mdev, + log_max_ra_req_qp); + } + + if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC && + attr->max_rd_atomic > log_max_ra_res) { + mlx5_ib_dbg(dev, "invalid max_rd_atomic value %d\n", + attr->max_rd_atomic); + return false; + } + + if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC && + attr->max_dest_rd_atomic > log_max_ra_req) { + mlx5_ib_dbg(dev, "invalid max_dest_rd_atomic value %d\n", + attr->max_dest_rd_atomic); + return false; + } + return true; +} + int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, struct ib_udata *udata) { @@ -4589,21 +4623,8 @@ int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, goto out; } - if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC && - attr->max_rd_atomic > - (1 << MLX5_CAP_GEN(dev->mdev, log_max_ra_res_qp))) { - mlx5_ib_dbg(dev, "invalid max_rd_atomic value %d\n", - attr->max_rd_atomic); - goto out; - } - - if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC && - attr->max_dest_rd_atomic > - (1 << MLX5_CAP_GEN(dev->mdev, log_max_ra_req_qp))) { - mlx5_ib_dbg(dev, "invalid max_dest_rd_atomic value %d\n", - attr->max_dest_rd_atomic); + if (!validate_rd_atomic(dev, attr, attr_mask, qp_type)) goto out; - } if (cur_state == new_state && cur_state == IB_QPS_RESET) { err = 0; diff --git a/drivers/infiniband/sw/rxe/rxe_param.h b/drivers/infiniband/sw/rxe/rxe_param.h index a754fc902e3d..7b41d79e72b2 100644 --- a/drivers/infiniband/sw/rxe/rxe_param.h +++ b/drivers/infiniband/sw/rxe/rxe_param.h @@ -98,11 +98,11 @@ enum rxe_device_param { RXE_MAX_SRQ = DEFAULT_MAX_VALUE - RXE_MIN_SRQ_INDEX, RXE_MIN_MR_INDEX = 0x00000001, - RXE_MAX_MR_INDEX = DEFAULT_MAX_VALUE, - RXE_MAX_MR = DEFAULT_MAX_VALUE - RXE_MIN_MR_INDEX, - RXE_MIN_MW_INDEX = 0x00010001, - RXE_MAX_MW_INDEX = 0x00020000, - RXE_MAX_MW = 0x00001000, + RXE_MAX_MR_INDEX = DEFAULT_MAX_VALUE >> 1, + RXE_MAX_MR = RXE_MAX_MR_INDEX - RXE_MIN_MR_INDEX, + RXE_MIN_MW_INDEX = RXE_MAX_MR_INDEX + 1, + RXE_MAX_MW_INDEX = DEFAULT_MAX_VALUE, + RXE_MAX_MW = RXE_MAX_MW_INDEX - RXE_MIN_MW_INDEX, RXE_MAX_PKT_PER_ACK = 64, diff --git a/drivers/infiniband/sw/rxe/rxe_pool.c b/drivers/infiniband/sw/rxe/rxe_pool.c index f50620f5a0a1..1151c0b5ccea 100644 --- a/drivers/infiniband/sw/rxe/rxe_pool.c +++ b/drivers/infiniband/sw/rxe/rxe_pool.c @@ -23,16 +23,16 @@ static const struct rxe_type_info { .size = sizeof(struct rxe_ucontext), .elem_offset = offsetof(struct rxe_ucontext, elem), .min_index = 1, - .max_index = UINT_MAX, - .max_elem = UINT_MAX, + .max_index = RXE_MAX_UCONTEXT, + .max_elem = RXE_MAX_UCONTEXT, }, [RXE_TYPE_PD] = { .name = "pd", .size = sizeof(struct rxe_pd), .elem_offset = offsetof(struct rxe_pd, elem), .min_index = 1, - .max_index = UINT_MAX, - .max_elem = UINT_MAX, + .max_index = RXE_MAX_PD, + .max_elem = RXE_MAX_PD, }, [RXE_TYPE_AH] = { .name = "ah", @@ -40,7 +40,7 @@ static const struct rxe_type_info { .elem_offset = offsetof(struct rxe_ah, elem), .min_index = RXE_MIN_AH_INDEX, .max_index = RXE_MAX_AH_INDEX, - .max_elem = RXE_MAX_AH_INDEX - RXE_MIN_AH_INDEX + 1, + .max_elem = RXE_MAX_AH, }, [RXE_TYPE_SRQ] = { .name = "srq", @@ -49,7 +49,7 @@ static const struct rxe_type_info { .cleanup = rxe_srq_cleanup, .min_index = RXE_MIN_SRQ_INDEX, .max_index = RXE_MAX_SRQ_INDEX, - .max_elem = RXE_MAX_SRQ_INDEX - RXE_MIN_SRQ_INDEX + 1, + .max_elem = RXE_MAX_SRQ, }, [RXE_TYPE_QP] = { .name = "qp", @@ -58,7 +58,7 @@ static const struct rxe_type_info { .cleanup = rxe_qp_cleanup, .min_index = RXE_MIN_QP_INDEX, .max_index = RXE_MAX_QP_INDEX, - .max_elem = RXE_MAX_QP_INDEX - RXE_MIN_QP_INDEX + 1, + .max_elem = RXE_MAX_QP, }, [RXE_TYPE_CQ] = { .name = "cq", @@ -66,8 +66,8 @@ static const struct rxe_type_info { .elem_offset = offsetof(struct rxe_cq, elem), .cleanup = rxe_cq_cleanup, .min_index = 1, - .max_index = UINT_MAX, - .max_elem = UINT_MAX, + .max_index = RXE_MAX_CQ, + .max_elem = RXE_MAX_CQ, }, [RXE_TYPE_MR] = { .name = "mr", @@ -76,7 +76,7 @@ static const struct rxe_type_info { .cleanup = rxe_mr_cleanup, .min_index = RXE_MIN_MR_INDEX, .max_index = RXE_MAX_MR_INDEX, - .max_elem = RXE_MAX_MR_INDEX - RXE_MIN_MR_INDEX + 1, + .max_elem = RXE_MAX_MR, }, [RXE_TYPE_MW] = { .name = "mw", @@ -85,7 +85,7 @@ static const struct rxe_type_info { .cleanup = rxe_mw_cleanup, .min_index = RXE_MIN_MW_INDEX, .max_index = RXE_MAX_MW_INDEX, - .max_elem = RXE_MAX_MW_INDEX - RXE_MIN_MW_INDEX + 1, + .max_elem = RXE_MAX_MW, }, }; diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h index 00b0068fda20..5d94db453df3 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.h +++ b/drivers/infiniband/ulp/srp/ib_srp.h @@ -62,9 +62,6 @@ enum { SRP_DEFAULT_CMD_SQ_SIZE = SRP_DEFAULT_QUEUE_SIZE - SRP_RSP_SQ_SIZE - SRP_TSK_MGMT_SQ_SIZE, - SRP_TAG_NO_REQ = ~0U, - SRP_TAG_TSK_MGMT = 1U << 31, - SRP_MAX_PAGES_PER_MR = 512, SRP_MAX_ADD_CDB_LEN = 16, @@ -79,6 +76,11 @@ enum { sizeof(struct srp_imm_buf), }; +enum { + SRP_TAG_NO_REQ = ~0U, + SRP_TAG_TSK_MGMT = BIT(31), +}; + enum srp_target_state { SRP_TARGET_SCANNING, SRP_TARGET_LIVE, diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index 8d8ebdc2039b..67f1c7364c95 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -51,7 +51,7 @@ module_param_array(ptr_size, int, NULL, 0444); MODULE_PARM_DESC(ptr_size, "Pointing device width, height in pixels (default 800,600)"); -static int xenkbd_remove(struct xenbus_device *); +static void xenkbd_remove(struct xenbus_device *); static int xenkbd_connect_backend(struct xenbus_device *, struct xenkbd_info *); static void xenkbd_disconnect_backend(struct xenkbd_info *); @@ -404,7 +404,7 @@ static int xenkbd_resume(struct xenbus_device *dev) return xenkbd_connect_backend(dev, info); } -static int xenkbd_remove(struct xenbus_device *dev) +static void xenkbd_remove(struct xenbus_device *dev) { struct xenkbd_info *info = dev_get_drvdata(&dev->dev); @@ -417,7 +417,6 @@ static int xenkbd_remove(struct xenbus_device *dev) input_unregister_device(info->mtouch); free_page((unsigned long)info->page); kfree(info); - return 0; } static int xenkbd_connect_backend(struct xenbus_device *dev, diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index b0f776448a1c..fa021af8506e 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -192,7 +192,6 @@ static const char * const smbus_pnp_ids[] = { "SYN3221", /* HP 15-ay000 */ "SYN323d", /* HP Spectre X360 13-w013dx */ "SYN3257", /* HP Envy 13-ad105ng */ - "SYN3286", /* HP Laptop 15-da3001TU */ NULL }; diff --git a/drivers/input/serio/i8042-acpipnpio.h b/drivers/input/serio/i8042-acpipnpio.h index 46f8a694291e..efc61736099b 100644 --- a/drivers/input/serio/i8042-acpipnpio.h +++ b/drivers/input/serio/i8042-acpipnpio.h @@ -1240,6 +1240,13 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { }, { .matches = { + DMI_MATCH(DMI_BOARD_NAME, "PCX0DX"), + }, + .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | + SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + }, + { + .matches = { DMI_MATCH(DMI_BOARD_NAME, "X170SM"), }, .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | diff --git a/drivers/interconnect/qcom/icc-rpm.c b/drivers/interconnect/qcom/icc-rpm.c index ba6781f54ab7..df3196f72536 100644 --- a/drivers/interconnect/qcom/icc-rpm.c +++ b/drivers/interconnect/qcom/icc-rpm.c @@ -488,7 +488,7 @@ int qnoc_probe(struct platform_device *pdev) } regmap_done: - ret = devm_clk_bulk_get(dev, qp->num_clks, qp->bus_clks); + ret = devm_clk_bulk_get_optional(dev, qp->num_clks, qp->bus_clks); if (ret) return ret; diff --git a/drivers/interconnect/qcom/msm8996.c b/drivers/interconnect/qcom/msm8996.c index c2903ae3b3bc..25a1a32bc611 100644 --- a/drivers/interconnect/qcom/msm8996.c +++ b/drivers/interconnect/qcom/msm8996.c @@ -33,6 +33,13 @@ static const char * const bus_a0noc_clocks[] = { "aggre0_noc_mpu_cfg" }; +static const char * const bus_a2noc_clocks[] = { + "bus", + "bus_a", + "aggre2_ufs_axi", + "ufs_axi" +}; + static const u16 mas_a0noc_common_links[] = { MSM8996_SLAVE_A0NOC_SNOC }; @@ -1806,7 +1813,7 @@ static const struct regmap_config msm8996_a0noc_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, - .max_register = 0x9000, + .max_register = 0x6000, .fast_io = true }; @@ -1830,7 +1837,7 @@ static const struct regmap_config msm8996_a1noc_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, - .max_register = 0x7000, + .max_register = 0x5000, .fast_io = true }; @@ -1851,7 +1858,7 @@ static const struct regmap_config msm8996_a2noc_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, - .max_register = 0xa000, + .max_register = 0x7000, .fast_io = true }; @@ -1859,6 +1866,8 @@ static const struct qcom_icc_desc msm8996_a2noc = { .type = QCOM_ICC_NOC, .nodes = a2noc_nodes, .num_nodes = ARRAY_SIZE(a2noc_nodes), + .clocks = bus_a2noc_clocks, + .num_clocks = ARRAY_SIZE(bus_a2noc_clocks), .regmap_cfg = &msm8996_a2noc_regmap_config }; @@ -1877,7 +1886,7 @@ static const struct regmap_config msm8996_bimc_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, - .max_register = 0x62000, + .max_register = 0x5a000, .fast_io = true }; @@ -1988,7 +1997,7 @@ static const struct regmap_config msm8996_mnoc_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, - .max_register = 0x20000, + .max_register = 0x1c000, .fast_io = true }; diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c index ab160198edd6..f2425b0f0cd6 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -3858,7 +3858,9 @@ static int arm_smmu_device_remove(struct platform_device *pdev) static void arm_smmu_device_shutdown(struct platform_device *pdev) { - arm_smmu_device_remove(pdev); + struct arm_smmu_device *smmu = platform_get_drvdata(pdev); + + arm_smmu_device_disable(smmu); } static const struct of_device_id arm_smmu_of_match[] = { diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c index 719fbca1fe52..2ff7a72cf377 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c @@ -1316,8 +1316,14 @@ static bool arm_smmu_capable(struct device *dev, enum iommu_cap cap) switch (cap) { case IOMMU_CAP_CACHE_COHERENCY: - /* Assume that a coherent TCU implies coherent TBUs */ - return cfg->smmu->features & ARM_SMMU_FEAT_COHERENT_WALK; + /* + * It's overwhelmingly the case in practice that when the pagetable + * walk interface is connected to a coherent interconnect, all the + * translation interfaces are too. Furthermore if the device is + * natively coherent, then its translation interface must also be. + */ + return cfg->smmu->features & ARM_SMMU_FEAT_COHERENT_WALK || + device_get_dma_attr(dev) == DEV_DMA_COHERENT; case IOMMU_CAP_NOEXEC: return true; default: @@ -2185,19 +2191,16 @@ static int arm_smmu_device_probe(struct platform_device *pdev) return 0; } -static int arm_smmu_device_remove(struct platform_device *pdev) +static void arm_smmu_device_shutdown(struct platform_device *pdev) { struct arm_smmu_device *smmu = platform_get_drvdata(pdev); if (!smmu) - return -ENODEV; + return; if (!bitmap_empty(smmu->context_map, ARM_SMMU_MAX_CBS)) dev_notice(&pdev->dev, "disabling translation\n"); - iommu_device_unregister(&smmu->iommu); - iommu_device_sysfs_remove(&smmu->iommu); - arm_smmu_rpm_get(smmu); /* Turn the thing off */ arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_sCR0, ARM_SMMU_sCR0_CLIENTPD); @@ -2209,12 +2212,21 @@ static int arm_smmu_device_remove(struct platform_device *pdev) clk_bulk_disable(smmu->num_clks, smmu->clks); clk_bulk_unprepare(smmu->num_clks, smmu->clks); - return 0; } -static void arm_smmu_device_shutdown(struct platform_device *pdev) +static int arm_smmu_device_remove(struct platform_device *pdev) { - arm_smmu_device_remove(pdev); + struct arm_smmu_device *smmu = platform_get_drvdata(pdev); + + if (!smmu) + return -ENODEV; + + iommu_device_unregister(&smmu->iommu); + iommu_device_sysfs_remove(&smmu->iommu); + + arm_smmu_device_shutdown(pdev); + + return 0; } static int __maybe_unused arm_smmu_runtime_resume(struct device *dev) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index de91dd88705b..5f6a85aea501 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -3185,14 +3185,16 @@ EXPORT_SYMBOL_GPL(iommu_group_claim_dma_owner); */ int iommu_device_claim_dma_owner(struct device *dev, void *owner) { - struct iommu_group *group = iommu_group_get(dev); + struct iommu_group *group; int ret = 0; - if (!group) - return -ENODEV; if (WARN_ON(!owner)) return -EINVAL; + group = iommu_group_get(dev); + if (!group) + return -ENODEV; + mutex_lock(&group->mutex); if (group->owner_cnt) { if (group->owner != owner) { diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c index a44ad92fc5eb..fe452ce46642 100644 --- a/drivers/iommu/iova.c +++ b/drivers/iommu/iova.c @@ -197,7 +197,7 @@ static int __alloc_and_insert_iova_range(struct iova_domain *iovad, curr = __get_cached_rbnode(iovad, limit_pfn); curr_iova = to_iova(curr); - retry_pfn = curr_iova->pfn_hi + 1; + retry_pfn = curr_iova->pfn_hi; retry: do { @@ -211,7 +211,7 @@ retry: if (high_pfn < size || new_pfn < low_pfn) { if (low_pfn == iovad->start_pfn && retry_pfn < limit_pfn) { high_pfn = limit_pfn; - low_pfn = retry_pfn; + low_pfn = retry_pfn + 1; curr = iova_find_limit(iovad, limit_pfn); curr_iova = to_iova(curr); goto retry; diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c index 69682ee068d2..ca581ff1c769 100644 --- a/drivers/iommu/mtk_iommu_v1.c +++ b/drivers/iommu/mtk_iommu_v1.c @@ -683,7 +683,7 @@ static int mtk_iommu_v1_probe(struct platform_device *pdev) ret = iommu_device_sysfs_add(&data->iommu, &pdev->dev, NULL, dev_name(&pdev->dev)); if (ret) - return ret; + goto out_clk_unprepare; ret = iommu_device_register(&data->iommu, &mtk_iommu_v1_ops, dev); if (ret) @@ -698,6 +698,8 @@ out_dev_unreg: iommu_device_unregister(&data->iommu); out_sysfs_remove: iommu_device_sysfs_remove(&data->iommu); +out_clk_unprepare: + clk_disable_unprepare(data->bclk); return ret; } diff --git a/drivers/md/bcache/bcache_ondisk.h b/drivers/md/bcache/bcache_ondisk.h index 97413586195b..f96034e0ba4f 100644 --- a/drivers/md/bcache/bcache_ondisk.h +++ b/drivers/md/bcache/bcache_ondisk.h @@ -106,7 +106,8 @@ static inline unsigned long bkey_bytes(const struct bkey *k) return bkey_u64s(k) * sizeof(__u64); } -#define bkey_copy(_dest, _src) memcpy(_dest, _src, bkey_bytes(_src)) +#define bkey_copy(_dest, _src) unsafe_memcpy(_dest, _src, bkey_bytes(_src), \ + /* bkey is always padded */) static inline void bkey_copy_key(struct bkey *dest, const struct bkey *src) { diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c index e5da469a4235..c182c21de2e8 100644 --- a/drivers/md/bcache/journal.c +++ b/drivers/md/bcache/journal.c @@ -149,7 +149,8 @@ add: bytes, GFP_KERNEL); if (!i) return -ENOMEM; - memcpy(&i->j, j, bytes); + unsafe_memcpy(&i->j, j, bytes, + /* "bytes" was calculated by set_bytes() above */); /* Add to the location after 'where' points to */ list_add(&i->list, where); ret = 1; diff --git a/drivers/md/dm.c b/drivers/md/dm.c index e1ea3a7bd9d9..b424a6ee27ba 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1742,6 +1742,8 @@ static void dm_split_and_process_bio(struct mapped_device *md, * otherwise associated queue_limits won't be imposed. */ bio = bio_split_to_limits(bio); + if (!bio) + return; } init_clone_info(&ci, md, map, bio, is_abnormal); diff --git a/drivers/md/md.c b/drivers/md/md.c index 775f1dde190a..02b0240e7c71 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -455,6 +455,8 @@ static void md_submit_bio(struct bio *bio) } bio = bio_split_to_limits(bio); + if (!bio) + return; if (mddev->ro == MD_RDONLY && unlikely(rw == WRITE)) { if (bio_sectors(bio) != 0) @@ -3642,7 +3644,7 @@ EXPORT_SYMBOL_GPL(md_rdev_init); */ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int super_minor) { - static struct md_rdev *claim_rdev; /* just for claiming the bdev */ + static struct md_rdev claim_rdev; /* just for claiming the bdev */ struct md_rdev *rdev; sector_t size; int err; @@ -3660,7 +3662,7 @@ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int supe rdev->bdev = blkdev_get_by_dev(newdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL, - super_format == -2 ? claim_rdev : rdev); + super_format == -2 ? &claim_rdev : rdev); if (IS_ERR(rdev->bdev)) { pr_warn("md: could not open device unknown-block(%u,%u).\n", MAJOR(newdev), MINOR(newdev)); diff --git a/drivers/media/platform/renesas/vsp1/vsp1_drv.c b/drivers/media/platform/renesas/vsp1/vsp1_drv.c index c260d318d298..5710152d6511 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_drv.c +++ b/drivers/media/platform/renesas/vsp1/vsp1_drv.c @@ -818,9 +818,9 @@ static const struct vsp1_device_info vsp1_device_infos[] = { .wpf_count = 2, .num_bru_inputs = 5, }, { - .version = VI6_IP_VERSION_MODEL_VSPD_V3U, + .version = VI6_IP_VERSION_MODEL_VSPD_GEN4, .model = "VSP2-D", - .gen = 3, + .gen = 4, .features = VSP1_HAS_BRU | VSP1_HAS_EXT_DL, .lif_count = 1, .rpf_count = 5, diff --git a/drivers/media/platform/renesas/vsp1/vsp1_hgo.c b/drivers/media/platform/renesas/vsp1/vsp1_hgo.c index bf3f981f93a1..e6492deb0a64 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_hgo.c +++ b/drivers/media/platform/renesas/vsp1/vsp1_hgo.c @@ -196,10 +196,10 @@ struct vsp1_hgo *vsp1_hgo_create(struct vsp1_device *vsp1) /* Initialize the control handler. */ v4l2_ctrl_handler_init(&hgo->ctrls.handler, - vsp1->info->gen == 3 ? 2 : 1); + vsp1->info->gen >= 3 ? 2 : 1); hgo->ctrls.max_rgb = v4l2_ctrl_new_custom(&hgo->ctrls.handler, &hgo_max_rgb_control, NULL); - if (vsp1->info->gen == 3) + if (vsp1->info->gen >= 3) hgo->ctrls.num_bins = v4l2_ctrl_new_custom(&hgo->ctrls.handler, &hgo_num_bins_control, NULL); diff --git a/drivers/media/platform/renesas/vsp1/vsp1_lif.c b/drivers/media/platform/renesas/vsp1/vsp1_lif.c index 186a5730e1e3..0ab2e0c70474 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_lif.c +++ b/drivers/media/platform/renesas/vsp1/vsp1_lif.c @@ -114,6 +114,7 @@ static void lif_configure_stream(struct vsp1_entity *entity, break; case VI6_IP_VERSION_MODEL_VSPD_GEN3: + case VI6_IP_VERSION_MODEL_VSPD_GEN4: default: hbth = 0; obth = 3000; diff --git a/drivers/media/platform/renesas/vsp1/vsp1_pipe.c b/drivers/media/platform/renesas/vsp1/vsp1_pipe.c index f72ac01c21ea..f8093ba9539e 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_pipe.c +++ b/drivers/media/platform/renesas/vsp1/vsp1_pipe.c @@ -146,6 +146,18 @@ static const struct vsp1_format_info vsp1_video_formats[] = { VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, 1, { 32, 0, 0 }, false, false, 1, 1, false }, + { V4L2_PIX_FMT_RGBX1010102, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_RGB10_RGB10A2_A2RGB10, + VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS, + 1, { 32, 0, 0 }, false, false, 1, 1, false }, + { V4L2_PIX_FMT_RGBA1010102, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_RGB10_RGB10A2_A2RGB10, + VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS, + 1, { 32, 0, 0 }, false, false, 1, 1, false }, + { V4L2_PIX_FMT_ARGB2101010, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_RGB10_RGB10A2_A2RGB10, + VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS, + 1, { 32, 0, 0 }, false, false, 1, 1, false }, { V4L2_PIX_FMT_UYVY, MEDIA_BUS_FMT_AYUV8_1X32, VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, @@ -202,6 +214,12 @@ static const struct vsp1_format_info vsp1_video_formats[] = { VI6_FMT_Y_U_V_444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, 3, { 8, 8, 8 }, false, true, 1, 1, false }, + { V4L2_PIX_FMT_Y210, MEDIA_BUS_FMT_AYUV8_1X32, + VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS, + 1, { 32, 0, 0 }, false, false, 2, 1, false }, + { V4L2_PIX_FMT_Y212, MEDIA_BUS_FMT_AYUV8_1X32, + VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS, + 1, { 32, 0, 0 }, false, false, 2, 1, false }, }; /** diff --git a/drivers/media/platform/renesas/vsp1/vsp1_regs.h b/drivers/media/platform/renesas/vsp1/vsp1_regs.h index 8928f4c6bb55..d94343ae57a1 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_regs.h +++ b/drivers/media/platform/renesas/vsp1/vsp1_regs.h @@ -228,6 +228,28 @@ #define VI6_RPF_MULT_ALPHA_RATIO_MASK (0xff << 0) #define VI6_RPF_MULT_ALPHA_RATIO_SHIFT 0 +#define VI6_RPF_EXT_INFMT0 0x0370 +#define VI6_RPF_EXT_INFMT0_F2B BIT(12) +#define VI6_RPF_EXT_INFMT0_IPBD_Y_8 (0 << 8) +#define VI6_RPF_EXT_INFMT0_IPBD_Y_10 (1 << 8) +#define VI6_RPF_EXT_INFMT0_IPBD_Y_12 (2 << 8) +#define VI6_RPF_EXT_INFMT0_IPBD_C_8 (0 << 4) +#define VI6_RPF_EXT_INFMT0_IPBD_C_10 (1 << 4) +#define VI6_RPF_EXT_INFMT0_IPBD_C_12 (2 << 4) +#define VI6_RPF_EXT_INFMT0_BYPP_M1_RGB10 (3 << 0) + +#define VI6_RPF_EXT_INFMT1 0x0374 +#define VI6_RPF_EXT_INFMT1_PACK_CPOS(a, b, c, d) \ + (((a) << 24) | ((b) << 16) | ((c) << 8) | ((d) << 0)) + +#define VI6_RPF_EXT_INFMT2 0x0378 +#define VI6_RPF_EXT_INFMT2_PACK_CLEN(a, b, c, d) \ + (((a) << 24) | ((b) << 16) | ((c) << 8) | ((d) << 0)) + +#define VI6_RPF_BRDITH_CTRL 0x03e0 +#define VI6_RPF_BRDITH_CTRL_ODE BIT(8) +#define VI6_RPF_BRDITH_CTRL_CBRM BIT(0) + /* ----------------------------------------------------------------------------- * WPF Control Registers */ @@ -766,7 +788,7 @@ #define VI6_IP_VERSION_MODEL_VSPD_V3 (0x18 << 8) #define VI6_IP_VERSION_MODEL_VSPDL_GEN3 (0x19 << 8) #define VI6_IP_VERSION_MODEL_VSPBS_GEN3 (0x1a << 8) -#define VI6_IP_VERSION_MODEL_VSPD_V3U (0x1c << 8) +#define VI6_IP_VERSION_MODEL_VSPD_GEN4 (0x1c << 8) /* RZ/G2L SoCs have no version register, So use 0x80 as the model version */ #define VI6_IP_VERSION_MODEL_VSPD_RZG2L (0x80 << 8) @@ -782,6 +804,7 @@ #define VI6_IP_VERSION_SOC_M3N (0x04 << 0) #define VI6_IP_VERSION_SOC_E3 (0x04 << 0) #define VI6_IP_VERSION_SOC_V3U (0x05 << 0) +#define VI6_IP_VERSION_SOC_V4H (0x06 << 0) /* RZ/G2L SoCs have no version register, So use 0x80 for SoC Identification */ #define VI6_IP_VERSION_SOC_RZG2L (0x80 << 0) @@ -845,6 +868,7 @@ #define VI6_FMT_XBXGXR_262626 0x21 #define VI6_FMT_ABGR_8888 0x22 #define VI6_FMT_XXRGB_88565 0x23 +#define VI6_FMT_RGB10_RGB10A2_A2RGB10 0x30 #define VI6_FMT_Y_UV_444 0x40 #define VI6_FMT_Y_UV_422 0x41 diff --git a/drivers/media/platform/renesas/vsp1/vsp1_rpf.c b/drivers/media/platform/renesas/vsp1/vsp1_rpf.c index 75083cb234fe..3b17f5fa4067 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/renesas/vsp1/vsp1_rpf.c @@ -109,6 +109,58 @@ static void rpf_configure_stream(struct vsp1_entity *entity, vsp1_rpf_write(rpf, dlb, VI6_RPF_INFMT, infmt); vsp1_rpf_write(rpf, dlb, VI6_RPF_DSWAP, fmtinfo->swap); + if (entity->vsp1->info->gen == 4) { + u32 ext_infmt0; + u32 ext_infmt1; + u32 ext_infmt2; + + switch (fmtinfo->fourcc) { + case V4L2_PIX_FMT_RGBX1010102: + ext_infmt0 = VI6_RPF_EXT_INFMT0_BYPP_M1_RGB10; + ext_infmt1 = VI6_RPF_EXT_INFMT1_PACK_CPOS(0, 10, 20, 0); + ext_infmt2 = VI6_RPF_EXT_INFMT2_PACK_CLEN(10, 10, 10, 0); + break; + + case V4L2_PIX_FMT_RGBA1010102: + ext_infmt0 = VI6_RPF_EXT_INFMT0_BYPP_M1_RGB10; + ext_infmt1 = VI6_RPF_EXT_INFMT1_PACK_CPOS(0, 10, 20, 30); + ext_infmt2 = VI6_RPF_EXT_INFMT2_PACK_CLEN(10, 10, 10, 2); + break; + + case V4L2_PIX_FMT_ARGB2101010: + ext_infmt0 = VI6_RPF_EXT_INFMT0_BYPP_M1_RGB10; + ext_infmt1 = VI6_RPF_EXT_INFMT1_PACK_CPOS(2, 12, 22, 0); + ext_infmt2 = VI6_RPF_EXT_INFMT2_PACK_CLEN(10, 10, 10, 2); + break; + + case V4L2_PIX_FMT_Y210: + ext_infmt0 = VI6_RPF_EXT_INFMT0_F2B | + VI6_RPF_EXT_INFMT0_IPBD_Y_10 | + VI6_RPF_EXT_INFMT0_IPBD_C_10; + ext_infmt1 = 0x0; + ext_infmt2 = 0x0; + break; + + case V4L2_PIX_FMT_Y212: + ext_infmt0 = VI6_RPF_EXT_INFMT0_F2B | + VI6_RPF_EXT_INFMT0_IPBD_Y_12 | + VI6_RPF_EXT_INFMT0_IPBD_C_12; + ext_infmt1 = 0x0; + ext_infmt2 = 0x0; + break; + + default: + ext_infmt0 = 0; + ext_infmt1 = 0; + ext_infmt2 = 0; + break; + } + + vsp1_rpf_write(rpf, dlb, VI6_RPF_EXT_INFMT0, ext_infmt0); + vsp1_rpf_write(rpf, dlb, VI6_RPF_EXT_INFMT1, ext_infmt1); + vsp1_rpf_write(rpf, dlb, VI6_RPF_EXT_INFMT2, ext_infmt2); + } + /* Output location. */ if (pipe->brx) { const struct v4l2_rect *compose; @@ -133,18 +185,18 @@ static void rpf_configure_stream(struct vsp1_entity *entity, * a fixed alpha value set through the V4L2_CID_ALPHA_COMPONENT control * otherwise. * - * The Gen3 RPF has extended alpha capability and can both multiply the + * The Gen3+ RPF has extended alpha capability and can both multiply the * alpha channel by a fixed global alpha value, and multiply the pixel * components to convert the input to premultiplied alpha. * * As alpha premultiplication is available in the BRx for both Gen2 and - * Gen3 we handle it there and use the Gen3 alpha multiplier for global + * Gen3+ we handle it there and use the Gen3 alpha multiplier for global * alpha multiplication only. This however prevents conversion to * premultiplied alpha if no BRx is present in the pipeline. If that use * case turns out to be useful we will revisit the implementation (for * Gen3 only). * - * We enable alpha multiplication on Gen3 using the fixed alpha value + * We enable alpha multiplication on Gen3+ using the fixed alpha value * set through the V4L2_CID_ALPHA_COMPONENT control when the input * contains an alpha channel. On Gen2 the global alpha is ignored in * that case. @@ -155,7 +207,7 @@ static void rpf_configure_stream(struct vsp1_entity *entity, (fmtinfo->alpha ? VI6_RPF_ALPH_SEL_ASEL_PACKED : VI6_RPF_ALPH_SEL_ASEL_FIXED)); - if (entity->vsp1->info->gen == 3) { + if (entity->vsp1->info->gen >= 3) { u32 mult; if (fmtinfo->alpha) { @@ -301,10 +353,10 @@ static void rpf_configure_partition(struct vsp1_entity *entity, } /* - * On Gen3 hardware the SPUVS bit has no effect on 3-planar + * On Gen3+ hardware the SPUVS bit has no effect on 3-planar * formats. Swap the U and V planes manually in that case. */ - if (vsp1->info->gen == 3 && format->num_planes == 3 && + if (vsp1->info->gen >= 3 && format->num_planes == 3 && fmtinfo->swap_uv) swap(mem.addr[1], mem.addr[2]); diff --git a/drivers/media/platform/renesas/vsp1/vsp1_video.c b/drivers/media/platform/renesas/vsp1/vsp1_video.c index 9d24647c8f32..544012fd1fe9 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_video.c +++ b/drivers/media/platform/renesas/vsp1/vsp1_video.c @@ -267,10 +267,10 @@ static int vsp1_video_pipeline_setup_partitions(struct vsp1_pipeline *pipe) div_size = format->width; /* - * Only Gen3 hardware requires image partitioning, Gen2 will operate + * Only Gen3+ hardware requires image partitioning, Gen2 will operate * with a single partition that covers the whole output. */ - if (vsp1->info->gen == 3) { + if (vsp1->info->gen >= 3) { list_for_each_entry(entity, &pipe->entities, list_pipe) { unsigned int entity_max; diff --git a/drivers/media/platform/renesas/vsp1/vsp1_wpf.c b/drivers/media/platform/renesas/vsp1/vsp1_wpf.c index 94e91d7bb56c..d0074ca00920 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/renesas/vsp1/vsp1_wpf.c @@ -512,10 +512,10 @@ static void wpf_configure_partition(struct vsp1_entity *entity, } /* - * On Gen3 hardware the SPUVS bit has no effect on 3-planar + * On Gen3+ hardware the SPUVS bit has no effect on 3-planar * formats. Swap the U and V planes manually in that case. */ - if (vsp1->info->gen == 3 && format->num_planes == 3 && + if (vsp1->info->gen >= 3 && format->num_planes == 3 && fmtinfo->swap_uv) swap(mem.addr[1], mem.addr[2]); diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 8e0a0ff62a70..2a0139c72d29 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1298,6 +1298,9 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_PIX_FMT_BGRX32: descr = "32-bit XBGR 8-8-8-8"; break; case V4L2_PIX_FMT_RGBA32: descr = "32-bit RGBA 8-8-8-8"; break; case V4L2_PIX_FMT_RGBX32: descr = "32-bit RGBX 8-8-8-8"; break; + case V4L2_PIX_FMT_RGBX1010102: descr = "32-bit RGBX 10-10-10-2"; break; + case V4L2_PIX_FMT_RGBA1010102: descr = "32-bit RGBA 10-10-10-2"; break; + case V4L2_PIX_FMT_ARGB2101010: descr = "32-bit ARGB 2-10-10-10"; break; case V4L2_PIX_FMT_GREY: descr = "8-bit Greyscale"; break; case V4L2_PIX_FMT_Y4: descr = "4-bit Greyscale"; break; case V4L2_PIX_FMT_Y6: descr = "6-bit Greyscale"; break; @@ -1442,6 +1445,9 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_PIX_FMT_NV12M_8L128: descr = "NV12M (8x128 Linear)"; break; case V4L2_PIX_FMT_NV12_10BE_8L128: descr = "10-bit NV12 (8x128 Linear, BE)"; break; case V4L2_PIX_FMT_NV12M_10BE_8L128: descr = "10-bit NV12M (8x128 Linear, BE)"; break; + case V4L2_PIX_FMT_Y210: descr = "10-bit YUYV Packed"; break; + case V4L2_PIX_FMT_Y212: descr = "12-bit YUYV Packed"; break; + case V4L2_PIX_FMT_Y216: descr = "16-bit YUYV Packed"; break; default: /* Compressed formats */ diff --git a/drivers/memory/atmel-sdramc.c b/drivers/memory/atmel-sdramc.c index 9c49d00c2a96..ea6e9e1eaf04 100644 --- a/drivers/memory/atmel-sdramc.c +++ b/drivers/memory/atmel-sdramc.c @@ -47,19 +47,17 @@ static int atmel_ramc_probe(struct platform_device *pdev) caps = of_device_get_match_data(&pdev->dev); if (caps->has_ddrck) { - clk = devm_clk_get(&pdev->dev, "ddrck"); + clk = devm_clk_get_enabled(&pdev->dev, "ddrck"); if (IS_ERR(clk)) return PTR_ERR(clk); - clk_prepare_enable(clk); } if (caps->has_mpddr_clk) { - clk = devm_clk_get(&pdev->dev, "mpddr"); + clk = devm_clk_get_enabled(&pdev->dev, "mpddr"); if (IS_ERR(clk)) { pr_err("AT91 RAMC: couldn't get mpddr clock\n"); return PTR_ERR(clk); } - clk_prepare_enable(clk); } return 0; diff --git a/drivers/memory/mvebu-devbus.c b/drivers/memory/mvebu-devbus.c index 8450638e8670..efc6c08db2b7 100644 --- a/drivers/memory/mvebu-devbus.c +++ b/drivers/memory/mvebu-devbus.c @@ -280,10 +280,9 @@ static int mvebu_devbus_probe(struct platform_device *pdev) if (IS_ERR(devbus->base)) return PTR_ERR(devbus->base); - clk = devm_clk_get(&pdev->dev, NULL); + clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(clk)) return PTR_ERR(clk); - clk_prepare_enable(clk); /* * Obtain clock period in picoseconds, diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index 57d9f91fe89b..d78f73db37c8 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -1918,7 +1918,8 @@ int gpmc_cs_program_settings(int cs, struct gpmc_settings *p) } } - if (p->wait_pin > gpmc_nr_waitpins) { + if (p->wait_pin != GPMC_WAITPIN_INVALID && + p->wait_pin > gpmc_nr_waitpins) { pr_err("%s: invalid wait-pin (%d)\n", __func__, p->wait_pin); return -EINVAL; } diff --git a/drivers/memory/tegra/tegra186.c b/drivers/memory/tegra/tegra186.c index 62477e592bf5..7bb73f06fad3 100644 --- a/drivers/memory/tegra/tegra186.c +++ b/drivers/memory/tegra/tegra186.c @@ -22,32 +22,6 @@ #define MC_SID_STREAMID_SECURITY_WRITE_ACCESS_DISABLED BIT(16) #define MC_SID_STREAMID_SECURITY_OVERRIDE BIT(8) -static void tegra186_mc_program_sid(struct tegra_mc *mc) -{ - unsigned int i; - - for (i = 0; i < mc->soc->num_clients; i++) { - const struct tegra_mc_client *client = &mc->soc->clients[i]; - u32 override, security; - - override = readl(mc->regs + client->regs.sid.override); - security = readl(mc->regs + client->regs.sid.security); - - dev_dbg(mc->dev, "client %s: override: %x security: %x\n", - client->name, override, security); - - dev_dbg(mc->dev, "setting SID %u for %s\n", client->sid, - client->name); - writel(client->sid, mc->regs + client->regs.sid.override); - - override = readl(mc->regs + client->regs.sid.override); - security = readl(mc->regs + client->regs.sid.security); - - dev_dbg(mc->dev, "client %s: override: %x security: %x\n", - client->name, override, security); - } -} - static int tegra186_mc_probe(struct tegra_mc *mc) { struct platform_device *pdev = to_platform_device(mc->dev); @@ -85,8 +59,6 @@ populate: if (err < 0) return err; - tegra186_mc_program_sid(mc); - return 0; } @@ -95,13 +67,6 @@ static void tegra186_mc_remove(struct tegra_mc *mc) of_platform_depopulate(mc->dev); } -static int tegra186_mc_resume(struct tegra_mc *mc) -{ - tegra186_mc_program_sid(mc); - - return 0; -} - #if IS_ENABLED(CONFIG_IOMMU_API) static void tegra186_mc_client_sid_override(struct tegra_mc *mc, const struct tegra_mc_client *client, @@ -173,7 +138,6 @@ static int tegra186_mc_probe_device(struct tegra_mc *mc, struct device *dev) const struct tegra_mc_ops tegra186_mc_ops = { .probe = tegra186_mc_probe, .remove = tegra186_mc_remove, - .resume = tegra186_mc_resume, .probe_device = tegra186_mc_probe_device, .handle_irq = tegra30_mc_handle_irq, }; diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 9947b7892bd5..a615605d6d56 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -532,7 +532,6 @@ source "drivers/misc/cxl/Kconfig" source "drivers/misc/ocxl/Kconfig" source "drivers/misc/bcm-vk/Kconfig" source "drivers/misc/cardreader/Kconfig" -source "drivers/misc/habanalabs/Kconfig" source "drivers/misc/uacce/Kconfig" source "drivers/misc/pvpanic/Kconfig" source "drivers/misc/mchp_pci1xxxx/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 87b54a4a4422..33f80469e5f4 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -56,7 +56,6 @@ obj-$(CONFIG_OCXL) += ocxl/ obj-$(CONFIG_BCM_VK) += bcm-vk/ obj-y += cardreader/ obj-$(CONFIG_PVPANIC) += pvpanic/ -obj-$(CONFIG_HABANA_AI) += habanalabs/ obj-$(CONFIG_UACCE) += uacce/ obj-$(CONFIG_XILINX_SDFEC) += xilinx_sdfec.o obj-$(CONFIG_HISI_HIKEY_USB) += hisi_hikey_usb.o diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index c9902a1dcf5d..5310606113fe 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -321,7 +321,7 @@ static void fastrpc_free_map(struct kref *ref) perm.vmid = QCOM_SCM_VMID_HLOS; perm.perm = QCOM_SCM_PERM_RWX; err = qcom_scm_assign_mem(map->phys, map->size, - &(map->fl->cctx->vmperms[0].vmid), &perm, 1); + &map->fl->cctx->perms, &perm, 1); if (err) { dev_err(map->fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d", map->phys, map->size, err); @@ -334,6 +334,13 @@ static void fastrpc_free_map(struct kref *ref) dma_buf_put(map->buf); } + if (map->fl) { + spin_lock(&map->fl->lock); + list_del(&map->node); + spin_unlock(&map->fl->lock); + map->fl = NULL; + } + kfree(map); } @@ -343,38 +350,41 @@ static void fastrpc_map_put(struct fastrpc_map *map) kref_put(&map->refcount, fastrpc_free_map); } -static void fastrpc_map_get(struct fastrpc_map *map) +static int fastrpc_map_get(struct fastrpc_map *map) { - if (map) - kref_get(&map->refcount); + if (!map) + return -ENOENT; + + return kref_get_unless_zero(&map->refcount) ? 0 : -ENOENT; } static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd, - struct fastrpc_map **ppmap) + struct fastrpc_map **ppmap, bool take_ref) { + struct fastrpc_session_ctx *sess = fl->sctx; struct fastrpc_map *map = NULL; + int ret = -ENOENT; - mutex_lock(&fl->mutex); + spin_lock(&fl->lock); list_for_each_entry(map, &fl->maps, node) { - if (map->fd == fd) { - *ppmap = map; - mutex_unlock(&fl->mutex); - return 0; - } - } - mutex_unlock(&fl->mutex); - - return -ENOENT; -} + if (map->fd != fd) + continue; -static int fastrpc_map_find(struct fastrpc_user *fl, int fd, - struct fastrpc_map **ppmap) -{ - int ret = fastrpc_map_lookup(fl, fd, ppmap); + if (take_ref) { + ret = fastrpc_map_get(map); + if (ret) { + dev_dbg(sess->dev, "%s: Failed to get map fd=%d ret=%d\n", + __func__, fd, ret); + break; + } + } - if (!ret) - fastrpc_map_get(*ppmap); + *ppmap = map; + ret = 0; + break; + } + spin_unlock(&fl->lock); return ret; } @@ -746,7 +756,7 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd, struct fastrpc_map *map = NULL; int err = 0; - if (!fastrpc_map_find(fl, fd, ppmap)) + if (!fastrpc_map_lookup(fl, fd, ppmap, true)) return 0; map = kzalloc(sizeof(*map), GFP_KERNEL); @@ -788,10 +798,8 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd, * If subsystem VMIDs are defined in DTSI, then do * hyp_assign from HLOS to those VM(s) */ - unsigned int perms = BIT(QCOM_SCM_VMID_HLOS); - map->attr = attr; - err = qcom_scm_assign_mem(map->phys, (u64)map->size, &perms, + err = qcom_scm_assign_mem(map->phys, (u64)map->size, &fl->cctx->perms, fl->cctx->vmperms, fl->cctx->vmcount); if (err) { dev_err(sess->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d", @@ -1070,7 +1078,7 @@ static int fastrpc_put_args(struct fastrpc_invoke_ctx *ctx, for (i = 0; i < FASTRPC_MAX_FDLIST; i++) { if (!fdlist[i]) break; - if (!fastrpc_map_lookup(fl, (int)fdlist[i], &mmap)) + if (!fastrpc_map_lookup(fl, (int)fdlist[i], &mmap, false)) fastrpc_map_put(mmap); } @@ -1258,10 +1266,9 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, /* Map if we have any heap VMIDs associated with this ADSP Static Process. */ if (fl->cctx->vmcount) { - unsigned int perms = BIT(QCOM_SCM_VMID_HLOS); - err = qcom_scm_assign_mem(fl->cctx->remote_heap->phys, - (u64)fl->cctx->remote_heap->size, &perms, + (u64)fl->cctx->remote_heap->size, + &fl->cctx->perms, fl->cctx->vmperms, fl->cctx->vmcount); if (err) { dev_err(fl->sctx->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d", @@ -1309,7 +1316,7 @@ err_invoke: perm.perm = QCOM_SCM_PERM_RWX; err = qcom_scm_assign_mem(fl->cctx->remote_heap->phys, (u64)fl->cctx->remote_heap->size, - &(fl->cctx->vmperms[0].vmid), &perm, 1); + &fl->cctx->perms, &perm, 1); if (err) dev_err(fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d", fl->cctx->remote_heap->phys, fl->cctx->remote_heap->size, err); @@ -1433,12 +1440,7 @@ err_invoke: fl->init_mem = NULL; fastrpc_buf_free(imem); err_alloc: - if (map) { - spin_lock(&fl->lock); - list_del(&map->node); - spin_unlock(&fl->lock); - fastrpc_map_put(map); - } + fastrpc_map_put(map); err: kfree(args); @@ -1514,10 +1516,8 @@ static int fastrpc_device_release(struct inode *inode, struct file *file) fastrpc_context_put(ctx); } - list_for_each_entry_safe(map, m, &fl->maps, node) { - list_del(&map->node); + list_for_each_entry_safe(map, m, &fl->maps, node) fastrpc_map_put(map); - } list_for_each_entry_safe(buf, b, &fl->mmaps, node) { list_del(&buf->node); @@ -1894,12 +1894,11 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp) /* Add memory to static PD pool, protection thru hypervisor */ if (req.flags != ADSP_MMAP_REMOTE_HEAP_ADDR && fl->cctx->vmcount) { struct qcom_scm_vmperm perm; - int err = 0; perm.vmid = QCOM_SCM_VMID_HLOS; perm.perm = QCOM_SCM_PERM_RWX; err = qcom_scm_assign_mem(buf->phys, buf->size, - &(fl->cctx->vmperms[0].vmid), &perm, 1); + &fl->cctx->perms, &perm, 1); if (err) { dev_err(fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d", buf->phys, buf->size, err); diff --git a/drivers/misc/habanalabs/include/gaudi2/arc/gaudi2_arc_common_packets.h b/drivers/misc/habanalabs/include/gaudi2/arc/gaudi2_arc_common_packets.h deleted file mode 100644 index 2cf30c206ac6..000000000000 --- a/drivers/misc/habanalabs/include/gaudi2/arc/gaudi2_arc_common_packets.h +++ /dev/null @@ -1,213 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 - * - * Copyright (C) 2020 HabanaLabs Ltd. - * All Rights Reserved. - */ - -#ifndef __GAUDI2_ARC_COMMON_PACKETS_H__ -#define __GAUDI2_ARC_COMMON_PACKETS_H__ - -/* - * CPU IDs for each ARC CPUs - */ - -#define CPU_ID_SCHED_ARC0 0 /* FARM_ARC0 */ -#define CPU_ID_SCHED_ARC1 1 /* FARM_ARC1 */ -#define CPU_ID_SCHED_ARC2 2 /* FARM_ARC2 */ -#define CPU_ID_SCHED_ARC3 3 /* FARM_ARC3 */ -/* Dcore1 MME Engine ARC instance used as scheduler */ -#define CPU_ID_SCHED_ARC4 4 /* DCORE1_MME0 */ -/* Dcore3 MME Engine ARC instance used as scheduler */ -#define CPU_ID_SCHED_ARC5 5 /* DCORE3_MME0 */ - -#define CPU_ID_TPC_QMAN_ARC0 6 /* DCORE0_TPC0 */ -#define CPU_ID_TPC_QMAN_ARC1 7 /* DCORE0_TPC1 */ -#define CPU_ID_TPC_QMAN_ARC2 8 /* DCORE0_TPC2 */ -#define CPU_ID_TPC_QMAN_ARC3 9 /* DCORE0_TPC3 */ -#define CPU_ID_TPC_QMAN_ARC4 10 /* DCORE0_TPC4 */ -#define CPU_ID_TPC_QMAN_ARC5 11 /* DCORE0_TPC5 */ -#define CPU_ID_TPC_QMAN_ARC6 12 /* DCORE1_TPC0 */ -#define CPU_ID_TPC_QMAN_ARC7 13 /* DCORE1_TPC1 */ -#define CPU_ID_TPC_QMAN_ARC8 14 /* DCORE1_TPC2 */ -#define CPU_ID_TPC_QMAN_ARC9 15 /* DCORE1_TPC3 */ -#define CPU_ID_TPC_QMAN_ARC10 16 /* DCORE1_TPC4 */ -#define CPU_ID_TPC_QMAN_ARC11 17 /* DCORE1_TPC5 */ -#define CPU_ID_TPC_QMAN_ARC12 18 /* DCORE2_TPC0 */ -#define CPU_ID_TPC_QMAN_ARC13 19 /* DCORE2_TPC1 */ -#define CPU_ID_TPC_QMAN_ARC14 20 /* DCORE2_TPC2 */ -#define CPU_ID_TPC_QMAN_ARC15 21 /* DCORE2_TPC3 */ -#define CPU_ID_TPC_QMAN_ARC16 22 /* DCORE2_TPC4 */ -#define CPU_ID_TPC_QMAN_ARC17 23 /* DCORE2_TPC5 */ -#define CPU_ID_TPC_QMAN_ARC18 24 /* DCORE3_TPC0 */ -#define CPU_ID_TPC_QMAN_ARC19 25 /* DCORE3_TPC1 */ -#define CPU_ID_TPC_QMAN_ARC20 26 /* DCORE3_TPC2 */ -#define CPU_ID_TPC_QMAN_ARC21 27 /* DCORE3_TPC3 */ -#define CPU_ID_TPC_QMAN_ARC22 28 /* DCORE3_TPC4 */ -#define CPU_ID_TPC_QMAN_ARC23 29 /* DCORE3_TPC5 */ -#define CPU_ID_TPC_QMAN_ARC24 30 /* DCORE0_TPC6 - Never present */ - -#define CPU_ID_MME_QMAN_ARC0 31 /* DCORE0_MME0 */ -#define CPU_ID_MME_QMAN_ARC1 32 /* DCORE2_MME0 */ - -#define CPU_ID_EDMA_QMAN_ARC0 33 /* DCORE0_EDMA0 */ -#define CPU_ID_EDMA_QMAN_ARC1 34 /* DCORE0_EDMA1 */ -#define CPU_ID_EDMA_QMAN_ARC2 35 /* DCORE1_EDMA0 */ -#define CPU_ID_EDMA_QMAN_ARC3 36 /* DCORE1_EDMA1 */ -#define CPU_ID_EDMA_QMAN_ARC4 37 /* DCORE2_EDMA0 */ -#define CPU_ID_EDMA_QMAN_ARC5 38 /* DCORE2_EDMA1 */ -#define CPU_ID_EDMA_QMAN_ARC6 39 /* DCORE3_EDMA0 */ -#define CPU_ID_EDMA_QMAN_ARC7 40 /* DCORE3_EDMA1 */ - -#define CPU_ID_PDMA_QMAN_ARC0 41 /* DCORE0_PDMA0 */ -#define CPU_ID_PDMA_QMAN_ARC1 42 /* DCORE0_PDMA1 */ - -#define CPU_ID_ROT_QMAN_ARC0 43 /* ROT0 */ -#define CPU_ID_ROT_QMAN_ARC1 44 /* ROT1 */ - -#define CPU_ID_NIC_QMAN_ARC0 45 /* NIC0_0 */ -#define CPU_ID_NIC_QMAN_ARC1 46 /* NIC0_1 */ -#define CPU_ID_NIC_QMAN_ARC2 47 /* NIC1_0 */ -#define CPU_ID_NIC_QMAN_ARC3 48 /* NIC1_1 */ -#define CPU_ID_NIC_QMAN_ARC4 49 /* NIC2_0 */ -#define CPU_ID_NIC_QMAN_ARC5 50 /* NIC2_1 */ -#define CPU_ID_NIC_QMAN_ARC6 51 /* NIC3_0 */ -#define CPU_ID_NIC_QMAN_ARC7 52 /* NIC3_1 */ -#define CPU_ID_NIC_QMAN_ARC8 53 /* NIC4_0 */ -#define CPU_ID_NIC_QMAN_ARC9 54 /* NIC4_1 */ -#define CPU_ID_NIC_QMAN_ARC10 55 /* NIC5_0 */ -#define CPU_ID_NIC_QMAN_ARC11 56 /* NIC5_1 */ -#define CPU_ID_NIC_QMAN_ARC12 57 /* NIC6_0 */ -#define CPU_ID_NIC_QMAN_ARC13 58 /* NIC6_1 */ -#define CPU_ID_NIC_QMAN_ARC14 59 /* NIC7_0 */ -#define CPU_ID_NIC_QMAN_ARC15 60 /* NIC7_1 */ -#define CPU_ID_NIC_QMAN_ARC16 61 /* NIC8_0 */ -#define CPU_ID_NIC_QMAN_ARC17 62 /* NIC8_1 */ -#define CPU_ID_NIC_QMAN_ARC18 63 /* NIC9_0 */ -#define CPU_ID_NIC_QMAN_ARC19 64 /* NIC9_1 */ -#define CPU_ID_NIC_QMAN_ARC20 65 /* NIC10_0 */ -#define CPU_ID_NIC_QMAN_ARC21 66 /* NIC10_1 */ -#define CPU_ID_NIC_QMAN_ARC22 67 /* NIC11_0 */ -#define CPU_ID_NIC_QMAN_ARC23 68 /* NIC11_1 */ - -#define CPU_ID_MAX 69 -#define CPU_ID_SCHED_MAX 6 - -#define CPU_ID_ALL 0xFE -#define CPU_ID_INVALID 0xFF - -enum arc_regions_t { - ARC_REGION0_UNSED = 0, - /* - * Extension registers - * None - */ - ARC_REGION1_SRAM = 1, - /* - * Extension registers - * AUX_SRAM_LSB_ADDR - * AUX_SRAM_MSB_ADDR - * ARC Address: 0x1000_0000 - */ - ARC_REGION2_CFG = 2, - /* - * Extension registers - * AUX_CFG_LSB_ADDR - * AUX_CFG_MSB_ADDR - * ARC Address: 0x2000_0000 - */ - ARC_REGION3_GENERAL = 3, - /* - * Extension registers - * AUX_GENERAL_PURPOSE_LSB_ADDR_0 - * AUX_GENERAL_PURPOSE_MSB_ADDR_0 - * ARC Address: 0x3000_0000 - */ - ARC_REGION4_HBM0_FW = 4, - /* - * Extension registers - * AUX_HBM0_LSB_ADDR - * AUX_HBM0_MSB_ADDR - * AUX_HBM0_OFFSET - * ARC Address: 0x4000_0000 - */ - ARC_REGION5_HBM1_GC_DATA = 5, - /* - * Extension registers - * AUX_HBM1_LSB_ADDR - * AUX_HBM1_MSB_ADDR - * AUX_HBM1_OFFSET - * ARC Address: 0x5000_0000 - */ - ARC_REGION6_HBM2_GC_DATA = 6, - /* - * Extension registers - * AUX_HBM2_LSB_ADDR - * AUX_HBM2_MSB_ADDR - * AUX_HBM2_OFFSET - * ARC Address: 0x6000_0000 - */ - ARC_REGION7_HBM3_GC_DATA = 7, - /* - * Extension registers - * AUX_HBM3_LSB_ADDR - * AUX_HBM3_MSB_ADDR - * AUX_HBM3_OFFSET - * ARC Address: 0x7000_0000 - */ - ARC_REGION8_DCCM = 8, - /* - * Extension registers - * None - * ARC Address: 0x8000_0000 - */ - ARC_REGION9_PCIE = 9, - /* - * Extension registers - * AUX_PCIE_LSB_ADDR - * AUX_PCIE_MSB_ADDR - * ARC Address: 0x9000_0000 - */ - ARC_REGION10_GENERAL = 10, - /* - * Extension registers - * AUX_GENERAL_PURPOSE_LSB_ADDR_1 - * AUX_GENERAL_PURPOSE_MSB_ADDR_1 - * ARC Address: 0xA000_0000 - */ - ARC_REGION11_GENERAL = 11, - /* - * Extension registers - * AUX_GENERAL_PURPOSE_LSB_ADDR_2 - * AUX_GENERAL_PURPOSE_MSB_ADDR_2 - * ARC Address: 0xB000_0000 - */ - ARC_REGION12_GENERAL = 12, - /* - * Extension registers - * AUX_GENERAL_PURPOSE_LSB_ADDR_3 - * AUX_GENERAL_PURPOSE_MSB_ADDR_3 - * ARC Address: 0xC000_0000 - */ - ARC_REGION13_GENERAL = 13, - /* - * Extension registers - * AUX_GENERAL_PURPOSE_LSB_ADDR_4 - * AUX_GENERAL_PURPOSE_MSB_ADDR_4 - * ARC Address: 0xD000_0000 - */ - ARC_REGION14_GENERAL = 14, - /* - * Extension registers - * AUX_GENERAL_PURPOSE_LSB_ADDR_5 - * AUX_GENERAL_PURPOSE_MSB_ADDR_5 - * ARC Address: 0xE000_0000 - */ - ARC_REGION15_LBU = 15 - /* - * Extension registers - * None - * ARC Address: 0xF000_0000 - */ -}; - -#endif /* __GAUDI2_ARC_COMMON_PACKETS_H__ */ diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 4a08b624910a..a81b890c7ee6 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -702,13 +702,15 @@ void *mei_cldev_dma_map(struct mei_cl_device *cldev, u8 buffer_id, size_t size) if (cl->state == MEI_FILE_UNINITIALIZED) { ret = mei_cl_link(cl); if (ret) - goto out; + goto notlinked; /* update pointers */ cl->cldev = cldev; } ret = mei_cl_dma_alloc_and_map(cl, NULL, buffer_id, size); -out: + if (ret) + mei_cl_unlink(cl); +notlinked: mutex_unlock(&bus->device_lock); if (ret) return ERR_PTR(ret); @@ -758,7 +760,7 @@ int mei_cldev_enable(struct mei_cl_device *cldev) if (cl->state == MEI_FILE_UNINITIALIZED) { ret = mei_cl_link(cl); if (ret) - goto out; + goto notlinked; /* update pointers */ cl->cldev = cldev; } @@ -785,6 +787,9 @@ int mei_cldev_enable(struct mei_cl_device *cldev) } out: + if (ret) + mei_cl_unlink(cl); +notlinked: mutex_unlock(&bus->device_lock); return ret; @@ -1277,7 +1282,6 @@ static void mei_cl_bus_dev_release(struct device *dev) mei_cl_flush_queues(cldev->cl, NULL); mei_me_cl_put(cldev->me_cl); mei_dev_bus_put(cldev->bus); - mei_cl_unlink(cldev->cl); kfree(cldev->cl); kfree(cldev); } diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h index 99966cd3e7d8..bdc65d50b945 100644 --- a/drivers/misc/mei/hw-me-regs.h +++ b/drivers/misc/mei/hw-me-regs.h @@ -111,6 +111,8 @@ #define MEI_DEV_ID_RPL_S 0x7A68 /* Raptor Lake Point S */ +#define MEI_DEV_ID_MTL_M 0x7E70 /* Meteor Lake Point M */ + /* * MEI HW Section */ diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index 704cd0caa172..5bf0d50d55a0 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -118,6 +118,8 @@ static const struct pci_device_id mei_me_pci_tbl[] = { {MEI_PCI_DEVICE(MEI_DEV_ID_RPL_S, MEI_ME_PCH15_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_MTL_M, MEI_ME_PCH15_CFG)}, + /* required last entry */ {0, } }; diff --git a/drivers/misc/vmw_vmci/vmci_guest.c b/drivers/misc/vmw_vmci/vmci_guest.c index aa7b05de97dd..4f8d962bb5b2 100644 --- a/drivers/misc/vmw_vmci/vmci_guest.c +++ b/drivers/misc/vmw_vmci/vmci_guest.c @@ -56,8 +56,6 @@ struct vmci_guest_device { bool exclusive_vectors; - struct tasklet_struct datagram_tasklet; - struct tasklet_struct bm_tasklet; struct wait_queue_head inout_wq; void *data_buffer; @@ -304,9 +302,8 @@ static int vmci_check_host_caps(struct pci_dev *pdev) * This function assumes that it has exclusive access to the data * in register(s) for the duration of the call. */ -static void vmci_dispatch_dgs(unsigned long data) +static void vmci_dispatch_dgs(struct vmci_guest_device *vmci_dev) { - struct vmci_guest_device *vmci_dev = (struct vmci_guest_device *)data; u8 *dg_in_buffer = vmci_dev->data_buffer; struct vmci_datagram *dg; size_t dg_in_buffer_size = VMCI_MAX_DG_SIZE; @@ -465,10 +462,8 @@ static void vmci_dispatch_dgs(unsigned long data) * Scans the notification bitmap for raised flags, clears them * and handles the notifications. */ -static void vmci_process_bitmap(unsigned long data) +static void vmci_process_bitmap(struct vmci_guest_device *dev) { - struct vmci_guest_device *dev = (struct vmci_guest_device *)data; - if (!dev->notification_bitmap) { dev_dbg(dev->dev, "No bitmap present in %s\n", __func__); return; @@ -486,13 +481,13 @@ static irqreturn_t vmci_interrupt(int irq, void *_dev) struct vmci_guest_device *dev = _dev; /* - * If we are using MSI-X with exclusive vectors then we simply schedule - * the datagram tasklet, since we know the interrupt was meant for us. + * If we are using MSI-X with exclusive vectors then we simply call + * vmci_dispatch_dgs(), since we know the interrupt was meant for us. * Otherwise we must read the ICR to determine what to do. */ if (dev->exclusive_vectors) { - tasklet_schedule(&dev->datagram_tasklet); + vmci_dispatch_dgs(dev); } else { unsigned int icr; @@ -502,12 +497,12 @@ static irqreturn_t vmci_interrupt(int irq, void *_dev) return IRQ_NONE; if (icr & VMCI_ICR_DATAGRAM) { - tasklet_schedule(&dev->datagram_tasklet); + vmci_dispatch_dgs(dev); icr &= ~VMCI_ICR_DATAGRAM; } if (icr & VMCI_ICR_NOTIFICATION) { - tasklet_schedule(&dev->bm_tasklet); + vmci_process_bitmap(dev); icr &= ~VMCI_ICR_NOTIFICATION; } @@ -536,7 +531,7 @@ static irqreturn_t vmci_interrupt_bm(int irq, void *_dev) struct vmci_guest_device *dev = _dev; /* For MSI-X we can just assume it was meant for us. */ - tasklet_schedule(&dev->bm_tasklet); + vmci_process_bitmap(dev); return IRQ_HANDLED; } @@ -638,10 +633,6 @@ static int vmci_guest_probe_device(struct pci_dev *pdev, vmci_dev->iobase = iobase; vmci_dev->mmio_base = mmio_base; - tasklet_init(&vmci_dev->datagram_tasklet, - vmci_dispatch_dgs, (unsigned long)vmci_dev); - tasklet_init(&vmci_dev->bm_tasklet, - vmci_process_bitmap, (unsigned long)vmci_dev); init_waitqueue_head(&vmci_dev->inout_wq); if (mmio_base != NULL) { @@ -808,8 +799,9 @@ static int vmci_guest_probe_device(struct pci_dev *pdev, * Request IRQ for legacy or MSI interrupts, or for first * MSI-X vector. */ - error = request_irq(pci_irq_vector(pdev, 0), vmci_interrupt, - IRQF_SHARED, KBUILD_MODNAME, vmci_dev); + error = request_threaded_irq(pci_irq_vector(pdev, 0), NULL, + vmci_interrupt, IRQF_SHARED, + KBUILD_MODNAME, vmci_dev); if (error) { dev_err(&pdev->dev, "Irq %u in use: %d\n", pci_irq_vector(pdev, 0), error); @@ -823,9 +815,9 @@ static int vmci_guest_probe_device(struct pci_dev *pdev, * between the vectors. */ if (vmci_dev->exclusive_vectors) { - error = request_irq(pci_irq_vector(pdev, 1), - vmci_interrupt_bm, 0, KBUILD_MODNAME, - vmci_dev); + error = request_threaded_irq(pci_irq_vector(pdev, 1), NULL, + vmci_interrupt_bm, 0, + KBUILD_MODNAME, vmci_dev); if (error) { dev_err(&pdev->dev, "Failed to allocate irq %u: %d\n", @@ -833,9 +825,11 @@ static int vmci_guest_probe_device(struct pci_dev *pdev, goto err_free_irq; } if (caps_in_use & VMCI_CAPS_DMA_DATAGRAM) { - error = request_irq(pci_irq_vector(pdev, 2), - vmci_interrupt_dma_datagram, - 0, KBUILD_MODNAME, vmci_dev); + error = request_threaded_irq(pci_irq_vector(pdev, 2), + NULL, + vmci_interrupt_dma_datagram, + 0, KBUILD_MODNAME, + vmci_dev); if (error) { dev_err(&pdev->dev, "Failed to allocate irq %u: %d\n", @@ -871,8 +865,6 @@ err_free_bm_irq: err_free_irq: free_irq(pci_irq_vector(pdev, 0), vmci_dev); - tasklet_kill(&vmci_dev->datagram_tasklet); - tasklet_kill(&vmci_dev->bm_tasklet); err_disable_msi: pci_free_irq_vectors(pdev); @@ -943,9 +935,6 @@ static void vmci_guest_remove_device(struct pci_dev *pdev) free_irq(pci_irq_vector(pdev, 0), vmci_dev); pci_free_irq_vectors(pdev); - tasklet_kill(&vmci_dev->datagram_tasklet); - tasklet_kill(&vmci_dev->bm_tasklet); - if (vmci_dev->notification_bitmap) { /* * The device reset above cleared the bitmap state of the diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 89ef0c80ac37..9e73c34b6401 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -107,6 +107,7 @@ #define ESDHC_TUNING_START_TAP_DEFAULT 0x1 #define ESDHC_TUNING_START_TAP_MASK 0x7f #define ESDHC_TUNING_CMD_CRC_CHECK_DISABLE (1 << 7) +#define ESDHC_TUNING_STEP_DEFAULT 0x1 #define ESDHC_TUNING_STEP_MASK 0x00070000 #define ESDHC_TUNING_STEP_SHIFT 16 @@ -1368,7 +1369,7 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); struct cqhci_host *cq_host = host->mmc->cqe_private; - int tmp; + u32 tmp; if (esdhc_is_usdhc(imx_data)) { /* @@ -1423,17 +1424,24 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host) if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { tmp = readl(host->ioaddr + ESDHC_TUNING_CTRL); - tmp |= ESDHC_STD_TUNING_EN | - ESDHC_TUNING_START_TAP_DEFAULT; - if (imx_data->boarddata.tuning_start_tap) { - tmp &= ~ESDHC_TUNING_START_TAP_MASK; + tmp |= ESDHC_STD_TUNING_EN; + + /* + * ROM code or bootloader may config the start tap + * and step, unmask them first. + */ + tmp &= ~(ESDHC_TUNING_START_TAP_MASK | ESDHC_TUNING_STEP_MASK); + if (imx_data->boarddata.tuning_start_tap) tmp |= imx_data->boarddata.tuning_start_tap; - } + else + tmp |= ESDHC_TUNING_START_TAP_DEFAULT; if (imx_data->boarddata.tuning_step) { - tmp &= ~ESDHC_TUNING_STEP_MASK; tmp |= imx_data->boarddata.tuning_step << ESDHC_TUNING_STEP_SHIFT; + } else { + tmp |= ESDHC_TUNING_STEP_DEFAULT + << ESDHC_TUNING_STEP_SHIFT; } /* Disable the CMD CRC check for tuning, if not, need to diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index b16e12e62e72..3db9f32d6a7b 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c @@ -1492,9 +1492,11 @@ static int sunxi_mmc_remove(struct platform_device *pdev) struct sunxi_mmc_host *host = mmc_priv(mmc); mmc_remove_host(mmc); - pm_runtime_force_suspend(&pdev->dev); - disable_irq(host->irq); - sunxi_mmc_disable(host); + pm_runtime_disable(&pdev->dev); + if (!pm_runtime_status_suspended(&pdev->dev)) { + disable_irq(host->irq); + sunxi_mmc_disable(host); + } dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); mmc_free_host(mmc); diff --git a/drivers/mtd/parsers/scpart.c b/drivers/mtd/parsers/scpart.c index 02601bb33de4..6e5e11c37078 100644 --- a/drivers/mtd/parsers/scpart.c +++ b/drivers/mtd/parsers/scpart.c @@ -50,7 +50,7 @@ static int scpart_scan_partmap(struct mtd_info *master, loff_t partmap_offs, int cnt = 0; int res = 0; int res2; - loff_t offs; + uint32_t offs; size_t retlen; struct sc_part_desc *pdesc = NULL; struct sc_part_desc *tmpdesc; diff --git a/drivers/mtd/parsers/tplink_safeloader.c b/drivers/mtd/parsers/tplink_safeloader.c index f601e7bd8627..1c689dafca2a 100644 --- a/drivers/mtd/parsers/tplink_safeloader.c +++ b/drivers/mtd/parsers/tplink_safeloader.c @@ -91,7 +91,7 @@ static int mtd_parser_tplink_safeloader_parse(struct mtd_info *mtd, buf = mtd_parser_tplink_safeloader_read_table(mtd); if (!buf) { err = -ENOENT; - goto err_out; + goto err_free_parts; } for (idx = 0, offset = TPLINK_SAFELOADER_DATA_OFFSET; @@ -118,6 +118,8 @@ static int mtd_parser_tplink_safeloader_parse(struct mtd_info *mtd, err_free: for (idx -= 1; idx >= 0; idx--) kfree(parts[idx].name); +err_free_parts: + kfree(parts); err_out: return err; }; diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index d8703d7dfd0a..d67c926bca8b 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -10,6 +10,7 @@ #include <linux/err.h> #include <linux/errno.h> #include <linux/module.h> +#include <linux/delay.h> #include <linux/device.h> #include <linux/mutex.h> #include <linux/math64.h> diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 455b555275f1..c99ffe6c683a 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -1549,6 +1549,7 @@ static void ad_port_selection_logic(struct port *port, bool *update_slave_arr) slave_err(bond->dev, port->slave->dev, "Port %d did not find a suitable aggregator\n", port->actor_port_number); + return; } } /* if all aggregator's ports are READY_N == TRUE, set ready=TRUE diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index b4c65783960a..0363ce597661 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2654,10 +2654,12 @@ static void bond_miimon_link_change(struct bonding *bond, static void bond_miimon_commit(struct bonding *bond) { - struct slave *slave, *primary; + struct slave *slave, *primary, *active; bool do_failover = false; struct list_head *iter; + ASSERT_RTNL(); + bond_for_each_slave(bond, slave, iter) { switch (slave->link_new_state) { case BOND_LINK_NOCHANGE: @@ -2700,8 +2702,8 @@ static void bond_miimon_commit(struct bonding *bond) bond_miimon_link_change(bond, slave, BOND_LINK_UP); - if (!rcu_access_pointer(bond->curr_active_slave) || slave == primary || - slave->prio > rcu_dereference(bond->curr_active_slave)->prio) + active = rtnl_dereference(bond->curr_active_slave); + if (!active || slave == primary || slave->prio > active->prio) do_failover = true; continue; diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c index 47b54ecf2c6f..6178a96e389f 100644 --- a/drivers/net/dsa/microchip/ksz9477.c +++ b/drivers/net/dsa/microchip/ksz9477.c @@ -540,10 +540,10 @@ int ksz9477_fdb_del(struct ksz_device *dev, int port, ksz_read32(dev, REG_SW_ALU_VAL_D, &alu_table[3]); /* clear forwarding port */ - alu_table[2] &= ~BIT(port); + alu_table[1] &= ~BIT(port); /* if there is no port to forward, clear table */ - if ((alu_table[2] & ALU_V_PORT_MAP) == 0) { + if ((alu_table[1] & ALU_V_PORT_MAP) == 0) { alu_table[0] = 0; alu_table[1] = 0; alu_table[2] = 0; diff --git a/drivers/net/dsa/microchip/ksz9477_i2c.c b/drivers/net/dsa/microchip/ksz9477_i2c.c index c1a633ca1e6d..e315f669ec06 100644 --- a/drivers/net/dsa/microchip/ksz9477_i2c.c +++ b/drivers/net/dsa/microchip/ksz9477_i2c.c @@ -104,7 +104,7 @@ static const struct of_device_id ksz9477_dt_ids[] = { }, { .compatible = "microchip,ksz8563", - .data = &ksz_switch_chips[KSZ9893] + .data = &ksz_switch_chips[KSZ8563] }, { .compatible = "microchip,ksz9567", diff --git a/drivers/net/dsa/mv88e6xxx/Kconfig b/drivers/net/dsa/mv88e6xxx/Kconfig index 7a2445a34eb7..e3181d5471df 100644 --- a/drivers/net/dsa/mv88e6xxx/Kconfig +++ b/drivers/net/dsa/mv88e6xxx/Kconfig @@ -2,7 +2,6 @@ config NET_DSA_MV88E6XXX tristate "Marvell 88E6xxx Ethernet switch fabric support" depends on NET_DSA - depends on PTP_1588_CLOCK_OPTIONAL select IRQ_DOMAIN select NET_DSA_TAG_EDSA select NET_DSA_TAG_DSA @@ -13,7 +12,8 @@ config NET_DSA_MV88E6XXX config NET_DSA_MV88E6XXX_PTP bool "PTP support for Marvell 88E6xxx" default n - depends on NET_DSA_MV88E6XXX && PTP_1588_CLOCK + depends on (NET_DSA_MV88E6XXX = y && PTP_1588_CLOCK = y) || \ + (NET_DSA_MV88E6XXX = m && PTP_1588_CLOCK) help Say Y to enable PTP hardware timestamping on Marvell 88E6xxx switch chips that support it. diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c index c5c3b4e92f28..2f224b166bbb 100644 --- a/drivers/net/dsa/qca/qca8k-8xxx.c +++ b/drivers/net/dsa/qca/qca8k-8xxx.c @@ -37,77 +37,104 @@ qca8k_split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page) } static int -qca8k_set_lo(struct qca8k_priv *priv, int phy_id, u32 regnum, u16 lo) +qca8k_mii_write_lo(struct mii_bus *bus, int phy_id, u32 regnum, u32 val) { - u16 *cached_lo = &priv->mdio_cache.lo; - struct mii_bus *bus = priv->bus; int ret; + u16 lo; - if (lo == *cached_lo) - return 0; - + lo = val & 0xffff; ret = bus->write(bus, phy_id, regnum, lo); if (ret < 0) dev_err_ratelimited(&bus->dev, "failed to write qca8k 32bit lo register\n"); - *cached_lo = lo; - return 0; + return ret; } static int -qca8k_set_hi(struct qca8k_priv *priv, int phy_id, u32 regnum, u16 hi) +qca8k_mii_write_hi(struct mii_bus *bus, int phy_id, u32 regnum, u32 val) { - u16 *cached_hi = &priv->mdio_cache.hi; - struct mii_bus *bus = priv->bus; int ret; + u16 hi; - if (hi == *cached_hi) - return 0; - + hi = (u16)(val >> 16); ret = bus->write(bus, phy_id, regnum, hi); if (ret < 0) dev_err_ratelimited(&bus->dev, "failed to write qca8k 32bit hi register\n"); - *cached_hi = hi; - return 0; + return ret; } static int -qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val) +qca8k_mii_read_lo(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val) { int ret; ret = bus->read(bus, phy_id, regnum); - if (ret >= 0) { - *val = ret; - ret = bus->read(bus, phy_id, regnum + 1); - *val |= ret << 16; - } + if (ret < 0) + goto err; - if (ret < 0) { - dev_err_ratelimited(&bus->dev, - "failed to read qca8k 32bit register\n"); - *val = 0; - return ret; - } + *val = ret & 0xffff; + return 0; + +err: + dev_err_ratelimited(&bus->dev, + "failed to read qca8k 32bit lo register\n"); + *val = 0; + + return ret; +} +static int +qca8k_mii_read_hi(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val) +{ + int ret; + + ret = bus->read(bus, phy_id, regnum); + if (ret < 0) + goto err; + + *val = ret << 16; return 0; + +err: + dev_err_ratelimited(&bus->dev, + "failed to read qca8k 32bit hi register\n"); + *val = 0; + + return ret; } -static void -qca8k_mii_write32(struct qca8k_priv *priv, int phy_id, u32 regnum, u32 val) +static int +qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val) { - u16 lo, hi; + u32 hi, lo; int ret; - lo = val & 0xffff; - hi = (u16)(val >> 16); + *val = 0; - ret = qca8k_set_lo(priv, phy_id, regnum, lo); - if (ret >= 0) - ret = qca8k_set_hi(priv, phy_id, regnum + 1, hi); + ret = qca8k_mii_read_lo(bus, phy_id, regnum, &lo); + if (ret < 0) + goto err; + + ret = qca8k_mii_read_hi(bus, phy_id, regnum + 1, &hi); + if (ret < 0) + goto err; + + *val = lo | hi; + +err: + return ret; +} + +static void +qca8k_mii_write32(struct mii_bus *bus, int phy_id, u32 regnum, u32 val) +{ + if (qca8k_mii_write_lo(bus, phy_id, regnum, val) < 0) + return; + + qca8k_mii_write_hi(bus, phy_id, regnum + 1, val); } static int @@ -146,7 +173,16 @@ static void qca8k_rw_reg_ack_handler(struct dsa_switch *ds, struct sk_buff *skb) command = get_unaligned_le32(&mgmt_ethhdr->command); cmd = FIELD_GET(QCA_HDR_MGMT_CMD, command); + len = FIELD_GET(QCA_HDR_MGMT_LENGTH, command); + /* Special case for len of 15 as this is the max value for len and needs to + * be increased before converting it from word to dword. + */ + if (len == 15) + len++; + + /* We can ignore odd value, we always round up them in the alloc function. */ + len *= sizeof(u16); /* Make sure the seq match the requested packet */ if (get_unaligned_le32(&mgmt_ethhdr->seq) == mgmt_eth_data->seq) @@ -193,17 +229,33 @@ static struct sk_buff *qca8k_alloc_mdio_header(enum mdio_cmd cmd, u32 reg, u32 * if (!skb) return NULL; - /* Max value for len reg is 15 (0xf) but the switch actually return 16 byte - * Actually for some reason the steps are: - * 0: nothing - * 1-4: first 4 byte - * 5-6: first 12 byte - * 7-15: all 16 byte + /* Hdr mgmt length value is in step of word size. + * As an example to process 4 byte of data the correct length to set is 2. + * To process 8 byte 4, 12 byte 6, 16 byte 8... + * + * Odd values will always return the next size on the ack packet. + * (length of 3 (6 byte) will always return 8 bytes of data) + * + * This means that a value of 15 (0xf) actually means reading/writing 32 bytes + * of data. + * + * To correctly calculate the length we devide the requested len by word and + * round up. + * On the ack function we can skip the odd check as we already handle the + * case here. */ - if (len == 16) - real_len = 15; - else - real_len = len; + real_len = DIV_ROUND_UP(len, sizeof(u16)); + + /* We check if the result len is odd and we round up another time to + * the next size. (length of 3 will be increased to 4 as switch will always + * return 8 bytes) + */ + if (real_len % sizeof(u16) != 0) + real_len++; + + /* Max reg value is 0xf(15) but switch will always return the next size (32 byte) */ + if (real_len == 16) + real_len--; skb_reset_mac_header(skb); skb_set_network_header(skb, skb->len); @@ -417,7 +469,7 @@ qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val) if (ret < 0) goto exit; - qca8k_mii_write32(priv, 0x10 | r2, r1, val); + qca8k_mii_write32(bus, 0x10 | r2, r1, val); exit: mutex_unlock(&bus->mdio_lock); @@ -450,7 +502,7 @@ qca8k_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask, uint32_t write_ val &= ~mask; val |= write_val; - qca8k_mii_write32(priv, 0x10 | r2, r1, val); + qca8k_mii_write32(bus, 0x10 | r2, r1, val); exit: mutex_unlock(&bus->mdio_lock); @@ -688,9 +740,9 @@ qca8k_mdio_busy_wait(struct mii_bus *bus, u32 reg, u32 mask) qca8k_split_addr(reg, &r1, &r2, &page); - ret = read_poll_timeout(qca8k_mii_read32, ret1, !(val & mask), 0, + ret = read_poll_timeout(qca8k_mii_read_hi, ret1, !(val & mask), 0, QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false, - bus, 0x10 | r2, r1, &val); + bus, 0x10 | r2, r1 + 1, &val); /* Check if qca8k_read has failed for a different reason * before returnting -ETIMEDOUT @@ -725,14 +777,14 @@ qca8k_mdio_write(struct qca8k_priv *priv, int phy, int regnum, u16 data) if (ret) goto exit; - qca8k_mii_write32(priv, 0x10 | r2, r1, val); + qca8k_mii_write32(bus, 0x10 | r2, r1, val); ret = qca8k_mdio_busy_wait(bus, QCA8K_MDIO_MASTER_CTRL, QCA8K_MDIO_MASTER_BUSY); exit: /* even if the busy_wait timeouts try to clear the MASTER_EN */ - qca8k_mii_write32(priv, 0x10 | r2, r1, 0); + qca8k_mii_write_hi(bus, 0x10 | r2, r1 + 1, 0); mutex_unlock(&bus->mdio_lock); @@ -762,18 +814,18 @@ qca8k_mdio_read(struct qca8k_priv *priv, int phy, int regnum) if (ret) goto exit; - qca8k_mii_write32(priv, 0x10 | r2, r1, val); + qca8k_mii_write_hi(bus, 0x10 | r2, r1 + 1, val); ret = qca8k_mdio_busy_wait(bus, QCA8K_MDIO_MASTER_CTRL, QCA8K_MDIO_MASTER_BUSY); if (ret) goto exit; - ret = qca8k_mii_read32(bus, 0x10 | r2, r1, &val); + ret = qca8k_mii_read_lo(bus, 0x10 | r2, r1, &val); exit: /* even if the busy_wait timeouts try to clear the MASTER_EN */ - qca8k_mii_write32(priv, 0x10 | r2, r1, 0); + qca8k_mii_write_hi(bus, 0x10 | r2, r1 + 1, 0); mutex_unlock(&bus->mdio_lock); @@ -1943,8 +1995,6 @@ qca8k_sw_probe(struct mdio_device *mdiodev) } priv->mdio_cache.page = 0xffff; - priv->mdio_cache.lo = 0xffff; - priv->mdio_cache.hi = 0xffff; /* Check the detected switch id */ ret = qca8k_read_switch_id(priv); diff --git a/drivers/net/dsa/qca/qca8k.h b/drivers/net/dsa/qca/qca8k.h index 0b7a5cb12321..03514f7a20be 100644 --- a/drivers/net/dsa/qca/qca8k.h +++ b/drivers/net/dsa/qca/qca8k.h @@ -375,11 +375,6 @@ struct qca8k_mdio_cache { * mdio writes */ u16 page; -/* lo and hi can also be cached and from Documentation we can skip one - * extra mdio write if lo or hi is didn't change. - */ - u16 lo; - u16 hi; }; struct qca8k_pcs { diff --git a/drivers/net/ethernet/adi/adin1110.c b/drivers/net/ethernet/adi/adin1110.c index 0805f249fff2..c26b8597945b 100644 --- a/drivers/net/ethernet/adi/adin1110.c +++ b/drivers/net/ethernet/adi/adin1110.c @@ -356,7 +356,7 @@ static int adin1110_read_fifo(struct adin1110_port_priv *port_priv) if ((port_priv->flags & IFF_ALLMULTI && rxb->pkt_type == PACKET_MULTICAST) || (port_priv->flags & IFF_BROADCAST && rxb->pkt_type == PACKET_BROADCAST)) - rxb->offload_fwd_mark = 1; + rxb->offload_fwd_mark = port_priv->priv->forwarding; netif_rx(rxb); diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c b/drivers/net/ethernet/amazon/ena/ena_com.c index 8c8b4c88c7de..451c3a1b6255 100644 --- a/drivers/net/ethernet/amazon/ena/ena_com.c +++ b/drivers/net/ethernet/amazon/ena/ena_com.c @@ -2400,29 +2400,18 @@ int ena_com_fill_hash_function(struct ena_com_dev *ena_dev, return -EOPNOTSUPP; } - switch (func) { - case ENA_ADMIN_TOEPLITZ: - if (key) { - if (key_len != sizeof(hash_key->key)) { - netdev_err(ena_dev->net_device, - "key len (%u) doesn't equal the supported size (%zu)\n", - key_len, sizeof(hash_key->key)); - return -EINVAL; - } - memcpy(hash_key->key, key, key_len); - rss->hash_init_val = init_val; - hash_key->key_parts = key_len / sizeof(hash_key->key[0]); + if ((func == ENA_ADMIN_TOEPLITZ) && key) { + if (key_len != sizeof(hash_key->key)) { + netdev_err(ena_dev->net_device, + "key len (%u) doesn't equal the supported size (%zu)\n", + key_len, sizeof(hash_key->key)); + return -EINVAL; } - break; - case ENA_ADMIN_CRC32: - rss->hash_init_val = init_val; - break; - default: - netdev_err(ena_dev->net_device, "Invalid hash function (%d)\n", - func); - return -EINVAL; + memcpy(hash_key->key, key, key_len); + hash_key->key_parts = key_len / sizeof(hash_key->key[0]); } + rss->hash_init_val = init_val; old_func = rss->hash_func; rss->hash_func = func; rc = ena_com_set_hash_function(ena_dev); diff --git a/drivers/net/ethernet/amazon/ena/ena_ethtool.c b/drivers/net/ethernet/amazon/ena/ena_ethtool.c index 48ae6d810f8f..8da79eedc057 100644 --- a/drivers/net/ethernet/amazon/ena/ena_ethtool.c +++ b/drivers/net/ethernet/amazon/ena/ena_ethtool.c @@ -887,11 +887,7 @@ static int ena_set_tunable(struct net_device *netdev, switch (tuna->id) { case ETHTOOL_RX_COPYBREAK: len = *(u32 *)data; - if (len > adapter->netdev->mtu) { - ret = -EINVAL; - break; - } - adapter->rx_copybreak = len; + ret = ena_set_rx_copybreak(adapter, len); break; default: ret = -EINVAL; diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index a95529a69cbb..e8ad5ea31aff 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -374,9 +374,9 @@ static int ena_xdp_xmit(struct net_device *dev, int n, static int ena_xdp_execute(struct ena_ring *rx_ring, struct xdp_buff *xdp) { + u32 verdict = ENA_XDP_PASS; struct bpf_prog *xdp_prog; struct ena_ring *xdp_ring; - u32 verdict = XDP_PASS; struct xdp_frame *xdpf; u64 *xdp_stat; @@ -393,7 +393,7 @@ static int ena_xdp_execute(struct ena_ring *rx_ring, struct xdp_buff *xdp) if (unlikely(!xdpf)) { trace_xdp_exception(rx_ring->netdev, xdp_prog, verdict); xdp_stat = &rx_ring->rx_stats.xdp_aborted; - verdict = XDP_ABORTED; + verdict = ENA_XDP_DROP; break; } @@ -409,29 +409,35 @@ static int ena_xdp_execute(struct ena_ring *rx_ring, struct xdp_buff *xdp) spin_unlock(&xdp_ring->xdp_tx_lock); xdp_stat = &rx_ring->rx_stats.xdp_tx; + verdict = ENA_XDP_TX; break; case XDP_REDIRECT: if (likely(!xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog))) { xdp_stat = &rx_ring->rx_stats.xdp_redirect; + verdict = ENA_XDP_REDIRECT; break; } trace_xdp_exception(rx_ring->netdev, xdp_prog, verdict); xdp_stat = &rx_ring->rx_stats.xdp_aborted; - verdict = XDP_ABORTED; + verdict = ENA_XDP_DROP; break; case XDP_ABORTED: trace_xdp_exception(rx_ring->netdev, xdp_prog, verdict); xdp_stat = &rx_ring->rx_stats.xdp_aborted; + verdict = ENA_XDP_DROP; break; case XDP_DROP: xdp_stat = &rx_ring->rx_stats.xdp_drop; + verdict = ENA_XDP_DROP; break; case XDP_PASS: xdp_stat = &rx_ring->rx_stats.xdp_pass; + verdict = ENA_XDP_PASS; break; default: bpf_warn_invalid_xdp_action(rx_ring->netdev, xdp_prog, verdict); xdp_stat = &rx_ring->rx_stats.xdp_invalid; + verdict = ENA_XDP_DROP; } ena_increase_stat(xdp_stat, 1, &rx_ring->syncp); @@ -512,16 +518,18 @@ static void ena_xdp_exchange_program_rx_in_range(struct ena_adapter *adapter, struct bpf_prog *prog, int first, int count) { + struct bpf_prog *old_bpf_prog; struct ena_ring *rx_ring; int i = 0; for (i = first; i < count; i++) { rx_ring = &adapter->rx_ring[i]; - xchg(&rx_ring->xdp_bpf_prog, prog); - if (prog) { + old_bpf_prog = xchg(&rx_ring->xdp_bpf_prog, prog); + + if (!old_bpf_prog && prog) { ena_xdp_register_rxq_info(rx_ring); rx_ring->rx_headroom = XDP_PACKET_HEADROOM; - } else { + } else if (old_bpf_prog && !prog) { ena_xdp_unregister_rxq_info(rx_ring); rx_ring->rx_headroom = NET_SKB_PAD; } @@ -672,6 +680,7 @@ static void ena_init_io_rings_common(struct ena_adapter *adapter, ring->ena_dev = adapter->ena_dev; ring->per_napi_packets = 0; ring->cpu = 0; + ring->numa_node = 0; ring->no_interrupt_event_cnt = 0; u64_stats_init(&ring->syncp); } @@ -775,6 +784,7 @@ static int ena_setup_tx_resources(struct ena_adapter *adapter, int qid) tx_ring->next_to_use = 0; tx_ring->next_to_clean = 0; tx_ring->cpu = ena_irq->cpu; + tx_ring->numa_node = node; return 0; err_push_buf_intermediate_buf: @@ -907,6 +917,7 @@ static int ena_setup_rx_resources(struct ena_adapter *adapter, rx_ring->next_to_clean = 0; rx_ring->next_to_use = 0; rx_ring->cpu = ena_irq->cpu; + rx_ring->numa_node = node; return 0; } @@ -1619,12 +1630,12 @@ static int ena_xdp_handle_buff(struct ena_ring *rx_ring, struct xdp_buff *xdp) * we expect, then we simply drop it */ if (unlikely(rx_ring->ena_bufs[0].len > ENA_XDP_MAX_MTU)) - return XDP_DROP; + return ENA_XDP_DROP; ret = ena_xdp_execute(rx_ring, xdp); /* The xdp program might expand the headers */ - if (ret == XDP_PASS) { + if (ret == ENA_XDP_PASS) { rx_info->page_offset = xdp->data - xdp->data_hard_start; rx_ring->ena_bufs[0].len = xdp->data_end - xdp->data; } @@ -1663,7 +1674,7 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi, xdp_init_buff(&xdp, ENA_PAGE_SIZE, &rx_ring->xdp_rxq); do { - xdp_verdict = XDP_PASS; + xdp_verdict = ENA_XDP_PASS; skb = NULL; ena_rx_ctx.ena_bufs = rx_ring->ena_bufs; ena_rx_ctx.max_bufs = rx_ring->sgl_size; @@ -1691,7 +1702,7 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi, xdp_verdict = ena_xdp_handle_buff(rx_ring, &xdp); /* allocate skb and fill it */ - if (xdp_verdict == XDP_PASS) + if (xdp_verdict == ENA_XDP_PASS) skb = ena_rx_skb(rx_ring, rx_ring->ena_bufs, ena_rx_ctx.descs, @@ -1709,14 +1720,15 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi, /* Packets was passed for transmission, unmap it * from RX side. */ - if (xdp_verdict == XDP_TX || xdp_verdict == XDP_REDIRECT) { + if (xdp_verdict & ENA_XDP_FORWARDED) { ena_unmap_rx_buff(rx_ring, &rx_ring->rx_buffer_info[req_id]); rx_ring->rx_buffer_info[req_id].page = NULL; } } - if (xdp_verdict != XDP_PASS) { + if (xdp_verdict != ENA_XDP_PASS) { xdp_flags |= xdp_verdict; + total_len += ena_rx_ctx.ena_bufs[0].len; res_budget--; continue; } @@ -1760,7 +1772,7 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi, ena_refill_rx_bufs(rx_ring, refill_required); } - if (xdp_flags & XDP_REDIRECT) + if (xdp_flags & ENA_XDP_REDIRECT) xdp_do_flush_map(); return work_done; @@ -1814,8 +1826,9 @@ static void ena_adjust_adaptive_rx_intr_moderation(struct ena_napi *ena_napi) static void ena_unmask_interrupt(struct ena_ring *tx_ring, struct ena_ring *rx_ring) { + u32 rx_interval = tx_ring->smoothed_interval; struct ena_eth_io_intr_reg intr_reg; - u32 rx_interval = 0; + /* Rx ring can be NULL when for XDP tx queues which don't have an * accompanying rx_ring pair. */ @@ -1853,20 +1866,27 @@ static void ena_update_ring_numa_node(struct ena_ring *tx_ring, if (likely(tx_ring->cpu == cpu)) goto out; + tx_ring->cpu = cpu; + if (rx_ring) + rx_ring->cpu = cpu; + numa_node = cpu_to_node(cpu); + + if (likely(tx_ring->numa_node == numa_node)) + goto out; + put_cpu(); if (numa_node != NUMA_NO_NODE) { ena_com_update_numa_node(tx_ring->ena_com_io_cq, numa_node); - if (rx_ring) + tx_ring->numa_node = numa_node; + if (rx_ring) { + rx_ring->numa_node = numa_node; ena_com_update_numa_node(rx_ring->ena_com_io_cq, numa_node); + } } - tx_ring->cpu = cpu; - if (rx_ring) - rx_ring->cpu = cpu; - return; out: put_cpu(); @@ -1987,11 +2007,10 @@ static int ena_io_poll(struct napi_struct *napi, int budget) if (ena_com_get_adaptive_moderation_enabled(rx_ring->ena_dev)) ena_adjust_adaptive_rx_intr_moderation(ena_napi); + ena_update_ring_numa_node(tx_ring, rx_ring); ena_unmask_interrupt(tx_ring, rx_ring); } - ena_update_ring_numa_node(tx_ring, rx_ring); - ret = rx_work_done; } else { ret = budget; @@ -2376,7 +2395,7 @@ static int ena_create_io_tx_queue(struct ena_adapter *adapter, int qid) ctx.mem_queue_type = ena_dev->tx_mem_queue_type; ctx.msix_vector = msix_vector; ctx.queue_size = tx_ring->ring_size; - ctx.numa_node = cpu_to_node(tx_ring->cpu); + ctx.numa_node = tx_ring->numa_node; rc = ena_com_create_io_queue(ena_dev, &ctx); if (rc) { @@ -2444,7 +2463,7 @@ static int ena_create_io_rx_queue(struct ena_adapter *adapter, int qid) ctx.mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST; ctx.msix_vector = msix_vector; ctx.queue_size = rx_ring->ring_size; - ctx.numa_node = cpu_to_node(rx_ring->cpu); + ctx.numa_node = rx_ring->numa_node; rc = ena_com_create_io_queue(ena_dev, &ctx); if (rc) { @@ -2805,6 +2824,24 @@ int ena_update_queue_sizes(struct ena_adapter *adapter, return dev_was_up ? ena_up(adapter) : 0; } +int ena_set_rx_copybreak(struct ena_adapter *adapter, u32 rx_copybreak) +{ + struct ena_ring *rx_ring; + int i; + + if (rx_copybreak > min_t(u16, adapter->netdev->mtu, ENA_PAGE_SIZE)) + return -EINVAL; + + adapter->rx_copybreak = rx_copybreak; + + for (i = 0; i < adapter->num_io_queues; i++) { + rx_ring = &adapter->rx_ring[i]; + rx_ring->rx_copybreak = rx_copybreak; + } + + return 0; +} + int ena_update_queue_count(struct ena_adapter *adapter, u32 new_channel_count) { struct ena_com_dev *ena_dev = adapter->ena_dev; diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.h b/drivers/net/ethernet/amazon/ena/ena_netdev.h index 1bdce99bf688..2cb141079474 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.h +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.h @@ -262,9 +262,11 @@ struct ena_ring { bool disable_meta_caching; u16 no_interrupt_event_cnt; - /* cpu for TPH */ + /* cpu and NUMA for TPH */ int cpu; - /* number of tx/rx_buffer_info's entries */ + int numa_node; + + /* number of tx/rx_buffer_info's entries */ int ring_size; enum ena_admin_placement_policy_type tx_mem_queue_type; @@ -392,6 +394,8 @@ int ena_update_queue_sizes(struct ena_adapter *adapter, int ena_update_queue_count(struct ena_adapter *adapter, u32 new_channel_count); +int ena_set_rx_copybreak(struct ena_adapter *adapter, u32 rx_copybreak); + int ena_get_sset_count(struct net_device *netdev, int sset); static inline void ena_reset_device(struct ena_adapter *adapter, @@ -409,6 +413,15 @@ enum ena_xdp_errors_t { ENA_XDP_NO_ENOUGH_QUEUES, }; +enum ENA_XDP_ACTIONS { + ENA_XDP_PASS = 0, + ENA_XDP_TX = BIT(0), + ENA_XDP_REDIRECT = BIT(1), + ENA_XDP_DROP = BIT(2) +}; + +#define ENA_XDP_FORWARDED (ENA_XDP_TX | ENA_XDP_REDIRECT) + static inline bool ena_xdp_present(struct ena_adapter *adapter) { return !!adapter->xdp_bpf_prog; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index 3936543a74d8..4030d619e84f 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c @@ -524,19 +524,28 @@ static void xgbe_disable_vxlan(struct xgbe_prv_data *pdata) netif_dbg(pdata, drv, pdata->netdev, "VXLAN acceleration disabled\n"); } +static unsigned int xgbe_get_fc_queue_count(struct xgbe_prv_data *pdata) +{ + unsigned int max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES; + + /* From MAC ver 30H the TFCR is per priority, instead of per queue */ + if (XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER) >= 0x30) + return max_q_count; + else + return min_t(unsigned int, pdata->tx_q_count, max_q_count); +} + static int xgbe_disable_tx_flow_control(struct xgbe_prv_data *pdata) { - unsigned int max_q_count, q_count; unsigned int reg, reg_val; - unsigned int i; + unsigned int i, q_count; /* Clear MTL flow control */ for (i = 0; i < pdata->rx_q_count; i++) XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, EHFC, 0); /* Clear MAC flow control */ - max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES; - q_count = min_t(unsigned int, pdata->tx_q_count, max_q_count); + q_count = xgbe_get_fc_queue_count(pdata); reg = MAC_Q0TFCR; for (i = 0; i < q_count; i++) { reg_val = XGMAC_IOREAD(pdata, reg); @@ -553,9 +562,8 @@ static int xgbe_enable_tx_flow_control(struct xgbe_prv_data *pdata) { struct ieee_pfc *pfc = pdata->pfc; struct ieee_ets *ets = pdata->ets; - unsigned int max_q_count, q_count; unsigned int reg, reg_val; - unsigned int i; + unsigned int i, q_count; /* Set MTL flow control */ for (i = 0; i < pdata->rx_q_count; i++) { @@ -579,8 +587,7 @@ static int xgbe_enable_tx_flow_control(struct xgbe_prv_data *pdata) } /* Set MAC flow control */ - max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES; - q_count = min_t(unsigned int, pdata->tx_q_count, max_q_count); + q_count = xgbe_get_fc_queue_count(pdata); reg = MAC_Q0TFCR; for (i = 0; i < q_count; i++) { reg_val = XGMAC_IOREAD(pdata, reg); diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 7b666106feee..614c0278419b 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -1064,6 +1064,9 @@ static void xgbe_free_irqs(struct xgbe_prv_data *pdata) devm_free_irq(pdata->dev, pdata->dev_irq, pdata); + tasklet_kill(&pdata->tasklet_dev); + tasklet_kill(&pdata->tasklet_ecc); + if (pdata->vdata->ecc_support && (pdata->dev_irq != pdata->ecc_irq)) devm_free_irq(pdata->dev, pdata->ecc_irq, pdata); diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c b/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c index 22d4fc547a0a..a9ccc4258ee5 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c @@ -447,8 +447,10 @@ static void xgbe_i2c_stop(struct xgbe_prv_data *pdata) xgbe_i2c_disable(pdata); xgbe_i2c_clear_all_interrupts(pdata); - if (pdata->dev_irq != pdata->i2c_irq) + if (pdata->dev_irq != pdata->i2c_irq) { devm_free_irq(pdata->dev, pdata->i2c_irq, pdata); + tasklet_kill(&pdata->tasklet_i2c); + } } static int xgbe_i2c_start(struct xgbe_prv_data *pdata) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c index 4e97b4869522..43fdd111235a 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c @@ -496,6 +496,7 @@ static enum xgbe_an xgbe_an73_tx_training(struct xgbe_prv_data *pdata, reg |= XGBE_KR_TRAINING_ENABLE; reg |= XGBE_KR_TRAINING_START; XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg); + pdata->kr_start_time = jiffies; netif_dbg(pdata, link, pdata->netdev, "KR training initiated\n"); @@ -632,6 +633,8 @@ static enum xgbe_an xgbe_an73_incompat_link(struct xgbe_prv_data *pdata) xgbe_switch_mode(pdata); + pdata->an_result = XGBE_AN_READY; + xgbe_an_restart(pdata); return XGBE_AN_INCOMPAT_LINK; @@ -1275,9 +1278,30 @@ static bool xgbe_phy_aneg_done(struct xgbe_prv_data *pdata) static void xgbe_check_link_timeout(struct xgbe_prv_data *pdata) { unsigned long link_timeout; + unsigned long kr_time; + int wait; link_timeout = pdata->link_check + (XGBE_LINK_TIMEOUT * HZ); if (time_after(jiffies, link_timeout)) { + if ((xgbe_cur_mode(pdata) == XGBE_MODE_KR) && + pdata->phy.autoneg == AUTONEG_ENABLE) { + /* AN restart should not happen while KR training is in progress. + * The while loop ensures no AN restart during KR training, + * waits up to 500ms and AN restart is triggered only if KR + * training is failed. + */ + wait = XGBE_KR_TRAINING_WAIT_ITER; + while (wait--) { + kr_time = pdata->kr_start_time + + msecs_to_jiffies(XGBE_AN_MS_TIMEOUT); + if (time_after(jiffies, kr_time)) + break; + /* AN restart is not required, if AN result is COMPLETE */ + if (pdata->an_result == XGBE_AN_COMPLETE) + return; + usleep_range(10000, 11000); + } + } netif_dbg(pdata, link, pdata->netdev, "AN link timeout\n"); xgbe_phy_config_aneg(pdata); } @@ -1390,8 +1414,10 @@ static void xgbe_phy_stop(struct xgbe_prv_data *pdata) /* Disable auto-negotiation */ xgbe_an_disable_all(pdata); - if (pdata->dev_irq != pdata->an_irq) + if (pdata->dev_irq != pdata->an_irq) { devm_free_irq(pdata->dev, pdata->an_irq, pdata); + tasklet_kill(&pdata->tasklet_an); + } pdata->phy_if.phy_impl.stop(pdata); diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index 71f24cb47935..7a41367c437d 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h @@ -290,6 +290,7 @@ /* Auto-negotiation */ #define XGBE_AN_MS_TIMEOUT 500 #define XGBE_LINK_TIMEOUT 5 +#define XGBE_KR_TRAINING_WAIT_ITER 50 #define XGBE_SGMII_AN_LINK_STATUS BIT(1) #define XGBE_SGMII_AN_LINK_SPEED (BIT(2) | BIT(3)) @@ -1280,6 +1281,7 @@ struct xgbe_prv_data { unsigned int parallel_detect; unsigned int fec_ability; unsigned long an_start; + unsigned long kr_start_time; enum xgbe_an_mode an_mode; /* I2C support */ diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c index d91fdb0c2649..2cf96892e565 100644 --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c @@ -2784,17 +2784,11 @@ static int bcm_enet_shared_probe(struct platform_device *pdev) return 0; } -static int bcm_enet_shared_remove(struct platform_device *pdev) -{ - return 0; -} - /* this "shared" driver is needed because both macs share a single * address space */ struct platform_driver bcm63xx_enet_shared_driver = { .probe = bcm_enet_shared_probe, - .remove = bcm_enet_shared_remove, .driver = { .name = "bcm63xx_enet_shared", .owner = THIS_MODULE, diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 4c7d07c684c4..240a7e8a7652 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -991,10 +991,9 @@ static struct sk_buff *bnxt_rx_multi_page_skb(struct bnxt *bp, dma_addr -= bp->rx_dma_offset; dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, PAGE_SIZE, bp->rx_dir, DMA_ATTR_WEAK_ORDERING); - skb = build_skb(page_address(page), BNXT_PAGE_MODE_BUF_SIZE + - bp->rx_dma_offset); + skb = build_skb(page_address(page), PAGE_SIZE); if (!skb) { - __free_page(page); + page_pool_recycle_direct(rxr->page_pool, page); return NULL; } skb_mark_for_recycle(skb); @@ -1032,7 +1031,7 @@ static struct sk_buff *bnxt_rx_page_skb(struct bnxt *bp, skb = napi_alloc_skb(&rxr->bnapi->napi, payload); if (!skb) { - __free_page(page); + page_pool_recycle_direct(rxr->page_pool, page); return NULL; } @@ -1925,7 +1924,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, dma_addr = rx_buf->mapping; if (bnxt_xdp_attached(bp, rxr)) { - bnxt_xdp_buff_init(bp, rxr, cons, &data_ptr, &len, &xdp); + bnxt_xdp_buff_init(bp, rxr, cons, data_ptr, len, &xdp); if (agg_bufs) { u32 frag_len = bnxt_rx_agg_pages_xdp(bp, cpr, &xdp, cp_cons, agg_bufs, @@ -1940,7 +1939,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, } if (xdp_active) { - if (bnxt_rx_xdp(bp, rxr, cons, xdp, data, &len, event)) { + if (bnxt_rx_xdp(bp, rxr, cons, xdp, data, &data_ptr, &len, event)) { rc = 1; goto next_rx; } @@ -3969,8 +3968,10 @@ void bnxt_set_ring_params(struct bnxt *bp) bp->rx_agg_ring_mask = (bp->rx_agg_nr_pages * RX_DESC_CNT) - 1; if (BNXT_RX_PAGE_MODE(bp)) { - rx_space = BNXT_PAGE_MODE_BUF_SIZE; - rx_size = BNXT_MAX_PAGE_MODE_MTU; + rx_space = PAGE_SIZE; + rx_size = PAGE_SIZE - + ALIGN(max(NET_SKB_PAD, XDP_PACKET_HEADROOM), 8) - + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); } else { rx_size = SKB_DATA_ALIGN(BNXT_RX_COPY_THRESH + NET_IP_ALIGN); rx_space = rx_size + NET_SKB_PAD + @@ -5398,15 +5399,16 @@ static int bnxt_hwrm_vnic_set_hds(struct bnxt *bp, u16 vnic_id) req->flags = cpu_to_le32(VNIC_PLCMODES_CFG_REQ_FLAGS_JUMBO_PLACEMENT); req->enables = cpu_to_le32(VNIC_PLCMODES_CFG_REQ_ENABLES_JUMBO_THRESH_VALID); - if (BNXT_RX_PAGE_MODE(bp) && !BNXT_RX_JUMBO_MODE(bp)) { + if (BNXT_RX_PAGE_MODE(bp)) { + req->jumbo_thresh = cpu_to_le16(bp->rx_buf_use_size); + } else { req->flags |= cpu_to_le32(VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_IPV4 | VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_IPV6); req->enables |= cpu_to_le32(VNIC_PLCMODES_CFG_REQ_ENABLES_HDS_THRESHOLD_VALID); + req->jumbo_thresh = cpu_to_le16(bp->rx_copy_thresh); + req->hds_threshold = cpu_to_le16(bp->rx_copy_thresh); } - /* thresholds not implemented in firmware yet */ - req->jumbo_thresh = cpu_to_le16(bp->rx_copy_thresh); - req->hds_threshold = cpu_to_le16(bp->rx_copy_thresh); req->vnic_id = cpu_to_le32(vnic->fw_vnic_id); return hwrm_req_send(bp, req); } @@ -13591,7 +13593,6 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) return -ENOMEM; bp = netdev_priv(dev); - SET_NETDEV_DEVLINK_PORT(dev, &bp->dl_port); bp->board_idx = ent->driver_data; bp->msg_enable = BNXT_DEF_MSG_ENABLE; bnxt_set_max_func_irqs(bp, max_irqs); @@ -13599,6 +13600,10 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (bnxt_vf_pciid(bp->board_idx)) bp->flags |= BNXT_FLAG_VF; + /* No devlink port registration in case of a VF */ + if (BNXT_PF(bp)) + SET_NETDEV_DEVLINK_PORT(dev, &bp->dl_port); + if (pdev->msix_cap) bp->flags |= BNXT_FLAG_MSIX_CAP; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 41c6dd0ae447..5163ef4a49ea 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -591,12 +591,20 @@ struct nqe_cn { #define BNXT_RX_PAGE_SIZE (1 << BNXT_RX_PAGE_SHIFT) #define BNXT_MAX_MTU 9500 -#define BNXT_PAGE_MODE_BUF_SIZE \ + +/* First RX buffer page in XDP multi-buf mode + * + * +-------------------------------------------------------------------------+ + * | XDP_PACKET_HEADROOM | bp->rx_buf_use_size | skb_shared_info| + * | (bp->rx_dma_offset) | | | + * +-------------------------------------------------------------------------+ + */ +#define BNXT_MAX_PAGE_MODE_MTU_SBUF \ ((unsigned int)PAGE_SIZE - VLAN_ETH_HLEN - NET_IP_ALIGN - \ XDP_PACKET_HEADROOM) #define BNXT_MAX_PAGE_MODE_MTU \ - BNXT_PAGE_MODE_BUF_SIZE - \ - SKB_DATA_ALIGN((unsigned int)sizeof(struct skb_shared_info)) + (BNXT_MAX_PAGE_MODE_MTU_SBUF - \ + SKB_DATA_ALIGN((unsigned int)sizeof(struct skb_shared_info))) #define BNXT_MIN_PKT_SIZE 52 @@ -2134,7 +2142,6 @@ struct bnxt { #define BNXT_DUMP_CRASH 1 struct bpf_prog *xdp_prog; - u8 xdp_has_frags; struct bnxt_ptp_cfg *ptp_cfg; u8 ptp_all_rx_tstamp; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index cbf17fcfb7ab..ec573127b707 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -3969,7 +3969,7 @@ void bnxt_ethtool_init(struct bnxt *bp) test_info->timeout = HWRM_CMD_TIMEOUT; for (i = 0; i < bp->num_tests; i++) { char *str = test_info->string[i]; - char *fw_str = resp->test0_name + i * 32; + char *fw_str = resp->test_name[i]; if (i == BNXT_MACLPBK_TEST_IDX) { strcpy(str, "Mac loopback test (offline)"); @@ -3980,14 +3980,9 @@ void bnxt_ethtool_init(struct bnxt *bp) } else if (i == BNXT_IRQ_TEST_IDX) { strcpy(str, "Interrupt_test (offline)"); } else { - strscpy(str, fw_str, ETH_GSTRING_LEN); - strncat(str, " test", ETH_GSTRING_LEN - strlen(str)); - if (test_info->offline_mask & (1 << i)) - strncat(str, " (offline)", - ETH_GSTRING_LEN - strlen(str)); - else - strncat(str, " (online)", - ETH_GSTRING_LEN - strlen(str)); + snprintf(str, ETH_GSTRING_LEN, "%s test (%s)", + fw_str, test_info->offline_mask & (1 << i) ? + "offline" : "online"); } } diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h index 2686a714a59f..a5408879e077 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h @@ -10249,14 +10249,7 @@ struct hwrm_selftest_qlist_output { u8 unused_0; __le16 test_timeout; u8 unused_1[2]; - char test0_name[32]; - char test1_name[32]; - char test2_name[32]; - char test3_name[32]; - char test4_name[32]; - char test5_name[32]; - char test6_name[32]; - char test7_name[32]; + char test_name[8][32]; u8 eyescope_target_BER_support; #define SELFTEST_QLIST_RESP_EYESCOPE_TARGET_BER_SUPPORT_BER_1E8_SUPPORTED 0x0UL #define SELFTEST_QLIST_RESP_EYESCOPE_TARGET_BER_SUPPORT_BER_1E9_SUPPORTED 0x1UL diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c index c3065ec0a479..36d5202c0aee 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c @@ -177,7 +177,7 @@ bool bnxt_xdp_attached(struct bnxt *bp, struct bnxt_rx_ring_info *rxr) } void bnxt_xdp_buff_init(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, - u16 cons, u8 **data_ptr, unsigned int *len, + u16 cons, u8 *data_ptr, unsigned int len, struct xdp_buff *xdp) { struct bnxt_sw_rx_bd *rx_buf; @@ -191,13 +191,10 @@ void bnxt_xdp_buff_init(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, offset = bp->rx_offset; mapping = rx_buf->mapping - bp->rx_dma_offset; - dma_sync_single_for_cpu(&pdev->dev, mapping + offset, *len, bp->rx_dir); - - if (bp->xdp_has_frags) - buflen = BNXT_PAGE_MODE_BUF_SIZE + offset; + dma_sync_single_for_cpu(&pdev->dev, mapping + offset, len, bp->rx_dir); xdp_init_buff(xdp, buflen, &rxr->xdp_rxq); - xdp_prepare_buff(xdp, *data_ptr - offset, offset, *len, false); + xdp_prepare_buff(xdp, data_ptr - offset, offset, len, false); } void bnxt_xdp_buff_frags_free(struct bnxt_rx_ring_info *rxr, @@ -222,7 +219,8 @@ void bnxt_xdp_buff_frags_free(struct bnxt_rx_ring_info *rxr, * false - packet should be passed to the stack. */ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons, - struct xdp_buff xdp, struct page *page, unsigned int *len, u8 *event) + struct xdp_buff xdp, struct page *page, u8 **data_ptr, + unsigned int *len, u8 *event) { struct bpf_prog *xdp_prog = READ_ONCE(rxr->xdp_prog); struct bnxt_tx_ring_info *txr; @@ -255,8 +253,10 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons, *event &= ~BNXT_RX_EVENT; *len = xdp.data_end - xdp.data; - if (orig_data != xdp.data) + if (orig_data != xdp.data) { offset = xdp.data - xdp.data_hard_start; + *data_ptr = xdp.data_hard_start + offset; + } switch (act) { case XDP_PASS: @@ -401,10 +401,8 @@ static int bnxt_xdp_set(struct bnxt *bp, struct bpf_prog *prog) netdev_warn(dev, "ethtool rx/tx channels must be combined to support XDP.\n"); return -EOPNOTSUPP; } - if (prog) { + if (prog) tx_xdp = bp->rx_nr_rings; - bp->xdp_has_frags = prog->aux->xdp_has_frags; - } tc = netdev_get_num_tc(dev); if (!tc) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h index 505911ae095d..ea430d6961df 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h @@ -18,8 +18,8 @@ struct bnxt_sw_tx_bd *bnxt_xmit_bd(struct bnxt *bp, struct xdp_buff *xdp); void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts); bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons, - struct xdp_buff xdp, struct page *page, unsigned int *len, - u8 *event); + struct xdp_buff xdp, struct page *page, u8 **data_ptr, + unsigned int *len, u8 *event); int bnxt_xdp(struct net_device *dev, struct netdev_bpf *xdp); int bnxt_xdp_xmit(struct net_device *dev, int num_frames, struct xdp_frame **frames, u32 flags); @@ -27,7 +27,7 @@ int bnxt_xdp_xmit(struct net_device *dev, int num_frames, bool bnxt_xdp_attached(struct bnxt *bp, struct bnxt_rx_ring_info *rxr); void bnxt_xdp_buff_init(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, - u16 cons, u8 **data_ptr, unsigned int *len, + u16 cons, u8 *data_ptr, unsigned int len, struct xdp_buff *xdp); void bnxt_xdp_buff_frags_free(struct bnxt_rx_ring_info *rxr, struct xdp_buff *xdp); diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 59debdc344a5..58747292521d 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -11166,7 +11166,7 @@ static void tg3_reset_task(struct work_struct *work) rtnl_lock(); tg3_full_lock(tp, 0); - if (!netif_running(tp->dev)) { + if (tp->pcierr_recovery || !netif_running(tp->dev)) { tg3_flag_clear(tp, RESET_TASK_PENDING); tg3_full_unlock(tp); rtnl_unlock(); @@ -18101,6 +18101,9 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev, netdev_info(netdev, "PCI I/O error detected\n"); + /* Want to make sure that the reset task doesn't run */ + tg3_reset_task_cancel(tp); + rtnl_lock(); /* Could be second call or maybe we don't have netdev yet */ @@ -18117,9 +18120,6 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev, tg3_timer_stop(tp); - /* Want to make sure that the reset task doesn't run */ - tg3_reset_task_cancel(tp); - netif_device_detach(netdev); /* Clean up software state, even if MMIO is blocked */ diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 95667b979fab..72e42820713d 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -2187,7 +2187,6 @@ static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev) bool cloned = skb_cloned(*skb) || skb_header_cloned(*skb) || skb_is_nonlinear(*skb); int padlen = ETH_ZLEN - (*skb)->len; - int headroom = skb_headroom(*skb); int tailroom = skb_tailroom(*skb); struct sk_buff *nskb; u32 fcs; @@ -2201,9 +2200,6 @@ static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev) /* FCS could be appeded to tailroom. */ if (tailroom >= ETH_FCS_LEN) goto add_fcs; - /* FCS could be appeded by moving data to headroom. */ - else if (!cloned && headroom + tailroom >= ETH_FCS_LEN) - padlen = 0; /* No room for FCS, need to reallocate skb. */ else padlen = ETH_FCS_LEN; @@ -2212,10 +2208,7 @@ static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev) padlen += ETH_FCS_LEN; } - if (!cloned && headroom + tailroom >= padlen) { - (*skb)->data = memmove((*skb)->head, (*skb)->data, (*skb)->len); - skb_set_tail_pointer(*skb, (*skb)->len); - } else { + if (cloned || tailroom < padlen) { nskb = skb_copy_expand(*skb, 0, padlen, GFP_ATOMIC); if (!nskb) return -ENOMEM; diff --git a/drivers/net/ethernet/engleder/tsnep_main.c b/drivers/net/ethernet/engleder/tsnep_main.c index bf0190e1d2ea..00e2108f2ca4 100644 --- a/drivers/net/ethernet/engleder/tsnep_main.c +++ b/drivers/net/ethernet/engleder/tsnep_main.c @@ -450,7 +450,7 @@ static netdev_tx_t tsnep_xmit_frame_ring(struct sk_buff *skb, /* ring full, shall not happen because queue is stopped if full * below */ - netif_stop_queue(tx->adapter->netdev); + netif_stop_subqueue(tx->adapter->netdev, tx->queue_index); spin_unlock_irqrestore(&tx->lock, flags); @@ -493,7 +493,7 @@ static netdev_tx_t tsnep_xmit_frame_ring(struct sk_buff *skb, if (tsnep_tx_desc_available(tx) < (MAX_SKB_FRAGS + 1)) { /* ring can get full with next frame */ - netif_stop_queue(tx->adapter->netdev); + netif_stop_subqueue(tx->adapter->netdev, tx->queue_index); } spin_unlock_irqrestore(&tx->lock, flags); @@ -503,11 +503,14 @@ static netdev_tx_t tsnep_xmit_frame_ring(struct sk_buff *skb, static bool tsnep_tx_poll(struct tsnep_tx *tx, int napi_budget) { + struct tsnep_tx_entry *entry; + struct netdev_queue *nq; unsigned long flags; int budget = 128; - struct tsnep_tx_entry *entry; - int count; int length; + int count; + + nq = netdev_get_tx_queue(tx->adapter->netdev, tx->queue_index); spin_lock_irqsave(&tx->lock, flags); @@ -564,8 +567,8 @@ static bool tsnep_tx_poll(struct tsnep_tx *tx, int napi_budget) } while (likely(budget)); if ((tsnep_tx_desc_available(tx) >= ((MAX_SKB_FRAGS + 1) * 2)) && - netif_queue_stopped(tx->adapter->netdev)) { - netif_wake_queue(tx->adapter->netdev); + netif_tx_queue_stopped(nq)) { + netif_tx_wake_queue(nq); } spin_unlock_irqrestore(&tx->lock, flags); diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c index 3a79ead5219a..e96449eedfb5 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.c +++ b/drivers/net/ethernet/freescale/enetc/enetc.c @@ -2290,14 +2290,14 @@ static void enetc_tx_onestep_tstamp(struct work_struct *work) priv = container_of(work, struct enetc_ndev_priv, tx_onestep_tstamp); - netif_tx_lock(priv->ndev); + netif_tx_lock_bh(priv->ndev); clear_bit_unlock(ENETC_TX_ONESTEP_TSTAMP_IN_PROGRESS, &priv->flags); skb = skb_dequeue(&priv->tx_skbs); if (skb) enetc_start_xmit(skb, priv->ndev); - netif_tx_unlock(priv->ndev); + netif_tx_unlock_bh(priv->ndev); } static void enetc_tx_onestep_tstamp_init(struct enetc_ndev_priv *priv) diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ierb.c b/drivers/net/ethernet/freescale/enetc/enetc_ierb.c index 91f02c505028..b307bef4dc29 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_ierb.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_ierb.c @@ -127,11 +127,6 @@ static int enetc_ierb_probe(struct platform_device *pdev) return 0; } -static int enetc_ierb_remove(struct platform_device *pdev) -{ - return 0; -} - static const struct of_device_id enetc_ierb_match[] = { { .compatible = "fsl,ls1028a-enetc-ierb", }, {}, @@ -144,7 +139,6 @@ static struct platform_driver enetc_ierb_driver = { .of_match_table = enetc_ierb_match, }, .probe = enetc_ierb_probe, - .remove = enetc_ierb_remove, }; module_platform_driver(enetc_ierb_driver); diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 644f3c963730..2341597408d1 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -3191,7 +3191,7 @@ static void fec_enet_free_buffers(struct net_device *ndev) for (q = 0; q < fep->num_rx_queues; q++) { rxq = fep->rx_queue[q]; for (i = 0; i < rxq->bd.ring_size; i++) - page_pool_release_page(rxq->page_pool, rxq->rx_skb_info[i].page); + page_pool_put_full_page(rxq->page_pool, rxq->rx_skb_info[i].page, false); for (i = 0; i < XDP_STATS_TOTAL; i++) rxq->stats[i] = 0; diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c index d00bae15a901..d528ca681b6f 100644 --- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c +++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c @@ -1430,7 +1430,7 @@ int dtsec_initialization(struct mac_device *mac_dev, dtsec->dtsec_drv_param->tx_pad_crc = true; phy_node = of_parse_phandle(mac_node, "tbi-handle", 0); - if (!phy_node || of_device_is_available(phy_node)) { + if (!phy_node || !of_device_is_available(phy_node)) { of_node_put(phy_node); err = -EINVAL; dev_err_probe(mac_dev->dev, err, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 0ec5730b1788..b4c4fb873568 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -3855,18 +3855,16 @@ static int hns3_gro_complete(struct sk_buff *skb, u32 l234info) return 0; } -static bool hns3_checksum_complete(struct hns3_enet_ring *ring, +static void hns3_checksum_complete(struct hns3_enet_ring *ring, struct sk_buff *skb, u32 ptype, u16 csum) { if (ptype == HNS3_INVALID_PTYPE || hns3_rx_ptype_tbl[ptype].ip_summed != CHECKSUM_COMPLETE) - return false; + return; hns3_ring_stats_update(ring, csum_complete); skb->ip_summed = CHECKSUM_COMPLETE; skb->csum = csum_unfold((__force __sum16)csum); - - return true; } static void hns3_rx_handle_csum(struct sk_buff *skb, u32 l234info, @@ -3926,8 +3924,7 @@ static void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb, ptype = hnae3_get_field(ol_info, HNS3_RXD_PTYPE_M, HNS3_RXD_PTYPE_S); - if (hns3_checksum_complete(ring, skb, ptype, csum)) - return; + hns3_checksum_complete(ring, skb, ptype, csum); /* check if hardware has done checksum */ if (!(bd_base_info & BIT(HNS3_RXD_L3L4P_B))) @@ -3936,6 +3933,7 @@ static void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb, if (unlikely(l234info & (BIT(HNS3_RXD_L3E_B) | BIT(HNS3_RXD_L4E_B) | BIT(HNS3_RXD_OL3E_B) | BIT(HNS3_RXD_OL4E_B)))) { + skb->ip_summed = CHECKSUM_NONE; hns3_ring_stats_update(ring, l3l4_csum_err); return; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 4e54f91f7a6c..07ad5f35219e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -3910,9 +3910,17 @@ static int hclge_set_all_vf_rst(struct hclge_dev *hdev, bool reset) return ret; } - if (!reset || !test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state)) + if (!reset || + !test_bit(HCLGE_VPORT_STATE_INITED, &vport->state)) continue; + if (!test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state) && + hdev->reset_type == HNAE3_FUNC_RESET) { + set_bit(HCLGE_VPORT_NEED_NOTIFY_RESET, + &vport->need_notify); + continue; + } + /* Inform VF to process the reset. * hclge_inform_reset_assert_to_vf may fail if VF * driver is not loaded. @@ -4609,18 +4617,25 @@ static void hclge_reset_service_task(struct hclge_dev *hdev) static void hclge_update_vport_alive(struct hclge_dev *hdev) { +#define HCLGE_ALIVE_SECONDS_NORMAL 8 + + unsigned long alive_time = HCLGE_ALIVE_SECONDS_NORMAL * HZ; int i; /* start from vport 1 for PF is always alive */ for (i = 1; i < hdev->num_alloc_vport; i++) { struct hclge_vport *vport = &hdev->vport[i]; - if (time_after(jiffies, vport->last_active_jiffies + 8 * HZ)) + if (!test_bit(HCLGE_VPORT_STATE_INITED, &vport->state) || + !test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state)) + continue; + if (time_after(jiffies, vport->last_active_jiffies + + alive_time)) { clear_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state); - - /* If vf is not alive, set to default value */ - if (!test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state)) - vport->mps = HCLGE_MAC_DEFAULT_FRAME; + dev_warn(&hdev->pdev->dev, + "VF %u heartbeat timeout\n", + i - HCLGE_VF_VPORT_START_NUM); + } } } @@ -8064,9 +8079,11 @@ int hclge_vport_start(struct hclge_vport *vport) { struct hclge_dev *hdev = vport->back; + set_bit(HCLGE_VPORT_STATE_INITED, &vport->state); set_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state); set_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, &vport->state); vport->last_active_jiffies = jiffies; + vport->need_notify = 0; if (test_bit(vport->vport_id, hdev->vport_config_block)) { if (vport->vport_id) { @@ -8084,7 +8101,9 @@ int hclge_vport_start(struct hclge_vport *vport) void hclge_vport_stop(struct hclge_vport *vport) { + clear_bit(HCLGE_VPORT_STATE_INITED, &vport->state); clear_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state); + vport->need_notify = 0; } static int hclge_client_start(struct hnae3_handle *handle) @@ -9208,7 +9227,8 @@ static int hclge_set_vf_mac(struct hnae3_handle *handle, int vf, return 0; } - dev_info(&hdev->pdev->dev, "MAC of VF %d has been set to %s\n", + dev_info(&hdev->pdev->dev, + "MAC of VF %d has been set to %s, will be active after VF reset\n", vf, format_mac_addr); return 0; } @@ -10465,12 +10485,16 @@ static int hclge_set_vf_vlan_filter(struct hnae3_handle *handle, int vfid, * for DEVICE_VERSION_V3, vf doesn't need to know about the port based * VLAN state. */ - if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V3 && - test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state)) - (void)hclge_push_vf_port_base_vlan_info(&hdev->vport[0], - vport->vport_id, - state, &vlan_info); - + if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V3) { + if (test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state)) + (void)hclge_push_vf_port_base_vlan_info(&hdev->vport[0], + vport->vport_id, + state, + &vlan_info); + else + set_bit(HCLGE_VPORT_NEED_NOTIFY_VF_VLAN, + &vport->need_notify); + } return 0; } @@ -11941,7 +11965,7 @@ static void hclge_reset_vport_state(struct hclge_dev *hdev) int i; for (i = 0; i < hdev->num_alloc_vport; i++) { - hclge_vport_stop(vport); + clear_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state); vport++; } } @@ -12754,60 +12778,71 @@ static int hclge_gro_en(struct hnae3_handle *handle, bool enable) return ret; } -static void hclge_sync_promisc_mode(struct hclge_dev *hdev) +static int hclge_sync_vport_promisc_mode(struct hclge_vport *vport) { - struct hclge_vport *vport = &hdev->vport[0]; struct hnae3_handle *handle = &vport->nic; + struct hclge_dev *hdev = vport->back; + bool uc_en = false; + bool mc_en = false; u8 tmp_flags; + bool bc_en; int ret; - u16 i; if (vport->last_promisc_flags != vport->overflow_promisc_flags) { set_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, &vport->state); vport->last_promisc_flags = vport->overflow_promisc_flags; } - if (test_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, &vport->state)) { + if (!test_and_clear_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, + &vport->state)) + return 0; + + /* for PF */ + if (!vport->vport_id) { tmp_flags = handle->netdev_flags | vport->last_promisc_flags; ret = hclge_set_promisc_mode(handle, tmp_flags & HNAE3_UPE, tmp_flags & HNAE3_MPE); - if (!ret) { - clear_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, - &vport->state); + if (!ret) set_bit(HCLGE_VPORT_STATE_VLAN_FLTR_CHANGE, &vport->state); - } + else + set_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, + &vport->state); + return ret; } - for (i = 1; i < hdev->num_alloc_vport; i++) { - bool uc_en = false; - bool mc_en = false; - bool bc_en; + /* for VF */ + if (vport->vf_info.trusted) { + uc_en = vport->vf_info.request_uc_en > 0 || + vport->overflow_promisc_flags & HNAE3_OVERFLOW_UPE; + mc_en = vport->vf_info.request_mc_en > 0 || + vport->overflow_promisc_flags & HNAE3_OVERFLOW_MPE; + } + bc_en = vport->vf_info.request_bc_en > 0; - vport = &hdev->vport[i]; + ret = hclge_cmd_set_promisc_mode(hdev, vport->vport_id, uc_en, + mc_en, bc_en); + if (ret) { + set_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, &vport->state); + return ret; + } + hclge_set_vport_vlan_fltr_change(vport); - if (!test_and_clear_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, - &vport->state)) - continue; + return 0; +} - if (vport->vf_info.trusted) { - uc_en = vport->vf_info.request_uc_en > 0 || - vport->overflow_promisc_flags & - HNAE3_OVERFLOW_UPE; - mc_en = vport->vf_info.request_mc_en > 0 || - vport->overflow_promisc_flags & - HNAE3_OVERFLOW_MPE; - } - bc_en = vport->vf_info.request_bc_en > 0; +static void hclge_sync_promisc_mode(struct hclge_dev *hdev) +{ + struct hclge_vport *vport; + int ret; + u16 i; - ret = hclge_cmd_set_promisc_mode(hdev, vport->vport_id, uc_en, - mc_en, bc_en); - if (ret) { - set_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, - &vport->state); + for (i = 0; i < hdev->num_alloc_vport; i++) { + vport = &hdev->vport[i]; + + ret = hclge_sync_vport_promisc_mode(vport); + if (ret) return; - } - hclge_set_vport_vlan_fltr_change(vport); } } @@ -12944,6 +12979,11 @@ static void hclge_clear_vport_vf_info(struct hclge_vport *vport, int vfid) struct hclge_vlan_info vlan_info; int ret; + clear_bit(HCLGE_VPORT_STATE_INITED, &vport->state); + clear_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state); + vport->need_notify = 0; + vport->mps = 0; + /* after disable sriov, clean VF rate configured by PF */ ret = hclge_tm_qs_shaper_cfg(vport, 0); if (ret) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 495b639b0dc2..13f23d606e77 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -995,9 +995,15 @@ enum HCLGE_VPORT_STATE { HCLGE_VPORT_STATE_MAC_TBL_CHANGE, HCLGE_VPORT_STATE_PROMISC_CHANGE, HCLGE_VPORT_STATE_VLAN_FLTR_CHANGE, + HCLGE_VPORT_STATE_INITED, HCLGE_VPORT_STATE_MAX }; +enum HCLGE_VPORT_NEED_NOTIFY { + HCLGE_VPORT_NEED_NOTIFY_RESET, + HCLGE_VPORT_NEED_NOTIFY_VF_VLAN, +}; + struct hclge_vlan_info { u16 vlan_proto; /* so far support 802.1Q only */ u16 qos; @@ -1044,6 +1050,7 @@ struct hclge_vport { struct hnae3_handle roce; unsigned long state; + unsigned long need_notify; unsigned long last_active_jiffies; u32 mps; /* Max packet size */ struct hclge_vf_info vf_info; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index a7b06c63143c..04ff9bf12185 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -124,17 +124,26 @@ static int hclge_send_mbx_msg(struct hclge_vport *vport, u8 *msg, u16 msg_len, return status; } +static int hclge_inform_vf_reset(struct hclge_vport *vport, u16 reset_type) +{ + __le16 msg_data; + u8 dest_vfid; + + dest_vfid = (u8)vport->vport_id; + msg_data = cpu_to_le16(reset_type); + + /* send this requested info to VF */ + return hclge_send_mbx_msg(vport, (u8 *)&msg_data, sizeof(msg_data), + HCLGE_MBX_ASSERTING_RESET, dest_vfid); +} + int hclge_inform_reset_assert_to_vf(struct hclge_vport *vport) { struct hclge_dev *hdev = vport->back; - __le16 msg_data; u16 reset_type; - u8 dest_vfid; BUILD_BUG_ON(HNAE3_MAX_RESET > U16_MAX); - dest_vfid = (u8)vport->vport_id; - if (hdev->reset_type == HNAE3_FUNC_RESET) reset_type = HNAE3_VF_PF_FUNC_RESET; else if (hdev->reset_type == HNAE3_FLR_RESET) @@ -142,11 +151,7 @@ int hclge_inform_reset_assert_to_vf(struct hclge_vport *vport) else reset_type = HNAE3_VF_FUNC_RESET; - msg_data = cpu_to_le16(reset_type); - - /* send this requested info to VF */ - return hclge_send_mbx_msg(vport, (u8 *)&msg_data, sizeof(msg_data), - HCLGE_MBX_ASSERTING_RESET, dest_vfid); + return hclge_inform_vf_reset(vport, reset_type); } static void hclge_free_vector_ring_chain(struct hnae3_ring_chain_node *head) @@ -652,9 +657,56 @@ static int hclge_reset_vf(struct hclge_vport *vport) return hclge_func_reset_cmd(hdev, vport->vport_id); } +static void hclge_notify_vf_config(struct hclge_vport *vport) +{ + struct hclge_dev *hdev = vport->back; + struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev); + struct hclge_port_base_vlan_config *vlan_cfg; + int ret; + + hclge_push_vf_link_status(vport); + if (test_bit(HCLGE_VPORT_NEED_NOTIFY_RESET, &vport->need_notify)) { + ret = hclge_inform_vf_reset(vport, HNAE3_VF_PF_FUNC_RESET); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to inform VF %u reset!", + vport->vport_id - HCLGE_VF_VPORT_START_NUM); + return; + } + vport->need_notify = 0; + return; + } + + if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V3 && + test_bit(HCLGE_VPORT_NEED_NOTIFY_VF_VLAN, &vport->need_notify)) { + vlan_cfg = &vport->port_base_vlan_cfg; + ret = hclge_push_vf_port_base_vlan_info(&hdev->vport[0], + vport->vport_id, + vlan_cfg->state, + &vlan_cfg->vlan_info); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to inform VF %u port base vlan!", + vport->vport_id - HCLGE_VF_VPORT_START_NUM); + return; + } + clear_bit(HCLGE_VPORT_NEED_NOTIFY_VF_VLAN, &vport->need_notify); + } +} + static void hclge_vf_keep_alive(struct hclge_vport *vport) { + struct hclge_dev *hdev = vport->back; + vport->last_active_jiffies = jiffies; + + if (test_bit(HCLGE_VPORT_STATE_INITED, &vport->state) && + !test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state)) { + set_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state); + dev_info(&hdev->pdev->dev, "VF %u is alive!", + vport->vport_id - HCLGE_VF_VPORT_START_NUM); + hclge_notify_vf_config(vport); + } } static int hclge_set_vf_mtu(struct hclge_vport *vport, @@ -954,6 +1006,7 @@ static int hclge_mbx_vf_uninit_handler(struct hclge_mbx_ops_param *param) hclge_rm_vport_all_mac_table(param->vport, true, HCLGE_MAC_ADDR_MC); hclge_rm_vport_all_vlan_table(param->vport, true); + param->vport->mps = 0; return 0; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index db6f7cdba958..e84e5be8e59e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -2767,7 +2767,8 @@ static int hclgevf_pci_reset(struct hclgevf_dev *hdev) struct pci_dev *pdev = hdev->pdev; int ret = 0; - if (hdev->reset_type == HNAE3_VF_FULL_RESET && + if ((hdev->reset_type == HNAE3_VF_FULL_RESET || + hdev->reset_type == HNAE3_FLR_RESET) && test_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state)) { hclgevf_misc_irq_uninit(hdev); hclgevf_uninit_msi(hdev); @@ -3129,7 +3130,7 @@ static int hclgevf_set_channels(struct hnae3_handle *handle, u32 new_tqps_num, hclgevf_update_rss_size(handle, new_tqps_num); - hclge_comm_get_rss_tc_info(cur_rss_size, hdev->hw_tc_map, + hclge_comm_get_rss_tc_info(kinfo->rss_size, hdev->hw_tc_map, tc_offset, tc_valid, tc_size); ret = hclge_comm_set_rss_tc_mode(&hdev->hw.hw, tc_offset, tc_valid, tc_size); diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h index 0d1bab4ac1b0..2a9f1eeeb701 100644 --- a/drivers/net/ethernet/intel/iavf/iavf.h +++ b/drivers/net/ethernet/intel/iavf/iavf.h @@ -249,6 +249,7 @@ struct iavf_cloud_filter { /* board specific private data structure */ struct iavf_adapter { + struct workqueue_struct *wq; struct work_struct reset_task; struct work_struct adminq_task; struct delayed_work client_task; @@ -459,7 +460,6 @@ struct iavf_device { /* needed by iavf_ethtool.c */ extern char iavf_driver_name[]; -extern struct workqueue_struct *iavf_wq; static inline const char *iavf_state_str(enum iavf_state_t state) { diff --git a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c index d79ead5e8d0c..6f171d1d85b7 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c +++ b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c @@ -532,7 +532,7 @@ static int iavf_set_priv_flags(struct net_device *netdev, u32 flags) if (changed_flags & IAVF_FLAG_LEGACY_RX) { if (netif_running(netdev)) { adapter->flags |= IAVF_FLAG_RESET_NEEDED; - queue_work(iavf_wq, &adapter->reset_task); + queue_work(adapter->wq, &adapter->reset_task); } } @@ -672,7 +672,7 @@ static int iavf_set_ringparam(struct net_device *netdev, if (netif_running(netdev)) { adapter->flags |= IAVF_FLAG_RESET_NEEDED; - queue_work(iavf_wq, &adapter->reset_task); + queue_work(adapter->wq, &adapter->reset_task); } return 0; @@ -1433,7 +1433,7 @@ static int iavf_add_fdir_ethtool(struct iavf_adapter *adapter, struct ethtool_rx adapter->aq_required |= IAVF_FLAG_AQ_ADD_FDIR_FILTER; spin_unlock_bh(&adapter->fdir_fltr_lock); - mod_delayed_work(iavf_wq, &adapter->watchdog_task, 0); + mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0); ret: if (err && fltr) @@ -1474,7 +1474,7 @@ static int iavf_del_fdir_ethtool(struct iavf_adapter *adapter, struct ethtool_rx spin_unlock_bh(&adapter->fdir_fltr_lock); if (fltr && fltr->state == IAVF_FDIR_FLTR_DEL_REQUEST) - mod_delayed_work(iavf_wq, &adapter->watchdog_task, 0); + mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0); return err; } @@ -1658,7 +1658,7 @@ iavf_set_adv_rss_hash_opt(struct iavf_adapter *adapter, spin_unlock_bh(&adapter->adv_rss_lock); if (!err) - mod_delayed_work(iavf_wq, &adapter->watchdog_task, 0); + mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0); mutex_unlock(&adapter->crit_lock); diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c index c4e451ef7942..4b09785d2147 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_main.c +++ b/drivers/net/ethernet/intel/iavf/iavf_main.c @@ -49,7 +49,6 @@ MODULE_DESCRIPTION("Intel(R) Ethernet Adaptive Virtual Function Network Driver") MODULE_LICENSE("GPL v2"); static const struct net_device_ops iavf_netdev_ops; -struct workqueue_struct *iavf_wq; int iavf_status_to_errno(enum iavf_status status) { @@ -277,7 +276,7 @@ void iavf_schedule_reset(struct iavf_adapter *adapter) if (!(adapter->flags & (IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED))) { adapter->flags |= IAVF_FLAG_RESET_NEEDED; - queue_work(iavf_wq, &adapter->reset_task); + queue_work(adapter->wq, &adapter->reset_task); } } @@ -291,7 +290,7 @@ void iavf_schedule_reset(struct iavf_adapter *adapter) void iavf_schedule_request_stats(struct iavf_adapter *adapter) { adapter->aq_required |= IAVF_FLAG_AQ_REQUEST_STATS; - mod_delayed_work(iavf_wq, &adapter->watchdog_task, 0); + mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0); } /** @@ -411,7 +410,7 @@ static irqreturn_t iavf_msix_aq(int irq, void *data) if (adapter->state != __IAVF_REMOVE) /* schedule work on the private workqueue */ - queue_work(iavf_wq, &adapter->adminq_task); + queue_work(adapter->wq, &adapter->adminq_task); return IRQ_HANDLED; } @@ -1034,7 +1033,7 @@ int iavf_replace_primary_mac(struct iavf_adapter *adapter, /* schedule the watchdog task to immediately process the request */ if (f) { - queue_work(iavf_wq, &adapter->watchdog_task.work); + mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0); return 0; } return -ENOMEM; @@ -1257,7 +1256,7 @@ static void iavf_up_complete(struct iavf_adapter *adapter) adapter->aq_required |= IAVF_FLAG_AQ_ENABLE_QUEUES; if (CLIENT_ENABLED(adapter)) adapter->flags |= IAVF_FLAG_CLIENT_NEEDS_OPEN; - mod_delayed_work(iavf_wq, &adapter->watchdog_task, 0); + mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0); } /** @@ -1414,7 +1413,7 @@ void iavf_down(struct iavf_adapter *adapter) adapter->aq_required |= IAVF_FLAG_AQ_DISABLE_QUEUES; } - mod_delayed_work(iavf_wq, &adapter->watchdog_task, 0); + mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0); } /** @@ -2248,7 +2247,7 @@ iavf_set_vlan_offload_features(struct iavf_adapter *adapter, if (aq_required) { adapter->aq_required |= aq_required; - mod_delayed_work(iavf_wq, &adapter->watchdog_task, 0); + mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0); } } @@ -2693,6 +2692,15 @@ static void iavf_watchdog_task(struct work_struct *work) goto restart_watchdog; } + if ((adapter->flags & IAVF_FLAG_SETUP_NETDEV_FEATURES) && + adapter->netdev_registered && + !test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section) && + rtnl_trylock()) { + netdev_update_features(adapter->netdev); + rtnl_unlock(); + adapter->flags &= ~IAVF_FLAG_SETUP_NETDEV_FEATURES; + } + if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED) iavf_change_state(adapter, __IAVF_COMM_FAILED); @@ -2700,7 +2708,7 @@ static void iavf_watchdog_task(struct work_struct *work) adapter->aq_required = 0; adapter->current_op = VIRTCHNL_OP_UNKNOWN; mutex_unlock(&adapter->crit_lock); - queue_work(iavf_wq, &adapter->reset_task); + queue_work(adapter->wq, &adapter->reset_task); return; } @@ -2708,31 +2716,31 @@ static void iavf_watchdog_task(struct work_struct *work) case __IAVF_STARTUP: iavf_startup(adapter); mutex_unlock(&adapter->crit_lock); - queue_delayed_work(iavf_wq, &adapter->watchdog_task, + queue_delayed_work(adapter->wq, &adapter->watchdog_task, msecs_to_jiffies(30)); return; case __IAVF_INIT_VERSION_CHECK: iavf_init_version_check(adapter); mutex_unlock(&adapter->crit_lock); - queue_delayed_work(iavf_wq, &adapter->watchdog_task, + queue_delayed_work(adapter->wq, &adapter->watchdog_task, msecs_to_jiffies(30)); return; case __IAVF_INIT_GET_RESOURCES: iavf_init_get_resources(adapter); mutex_unlock(&adapter->crit_lock); - queue_delayed_work(iavf_wq, &adapter->watchdog_task, + queue_delayed_work(adapter->wq, &adapter->watchdog_task, msecs_to_jiffies(1)); return; case __IAVF_INIT_EXTENDED_CAPS: iavf_init_process_extended_caps(adapter); mutex_unlock(&adapter->crit_lock); - queue_delayed_work(iavf_wq, &adapter->watchdog_task, + queue_delayed_work(adapter->wq, &adapter->watchdog_task, msecs_to_jiffies(1)); return; case __IAVF_INIT_CONFIG_ADAPTER: iavf_init_config_adapter(adapter); mutex_unlock(&adapter->crit_lock); - queue_delayed_work(iavf_wq, &adapter->watchdog_task, + queue_delayed_work(adapter->wq, &adapter->watchdog_task, msecs_to_jiffies(1)); return; case __IAVF_INIT_FAILED: @@ -2751,14 +2759,14 @@ static void iavf_watchdog_task(struct work_struct *work) adapter->flags |= IAVF_FLAG_PF_COMMS_FAILED; iavf_shutdown_adminq(hw); mutex_unlock(&adapter->crit_lock); - queue_delayed_work(iavf_wq, + queue_delayed_work(adapter->wq, &adapter->watchdog_task, (5 * HZ)); return; } /* Try again from failed step*/ iavf_change_state(adapter, adapter->last_state); mutex_unlock(&adapter->crit_lock); - queue_delayed_work(iavf_wq, &adapter->watchdog_task, HZ); + queue_delayed_work(adapter->wq, &adapter->watchdog_task, HZ); return; case __IAVF_COMM_FAILED: if (test_bit(__IAVF_IN_REMOVE_TASK, @@ -2789,13 +2797,14 @@ static void iavf_watchdog_task(struct work_struct *work) adapter->aq_required = 0; adapter->current_op = VIRTCHNL_OP_UNKNOWN; mutex_unlock(&adapter->crit_lock); - queue_delayed_work(iavf_wq, + queue_delayed_work(adapter->wq, &adapter->watchdog_task, msecs_to_jiffies(10)); return; case __IAVF_RESETTING: mutex_unlock(&adapter->crit_lock); - queue_delayed_work(iavf_wq, &adapter->watchdog_task, HZ * 2); + queue_delayed_work(adapter->wq, &adapter->watchdog_task, + HZ * 2); return; case __IAVF_DOWN: case __IAVF_DOWN_PENDING: @@ -2834,9 +2843,9 @@ static void iavf_watchdog_task(struct work_struct *work) adapter->aq_required = 0; adapter->current_op = VIRTCHNL_OP_UNKNOWN; dev_err(&adapter->pdev->dev, "Hardware reset detected\n"); - queue_work(iavf_wq, &adapter->reset_task); + queue_work(adapter->wq, &adapter->reset_task); mutex_unlock(&adapter->crit_lock); - queue_delayed_work(iavf_wq, + queue_delayed_work(adapter->wq, &adapter->watchdog_task, HZ * 2); return; } @@ -2845,12 +2854,13 @@ static void iavf_watchdog_task(struct work_struct *work) mutex_unlock(&adapter->crit_lock); restart_watchdog: if (adapter->state >= __IAVF_DOWN) - queue_work(iavf_wq, &adapter->adminq_task); + queue_work(adapter->wq, &adapter->adminq_task); if (adapter->aq_required) - queue_delayed_work(iavf_wq, &adapter->watchdog_task, + queue_delayed_work(adapter->wq, &adapter->watchdog_task, msecs_to_jiffies(20)); else - queue_delayed_work(iavf_wq, &adapter->watchdog_task, HZ * 2); + queue_delayed_work(adapter->wq, &adapter->watchdog_task, + HZ * 2); } /** @@ -2952,7 +2962,7 @@ static void iavf_reset_task(struct work_struct *work) */ if (!mutex_trylock(&adapter->crit_lock)) { if (adapter->state != __IAVF_REMOVE) - queue_work(iavf_wq, &adapter->reset_task); + queue_work(adapter->wq, &adapter->reset_task); goto reset_finish; } @@ -3116,7 +3126,7 @@ continue_reset: bitmap_clear(adapter->vsi.active_cvlans, 0, VLAN_N_VID); bitmap_clear(adapter->vsi.active_svlans, 0, VLAN_N_VID); - mod_delayed_work(iavf_wq, &adapter->watchdog_task, 2); + mod_delayed_work(adapter->wq, &adapter->watchdog_task, 2); /* We were running when the reset started, so we need to restore some * state here. @@ -3208,7 +3218,7 @@ static void iavf_adminq_task(struct work_struct *work) if (adapter->state == __IAVF_REMOVE) return; - queue_work(iavf_wq, &adapter->adminq_task); + queue_work(adapter->wq, &adapter->adminq_task); goto out; } @@ -3232,24 +3242,6 @@ static void iavf_adminq_task(struct work_struct *work) } while (pending); mutex_unlock(&adapter->crit_lock); - if ((adapter->flags & IAVF_FLAG_SETUP_NETDEV_FEATURES)) { - if (adapter->netdev_registered || - !test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section)) { - struct net_device *netdev = adapter->netdev; - - rtnl_lock(); - netdev_update_features(netdev); - rtnl_unlock(); - /* Request VLAN offload settings */ - if (VLAN_V2_ALLOWED(adapter)) - iavf_set_vlan_offload_features - (adapter, 0, netdev->features); - - iavf_set_queue_vlan_tag_loc(adapter); - } - - adapter->flags &= ~IAVF_FLAG_SETUP_NETDEV_FEATURES; - } if ((adapter->flags & (IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED)) || adapter->state == __IAVF_RESETTING) @@ -3850,7 +3842,7 @@ static int iavf_parse_cls_flower(struct iavf_adapter *adapter, field_flags |= IAVF_CLOUD_FIELD_IIP; } else { dev_err(&adapter->pdev->dev, "Bad ip src mask 0x%08x\n", - be32_to_cpu(match.mask->dst)); + be32_to_cpu(match.mask->src)); return -EINVAL; } } @@ -4349,7 +4341,7 @@ static int iavf_change_mtu(struct net_device *netdev, int new_mtu) if (netif_running(netdev)) { adapter->flags |= IAVF_FLAG_RESET_NEEDED; - queue_work(iavf_wq, &adapter->reset_task); + queue_work(adapter->wq, &adapter->reset_task); } return 0; @@ -4898,6 +4890,13 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hw = &adapter->hw; hw->back = adapter; + adapter->wq = alloc_ordered_workqueue("%s", WQ_MEM_RECLAIM, + iavf_driver_name); + if (!adapter->wq) { + err = -ENOMEM; + goto err_alloc_wq; + } + adapter->msg_enable = BIT(DEFAULT_DEBUG_LEVEL_SHIFT) - 1; iavf_change_state(adapter, __IAVF_STARTUP); @@ -4942,7 +4941,7 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) INIT_WORK(&adapter->adminq_task, iavf_adminq_task); INIT_DELAYED_WORK(&adapter->watchdog_task, iavf_watchdog_task); INIT_DELAYED_WORK(&adapter->client_task, iavf_client_task); - queue_delayed_work(iavf_wq, &adapter->watchdog_task, + queue_delayed_work(adapter->wq, &adapter->watchdog_task, msecs_to_jiffies(5 * (pdev->devfn & 0x07))); /* Setup the wait queue for indicating transition to down status */ @@ -4954,6 +4953,8 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; err_ioremap: + destroy_workqueue(adapter->wq); +err_alloc_wq: free_netdev(netdev); err_alloc_etherdev: pci_disable_pcie_error_reporting(pdev); @@ -5023,7 +5024,7 @@ static int __maybe_unused iavf_resume(struct device *dev_d) return err; } - queue_work(iavf_wq, &adapter->reset_task); + queue_work(adapter->wq, &adapter->reset_task); netif_device_attach(adapter->netdev); @@ -5170,6 +5171,8 @@ static void iavf_remove(struct pci_dev *pdev) } spin_unlock_bh(&adapter->adv_rss_lock); + destroy_workqueue(adapter->wq); + free_netdev(netdev); pci_disable_pcie_error_reporting(pdev); @@ -5196,24 +5199,11 @@ static struct pci_driver iavf_driver = { **/ static int __init iavf_init_module(void) { - int ret; - pr_info("iavf: %s\n", iavf_driver_string); pr_info("%s\n", iavf_copyright); - iavf_wq = alloc_workqueue("%s", WQ_UNBOUND | WQ_MEM_RECLAIM, 1, - iavf_driver_name); - if (!iavf_wq) { - pr_err("%s: Failed to create workqueue\n", iavf_driver_name); - return -ENOMEM; - } - - ret = pci_register_driver(&iavf_driver); - if (ret) - destroy_workqueue(iavf_wq); - - return ret; + return pci_register_driver(&iavf_driver); } module_init(iavf_init_module); @@ -5227,7 +5217,6 @@ module_init(iavf_init_module); static void __exit iavf_exit_module(void) { pci_unregister_driver(&iavf_driver); - destroy_workqueue(iavf_wq); } module_exit(iavf_exit_module); diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c index 24a701fd140e..365ca0c710c4 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c +++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c @@ -1952,7 +1952,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter, if (!(adapter->flags & IAVF_FLAG_RESET_PENDING)) { adapter->flags |= IAVF_FLAG_RESET_PENDING; dev_info(&adapter->pdev->dev, "Scheduling reset task\n"); - queue_work(iavf_wq, &adapter->reset_task); + queue_work(adapter->wq, &adapter->reset_task); } break; default: @@ -2226,6 +2226,14 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter, iavf_process_config(adapter); adapter->flags |= IAVF_FLAG_SETUP_NETDEV_FEATURES; + + /* Request VLAN offload settings */ + if (VLAN_V2_ALLOWED(adapter)) + iavf_set_vlan_offload_features(adapter, 0, + netdev->features); + + iavf_set_queue_vlan_tag_loc(adapter); + was_mac_changed = !ether_addr_equal(netdev->dev_addr, adapter->hw.mac.addr); diff --git a/drivers/net/ethernet/intel/ice/ice_gnss.c b/drivers/net/ethernet/intel/ice/ice_gnss.c index b5a7f246d230..43e199b5b513 100644 --- a/drivers/net/ethernet/intel/ice/ice_gnss.c +++ b/drivers/net/ethernet/intel/ice/ice_gnss.c @@ -363,6 +363,7 @@ ice_gnss_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) /* Send the data out to a hardware port */ write_buf = kzalloc(sizeof(*write_buf), GFP_KERNEL); if (!write_buf) { + kfree(cmd_buf); err = -ENOMEM; goto exit; } @@ -460,6 +461,9 @@ static struct tty_driver *ice_gnss_create_tty_driver(struct ice_pf *pf) for (i = 0; i < ICE_GNSS_TTY_MINOR_DEVICES; i++) { pf->gnss_tty_port[i] = kzalloc(sizeof(*pf->gnss_tty_port[i]), GFP_KERNEL); + if (!pf->gnss_tty_port[i]) + goto err_out; + pf->gnss_serial[i] = NULL; tty_port_init(pf->gnss_tty_port[i]); @@ -469,21 +473,23 @@ static struct tty_driver *ice_gnss_create_tty_driver(struct ice_pf *pf) err = tty_register_driver(tty_driver); if (err) { dev_err(dev, "Failed to register TTY driver err=%d\n", err); - - for (i = 0; i < ICE_GNSS_TTY_MINOR_DEVICES; i++) { - tty_port_destroy(pf->gnss_tty_port[i]); - kfree(pf->gnss_tty_port[i]); - } - kfree(ttydrv_name); - tty_driver_kref_put(pf->ice_gnss_tty_driver); - - return NULL; + goto err_out; } for (i = 0; i < ICE_GNSS_TTY_MINOR_DEVICES; i++) dev_info(dev, "%s%d registered\n", ttydrv_name, i); return tty_driver; + +err_out: + while (i--) { + tty_port_destroy(pf->gnss_tty_port[i]); + kfree(pf->gnss_tty_port[i]); + } + kfree(ttydrv_name); + tty_driver_kref_put(pf->ice_gnss_tty_driver); + + return NULL; } /** diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 94aa834cd9a6..a596e07b3ce9 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -3235,9 +3235,6 @@ int ice_vsi_release(struct ice_vsi *vsi) } } - if (vsi->type == ICE_VSI_PF) - ice_devlink_destroy_pf_port(pf); - if (vsi->type == ICE_VSI_VF && vsi->agg_node && vsi->agg_node->valid) vsi->agg_node->num_vsis--; diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index a9a7f8b52140..237ede2cffb0 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -4590,7 +4590,7 @@ static void ice_print_wake_reason(struct ice_pf *pf) } /** - * ice_register_netdev - register netdev and devlink port + * ice_register_netdev - register netdev * @pf: pointer to the PF struct */ static int ice_register_netdev(struct ice_pf *pf) @@ -4602,11 +4602,6 @@ static int ice_register_netdev(struct ice_pf *pf) if (!vsi || !vsi->netdev) return -EIO; - err = ice_devlink_create_pf_port(pf); - if (err) - goto err_devlink_create; - - SET_NETDEV_DEVLINK_PORT(vsi->netdev, &pf->devlink_port); err = register_netdev(vsi->netdev); if (err) goto err_register_netdev; @@ -4617,8 +4612,6 @@ static int ice_register_netdev(struct ice_pf *pf) return 0; err_register_netdev: - ice_devlink_destroy_pf_port(pf); -err_devlink_create: free_netdev(vsi->netdev); vsi->netdev = NULL; clear_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state); @@ -4636,6 +4629,7 @@ static int ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent) { struct device *dev = &pdev->dev; + struct ice_vsi *vsi; struct ice_pf *pf; struct ice_hw *hw; int i, err; @@ -4918,6 +4912,18 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent) pcie_print_link_status(pf->pdev); probe_done: + err = ice_devlink_create_pf_port(pf); + if (err) + goto err_create_pf_port; + + vsi = ice_get_main_vsi(pf); + if (!vsi || !vsi->netdev) { + err = -EINVAL; + goto err_netdev_reg; + } + + SET_NETDEV_DEVLINK_PORT(vsi->netdev, &pf->devlink_port); + err = ice_register_netdev(pf); if (err) goto err_netdev_reg; @@ -4955,6 +4961,8 @@ err_init_aux_unroll: err_devlink_reg_param: ice_devlink_unregister_params(pf); err_netdev_reg: + ice_devlink_destroy_pf_port(pf); +err_create_pf_port: err_send_version_unroll: ice_vsi_release_all(pf); err_alloc_sw_unroll: @@ -5083,6 +5091,7 @@ static void ice_remove(struct pci_dev *pdev) ice_setup_mc_magic_wake(pf); ice_vsi_release_all(pf); mutex_destroy(&(&pf->hw)->fdir_fltr_lock); + ice_devlink_destroy_pf_port(pf); ice_set_wake(pf); ice_free_irq_msix_misc(pf); ice_for_each_vsi(pf, i) { diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.c b/drivers/net/ethernet/intel/ice/ice_xsk.c index 907055b77af0..7105de6fb344 100644 --- a/drivers/net/ethernet/intel/ice/ice_xsk.c +++ b/drivers/net/ethernet/intel/ice/ice_xsk.c @@ -783,7 +783,7 @@ construct_skb: static void ice_clean_xdp_tx_buf(struct ice_tx_ring *xdp_ring, struct ice_tx_buf *tx_buf) { - xdp_return_frame((struct xdp_frame *)tx_buf->raw_buf); + page_frag_free(tx_buf->raw_buf); xdp_ring->xdp_tx_active--; dma_unmap_single(xdp_ring->dev, dma_unmap_addr(tx_buf, dma), dma_unmap_len(tx_buf, len), DMA_TO_DEVICE); diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h index a7b22639cfcd..e9747ec5ac0b 100644 --- a/drivers/net/ethernet/intel/igc/igc_defines.h +++ b/drivers/net/ethernet/intel/igc/igc_defines.h @@ -475,7 +475,9 @@ #define IGC_TSAUXC_EN_TT0 BIT(0) /* Enable target time 0. */ #define IGC_TSAUXC_EN_TT1 BIT(1) /* Enable target time 1. */ #define IGC_TSAUXC_EN_CLK0 BIT(2) /* Enable Configurable Frequency Clock 0. */ +#define IGC_TSAUXC_ST0 BIT(4) /* Start Clock 0 Toggle on Target Time 0. */ #define IGC_TSAUXC_EN_CLK1 BIT(5) /* Enable Configurable Frequency Clock 1. */ +#define IGC_TSAUXC_ST1 BIT(7) /* Start Clock 1 Toggle on Target Time 1. */ #define IGC_TSAUXC_EN_TS0 BIT(8) /* Enable hardware timestamp 0. */ #define IGC_TSAUXC_AUTT0 BIT(9) /* Auxiliary Timestamp Taken. */ #define IGC_TSAUXC_EN_TS1 BIT(10) /* Enable hardware timestamp 0. */ diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/ethernet/intel/igc/igc_ptp.c index 8dbb9f903ca7..c34734d432e0 100644 --- a/drivers/net/ethernet/intel/igc/igc_ptp.c +++ b/drivers/net/ethernet/intel/igc/igc_ptp.c @@ -322,7 +322,7 @@ static int igc_ptp_feature_enable_i225(struct ptp_clock_info *ptp, ts = ns_to_timespec64(ns); if (rq->perout.index == 1) { if (use_freq) { - tsauxc_mask = IGC_TSAUXC_EN_CLK1; + tsauxc_mask = IGC_TSAUXC_EN_CLK1 | IGC_TSAUXC_ST1; tsim_mask = 0; } else { tsauxc_mask = IGC_TSAUXC_EN_TT1; @@ -333,7 +333,7 @@ static int igc_ptp_feature_enable_i225(struct ptp_clock_info *ptp, freqout = IGC_FREQOUT1; } else { if (use_freq) { - tsauxc_mask = IGC_TSAUXC_EN_CLK0; + tsauxc_mask = IGC_TSAUXC_EN_CLK0 | IGC_TSAUXC_ST0; tsim_mask = 0; } else { tsauxc_mask = IGC_TSAUXC_EN_TT0; @@ -347,10 +347,12 @@ static int igc_ptp_feature_enable_i225(struct ptp_clock_info *ptp, tsauxc = rd32(IGC_TSAUXC); tsim = rd32(IGC_TSIM); if (rq->perout.index == 1) { - tsauxc &= ~(IGC_TSAUXC_EN_TT1 | IGC_TSAUXC_EN_CLK1); + tsauxc &= ~(IGC_TSAUXC_EN_TT1 | IGC_TSAUXC_EN_CLK1 | + IGC_TSAUXC_ST1); tsim &= ~IGC_TSICR_TT1; } else { - tsauxc &= ~(IGC_TSAUXC_EN_TT0 | IGC_TSAUXC_EN_CLK0); + tsauxc &= ~(IGC_TSAUXC_EN_TT0 | IGC_TSAUXC_EN_CLK0 | + IGC_TSAUXC_ST0); tsim &= ~IGC_TSICR_TT0; } if (on) { diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c index 24aa97f993ca..123dca9ce468 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c @@ -855,9 +855,11 @@ static struct pci_dev *ixgbe_get_first_secondary_devfn(unsigned int devfn) rp_pdev = pci_get_domain_bus_and_slot(0, 0, devfn); if (rp_pdev && rp_pdev->subordinate) { bus = rp_pdev->subordinate->number; + pci_dev_put(rp_pdev); return pci_get_domain_bus_and_slot(0, bus, 0); } + pci_dev_put(rp_pdev); return NULL; } @@ -874,6 +876,7 @@ static bool ixgbe_x550em_a_has_mii(struct ixgbe_hw *hw) struct ixgbe_adapter *adapter = hw->back; struct pci_dev *pdev = adapter->pdev; struct pci_dev *func0_pdev; + bool has_mii = false; /* For the C3000 family of SoCs (x550em_a) the internal ixgbe devices * are always downstream of root ports @ 0000:00:16.0 & 0000:00:17.0 @@ -884,15 +887,16 @@ static bool ixgbe_x550em_a_has_mii(struct ixgbe_hw *hw) func0_pdev = ixgbe_get_first_secondary_devfn(PCI_DEVFN(0x16, 0)); if (func0_pdev) { if (func0_pdev == pdev) - return true; - else - return false; + has_mii = true; + goto out; } func0_pdev = ixgbe_get_first_secondary_devfn(PCI_DEVFN(0x17, 0)); if (func0_pdev == pdev) - return true; + has_mii = true; - return false; +out: + pci_dev_put(func0_pdev); + return has_mii; } /** diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c index b2b71fe80d61..724df6398bbe 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c @@ -774,9 +774,9 @@ int cgx_lmac_rx_tx_enable(void *cgxd, int lmac_id, bool enable) cfg = cgx_read(cgx, lmac_id, CGXX_CMRX_CFG); if (enable) - cfg |= CMR_EN | DATA_PKT_RX_EN | DATA_PKT_TX_EN; + cfg |= DATA_PKT_RX_EN | DATA_PKT_TX_EN; else - cfg &= ~(CMR_EN | DATA_PKT_RX_EN | DATA_PKT_TX_EN); + cfg &= ~(DATA_PKT_RX_EN | DATA_PKT_TX_EN); cgx_write(cgx, lmac_id, CGXX_CMRX_CFG, cfg); return 0; } diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h index fb2d37676d84..5a20d93004c7 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h @@ -26,7 +26,6 @@ #define CMR_P2X_SEL_SHIFT 59ULL #define CMR_P2X_SEL_NIX0 1ULL #define CMR_P2X_SEL_NIX1 2ULL -#define CMR_EN BIT_ULL(55) #define DATA_PKT_TX_EN BIT_ULL(53) #define DATA_PKT_RX_EN BIT_ULL(54) #define CGX_LMAC_TYPE_SHIFT 40 diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mcs_rvu_if.c b/drivers/net/ethernet/marvell/octeontx2/af/mcs_rvu_if.c index fa8029a94068..eb25e458266c 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/mcs_rvu_if.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/mcs_rvu_if.c @@ -589,7 +589,7 @@ int rvu_mbox_handler_mcs_free_resources(struct rvu *rvu, u16 pcifunc = req->hdr.pcifunc; struct mcs_rsrc_map *map; struct mcs *mcs; - int rc; + int rc = 0; if (req->mcs_id >= rvu->mcs_blk_cnt) return MCS_AF_ERR_INVALID_MCSID; diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c index 9e10e7471b88..8a41ad8ca04f 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c @@ -1376,18 +1376,23 @@ int otx2_sq_aura_pool_init(struct otx2_nic *pfvf) sq = &qset->sq[qidx]; sq->sqb_count = 0; sq->sqb_ptrs = kcalloc(num_sqbs, sizeof(*sq->sqb_ptrs), GFP_KERNEL); - if (!sq->sqb_ptrs) - return -ENOMEM; + if (!sq->sqb_ptrs) { + err = -ENOMEM; + goto err_mem; + } for (ptr = 0; ptr < num_sqbs; ptr++) { - if (otx2_alloc_rbuf(pfvf, pool, &bufptr)) - return -ENOMEM; + err = otx2_alloc_rbuf(pfvf, pool, &bufptr); + if (err) + goto err_mem; pfvf->hw_ops->aura_freeptr(pfvf, pool_id, bufptr); sq->sqb_ptrs[sq->sqb_count++] = (u64)bufptr; } } - return 0; +err_mem: + return err ? -ENOMEM : 0; + fail: otx2_mbox_reset(&pfvf->mbox.mbox, 0); otx2_aura_pool_free(pfvf); @@ -1430,13 +1435,13 @@ int otx2_rq_aura_pool_init(struct otx2_nic *pfvf) for (pool_id = 0; pool_id < hw->rqpool_cnt; pool_id++) { pool = &pfvf->qset.pool[pool_id]; for (ptr = 0; ptr < num_ptrs; ptr++) { - if (otx2_alloc_rbuf(pfvf, pool, &bufptr)) + err = otx2_alloc_rbuf(pfvf, pool, &bufptr); + if (err) return -ENOMEM; pfvf->hw_ops->aura_freeptr(pfvf, pool_id, bufptr + OTX2_HEAD_ROOM); } } - return 0; fail: otx2_mbox_reset(&pfvf->mbox.mbox, 0); diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h index 5bee3c3a7ce4..3d22cc6a2804 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h @@ -736,8 +736,10 @@ static inline void cn10k_aura_freeptr(void *dev, int aura, u64 buf) u64 ptrs[2]; ptrs[1] = buf; + get_cpu(); /* Free only one buffer at time during init and teardown */ __cn10k_aura_freeptr(pfvf, aura, ptrs, 2); + put_cpu(); } /* Alloc pointer from pool/aura */ diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c index 86653bb8e403..7f8ffbf79cf7 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c @@ -758,6 +758,8 @@ static void otx2vf_remove(struct pci_dev *pdev) if (vf->otx2_wq) destroy_workqueue(vf->otx2_wq); otx2_ptp_destroy(vf); + otx2_mcam_flow_del(vf); + otx2_shutdown_tc(vf); otx2vf_disable_mbox_intr(vf); otx2_detach_resources(&vf->mbox); if (test_bit(CN10K_LMTST, &vf->hw.cap_flag)) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index d3ca745d107d..c837103a9ee3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -2176,15 +2176,9 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev) return -EINVAL; } - cmd->stats = kvcalloc(MLX5_CMD_OP_MAX, sizeof(*cmd->stats), GFP_KERNEL); - if (!cmd->stats) - return -ENOMEM; - cmd->pool = dma_pool_create("mlx5_cmd", mlx5_core_dma_dev(dev), size, align, 0); - if (!cmd->pool) { - err = -ENOMEM; - goto dma_pool_err; - } + if (!cmd->pool) + return -ENOMEM; err = alloc_cmd_page(dev, cmd); if (err) @@ -2268,8 +2262,6 @@ err_free_page: err_free_pool: dma_pool_destroy(cmd->pool); -dma_pool_err: - kvfree(cmd->stats); return err; } @@ -2282,7 +2274,6 @@ void mlx5_cmd_cleanup(struct mlx5_core_dev *dev) destroy_msg_cache(dev); free_cmd_page(dev, cmd); dma_pool_destroy(cmd->pool); - kvfree(cmd->stats); } void mlx5_cmd_set_state(struct mlx5_core_dev *dev, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c index ddb197970c22..5bd83c0275f8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c @@ -468,7 +468,7 @@ static int mlx5_devlink_enable_roce_validate(struct devlink *devlink, u32 id, bool new_state = val.vbool; if (new_state && !MLX5_CAP_GEN(dev, roce) && - !MLX5_CAP_GEN(dev, roce_rw_supported)) { + !(MLX5_CAP_GEN(dev, roce_rw_supported) && MLX5_CAP_GEN_MAX(dev, roce))) { NL_SET_ERR_MSG_MOD(extack, "Device doesn't support RoCE"); return -EOPNOTSUPP; } @@ -563,7 +563,7 @@ static int mlx5_devlink_eq_depth_validate(struct devlink *devlink, u32 id, union devlink_param_value val, struct netlink_ext_ack *extack) { - return (val.vu16 >= 64 && val.vu16 <= 4096) ? 0 : -EINVAL; + return (val.vu32 >= 64 && val.vu32 <= 4096) ? 0 : -EINVAL; } static const struct devlink_param mlx5_devlink_params[] = { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/htb.c b/drivers/net/ethernet/mellanox/mlx5/core/en/htb.c index 6dac76fa58a3..09d441ecb9f6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/htb.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/htb.c @@ -637,7 +637,7 @@ mlx5e_htb_update_children(struct mlx5e_htb *htb, struct mlx5e_qos_node *node, if (child->bw_share == old_bw_share) continue; - err_one = mlx5_qos_update_node(htb->mdev, child->hw_id, child->bw_share, + err_one = mlx5_qos_update_node(htb->mdev, child->bw_share, child->max_average_bw, child->hw_id); if (!err && err_one) { err = err_one; @@ -671,7 +671,7 @@ mlx5e_htb_node_modify(struct mlx5e_htb *htb, u16 classid, u64 rate, u64 ceil, mlx5e_htb_convert_rate(htb, rate, node->parent, &bw_share); mlx5e_htb_convert_ceil(htb, ceil, &max_average_bw); - err = mlx5_qos_update_node(htb->mdev, node->parent->hw_id, bw_share, + err = mlx5_qos_update_node(htb->mdev, bw_share, max_average_bw, node->hw_id); if (err) { NL_SET_ERR_MSG_MOD(extack, "Firmware error when modifying a node."); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c index 585bdc8383ee..4ad19c981294 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c @@ -578,7 +578,6 @@ int mlx5e_mpwrq_validate_xsk(struct mlx5_core_dev *mdev, struct mlx5e_params *pa { enum mlx5e_mpwrq_umr_mode umr_mode = mlx5e_mpwrq_umr_mode(mdev, xsk); u8 page_shift = mlx5e_mpwrq_page_shift(mdev, xsk); - bool unaligned = xsk ? xsk->unaligned : false; u16 max_mtu_pkts; if (!mlx5e_check_fragmented_striding_rq_cap(mdev, page_shift, umr_mode)) @@ -591,7 +590,7 @@ int mlx5e_mpwrq_validate_xsk(struct mlx5_core_dev *mdev, struct mlx5e_params *pa * needed number of WQEs exceeds the maximum. */ max_mtu_pkts = min_t(u8, MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE, - mlx5e_mpwrq_max_log_rq_pkts(mdev, page_shift, unaligned)); + mlx5e_mpwrq_max_log_rq_pkts(mdev, page_shift, xsk->unaligned)); if (params->log_rq_mtu_frames > max_mtu_pkts) { mlx5_core_err(mdev, "Current RQ length %d is too big for XSK with given frame size %u\n", 1 << params->log_rq_mtu_frames, xsk->chunk_size); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c index 5f6f95ad6888..1ae15b8536a8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c @@ -459,7 +459,11 @@ static int mlx5e_rx_reporter_diagnose(struct devlink_health_reporter *reporter, goto unlock; for (i = 0; i < priv->channels.num; i++) { - struct mlx5e_rq *rq = &priv->channels.c[i]->rq; + struct mlx5e_channel *c = priv->channels.c[i]; + struct mlx5e_rq *rq; + + rq = test_bit(MLX5E_CHANNEL_STATE_XSK, c->state) ? + &c->xskrq : &c->rq; err = mlx5e_rx_reporter_build_diagnose_output(rq, fmsg); if (err) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/police.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/police.c index 512d43148922..c4378afdec09 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/police.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/police.c @@ -34,12 +34,6 @@ static int police_act_validate(const struct flow_action_entry *act, return -EOPNOTSUPP; } - if (act->police.rate_pkt_ps) { - NL_SET_ERR_MSG_MOD(extack, - "QoS offload not support packets per second"); - return -EOPNOTSUPP; - } - return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/post_meter.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/post_meter.c index 8d7d761482d2..50b60fd00946 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/post_meter.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/post_meter.c @@ -127,6 +127,7 @@ mlx5e_post_meter_add_rule(struct mlx5e_priv *priv, attr->counter = act_counter; attr->flags |= MLX5_ATTR_FLAG_NO_IN_PORT; + attr->inner_match_level = MLX5_MATCH_NONE; attr->outer_match_level = MLX5_MATCH_NONE; attr->chain = 0; attr->prio = 0; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/sample.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/sample.c index 1cbd2eb9d04f..f2c2c752bd1c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/sample.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/sample.c @@ -477,7 +477,6 @@ mlx5e_tc_sample_offload(struct mlx5e_tc_psample *tc_psample, struct mlx5e_sample_flow *sample_flow; struct mlx5e_sample_attr *sample_attr; struct mlx5_flow_attr *pre_attr; - u32 tunnel_id = attr->tunnel_id; struct mlx5_eswitch *esw; u32 default_tbl_id; u32 obj_id; @@ -522,7 +521,7 @@ mlx5e_tc_sample_offload(struct mlx5e_tc_psample *tc_psample, restore_obj.sample.group_id = sample_attr->group_num; restore_obj.sample.rate = sample_attr->rate; restore_obj.sample.trunc_size = sample_attr->trunc_size; - restore_obj.sample.tunnel_id = tunnel_id; + restore_obj.sample.tunnel_id = attr->tunnel_id; err = mapping_add(esw->offloads.reg_c0_obj_pool, &restore_obj, &obj_id); if (err) goto err_obj_id; @@ -548,7 +547,7 @@ mlx5e_tc_sample_offload(struct mlx5e_tc_psample *tc_psample, /* For decap action, do decap in the original flow table instead of the * default flow table. */ - if (tunnel_id) + if (attr->action & MLX5_FLOW_CONTEXT_ACTION_DECAP) pre_attr->action |= MLX5_FLOW_CONTEXT_ACTION_DECAP; pre_attr->modify_hdr = sample_flow->restore->modify_hdr; pre_attr->flags = MLX5_ATTR_FLAG_SAMPLE; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c index a69849e0deed..313df8232db7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c @@ -2103,14 +2103,9 @@ out_err: static void mlx5_ct_tc_create_dbgfs(struct mlx5_tc_ct_priv *ct_priv) { - bool is_fdb = ct_priv->ns_type == MLX5_FLOW_NAMESPACE_FDB; struct mlx5_tc_ct_debugfs *ct_dbgfs = &ct_priv->debugfs; - char dirname[16] = {}; - if (sscanf(dirname, "ct_%s", is_fdb ? "fdb" : "nic") < 0) - return; - - ct_dbgfs->root = debugfs_create_dir(dirname, mlx5_debugfs_get_dev_root(ct_priv->dev)); + ct_dbgfs->root = debugfs_create_dir("ct", mlx5_debugfs_get_dev_root(ct_priv->dev)); debugfs_create_atomic_t("offloaded", 0400, ct_dbgfs->root, &ct_dbgfs->stats.offloaded); debugfs_create_atomic_t("rx_dropped", 0400, ct_dbgfs->root, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c index ff73d25bc6eb..2aaf8ab857b8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c @@ -222,7 +222,7 @@ void mlx5e_tc_encap_flows_del(struct mlx5e_priv *priv, int err; list_for_each_entry(flow, flow_list, tmp_list) { - if (!mlx5e_is_offloaded_flow(flow) || flow_flag_test(flow, SLOW)) + if (!mlx5e_is_offloaded_flow(flow)) continue; attr = mlx5e_tc_get_encap_attr(flow); @@ -231,6 +231,13 @@ void mlx5e_tc_encap_flows_del(struct mlx5e_priv *priv, esw_attr->dests[flow->tmp_entry_index].flags &= ~MLX5_ESW_DEST_ENCAP_VALID; esw_attr->dests[flow->tmp_entry_index].pkt_reformat = NULL; + /* Clear pkt_reformat before checking slow path flag. Because + * in next iteration, the same flow is already set slow path + * flag, but still need to clear the pkt_reformat. + */ + if (flow_flag_test(flow, SLOW)) + continue; + /* update from encap rule to slow path rule */ spec = &flow->attr->parse_attr->spec; rule = mlx5e_tc_offload_to_slow_path(esw, flow, spec); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_geneve.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_geneve.c index f5b26f5a7de4..054d80c4e65c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_geneve.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_geneve.c @@ -273,6 +273,11 @@ static int mlx5e_tc_tun_parse_geneve_options(struct mlx5e_priv *priv, geneve_tlv_option_0_data, be32_to_cpu(opt_data_key)); MLX5_SET(fte_match_set_misc3, misc_3_c, geneve_tlv_option_0_data, be32_to_cpu(opt_data_mask)); + if (MLX5_CAP_ESW_FLOWTABLE_FDB(priv->mdev, + ft_field_support.geneve_tlv_option_0_exist)) { + MLX5_SET_TO_ONES(fte_match_set_misc, misc_c, geneve_tlv_option_0_exist); + MLX5_SET_TO_ONES(fte_match_set_misc, misc_v, geneve_tlv_option_0_exist); + } spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_3; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c index fd07c4cbfd1d..1f62c702b625 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c @@ -88,6 +88,8 @@ static int mlx5e_gen_ip_tunnel_header_vxlan(char buf[], struct udphdr *udp = (struct udphdr *)(buf); struct vxlanhdr *vxh; + if (tun_key->tun_flags & TUNNEL_VXLAN_OPT) + return -EOPNOTSUPP; vxh = (struct vxlanhdr *)((char *)udp + sizeof(struct udphdr)); *ip_proto = IPPROTO_UDP; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h index a92e19c4c499..8bed9c361075 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h @@ -122,11 +122,8 @@ struct mlx5e_ipsec_aso { u8 ctx[MLX5_ST_SZ_BYTES(ipsec_aso)]; dma_addr_t dma_addr; struct mlx5_aso *aso; - /* IPsec ASO caches data on every query call, - * so in nested calls, we can use this boolean to save - * recursive calls to mlx5e_ipsec_aso_query() - */ - u8 use_cache : 1; + /* Protect ASO WQ access, as it is global to whole IPsec */ + spinlock_t lock; }; struct mlx5e_ipsec { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c index 8e3614218fc4..2461462b7b99 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c @@ -320,7 +320,6 @@ static void mlx5e_ipsec_handle_event(struct work_struct *_work) if (ret) goto unlock; - aso->use_cache = true; if (attrs->esn_trigger && !MLX5_GET(ipsec_aso, aso->ctx, esn_event_arm)) { u32 mode_param = MLX5_GET(ipsec_aso, aso->ctx, mode_parameter); @@ -333,7 +332,6 @@ static void mlx5e_ipsec_handle_event(struct work_struct *_work) !MLX5_GET(ipsec_aso, aso->ctx, hard_lft_arm) || !MLX5_GET(ipsec_aso, aso->ctx, remove_flow_enable)) xfrm_state_check_expire(sa_entry->x); - aso->use_cache = false; unlock: spin_unlock(&sa_entry->x->lock); @@ -398,6 +396,7 @@ int mlx5e_ipsec_aso_init(struct mlx5e_ipsec *ipsec) goto err_aso_create; } + spin_lock_init(&aso->lock); ipsec->nb.notifier_call = mlx5e_ipsec_event; mlx5_notifier_register(mdev, &ipsec->nb); @@ -456,13 +455,12 @@ int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry, struct mlx5e_hw_objs *res; struct mlx5_aso_wqe *wqe; u8 ds_cnt; + int ret; lockdep_assert_held(&sa_entry->x->lock); - if (aso->use_cache) - return 0; - res = &mdev->mlx5e_res.hw_objs; + spin_lock_bh(&aso->lock); memset(aso->ctx, 0, sizeof(aso->ctx)); wqe = mlx5_aso_get_wqe(aso->aso); ds_cnt = DIV_ROUND_UP(sizeof(*wqe), MLX5_SEND_WQE_DS); @@ -477,7 +475,9 @@ int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry, mlx5e_ipsec_aso_copy(ctrl, data); mlx5_aso_post_wqe(aso->aso, false, &wqe->ctrl); - return mlx5_aso_poll_cq(aso->aso, false); + ret = mlx5_aso_poll_cq(aso->aso, false); + spin_unlock_bh(&aso->lock); + return ret; } void mlx5e_ipsec_aso_update_curlft(struct mlx5e_ipsec_sa_entry *sa_entry, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c index 9369a580743e..7f6b940830b3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c @@ -62,6 +62,7 @@ struct mlx5e_macsec_sa { u32 enc_key_id; u32 next_pn; sci_t sci; + ssci_t ssci; salt_t salt; struct rhash_head hash; @@ -358,7 +359,6 @@ static int mlx5e_macsec_init_sa(struct macsec_context *ctx, struct mlx5_core_dev *mdev = priv->mdev; struct mlx5_macsec_obj_attrs obj_attrs; union mlx5e_macsec_rule *macsec_rule; - struct macsec_key *key; int err; obj_attrs.next_pn = sa->next_pn; @@ -368,13 +368,9 @@ static int mlx5e_macsec_init_sa(struct macsec_context *ctx, obj_attrs.aso_pdn = macsec->aso.pdn; obj_attrs.epn_state = sa->epn_state; - key = (is_tx) ? &ctx->sa.tx_sa->key : &ctx->sa.rx_sa->key; - if (sa->epn_state.epn_enabled) { - obj_attrs.ssci = (is_tx) ? cpu_to_be32((__force u32)ctx->sa.tx_sa->ssci) : - cpu_to_be32((__force u32)ctx->sa.rx_sa->ssci); - - memcpy(&obj_attrs.salt, &key->salt, sizeof(key->salt)); + obj_attrs.ssci = cpu_to_be32((__force u32)sa->ssci); + memcpy(&obj_attrs.salt, &sa->salt, sizeof(sa->salt)); } obj_attrs.replay_window = ctx->secy->replay_window; @@ -499,10 +495,11 @@ mlx5e_macsec_get_macsec_device_context(const struct mlx5e_macsec *macsec, } static void update_macsec_epn(struct mlx5e_macsec_sa *sa, const struct macsec_key *key, - const pn_t *next_pn_halves) + const pn_t *next_pn_halves, ssci_t ssci) { struct mlx5e_macsec_epn_state *epn_state = &sa->epn_state; + sa->ssci = ssci; sa->salt = key->salt; epn_state->epn_enabled = 1; epn_state->epn_msb = next_pn_halves->upper; @@ -550,7 +547,8 @@ static int mlx5e_macsec_add_txsa(struct macsec_context *ctx) tx_sa->assoc_num = assoc_num; if (secy->xpn) - update_macsec_epn(tx_sa, &ctx_tx_sa->key, &ctx_tx_sa->next_pn_halves); + update_macsec_epn(tx_sa, &ctx_tx_sa->key, &ctx_tx_sa->next_pn_halves, + ctx_tx_sa->ssci); err = mlx5_create_encryption_key(mdev, ctx->sa.key, secy->key_len, MLX5_ACCEL_OBJ_MACSEC_KEY, @@ -945,7 +943,8 @@ static int mlx5e_macsec_add_rxsa(struct macsec_context *ctx) rx_sa->fs_id = rx_sc->sc_xarray_element->fs_id; if (ctx->secy->xpn) - update_macsec_epn(rx_sa, &ctx_rx_sa->key, &ctx_rx_sa->next_pn_halves); + update_macsec_epn(rx_sa, &ctx_rx_sa->key, &ctx_rx_sa->next_pn_halves, + ctx_rx_sa->ssci); err = mlx5_create_encryption_key(mdev, ctx->sa.key, ctx->secy->key_len, MLX5_ACCEL_OBJ_MACSEC_KEY, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 8d36e2de53a9..abcc614b6191 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -1305,7 +1305,7 @@ static int mlx5e_alloc_xdpsq(struct mlx5e_channel *c, sq->channel = c; sq->uar_map = mdev->mlx5e_res.hw_objs.bfreg.map; sq->min_inline_mode = params->tx_min_inline_mode; - sq->hw_mtu = MLX5E_SW2HW_MTU(params, params->sw_mtu); + sq->hw_mtu = MLX5E_SW2HW_MTU(params, params->sw_mtu) - ETH_FCS_LEN; sq->xsk_pool = xsk_pool; sq->stats = sq->xsk_pool ? @@ -4084,6 +4084,9 @@ static netdev_features_t mlx5e_fix_features(struct net_device *netdev, struct mlx5e_vlan_table *vlan; struct mlx5e_params *params; + if (!netif_device_present(netdev)) + return features; + vlan = mlx5e_fs_get_vlan(priv->fs); mutex_lock(&priv->state_lock); params = &priv->channels.params; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 75b9e1528fd2..7d90e5b72854 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -191,7 +191,7 @@ static MLX5E_DECLARE_STATS_GRP_OP_UPDATE_STATS(vport_rep) if (err) { netdev_warn(priv->netdev, "vport %d error %d reading stats\n", rep->vport, err); - return; + goto out; } #define MLX5_GET_CTR(p, x) \ @@ -241,6 +241,7 @@ static MLX5E_DECLARE_STATS_GRP_OP_UPDATE_STATS(vport_rep) rep_stats->tx_vport_rdma_multicast_bytes = MLX5_GET_CTR(out, received_ib_multicast.octets); +out: kvfree(out); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index c8820ab22169..3df455f6b168 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -2419,7 +2419,7 @@ static inline void mlx5i_complete_rx_cqe(struct mlx5e_rq *rq, priv = mlx5i_epriv(netdev); tstamp = &priv->tstamp; - stats = rq->stats; + stats = &priv->channel_stats[rq->ix]->rq; flags_rqpn = be32_to_cpu(cqe->flags_rqpn); g = (flags_rqpn >> 28) & 3; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 9af2aa2922f5..243d5d7750be 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -166,6 +166,7 @@ struct mlx5_fs_chains *mlx5e_nic_chains(struct mlx5e_tc_table *tc) * it's different than the ht->mutex here. */ static struct lock_class_key tc_ht_lock_key; +static struct lock_class_key tc_ht_wq_key; static void mlx5e_put_flow_tunnel_id(struct mlx5e_tc_flow *flow); static void free_flow_post_acts(struct mlx5e_tc_flow *flow); @@ -1301,7 +1302,6 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv, if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) { err = mlx5e_attach_mod_hdr(priv, flow, parse_attr); - mlx5e_mod_hdr_dealloc(&parse_attr->mod_hdr_acts); if (err) return err; } @@ -1359,8 +1359,10 @@ static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv, } mutex_unlock(&tc->t_lock); - if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) + if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) { + mlx5e_mod_hdr_dealloc(&attr->parse_attr->mod_hdr_acts); mlx5e_detach_mod_hdr(priv, flow); + } if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) mlx5_fc_destroy(priv->mdev, attr->counter); @@ -5181,6 +5183,7 @@ int mlx5e_tc_nic_init(struct mlx5e_priv *priv) return err; lockdep_set_class(&tc->ht.mutex, &tc_ht_lock_key); + lockdep_init_map(&tc->ht.run_work.lockdep_map, "tc_ht_wq_key", &tc_ht_wq_key, 0); mapping_id = mlx5_query_nic_system_image_guid(dev); @@ -5287,6 +5290,7 @@ int mlx5e_tc_ht_init(struct rhashtable *tc_ht) return err; lockdep_set_class(&tc_ht->mutex, &tc_ht_lock_key); + lockdep_init_map(&tc_ht->run_work.lockdep_map, "tc_ht_wq_key", &tc_ht_wq_key, 0); return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_lgcy.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_lgcy.c index 60a73990017c..6b4c9ffad95b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_lgcy.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_lgcy.c @@ -67,6 +67,7 @@ static void esw_acl_egress_lgcy_groups_destroy(struct mlx5_vport *vport) int esw_acl_egress_lgcy_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport) { + bool vst_mode_steering = esw_vst_mode_is_steering(esw); struct mlx5_flow_destination drop_ctr_dst = {}; struct mlx5_flow_destination *dst = NULL; struct mlx5_fc *drop_counter = NULL; @@ -77,6 +78,7 @@ int esw_acl_egress_lgcy_setup(struct mlx5_eswitch *esw, */ int table_size = 2; int dest_num = 0; + int actions_flag; int err = 0; if (vport->egress.legacy.drop_counter) { @@ -119,8 +121,11 @@ int esw_acl_egress_lgcy_setup(struct mlx5_eswitch *esw, vport->vport, vport->info.vlan, vport->info.qos); /* Allowed vlan rule */ + actions_flag = MLX5_FLOW_CONTEXT_ACTION_ALLOW; + if (vst_mode_steering) + actions_flag |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP; err = esw_egress_acl_vlan_create(esw, vport, NULL, vport->info.vlan, - MLX5_FLOW_CONTEXT_ACTION_ALLOW); + actions_flag); if (err) goto out; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_lgcy.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_lgcy.c index b1a5199260f6..093ed86a0acd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_lgcy.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_lgcy.c @@ -139,11 +139,14 @@ static void esw_acl_ingress_lgcy_groups_destroy(struct mlx5_vport *vport) int esw_acl_ingress_lgcy_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport) { + bool vst_mode_steering = esw_vst_mode_is_steering(esw); struct mlx5_flow_destination drop_ctr_dst = {}; struct mlx5_flow_destination *dst = NULL; struct mlx5_flow_act flow_act = {}; struct mlx5_flow_spec *spec = NULL; struct mlx5_fc *counter = NULL; + bool vst_check_cvlan = false; + bool vst_push_cvlan = false; /* The ingress acl table contains 4 groups * (2 active rules at the same time - * 1 allow rule from one of the first 3 groups. @@ -203,7 +206,26 @@ int esw_acl_ingress_lgcy_setup(struct mlx5_eswitch *esw, goto out; } - if (vport->info.vlan || vport->info.qos) + if ((vport->info.vlan || vport->info.qos)) { + if (vst_mode_steering) + vst_push_cvlan = true; + else if (!MLX5_CAP_ESW(esw->dev, vport_cvlan_insert_always)) + vst_check_cvlan = true; + } + + if (vst_check_cvlan || vport->info.spoofchk) + spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS; + + /* Create ingress allow rule */ + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW; + if (vst_push_cvlan) { + flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH; + flow_act.vlan[0].prio = vport->info.qos; + flow_act.vlan[0].vid = vport->info.vlan; + flow_act.vlan[0].ethtype = ETH_P_8021Q; + } + + if (vst_check_cvlan) MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.cvlan_tag); @@ -218,9 +240,6 @@ int esw_acl_ingress_lgcy_setup(struct mlx5_eswitch *esw, ether_addr_copy(smac_v, vport->info.mac); } - /* Create ingress allow rule */ - spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS; - flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW; vport->ingress.allow_rule = mlx5_add_flow_rules(vport->ingress.acl, spec, &flow_act, NULL, 0); if (IS_ERR(vport->ingress.allow_rule)) { @@ -232,6 +251,9 @@ int esw_acl_ingress_lgcy_setup(struct mlx5_eswitch *esw, goto out; } + if (!vst_check_cvlan && !vport->info.spoofchk) + goto out; + memset(&flow_act, 0, sizeof(flow_act)); flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP; /* Attach drop flow counter */ @@ -257,7 +279,8 @@ int esw_acl_ingress_lgcy_setup(struct mlx5_eswitch *esw, return 0; out: - esw_acl_ingress_lgcy_cleanup(esw, vport); + if (err) + esw_acl_ingress_lgcy_cleanup(esw, vport); kvfree(spec); return err; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c index 4f8a24d84a86..75015d370922 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c @@ -22,15 +22,13 @@ struct mlx5_esw_rate_group { }; static int esw_qos_tsar_config(struct mlx5_core_dev *dev, u32 *sched_ctx, - u32 parent_ix, u32 tsar_ix, - u32 max_rate, u32 bw_share) + u32 tsar_ix, u32 max_rate, u32 bw_share) { u32 bitmask = 0; if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling)) return -EOPNOTSUPP; - MLX5_SET(scheduling_context, sched_ctx, parent_element_id, parent_ix); MLX5_SET(scheduling_context, sched_ctx, max_average_bw, max_rate); MLX5_SET(scheduling_context, sched_ctx, bw_share, bw_share); bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW; @@ -51,7 +49,7 @@ static int esw_qos_group_config(struct mlx5_eswitch *esw, struct mlx5_esw_rate_g int err; err = esw_qos_tsar_config(dev, sched_ctx, - esw->qos.root_tsar_ix, group->tsar_ix, + group->tsar_ix, max_rate, bw_share); if (err) NL_SET_ERR_MSG_MOD(extack, "E-Switch modify group TSAR element failed"); @@ -67,23 +65,13 @@ static int esw_qos_vport_config(struct mlx5_eswitch *esw, struct netlink_ext_ack *extack) { u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {}; - struct mlx5_esw_rate_group *group = vport->qos.group; struct mlx5_core_dev *dev = esw->dev; - u32 parent_tsar_ix; - void *vport_elem; int err; if (!vport->qos.enabled) return -EIO; - parent_tsar_ix = group ? group->tsar_ix : esw->qos.root_tsar_ix; - MLX5_SET(scheduling_context, sched_ctx, element_type, - SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT); - vport_elem = MLX5_ADDR_OF(scheduling_context, sched_ctx, - element_attributes); - MLX5_SET(vport_element, vport_elem, vport_number, vport->vport); - - err = esw_qos_tsar_config(dev, sched_ctx, parent_tsar_ix, vport->qos.esw_tsar_ix, + err = esw_qos_tsar_config(dev, sched_ctx, vport->qos.esw_tsar_ix, max_rate, bw_share); if (err) { esw_warn(esw->dev, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 527e4bffda8d..9daf55e90367 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -161,10 +161,17 @@ static int modify_esw_vport_cvlan(struct mlx5_core_dev *dev, u16 vport, esw_vport_context.vport_cvlan_strip, 1); if (set_flags & SET_VLAN_INSERT) { - /* insert only if no vlan in packet */ - MLX5_SET(modify_esw_vport_context_in, in, - esw_vport_context.vport_cvlan_insert, 1); - + if (MLX5_CAP_ESW(dev, vport_cvlan_insert_always)) { + /* insert either if vlan exist in packet or not */ + MLX5_SET(modify_esw_vport_context_in, in, + esw_vport_context.vport_cvlan_insert, + MLX5_VPORT_CVLAN_INSERT_ALWAYS); + } else { + /* insert only if no vlan in packet */ + MLX5_SET(modify_esw_vport_context_in, in, + esw_vport_context.vport_cvlan_insert, + MLX5_VPORT_CVLAN_INSERT_WHEN_NO_CVLAN); + } MLX5_SET(modify_esw_vport_context_in, in, esw_vport_context.cvlan_pcp, qos); MLX5_SET(modify_esw_vport_context_in, in, @@ -809,6 +816,7 @@ out_free: static int esw_vport_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport) { + bool vst_mode_steering = esw_vst_mode_is_steering(esw); u16 vport_num = vport->vport; int flags; int err; @@ -839,8 +847,9 @@ static int esw_vport_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport) flags = (vport->info.vlan || vport->info.qos) ? SET_VLAN_STRIP | SET_VLAN_INSERT : 0; - modify_esw_vport_cvlan(esw->dev, vport_num, vport->info.vlan, - vport->info.qos, flags); + if (esw->mode == MLX5_ESWITCH_OFFLOADS || !vst_mode_steering) + modify_esw_vport_cvlan(esw->dev, vport_num, vport->info.vlan, + vport->info.qos, flags); return 0; @@ -1455,6 +1464,7 @@ void mlx5_eswitch_disable(struct mlx5_eswitch *esw) mlx5_lag_disable_change(esw->dev); down_write(&esw->mode_lock); mlx5_eswitch_disable_locked(esw); + esw->mode = MLX5_ESWITCH_LEGACY; up_write(&esw->mode_lock); mlx5_lag_enable_change(esw->dev); } @@ -1848,6 +1858,7 @@ int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw, u16 vport, u16 vlan, u8 qos, u8 set_flags) { struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport); + bool vst_mode_steering = esw_vst_mode_is_steering(esw); int err = 0; if (IS_ERR(evport)) @@ -1855,9 +1866,11 @@ int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw, if (vlan > 4095 || qos > 7) return -EINVAL; - err = modify_esw_vport_cvlan(esw->dev, vport, vlan, qos, set_flags); - if (err) - return err; + if (esw->mode == MLX5_ESWITCH_OFFLOADS || !vst_mode_steering) { + err = modify_esw_vport_cvlan(esw->dev, vport, vlan, qos, set_flags); + if (err) + return err; + } evport->info.vlan = vlan; evport->info.qos = qos; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 5a85a5d32be7..92644fbb5081 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -527,6 +527,12 @@ int mlx5_eswitch_del_vlan_action(struct mlx5_eswitch *esw, int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw, u16 vport, u16 vlan, u8 qos, u8 set_flags); +static inline bool esw_vst_mode_is_steering(struct mlx5_eswitch *esw) +{ + return (MLX5_CAP_ESW_EGRESS_ACL(esw->dev, pop_vlan) && + MLX5_CAP_ESW_INGRESS_ACL(esw->dev, push_vlan)); +} + static inline bool mlx5_eswitch_vlan_actions_supported(struct mlx5_core_dev *dev, u8 vlan_depth) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index e455b215c708..c981fa77f439 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -143,7 +143,7 @@ mlx5_eswitch_set_rule_source_port(struct mlx5_eswitch *esw, if (mlx5_esw_indir_table_decap_vport(attr)) vport = mlx5_esw_indir_table_decap_vport(attr); - if (attr && !attr->chain && esw_attr->int_port) + if (!attr->chain && esw_attr && esw_attr->int_port) metadata = mlx5e_tc_int_port_get_metadata_for_match(esw_attr->int_port); else @@ -4143,8 +4143,6 @@ int mlx5_devlink_port_fn_migratable_set(struct devlink_port *port, bool enable, } hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability); - memcpy(hca_caps, MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability), - MLX5_UN_SZ_BYTES(hca_cap_union)); MLX5_SET(cmd_hca_cap_2, hca_caps, migratable, 1); err = mlx5_vport_set_other_func_cap(esw->dev, hca_caps, vport->vport, @@ -4236,8 +4234,6 @@ int mlx5_devlink_port_fn_roce_set(struct devlink_port *port, bool enable, } hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability); - memcpy(hca_caps, MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability), - MLX5_UN_SZ_BYTES(hca_cap_union)); MLX5_SET(cmd_hca_cap, hca_caps, roce, enable); err = mlx5_vport_set_other_func_cap(esw->dev, hca_caps, vport_num, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c index 86ed87d704f7..879555ba847d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/health.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c @@ -674,6 +674,13 @@ static void mlx5_fw_fatal_reporter_err_work(struct work_struct *work) dev = container_of(priv, struct mlx5_core_dev, priv); devlink = priv_to_devlink(dev); + mutex_lock(&dev->intf_state_mutex); + if (test_bit(MLX5_DROP_NEW_HEALTH_WORK, &health->flags)) { + mlx5_core_err(dev, "health works are not permitted at this stage\n"); + mutex_unlock(&dev->intf_state_mutex); + return; + } + mutex_unlock(&dev->intf_state_mutex); enter_error_state(dev, false); if (IS_ERR_OR_NULL(health->fw_fatal_reporter)) { devl_lock(devlink); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c index c247cca154e9..eff92dc0927c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c @@ -90,9 +90,21 @@ static void mlx5i_get_ringparam(struct net_device *dev, static int mlx5i_set_channels(struct net_device *dev, struct ethtool_channels *ch) { - struct mlx5e_priv *priv = mlx5i_epriv(dev); + struct mlx5i_priv *ipriv = netdev_priv(dev); + struct mlx5e_priv *epriv = mlx5i_epriv(dev); + + /* rtnl lock protects from race between this ethtool op and sub + * interface ndo_init/uninit. + */ + ASSERT_RTNL(); + if (ipriv->num_sub_interfaces > 0) { + mlx5_core_warn(epriv->mdev, + "can't change number of channels for interfaces with sub interfaces (%u)\n", + ipriv->num_sub_interfaces); + return -EINVAL; + } - return mlx5e_ethtool_set_channels(priv, ch); + return mlx5e_ethtool_set_channels(epriv, ch); } static void mlx5i_get_channels(struct net_device *dev, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c index 7c5c500fd215..911cf4d23964 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c @@ -71,6 +71,10 @@ static void mlx5i_build_nic_params(struct mlx5_core_dev *mdev, params->packet_merge.type = MLX5E_PACKET_MERGE_NONE; params->hard_mtu = MLX5_IB_GRH_BYTES + MLX5_IPOIB_HARD_LEN; params->tunneled_offload_en = false; + + /* CQE compression is not supported for IPoIB */ + params->rx_cqe_compress_def = false; + MLX5E_SET_PFLAG(params, MLX5E_PFLAG_RX_CQE_COMPRESS, params->rx_cqe_compress_def); } /* Called directly after IPoIB netdevice was created to initialize SW structs */ @@ -156,6 +160,44 @@ void mlx5i_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats) stats->tx_dropped = sstats->tx_queue_dropped; } +struct net_device *mlx5i_parent_get(struct net_device *netdev) +{ + struct mlx5e_priv *priv = mlx5i_epriv(netdev); + struct mlx5i_priv *ipriv, *parent_ipriv; + struct net_device *parent_dev; + int parent_ifindex; + + ipriv = priv->ppriv; + + parent_ifindex = netdev->netdev_ops->ndo_get_iflink(netdev); + parent_dev = dev_get_by_index(dev_net(netdev), parent_ifindex); + if (!parent_dev) + return NULL; + + parent_ipriv = netdev_priv(parent_dev); + + ASSERT_RTNL(); + parent_ipriv->num_sub_interfaces++; + + ipriv->parent_dev = parent_dev; + + return parent_dev; +} + +void mlx5i_parent_put(struct net_device *netdev) +{ + struct mlx5e_priv *priv = mlx5i_epriv(netdev); + struct mlx5i_priv *ipriv, *parent_ipriv; + + ipriv = priv->ppriv; + parent_ipriv = netdev_priv(ipriv->parent_dev); + + ASSERT_RTNL(); + parent_ipriv->num_sub_interfaces--; + + dev_put(ipriv->parent_dev); +} + int mlx5i_init_underlay_qp(struct mlx5e_priv *priv) { struct mlx5_core_dev *mdev = priv->mdev; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h index 99d46fda9f82..f3f2af972020 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h @@ -54,9 +54,11 @@ struct mlx5i_priv { struct rdma_netdev rn; /* keep this first */ u32 qpn; bool sub_interface; + u32 num_sub_interfaces; u32 qkey; u16 pkey_index; struct mlx5i_pkey_qpn_ht *qpn_htbl; + struct net_device *parent_dev; char *mlx5e_priv[]; }; @@ -117,5 +119,9 @@ void mlx5i_sq_xmit(struct mlx5e_txqsq *sq, struct sk_buff *skb, struct mlx5_av *av, u32 dqpn, u32 dqkey, bool xmit_more); void mlx5i_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats); +/* Reference management for child to parent interfaces. */ +struct net_device *mlx5i_parent_get(struct net_device *netdev); +void mlx5i_parent_put(struct net_device *netdev); + #endif /* CONFIG_MLX5_CORE_IPOIB */ #endif /* __MLX5E_IPOB_H__ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c index 4d9c9e49645c..03e681297937 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c @@ -158,21 +158,28 @@ static int mlx5i_pkey_dev_init(struct net_device *dev) struct mlx5e_priv *priv = mlx5i_epriv(dev); struct mlx5i_priv *ipriv, *parent_ipriv; struct net_device *parent_dev; - int parent_ifindex; ipriv = priv->ppriv; - /* Get QPN to netdevice hash table from parent */ - parent_ifindex = dev->netdev_ops->ndo_get_iflink(dev); - parent_dev = dev_get_by_index(dev_net(dev), parent_ifindex); + /* Link to parent */ + parent_dev = mlx5i_parent_get(dev); if (!parent_dev) { mlx5_core_warn(priv->mdev, "failed to get parent device\n"); return -EINVAL; } + if (dev->num_rx_queues < parent_dev->real_num_rx_queues) { + mlx5_core_warn(priv->mdev, + "failed to create child device with rx queues [%d] less than parent's [%d]\n", + dev->num_rx_queues, + parent_dev->real_num_rx_queues); + mlx5i_parent_put(dev); + return -EINVAL; + } + + /* Get QPN to netdevice hash table from parent */ parent_ipriv = netdev_priv(parent_dev); ipriv->qpn_htbl = parent_ipriv->qpn_htbl; - dev_put(parent_dev); return mlx5i_dev_init(dev); } @@ -184,6 +191,7 @@ static int mlx5i_pkey_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) static void mlx5i_pkey_dev_cleanup(struct net_device *netdev) { + mlx5i_parent_put(netdev); return mlx5i_dev_cleanup(netdev); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c index 32c3e0a649a7..ad32b80e8501 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c @@ -228,6 +228,7 @@ static void mlx5_ldev_free(struct kref *ref) if (ldev->nb.notifier_call) unregister_netdevice_notifier_net(&init_net, &ldev->nb); mlx5_lag_mp_cleanup(ldev); + cancel_delayed_work_sync(&ldev->bond_work); destroy_workqueue(ldev->wq); mlx5_lag_mpesw_cleanup(ldev); mutex_destroy(&ldev->lock); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c index 69cfe60c558a..69318b143268 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c @@ -681,7 +681,7 @@ static int mlx5_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin, static const struct ptp_clock_info mlx5_ptp_clock_info = { .owner = THIS_MODULE, .name = "mlx5_ptp", - .max_adj = 100000000, + .max_adj = 50000000, .n_alarm = 0, .n_ext_ts = 0, .n_per_out = 0, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index 7f5db13e3550..3d5f2a4b1fed 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -613,7 +613,7 @@ static int handle_hca_cap(struct mlx5_core_dev *dev, void *set_ctx) MLX5_SET(cmd_hca_cap, set_hca_cap, num_total_dynamic_vf_msix, MLX5_CAP_GEN_MAX(dev, num_total_dynamic_vf_msix)); - if (MLX5_CAP_GEN(dev, roce_rw_supported)) + if (MLX5_CAP_GEN(dev, roce_rw_supported) && MLX5_CAP_GEN_MAX(dev, roce)) MLX5_SET(cmd_hca_cap, set_hca_cap, roce, mlx5_is_roce_on(dev)); @@ -1050,6 +1050,8 @@ err_rl_cleanup: err_tables_cleanup: mlx5_geneve_destroy(dev->geneve); mlx5_vxlan_destroy(dev->vxlan); + mlx5_cleanup_clock(dev); + mlx5_cleanup_reserved_gids(dev); mlx5_cq_debugfs_cleanup(dev); mlx5_fw_reset_cleanup(dev); err_events_cleanup: @@ -2096,7 +2098,7 @@ static void mlx5_core_verify_params(void) } } -static int __init init(void) +static int __init mlx5_init(void) { int err; @@ -2131,7 +2133,7 @@ err_debug: return err; } -static void __exit cleanup(void) +static void __exit mlx5_cleanup(void) { mlx5e_cleanup(); mlx5_sf_driver_unregister(); @@ -2139,5 +2141,5 @@ static void __exit cleanup(void) mlx5_unregister_debugfs(); } -module_init(init); -module_exit(cleanup); +module_init(mlx5_init); +module_exit(mlx5_cleanup); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/qos.c b/drivers/net/ethernet/mellanox/mlx5/core/qos.c index 0777be24a307..8bce730b5c5b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/qos.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/qos.c @@ -62,13 +62,12 @@ int mlx5_qos_create_root_node(struct mlx5_core_dev *mdev, u32 *id) return mlx5_qos_create_inner_node(mdev, MLX5_QOS_DEFAULT_DWRR_UID, 0, 0, id); } -int mlx5_qos_update_node(struct mlx5_core_dev *mdev, u32 parent_id, +int mlx5_qos_update_node(struct mlx5_core_dev *mdev, u32 bw_share, u32 max_avg_bw, u32 id) { u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0}; u32 bitmask = 0; - MLX5_SET(scheduling_context, sched_ctx, parent_element_id, parent_id); MLX5_SET(scheduling_context, sched_ctx, bw_share, bw_share); MLX5_SET(scheduling_context, sched_ctx, max_average_bw, max_avg_bw); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/qos.h b/drivers/net/ethernet/mellanox/mlx5/core/qos.h index 125e4e47e6f7..624ce822b7f5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/qos.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/qos.h @@ -23,7 +23,7 @@ int mlx5_qos_create_leaf_node(struct mlx5_core_dev *mdev, u32 parent_id, int mlx5_qos_create_inner_node(struct mlx5_core_dev *mdev, u32 parent_id, u32 bw_share, u32 max_avg_bw, u32 *id); int mlx5_qos_create_root_node(struct mlx5_core_dev *mdev, u32 *id); -int mlx5_qos_update_node(struct mlx5_core_dev *mdev, u32 parent_id, u32 bw_share, +int mlx5_qos_update_node(struct mlx5_core_dev *mdev, u32 bw_share, u32 max_avg_bw, u32 id); int mlx5_qos_destroy_node(struct mlx5_core_dev *mdev, u32 id); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c index 74cbe53ee9db..b851141e03de 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c @@ -3,7 +3,12 @@ #include "dr_types.h" +#if defined(CONFIG_FRAME_WARN) && (CONFIG_FRAME_WARN < 2048) +/* don't try to optimize STE allocation if the stack is too constaraining */ +#define DR_RULE_MAX_STES_OPTIMIZED 0 +#else #define DR_RULE_MAX_STES_OPTIMIZED 5 +#endif #define DR_RULE_MAX_STE_CHAIN_OPTIMIZED (DR_RULE_MAX_STES_OPTIMIZED + DR_ACTION_MAX_STES) static int dr_rule_append_to_miss_list(struct mlx5dr_domain *dmn, @@ -1218,10 +1223,7 @@ dr_rule_create_rule_nic(struct mlx5dr_rule *rule, mlx5dr_domain_nic_unlock(nic_dmn); - if (unlikely(!hw_ste_arr_is_opt)) - kfree(hw_ste_arr); - - return 0; + goto out; free_rule: dr_rule_clean_rule_members(rule, nic_rule); @@ -1238,6 +1240,7 @@ remove_from_nic_tbl: free_hw_ste: mlx5dr_domain_nic_unlock(nic_dmn); +out: if (unlikely(!hw_ste_arr_is_opt)) kfree(hw_ste_arr); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index c22c3ac4e2a1..09e32778b012 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -2951,7 +2951,7 @@ struct mlxsw_sp_nexthop_group_info { gateway:1, /* routes using the group use a gateway */ is_resilient:1; struct list_head list; /* member in nh_res_grp_list */ - struct mlxsw_sp_nexthop nexthops[0]; + struct mlxsw_sp_nexthop nexthops[]; #define nh_rif nexthops[0].rif }; diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c index cadde20505ba..580c91d24a52 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c @@ -1043,11 +1043,6 @@ static int lan966x_probe(struct platform_device *pdev) lan966x->base_mac[5] &= 0xf0; } - ports = device_get_named_child_node(&pdev->dev, "ethernet-ports"); - if (!ports) - return dev_err_probe(&pdev->dev, -ENODEV, - "no ethernet-ports child found\n"); - err = lan966x_create_targets(pdev, lan966x); if (err) return dev_err_probe(&pdev->dev, err, @@ -1125,6 +1120,11 @@ static int lan966x_probe(struct platform_device *pdev) } } + ports = device_get_named_child_node(&pdev->dev, "ethernet-ports"); + if (!ports) + return dev_err_probe(&pdev->dev, -ENODEV, + "no ethernet-ports child found\n"); + /* init switch */ lan966x_init(lan966x); lan966x_stats_init(lan966x); @@ -1162,6 +1162,8 @@ static int lan966x_probe(struct platform_device *pdev) goto cleanup_ports; } + fwnode_handle_put(ports); + lan966x_mdb_init(lan966x); err = lan966x_fdb_init(lan966x); if (err) @@ -1191,6 +1193,7 @@ cleanup_fdb: lan966x_fdb_deinit(lan966x); cleanup_ports: + fwnode_handle_put(ports); fwnode_handle_put(portnp); lan966x_cleanup_ports(lan966x); diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_port.c b/drivers/net/ethernet/microchip/lan966x/lan966x_port.c index 1a61c6cdb077..0050fcb988b7 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_port.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_port.c @@ -381,7 +381,7 @@ int lan966x_port_pcs_set(struct lan966x_port *port, } /* Take PCS out of reset */ - lan_rmw(DEV_CLOCK_CFG_LINK_SPEED_SET(2) | + lan_rmw(DEV_CLOCK_CFG_LINK_SPEED_SET(LAN966X_SPEED_1000) | DEV_CLOCK_CFG_PCS_RX_RST_SET(0) | DEV_CLOCK_CFG_PCS_TX_RST_SET(0), DEV_CLOCK_CFG_LINK_SPEED | diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c b/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c index f9ebfaafbebc..a8348437dd87 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c @@ -1073,6 +1073,9 @@ void lan966x_ptp_deinit(struct lan966x *lan966x) struct lan966x_port *port; int i; + if (!lan966x->ptp) + return; + for (i = 0; i < lan966x->num_phys_ports; i++) { port = lan966x->ports[i]; if (!port) diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_impl.c b/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_impl.c index d8dc9fbb81e1..a54c0426a35f 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_impl.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_impl.c @@ -95,10 +95,7 @@ lan966x_vcap_is2_get_port_keysets(struct net_device *dev, int lookup, bool found = false; u32 val; - /* Check if the port keyset selection is enabled */ val = lan_rd(lan966x, ANA_VCAP_S2_CFG(port->chip_port)); - if (!ANA_VCAP_S2_CFG_ENA_GET(val)) - return -ENOENT; /* Collect all keysets for the port in a list */ if (l3_proto == ETH_P_ALL) diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c index d25f4f09faa0..3c5d4fe99373 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c @@ -834,7 +834,7 @@ static int mchp_sparx5_probe(struct platform_device *pdev) if (err) goto cleanup_config; - if (!of_get_mac_address(np, sparx5->base_mac)) { + if (of_get_mac_address(np, sparx5->base_mac)) { dev_info(sparx5->dev, "MAC addr was not set, use random MAC\n"); eth_random_addr(sparx5->base_mac); sparx5->base_mac[5] = 0; diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c index e708c2d04983..b144f2237748 100644 --- a/drivers/net/ethernet/microsoft/mana/gdma_main.c +++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c @@ -1259,13 +1259,20 @@ static int mana_gd_setup_irqs(struct pci_dev *pdev) gic->handler = NULL; gic->arg = NULL; + if (!i) + snprintf(gic->name, MANA_IRQ_NAME_SZ, "mana_hwc@pci:%s", + pci_name(pdev)); + else + snprintf(gic->name, MANA_IRQ_NAME_SZ, "mana_q%d@pci:%s", + i - 1, pci_name(pdev)); + irq = pci_irq_vector(pdev, i); if (irq < 0) { err = irq; goto free_mask; } - err = request_irq(irq, mana_gd_intr, 0, "mana_intr", gic); + err = request_irq(irq, mana_gd_intr, 0, gic->name, gic); if (err) goto free_mask; irq_set_affinity_and_hint(irq, req_mask); diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h index da33f09facb9..432d79d691c2 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h @@ -617,6 +617,9 @@ struct nfp_net_dp { * @vnic_no_name: For non-port PF vNIC make ndo_get_phys_port_name return * -EOPNOTSUPP to keep backwards compatibility (set by app) * @port: Pointer to nfp_port structure if vNIC is a port + * @mc_lock: Protect mc_addrs list + * @mc_addrs: List of mc addrs to add/del to HW + * @mc_work: Work to update mc addrs * @app_priv: APP private data for this vNIC */ struct nfp_net { @@ -718,6 +721,10 @@ struct nfp_net { struct nfp_port *port; + spinlock_t mc_lock; + struct list_head mc_addrs; + struct work_struct mc_work; + void *app_priv; }; diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 09053373288f..18fc9971f1c8 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1334,9 +1334,14 @@ err_unlock: return err; } -static int nfp_net_mc_cfg(struct net_device *netdev, const unsigned char *addr, const u32 cmd) +struct nfp_mc_addr_entry { + u8 addr[ETH_ALEN]; + u32 cmd; + struct list_head list; +}; + +static int nfp_net_mc_cfg(struct nfp_net *nn, const unsigned char *addr, const u32 cmd) { - struct nfp_net *nn = netdev_priv(netdev); int ret; ret = nfp_net_mbox_lock(nn, NFP_NET_CFG_MULTICAST_SZ); @@ -1351,6 +1356,25 @@ static int nfp_net_mc_cfg(struct net_device *netdev, const unsigned char *addr, return nfp_net_mbox_reconfig_and_unlock(nn, cmd); } +static int nfp_net_mc_prep(struct nfp_net *nn, const unsigned char *addr, const u32 cmd) +{ + struct nfp_mc_addr_entry *entry; + + entry = kmalloc(sizeof(*entry), GFP_ATOMIC); + if (!entry) + return -ENOMEM; + + ether_addr_copy(entry->addr, addr); + entry->cmd = cmd; + spin_lock_bh(&nn->mc_lock); + list_add_tail(&entry->list, &nn->mc_addrs); + spin_unlock_bh(&nn->mc_lock); + + schedule_work(&nn->mc_work); + + return 0; +} + static int nfp_net_mc_sync(struct net_device *netdev, const unsigned char *addr) { struct nfp_net *nn = netdev_priv(netdev); @@ -1361,12 +1385,35 @@ static int nfp_net_mc_sync(struct net_device *netdev, const unsigned char *addr) return -EINVAL; } - return nfp_net_mc_cfg(netdev, addr, NFP_NET_CFG_MBOX_CMD_MULTICAST_ADD); + return nfp_net_mc_prep(nn, addr, NFP_NET_CFG_MBOX_CMD_MULTICAST_ADD); } static int nfp_net_mc_unsync(struct net_device *netdev, const unsigned char *addr) { - return nfp_net_mc_cfg(netdev, addr, NFP_NET_CFG_MBOX_CMD_MULTICAST_DEL); + struct nfp_net *nn = netdev_priv(netdev); + + return nfp_net_mc_prep(nn, addr, NFP_NET_CFG_MBOX_CMD_MULTICAST_DEL); +} + +static void nfp_net_mc_addr_config(struct work_struct *work) +{ + struct nfp_net *nn = container_of(work, struct nfp_net, mc_work); + struct nfp_mc_addr_entry *entry, *tmp; + struct list_head tmp_list; + + INIT_LIST_HEAD(&tmp_list); + + spin_lock_bh(&nn->mc_lock); + list_splice_init(&nn->mc_addrs, &tmp_list); + spin_unlock_bh(&nn->mc_lock); + + list_for_each_entry_safe(entry, tmp, &tmp_list, list) { + if (nfp_net_mc_cfg(nn, entry->addr, entry->cmd)) + nn_err(nn, "Config mc address to HW failed.\n"); + + list_del(&entry->list); + kfree(entry); + } } static void nfp_net_set_rx_mode(struct net_device *netdev) @@ -2633,6 +2680,11 @@ int nfp_net_init(struct nfp_net *nn) if (!nn->dp.netdev) return 0; + + spin_lock_init(&nn->mc_lock); + INIT_LIST_HEAD(&nn->mc_addrs); + INIT_WORK(&nn->mc_work, nfp_net_mc_addr_config); + return register_netdev(nn->dp.netdev); err_clean_mbox: @@ -2652,5 +2704,6 @@ void nfp_net_clean(struct nfp_net *nn) unregister_netdev(nn->dp.netdev); nfp_net_ipsec_clean(nn); nfp_ccm_mbox_clean(nn); + flush_work(&nn->mc_work); nfp_net_reconfig_wait_posted(nn); } diff --git a/drivers/net/ethernet/qlogic/qed/qed_debug.c b/drivers/net/ethernet/qlogic/qed/qed_debug.c index 86ecb080b153..cdcead614e9f 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_debug.c +++ b/drivers/net/ethernet/qlogic/qed/qed_debug.c @@ -1832,7 +1832,8 @@ static enum dbg_status qed_find_nvram_image(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, u32 image_type, u32 *nvram_offset_bytes, - u32 *nvram_size_bytes) + u32 *nvram_size_bytes, + bool b_can_sleep) { u32 ret_mcp_resp, ret_mcp_param, ret_txn_size; struct mcp_file_att file_att; @@ -1846,7 +1847,8 @@ static enum dbg_status qed_find_nvram_image(struct qed_hwfn *p_hwfn, &ret_mcp_resp, &ret_mcp_param, &ret_txn_size, - (u32 *)&file_att, false); + (u32 *)&file_att, + b_can_sleep); /* Check response */ if (nvm_result || (ret_mcp_resp & FW_MSG_CODE_MASK) != @@ -1873,7 +1875,9 @@ static enum dbg_status qed_find_nvram_image(struct qed_hwfn *p_hwfn, static enum dbg_status qed_nvram_read(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, u32 nvram_offset_bytes, - u32 nvram_size_bytes, u32 *ret_buf) + u32 nvram_size_bytes, + u32 *ret_buf, + bool b_can_sleep) { u32 ret_mcp_resp, ret_mcp_param, ret_read_size, bytes_to_copy; s32 bytes_left = nvram_size_bytes; @@ -1899,7 +1903,7 @@ static enum dbg_status qed_nvram_read(struct qed_hwfn *p_hwfn, &ret_mcp_resp, &ret_mcp_param, &ret_read_size, (u32 *)((u8 *)ret_buf + read_offset), - false)) + b_can_sleep)) return DBG_STATUS_NVRAM_READ_FAILED; /* Check response */ @@ -3380,7 +3384,8 @@ static u32 qed_grc_dump_mcp_hw_dump(struct qed_hwfn *p_hwfn, p_ptt, NVM_TYPE_HW_DUMP_OUT, &hw_dump_offset_bytes, - &hw_dump_size_bytes); + &hw_dump_size_bytes, + false); if (status != DBG_STATUS_OK) return 0; @@ -3397,7 +3402,9 @@ static u32 qed_grc_dump_mcp_hw_dump(struct qed_hwfn *p_hwfn, status = qed_nvram_read(p_hwfn, p_ptt, hw_dump_offset_bytes, - hw_dump_size_bytes, dump_buf + offset); + hw_dump_size_bytes, + dump_buf + offset, + false); if (status != DBG_STATUS_OK) { DP_NOTICE(p_hwfn, "Failed to read MCP HW Dump image from NVRAM\n"); @@ -4123,7 +4130,9 @@ static enum dbg_status qed_mcp_trace_get_meta_info(struct qed_hwfn *p_hwfn, return qed_find_nvram_image(p_hwfn, p_ptt, nvram_image_type, - trace_meta_offset, trace_meta_size); + trace_meta_offset, + trace_meta_size, + true); } /* Reads the MCP Trace meta data from NVRAM into the specified buffer */ @@ -4139,7 +4148,10 @@ static enum dbg_status qed_mcp_trace_read_meta(struct qed_hwfn *p_hwfn, /* Read meta data from NVRAM */ status = qed_nvram_read(p_hwfn, p_ptt, - nvram_offset_in_bytes, size_in_bytes, buf); + nvram_offset_in_bytes, + size_in_bytes, + buf, + true); if (status != DBG_STATUS_OK) return status; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c index dbb800769cb6..c95d56e56c59 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c @@ -2505,7 +2505,13 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter) goto disable_mbx_intr; qlcnic_83xx_clear_function_resources(adapter); - qlcnic_dcb_enable(adapter->dcb); + + err = qlcnic_dcb_enable(adapter->dcb); + if (err) { + qlcnic_dcb_free(adapter->dcb); + goto disable_mbx_intr; + } + qlcnic_83xx_initialize_nic(adapter, 1); qlcnic_dcb_get_info(adapter->dcb); diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h index 7519773eaca6..22afa2be85fd 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h @@ -41,11 +41,6 @@ struct qlcnic_dcb { unsigned long state; }; -static inline void qlcnic_clear_dcb_ops(struct qlcnic_dcb *dcb) -{ - kfree(dcb); -} - static inline int qlcnic_dcb_get_hw_capability(struct qlcnic_dcb *dcb) { if (dcb && dcb->ops->get_hw_capability) @@ -112,9 +107,8 @@ static inline void qlcnic_dcb_init_dcbnl_ops(struct qlcnic_dcb *dcb) dcb->ops->init_dcbnl_ops(dcb); } -static inline void qlcnic_dcb_enable(struct qlcnic_dcb *dcb) +static inline int qlcnic_dcb_enable(struct qlcnic_dcb *dcb) { - if (dcb && qlcnic_dcb_attach(dcb)) - qlcnic_clear_dcb_ops(dcb); + return dcb ? qlcnic_dcb_attach(dcb) : 0; } #endif diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 28476b982bab..44dac3c0908e 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -2599,7 +2599,13 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) "Device does not support MSI interrupts\n"); if (qlcnic_82xx_check(adapter)) { - qlcnic_dcb_enable(adapter->dcb); + err = qlcnic_dcb_enable(adapter->dcb); + if (err) { + qlcnic_dcb_free(adapter->dcb); + dev_err(&pdev->dev, "Failed to enable DCB\n"); + goto err_out_free_hw; + } + qlcnic_dcb_get_info(adapter->dcb); err = qlcnic_setup_intr(adapter); diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index a9dcc98b6af1..dadd61bccfe7 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -1996,10 +1996,7 @@ static enum mac_version rtl8169_get_mac_version(u16 xid, bool gmii) /* 8168F family. */ { 0x7c8, 0x488, RTL_GIGA_MAC_VER_38 }, - /* It seems this chip version never made it to - * the wild. Let's disable detection. - * { 0x7cf, 0x481, RTL_GIGA_MAC_VER_36 }, - */ + { 0x7cf, 0x481, RTL_GIGA_MAC_VER_36 }, { 0x7cf, 0x480, RTL_GIGA_MAC_VER_35 }, /* 8168E family. */ @@ -2210,28 +2207,6 @@ static int rtl_set_mac_address(struct net_device *dev, void *p) return 0; } -static void rtl_wol_enable_rx(struct rtl8169_private *tp) -{ - if (tp->mac_version >= RTL_GIGA_MAC_VER_25) - RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) | - AcceptBroadcast | AcceptMulticast | AcceptMyPhys); -} - -static void rtl_prepare_power_down(struct rtl8169_private *tp) -{ - if (tp->dash_type != RTL_DASH_NONE) - return; - - if (tp->mac_version == RTL_GIGA_MAC_VER_32 || - tp->mac_version == RTL_GIGA_MAC_VER_33) - rtl_ephy_write(tp, 0x19, 0xff64); - - if (device_may_wakeup(tp_to_dev(tp))) { - phy_speed_down(tp->phydev, false); - rtl_wol_enable_rx(tp); - } -} - static void rtl_init_rxcfg(struct rtl8169_private *tp) { switch (tp->mac_version) { @@ -2455,6 +2430,31 @@ static void rtl_enable_rxdvgate(struct rtl8169_private *tp) rtl_wait_txrx_fifo_empty(tp); } +static void rtl_wol_enable_rx(struct rtl8169_private *tp) +{ + if (tp->mac_version >= RTL_GIGA_MAC_VER_25) + RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) | + AcceptBroadcast | AcceptMulticast | AcceptMyPhys); + + if (tp->mac_version >= RTL_GIGA_MAC_VER_40) + rtl_disable_rxdvgate(tp); +} + +static void rtl_prepare_power_down(struct rtl8169_private *tp) +{ + if (tp->dash_type != RTL_DASH_NONE) + return; + + if (tp->mac_version == RTL_GIGA_MAC_VER_32 || + tp->mac_version == RTL_GIGA_MAC_VER_33) + rtl_ephy_write(tp, 0x19, 0xff64); + + if (device_may_wakeup(tp_to_dev(tp))) { + phy_speed_down(tp->phydev, false); + rtl_wol_enable_rx(tp); + } +} + static void rtl_set_tx_config_registers(struct rtl8169_private *tp) { u32 val = TX_DMA_BURST << TxDMAShift | @@ -3872,7 +3872,7 @@ static void rtl8169_tx_clear(struct rtl8169_private *tp) netdev_reset_queue(tp->dev); } -static void rtl8169_cleanup(struct rtl8169_private *tp, bool going_down) +static void rtl8169_cleanup(struct rtl8169_private *tp) { napi_disable(&tp->napi); @@ -3884,9 +3884,6 @@ static void rtl8169_cleanup(struct rtl8169_private *tp, bool going_down) rtl_rx_close(tp); - if (going_down && tp->dev->wol_enabled) - goto no_reset; - switch (tp->mac_version) { case RTL_GIGA_MAC_VER_28: case RTL_GIGA_MAC_VER_31: @@ -3907,7 +3904,7 @@ static void rtl8169_cleanup(struct rtl8169_private *tp, bool going_down) } rtl_hw_reset(tp); -no_reset: + rtl8169_tx_clear(tp); rtl8169_init_ring_indexes(tp); } @@ -3918,7 +3915,7 @@ static void rtl_reset_work(struct rtl8169_private *tp) netif_stop_queue(tp->dev); - rtl8169_cleanup(tp, false); + rtl8169_cleanup(tp); for (i = 0; i < NUM_RX_DESC; i++) rtl8169_mark_to_asic(tp->RxDescArray + i); @@ -4605,7 +4602,7 @@ static void rtl8169_down(struct rtl8169_private *tp) pci_clear_master(tp->pci_dev); rtl_pci_commit(tp); - rtl8169_cleanup(tp, true); + rtl8169_cleanup(tp); rtl_disable_exit_l1(tp); rtl_prepare_power_down(tp); } diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index b4e0fc7f65bd..0f54849a3823 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -1101,14 +1101,14 @@ static void ravb_error_interrupt(struct net_device *ndev) ravb_write(ndev, ~(EIS_QFS | EIS_RESERVED), EIS); if (eis & EIS_QFS) { ris2 = ravb_read(ndev, RIS2); - ravb_write(ndev, ~(RIS2_QFF0 | RIS2_RFFF | RIS2_RESERVED), + ravb_write(ndev, ~(RIS2_QFF0 | RIS2_QFF1 | RIS2_RFFF | RIS2_RESERVED), RIS2); /* Receive Descriptor Empty int */ if (ris2 & RIS2_QFF0) priv->stats[RAVB_BE].rx_over_errors++; - /* Receive Descriptor Empty int */ + /* Receive Descriptor Empty int */ if (ris2 & RIS2_QFF1) priv->stats[RAVB_NC].rx_over_errors++; @@ -2973,6 +2973,9 @@ static int __maybe_unused ravb_suspend(struct device *dev) else ret = ravb_close(ndev); + if (priv->info->ccc_gac) + ravb_ptp_stop(ndev); + return ret; } @@ -3011,6 +3014,9 @@ static int __maybe_unused ravb_resume(struct device *dev) /* Restore descriptor base address table */ ravb_write(ndev, priv->desc_bat_dma, DBAT); + if (priv->info->ccc_gac) + ravb_ptp_init(ndev, priv->pdev); + if (netif_running(ndev)) { if (priv->wol_enabled) { ret = ravb_wol_restore(ndev); diff --git a/drivers/net/ethernet/renesas/rswitch.c b/drivers/net/ethernet/renesas/rswitch.c index e42ceaa0099f..2370c7797a0a 100644 --- a/drivers/net/ethernet/renesas/rswitch.c +++ b/drivers/net/ethernet/renesas/rswitch.c @@ -1074,8 +1074,11 @@ static struct device_node *rswitch_get_port_node(struct rswitch_device *rdev) port = NULL; goto out; } - if (index == rdev->etha->index) + if (index == rdev->etha->index) { + if (!of_device_is_available(port)) + port = NULL; break; + } } out: @@ -1106,7 +1109,7 @@ static int rswitch_etha_get_params(struct rswitch_device *rdev) port = rswitch_get_port_node(rdev); if (!port) - return -ENODEV; + return 0; /* ignored */ err = of_get_phy_mode(port, &rdev->etha->phy_interface); of_node_put(port); @@ -1324,13 +1327,13 @@ static int rswitch_ether_port_init_all(struct rswitch_private *priv) { int i, err; - for (i = 0; i < RSWITCH_NUM_PORTS; i++) { + rswitch_for_each_enabled_port(priv, i) { err = rswitch_ether_port_init_one(priv->rdev[i]); if (err) goto err_init_one; } - for (i = 0; i < RSWITCH_NUM_PORTS; i++) { + rswitch_for_each_enabled_port(priv, i) { err = rswitch_serdes_init(priv->rdev[i]); if (err) goto err_serdes; @@ -1339,12 +1342,12 @@ static int rswitch_ether_port_init_all(struct rswitch_private *priv) return 0; err_serdes: - for (i--; i >= 0; i--) + rswitch_for_each_enabled_port_continue_reverse(priv, i) rswitch_serdes_deinit(priv->rdev[i]); i = RSWITCH_NUM_PORTS; err_init_one: - for (i--; i >= 0; i--) + rswitch_for_each_enabled_port_continue_reverse(priv, i) rswitch_ether_port_deinit_one(priv->rdev[i]); return err; @@ -1578,6 +1581,7 @@ static int rswitch_device_alloc(struct rswitch_private *priv, int index) { struct platform_device *pdev = priv->pdev; struct rswitch_device *rdev; + struct device_node *port; struct net_device *ndev; int err; @@ -1606,7 +1610,10 @@ static int rswitch_device_alloc(struct rswitch_private *priv, int index) netif_napi_add(ndev, &rdev->napi, rswitch_poll); - err = of_get_ethdev_address(pdev->dev.of_node, ndev); + port = rswitch_get_port_node(rdev); + rdev->disabled = !port; + err = of_get_ethdev_address(port, ndev); + of_node_put(port); if (err) { if (is_valid_ether_addr(rdev->etha->mac_addr)) eth_hw_addr_set(ndev, rdev->etha->mac_addr); @@ -1704,16 +1711,16 @@ static int rswitch_init(struct rswitch_private *priv) if (err) goto err_ether_port_init_all; - for (i = 0; i < RSWITCH_NUM_PORTS; i++) { + rswitch_for_each_enabled_port(priv, i) { err = register_netdev(priv->rdev[i]->ndev); if (err) { - for (i--; i >= 0; i--) + rswitch_for_each_enabled_port_continue_reverse(priv, i) unregister_netdev(priv->rdev[i]->ndev); goto err_register_netdev; } } - for (i = 0; i < RSWITCH_NUM_PORTS; i++) + rswitch_for_each_enabled_port(priv, i) netdev_info(priv->rdev[i]->ndev, "MAC address %pM\n", priv->rdev[i]->ndev->dev_addr); @@ -1786,6 +1793,11 @@ static int renesas_eth_sw_probe(struct platform_device *pdev) pm_runtime_get_sync(&pdev->dev); ret = rswitch_init(priv); + if (ret < 0) { + pm_runtime_put(&pdev->dev); + pm_runtime_disable(&pdev->dev); + return ret; + } device_set_wakeup_capable(&pdev->dev, 1); diff --git a/drivers/net/ethernet/renesas/rswitch.h b/drivers/net/ethernet/renesas/rswitch.h index edbdd1b98d3d..49efb0f31c77 100644 --- a/drivers/net/ethernet/renesas/rswitch.h +++ b/drivers/net/ethernet/renesas/rswitch.h @@ -13,6 +13,17 @@ #define RSWITCH_MAX_NUM_QUEUES 128 #define RSWITCH_NUM_PORTS 3 +#define rswitch_for_each_enabled_port(priv, i) \ + for (i = 0; i < RSWITCH_NUM_PORTS; i++) \ + if (priv->rdev[i]->disabled) \ + continue; \ + else + +#define rswitch_for_each_enabled_port_continue_reverse(priv, i) \ + for (i--; i >= 0; i--) \ + if (priv->rdev[i]->disabled) \ + continue; \ + else #define TX_RING_SIZE 1024 #define RX_RING_SIZE 1024 @@ -938,6 +949,7 @@ struct rswitch_device { struct rswitch_gwca_queue *tx_queue; struct rswitch_gwca_queue *rx_queue; u8 ts_tag; + bool disabled; int port; struct rswitch_etha *etha; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c index d42e1afb6521..2f7d8e4561d9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c @@ -90,7 +90,6 @@ struct mediatek_dwmac_plat_data { struct mediatek_dwmac_variant { int (*dwmac_set_phy_interface)(struct mediatek_dwmac_plat_data *plat); int (*dwmac_set_delay)(struct mediatek_dwmac_plat_data *plat); - void (*dwmac_fix_mac_speed)(void *priv, unsigned int speed); /* clock ids to be requested */ const char * const *clk_list; @@ -443,32 +442,9 @@ static int mt8195_set_delay(struct mediatek_dwmac_plat_data *plat) return 0; } -static void mt8195_fix_mac_speed(void *priv, unsigned int speed) -{ - struct mediatek_dwmac_plat_data *priv_plat = priv; - - if ((phy_interface_mode_is_rgmii(priv_plat->phy_mode))) { - /* prefer 2ns fixed delay which is controlled by TXC_PHASE_CTRL, - * when link speed is 1Gbps with RGMII interface, - * Fall back to delay macro circuit for 10/100Mbps link speed. - */ - if (speed == SPEED_1000) - regmap_update_bits(priv_plat->peri_regmap, - MT8195_PERI_ETH_CTRL0, - MT8195_RGMII_TXC_PHASE_CTRL | - MT8195_DLY_GTXC_ENABLE | - MT8195_DLY_GTXC_INV | - MT8195_DLY_GTXC_STAGES, - MT8195_RGMII_TXC_PHASE_CTRL); - else - mt8195_set_delay(priv_plat); - } -} - static const struct mediatek_dwmac_variant mt8195_gmac_variant = { .dwmac_set_phy_interface = mt8195_set_interface, .dwmac_set_delay = mt8195_set_delay, - .dwmac_fix_mac_speed = mt8195_fix_mac_speed, .clk_list = mt8195_dwmac_clk_l, .num_clks = ARRAY_SIZE(mt8195_dwmac_clk_l), .dma_bit_mask = 35, @@ -619,8 +595,6 @@ static int mediatek_dwmac_common_data(struct platform_device *pdev, plat->bsp_priv = priv_plat; plat->init = mediatek_dwmac_init; plat->clks_config = mediatek_dwmac_clks_config; - if (priv_plat->variant->dwmac_fix_mac_speed) - plat->fix_mac_speed = priv_plat->variant->dwmac_fix_mac_speed; plat->safety_feat_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->safety_feat_cfg), diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac5.c b/drivers/net/ethernet/stmicro/stmmac/dwmac5.c index 9c2d40f853ed..413f66017219 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac5.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac5.c @@ -186,11 +186,25 @@ static void dwmac5_handle_dma_err(struct net_device *ndev, int dwmac5_safety_feat_config(void __iomem *ioaddr, unsigned int asp, struct stmmac_safety_feature_cfg *safety_feat_cfg) { + struct stmmac_safety_feature_cfg all_safety_feats = { + .tsoee = 1, + .mrxpee = 1, + .mestee = 1, + .mrxee = 1, + .mtxee = 1, + .epsi = 1, + .edpp = 1, + .prtyen = 1, + .tmouten = 1, + }; u32 value; if (!asp) return -EINVAL; + if (!safety_feat_cfg) + safety_feat_cfg = &all_safety_feats; + /* 1. Enable Safety Features */ value = readl(ioaddr + MTL_ECC_CONTROL); value |= MEEAO; /* MTL ECC Error Addr Status Override */ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index f453b0d09366..35c8dd92d369 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c @@ -551,16 +551,16 @@ static void stmmac_get_per_qstats(struct stmmac_priv *priv, u64 *data) p = (char *)priv + offsetof(struct stmmac_priv, xstats.txq_stats[q].tx_pkt_n); for (stat = 0; stat < STMMAC_TXQ_STATS; stat++) { - *data++ = (*(u64 *)p); - p += sizeof(u64 *); + *data++ = (*(unsigned long *)p); + p += sizeof(unsigned long); } } for (q = 0; q < rx_cnt; q++) { p = (char *)priv + offsetof(struct stmmac_priv, xstats.rxq_stats[q].rx_pkt_n); for (stat = 0; stat < STMMAC_RXQ_STATS; stat++) { - *data++ = (*(u64 *)p); - p += sizeof(u64 *); + *data++ = (*(unsigned long *)p); + p += sizeof(unsigned long); } } } diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index c6951c976f5d..b7e5af58ab75 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1150,6 +1150,11 @@ static int stmmac_init_phy(struct net_device *dev) int addr = priv->plat->phy_addr; struct phy_device *phydev; + if (addr < 0) { + netdev_err(priv->dev, "no phy found\n"); + return -ENODEV; + } + phydev = mdiobus_get_phy(priv->mii, addr); if (!phydev) { netdev_err(priv->dev, "no phy at addr %d\n", addr); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c index fc06ddeac0d5..b4388ca8d211 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c @@ -210,7 +210,10 @@ static int stmmac_enable(struct ptp_clock_info *ptp, } writel(acr_value, ptpaddr + PTP_ACR); mutex_unlock(&priv->aux_ts_lock); - ret = 0; + /* wait for auxts fifo clear to finish */ + ret = readl_poll_timeout(ptpaddr + PTP_ACR, acr_value, + !(acr_value & PTP_ACR_ATSFC), + 10, 10000); break; default: diff --git a/drivers/net/ipa/data/ipa_data-v4.7.c b/drivers/net/ipa/data/ipa_data-v4.7.c index 7552c400961e..b83390c48615 100644 --- a/drivers/net/ipa/data/ipa_data-v4.7.c +++ b/drivers/net/ipa/data/ipa_data-v4.7.c @@ -357,7 +357,7 @@ static const struct ipa_mem ipa_mem_local_data[] = { static const struct ipa_mem_data ipa_mem_data = { .local_count = ARRAY_SIZE(ipa_mem_local_data), .local = ipa_mem_local_data, - .imem_addr = 0x146a9000, + .imem_addr = 0x146a8000, .imem_size = 0x00002000, .smem_id = 497, .smem_size = 0x00009000, diff --git a/drivers/net/ipa/ipa_interrupt.c b/drivers/net/ipa/ipa_interrupt.c index a49f66efacb8..c1b3977e1ae4 100644 --- a/drivers/net/ipa/ipa_interrupt.c +++ b/drivers/net/ipa/ipa_interrupt.c @@ -127,15 +127,25 @@ out_power_put: return IRQ_HANDLED; } +void ipa_interrupt_irq_disable(struct ipa *ipa) +{ + disable_irq(ipa->interrupt->irq); +} + +void ipa_interrupt_irq_enable(struct ipa *ipa) +{ + enable_irq(ipa->interrupt->irq); +} + /* Common function used to enable/disable TX_SUSPEND for an endpoint */ static void ipa_interrupt_suspend_control(struct ipa_interrupt *interrupt, u32 endpoint_id, bool enable) { struct ipa *ipa = interrupt->ipa; + u32 mask = BIT(endpoint_id % 32); u32 unit = endpoint_id / 32; const struct ipa_reg *reg; u32 offset; - u32 mask; u32 val; WARN_ON(!test_bit(endpoint_id, ipa->available)); @@ -148,7 +158,6 @@ static void ipa_interrupt_suspend_control(struct ipa_interrupt *interrupt, offset = ipa_reg_n_offset(reg, unit); val = ioread32(ipa->reg_virt + offset); - mask = BIT(endpoint_id); if (enable) val |= mask; else diff --git a/drivers/net/ipa/ipa_interrupt.h b/drivers/net/ipa/ipa_interrupt.h index f31fd9965fdc..8a1bd5b89393 100644 --- a/drivers/net/ipa/ipa_interrupt.h +++ b/drivers/net/ipa/ipa_interrupt.h @@ -86,6 +86,22 @@ void ipa_interrupt_suspend_clear_all(struct ipa_interrupt *interrupt); void ipa_interrupt_simulate_suspend(struct ipa_interrupt *interrupt); /** + * ipa_interrupt_irq_enable() - Enable IPA interrupts + * @ipa: IPA pointer + * + * This enables the IPA interrupt line + */ +void ipa_interrupt_irq_enable(struct ipa *ipa); + +/** + * ipa_interrupt_irq_disable() - Disable IPA interrupts + * @ipa: IPA pointer + * + * This disables the IPA interrupt line + */ +void ipa_interrupt_irq_disable(struct ipa *ipa); + +/** * ipa_interrupt_config() - Configure the IPA interrupt framework * @ipa: IPA pointer * diff --git a/drivers/net/ipa/ipa_power.c b/drivers/net/ipa/ipa_power.c index 8420f93128a2..8057be8cda80 100644 --- a/drivers/net/ipa/ipa_power.c +++ b/drivers/net/ipa/ipa_power.c @@ -181,6 +181,17 @@ static int ipa_suspend(struct device *dev) __set_bit(IPA_POWER_FLAG_SYSTEM, ipa->power->flags); + /* Increment the disable depth to ensure that the IRQ won't + * be re-enabled until the matching _enable call in + * ipa_resume(). We do this to ensure that the interrupt + * handler won't run whilst PM runtime is disabled. + * + * Note that disabling the IRQ is NOT the same as disabling + * irq wake. If wakeup is enabled for the IPA then the IRQ + * will still cause the system to wake up, see irq_set_irq_wake(). + */ + ipa_interrupt_irq_disable(ipa); + return pm_runtime_force_suspend(dev); } @@ -193,6 +204,12 @@ static int ipa_resume(struct device *dev) __clear_bit(IPA_POWER_FLAG_SYSTEM, ipa->power->flags); + /* Now that PM runtime is enabled again it's safe + * to turn the IRQ back on and process any data + * that was received during suspend. + */ + ipa_interrupt_irq_enable(ipa); + return ret; } diff --git a/drivers/net/mdio/mdio-mux-meson-g12a.c b/drivers/net/mdio/mdio-mux-meson-g12a.c index 4a2e94faf57e..c4542ecf5623 100644 --- a/drivers/net/mdio/mdio-mux-meson-g12a.c +++ b/drivers/net/mdio/mdio-mux-meson-g12a.c @@ -4,6 +4,7 @@ */ #include <linux/bitfield.h> +#include <linux/delay.h> #include <linux/clk.h> #include <linux/clk-provider.h> #include <linux/device.h> @@ -150,6 +151,7 @@ static const struct clk_ops g12a_ephy_pll_ops = { static int g12a_enable_internal_mdio(struct g12a_mdio_mux *priv) { + u32 value; int ret; /* Enable the phy clock */ @@ -163,18 +165,25 @@ static int g12a_enable_internal_mdio(struct g12a_mdio_mux *priv) /* Initialize ephy control */ writel(EPHY_G12A_ID, priv->regs + ETH_PHY_CNTL0); - writel(FIELD_PREP(PHY_CNTL1_ST_MODE, 3) | - FIELD_PREP(PHY_CNTL1_ST_PHYADD, EPHY_DFLT_ADD) | - FIELD_PREP(PHY_CNTL1_MII_MODE, EPHY_MODE_RMII) | - PHY_CNTL1_CLK_EN | - PHY_CNTL1_CLKFREQ | - PHY_CNTL1_PHY_ENB, - priv->regs + ETH_PHY_CNTL1); + + /* Make sure we get a 0 -> 1 transition on the enable bit */ + value = FIELD_PREP(PHY_CNTL1_ST_MODE, 3) | + FIELD_PREP(PHY_CNTL1_ST_PHYADD, EPHY_DFLT_ADD) | + FIELD_PREP(PHY_CNTL1_MII_MODE, EPHY_MODE_RMII) | + PHY_CNTL1_CLK_EN | + PHY_CNTL1_CLKFREQ; + writel(value, priv->regs + ETH_PHY_CNTL1); writel(PHY_CNTL2_USE_INTERNAL | PHY_CNTL2_SMI_SRC_MAC | PHY_CNTL2_RX_CLK_EPHY, priv->regs + ETH_PHY_CNTL2); + value |= PHY_CNTL1_PHY_ENB; + writel(value, priv->regs + ETH_PHY_CNTL1); + + /* The phy needs a bit of time to power up */ + mdelay(10); + return 0; } diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 1cd604cd1fa1..16e021b477f0 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -108,7 +108,12 @@ EXPORT_SYMBOL(mdiobus_unregister_device); struct phy_device *mdiobus_get_phy(struct mii_bus *bus, int addr) { - struct mdio_device *mdiodev = bus->mdio_map[addr]; + struct mdio_device *mdiodev; + + if (addr < 0 || addr >= ARRAY_SIZE(bus->mdio_map)) + return NULL; + + mdiodev = bus->mdio_map[addr]; if (!mdiodev) return NULL; diff --git a/drivers/net/phy/xilinx_gmii2rgmii.c b/drivers/net/phy/xilinx_gmii2rgmii.c index 8dcb49ed1f3d..7fd9fe6a602b 100644 --- a/drivers/net/phy/xilinx_gmii2rgmii.c +++ b/drivers/net/phy/xilinx_gmii2rgmii.c @@ -105,6 +105,7 @@ static int xgmiitorgmii_probe(struct mdio_device *mdiodev) if (!priv->phy_dev->drv) { dev_info(dev, "Attached phy not ready\n"); + put_device(&priv->phy_dev->mdio.dev); return -EPROBE_DEFER; } diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index fcd43d62d86b..d10606f257c4 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -1044,7 +1044,6 @@ static int team_port_enter(struct team *team, struct team_port *port) goto err_port_enter; } } - port->dev->priv_flags |= IFF_NO_ADDRCONF; return 0; @@ -1058,7 +1057,6 @@ static void team_port_leave(struct team *team, struct team_port *port) { if (team->ops.port_leave) team->ops.port_leave(team, port); - port->dev->priv_flags &= ~IFF_NO_ADDRCONF; dev_put(team->dev); } diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 8911cd2ed534..c140edb4b648 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -1008,6 +1008,12 @@ static const struct usb_device_id products[] = { USB_CDC_PROTO_NONE), .driver_info = (unsigned long)&wwan_info, }, { + /* Cinterion PLS62-W modem by GEMALTO/THALES */ + USB_DEVICE_AND_INTERFACE_INFO(0x1e2d, 0x005b, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, + USB_CDC_PROTO_NONE), + .driver_info = (unsigned long)&wwan_info, +}, { /* Cinterion PLS83/PLS63 modem by GEMALTO/THALES */ USB_DEVICE_AND_INTERFACE_INFO(0x1e2d, 0x0069, USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET, diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index a481a1d831e2..23da1d9dafd1 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -9836,6 +9836,7 @@ static const struct usb_device_id rtl8152_table[] = { REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07ab), REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07c6), REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x0927), + REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x0c5e), REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101), REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x304f), REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x3054), diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index f79333fe1783..7b3739b29c8f 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -255,7 +255,8 @@ static int rndis_query(struct usbnet *dev, struct usb_interface *intf, off = le32_to_cpu(u.get_c->offset); len = le32_to_cpu(u.get_c->len); - if (unlikely((8 + off + len) > CONTROL_BUFFER_SIZE)) + if (unlikely((off > CONTROL_BUFFER_SIZE - 8) || + (len > CONTROL_BUFFER_SIZE - 8 - off))) goto response_error; if (*reply_len != -1 && len != *reply_len) diff --git a/drivers/net/usb/sr9700.c b/drivers/net/usb/sr9700.c index 5a53e63d33a6..3164451e1010 100644 --- a/drivers/net/usb/sr9700.c +++ b/drivers/net/usb/sr9700.c @@ -413,7 +413,7 @@ static int sr9700_rx_fixup(struct usbnet *dev, struct sk_buff *skb) /* ignore the CRC length */ len = (skb->data[1] | (skb->data[2] << 8)) - 4; - if (len > ETH_FRAME_LEN || len > skb->len) + if (len > ETH_FRAME_LEN || len > skb->len || len < 0) return 0; /* the last packet of current skb */ diff --git a/drivers/net/veth.c b/drivers/net/veth.c index ac7c0653695f..dfc7d87fad59 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -974,6 +974,9 @@ static int veth_poll(struct napi_struct *napi, int budget) xdp_set_return_frame_no_direct(); done = veth_xdp_rcv(rq, budget, &bq, &stats); + if (stats.xdp_redirect > 0) + xdp_do_flush(); + if (done < budget && napi_complete_done(napi, done)) { /* Write rx_notify_masked before reading ptr_ring */ smp_store_mb(rq->rx_notify_masked, false); @@ -987,8 +990,6 @@ static int veth_poll(struct napi_struct *napi, int budget) if (stats.xdp_tx > 0) veth_xdp_flush(rq, &bq); - if (stats.xdp_redirect > 0) - xdp_do_flush(); xdp_clear_return_frame_no_direct(); return done; diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 7723b2a49d8e..18b3de854aeb 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1877,8 +1877,10 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) */ if (sq->vq->num_free < 2+MAX_SKB_FRAGS) { netif_stop_subqueue(dev, qnum); - if (!use_napi && - unlikely(!virtqueue_enable_cb_delayed(sq->vq))) { + if (use_napi) { + if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) + virtqueue_napi_schedule(&sq->napi, sq->vq); + } else if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) { /* More just got used, free them then recheck. */ free_old_xmit_skbs(sq, false); if (sq->vq->num_free >= 2+MAX_SKB_FRAGS) { diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 6f1e560fb15c..56267c327f0b 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -1288,6 +1288,10 @@ vmxnet3_rx_csum(struct vmxnet3_adapter *adapter, (le32_to_cpu(gdesc->dword[3]) & VMXNET3_RCD_CSUM_OK) == VMXNET3_RCD_CSUM_OK) { skb->ip_summed = CHECKSUM_UNNECESSARY; + if ((le32_to_cpu(gdesc->dword[0]) & + (1UL << VMXNET3_RCD_HDR_INNER_SHIFT))) { + skb->csum_level = 1; + } WARN_ON_ONCE(!(gdesc->rcd.tcp || gdesc->rcd.udp) && !(le32_to_cpu(gdesc->dword[0]) & (1UL << VMXNET3_RCD_HDR_INNER_SHIFT))); @@ -1297,6 +1301,10 @@ vmxnet3_rx_csum(struct vmxnet3_adapter *adapter, } else if (gdesc->rcd.v6 && (le32_to_cpu(gdesc->dword[3]) & (1 << VMXNET3_RCD_TUC_SHIFT))) { skb->ip_summed = CHECKSUM_UNNECESSARY; + if ((le32_to_cpu(gdesc->dword[0]) & + (1UL << VMXNET3_RCD_HDR_INNER_SHIFT))) { + skb->csum_level = 1; + } WARN_ON_ONCE(!(gdesc->rcd.tcp || gdesc->rcd.udp) && !(le32_to_cpu(gdesc->dword[0]) & (1UL << VMXNET3_RCD_HDR_INNER_SHIFT))); diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 6b5a4d036d15..bdb3a76a352e 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -1385,8 +1385,8 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev, /* loopback, multicast & non-ND link-local traffic; do not push through * packet taps again. Reset pkt_type for upper layers to process skb. - * For strict packets with a source LLA, determine the dst using the - * original ifindex. + * For non-loopback strict packets, determine the dst using the original + * ifindex. */ if (skb->pkt_type == PACKET_LOOPBACK || (need_strict && !is_ndisc)) { skb->dev = vrf_dev; @@ -1395,7 +1395,7 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev, if (skb->pkt_type == PACKET_LOOPBACK) skb->pkt_type = PACKET_HOST; - else if (ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL) + else vrf_ip6_input_dst(skb, vrf_dev, orig_iif); goto out; diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c index 92224b36787a..b1b179effe2a 100644 --- a/drivers/net/vxlan/vxlan_core.c +++ b/drivers/net/vxlan/vxlan_core.c @@ -2917,16 +2917,23 @@ static int vxlan_init(struct net_device *dev) vxlan_vnigroup_init(vxlan); dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); - if (!dev->tstats) - return -ENOMEM; + if (!dev->tstats) { + err = -ENOMEM; + goto err_vnigroup_uninit; + } err = gro_cells_init(&vxlan->gro_cells, dev); - if (err) { - free_percpu(dev->tstats); - return err; - } + if (err) + goto err_free_percpu; return 0; + +err_free_percpu: + free_percpu(dev->tstats); +err_vnigroup_uninit: + if (vxlan->cfg.flags & VXLAN_F_VNIFILTER) + vxlan_vnigroup_uninit(vxlan); + return err; } static void vxlan_fdb_delete_default(struct vxlan_dev *vxlan, __be32 vni) diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c index 22edea6ca4b8..1c53b5546927 100644 --- a/drivers/net/wan/fsl_ucc_hdlc.c +++ b/drivers/net/wan/fsl_ucc_hdlc.c @@ -1243,9 +1243,11 @@ static int ucc_hdlc_probe(struct platform_device *pdev) free_dev: free_netdev(dev); undo_uhdlc_init: - iounmap(utdm->siram); + if (utdm) + iounmap(utdm->siram); unmap_si_regs: - iounmap(utdm->si_regs); + if (utdm) + iounmap(utdm->si_regs); free_utdm: if (uhdlc_priv->tsa) kfree(utdm); diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 30f0765fb9fd..237f4ec2cffd 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -327,9 +327,9 @@ static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb) } #ifdef CONFIG_ATH9K_HTC_DEBUGFS -#define __STAT_SAFE(hif_dev, expr) ((hif_dev)->htc_handle->drv_priv ? (expr) : 0) -#define CAB_STAT_INC(priv) ((priv)->debug.tx_stats.cab_queued++) -#define TX_QSTAT_INC(priv, q) ((priv)->debug.tx_stats.queue_stats[q]++) +#define __STAT_SAFE(hif_dev, expr) do { ((hif_dev)->htc_handle->drv_priv ? (expr) : 0); } while (0) +#define CAB_STAT_INC(priv) do { ((priv)->debug.tx_stats.cab_queued++); } while (0) +#define TX_QSTAT_INC(priv, q) do { ((priv)->debug.tx_stats.queue_stats[q]++); } while (0) #define TX_STAT_INC(hif_dev, c) \ __STAT_SAFE((hif_dev), (hif_dev)->htc_handle->drv_priv->debug.tx_stats.c++) @@ -378,10 +378,10 @@ void ath9k_htc_get_et_stats(struct ieee80211_hw *hw, struct ethtool_stats *stats, u64 *data); #else -#define TX_STAT_INC(hif_dev, c) -#define TX_STAT_ADD(hif_dev, c, a) -#define RX_STAT_INC(hif_dev, c) -#define RX_STAT_ADD(hif_dev, c, a) +#define TX_STAT_INC(hif_dev, c) do { } while (0) +#define TX_STAT_ADD(hif_dev, c, a) do { } while (0) +#define RX_STAT_INC(hif_dev, c) do { } while (0) +#define RX_STAT_ADD(hif_dev, c, a) do { } while (0) #define CAB_STAT_INC(priv) #define TX_QSTAT_INC(priv, c) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index bff3128c2f26..b115902eb475 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -7937,6 +7937,9 @@ cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); + if (chan->flags & IEEE80211_CHAN_DISABLED) + return -EINVAL; + /* set_channel */ chspec = channel_to_chanspec(&cfg->d11inf, chan); if (chspec != INVCHANSPEC) { @@ -7961,7 +7964,7 @@ brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev, struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); struct brcmf_dump_survey survey = {}; struct ieee80211_supported_band *band; - struct ieee80211_channel *chan; + enum nl80211_band band_id; struct cca_msrmnt_query req; u32 noise; int err; @@ -7974,26 +7977,25 @@ brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev, return -EBUSY; } - band = wiphy->bands[NL80211_BAND_2GHZ]; - if (band && idx >= band->n_channels) { - idx -= band->n_channels; - band = NULL; - } + for (band_id = 0; band_id < NUM_NL80211_BANDS; band_id++) { + band = wiphy->bands[band_id]; + if (!band) + continue; + if (idx >= band->n_channels) { + idx -= band->n_channels; + continue; + } - if (!band || idx >= band->n_channels) { - band = wiphy->bands[NL80211_BAND_5GHZ]; - if (idx >= band->n_channels) - return -ENOENT; + info->channel = &band->channels[idx]; + break; } + if (band_id == NUM_NL80211_BANDS) + return -ENOENT; /* Setting current channel to the requested channel */ - chan = &band->channels[idx]; - err = cfg80211_set_channel(wiphy, ndev, chan, NL80211_CHAN_HT20); - if (err) { - info->channel = chan; - info->filled = 0; + info->filled = 0; + if (cfg80211_set_channel(wiphy, ndev, info->channel, NL80211_CHAN_HT20)) return 0; - } /* Disable mpc */ brcmf_set_mpc(ifp, 0); @@ -8028,7 +8030,6 @@ brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev, if (err) goto exit; - info->channel = chan; info->noise = noise; info->time = ACS_MSRMNT_DELAY; info->time_busy = ACS_MSRMNT_DELAY - survey.idle; @@ -8040,7 +8041,7 @@ brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev, SURVEY_INFO_TIME_TX; brcmf_dbg(INFO, "OBSS dump: channel %d: survey duration %d\n", - ieee80211_frequency_to_channel(chan->center_freq), + ieee80211_frequency_to_channel(info->channel->center_freq), ACS_MSRMNT_DELAY); brcmf_dbg(INFO, "noise(%d) busy(%llu) rx(%llu) tx(%llu)\n", info->noise, info->time_busy, info->time_rx, info->time_tx); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c index a83699de01ec..fdd0c9abc1a1 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c @@ -79,7 +79,8 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, /* Apple ARM64 platforms have their own idea of board type, passed in * via the device tree. They also have an antenna SKU parameter */ - if (!of_property_read_string(np, "brcm,board-type", &prop)) + err = of_property_read_string(np, "brcm,board-type", &prop); + if (!err) settings->board_type = prop; if (!of_property_read_string(np, "apple,antenna-sku", &prop)) @@ -87,7 +88,7 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, /* Set board-type to the first string of the machine compatible prop */ root = of_find_node_by_path("/"); - if (root && !settings->board_type) { + if (root && err) { char *board_type; const char *tmp; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index ae57a9a3ab05..b67f6d0810b6 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -1228,7 +1228,7 @@ static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo) BRCMF_NROF_H2D_COMMON_MSGRINGS; max_completionrings = BRCMF_NROF_D2H_COMMON_MSGRINGS; } - if (max_flowrings > 256) { + if (max_flowrings > 512) { brcmf_err(bus, "invalid max_flowrings(%d)\n", max_flowrings); return -EIO; } diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c index e6d64152c81a..a02e5a67b706 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c @@ -1106,6 +1106,11 @@ int iwl_read_ppag_table(struct iwl_fw_runtime *fwrt, union iwl_ppag_table_cmd *c int i, j, num_sub_bands; s8 *gain; + /* many firmware images for JF lie about this */ + if (CSR_HW_RFID_TYPE(fwrt->trans->hw_rf_id) == + CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_JF)) + return -EOPNOTSUPP; + if (!fw_has_capa(&fwrt->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SET_PPAG)) { IWL_DEBUG_RADIO(fwrt, "PPAG capability not supported by FW, command not sent.\n"); diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index f795548562f5..06161815c180 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -206,71 +206,103 @@ mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q) } static int +mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q, + struct mt76_queue_buf *buf, void *data) +{ + struct mt76_desc *desc = &q->desc[q->head]; + struct mt76_queue_entry *entry = &q->entry[q->head]; + struct mt76_txwi_cache *txwi = NULL; + u32 buf1 = 0, ctrl; + int idx = q->head; + int rx_token; + + ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len); + + if ((q->flags & MT_QFLAG_WED) && + FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX) { + txwi = mt76_get_rxwi(dev); + if (!txwi) + return -ENOMEM; + + rx_token = mt76_rx_token_consume(dev, data, txwi, buf->addr); + if (rx_token < 0) { + mt76_put_rxwi(dev, txwi); + return -ENOMEM; + } + + buf1 |= FIELD_PREP(MT_DMA_CTL_TOKEN, rx_token); + ctrl |= MT_DMA_CTL_TO_HOST; + } + + WRITE_ONCE(desc->buf0, cpu_to_le32(buf->addr)); + WRITE_ONCE(desc->buf1, cpu_to_le32(buf1)); + WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl)); + WRITE_ONCE(desc->info, 0); + + entry->dma_addr[0] = buf->addr; + entry->dma_len[0] = buf->len; + entry->txwi = txwi; + entry->buf = data; + entry->wcid = 0xffff; + entry->skip_buf1 = true; + q->head = (q->head + 1) % q->ndesc; + q->queued++; + + return idx; +} + +static int mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q, struct mt76_queue_buf *buf, int nbufs, u32 info, struct sk_buff *skb, void *txwi) { struct mt76_queue_entry *entry; struct mt76_desc *desc; - u32 ctrl; int i, idx = -1; + u32 ctrl, next; + + if (txwi) { + q->entry[q->head].txwi = DMA_DUMMY_DATA; + q->entry[q->head].skip_buf0 = true; + } for (i = 0; i < nbufs; i += 2, buf += 2) { u32 buf0 = buf[0].addr, buf1 = 0; idx = q->head; - q->head = (q->head + 1) % q->ndesc; + next = (q->head + 1) % q->ndesc; desc = &q->desc[idx]; entry = &q->entry[idx]; - if ((q->flags & MT_QFLAG_WED) && - FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX) { - struct mt76_txwi_cache *t = txwi; - int rx_token; - - if (!t) - return -ENOMEM; - - rx_token = mt76_rx_token_consume(dev, (void *)skb, t, - buf[0].addr); - buf1 |= FIELD_PREP(MT_DMA_CTL_TOKEN, rx_token); - ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len) | - MT_DMA_CTL_TO_HOST; - } else { - if (txwi) { - q->entry[q->head].txwi = DMA_DUMMY_DATA; - q->entry[q->head].skip_buf0 = true; - } - - if (buf[0].skip_unmap) - entry->skip_buf0 = true; - entry->skip_buf1 = i == nbufs - 1; - - entry->dma_addr[0] = buf[0].addr; - entry->dma_len[0] = buf[0].len; - - ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len); - if (i < nbufs - 1) { - entry->dma_addr[1] = buf[1].addr; - entry->dma_len[1] = buf[1].len; - buf1 = buf[1].addr; - ctrl |= FIELD_PREP(MT_DMA_CTL_SD_LEN1, buf[1].len); - if (buf[1].skip_unmap) - entry->skip_buf1 = true; - } - - if (i == nbufs - 1) - ctrl |= MT_DMA_CTL_LAST_SEC0; - else if (i == nbufs - 2) - ctrl |= MT_DMA_CTL_LAST_SEC1; + if (buf[0].skip_unmap) + entry->skip_buf0 = true; + entry->skip_buf1 = i == nbufs - 1; + + entry->dma_addr[0] = buf[0].addr; + entry->dma_len[0] = buf[0].len; + + ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len); + if (i < nbufs - 1) { + entry->dma_addr[1] = buf[1].addr; + entry->dma_len[1] = buf[1].len; + buf1 = buf[1].addr; + ctrl |= FIELD_PREP(MT_DMA_CTL_SD_LEN1, buf[1].len); + if (buf[1].skip_unmap) + entry->skip_buf1 = true; } + if (i == nbufs - 1) + ctrl |= MT_DMA_CTL_LAST_SEC0; + else if (i == nbufs - 2) + ctrl |= MT_DMA_CTL_LAST_SEC1; + WRITE_ONCE(desc->buf0, cpu_to_le32(buf0)); WRITE_ONCE(desc->buf1, cpu_to_le32(buf1)); WRITE_ONCE(desc->info, cpu_to_le32(info)); WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl)); + q->head = next; q->queued++; } @@ -577,17 +609,9 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q) spin_lock_bh(&q->lock); while (q->queued < q->ndesc - 1) { - struct mt76_txwi_cache *t = NULL; struct mt76_queue_buf qbuf; void *buf = NULL; - if ((q->flags & MT_QFLAG_WED) && - FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX) { - t = mt76_get_rxwi(dev); - if (!t) - break; - } - buf = page_frag_alloc(rx_page, q->buf_size, GFP_ATOMIC); if (!buf) break; @@ -601,7 +625,12 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q) qbuf.addr = addr + offset; qbuf.len = len - offset; qbuf.skip_unmap = false; - mt76_dma_add_buf(dev, q, &qbuf, 1, 0, buf, t); + if (mt76_dma_add_rx_buf(dev, q, &qbuf, buf) < 0) { + dma_unmap_single(dev->dma_dev, addr, len, + DMA_FROM_DEVICE); + skb_free_frag(buf); + break; + } frames++; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c index 0a95c3da241b..8388e2a65853 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c @@ -653,6 +653,13 @@ static u32 mt7915_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size) desc->buf0 = cpu_to_le32(phy_addr); token = mt76_rx_token_consume(&dev->mt76, ptr, t, phy_addr); + if (token < 0) { + dma_unmap_single(dev->mt76.dma_dev, phy_addr, + wed->wlan.rx_size, DMA_TO_DEVICE); + skb_free_frag(ptr); + goto unmap; + } + desc->token |= cpu_to_le32(FIELD_PREP(MT_DMA_CTL_TOKEN, token)); desc++; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig index 5c5fc569e6d5..79fb47a73c91 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig @@ -2,6 +2,7 @@ config MT7996E tristate "MediaTek MT7996 (PCIe) support" select MT76_CONNAC_LIB + select RELAY depends on MAC80211 depends on PCI help diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index 24568b98ed9d..1f309d05380a 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -764,11 +764,12 @@ int mt76_rx_token_consume(struct mt76_dev *dev, void *ptr, spin_lock_bh(&dev->rx_token_lock); token = idr_alloc(&dev->rx_token, t, 0, dev->rx_token_size, GFP_ATOMIC); + if (token >= 0) { + t->ptr = ptr; + t->dma_addr = phys; + } spin_unlock_bh(&dev->rx_token_lock); - t->ptr = ptr; - t->dma_addr = phys; - return token; } EXPORT_SYMBOL_GPL(mt76_rx_token_consume); diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 82a7458e01ae..bf72e5fd39cf 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -696,8 +696,8 @@ static int rndis_query_oid(struct usbnet *dev, u32 oid, void *data, int *len) struct rndis_query *get; struct rndis_query_c *get_c; } u; - int ret, buflen; - int resplen, respoffs, copylen; + int ret; + size_t buflen, resplen, respoffs, copylen; buflen = *len + sizeof(*u.get); if (buflen < CONTROL_BUFFER_SIZE) @@ -732,22 +732,15 @@ static int rndis_query_oid(struct usbnet *dev, u32 oid, void *data, int *len) if (respoffs > buflen) { /* Device returned data offset outside buffer, error. */ - netdev_dbg(dev->net, "%s(%s): received invalid " - "data offset: %d > %d\n", __func__, - oid_to_string(oid), respoffs, buflen); + netdev_dbg(dev->net, + "%s(%s): received invalid data offset: %zu > %zu\n", + __func__, oid_to_string(oid), respoffs, buflen); ret = -EINVAL; goto exit_unlock; } - if ((resplen + respoffs) > buflen) { - /* Device would have returned more data if buffer would - * have been big enough. Copy just the bits that we got. - */ - copylen = buflen - respoffs; - } else { - copylen = resplen; - } + copylen = min(resplen, buflen - respoffs); if (copylen > *len) copylen = *len; diff --git a/drivers/net/wireless/ti/Makefile b/drivers/net/wireless/ti/Makefile index 0530dd744275..05ee016594f8 100644 --- a/drivers/net/wireless/ti/Makefile +++ b/drivers/net/wireless/ti/Makefile @@ -3,6 +3,3 @@ obj-$(CONFIG_WLCORE) += wlcore/ obj-$(CONFIG_WL12XX) += wl12xx/ obj-$(CONFIG_WL1251) += wl1251/ obj-$(CONFIG_WL18XX) += wl18xx/ - -# small builtin driver bit -obj-$(CONFIG_WILINK_PLATFORM_DATA) += wilink_platform_data.o diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index c1ba4294f364..001636901dda 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -977,7 +977,7 @@ static int read_xenbus_vif_flags(struct backend_info *be) return 0; } -static int netback_remove(struct xenbus_device *dev) +static void netback_remove(struct xenbus_device *dev) { struct backend_info *be = dev_get_drvdata(&dev->dev); @@ -992,7 +992,6 @@ static int netback_remove(struct xenbus_device *dev) kfree(be->hotplug_script); kfree(be); dev_set_drvdata(&dev->dev, NULL); - return 0; } /* diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 14aec417fa06..12b074286df9 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -2646,7 +2646,7 @@ static void xennet_bus_close(struct xenbus_device *dev) } while (!ret); } -static int xennet_remove(struct xenbus_device *dev) +static void xennet_remove(struct xenbus_device *dev) { struct netfront_info *info = dev_get_drvdata(&dev->dev); @@ -2662,8 +2662,6 @@ static int xennet_remove(struct xenbus_device *dev) rtnl_unlock(); } xennet_free_netdev(info->netdev); - - return 0; } static const struct xenbus_device_id netfront_ids[] = { diff --git a/drivers/nfc/pn533/usb.c b/drivers/nfc/pn533/usb.c index 6f71ac72012e..ed9c5e2cf3ad 100644 --- a/drivers/nfc/pn533/usb.c +++ b/drivers/nfc/pn533/usb.c @@ -153,10 +153,17 @@ static int pn533_usb_send_ack(struct pn533 *dev, gfp_t flags) return usb_submit_urb(phy->ack_urb, flags); } +struct pn533_out_arg { + struct pn533_usb_phy *phy; + struct completion done; +}; + static int pn533_usb_send_frame(struct pn533 *dev, struct sk_buff *out) { struct pn533_usb_phy *phy = dev->phy; + struct pn533_out_arg arg; + void *cntx; int rc; if (phy->priv == NULL) @@ -168,10 +175,17 @@ static int pn533_usb_send_frame(struct pn533 *dev, print_hex_dump_debug("PN533 TX: ", DUMP_PREFIX_NONE, 16, 1, out->data, out->len, false); + init_completion(&arg.done); + cntx = phy->out_urb->context; + phy->out_urb->context = &arg; + rc = usb_submit_urb(phy->out_urb, GFP_KERNEL); if (rc) return rc; + wait_for_completion(&arg.done); + phy->out_urb->context = cntx; + if (dev->protocol_type == PN533_PROTO_REQ_RESP) { /* request for response for sent packet directly */ rc = pn533_submit_urb_for_response(phy, GFP_KERNEL); @@ -408,7 +422,31 @@ static int pn533_acr122_poweron_rdr(struct pn533_usb_phy *phy) return arg.rc; } -static void pn533_send_complete(struct urb *urb) +static void pn533_out_complete(struct urb *urb) +{ + struct pn533_out_arg *arg = urb->context; + struct pn533_usb_phy *phy = arg->phy; + + switch (urb->status) { + case 0: + break; /* success */ + case -ECONNRESET: + case -ENOENT: + dev_dbg(&phy->udev->dev, + "The urb has been stopped (status %d)\n", + urb->status); + break; + case -ESHUTDOWN: + default: + nfc_err(&phy->udev->dev, + "Urb failure (status %d)\n", + urb->status); + } + + complete(&arg->done); +} + +static void pn533_ack_complete(struct urb *urb) { struct pn533_usb_phy *phy = urb->context; @@ -496,10 +534,10 @@ static int pn533_usb_probe(struct usb_interface *interface, usb_fill_bulk_urb(phy->out_urb, phy->udev, usb_sndbulkpipe(phy->udev, out_endpoint), - NULL, 0, pn533_send_complete, phy); + NULL, 0, pn533_out_complete, phy); usb_fill_bulk_urb(phy->ack_urb, phy->udev, usb_sndbulkpipe(phy->udev, out_endpoint), - NULL, 0, pn533_send_complete, phy); + NULL, 0, pn533_ack_complete, phy); switch (id->driver_info) { case PN533_DEVICE_STD: diff --git a/drivers/nvme/host/apple.c b/drivers/nvme/host/apple.c index e36aeb50b4ed..b317ce6c4ec3 100644 --- a/drivers/nvme/host/apple.c +++ b/drivers/nvme/host/apple.c @@ -829,7 +829,23 @@ static void apple_nvme_disable(struct apple_nvme *anv, bool shutdown) apple_nvme_remove_cq(anv); } - nvme_disable_ctrl(&anv->ctrl, shutdown); + /* + * Always disable the NVMe controller after shutdown. + * We need to do this to bring it back up later anyway, and we + * can't do it while the firmware is not running (e.g. in the + * resume reset path before RTKit is initialized), so for Apple + * controllers it makes sense to unconditionally do it here. + * Additionally, this sequence of events is reliable, while + * others (like disabling after bringing back the firmware on + * resume) seem to run into trouble under some circumstances. + * + * Both U-Boot and m1n1 also use this convention (i.e. an ANS + * NVMe controller is handed off with firmware shut down, in an + * NVMe disabled state, after a clean shutdown). + */ + if (shutdown) + nvme_disable_ctrl(&anv->ctrl, shutdown); + nvme_disable_ctrl(&anv->ctrl, false); } WRITE_ONCE(anv->ioq.enabled, false); @@ -985,11 +1001,11 @@ static void apple_nvme_reset_work(struct work_struct *work) goto out; } - if (anv->ctrl.ctrl_config & NVME_CC_ENABLE) - apple_nvme_disable(anv, false); - /* RTKit must be shut down cleanly for the (soft)-reset to work */ if (apple_rtkit_is_running(anv->rtk)) { + /* reset the controller if it is enabled */ + if (anv->ctrl.ctrl_config & NVME_CC_ENABLE) + apple_nvme_disable(anv, false); dev_dbg(anv->dev, "Trying to shut down RTKit before reset."); ret = apple_rtkit_shutdown(anv->rtk); if (ret) @@ -1493,7 +1509,7 @@ static int apple_nvme_probe(struct platform_device *pdev) } ret = nvme_init_ctrl(&anv->ctrl, anv->dev, &nvme_ctrl_ops, - NVME_QUIRK_SKIP_CID_GEN); + NVME_QUIRK_SKIP_CID_GEN | NVME_QUIRK_IDENTIFY_CNS); if (ret) { dev_err_probe(dev, ret, "Failed to initialize nvme_ctrl"); goto put_dev; diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 7be562a4e1aa..505e16f20e57 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -1093,7 +1093,7 @@ u32 nvme_command_effects(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u8 opcode) if (ns) { if (ns->head->effects) effects = le32_to_cpu(ns->head->effects->iocs[opcode]); - if (ns->head->ids.csi == NVME_CAP_CSS_NVM) + if (ns->head->ids.csi == NVME_CSI_NVM) effects |= nvme_known_nvm_effects(opcode); if (effects & ~(NVME_CMD_EFFECTS_CSUPP | NVME_CMD_EFFECTS_LBCC)) dev_warn_once(ctrl->device, diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index 4564f16a0b20..456ee42a6133 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c @@ -3521,13 +3521,6 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts, nvme_fc_init_queue(ctrl, 0); - ret = nvme_alloc_admin_tag_set(&ctrl->ctrl, &ctrl->admin_tag_set, - &nvme_fc_admin_mq_ops, - struct_size((struct nvme_fcp_op_w_sgl *)NULL, priv, - ctrl->lport->ops->fcprqst_priv_sz)); - if (ret) - goto out_free_queues; - /* * Would have been nice to init io queues tag set as well. * However, we require interaction from the controller @@ -3537,10 +3530,17 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts, ret = nvme_init_ctrl(&ctrl->ctrl, dev, &nvme_fc_ctrl_ops, 0); if (ret) - goto out_cleanup_tagset; + goto out_free_queues; /* at this point, teardown path changes to ref counting on nvme ctrl */ + ret = nvme_alloc_admin_tag_set(&ctrl->ctrl, &ctrl->admin_tag_set, + &nvme_fc_admin_mq_ops, + struct_size((struct nvme_fcp_op_w_sgl *)NULL, priv, + ctrl->lport->ops->fcprqst_priv_sz)); + if (ret) + goto fail_ctrl; + spin_lock_irqsave(&rport->lock, flags); list_add_tail(&ctrl->ctrl_list, &rport->ctrl_list); spin_unlock_irqrestore(&rport->lock, flags); @@ -3592,8 +3592,6 @@ fail_ctrl: return ERR_PTR(-EIO); -out_cleanup_tagset: - nvme_remove_admin_tag_set(&ctrl->ctrl); out_free_queues: kfree(ctrl->queues); out_free_ida: diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c index a8639919237e..06f52db34be9 100644 --- a/drivers/nvme/host/ioctl.c +++ b/drivers/nvme/host/ioctl.c @@ -8,8 +8,13 @@ #include <linux/io_uring.h> #include "nvme.h" +enum { + NVME_IOCTL_VEC = (1 << 0), + NVME_IOCTL_PARTITION = (1 << 1), +}; + static bool nvme_cmd_allowed(struct nvme_ns *ns, struct nvme_command *c, - fmode_t mode) + unsigned int flags, fmode_t mode) { u32 effects; @@ -17,6 +22,13 @@ static bool nvme_cmd_allowed(struct nvme_ns *ns, struct nvme_command *c, return true; /* + * Do not allow unprivileged passthrough on partitions, as that allows an + * escape from the containment of the partition. + */ + if (flags & NVME_IOCTL_PARTITION) + return false; + + /* * Do not allow unprivileged processes to send vendor specific or fabrics * commands as we can't be sure about their effects. */ @@ -150,7 +162,7 @@ static struct request *nvme_alloc_user_request(struct request_queue *q, static int nvme_map_user_request(struct request *req, u64 ubuffer, unsigned bufflen, void __user *meta_buffer, unsigned meta_len, u32 meta_seed, void **metap, struct io_uring_cmd *ioucmd, - bool vec) + unsigned int flags) { struct request_queue *q = req->q; struct nvme_ns *ns = q->queuedata; @@ -163,7 +175,7 @@ static int nvme_map_user_request(struct request *req, u64 ubuffer, struct iov_iter iter; /* fixedbufs is only for non-vectored io */ - if (WARN_ON_ONCE(vec)) + if (WARN_ON_ONCE(flags & NVME_IOCTL_VEC)) return -EINVAL; ret = io_uring_cmd_import_fixed(ubuffer, bufflen, rq_data_dir(req), &iter, ioucmd); @@ -172,8 +184,8 @@ static int nvme_map_user_request(struct request *req, u64 ubuffer, ret = blk_rq_map_user_iov(q, req, NULL, &iter, GFP_KERNEL); } else { ret = blk_rq_map_user_io(req, NULL, nvme_to_user_ptr(ubuffer), - bufflen, GFP_KERNEL, vec, 0, 0, - rq_data_dir(req)); + bufflen, GFP_KERNEL, flags & NVME_IOCTL_VEC, 0, + 0, rq_data_dir(req)); } if (ret) @@ -203,9 +215,9 @@ out: } static int nvme_submit_user_cmd(struct request_queue *q, - struct nvme_command *cmd, u64 ubuffer, - unsigned bufflen, void __user *meta_buffer, unsigned meta_len, - u32 meta_seed, u64 *result, unsigned timeout, bool vec) + struct nvme_command *cmd, u64 ubuffer, unsigned bufflen, + void __user *meta_buffer, unsigned meta_len, u32 meta_seed, + u64 *result, unsigned timeout, unsigned int flags) { struct nvme_ctrl *ctrl; struct request *req; @@ -221,7 +233,7 @@ static int nvme_submit_user_cmd(struct request_queue *q, req->timeout = timeout; if (ubuffer && bufflen) { ret = nvme_map_user_request(req, ubuffer, bufflen, meta_buffer, - meta_len, meta_seed, &meta, NULL, vec); + meta_len, meta_seed, &meta, NULL, flags); if (ret) return ret; } @@ -304,10 +316,8 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) c.rw.apptag = cpu_to_le16(io.apptag); c.rw.appmask = cpu_to_le16(io.appmask); - return nvme_submit_user_cmd(ns->queue, &c, - io.addr, length, - metadata, meta_len, lower_32_bits(io.slba), NULL, 0, - false); + return nvme_submit_user_cmd(ns->queue, &c, io.addr, length, metadata, + meta_len, lower_32_bits(io.slba), NULL, 0, 0); } static bool nvme_validate_passthru_nsid(struct nvme_ctrl *ctrl, @@ -325,7 +335,8 @@ static bool nvme_validate_passthru_nsid(struct nvme_ctrl *ctrl, } static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns, - struct nvme_passthru_cmd __user *ucmd, fmode_t mode) + struct nvme_passthru_cmd __user *ucmd, unsigned int flags, + fmode_t mode) { struct nvme_passthru_cmd cmd; struct nvme_command c; @@ -353,16 +364,15 @@ static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns, c.common.cdw14 = cpu_to_le32(cmd.cdw14); c.common.cdw15 = cpu_to_le32(cmd.cdw15); - if (!nvme_cmd_allowed(ns, &c, mode)) + if (!nvme_cmd_allowed(ns, &c, 0, mode)) return -EACCES; if (cmd.timeout_ms) timeout = msecs_to_jiffies(cmd.timeout_ms); status = nvme_submit_user_cmd(ns ? ns->queue : ctrl->admin_q, &c, - cmd.addr, cmd.data_len, - nvme_to_user_ptr(cmd.metadata), cmd.metadata_len, - 0, &result, timeout, false); + cmd.addr, cmd.data_len, nvme_to_user_ptr(cmd.metadata), + cmd.metadata_len, 0, &result, timeout, 0); if (status >= 0) { if (put_user(result, &ucmd->result)) @@ -373,8 +383,8 @@ static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns, } static int nvme_user_cmd64(struct nvme_ctrl *ctrl, struct nvme_ns *ns, - struct nvme_passthru_cmd64 __user *ucmd, bool vec, - fmode_t mode) + struct nvme_passthru_cmd64 __user *ucmd, unsigned int flags, + fmode_t mode) { struct nvme_passthru_cmd64 cmd; struct nvme_command c; @@ -401,16 +411,15 @@ static int nvme_user_cmd64(struct nvme_ctrl *ctrl, struct nvme_ns *ns, c.common.cdw14 = cpu_to_le32(cmd.cdw14); c.common.cdw15 = cpu_to_le32(cmd.cdw15); - if (!nvme_cmd_allowed(ns, &c, mode)) + if (!nvme_cmd_allowed(ns, &c, flags, mode)) return -EACCES; if (cmd.timeout_ms) timeout = msecs_to_jiffies(cmd.timeout_ms); status = nvme_submit_user_cmd(ns ? ns->queue : ctrl->admin_q, &c, - cmd.addr, cmd.data_len, - nvme_to_user_ptr(cmd.metadata), cmd.metadata_len, - 0, &cmd.result, timeout, vec); + cmd.addr, cmd.data_len, nvme_to_user_ptr(cmd.metadata), + cmd.metadata_len, 0, &cmd.result, timeout, flags); if (status >= 0) { if (put_user(cmd.result, &ucmd->result)) @@ -571,7 +580,7 @@ static int nvme_uring_cmd_io(struct nvme_ctrl *ctrl, struct nvme_ns *ns, c.common.cdw14 = cpu_to_le32(READ_ONCE(cmd->cdw14)); c.common.cdw15 = cpu_to_le32(READ_ONCE(cmd->cdw15)); - if (!nvme_cmd_allowed(ns, &c, ioucmd->file->f_mode)) + if (!nvme_cmd_allowed(ns, &c, 0, ioucmd->file->f_mode)) return -EACCES; d.metadata = READ_ONCE(cmd->metadata); @@ -641,9 +650,9 @@ static int nvme_ctrl_ioctl(struct nvme_ctrl *ctrl, unsigned int cmd, { switch (cmd) { case NVME_IOCTL_ADMIN_CMD: - return nvme_user_cmd(ctrl, NULL, argp, mode); + return nvme_user_cmd(ctrl, NULL, argp, 0, mode); case NVME_IOCTL_ADMIN64_CMD: - return nvme_user_cmd64(ctrl, NULL, argp, false, mode); + return nvme_user_cmd64(ctrl, NULL, argp, 0, mode); default: return sed_ioctl(ctrl->opal_dev, cmd, argp); } @@ -668,14 +677,14 @@ struct nvme_user_io32 { #endif /* COMPAT_FOR_U64_ALIGNMENT */ static int nvme_ns_ioctl(struct nvme_ns *ns, unsigned int cmd, - void __user *argp, fmode_t mode) + void __user *argp, unsigned int flags, fmode_t mode) { switch (cmd) { case NVME_IOCTL_ID: force_successful_syscall_return(); return ns->head->ns_id; case NVME_IOCTL_IO_CMD: - return nvme_user_cmd(ns->ctrl, ns, argp, mode); + return nvme_user_cmd(ns->ctrl, ns, argp, flags, mode); /* * struct nvme_user_io can have different padding on some 32-bit ABIs. * Just accept the compat version as all fields that are used are the @@ -686,37 +695,40 @@ static int nvme_ns_ioctl(struct nvme_ns *ns, unsigned int cmd, #endif case NVME_IOCTL_SUBMIT_IO: return nvme_submit_io(ns, argp); - case NVME_IOCTL_IO64_CMD: - return nvme_user_cmd64(ns->ctrl, ns, argp, false, mode); case NVME_IOCTL_IO64_CMD_VEC: - return nvme_user_cmd64(ns->ctrl, ns, argp, true, mode); + flags |= NVME_IOCTL_VEC; + fallthrough; + case NVME_IOCTL_IO64_CMD: + return nvme_user_cmd64(ns->ctrl, ns, argp, flags, mode); default: return -ENOTTY; } } -static int __nvme_ioctl(struct nvme_ns *ns, unsigned int cmd, void __user *arg, - fmode_t mode) -{ - if (is_ctrl_ioctl(cmd)) - return nvme_ctrl_ioctl(ns->ctrl, cmd, arg, mode); - return nvme_ns_ioctl(ns, cmd, arg, mode); -} - int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { struct nvme_ns *ns = bdev->bd_disk->private_data; + void __user *argp = (void __user *)arg; + unsigned int flags = 0; - return __nvme_ioctl(ns, cmd, (void __user *)arg, mode); + if (bdev_is_partition(bdev)) + flags |= NVME_IOCTL_PARTITION; + + if (is_ctrl_ioctl(cmd)) + return nvme_ctrl_ioctl(ns->ctrl, cmd, argp, mode); + return nvme_ns_ioctl(ns, cmd, argp, flags, mode); } long nvme_ns_chr_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct nvme_ns *ns = container_of(file_inode(file)->i_cdev, struct nvme_ns, cdev); + void __user *argp = (void __user *)arg; - return __nvme_ioctl(ns, cmd, (void __user *)arg, file->f_mode); + if (is_ctrl_ioctl(cmd)) + return nvme_ctrl_ioctl(ns->ctrl, cmd, argp, file->f_mode); + return nvme_ns_ioctl(ns, cmd, argp, 0, file->f_mode); } static int nvme_uring_cmd_checks(unsigned int issue_flags) @@ -806,6 +818,10 @@ int nvme_ns_head_ioctl(struct block_device *bdev, fmode_t mode, void __user *argp = (void __user *)arg; struct nvme_ns *ns; int srcu_idx, ret = -EWOULDBLOCK; + unsigned int flags = 0; + + if (bdev_is_partition(bdev)) + flags |= NVME_IOCTL_PARTITION; srcu_idx = srcu_read_lock(&head->srcu); ns = nvme_find_path(head); @@ -821,7 +837,7 @@ int nvme_ns_head_ioctl(struct block_device *bdev, fmode_t mode, return nvme_ns_head_ctrl_ioctl(ns, cmd, argp, head, srcu_idx, mode); - ret = nvme_ns_ioctl(ns, cmd, argp, mode); + ret = nvme_ns_ioctl(ns, cmd, argp, flags, mode); out_unlock: srcu_read_unlock(&head->srcu, srcu_idx); return ret; @@ -846,7 +862,7 @@ long nvme_ns_head_chr_ioctl(struct file *file, unsigned int cmd, return nvme_ns_head_ctrl_ioctl(ns, cmd, argp, head, srcu_idx, file->f_mode); - ret = nvme_ns_ioctl(ns, cmd, argp, file->f_mode); + ret = nvme_ns_ioctl(ns, cmd, argp, 0, file->f_mode); out_unlock: srcu_read_unlock(&head->srcu, srcu_idx); return ret; @@ -945,7 +961,7 @@ static int nvme_dev_user_cmd(struct nvme_ctrl *ctrl, void __user *argp, kref_get(&ns->kref); up_read(&ctrl->namespaces_rwsem); - ret = nvme_user_cmd(ctrl, ns, argp, mode); + ret = nvme_user_cmd(ctrl, ns, argp, 0, mode); nvme_put_ns(ns); return ret; @@ -962,9 +978,9 @@ long nvme_dev_ioctl(struct file *file, unsigned int cmd, switch (cmd) { case NVME_IOCTL_ADMIN_CMD: - return nvme_user_cmd(ctrl, NULL, argp, file->f_mode); + return nvme_user_cmd(ctrl, NULL, argp, 0, file->f_mode); case NVME_IOCTL_ADMIN64_CMD: - return nvme_user_cmd64(ctrl, NULL, argp, false, file->f_mode); + return nvme_user_cmd64(ctrl, NULL, argp, 0, file->f_mode); case NVME_IOCTL_IO_CMD: return nvme_dev_user_cmd(ctrl, argp, file->f_mode); case NVME_IOCTL_RESET: diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c index c03093b6813c..fc39d01e7b63 100644 --- a/drivers/nvme/host/multipath.c +++ b/drivers/nvme/host/multipath.c @@ -376,6 +376,8 @@ static void nvme_ns_head_submit_bio(struct bio *bio) * pool from the original queue to allocate the bvecs from. */ bio = bio_split_to_limits(bio); + if (!bio) + return; srcu_idx = srcu_read_lock(&head->srcu); ns = nvme_find_path(head); diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index b13baccedb4a..c734934c407c 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -1362,7 +1362,7 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req) else nvme_poll_irqdisable(nvmeq); - if (blk_mq_request_completed(req)) { + if (blk_mq_rq_state(req) != MQ_RQ_IN_FLIGHT) { dev_warn(dev->ctrl.device, "I/O %d QID %d timeout, completion polled\n", req->tag, nvmeq->qid); @@ -2533,7 +2533,7 @@ static int nvme_pci_enable(struct nvme_dev *dev) */ result = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); if (result < 0) - return result; + goto disable; dev->ctrl.cap = lo_hi_readq(dev->bar + NVME_REG_CAP); @@ -2586,8 +2586,13 @@ static int nvme_pci_enable(struct nvme_dev *dev) pci_enable_pcie_error_reporting(pdev); pci_save_state(pdev); - return nvme_pci_configure_admin_queue(dev); + result = nvme_pci_configure_admin_queue(dev); + if (result) + goto free_irq; + return result; + free_irq: + pci_free_irq_vectors(pdev); disable: pci_disable_device(pdev); return result; @@ -3097,6 +3102,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) nvme_start_ctrl(&dev->ctrl); nvme_put_ctrl(&dev->ctrl); + flush_work(&dev->ctrl.scan_work); return 0; out_disable: @@ -3495,7 +3501,8 @@ static const struct pci_device_id nvme_id_table[] = { .driver_data = NVME_QUIRK_SINGLE_VECTOR | NVME_QUIRK_128_BYTES_SQES | NVME_QUIRK_SHARED_TAGS | - NVME_QUIRK_SKIP_CID_GEN }, + NVME_QUIRK_SKIP_CID_GEN | + NVME_QUIRK_IDENTIFY_CNS }, { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) }, { 0, } }; diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index b2272bccf85c..f08b25195ae7 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -1099,7 +1099,7 @@ u64 __init dt_mem_next_cell(int s, const __be32 **cellp) */ int __init early_init_dt_scan_memory(void) { - int node; + int node, found_memory = 0; const void *fdt = initial_boot_params; fdt_for_each_subnode(node, fdt, 0) { @@ -1139,6 +1139,8 @@ int __init early_init_dt_scan_memory(void) early_init_dt_add_memory_arch(base, size); + found_memory = 1; + if (!hotpluggable) continue; @@ -1147,7 +1149,7 @@ int __init early_init_dt_scan_memory(void) base, base + size); } } - return 0; + return found_memory; } int __init early_init_dt_scan_chosen(char *cmdline) @@ -1161,18 +1163,14 @@ int __init early_init_dt_scan_chosen(char *cmdline) if (node < 0) node = fdt_path_offset(fdt, "/chosen@0"); if (node < 0) - return -ENOENT; + /* Handle the cmdline config options even if no /chosen node */ + goto handle_cmdline; chosen_node_offset = node; early_init_dt_check_for_initrd(node); early_init_dt_check_for_elfcorehdr(node); - /* Retrieve command line */ - p = of_get_flat_dt_prop(node, "bootargs", &l); - if (p != NULL && l > 0) - strscpy(cmdline, p, min(l, COMMAND_LINE_SIZE)); - rng_seed = of_get_flat_dt_prop(node, "rng-seed", &l); if (rng_seed && l > 0) { add_bootloader_randomness(rng_seed, l); @@ -1185,6 +1183,32 @@ int __init early_init_dt_scan_chosen(char *cmdline) fdt_totalsize(initial_boot_params)); } + /* Retrieve command line */ + p = of_get_flat_dt_prop(node, "bootargs", &l); + if (p != NULL && l > 0) + strscpy(cmdline, p, min(l, COMMAND_LINE_SIZE)); + +handle_cmdline: + /* + * CONFIG_CMDLINE is meant to be a default in case nothing else + * managed to set the command line, unless CONFIG_CMDLINE_FORCE + * is set in which case we override whatever was found earlier. + */ +#ifdef CONFIG_CMDLINE +#if defined(CONFIG_CMDLINE_EXTEND) + strlcat(cmdline, " ", COMMAND_LINE_SIZE); + strlcat(cmdline, CONFIG_CMDLINE, COMMAND_LINE_SIZE); +#elif defined(CONFIG_CMDLINE_FORCE) + strscpy(cmdline, CONFIG_CMDLINE, COMMAND_LINE_SIZE); +#else + /* No arguments from boot loader, use kernel's cmdl*/ + if (!((char *)cmdline)[0]) + strscpy(cmdline, CONFIG_CMDLINE, COMMAND_LINE_SIZE); +#endif +#endif /* CONFIG_CMDLINE */ + + pr_debug("Command line is: %s\n", (char *)cmdline); + return 0; } @@ -1277,26 +1301,6 @@ void __init early_init_dt_scan_nodes(void) if (rc) pr_warn("No chosen node found, continuing without\n"); - /* - * CONFIG_CMDLINE is meant to be a default in case nothing else - * managed to set the command line, unless CONFIG_CMDLINE_FORCE - * is set in which case we override whatever was found earlier. - */ -#ifdef CONFIG_CMDLINE -#if defined(CONFIG_CMDLINE_EXTEND) - strlcat(boot_command_line, " ", COMMAND_LINE_SIZE); - strlcat(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); -#elif defined(CONFIG_CMDLINE_FORCE) - strscpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); -#else - /* No arguments from boot loader, use kernel's cmdl */ - if (!boot_command_line[0]) - strscpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); -#endif -#endif /* CONFIG_CMDLINE */ - - pr_debug("Command line is: %s\n", boot_command_line); - /* Setup memory, calling early_init_dt_add_memory_arch */ early_init_dt_scan_memory(); diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig index a0d2713f0e88..99ec91e2a5cf 100644 --- a/drivers/pci/controller/dwc/Kconfig +++ b/drivers/pci/controller/dwc/Kconfig @@ -225,7 +225,7 @@ config PCIE_ARTPEC6_EP config PCIE_BT1 tristate "Baikal-T1 PCIe controller" depends on MIPS_BAIKAL_T1 || COMPILE_TEST - depends on PCI_MSI_IRQ_DOMAIN + depends on PCI_MSI select PCIE_DW_HOST help Enables support for the PCIe controller in the Baikal-T1 SoC to work diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c index 7378e2f3e525..fcd029ca2eb1 100644 --- a/drivers/pci/xen-pcifront.c +++ b/drivers/pci/xen-pcifront.c @@ -1055,14 +1055,12 @@ out: return err; } -static int pcifront_xenbus_remove(struct xenbus_device *xdev) +static void pcifront_xenbus_remove(struct xenbus_device *xdev) { struct pcifront_device *pdev = dev_get_drvdata(&xdev->dev); if (pdev) free_pdev(pdev); - - return 0; } static const struct xenbus_device_id xenpci_ids[] = { diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c index b80a9b74662b..1deb61b22bc7 100644 --- a/drivers/perf/arm-cmn.c +++ b/drivers/perf/arm-cmn.c @@ -1576,7 +1576,6 @@ static int arm_cmn_event_init(struct perf_event *event) hw->dn++; continue; } - hw->dtcs_used |= arm_cmn_node_to_xp(cmn, dn)->dtc; hw->num_dns++; if (bynodeid) break; @@ -1589,6 +1588,12 @@ static int arm_cmn_event_init(struct perf_event *event) nodeid, nid.x, nid.y, nid.port, nid.dev, type); return -EINVAL; } + /* + * Keep assuming non-cycles events count in all DTC domains; turns out + * it's hard to make a worthwhile optimisation around this, short of + * going all-in with domain-local counter allocation as well. + */ + hw->dtcs_used = (1U << cmn->num_dtcs) - 1; return arm_cmn_validate_group(cmn, event); } diff --git a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c index 7585e8080b77..afc63552ecaf 100644 --- a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c +++ b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c @@ -255,7 +255,7 @@ static int imx8_pcie_phy_probe(struct platform_device *pdev) imx8_phy->perst = devm_reset_control_get_exclusive(dev, "perst"); if (IS_ERR(imx8_phy->perst)) - dev_err_probe(dev, PTR_ERR(imx8_phy->perst), + return dev_err_probe(dev, PTR_ERR(imx8_phy->perst), "Failed to get PCIE PHY PERST control\n"); } diff --git a/drivers/phy/phy-can-transceiver.c b/drivers/phy/phy-can-transceiver.c index 95c6dbb52da7..ce511ad5d369 100644 --- a/drivers/phy/phy-can-transceiver.c +++ b/drivers/phy/phy-can-transceiver.c @@ -99,6 +99,7 @@ static int can_transceiver_phy_probe(struct platform_device *pdev) struct gpio_desc *standby_gpio; struct gpio_desc *enable_gpio; u32 max_bitrate = 0; + int err; can_transceiver_phy = devm_kzalloc(dev, sizeof(struct can_transceiver_phy), GFP_KERNEL); if (!can_transceiver_phy) @@ -124,8 +125,8 @@ static int can_transceiver_phy_probe(struct platform_device *pdev) return PTR_ERR(phy); } - device_property_read_u32(dev, "max-bitrate", &max_bitrate); - if (!max_bitrate) + err = device_property_read_u32(dev, "max-bitrate", &max_bitrate); + if ((err != -EINVAL) && !max_bitrate) dev_warn(dev, "Invalid value for transceiver max bitrate. Ignoring bitrate limit\n"); phy->attrs.max_link_rate = max_bitrate; diff --git a/drivers/phy/qualcomm/phy-qcom-usb-hs-28nm.c b/drivers/phy/qualcomm/phy-qcom-usb-hs-28nm.c index 8807e59a1162..a52a9bf13b75 100644 --- a/drivers/phy/qualcomm/phy-qcom-usb-hs-28nm.c +++ b/drivers/phy/qualcomm/phy-qcom-usb-hs-28nm.c @@ -401,26 +401,13 @@ static const struct hsphy_init_seq init_seq_femtophy[] = { HSPHY_INIT_CFG(0x90, 0x60, 0), }; -static const struct hsphy_init_seq init_seq_mdm9607[] = { - HSPHY_INIT_CFG(0x80, 0x44, 0), - HSPHY_INIT_CFG(0x81, 0x38, 0), - HSPHY_INIT_CFG(0x82, 0x24, 0), - HSPHY_INIT_CFG(0x83, 0x13, 0), -}; - static const struct hsphy_data hsphy_data_femtophy = { .init_seq = init_seq_femtophy, .init_seq_num = ARRAY_SIZE(init_seq_femtophy), }; -static const struct hsphy_data hsphy_data_mdm9607 = { - .init_seq = init_seq_mdm9607, - .init_seq_num = ARRAY_SIZE(init_seq_mdm9607), -}; - static const struct of_device_id qcom_snps_hsphy_match[] = { { .compatible = "qcom,usb-hs-28nm-femtophy", .data = &hsphy_data_femtophy, }, - { .compatible = "qcom,usb-hs-28nm-mdm9607", .data = &hsphy_data_mdm9607, }, { }, }; MODULE_DEVICE_TABLE(of, qcom_snps_hsphy_match); diff --git a/drivers/phy/renesas/r8a779f0-ether-serdes.c b/drivers/phy/renesas/r8a779f0-ether-serdes.c index ec6594e6dc27..e7588a940d69 100644 --- a/drivers/phy/renesas/r8a779f0-ether-serdes.c +++ b/drivers/phy/renesas/r8a779f0-ether-serdes.c @@ -126,7 +126,7 @@ r8a779f0_eth_serdes_chan_setting(struct r8a779f0_eth_serdes_channel *channel) r8a779f0_eth_serdes_write32(channel->addr, 0x0160, 0x180, 0x0007); r8a779f0_eth_serdes_write32(channel->addr, 0x01ac, 0x180, 0x0000); r8a779f0_eth_serdes_write32(channel->addr, 0x00c4, 0x180, 0x0310); - r8a779f0_eth_serdes_write32(channel->addr, 0x00c8, 0x380, 0x0101); + r8a779f0_eth_serdes_write32(channel->addr, 0x00c8, 0x180, 0x0101); ret = r8a779f0_eth_serdes_reg_wait(channel, 0x00c8, 0x0180, BIT(0), 0); if (ret) return ret; diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c index e6ededc51523..a0bc10aa7961 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c @@ -485,8 +485,10 @@ static int rockchip_usb2phy_power_on(struct phy *phy) return ret; ret = property_enable(base, &rport->port_cfg->phy_sus, false); - if (ret) + if (ret) { + clk_disable_unprepare(rphy->clk480m); return ret; + } /* waiting for the utmi_clk to become stable */ usleep_range(1500, 2000); diff --git a/drivers/phy/sunplus/phy-sunplus-usb2.c b/drivers/phy/sunplus/phy-sunplus-usb2.c index e827b79f6d49..56de41091d63 100644 --- a/drivers/phy/sunplus/phy-sunplus-usb2.c +++ b/drivers/phy/sunplus/phy-sunplus-usb2.c @@ -254,6 +254,9 @@ static int sp_usb_phy_probe(struct platform_device *pdev) return PTR_ERR(usbphy->phy_regs); usbphy->moon4_res_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "moon4"); + if (!usbphy->moon4_res_mem) + return -EINVAL; + usbphy->moon4_regs = devm_ioremap(&pdev->dev, usbphy->moon4_res_mem->start, resource_size(usbphy->moon4_res_mem)); if (!usbphy->moon4_regs) diff --git a/drivers/phy/ti/Kconfig b/drivers/phy/ti/Kconfig index 15a3bcf32308..b905902d5750 100644 --- a/drivers/phy/ti/Kconfig +++ b/drivers/phy/ti/Kconfig @@ -23,7 +23,7 @@ config PHY_DM816X_USB config PHY_AM654_SERDES tristate "TI AM654 SERDES support" - depends on OF && ARCH_K3 || COMPILE_TEST + depends on OF && (ARCH_K3 || COMPILE_TEST) depends on COMMON_CLK select GENERIC_PHY select MULTIPLEXER @@ -35,7 +35,7 @@ config PHY_AM654_SERDES config PHY_J721E_WIZ tristate "TI J721E WIZ (SERDES Wrapper) support" - depends on OF && ARCH_K3 || COMPILE_TEST + depends on OF && (ARCH_K3 || COMPILE_TEST) depends on HAS_IOMEM && OF_ADDRESS depends on COMMON_CLK select GENERIC_PHY diff --git a/drivers/pinctrl/nomadik/pinctrl-ab8500.c b/drivers/pinctrl/nomadik/pinctrl-ab8500.c index 3106a21cd277..d7b244df058f 100644 --- a/drivers/pinctrl/nomadik/pinctrl-ab8500.c +++ b/drivers/pinctrl/nomadik/pinctrl-ab8500.c @@ -6,9 +6,10 @@ */ #include <linux/kernel.h> -#include <linux/gpio/driver.h> #include <linux/pinctrl/pinctrl.h> + #include <linux/mfd/abx500/ab8500.h> + #include "pinctrl-abx500.h" /* All the pins that can be used for GPIO and some other functions */ diff --git a/drivers/pinctrl/nomadik/pinctrl-ab8505.c b/drivers/pinctrl/nomadik/pinctrl-ab8505.c index b93af1fb37f0..45aa958b573e 100644 --- a/drivers/pinctrl/nomadik/pinctrl-ab8505.c +++ b/drivers/pinctrl/nomadik/pinctrl-ab8505.c @@ -6,9 +6,10 @@ */ #include <linux/kernel.h> -#include <linux/gpio/driver.h> #include <linux/pinctrl/pinctrl.h> + #include <linux/mfd/abx500/ab8500.h> + #include "pinctrl-abx500.h" /* All the pins that can be used for GPIO and some other functions */ diff --git a/drivers/pinctrl/nomadik/pinctrl-abx500.c b/drivers/pinctrl/nomadik/pinctrl-abx500.c index 7aa534576a45..28c3403df1b0 100644 --- a/drivers/pinctrl/nomadik/pinctrl-abx500.c +++ b/drivers/pinctrl/nomadik/pinctrl-abx500.c @@ -6,33 +6,37 @@ * * Driver allows to use AxB5xx unused pins to be used as GPIO */ -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/slab.h> -#include <linux/init.h> +#include <linux/bitops.h> #include <linux/err.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/platform_device.h> #include <linux/gpio/driver.h> +#include <linux/init.h> +#include <linux/interrupt.h> #include <linux/irq.h> #include <linux/irqdomain.h> -#include <linux/interrupt.h> -#include <linux/bitops.h> +#include <linux/kernel.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/seq_file.h> +#include <linux/slab.h> +#include <linux/types.h> + #include <linux/mfd/abx500.h> #include <linux/mfd/abx500/ab8500.h> -#include <linux/pinctrl/pinctrl.h> + #include <linux/pinctrl/consumer.h> -#include <linux/pinctrl/pinmux.h> -#include <linux/pinctrl/pinconf.h> -#include <linux/pinctrl/pinconf-generic.h> #include <linux/pinctrl/machine.h> +#include <linux/pinctrl/pinconf-generic.h> +#include <linux/pinctrl/pinconf.h> +#include <linux/pinctrl/pinctrl.h> +#include <linux/pinctrl/pinmux.h> -#include "pinctrl-abx500.h" #include "../core.h" #include "../pinconf.h" #include "../pinctrl-utils.h" +#include "pinctrl-abx500.h" + /* * GPIO registers offset * Bank: 0x10 diff --git a/drivers/pinctrl/nomadik/pinctrl-abx500.h b/drivers/pinctrl/nomadik/pinctrl-abx500.h index 90bb12fe8073..d67522084675 100644 --- a/drivers/pinctrl/nomadik/pinctrl-abx500.h +++ b/drivers/pinctrl/nomadik/pinctrl-abx500.h @@ -2,6 +2,10 @@ #ifndef PINCTRL_PINCTRL_ABx500_H #define PINCTRL_PINCTRL_ABx500_H +#include <linux/types.h> + +struct pinctrl_pin_desc; + /* Package definitions */ #define PINCTRL_AB8500 0 #define PINCTRL_AB8505 1 diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c b/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c index 758d21f0a850..490e0959e8be 100644 --- a/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c @@ -1,6 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 #include <linux/kernel.h> +#include <linux/types.h> + #include <linux/pinctrl/pinctrl.h> + #include "pinctrl-nomadik.h" /* All the pins that can be used for GPIO and some other functions */ diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c b/drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c index c0d7c86d0939..1552222ac68e 100644 --- a/drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c @@ -1,6 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 #include <linux/kernel.h> +#include <linux/types.h> + #include <linux/pinctrl/pinctrl.h> + #include "pinctrl-nomadik.h" /* All the pins that can be used for GPIO and some other functions */ diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik.c b/drivers/pinctrl/nomadik/pinctrl-nomadik.c index f7d02513d8cc..86a638077a69 100644 --- a/drivers/pinctrl/nomadik/pinctrl-nomadik.c +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.c @@ -7,30 +7,34 @@ * Rewritten based on work by Prafulla WADASKAR <prafulla.wadaskar@st.com> * Copyright (C) 2011-2013 Linus Walleij <linus.walleij@linaro.org> */ -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/device.h> -#include <linux/platform_device.h> -#include <linux/io.h> +#include <linux/bitops.h> #include <linux/clk.h> +#include <linux/device.h> #include <linux/err.h> #include <linux/gpio/driver.h> -#include <linux/spinlock.h> +#include <linux/init.h> #include <linux/interrupt.h> -#include <linux/slab.h> -#include <linux/of_device.h> +#include <linux/io.h> +#include <linux/kernel.h> #include <linux/of_address.h> -#include <linux/bitops.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/seq_file.h> +#include <linux/slab.h> +#include <linux/spinlock.h> + +/* Since we request GPIOs from ourself */ +#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/machine.h> +#include <linux/pinctrl/pinconf.h> #include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinmux.h> -#include <linux/pinctrl/pinconf.h> -/* Since we request GPIOs from ourself */ -#include <linux/pinctrl/consumer.h> -#include "pinctrl-nomadik.h" + #include "../core.h" #include "../pinctrl-utils.h" +#include "pinctrl-nomadik.h" + /* * The GPIO module in the Nomadik family of Systems-on-Chip is an * AMBA device, managing 32 pins and alternate functions. The logic block @@ -907,8 +911,6 @@ static int nmk_gpio_get_mode(struct nmk_gpio_chip *nmk_chip, int offset) return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0); } -#include <linux/seq_file.h> - static void nmk_gpio_dbg_show_one(struct seq_file *s, struct pinctrl_dev *pctldev, struct gpio_chip *chip, unsigned offset, unsigned gpio) diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik.h b/drivers/pinctrl/nomadik/pinctrl-nomadik.h index 84e297757335..1ef2559bc571 100644 --- a/drivers/pinctrl/nomadik/pinctrl-nomadik.h +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.h @@ -2,6 +2,11 @@ #ifndef PINCTRL_PINCTRL_NOMADIK_H #define PINCTRL_PINCTRL_NOMADIK_H +#include <linux/kernel.h> +#include <linux/types.h> + +#include <linux/pinctrl/pinctrl.h> + /* Package definitions */ #define PINCTRL_NMK_STN8815 0 #define PINCTRL_NMK_DB8500 1 diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index da974ff2d75d..5eeac92f610a 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -926,19 +926,19 @@ static struct rockchip_mux_route_data rk3568_mux_route_data[] = { RK_MUXROUTE_PMU(0, RK_PB5, 4, 0x0110, WRITE_MASK_VAL(3, 2, 1)), /* PWM1 IO mux M1 */ RK_MUXROUTE_PMU(0, RK_PC1, 1, 0x0110, WRITE_MASK_VAL(5, 4, 0)), /* PWM2 IO mux M0 */ RK_MUXROUTE_PMU(0, RK_PB6, 4, 0x0110, WRITE_MASK_VAL(5, 4, 1)), /* PWM2 IO mux M1 */ - RK_MUXROUTE_PMU(0, RK_PB3, 2, 0x0300, WRITE_MASK_VAL(0, 0, 0)), /* CAN0 IO mux M0 */ + RK_MUXROUTE_GRF(0, RK_PB3, 2, 0x0300, WRITE_MASK_VAL(0, 0, 0)), /* CAN0 IO mux M0 */ RK_MUXROUTE_GRF(2, RK_PA1, 4, 0x0300, WRITE_MASK_VAL(0, 0, 1)), /* CAN0 IO mux M1 */ RK_MUXROUTE_GRF(1, RK_PA1, 3, 0x0300, WRITE_MASK_VAL(2, 2, 0)), /* CAN1 IO mux M0 */ RK_MUXROUTE_GRF(4, RK_PC3, 3, 0x0300, WRITE_MASK_VAL(2, 2, 1)), /* CAN1 IO mux M1 */ RK_MUXROUTE_GRF(4, RK_PB5, 3, 0x0300, WRITE_MASK_VAL(4, 4, 0)), /* CAN2 IO mux M0 */ RK_MUXROUTE_GRF(2, RK_PB2, 4, 0x0300, WRITE_MASK_VAL(4, 4, 1)), /* CAN2 IO mux M1 */ RK_MUXROUTE_GRF(4, RK_PC4, 1, 0x0300, WRITE_MASK_VAL(6, 6, 0)), /* HPDIN IO mux M0 */ - RK_MUXROUTE_PMU(0, RK_PC2, 2, 0x0300, WRITE_MASK_VAL(6, 6, 1)), /* HPDIN IO mux M1 */ + RK_MUXROUTE_GRF(0, RK_PC2, 2, 0x0300, WRITE_MASK_VAL(6, 6, 1)), /* HPDIN IO mux M1 */ RK_MUXROUTE_GRF(3, RK_PB1, 3, 0x0300, WRITE_MASK_VAL(8, 8, 0)), /* GMAC1 IO mux M0 */ RK_MUXROUTE_GRF(4, RK_PA7, 3, 0x0300, WRITE_MASK_VAL(8, 8, 1)), /* GMAC1 IO mux M1 */ RK_MUXROUTE_GRF(4, RK_PD1, 1, 0x0300, WRITE_MASK_VAL(10, 10, 0)), /* HDMITX IO mux M0 */ - RK_MUXROUTE_PMU(0, RK_PC7, 1, 0x0300, WRITE_MASK_VAL(10, 10, 1)), /* HDMITX IO mux M1 */ - RK_MUXROUTE_PMU(0, RK_PB6, 1, 0x0300, WRITE_MASK_VAL(14, 14, 0)), /* I2C2 IO mux M0 */ + RK_MUXROUTE_GRF(0, RK_PC7, 1, 0x0300, WRITE_MASK_VAL(10, 10, 1)), /* HDMITX IO mux M1 */ + RK_MUXROUTE_GRF(0, RK_PB6, 1, 0x0300, WRITE_MASK_VAL(14, 14, 0)), /* I2C2 IO mux M0 */ RK_MUXROUTE_GRF(4, RK_PB4, 1, 0x0300, WRITE_MASK_VAL(14, 14, 1)), /* I2C2 IO mux M1 */ RK_MUXROUTE_GRF(1, RK_PA0, 1, 0x0304, WRITE_MASK_VAL(0, 0, 0)), /* I2C3 IO mux M0 */ RK_MUXROUTE_GRF(3, RK_PB6, 4, 0x0304, WRITE_MASK_VAL(0, 0, 1)), /* I2C3 IO mux M1 */ @@ -964,7 +964,7 @@ static struct rockchip_mux_route_data rk3568_mux_route_data[] = { RK_MUXROUTE_GRF(4, RK_PC3, 1, 0x0308, WRITE_MASK_VAL(12, 12, 1)), /* PWM15 IO mux M1 */ RK_MUXROUTE_GRF(3, RK_PD2, 3, 0x0308, WRITE_MASK_VAL(14, 14, 0)), /* SDMMC2 IO mux M0 */ RK_MUXROUTE_GRF(3, RK_PA5, 5, 0x0308, WRITE_MASK_VAL(14, 14, 1)), /* SDMMC2 IO mux M1 */ - RK_MUXROUTE_PMU(0, RK_PB5, 2, 0x030c, WRITE_MASK_VAL(0, 0, 0)), /* SPI0 IO mux M0 */ + RK_MUXROUTE_GRF(0, RK_PB5, 2, 0x030c, WRITE_MASK_VAL(0, 0, 0)), /* SPI0 IO mux M0 */ RK_MUXROUTE_GRF(2, RK_PD3, 3, 0x030c, WRITE_MASK_VAL(0, 0, 1)), /* SPI0 IO mux M1 */ RK_MUXROUTE_GRF(2, RK_PB5, 3, 0x030c, WRITE_MASK_VAL(2, 2, 0)), /* SPI1 IO mux M0 */ RK_MUXROUTE_GRF(3, RK_PC3, 3, 0x030c, WRITE_MASK_VAL(2, 2, 1)), /* SPI1 IO mux M1 */ @@ -973,8 +973,8 @@ static struct rockchip_mux_route_data rk3568_mux_route_data[] = { RK_MUXROUTE_GRF(4, RK_PB3, 4, 0x030c, WRITE_MASK_VAL(6, 6, 0)), /* SPI3 IO mux M0 */ RK_MUXROUTE_GRF(4, RK_PC2, 2, 0x030c, WRITE_MASK_VAL(6, 6, 1)), /* SPI3 IO mux M1 */ RK_MUXROUTE_GRF(2, RK_PB4, 2, 0x030c, WRITE_MASK_VAL(8, 8, 0)), /* UART1 IO mux M0 */ - RK_MUXROUTE_PMU(0, RK_PD1, 1, 0x030c, WRITE_MASK_VAL(8, 8, 1)), /* UART1 IO mux M1 */ - RK_MUXROUTE_PMU(0, RK_PD1, 1, 0x030c, WRITE_MASK_VAL(10, 10, 0)), /* UART2 IO mux M0 */ + RK_MUXROUTE_GRF(3, RK_PD6, 4, 0x030c, WRITE_MASK_VAL(8, 8, 1)), /* UART1 IO mux M1 */ + RK_MUXROUTE_GRF(0, RK_PD1, 1, 0x030c, WRITE_MASK_VAL(10, 10, 0)), /* UART2 IO mux M0 */ RK_MUXROUTE_GRF(1, RK_PD5, 2, 0x030c, WRITE_MASK_VAL(10, 10, 1)), /* UART2 IO mux M1 */ RK_MUXROUTE_GRF(1, RK_PA1, 2, 0x030c, WRITE_MASK_VAL(12, 12, 0)), /* UART3 IO mux M0 */ RK_MUXROUTE_GRF(3, RK_PB7, 4, 0x030c, WRITE_MASK_VAL(12, 12, 1)), /* UART3 IO mux M1 */ @@ -1004,13 +1004,13 @@ static struct rockchip_mux_route_data rk3568_mux_route_data[] = { RK_MUXROUTE_GRF(3, RK_PD6, 5, 0x0314, WRITE_MASK_VAL(1, 0, 1)), /* PDM IO mux M1 */ RK_MUXROUTE_GRF(4, RK_PA0, 4, 0x0314, WRITE_MASK_VAL(1, 0, 1)), /* PDM IO mux M1 */ RK_MUXROUTE_GRF(3, RK_PC4, 5, 0x0314, WRITE_MASK_VAL(1, 0, 2)), /* PDM IO mux M2 */ - RK_MUXROUTE_PMU(0, RK_PA5, 3, 0x0314, WRITE_MASK_VAL(3, 2, 0)), /* PCIE20 IO mux M0 */ + RK_MUXROUTE_GRF(0, RK_PA5, 3, 0x0314, WRITE_MASK_VAL(3, 2, 0)), /* PCIE20 IO mux M0 */ RK_MUXROUTE_GRF(2, RK_PD0, 4, 0x0314, WRITE_MASK_VAL(3, 2, 1)), /* PCIE20 IO mux M1 */ RK_MUXROUTE_GRF(1, RK_PB0, 4, 0x0314, WRITE_MASK_VAL(3, 2, 2)), /* PCIE20 IO mux M2 */ - RK_MUXROUTE_PMU(0, RK_PA4, 3, 0x0314, WRITE_MASK_VAL(5, 4, 0)), /* PCIE30X1 IO mux M0 */ + RK_MUXROUTE_GRF(0, RK_PA4, 3, 0x0314, WRITE_MASK_VAL(5, 4, 0)), /* PCIE30X1 IO mux M0 */ RK_MUXROUTE_GRF(2, RK_PD2, 4, 0x0314, WRITE_MASK_VAL(5, 4, 1)), /* PCIE30X1 IO mux M1 */ RK_MUXROUTE_GRF(1, RK_PA5, 4, 0x0314, WRITE_MASK_VAL(5, 4, 2)), /* PCIE30X1 IO mux M2 */ - RK_MUXROUTE_PMU(0, RK_PA6, 2, 0x0314, WRITE_MASK_VAL(7, 6, 0)), /* PCIE30X2 IO mux M0 */ + RK_MUXROUTE_GRF(0, RK_PA6, 2, 0x0314, WRITE_MASK_VAL(7, 6, 0)), /* PCIE30X2 IO mux M0 */ RK_MUXROUTE_GRF(2, RK_PD4, 4, 0x0314, WRITE_MASK_VAL(7, 6, 1)), /* PCIE30X2 IO mux M1 */ RK_MUXROUTE_GRF(4, RK_PC2, 4, 0x0314, WRITE_MASK_VAL(7, 6, 2)), /* PCIE30X2 IO mux M2 */ }; @@ -2436,10 +2436,19 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num) case RK3308: case RK3368: case RK3399: + case RK3568: case RK3588: pull_type = bank->pull_type[pin_num / 8]; data >>= bit; data &= (1 << RK3188_PULL_BITS_PER_PIN) - 1; + /* + * In the TRM, pull-up being 1 for everything except the GPIO0_D3-D6, + * where that pull up value becomes 3. + */ + if (ctrl->type == RK3568 && bank->bank_num == 0 && pin_num >= 27 && pin_num <= 30) { + if (data == 3) + data = 1; + } return rockchip_pull_list[pull_type][data]; default: @@ -2497,7 +2506,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank, } } /* - * In the TRM, pull-up being 1 for everything except the GPIO0_D0-D6, + * In the TRM, pull-up being 1 for everything except the GPIO0_D3-D6, * where that pull up value becomes 3. */ if (ctrl->type == RK3568 && bank->bank_num == 0 && pin_num >= 27 && pin_num <= 30) { diff --git a/drivers/pinctrl/sunplus/sppctl.c b/drivers/pinctrl/sunplus/sppctl.c index 2b3335ab56c6..25101293268f 100644 --- a/drivers/pinctrl/sunplus/sppctl.c +++ b/drivers/pinctrl/sunplus/sppctl.c @@ -499,7 +499,6 @@ static int sppctl_gpio_set_config(struct gpio_chip *chip, unsigned int offset, return 0; } -#ifdef CONFIG_DEBUG_FS static void sppctl_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) { const char *label; @@ -521,7 +520,6 @@ static void sppctl_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) seq_puts(s, "\n"); } } -#endif static int sppctl_gpio_new(struct platform_device *pdev, struct sppctl_pdata *pctl) { @@ -550,9 +548,8 @@ static int sppctl_gpio_new(struct platform_device *pdev, struct sppctl_pdata *pc gchip->get = sppctl_gpio_get; gchip->set = sppctl_gpio_set; gchip->set_config = sppctl_gpio_set_config; -#ifdef CONFIG_DEBUG_FS - gchip->dbg_show = sppctl_gpio_dbg_show; -#endif + gchip->dbg_show = IS_ENABLED(CONFIG_DEBUG_FS) ? + sppctl_gpio_dbg_show : NULL; gchip->base = -1; gchip->ngpio = sppctl_gpio_list_sz; gchip->names = sppctl_gpio_list_s; diff --git a/drivers/platform/surface/aggregator/controller.c b/drivers/platform/surface/aggregator/controller.c index 43e765199137..c6537a1b3a2e 100644 --- a/drivers/platform/surface/aggregator/controller.c +++ b/drivers/platform/surface/aggregator/controller.c @@ -1700,8 +1700,10 @@ int ssam_request_sync(struct ssam_controller *ctrl, return status; status = ssam_request_sync_init(rqst, spec->flags); - if (status) + if (status) { + ssam_request_sync_free(rqst); return status; + } ssam_request_sync_set_resp(rqst, rsp); diff --git a/drivers/platform/surface/aggregator/ssh_request_layer.c b/drivers/platform/surface/aggregator/ssh_request_layer.c index f5565570f16c..69132976d297 100644 --- a/drivers/platform/surface/aggregator/ssh_request_layer.c +++ b/drivers/platform/surface/aggregator/ssh_request_layer.c @@ -916,6 +916,20 @@ static void ssh_rtl_rx_command(struct ssh_ptl *p, const struct ssam_span *data) if (sshp_parse_command(dev, data, &command, &command_data)) return; + /* + * Check if the message was intended for us. If not, drop it. + * + * Note: We will need to change this to handle debug messages. On newer + * generation devices, these seem to be sent to tid_out=0x03. We as + * host can still receive them as they can be forwarded via an override + * option on SAM, but doing so does not change tid_out=0x00. + */ + if (command->tid_out != 0x00) { + rtl_warn(rtl, "rtl: dropping message not intended for us (tid = %#04x)\n", + command->tid_out); + return; + } + if (ssh_rqid_is_event(get_unaligned_le16(&command->rqid))) ssh_rtl_rx_event(rtl, command, &command_data); else diff --git a/drivers/platform/x86/amd/pmc.c b/drivers/platform/x86/amd/pmc.c index 439d282aafd1..3cbb01ec10e3 100644 --- a/drivers/platform/x86/amd/pmc.c +++ b/drivers/platform/x86/amd/pmc.c @@ -22,6 +22,7 @@ #include <linux/pci.h> #include <linux/platform_device.h> #include <linux/rtc.h> +#include <linux/serio.h> #include <linux/suspend.h> #include <linux/seq_file.h> #include <linux/uaccess.h> @@ -160,6 +161,10 @@ static bool enable_stb; module_param(enable_stb, bool, 0644); MODULE_PARM_DESC(enable_stb, "Enable the STB debug mechanism"); +static bool disable_workarounds; +module_param(disable_workarounds, bool, 0644); +MODULE_PARM_DESC(disable_workarounds, "Disable workarounds for platform bugs"); + static struct amd_pmc_dev pmc; static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, u32 arg, u32 *data, u8 msg, bool ret); static int amd_pmc_read_stb(struct amd_pmc_dev *dev, u32 *buf); @@ -653,6 +658,33 @@ static int amd_pmc_get_os_hint(struct amd_pmc_dev *dev) return -EINVAL; } +static int amd_pmc_czn_wa_irq1(struct amd_pmc_dev *pdev) +{ + struct device *d; + int rc; + + if (!pdev->major) { + rc = amd_pmc_get_smu_version(pdev); + if (rc) + return rc; + } + + if (pdev->major > 64 || (pdev->major == 64 && pdev->minor > 65)) + return 0; + + d = bus_find_device_by_name(&serio_bus, NULL, "serio0"); + if (!d) + return 0; + if (device_may_wakeup(d)) { + dev_info_once(d, "Disabling IRQ1 wakeup source to avoid platform firmware bug\n"); + disable_irq_wake(1); + device_set_wakeup_enable(d, false); + } + put_device(d); + + return 0; +} + static int amd_pmc_verify_czn_rtc(struct amd_pmc_dev *pdev, u32 *arg) { struct rtc_device *rtc_device; @@ -715,8 +747,8 @@ static void amd_pmc_s2idle_prepare(void) /* Reset and Start SMU logging - to monitor the s0i3 stats */ amd_pmc_setup_smu_logging(pdev); - /* Activate CZN specific RTC functionality */ - if (pdev->cpu_id == AMD_CPU_ID_CZN) { + /* Activate CZN specific platform bug workarounds */ + if (pdev->cpu_id == AMD_CPU_ID_CZN && !disable_workarounds) { rc = amd_pmc_verify_czn_rtc(pdev, &arg); if (rc) { dev_err(pdev->dev, "failed to set RTC: %d\n", rc); @@ -782,6 +814,25 @@ static struct acpi_s2idle_dev_ops amd_pmc_s2idle_dev_ops = { .check = amd_pmc_s2idle_check, .restore = amd_pmc_s2idle_restore, }; + +static int __maybe_unused amd_pmc_suspend_handler(struct device *dev) +{ + struct amd_pmc_dev *pdev = dev_get_drvdata(dev); + + if (pdev->cpu_id == AMD_CPU_ID_CZN && !disable_workarounds) { + int rc = amd_pmc_czn_wa_irq1(pdev); + + if (rc) { + dev_err(pdev->dev, "failed to adjust keyboard wakeup: %d\n", rc); + return rc; + } + } + + return 0; +} + +static SIMPLE_DEV_PM_OPS(amd_pmc_pm, amd_pmc_suspend_handler, NULL); + #endif static const struct pci_device_id pmc_pci_ids[] = { @@ -932,7 +983,7 @@ static int amd_pmc_probe(struct platform_device *pdev) if (enable_stb && (dev->cpu_id == AMD_CPU_ID_YC || dev->cpu_id == AMD_CPU_ID_CB)) { err = amd_pmc_s2d_init(dev); if (err) - return err; + goto err_pci_dev_put; } platform_set_drvdata(pdev, dev); @@ -980,6 +1031,9 @@ static struct platform_driver amd_pmc_driver = { .name = "amd_pmc", .acpi_match_table = amd_pmc_acpi_ids, .dev_groups = pmc_groups, +#ifdef CONFIG_SUSPEND + .pm = &amd_pmc_pm, +#endif }, .probe = amd_pmc_probe, .remove = amd_pmc_remove, diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index ca33df7ea550..9333f82cfa8a 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -64,29 +64,6 @@ struct apple_gmux_data { static struct apple_gmux_data *apple_gmux_data; -/* - * gmux port offsets. Many of these are not yet used, but may be in the - * future, and it's useful to have them documented here anyhow. - */ -#define GMUX_PORT_VERSION_MAJOR 0x04 -#define GMUX_PORT_VERSION_MINOR 0x05 -#define GMUX_PORT_VERSION_RELEASE 0x06 -#define GMUX_PORT_SWITCH_DISPLAY 0x10 -#define GMUX_PORT_SWITCH_GET_DISPLAY 0x11 -#define GMUX_PORT_INTERRUPT_ENABLE 0x14 -#define GMUX_PORT_INTERRUPT_STATUS 0x16 -#define GMUX_PORT_SWITCH_DDC 0x28 -#define GMUX_PORT_SWITCH_EXTERNAL 0x40 -#define GMUX_PORT_SWITCH_GET_EXTERNAL 0x41 -#define GMUX_PORT_DISCRETE_POWER 0x50 -#define GMUX_PORT_MAX_BRIGHTNESS 0x70 -#define GMUX_PORT_BRIGHTNESS 0x74 -#define GMUX_PORT_VALUE 0xc2 -#define GMUX_PORT_READ 0xd0 -#define GMUX_PORT_WRITE 0xd4 - -#define GMUX_MIN_IO_LEN (GMUX_PORT_BRIGHTNESS + 4) - #define GMUX_INTERRUPT_ENABLE 0xff #define GMUX_INTERRUPT_DISABLE 0x00 @@ -249,23 +226,6 @@ static void gmux_write32(struct apple_gmux_data *gmux_data, int port, gmux_pio_write32(gmux_data, port, val); } -static bool gmux_is_indexed(struct apple_gmux_data *gmux_data) -{ - u16 val; - - outb(0xaa, gmux_data->iostart + 0xcc); - outb(0x55, gmux_data->iostart + 0xcd); - outb(0x00, gmux_data->iostart + 0xce); - - val = inb(gmux_data->iostart + 0xcc) | - (inb(gmux_data->iostart + 0xcd) << 8); - - if (val == 0x55aa) - return true; - - return false; -} - /** * DOC: Backlight control * @@ -605,60 +565,43 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) int ret = -ENXIO; acpi_status status; unsigned long long gpe; + bool indexed = false; + u32 version; if (apple_gmux_data) return -EBUSY; + if (!apple_gmux_detect(pnp, &indexed)) { + pr_info("gmux device not present\n"); + return -ENODEV; + } + gmux_data = kzalloc(sizeof(*gmux_data), GFP_KERNEL); if (!gmux_data) return -ENOMEM; pnp_set_drvdata(pnp, gmux_data); res = pnp_get_resource(pnp, IORESOURCE_IO, 0); - if (!res) { - pr_err("Failed to find gmux I/O resource\n"); - goto err_free; - } - gmux_data->iostart = res->start; gmux_data->iolen = resource_size(res); - if (gmux_data->iolen < GMUX_MIN_IO_LEN) { - pr_err("gmux I/O region too small (%lu < %u)\n", - gmux_data->iolen, GMUX_MIN_IO_LEN); - goto err_free; - } - if (!request_region(gmux_data->iostart, gmux_data->iolen, "Apple gmux")) { pr_err("gmux I/O already in use\n"); goto err_free; } - /* - * Invalid version information may indicate either that the gmux - * device isn't present or that it's a new one that uses indexed - * io - */ - - ver_major = gmux_read8(gmux_data, GMUX_PORT_VERSION_MAJOR); - ver_minor = gmux_read8(gmux_data, GMUX_PORT_VERSION_MINOR); - ver_release = gmux_read8(gmux_data, GMUX_PORT_VERSION_RELEASE); - if (ver_major == 0xff && ver_minor == 0xff && ver_release == 0xff) { - if (gmux_is_indexed(gmux_data)) { - u32 version; - mutex_init(&gmux_data->index_lock); - gmux_data->indexed = true; - version = gmux_read32(gmux_data, - GMUX_PORT_VERSION_MAJOR); - ver_major = (version >> 24) & 0xff; - ver_minor = (version >> 16) & 0xff; - ver_release = (version >> 8) & 0xff; - } else { - pr_info("gmux device not present\n"); - ret = -ENODEV; - goto err_release; - } + if (indexed) { + mutex_init(&gmux_data->index_lock); + gmux_data->indexed = true; + version = gmux_read32(gmux_data, GMUX_PORT_VERSION_MAJOR); + ver_major = (version >> 24) & 0xff; + ver_minor = (version >> 16) & 0xff; + ver_release = (version >> 8) & 0xff; + } else { + ver_major = gmux_read8(gmux_data, GMUX_PORT_VERSION_MAJOR); + ver_minor = gmux_read8(gmux_data, GMUX_PORT_VERSION_MINOR); + ver_release = gmux_read8(gmux_data, GMUX_PORT_VERSION_RELEASE); } pr_info("Found gmux version %d.%d.%d [%s]\n", ver_major, ver_minor, ver_release, (gmux_data->indexed ? "indexed" : "classic")); diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index c685a705b73d..cb15acdf14a3 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -121,6 +121,10 @@ static struct quirk_entry quirk_asus_tablet_mode = { .tablet_switch_mode = asus_wmi_lid_flip_rog_devid, }; +static struct quirk_entry quirk_asus_ignore_fan = { + .wmi_ignore_fan = true, +}; + static int dmi_matched(const struct dmi_system_id *dmi) { pr_info("Identified laptop model '%s'\n", dmi->ident); @@ -473,6 +477,15 @@ static const struct dmi_system_id asus_quirks[] = { }, .driver_data = &quirk_asus_tablet_mode, }, + { + .callback = dmi_matched, + .ident = "ASUS VivoBook E410MA", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "E410MA"), + }, + .driver_data = &quirk_asus_ignore_fan, + }, {}, }; @@ -511,6 +524,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = { { KE_KEY, 0x30, { KEY_VOLUMEUP } }, { KE_KEY, 0x31, { KEY_VOLUMEDOWN } }, { KE_KEY, 0x32, { KEY_MUTE } }, + { KE_KEY, 0x33, { KEY_SCREENLOCK } }, { KE_KEY, 0x35, { KEY_SCREENLOCK } }, { KE_KEY, 0x38, { KEY_PROG3 } }, /* Armoury Crate */ { KE_KEY, 0x40, { KEY_PREVIOUSSONG } }, @@ -544,6 +558,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = { { KE_KEY, 0x7D, { KEY_BLUETOOTH } }, /* Bluetooth Enable */ { KE_KEY, 0x7E, { KEY_BLUETOOTH } }, /* Bluetooth Disable */ { KE_KEY, 0x82, { KEY_CAMERA } }, + { KE_KEY, 0x85, { KEY_CAMERA } }, { KE_KEY, 0x86, { KEY_PROG1 } }, /* MyASUS Key */ { KE_KEY, 0x88, { KEY_RFKILL } }, /* Radio Toggle Key */ { KE_KEY, 0x8A, { KEY_PROG1 } }, /* Color enhancement mode */ diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 6f81b2844dcb..1038dfdcdd32 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -225,6 +225,7 @@ struct asus_wmi { int tablet_switch_event_code; u32 tablet_switch_dev_id; + bool tablet_switch_inverted; enum fan_type fan_type; enum fan_type gpu_fan_type; @@ -493,6 +494,13 @@ static bool asus_wmi_dev_is_present(struct asus_wmi *asus, u32 dev_id) } /* Input **********************************************************************/ +static void asus_wmi_tablet_sw_report(struct asus_wmi *asus, bool value) +{ + input_report_switch(asus->inputdev, SW_TABLET_MODE, + asus->tablet_switch_inverted ? !value : value); + input_sync(asus->inputdev); +} + static void asus_wmi_tablet_sw_init(struct asus_wmi *asus, u32 dev_id, int event_code) { struct device *dev = &asus->platform_device->dev; @@ -501,7 +509,7 @@ static void asus_wmi_tablet_sw_init(struct asus_wmi *asus, u32 dev_id, int event result = asus_wmi_get_devstate_simple(asus, dev_id); if (result >= 0) { input_set_capability(asus->inputdev, EV_SW, SW_TABLET_MODE); - input_report_switch(asus->inputdev, SW_TABLET_MODE, result); + asus_wmi_tablet_sw_report(asus, result); asus->tablet_switch_dev_id = dev_id; asus->tablet_switch_event_code = event_code; } else if (result == -ENODEV) { @@ -534,6 +542,7 @@ static int asus_wmi_input_init(struct asus_wmi *asus) case asus_wmi_no_tablet_switch: break; case asus_wmi_kbd_dock_devid: + asus->tablet_switch_inverted = true; asus_wmi_tablet_sw_init(asus, ASUS_WMI_DEVID_KBD_DOCK, NOTIFY_KBD_DOCK_CHANGE); break; case asus_wmi_lid_flip_devid: @@ -573,10 +582,8 @@ static void asus_wmi_tablet_mode_get_state(struct asus_wmi *asus) return; result = asus_wmi_get_devstate_simple(asus, asus->tablet_switch_dev_id); - if (result >= 0) { - input_report_switch(asus->inputdev, SW_TABLET_MODE, result); - input_sync(asus->inputdev); - } + if (result >= 0) + asus_wmi_tablet_sw_report(asus, result); } /* dGPU ********************************************************************/ @@ -2243,7 +2250,9 @@ static int asus_wmi_fan_init(struct asus_wmi *asus) asus->fan_type = FAN_TYPE_NONE; asus->agfn_pwm = -1; - if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_CPU_FAN_CTRL)) + if (asus->driver->quirks->wmi_ignore_fan) + asus->fan_type = FAN_TYPE_NONE; + else if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_CPU_FAN_CTRL)) asus->fan_type = FAN_TYPE_SPEC83; else if (asus_wmi_has_agfn_fan(asus)) asus->fan_type = FAN_TYPE_AGFN; @@ -2436,6 +2445,9 @@ static int fan_curve_check_present(struct asus_wmi *asus, bool *available, *available = false; + if (asus->fan_type == FAN_TYPE_NONE) + return 0; + err = fan_curve_get_factory_default(asus, fan_dev); if (err) { return 0; diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h index 65316998b898..a478ebfd34df 100644 --- a/drivers/platform/x86/asus-wmi.h +++ b/drivers/platform/x86/asus-wmi.h @@ -38,6 +38,7 @@ struct quirk_entry { bool store_backlight_power; bool wmi_backlight_set_devstate; bool wmi_force_als_set; + bool wmi_ignore_fan; enum asus_wmi_tablet_switch_mode tablet_switch_mode; int wapf; /* diff --git a/drivers/platform/x86/dell/dell-wmi-base.c b/drivers/platform/x86/dell/dell-wmi-base.c index 0a259a27459f..502783a7adb1 100644 --- a/drivers/platform/x86/dell/dell-wmi-base.c +++ b/drivers/platform/x86/dell/dell-wmi-base.c @@ -261,6 +261,9 @@ static const struct key_entry dell_wmi_keymap_type_0010[] = { { KE_KEY, 0x57, { KEY_BRIGHTNESSDOWN } }, { KE_KEY, 0x58, { KEY_BRIGHTNESSUP } }, + /*Speaker Mute*/ + { KE_KEY, 0x109, { KEY_MUTE} }, + /* Mic mute */ { KE_KEY, 0x150, { KEY_MICMUTE } }, diff --git a/drivers/platform/x86/dell/dell-wmi-privacy.c b/drivers/platform/x86/dell/dell-wmi-privacy.c index c82b3d6867c5..c517bd45dd32 100644 --- a/drivers/platform/x86/dell/dell-wmi-privacy.c +++ b/drivers/platform/x86/dell/dell-wmi-privacy.c @@ -61,7 +61,7 @@ static const struct key_entry dell_wmi_keymap_type_0012[] = { /* privacy mic mute */ { KE_KEY, 0x0001, { KEY_MICMUTE } }, /* privacy camera mute */ - { KE_SW, 0x0002, { SW_CAMERA_LENS_COVER } }, + { KE_VSW, 0x0002, { SW_CAMERA_LENS_COVER } }, { KE_END, 0}, }; @@ -115,11 +115,15 @@ bool dell_privacy_process_event(int type, int code, int status) switch (code) { case DELL_PRIVACY_AUDIO_EVENT: /* Mic mute */ - case DELL_PRIVACY_CAMERA_EVENT: /* Camera mute */ priv->last_status = status; sparse_keymap_report_entry(priv->input_dev, key, 1, true); ret = true; break; + case DELL_PRIVACY_CAMERA_EVENT: /* Camera mute */ + priv->last_status = status; + sparse_keymap_report_entry(priv->input_dev, key, !(status & CAMERA_STATUS), false); + ret = true; + break; default: dev_dbg(&priv->wdev->dev, "unknown event type 0x%04x 0x%04x\n", type, code); } @@ -292,7 +296,7 @@ static int dell_privacy_wmi_probe(struct wmi_device *wdev, const void *context) { struct privacy_wmi_data *priv; struct key_entry *keymap; - int ret, i; + int ret, i, j; ret = wmi_has_guid(DELL_PRIVACY_GUID); if (!ret) @@ -304,6 +308,11 @@ static int dell_privacy_wmi_probe(struct wmi_device *wdev, const void *context) dev_set_drvdata(&wdev->dev, priv); priv->wdev = wdev; + + ret = get_current_status(priv->wdev); + if (ret) + return ret; + /* create evdev passing interface */ priv->input_dev = devm_input_allocate_device(&wdev->dev); if (!priv->input_dev) @@ -318,9 +327,20 @@ static int dell_privacy_wmi_probe(struct wmi_device *wdev, const void *context) /* remap the keymap code with Dell privacy key type 0x12 as prefix * KEY_MICMUTE scancode will be reported as 0x120001 */ - for (i = 0; i < ARRAY_SIZE(dell_wmi_keymap_type_0012); i++) { - keymap[i] = dell_wmi_keymap_type_0012[i]; - keymap[i].code |= (0x0012 << 16); + for (i = 0, j = 0; i < ARRAY_SIZE(dell_wmi_keymap_type_0012); i++) { + /* + * Unlike keys where only presses matter, userspace may act + * on switches in both of their positions. Only register + * SW_CAMERA_LENS_COVER if it is actually there. + */ + if (dell_wmi_keymap_type_0012[i].type == KE_VSW && + dell_wmi_keymap_type_0012[i].sw.code == SW_CAMERA_LENS_COVER && + !(priv->features_present & BIT(DELL_PRIVACY_TYPE_CAMERA))) + continue; + + keymap[j] = dell_wmi_keymap_type_0012[i]; + keymap[j].code |= (0x0012 << 16); + j++; } ret = sparse_keymap_setup(priv->input_dev, keymap, NULL); kfree(keymap); @@ -331,11 +351,12 @@ static int dell_privacy_wmi_probe(struct wmi_device *wdev, const void *context) priv->input_dev->name = "Dell Privacy Driver"; priv->input_dev->id.bustype = BUS_HOST; - ret = input_register_device(priv->input_dev); - if (ret) - return ret; + /* Report initial camera-cover status */ + if (priv->features_present & BIT(DELL_PRIVACY_TYPE_CAMERA)) + input_report_switch(priv->input_dev, SW_CAMERA_LENS_COVER, + !(priv->last_status & CAMERA_STATUS)); - ret = get_current_status(priv->wdev); + ret = input_register_device(priv->input_dev); if (ret) return ret; diff --git a/drivers/platform/x86/gigabyte-wmi.c b/drivers/platform/x86/gigabyte-wmi.c index 5e7e6659a849..322cfaeda17b 100644 --- a/drivers/platform/x86/gigabyte-wmi.c +++ b/drivers/platform/x86/gigabyte-wmi.c @@ -141,6 +141,7 @@ static u8 gigabyte_wmi_detect_sensor_usability(struct wmi_device *wdev) static const struct dmi_system_id gigabyte_wmi_known_working_platforms[] = { DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B450M DS3H-CF"), + DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B450M DS3H WIFI-CF"), DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B450M S2H V2"), DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE AX V2"), DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE"), diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c index 0a99058be813..2ef201b625b3 100644 --- a/drivers/platform/x86/hp/hp-wmi.c +++ b/drivers/platform/x86/hp/hp-wmi.c @@ -90,6 +90,7 @@ enum hp_wmi_event_ids { HPWMI_PEAKSHIFT_PERIOD = 0x0F, HPWMI_BATTERY_CHARGE_PERIOD = 0x10, HPWMI_SANITIZATION_MODE = 0x17, + HPWMI_OMEN_KEY = 0x1D, HPWMI_SMART_EXPERIENCE_APP = 0x21, }; @@ -216,6 +217,8 @@ static const struct key_entry hp_wmi_keymap[] = { { KE_KEY, 0x213b, { KEY_INFO } }, { KE_KEY, 0x2169, { KEY_ROTATE_DISPLAY } }, { KE_KEY, 0x216a, { KEY_SETUP } }, + { KE_KEY, 0x21a5, { KEY_PROG2 } }, /* HP Omen Key */ + { KE_KEY, 0x21a7, { KEY_FN_ESC } }, { KE_KEY, 0x21a9, { KEY_TOUCHPAD_OFF } }, { KE_KEY, 0x121a9, { KEY_TOUCHPAD_ON } }, { KE_KEY, 0x231b, { KEY_HELP } }, @@ -548,7 +551,7 @@ static int __init hp_wmi_enable_hotkeys(void) static int hp_wmi_set_block(void *data, bool blocked) { - enum hp_wmi_radio r = (enum hp_wmi_radio) data; + enum hp_wmi_radio r = (long)data; int query = BIT(r + 8) | ((!blocked) << r); int ret; @@ -810,6 +813,7 @@ static void hp_wmi_notify(u32 value, void *context) case HPWMI_SMART_ADAPTER: break; case HPWMI_BEZEL_BUTTON: + case HPWMI_OMEN_KEY: key_code = hp_wmi_read_int(HPWMI_HOTKEY_QUERY); if (key_code < 0) break; diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 435d2d3d903b..0eb5bfdd823a 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -1621,6 +1621,12 @@ static const struct dmi_system_id set_fn_lock_led_list[] = { DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Legion R7000P2020H"), } }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Legion 5 15ARH05"), + } + }, {} }; diff --git a/drivers/platform/x86/intel/int3472/clk_and_regulator.c b/drivers/platform/x86/intel/int3472/clk_and_regulator.c index b2342b3d78c7..74dc2cff799e 100644 --- a/drivers/platform/x86/intel/int3472/clk_and_regulator.c +++ b/drivers/platform/x86/intel/int3472/clk_and_regulator.c @@ -181,6 +181,9 @@ int skl_int3472_register_regulator(struct int3472_discrete_device *int3472, return PTR_ERR(int3472->regulator.gpio); } + /* Ensure the pin is in output mode and non-active state */ + gpiod_direction_output(int3472->regulator.gpio, 0); + cfg.dev = &int3472->adev->dev; cfg.init_data = &init_data; cfg.ena_gpiod = int3472->regulator.gpio; diff --git a/drivers/platform/x86/intel/int3472/discrete.c b/drivers/platform/x86/intel/int3472/discrete.c index 974a132db651..c42c3faa2c32 100644 --- a/drivers/platform/x86/intel/int3472/discrete.c +++ b/drivers/platform/x86/intel/int3472/discrete.c @@ -168,6 +168,8 @@ static int skl_int3472_map_gpio_to_clk(struct int3472_discrete_device *int3472, return (PTR_ERR(gpio)); int3472->clock.ena_gpio = gpio; + /* Ensure the pin is in output mode and non-active state */ + gpiod_direction_output(int3472->clock.ena_gpio, 0); break; case INT3472_GPIO_TYPE_PRIVACY_LED: gpio = acpi_get_and_request_gpiod(path, pin, "int3472,privacy-led"); @@ -175,6 +177,8 @@ static int skl_int3472_map_gpio_to_clk(struct int3472_discrete_device *int3472, return (PTR_ERR(gpio)); int3472->clock.led_gpio = gpio; + /* Ensure the pin is in output mode and non-active state */ + gpiod_direction_output(int3472->clock.led_gpio, 0); break; default: dev_err(int3472->dev, "Invalid GPIO type 0x%02x for clock\n", type); diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c index f1d802f6ec3f..3a15d32d7644 100644 --- a/drivers/platform/x86/intel/pmc/core.c +++ b/drivers/platform/x86/intel/pmc/core.c @@ -1029,6 +1029,7 @@ static const struct x86_cpu_id intel_pmc_core_ids[] = { X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, adl_core_init), X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_S, adl_core_init), X86_MATCH_INTEL_FAM6_MODEL(METEORLAKE, mtl_core_init), + X86_MATCH_INTEL_FAM6_MODEL(METEORLAKE_L, mtl_core_init), {} }; diff --git a/drivers/platform/x86/simatic-ipc.c b/drivers/platform/x86/simatic-ipc.c index ca76076fc706..b3622419cd1a 100644 --- a/drivers/platform/x86/simatic-ipc.c +++ b/drivers/platform/x86/simatic-ipc.c @@ -46,7 +46,8 @@ static struct { {SIMATIC_IPC_IPC427D, SIMATIC_IPC_DEVICE_427E, SIMATIC_IPC_DEVICE_NONE}, {SIMATIC_IPC_IPC427E, SIMATIC_IPC_DEVICE_427E, SIMATIC_IPC_DEVICE_427E}, {SIMATIC_IPC_IPC477E, SIMATIC_IPC_DEVICE_NONE, SIMATIC_IPC_DEVICE_427E}, - {SIMATIC_IPC_IPC427G, SIMATIC_IPC_DEVICE_227G, SIMATIC_IPC_DEVICE_227G}, + {SIMATIC_IPC_IPCBX_39A, SIMATIC_IPC_DEVICE_227G, SIMATIC_IPC_DEVICE_227G}, + {SIMATIC_IPC_IPCPX_39A, SIMATIC_IPC_DEVICE_NONE, SIMATIC_IPC_DEVICE_227G}, }; static int register_platform_devices(u32 station_id) diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 7156ae2ad196..537d6a2d0781 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -1887,14 +1887,21 @@ static int sony_nc_kbd_backlight_setup(struct platform_device *pd, break; } - ret = sony_call_snc_handle(handle, probe_base, &result); - if (ret) - return ret; + /* + * Only probe if there is a separate probe_base, otherwise the probe call + * is equivalent to __sony_nc_kbd_backlight_mode_set(0), resulting in + * the keyboard backlight being turned off. + */ + if (probe_base) { + ret = sony_call_snc_handle(handle, probe_base, &result); + if (ret) + return ret; - if ((handle == 0x0137 && !(result & 0x02)) || - !(result & 0x01)) { - dprintk("no backlight keyboard found\n"); - return 0; + if ((handle == 0x0137 && !(result & 0x02)) || + !(result & 0x01)) { + dprintk("no backlight keyboard found\n"); + return 0; + } } kbdbl_ctl = kzalloc(sizeof(*kbdbl_ctl), GFP_KERNEL); diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 1195293b22fd..02860c32625e 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -10311,9 +10311,11 @@ static DEFINE_MUTEX(dytc_mutex); static int dytc_capabilities; static bool dytc_mmc_get_available; -static int convert_dytc_to_profile(int dytcmode, enum platform_profile_option *profile) +static int convert_dytc_to_profile(int funcmode, int dytcmode, + enum platform_profile_option *profile) { - if (dytc_capabilities & BIT(DYTC_FC_MMC)) { + switch (funcmode) { + case DYTC_FUNCTION_MMC: switch (dytcmode) { case DYTC_MODE_MMC_LOWPOWER: *profile = PLATFORM_PROFILE_LOW_POWER; @@ -10329,8 +10331,7 @@ static int convert_dytc_to_profile(int dytcmode, enum platform_profile_option *p return -EINVAL; } return 0; - } - if (dytc_capabilities & BIT(DYTC_FC_PSC)) { + case DYTC_FUNCTION_PSC: switch (dytcmode) { case DYTC_MODE_PSC_LOWPOWER: *profile = PLATFORM_PROFILE_LOW_POWER; @@ -10344,6 +10345,14 @@ static int convert_dytc_to_profile(int dytcmode, enum platform_profile_option *p default: /* Unknown mode */ return -EINVAL; } + return 0; + case DYTC_FUNCTION_AMT: + /* For now return balanced. It's the closest we have to 'auto' */ + *profile = PLATFORM_PROFILE_BALANCED; + return 0; + default: + /* Unknown function */ + return -EOPNOTSUPP; } return 0; } @@ -10487,11 +10496,11 @@ static int dytc_profile_set(struct platform_profile_handler *pprof, if (err) goto unlock; } - } - if (dytc_capabilities & BIT(DYTC_FC_PSC)) { + } else if (dytc_capabilities & BIT(DYTC_FC_PSC)) { err = dytc_command(DYTC_SET_COMMAND(DYTC_FUNCTION_PSC, perfmode, 1), &output); if (err) goto unlock; + /* system supports AMT, activate it when on balanced */ if (dytc_capabilities & BIT(DYTC_FC_AMT)) dytc_control_amt(profile == PLATFORM_PROFILE_BALANCED); @@ -10507,7 +10516,7 @@ static void dytc_profile_refresh(void) { enum platform_profile_option profile; int output, err = 0; - int perfmode; + int perfmode, funcmode; mutex_lock(&dytc_mutex); if (dytc_capabilities & BIT(DYTC_FC_MMC)) { @@ -10515,15 +10524,18 @@ static void dytc_profile_refresh(void) err = dytc_command(DYTC_CMD_MMC_GET, &output); else err = dytc_cql_command(DYTC_CMD_GET, &output); - } else if (dytc_capabilities & BIT(DYTC_FC_PSC)) + funcmode = DYTC_FUNCTION_MMC; + } else if (dytc_capabilities & BIT(DYTC_FC_PSC)) { err = dytc_command(DYTC_CMD_GET, &output); - + /* Check if we are PSC mode, or have AMT enabled */ + funcmode = (output >> DYTC_GET_FUNCTION_BIT) & 0xF; + } mutex_unlock(&dytc_mutex); if (err) return; perfmode = (output >> DYTC_GET_MODE_BIT) & 0xF; - convert_dytc_to_profile(perfmode, &profile); + convert_dytc_to_profile(funcmode, perfmode, &profile); if (profile != dytc_current_profile) { dytc_current_profile = profile; platform_profile_notify(); diff --git a/drivers/platform/x86/touchscreen_dmi.c b/drivers/platform/x86/touchscreen_dmi.c index baae3120efd0..f00995390fdf 100644 --- a/drivers/platform/x86/touchscreen_dmi.c +++ b/drivers/platform/x86/touchscreen_dmi.c @@ -264,6 +264,23 @@ static const struct ts_dmi_data connect_tablet9_data = { .properties = connect_tablet9_props, }; +static const struct property_entry csl_panther_tab_hd_props[] = { + PROPERTY_ENTRY_U32("touchscreen-min-x", 1), + PROPERTY_ENTRY_U32("touchscreen-min-y", 20), + PROPERTY_ENTRY_U32("touchscreen-size-x", 1980), + PROPERTY_ENTRY_U32("touchscreen-size-y", 1526), + PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"), + PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), + PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-csl-panther-tab-hd.fw"), + PROPERTY_ENTRY_U32("silead,max-fingers", 10), + { } +}; + +static const struct ts_dmi_data csl_panther_tab_hd_data = { + .acpi_name = "MSSL1680:00", + .properties = csl_panther_tab_hd_props, +}; + static const struct property_entry cube_iwork8_air_props[] = { PROPERTY_ENTRY_U32("touchscreen-min-x", 1), PROPERTY_ENTRY_U32("touchscreen-min-y", 3), @@ -1125,6 +1142,14 @@ const struct dmi_system_id touchscreen_dmi_table[] = { }, }, { + /* CSL Panther Tab HD */ + .driver_data = (void *)&csl_panther_tab_hd_data, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "CSL Computer GmbH & Co. KG"), + DMI_MATCH(DMI_PRODUCT_NAME, "CSL Panther Tab HD"), + }, + }, + { /* CUBE iwork8 Air */ .driver_data = (void *)&cube_iwork8_air_data, .matches = { diff --git a/drivers/regulator/da9211-regulator.c b/drivers/regulator/da9211-regulator.c index e01b32d1fa17..00828f5baa97 100644 --- a/drivers/regulator/da9211-regulator.c +++ b/drivers/regulator/da9211-regulator.c @@ -498,6 +498,12 @@ static int da9211_i2c_probe(struct i2c_client *i2c) chip->chip_irq = i2c->irq; + ret = da9211_regulator_init(chip); + if (ret < 0) { + dev_err(chip->dev, "Failed to initialize regulator: %d\n", ret); + return ret; + } + if (chip->chip_irq != 0) { ret = devm_request_threaded_irq(chip->dev, chip->chip_irq, NULL, da9211_irq_handler, @@ -512,11 +518,6 @@ static int da9211_i2c_probe(struct i2c_client *i2c) dev_warn(chip->dev, "No IRQ configured\n"); } - ret = da9211_regulator_init(chip); - - if (ret < 0) - dev_err(chip->dev, "Failed to initialize regulator: %d\n", ret); - return ret; } diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c index 43b5b9377714..ae6021390143 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -1016,7 +1016,7 @@ static const struct rpmh_vreg_init_data pm8550_vreg_data[] = { RPMH_VREG("ldo8", "ldo%s8", &pmic5_pldo_lv, "vdd-l8-l9"), RPMH_VREG("ldo9", "ldo%s9", &pmic5_pldo, "vdd-l8-l9"), RPMH_VREG("ldo10", "ldo%s10", &pmic5_nldo, "vdd-l1-l4-l10"), - RPMH_VREG("ldo11", "ldo%s11", &pmic5_pldo, "vdd-l11"), + RPMH_VREG("ldo11", "ldo%s11", &pmic5_nldo, "vdd-l11"), RPMH_VREG("ldo12", "ldo%s12", &pmic5_pldo, "vdd-l12"), RPMH_VREG("ldo13", "ldo%s13", &pmic5_pldo, "vdd-l2-l13-l14"), RPMH_VREG("ldo14", "ldo%s14", &pmic5_pldo, "vdd-l2-l13-l14"), diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index de176c2fbad9..2a52c990d4fe 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -257,7 +257,7 @@ config RESET_SUNXI config RESET_TI_SCI tristate "TI System Control Interface (TI-SCI) reset driver" - depends on TI_SCI_PROTOCOL || COMPILE_TEST + depends on TI_SCI_PROTOCOL || (COMPILE_TEST && TI_SCI_PROTOCOL=n) help This enables the reset driver support over TI System Control Interface available on some new TI's SoCs. If you wish to use reset resources diff --git a/drivers/reset/reset-uniphier-glue.c b/drivers/reset/reset-uniphier-glue.c index 146fd5d45e99..15abac9fc72c 100644 --- a/drivers/reset/reset-uniphier-glue.c +++ b/drivers/reset/reset-uniphier-glue.c @@ -47,7 +47,6 @@ static int uniphier_glue_reset_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct uniphier_glue_reset_priv *priv; struct resource *res; - resource_size_t size; int i, ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); @@ -60,7 +59,6 @@ static int uniphier_glue_reset_probe(struct platform_device *pdev) return -EINVAL; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - size = resource_size(res); priv->rdata.membase = devm_ioremap_resource(dev, res); if (IS_ERR(priv->rdata.membase)) return PTR_ERR(priv->rdata.membase); @@ -96,7 +94,7 @@ static int uniphier_glue_reset_probe(struct platform_device *pdev) spin_lock_init(&priv->rdata.lock); priv->rdata.rcdev.owner = THIS_MODULE; - priv->rdata.rcdev.nr_resets = size * BITS_PER_BYTE; + priv->rdata.rcdev.nr_resets = resource_size(res) * BITS_PER_BYTE; priv->rdata.rcdev.ops = &reset_simple_ops; priv->rdata.rcdev.of_node = dev->of_node; priv->rdata.active_low = true; diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index b392b9f5482e..c0f85ffb2b62 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -865,6 +865,8 @@ dcssblk_submit_bio(struct bio *bio) unsigned long bytes_done; bio = bio_split_to_limits(bio); + if (!bio) + return; bytes_done = 0; dev_info = bio->bi_bdev->bd_disk->private_data; diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index 406be169173c..d1adc4b83193 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c @@ -410,13 +410,13 @@ static ssize_t qeth_dev_isolation_show(struct device *dev, switch (card->options.isolation) { case ISOLATION_MODE_NONE: - return snprintf(buf, 6, "%s\n", ATTR_QETH_ISOLATION_NONE); + return sysfs_emit(buf, "%s\n", ATTR_QETH_ISOLATION_NONE); case ISOLATION_MODE_FWD: - return snprintf(buf, 9, "%s\n", ATTR_QETH_ISOLATION_FWD); + return sysfs_emit(buf, "%s\n", ATTR_QETH_ISOLATION_FWD); case ISOLATION_MODE_DROP: - return snprintf(buf, 6, "%s\n", ATTR_QETH_ISOLATION_DROP); + return sysfs_emit(buf, "%s\n", ATTR_QETH_ISOLATION_DROP); default: - return snprintf(buf, 5, "%s\n", "N/A"); + return sysfs_emit(buf, "%s\n", "N/A"); } } @@ -500,9 +500,9 @@ static ssize_t qeth_hw_trap_show(struct device *dev, struct qeth_card *card = dev_get_drvdata(dev); if (card->info.hwtrap) - return snprintf(buf, 5, "arm\n"); + return sysfs_emit(buf, "arm\n"); else - return snprintf(buf, 8, "disarm\n"); + return sysfs_emit(buf, "disarm\n"); } static ssize_t qeth_hw_trap_store(struct device *dev, diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 49cc18a87473..29a2865b8e2e 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -981,6 +981,9 @@ queue_rtpg: * * Returns true if and only if alua_rtpg_work() will be called asynchronously. * That function is responsible for calling @qdata->fn(). + * + * Context: may be called from atomic context (alua_check()) only if the caller + * holds an sdev reference. */ static bool alua_rtpg_queue(struct alua_port_group *pg, struct scsi_device *sdev, @@ -989,8 +992,6 @@ static bool alua_rtpg_queue(struct alua_port_group *pg, int start_queue = 0; unsigned long flags; - might_sleep(); - if (WARN_ON_ONCE(!pg) || scsi_device_get(sdev)) return false; diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 41ba22f6c7f0..8c038ccf1c09 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -162,7 +162,7 @@ static void hisi_sas_slot_index_clear(struct hisi_hba *hisi_hba, int slot_idx) static void hisi_sas_slot_index_free(struct hisi_hba *hisi_hba, int slot_idx) { if (hisi_hba->hw->slot_index_alloc || - slot_idx >= HISI_SAS_UNRESERVED_IPTT) { + slot_idx < HISI_SAS_RESERVED_IPTT) { spin_lock(&hisi_hba->lock); hisi_sas_slot_index_clear(hisi_hba, slot_idx); spin_unlock(&hisi_hba->lock); @@ -704,7 +704,7 @@ static int hisi_sas_init_device(struct domain_device *device) int_to_scsilun(0, &lun); while (retry-- > 0) { - rc = sas_clear_task_set(device, lun.scsi_lun); + rc = sas_abort_task_set(device, lun.scsi_lun); if (rc == TMF_RESP_FUNC_COMPLETE) { hisi_sas_release_task(hisi_hba, device); break; @@ -1316,7 +1316,7 @@ static void hisi_sas_refresh_port_id(struct hisi_hba *hisi_hba) device->linkrate = phy->sas_phy.linkrate; hisi_hba->hw->setup_itct(hisi_hba, sas_dev); - } else + } else if (!port->port_attached) port->id = 0xff; } } diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 4dbf51e2623a..f6da34850af9 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -5850,7 +5850,7 @@ static int hpsa_scsi_host_alloc(struct ctlr_info *h) { struct Scsi_Host *sh; - sh = scsi_host_alloc(&hpsa_driver_template, sizeof(h)); + sh = scsi_host_alloc(&hpsa_driver_template, sizeof(struct ctlr_info)); if (sh == NULL) { dev_err(&h->pdev->dev, "scsi_host_alloc failed\n"); return -ENOMEM; diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 1d1cf641937c..0454d94e8cf0 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -849,7 +849,7 @@ static int iscsi_sw_tcp_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param, char *buf) { struct iscsi_sw_tcp_host *tcp_sw_host = iscsi_host_priv(shost); - struct iscsi_session *session = tcp_sw_host->session; + struct iscsi_session *session; struct iscsi_conn *conn; struct iscsi_tcp_conn *tcp_conn; struct iscsi_sw_tcp_conn *tcp_sw_conn; @@ -859,6 +859,7 @@ static int iscsi_sw_tcp_host_get_param(struct Scsi_Host *shost, switch (param) { case ISCSI_HOST_PARAM_IPADDRESS: + session = tcp_sw_host->session; if (!session) return -ENOTCONN; @@ -959,11 +960,13 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max, if (!cls_session) goto remove_host; session = cls_session->dd_data; - tcp_sw_host = iscsi_host_priv(shost); - tcp_sw_host->session = session; if (iscsi_tcp_r2tpool_alloc(session)) goto remove_session; + + /* We are now fully setup so expose the session to sysfs. */ + tcp_sw_host = iscsi_host_priv(shost); + tcp_sw_host->session = session; return cls_session; remove_session: @@ -983,10 +986,17 @@ static void iscsi_sw_tcp_session_destroy(struct iscsi_cls_session *cls_session) if (WARN_ON_ONCE(session->leadconn)) return; + iscsi_session_remove(cls_session); + /* + * Our get_host_param needs to access the session, so remove the + * host from sysfs before freeing the session to make sure userspace + * is no longer accessing the callout. + */ + iscsi_host_remove(shost, false); + iscsi_tcp_r2tpool_free(cls_session->dd_data); - iscsi_session_teardown(cls_session); - iscsi_host_remove(shost, false); + iscsi_session_free(cls_session); iscsi_host_free(shost); } diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index ef2fc860257e..127f3d7f19dc 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -3104,17 +3104,32 @@ dec_session_count: } EXPORT_SYMBOL_GPL(iscsi_session_setup); -/** - * iscsi_session_teardown - destroy session, host, and cls_session - * @cls_session: iscsi session +/* + * issi_session_remove - Remove session from iSCSI class. */ -void iscsi_session_teardown(struct iscsi_cls_session *cls_session) +void iscsi_session_remove(struct iscsi_cls_session *cls_session) { struct iscsi_session *session = cls_session->dd_data; - struct module *owner = cls_session->transport->owner; struct Scsi_Host *shost = session->host; iscsi_remove_session(cls_session); + /* + * host removal only has to wait for its children to be removed from + * sysfs, and iscsi_tcp needs to do iscsi_host_remove before freeing + * the session, so drop the session count here. + */ + iscsi_host_dec_session_cnt(shost); +} +EXPORT_SYMBOL_GPL(iscsi_session_remove); + +/** + * iscsi_session_free - Free iscsi session and it's resources + * @cls_session: iscsi session + */ +void iscsi_session_free(struct iscsi_cls_session *cls_session) +{ + struct iscsi_session *session = cls_session->dd_data; + struct module *owner = cls_session->transport->owner; iscsi_pool_free(&session->cmdpool); kfree(session->password); @@ -3132,10 +3147,19 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session) kfree(session->discovery_parent_type); iscsi_free_session(cls_session); - - iscsi_host_dec_session_cnt(shost); module_put(owner); } +EXPORT_SYMBOL_GPL(iscsi_session_free); + +/** + * iscsi_session_teardown - destroy session and cls_session + * @cls_session: iscsi session + */ +void iscsi_session_teardown(struct iscsi_cls_session *cls_session) +{ + iscsi_session_remove(cls_session); + iscsi_session_free(cls_session); +} EXPORT_SYMBOL_GPL(iscsi_session_teardown); /** diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 1ccce706167a..5e80225b5308 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -889,7 +889,9 @@ void sas_ata_device_link_abort(struct domain_device *device, bool force_reset) { struct ata_port *ap = device->sata_dev.ap; struct ata_link *link = &ap->link; + unsigned long flags; + spin_lock_irqsave(ap->lock, flags); device->sata_dev.fis[2] = ATA_ERR | ATA_DRDY; /* tf status */ device->sata_dev.fis[3] = ATA_ABORTED; /* tf error */ @@ -897,6 +899,7 @@ void sas_ata_device_link_abort(struct domain_device *device, bool force_reset) if (force_reset) link->eh_info.action |= ATA_EH_RESET; ata_link_abort(link); + spin_unlock_irqrestore(ap->lock, flags); } EXPORT_SYMBOL_GPL(sas_ata_device_link_abort); diff --git a/drivers/scsi/mpi3mr/Makefile b/drivers/scsi/mpi3mr/Makefile index ef86ca46646b..3bf8cf34e1c3 100644 --- a/drivers/scsi/mpi3mr/Makefile +++ b/drivers/scsi/mpi3mr/Makefile @@ -1,5 +1,5 @@ # mpi3mr makefile -obj-m += mpi3mr.o +obj-$(CONFIG_SCSI_MPI3MR) += mpi3mr.o mpi3mr-y += mpi3mr_os.o \ mpi3mr_fw.o \ mpi3mr_app.o \ diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index 0c4aabaefdcc..286a44506578 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -3633,8 +3633,7 @@ int mpi3mr_setup_resources(struct mpi3mr_ioc *mrioc) int i, retval = 0, capb = 0; u16 message_control; u64 dma_mask = mrioc->dma_mask ? mrioc->dma_mask : - (((dma_get_required_mask(&pdev->dev) > DMA_BIT_MASK(32)) && - (sizeof(dma_addr_t) > 4)) ? DMA_BIT_MASK(64) : DMA_BIT_MASK(32)); + ((sizeof(dma_addr_t) > 4) ? DMA_BIT_MASK(64) : DMA_BIT_MASK(32)); if (pci_enable_device_mem(pdev)) { ioc_err(mrioc, "pci_enable_device_mem: failed\n"); diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 4e981ccaac41..69061545d9d2 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -2992,8 +2992,7 @@ _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev) struct sysinfo s; u64 coherent_dma_mask, dma_mask; - if (ioc->is_mcpu_endpoint || sizeof(dma_addr_t) == 4 || - dma_get_required_mask(&pdev->dev) <= DMA_BIT_MASK(32)) { + if (ioc->is_mcpu_endpoint || sizeof(dma_addr_t) == 4) { ioc->dma_mask = 32; coherent_dma_mask = dma_mask = DMA_BIT_MASK(32); /* Set 63 bit DMA mask for all SAS3 and SAS35 controllers */ diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index cc6953809a24..8553277effb3 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -1511,8 +1511,6 @@ static int inquiry_vpd_b0(unsigned char *arr) put_unaligned_be64(sdebug_write_same_length, &arr[32]); return 0x3c; /* Mandatory page length for Logical Block Provisioning */ - - return sizeof(vpdb0_data); } /* Block device characteristics VPD page (SBC-3) */ diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index a7960ad2d386..2aa2c2aee6e7 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -231,6 +231,11 @@ scsi_abort_command(struct scsi_cmnd *scmd) struct Scsi_Host *shost = sdev->host; unsigned long flags; + if (!shost->hostt->eh_abort_handler) { + /* No abort handler, fail command directly */ + return FAILED; + } + if (scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED) { /* * Retry after abort failed, escalate to next level. diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 13cfd3e317cc..b9b97300e3b3 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1677,6 +1677,13 @@ static const char *iscsi_session_state_name(int state) return name; } +static char *iscsi_session_target_state_name[] = { + [ISCSI_SESSION_TARGET_UNBOUND] = "UNBOUND", + [ISCSI_SESSION_TARGET_ALLOCATED] = "ALLOCATED", + [ISCSI_SESSION_TARGET_SCANNED] = "SCANNED", + [ISCSI_SESSION_TARGET_UNBINDING] = "UNBINDING", +}; + int iscsi_session_chkready(struct iscsi_cls_session *session) { int err; @@ -1786,9 +1793,13 @@ static int iscsi_user_scan_session(struct device *dev, void *data) if ((scan_data->channel == SCAN_WILD_CARD || scan_data->channel == 0) && (scan_data->id == SCAN_WILD_CARD || - scan_data->id == id)) + scan_data->id == id)) { scsi_scan_target(&session->dev, 0, id, scan_data->lun, scan_data->rescan); + spin_lock_irqsave(&session->lock, flags); + session->target_state = ISCSI_SESSION_TARGET_SCANNED; + spin_unlock_irqrestore(&session->lock, flags); + } } user_scan_exit: @@ -1961,31 +1972,41 @@ static void __iscsi_unbind_session(struct work_struct *work) struct iscsi_cls_host *ihost = shost->shost_data; unsigned long flags; unsigned int target_id; + bool remove_target = true; ISCSI_DBG_TRANS_SESSION(session, "Unbinding session\n"); /* Prevent new scans and make sure scanning is not in progress */ mutex_lock(&ihost->mutex); spin_lock_irqsave(&session->lock, flags); - if (session->target_id == ISCSI_MAX_TARGET) { + if (session->target_state == ISCSI_SESSION_TARGET_ALLOCATED) { + remove_target = false; + } else if (session->target_state != ISCSI_SESSION_TARGET_SCANNED) { spin_unlock_irqrestore(&session->lock, flags); mutex_unlock(&ihost->mutex); - goto unbind_session_exit; + ISCSI_DBG_TRANS_SESSION(session, + "Skipping target unbinding: Session is unbound/unbinding.\n"); + return; } + session->target_state = ISCSI_SESSION_TARGET_UNBINDING; target_id = session->target_id; session->target_id = ISCSI_MAX_TARGET; spin_unlock_irqrestore(&session->lock, flags); mutex_unlock(&ihost->mutex); - scsi_remove_target(&session->dev); + if (remove_target) + scsi_remove_target(&session->dev); if (session->ida_used) ida_free(&iscsi_sess_ida, target_id); -unbind_session_exit: iscsi_session_event(session, ISCSI_KEVENT_UNBIND_SESSION); ISCSI_DBG_TRANS_SESSION(session, "Completed target removal\n"); + + spin_lock_irqsave(&session->lock, flags); + session->target_state = ISCSI_SESSION_TARGET_UNBOUND; + spin_unlock_irqrestore(&session->lock, flags); } static void __iscsi_destroy_session(struct work_struct *work) @@ -2062,6 +2083,9 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id) session->ida_used = true; } else session->target_id = target_id; + spin_lock_irqsave(&session->lock, flags); + session->target_state = ISCSI_SESSION_TARGET_ALLOCATED; + spin_unlock_irqrestore(&session->lock, flags); dev_set_name(&session->dev, "session%u", session->sid); err = device_add(&session->dev); @@ -4370,6 +4394,19 @@ iscsi_session_attr(discovery_parent_idx, ISCSI_PARAM_DISCOVERY_PARENT_IDX, 0); iscsi_session_attr(discovery_parent_type, ISCSI_PARAM_DISCOVERY_PARENT_TYPE, 0); static ssize_t +show_priv_session_target_state(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent); + + return sysfs_emit(buf, "%s\n", + iscsi_session_target_state_name[session->target_state]); +} + +static ISCSI_CLASS_ATTR(priv_sess, target_state, S_IRUGO, + show_priv_session_target_state, NULL); + +static ssize_t show_priv_session_state(struct device *dev, struct device_attribute *attr, char *buf) { @@ -4471,6 +4508,7 @@ static struct attribute *iscsi_session_attrs[] = { &dev_attr_sess_boot_target.attr, &dev_attr_priv_sess_recovery_tmo.attr, &dev_attr_priv_sess_state.attr, + &dev_attr_priv_sess_target_state.attr, &dev_attr_priv_sess_creator.attr, &dev_attr_sess_chap_out_idx.attr, &dev_attr_sess_chap_in_idx.attr, @@ -4584,6 +4622,8 @@ static umode_t iscsi_session_attr_is_visible(struct kobject *kobj, return S_IRUGO | S_IWUSR; else if (attr == &dev_attr_priv_sess_state.attr) return S_IRUGO; + else if (attr == &dev_attr_priv_sess_target_state.attr) + return S_IRUGO; else if (attr == &dev_attr_priv_sess_creator.attr) return S_IRUGO; else if (attr == &dev_attr_priv_sess_target_id.attr) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index d7a84c0bfaeb..22705eb781b0 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1823,6 +1823,9 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) ret = storvsc_do_io(dev, cmd_request, get_cpu()); put_cpu(); + if (ret) + scsi_dma_unmap(scmnd); + if (ret == -EAGAIN) { /* no more space */ ret = SCSI_MLQUEUE_DEVICE_BUSY; diff --git a/drivers/scsi/xen-scsifront.c b/drivers/scsi/xen-scsifront.c index 66b316d173b0..71a3bb83984c 100644 --- a/drivers/scsi/xen-scsifront.c +++ b/drivers/scsi/xen-scsifront.c @@ -995,7 +995,7 @@ static int scsifront_suspend(struct xenbus_device *dev) return err; } -static int scsifront_remove(struct xenbus_device *dev) +static void scsifront_remove(struct xenbus_device *dev) { struct vscsifrnt_info *info = dev_get_drvdata(&dev->dev); @@ -1011,8 +1011,6 @@ static int scsifront_remove(struct xenbus_device *dev) scsifront_free_ring(info); scsi_host_put(info->host); - - return 0; } static void scsifront_disconnect(struct vscsifrnt_info *info) diff --git a/drivers/soc/imx/imx8mp-blk-ctrl.c b/drivers/soc/imx/imx8mp-blk-ctrl.c index 0e3b6ba22f94..0f13853901df 100644 --- a/drivers/soc/imx/imx8mp-blk-ctrl.c +++ b/drivers/soc/imx/imx8mp-blk-ctrl.c @@ -212,7 +212,7 @@ static void imx8mp_hdmi_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc, break; case IMX8MP_HDMIBLK_PD_LCDIF: regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, - BIT(7) | BIT(16) | BIT(17) | BIT(18) | + BIT(16) | BIT(17) | BIT(18) | BIT(19) | BIT(20)); regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(11)); regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, @@ -241,6 +241,7 @@ static void imx8mp_hdmi_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc, regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(1)); break; case IMX8MP_HDMIBLK_PD_HDMI_TX_PHY: + regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(7)); regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(22) | BIT(24)); regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12)); regmap_clear_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3)); @@ -270,7 +271,7 @@ static void imx8mp_hdmi_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc, BIT(4) | BIT(5) | BIT(6)); regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(11)); regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, - BIT(7) | BIT(16) | BIT(17) | BIT(18) | + BIT(16) | BIT(17) | BIT(18) | BIT(19) | BIT(20)); break; case IMX8MP_HDMIBLK_PD_PAI: @@ -298,6 +299,7 @@ static void imx8mp_hdmi_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc, case IMX8MP_HDMIBLK_PD_HDMI_TX_PHY: regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3)); regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12)); + regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(7)); regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(22) | BIT(24)); break; case IMX8MP_HDMIBLK_PD_HDCP: @@ -590,7 +592,6 @@ static int imx8mp_blk_ctrl_probe(struct platform_device *pdev) ret = PTR_ERR(domain->power_dev); goto cleanup_pds; } - dev_set_name(domain->power_dev, "%s", data->name); domain->genpd.name = data->name; domain->genpd.power_on = imx8mp_blk_ctrl_power_on; diff --git a/drivers/soc/imx/soc-imx8m.c b/drivers/soc/imx/soc-imx8m.c index 28144c699b0c..32ed9dc88e45 100644 --- a/drivers/soc/imx/soc-imx8m.c +++ b/drivers/soc/imx/soc-imx8m.c @@ -66,8 +66,8 @@ static u32 __init imx8mq_soc_revision(void) ocotp_base = of_iomap(np, 0); WARN_ON(!ocotp_base); clk = of_clk_get_by_name(np, NULL); - if (!clk) { - WARN_ON(!clk); + if (IS_ERR(clk)) { + WARN_ON(IS_ERR(clk)); return 0; } diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c index cd44f17dad3d..d51abb462ae5 100644 --- a/drivers/soc/qcom/apr.c +++ b/drivers/soc/qcom/apr.c @@ -461,9 +461,10 @@ static int apr_add_device(struct device *dev, struct device_node *np, goto out; } + /* Protection domain is optional, it does not exist on older platforms */ ret = of_property_read_string_index(np, "qcom,protection-domain", 1, &adev->service_path); - if (ret < 0) { + if (ret < 0 && ret != -EINVAL) { dev_err(dev, "Failed to read second value of qcom,protection-domain\n"); goto out; } diff --git a/drivers/soc/qcom/cpr.c b/drivers/soc/qcom/cpr.c index e9b854ed1bdf..144ea68e0920 100644 --- a/drivers/soc/qcom/cpr.c +++ b/drivers/soc/qcom/cpr.c @@ -1708,12 +1708,16 @@ static int cpr_probe(struct platform_device *pdev) ret = of_genpd_add_provider_simple(dev->of_node, &drv->pd); if (ret) - return ret; + goto err_remove_genpd; platform_set_drvdata(pdev, drv); cpr_debugfs_init(drv); return 0; + +err_remove_genpd: + pm_genpd_remove(&drv->pd); + return ret; } static int cpr_remove(struct platform_device *pdev) diff --git a/drivers/spi/spi-cadence-xspi.c b/drivers/spi/spi-cadence-xspi.c index 520b4cc69cdc..91db3c973167 100644 --- a/drivers/spi/spi-cadence-xspi.c +++ b/drivers/spi/spi-cadence-xspi.c @@ -177,7 +177,10 @@ #define CDNS_XSPI_CMD_FLD_DSEQ_CMD_3(op) ( \ FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R3_DCNT_H, \ ((op)->data.nbytes >> 16) & 0xffff) | \ - FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R3_NUM_OF_DUMMY, (op)->dummy.nbytes * 8)) + FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R3_NUM_OF_DUMMY, \ + (op)->dummy.buswidth != 0 ? \ + (((op)->dummy.nbytes * 8) / (op)->dummy.buswidth) : \ + 0)) #define CDNS_XSPI_CMD_FLD_DSEQ_CMD_4(op, chipsel) ( \ FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R4_BANK, chipsel) | \ diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 6de8360e5c2a..9eab6c20dbc5 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -1253,6 +1253,11 @@ static int mtk_spi_probe(struct platform_device *pdev) dev_notice(dev, "SPI dma_set_mask(%d) failed, ret:%d\n", addr_bits, ret); + ret = devm_request_irq(dev, irq, mtk_spi_interrupt, + IRQF_TRIGGER_NONE, dev_name(dev), master); + if (ret) + return dev_err_probe(dev, ret, "failed to register irq\n"); + pm_runtime_enable(dev); ret = devm_spi_register_master(dev, master); @@ -1261,13 +1266,6 @@ static int mtk_spi_probe(struct platform_device *pdev) return dev_err_probe(dev, ret, "failed to register master\n"); } - ret = devm_request_irq(dev, irq, mtk_spi_interrupt, - IRQF_TRIGGER_NONE, dev_name(dev), master); - if (ret) { - pm_runtime_disable(dev); - return dev_err_probe(dev, ret, "failed to register irq\n"); - } - return 0; } diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 3cc7bb4d03de..15f174f4e056 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2310,7 +2310,7 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, if (!of_property_read_u32(nc, "spi-max-frequency", &value)) spi->max_speed_hz = value; - if (!of_property_read_u16(nc, "spi-cs-setup-ns", &cs_setup)) { + if (!of_property_read_u16(nc, "spi-cs-setup-delay-ns", &cs_setup)) { spi->cs_setup.value = cs_setup; spi->cs_setup.unit = SPI_DELAY_UNIT_NSECS; } diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 6313e7d0cdf8..1935ca613447 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -68,7 +68,7 @@ static_assert(N_SPI_MINORS > 0 && N_SPI_MINORS <= 256); struct spidev_data { dev_t devt; - spinlock_t spi_lock; + struct mutex spi_lock; struct spi_device *spi; struct list_head device_entry; @@ -95,9 +95,8 @@ spidev_sync(struct spidev_data *spidev, struct spi_message *message) int status; struct spi_device *spi; - spin_lock_irq(&spidev->spi_lock); + mutex_lock(&spidev->spi_lock); spi = spidev->spi; - spin_unlock_irq(&spidev->spi_lock); if (spi == NULL) status = -ESHUTDOWN; @@ -107,6 +106,7 @@ spidev_sync(struct spidev_data *spidev, struct spi_message *message) if (status == 0) status = message->actual_length; + mutex_unlock(&spidev->spi_lock); return status; } @@ -359,12 +359,12 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) * we issue this ioctl. */ spidev = filp->private_data; - spin_lock_irq(&spidev->spi_lock); + mutex_lock(&spidev->spi_lock); spi = spi_dev_get(spidev->spi); - spin_unlock_irq(&spidev->spi_lock); - - if (spi == NULL) + if (spi == NULL) { + mutex_unlock(&spidev->spi_lock); return -ESHUTDOWN; + } /* use the buffer lock here for triple duty: * - prevent I/O (from us) so calling spi_setup() is safe; @@ -508,6 +508,7 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) mutex_unlock(&spidev->buf_lock); spi_dev_put(spi); + mutex_unlock(&spidev->spi_lock); return retval; } @@ -529,12 +530,12 @@ spidev_compat_ioc_message(struct file *filp, unsigned int cmd, * we issue this ioctl. */ spidev = filp->private_data; - spin_lock_irq(&spidev->spi_lock); + mutex_lock(&spidev->spi_lock); spi = spi_dev_get(spidev->spi); - spin_unlock_irq(&spidev->spi_lock); - - if (spi == NULL) + if (spi == NULL) { + mutex_unlock(&spidev->spi_lock); return -ESHUTDOWN; + } /* SPI_IOC_MESSAGE needs the buffer locked "normally" */ mutex_lock(&spidev->buf_lock); @@ -561,6 +562,7 @@ spidev_compat_ioc_message(struct file *filp, unsigned int cmd, done: mutex_unlock(&spidev->buf_lock); spi_dev_put(spi); + mutex_unlock(&spidev->spi_lock); return retval; } @@ -601,7 +603,6 @@ static int spidev_open(struct inode *inode, struct file *filp) if (!spidev->tx_buffer) { spidev->tx_buffer = kmalloc(bufsiz, GFP_KERNEL); if (!spidev->tx_buffer) { - dev_dbg(&spidev->spi->dev, "open/ENOMEM\n"); status = -ENOMEM; goto err_find_dev; } @@ -610,7 +611,6 @@ static int spidev_open(struct inode *inode, struct file *filp) if (!spidev->rx_buffer) { spidev->rx_buffer = kmalloc(bufsiz, GFP_KERNEL); if (!spidev->rx_buffer) { - dev_dbg(&spidev->spi->dev, "open/ENOMEM\n"); status = -ENOMEM; goto err_alloc_rx_buf; } @@ -640,10 +640,10 @@ static int spidev_release(struct inode *inode, struct file *filp) spidev = filp->private_data; filp->private_data = NULL; - spin_lock_irq(&spidev->spi_lock); + mutex_lock(&spidev->spi_lock); /* ... after we unbound from the underlying device? */ dofree = (spidev->spi == NULL); - spin_unlock_irq(&spidev->spi_lock); + mutex_unlock(&spidev->spi_lock); /* last close? */ spidev->users--; @@ -776,7 +776,7 @@ static int spidev_probe(struct spi_device *spi) /* Initialize the driver data */ spidev->spi = spi; - spin_lock_init(&spidev->spi_lock); + mutex_init(&spidev->spi_lock); mutex_init(&spidev->buf_lock); INIT_LIST_HEAD(&spidev->device_entry); @@ -821,9 +821,9 @@ static void spidev_remove(struct spi_device *spi) /* prevent new opens */ mutex_lock(&device_list_lock); /* make sure ops on existing fds can abort cleanly */ - spin_lock_irq(&spidev->spi_lock); + mutex_lock(&spidev->spi_lock); spidev->spi = NULL; - spin_unlock_irq(&spidev->spi_lock); + mutex_unlock(&spidev->spi_lock); list_del(&spidev->device_entry); device_destroy(spidev_class, spidev->devt); diff --git a/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h b/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h index db1441c0cc66..690ab7165b2c 100644 --- a/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h +++ b/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h @@ -86,7 +86,7 @@ struct vchiq_service_params_kernel { struct vchiq_instance; -extern enum vchiq_status vchiq_initialise(struct vchiq_instance **pinstance); +extern int vchiq_initialise(struct vchiq_instance **pinstance); extern enum vchiq_status vchiq_shutdown(struct vchiq_instance *instance); extern enum vchiq_status vchiq_connect(struct vchiq_instance *instance); extern enum vchiq_status vchiq_open_service(struct vchiq_instance *instance, diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h index 2851ef6b9cd0..cd20eb18f275 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h @@ -100,10 +100,10 @@ vchiq_dump_platform_use_state(struct vchiq_state *state); extern void vchiq_dump_service_use_state(struct vchiq_state *state); -extern enum vchiq_status +extern int vchiq_use_internal(struct vchiq_state *state, struct vchiq_service *service, enum USE_TYPE_E use_type); -extern enum vchiq_status +extern int vchiq_release_internal(struct vchiq_state *state, struct vchiq_service *service); diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index bac111456fa1..2b95b4550a63 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -73,8 +73,8 @@ static bool __target_check_io_state(struct se_cmd *se_cmd, { struct se_session *sess = se_cmd->se_sess; - assert_spin_locked(&sess->sess_cmd_lock); - WARN_ON_ONCE(!irqs_disabled()); + lockdep_assert_held(&sess->sess_cmd_lock); + /* * If command already reached CMD_T_COMPLETE state within * target_complete_cmd() or CMD_T_FABRIC_STOP due to shutdown, diff --git a/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c b/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c index 62c0aa5d0783..0a4eaa307156 100644 --- a/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c +++ b/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c @@ -44,11 +44,13 @@ static int int340x_thermal_get_trip_temp(struct thermal_zone_device *zone, int trip, int *temp) { struct int34x_thermal_zone *d = zone->devdata; - int i; + int i, ret = 0; if (d->override_ops && d->override_ops->get_trip_temp) return d->override_ops->get_trip_temp(zone, trip, temp); + mutex_lock(&d->trip_mutex); + if (trip < d->aux_trip_nr) *temp = d->aux_trips[trip]; else if (trip == d->crt_trip_id) @@ -66,10 +68,12 @@ static int int340x_thermal_get_trip_temp(struct thermal_zone_device *zone, } } if (i == INT340X_THERMAL_MAX_ACT_TRIP_COUNT) - return -EINVAL; + ret = -EINVAL; } - return 0; + mutex_unlock(&d->trip_mutex); + + return ret; } static int int340x_thermal_get_trip_type(struct thermal_zone_device *zone, @@ -77,11 +81,13 @@ static int int340x_thermal_get_trip_type(struct thermal_zone_device *zone, enum thermal_trip_type *type) { struct int34x_thermal_zone *d = zone->devdata; - int i; + int i, ret = 0; if (d->override_ops && d->override_ops->get_trip_type) return d->override_ops->get_trip_type(zone, trip, type); + mutex_lock(&d->trip_mutex); + if (trip < d->aux_trip_nr) *type = THERMAL_TRIP_PASSIVE; else if (trip == d->crt_trip_id) @@ -99,10 +105,12 @@ static int int340x_thermal_get_trip_type(struct thermal_zone_device *zone, } } if (i == INT340X_THERMAL_MAX_ACT_TRIP_COUNT) - return -EINVAL; + ret = -EINVAL; } - return 0; + mutex_unlock(&d->trip_mutex); + + return ret; } static int int340x_thermal_set_trip_temp(struct thermal_zone_device *zone, @@ -180,6 +188,8 @@ int int340x_thermal_read_trips(struct int34x_thermal_zone *int34x_zone) int trip_cnt = int34x_zone->aux_trip_nr; int i; + mutex_lock(&int34x_zone->trip_mutex); + int34x_zone->crt_trip_id = -1; if (!int340x_thermal_get_trip_config(int34x_zone->adev->handle, "_CRT", &int34x_zone->crt_temp)) @@ -207,6 +217,8 @@ int int340x_thermal_read_trips(struct int34x_thermal_zone *int34x_zone) int34x_zone->act_trips[i].valid = true; } + mutex_unlock(&int34x_zone->trip_mutex); + return trip_cnt; } EXPORT_SYMBOL_GPL(int340x_thermal_read_trips); @@ -230,6 +242,8 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev, if (!int34x_thermal_zone) return ERR_PTR(-ENOMEM); + mutex_init(&int34x_thermal_zone->trip_mutex); + int34x_thermal_zone->adev = adev; int34x_thermal_zone->override_ops = override_ops; @@ -281,6 +295,7 @@ err_thermal_zone: acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table); kfree(int34x_thermal_zone->aux_trips); err_trip_alloc: + mutex_destroy(&int34x_thermal_zone->trip_mutex); kfree(int34x_thermal_zone); return ERR_PTR(ret); } @@ -292,6 +307,7 @@ void int340x_thermal_zone_remove(struct int34x_thermal_zone thermal_zone_device_unregister(int34x_thermal_zone->zone); acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table); kfree(int34x_thermal_zone->aux_trips); + mutex_destroy(&int34x_thermal_zone->trip_mutex); kfree(int34x_thermal_zone); } EXPORT_SYMBOL_GPL(int340x_thermal_zone_remove); diff --git a/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.h b/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.h index 3b4971df1b33..8f9872afd0d3 100644 --- a/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.h +++ b/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.h @@ -32,6 +32,7 @@ struct int34x_thermal_zone { struct thermal_zone_device_ops *override_ops; void *priv_data; struct acpi_lpat_conversion_table *lpat_table; + struct mutex trip_mutex; }; struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *, diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c index 8c42e7662033..92ed1213fe37 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c @@ -172,6 +172,7 @@ static const struct attribute_group fivr_attribute_group = { RFIM_SHOW(rfi_restriction_run_busy, 1) RFIM_SHOW(rfi_restriction_err_code, 1) RFIM_SHOW(rfi_restriction_data_rate, 1) +RFIM_SHOW(rfi_restriction_data_rate_base, 1) RFIM_SHOW(ddr_data_rate_point_0, 1) RFIM_SHOW(ddr_data_rate_point_1, 1) RFIM_SHOW(ddr_data_rate_point_2, 1) @@ -181,11 +182,13 @@ RFIM_SHOW(rfi_disable, 1) RFIM_STORE(rfi_restriction_run_busy, 1) RFIM_STORE(rfi_restriction_err_code, 1) RFIM_STORE(rfi_restriction_data_rate, 1) +RFIM_STORE(rfi_restriction_data_rate_base, 1) RFIM_STORE(rfi_disable, 1) static DEVICE_ATTR_RW(rfi_restriction_run_busy); static DEVICE_ATTR_RW(rfi_restriction_err_code); static DEVICE_ATTR_RW(rfi_restriction_data_rate); +static DEVICE_ATTR_RW(rfi_restriction_data_rate_base); static DEVICE_ATTR_RO(ddr_data_rate_point_0); static DEVICE_ATTR_RO(ddr_data_rate_point_1); static DEVICE_ATTR_RO(ddr_data_rate_point_2); @@ -248,6 +251,7 @@ static struct attribute *dvfs_attrs[] = { &dev_attr_rfi_restriction_run_busy.attr, &dev_attr_rfi_restriction_err_code.attr, &dev_attr_rfi_restriction_data_rate.attr, + &dev_attr_rfi_restriction_data_rate_base.attr, &dev_attr_ddr_data_rate_point_0.attr, &dev_attr_ddr_data_rate_point_1.attr, &dev_attr_ddr_data_rate_point_2.attr, diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index f17ab2316dbd..77bd47d976a2 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -909,15 +909,20 @@ __thermal_cooling_device_register(struct device_node *np, cdev->devdata = devdata; ret = cdev->ops->get_max_state(cdev, &cdev->max_state); - if (ret) - goto out_kfree_type; + if (ret) { + kfree(cdev->type); + goto out_ida_remove; + } thermal_cooling_device_setup_sysfs(cdev); + ret = dev_set_name(&cdev->device, "cooling_device%d", cdev->id); if (ret) { + kfree(cdev->type); thermal_cooling_device_destroy_sysfs(cdev); - goto out_kfree_type; + goto out_ida_remove; } + ret = device_register(&cdev->device); if (ret) goto out_kfree_type; @@ -943,6 +948,8 @@ out_kfree_type: thermal_cooling_device_destroy_sysfs(cdev); kfree(cdev->type); put_device(&cdev->device); + + /* thermal_release() takes care of the rest */ cdev = NULL; out_ida_remove: ida_free(&thermal_cdev_ida, id); diff --git a/drivers/thunderbolt/retimer.c b/drivers/thunderbolt/retimer.c index 81252e31014a..56008eb91e2e 100644 --- a/drivers/thunderbolt/retimer.c +++ b/drivers/thunderbolt/retimer.c @@ -427,13 +427,6 @@ int tb_retimer_scan(struct tb_port *port, bool add) { u32 status[TB_MAX_RETIMER_INDEX + 1] = {}; int ret, i, last_idx = 0; - struct usb4_port *usb4; - - usb4 = port->usb4; - if (!usb4) - return 0; - - pm_runtime_get_sync(&usb4->dev); /* * Send broadcast RT to make sure retimer indices facing this @@ -441,7 +434,7 @@ int tb_retimer_scan(struct tb_port *port, bool add) */ ret = usb4_port_enumerate_retimers(port); if (ret) - goto out; + return ret; /* * Enable sideband channel for each retimer. We can do this @@ -471,12 +464,11 @@ int tb_retimer_scan(struct tb_port *port, bool add) break; } - if (!last_idx) { - ret = 0; - goto out; - } + if (!last_idx) + return 0; /* Add on-board retimers if they do not exist already */ + ret = 0; for (i = 1; i <= last_idx; i++) { struct tb_retimer *rt; @@ -490,10 +482,6 @@ int tb_retimer_scan(struct tb_port *port, bool add) } } -out: - pm_runtime_mark_last_busy(&usb4->dev); - pm_runtime_put_autosuspend(&usb4->dev); - return ret; } diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index 462845804427..3f1ab30c4fb1 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -628,11 +628,15 @@ static void tb_scan_port(struct tb_port *port) * Downstream switch is reachable through two ports. * Only scan on the primary port (link_nr == 0). */ + + if (port->usb4) + pm_runtime_get_sync(&port->usb4->dev); + if (tb_wait_for_port(port, false) <= 0) - return; + goto out_rpm_put; if (port->remote) { tb_port_dbg(port, "port already has a remote\n"); - return; + goto out_rpm_put; } tb_retimer_scan(port, true); @@ -647,12 +651,12 @@ static void tb_scan_port(struct tb_port *port) */ if (PTR_ERR(sw) == -EIO || PTR_ERR(sw) == -EADDRNOTAVAIL) tb_scan_xdomain(port); - return; + goto out_rpm_put; } if (tb_switch_configure(sw)) { tb_switch_put(sw); - return; + goto out_rpm_put; } /* @@ -681,7 +685,7 @@ static void tb_scan_port(struct tb_port *port) if (tb_switch_add(sw)) { tb_switch_put(sw); - return; + goto out_rpm_put; } /* Link the switches using both links if available */ @@ -733,6 +737,12 @@ static void tb_scan_port(struct tb_port *port) tb_add_dp_resources(sw); tb_scan_switch(sw); + +out_rpm_put: + if (port->usb4) { + pm_runtime_mark_last_busy(&port->usb4->dev); + pm_runtime_put_autosuspend(&port->usb4->dev); + } } static void tb_deactivate_and_free_tunnel(struct tb_tunnel *tunnel) diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c index 2c3cf7fc3357..1fc3c29b24f8 100644 --- a/drivers/thunderbolt/tunnel.c +++ b/drivers/thunderbolt/tunnel.c @@ -1275,7 +1275,7 @@ static void tb_usb3_reclaim_available_bandwidth(struct tb_tunnel *tunnel, return; } else if (!ret) { /* Use maximum link rate if the link valid is not set */ - ret = usb4_usb3_port_max_link_rate(tunnel->src_port); + ret = tb_usb3_max_link_rate(tunnel->dst_port, tunnel->src_port); if (ret < 0) { tb_tunnel_warn(tunnel, "failed to read maximum link rate\n"); return; diff --git a/drivers/thunderbolt/xdomain.c b/drivers/thunderbolt/xdomain.c index cfa83486c9da..3c51e47dd86b 100644 --- a/drivers/thunderbolt/xdomain.c +++ b/drivers/thunderbolt/xdomain.c @@ -1419,12 +1419,19 @@ static int tb_xdomain_get_properties(struct tb_xdomain *xd) * registered, we notify the userspace that it has changed. */ if (!update) { - struct tb_port *port; + /* + * Now disable lane 1 if bonding was not enabled. Do + * this only if bonding was possible at the beginning + * (that is we are the connection manager and there are + * two lanes). + */ + if (xd->bonding_possible) { + struct tb_port *port; - /* Now disable lane 1 if bonding was not enabled */ - port = tb_port_at(xd->route, tb_xdomain_parent(xd)); - if (!port->bonded) - tb_port_disable(port->dual_link_port); + port = tb_port_at(xd->route, tb_xdomain_parent(xd)); + if (!port->bonded) + tb_port_disable(port->dual_link_port); + } if (device_add(&xd->dev)) { dev_err(&xd->dev, "failed to add XDomain device\n"); diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c index 7c23112dc923..5bddb2f5e931 100644 --- a/drivers/tty/hvc/hvc_xen.c +++ b/drivers/tty/hvc/hvc_xen.c @@ -52,17 +52,22 @@ static DEFINE_SPINLOCK(xencons_lock); static struct xencons_info *vtermno_to_xencons(int vtermno) { - struct xencons_info *entry, *n, *ret = NULL; + struct xencons_info *entry, *ret = NULL; + unsigned long flags; - if (list_empty(&xenconsoles)) - return NULL; + spin_lock_irqsave(&xencons_lock, flags); + if (list_empty(&xenconsoles)) { + spin_unlock_irqrestore(&xencons_lock, flags); + return NULL; + } - list_for_each_entry_safe(entry, n, &xenconsoles, list) { + list_for_each_entry(entry, &xenconsoles, list) { if (entry->vtermno == vtermno) { ret = entry; break; } } + spin_unlock_irqrestore(&xencons_lock, flags); return ret; } @@ -223,7 +228,7 @@ static int xen_hvm_console_init(void) { int r; uint64_t v = 0; - unsigned long gfn; + unsigned long gfn, flags; struct xencons_info *info; if (!xen_hvm_domain()) @@ -258,9 +263,9 @@ static int xen_hvm_console_init(void) goto err; info->vtermno = HVC_COOKIE; - spin_lock(&xencons_lock); + spin_lock_irqsave(&xencons_lock, flags); list_add_tail(&info->list, &xenconsoles); - spin_unlock(&xencons_lock); + spin_unlock_irqrestore(&xencons_lock, flags); return 0; err: @@ -283,6 +288,7 @@ static int xencons_info_pv_init(struct xencons_info *info, int vtermno) static int xen_pv_console_init(void) { struct xencons_info *info; + unsigned long flags; if (!xen_pv_domain()) return -ENODEV; @@ -299,9 +305,9 @@ static int xen_pv_console_init(void) /* already configured */ return 0; } - spin_lock(&xencons_lock); + spin_lock_irqsave(&xencons_lock, flags); xencons_info_pv_init(info, HVC_COOKIE); - spin_unlock(&xencons_lock); + spin_unlock_irqrestore(&xencons_lock, flags); return 0; } @@ -309,6 +315,7 @@ static int xen_pv_console_init(void) static int xen_initial_domain_console_init(void) { struct xencons_info *info; + unsigned long flags; if (!xen_initial_domain()) return -ENODEV; @@ -323,9 +330,9 @@ static int xen_initial_domain_console_init(void) info->irq = bind_virq_to_irq(VIRQ_CONSOLE, 0, false); info->vtermno = HVC_COOKIE; - spin_lock(&xencons_lock); + spin_lock_irqsave(&xencons_lock, flags); list_add_tail(&info->list, &xenconsoles); - spin_unlock(&xencons_lock); + spin_unlock_irqrestore(&xencons_lock, flags); return 0; } @@ -380,10 +387,12 @@ static void xencons_free(struct xencons_info *info) static int xen_console_remove(struct xencons_info *info) { + unsigned long flags; + xencons_disconnect_backend(info); - spin_lock(&xencons_lock); + spin_lock_irqsave(&xencons_lock, flags); list_del(&info->list); - spin_unlock(&xencons_lock); + spin_unlock_irqrestore(&xencons_lock, flags); if (info->xbdev != NULL) xencons_free(info); else { @@ -394,9 +403,9 @@ static int xen_console_remove(struct xencons_info *info) return 0; } -static int xencons_remove(struct xenbus_device *dev) +static void xencons_remove(struct xenbus_device *dev) { - return xen_console_remove(dev_get_drvdata(&dev->dev)); + xen_console_remove(dev_get_drvdata(&dev->dev)); } static int xencons_connect_backend(struct xenbus_device *dev, @@ -464,6 +473,7 @@ static int xencons_probe(struct xenbus_device *dev, { int ret, devid; struct xencons_info *info; + unsigned long flags; devid = dev->nodename[strlen(dev->nodename) - 1] - '0'; if (devid == 0) @@ -482,9 +492,9 @@ static int xencons_probe(struct xenbus_device *dev, ret = xencons_connect_backend(dev, info); if (ret < 0) goto error; - spin_lock(&xencons_lock); + spin_lock_irqsave(&xencons_lock, flags); list_add_tail(&info->list, &xenconsoles); - spin_unlock(&xencons_lock); + spin_unlock_irqrestore(&xencons_lock, flags); return 0; @@ -584,10 +594,12 @@ static int __init xen_hvc_init(void) info->hvc = hvc_alloc(HVC_COOKIE, info->irq, ops, 256); if (IS_ERR(info->hvc)) { + unsigned long flags; + r = PTR_ERR(info->hvc); - spin_lock(&xencons_lock); + spin_lock_irqsave(&xencons_lock, flags); list_del(&info->list); - spin_unlock(&xencons_lock); + spin_unlock_irqrestore(&xencons_lock, flags); if (info->irq) unbind_from_irqhandler(info->irq, NULL); kfree(info); diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c index 314a05e009df..64770c62bbec 100644 --- a/drivers/tty/serial/8250/8250_exar.c +++ b/drivers/tty/serial/8250/8250_exar.c @@ -43,6 +43,12 @@ #define PCI_DEVICE_ID_EXAR_XR17V4358 0x4358 #define PCI_DEVICE_ID_EXAR_XR17V8358 0x8358 +#define PCI_DEVICE_ID_SEALEVEL_710xC 0x1001 +#define PCI_DEVICE_ID_SEALEVEL_720xC 0x1002 +#define PCI_DEVICE_ID_SEALEVEL_740xC 0x1004 +#define PCI_DEVICE_ID_SEALEVEL_780xC 0x1008 +#define PCI_DEVICE_ID_SEALEVEL_716xC 0x1010 + #define UART_EXAR_INT0 0x80 #define UART_EXAR_8XMODE 0x88 /* 8X sampling rate select */ #define UART_EXAR_SLEEP 0x8b /* Sleep mode */ @@ -638,6 +644,8 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent) nr_ports = BIT(((pcidev->device & 0x38) >> 3) - 1); else if (board->num_ports) nr_ports = board->num_ports; + else if (pcidev->vendor == PCI_VENDOR_ID_SEALEVEL) + nr_ports = pcidev->device & 0xff; else nr_ports = pcidev->device & 0x0f; @@ -864,6 +872,12 @@ static const struct pci_device_id exar_pci_tbl[] = { EXAR_DEVICE(COMMTECH, 4224PCI335, pbn_fastcom335_4), EXAR_DEVICE(COMMTECH, 2324PCI335, pbn_fastcom335_4), EXAR_DEVICE(COMMTECH, 2328PCI335, pbn_fastcom335_8), + + EXAR_DEVICE(SEALEVEL, 710xC, pbn_exar_XR17V35x), + EXAR_DEVICE(SEALEVEL, 720xC, pbn_exar_XR17V35x), + EXAR_DEVICE(SEALEVEL, 740xC, pbn_exar_XR17V35x), + EXAR_DEVICE(SEALEVEL, 780xC, pbn_exar_XR17V35x), + EXAR_DEVICE(SEALEVEL, 716xC, pbn_exar_XR17V35x), { 0, } }; MODULE_DEVICE_TABLE(pci, exar_pci_tbl); diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index d75c39f4622b..d8c2f3455eeb 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1466,6 +1466,10 @@ static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq) struct circ_buf *xmit = &uap->port.state->xmit; int count = uap->fifosize >> 1; + if ((uap->port.rs485.flags & SER_RS485_ENABLED) && + !uap->rs485_tx_started) + pl011_rs485_tx_start(uap); + if (uap->port.x_char) { if (!pl011_tx_char(uap, uap->port.x_char, from_irq)) return true; @@ -1477,10 +1481,6 @@ static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq) return false; } - if ((uap->port.rs485.flags & SER_RS485_ENABLED) && - !uap->rs485_tx_started) - pl011_rs485_tx_start(uap); - /* If we are using DMA mode, try to send some characters. */ if (pl011_dma_tx_irq(uap)) return true; diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index f1c06e12efa0..9cd7479b03c0 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -2657,13 +2657,7 @@ static void __init atmel_console_get_options(struct uart_port *port, int *baud, else if (mr == ATMEL_US_PAR_ODD) *parity = 'o'; - /* - * The serial core only rounds down when matching this to a - * supported baud rate. Make sure we don't end up slightly - * lower than one of those, as it would make us fall through - * to a much lower baud rate than we really want. - */ - *baud = port->uartclk / (16 * (quot - 1)); + *baud = port->uartclk / (16 * quot); } static int __init atmel_console_setup(struct console *co, char *options) diff --git a/drivers/tty/serial/kgdboc.c b/drivers/tty/serial/kgdboc.c index a3ed9b34e2ab..7ce7bb164005 100644 --- a/drivers/tty/serial/kgdboc.c +++ b/drivers/tty/serial/kgdboc.c @@ -171,6 +171,7 @@ static int configure_kgdboc(void) int err = -ENODEV; char *cptr = config; struct console *cons; + int cookie; if (!strlen(config) || isspace(config[0])) { err = 0; @@ -189,20 +190,9 @@ static int configure_kgdboc(void) if (kgdboc_register_kbd(&cptr)) goto do_register; - /* - * tty_find_polling_driver() can call uart_set_options() - * (via poll_init) to configure the uart. Take the console_list_lock - * in order to synchronize against register_console(), which can also - * configure the uart via uart_set_options(). This also allows safe - * traversal of the console list. - */ - console_list_lock(); - p = tty_find_polling_driver(cptr, &tty_line); - if (!p) { - console_list_unlock(); + if (!p) goto noconfig; - } /* * Take console_lock to serialize device() callback with @@ -211,7 +201,8 @@ static int configure_kgdboc(void) */ console_lock(); - for_each_console(cons) { + cookie = console_srcu_read_lock(); + for_each_console_srcu(cons) { int idx; if (cons->device && cons->device(cons, &idx) == p && idx == tty_line) { @@ -219,11 +210,10 @@ static int configure_kgdboc(void) break; } } + console_srcu_read_unlock(cookie); console_unlock(); - console_list_unlock(); - kgdb_tty_driver = p; kgdb_tty_line = tty_line; diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 3d54a43768cd..9576ba8bbc40 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -749,7 +749,7 @@ static void pch_dma_tx_complete(void *arg) uart_xmit_advance(port, sg_dma_len(sg)); async_tx_ack(priv->desc_tx); - dma_unmap_sg(port->dev, sg, priv->orig_nent, DMA_TO_DEVICE); + dma_unmap_sg(port->dev, priv->sg_tx_p, priv->orig_nent, DMA_TO_DEVICE); priv->tx_dma_use = 0; priv->nent = 0; priv->orig_nent = 0; diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index b487823f0e61..57f04f8bf504 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -864,9 +864,10 @@ out_unlock: return IRQ_HANDLED; } -static void get_tx_fifo_size(struct qcom_geni_serial_port *port) +static int setup_fifos(struct qcom_geni_serial_port *port) { struct uart_port *uport; + u32 old_rx_fifo_depth = port->rx_fifo_depth; uport = &port->uport; port->tx_fifo_depth = geni_se_get_tx_fifo_depth(&port->se); @@ -874,6 +875,16 @@ static void get_tx_fifo_size(struct qcom_geni_serial_port *port) port->rx_fifo_depth = geni_se_get_rx_fifo_depth(&port->se); uport->fifosize = (port->tx_fifo_depth * port->tx_fifo_width) / BITS_PER_BYTE; + + if (port->rx_fifo && (old_rx_fifo_depth != port->rx_fifo_depth) && port->rx_fifo_depth) { + port->rx_fifo = devm_krealloc(uport->dev, port->rx_fifo, + port->rx_fifo_depth * sizeof(u32), + GFP_KERNEL); + if (!port->rx_fifo) + return -ENOMEM; + } + + return 0; } @@ -888,6 +899,7 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport) u32 rxstale = DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT; u32 proto; u32 pin_swap; + int ret; proto = geni_se_read_proto(&port->se); if (proto != GENI_SE_UART) { @@ -897,7 +909,9 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport) qcom_geni_serial_stop_rx(uport); - get_tx_fifo_size(port); + ret = setup_fifos(port); + if (ret) + return ret; writel(rxstale, uport->membase + SE_UART_RX_STALE_CNT); @@ -1516,7 +1530,7 @@ static int qcom_geni_serial_remove(struct platform_device *pdev) return 0; } -static int __maybe_unused qcom_geni_serial_sys_suspend(struct device *dev) +static int qcom_geni_serial_sys_suspend(struct device *dev) { struct qcom_geni_serial_port *port = dev_get_drvdata(dev); struct uart_port *uport = &port->uport; @@ -1533,7 +1547,7 @@ static int __maybe_unused qcom_geni_serial_sys_suspend(struct device *dev) return uart_suspend_port(private_data->drv, uport); } -static int __maybe_unused qcom_geni_serial_sys_resume(struct device *dev) +static int qcom_geni_serial_sys_resume(struct device *dev) { int ret; struct qcom_geni_serial_port *port = dev_get_drvdata(dev); @@ -1581,10 +1595,12 @@ static int qcom_geni_serial_sys_hib_resume(struct device *dev) } static const struct dev_pm_ops qcom_geni_serial_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(qcom_geni_serial_sys_suspend, - qcom_geni_serial_sys_resume) - .restore = qcom_geni_serial_sys_hib_resume, - .thaw = qcom_geni_serial_sys_hib_resume, + .suspend = pm_sleep_ptr(qcom_geni_serial_sys_suspend), + .resume = pm_sleep_ptr(qcom_geni_serial_sys_resume), + .freeze = pm_sleep_ptr(qcom_geni_serial_sys_suspend), + .poweroff = pm_sleep_ptr(qcom_geni_serial_sys_suspend), + .restore = pm_sleep_ptr(qcom_geni_serial_sys_hib_resume), + .thaw = pm_sleep_ptr(qcom_geni_serial_sys_hib_resume), }; static const struct of_device_id qcom_geni_serial_match_table[] = { diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index b9fbbee598b8..ec874f3a567c 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -2212,6 +2212,9 @@ EXPORT_SYMBOL_GPL(uart_parse_options); * @parity: parity character - 'n' (none), 'o' (odd), 'e' (even) * @bits: number of data bits * @flow: flow control character - 'r' (rts) + * + * Locking: Caller must hold console_list_lock in order to serialize + * early initialization of the serial-console lock. */ int uart_set_options(struct uart_port *port, struct console *co, @@ -2619,7 +2622,9 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options) if (!ret && options) { uart_parse_options(options, &baud, &parity, &bits, &flow); + console_list_lock(); ret = uart_set_options(port, NULL, baud, parity, bits, flow); + console_list_unlock(); } out: mutex_unlock(&tport->mutex); diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index e18c9f4463ec..3a1c4d31e010 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -1234,12 +1234,14 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba) * clock scaling is in progress */ ufshcd_scsi_block_requests(hba); + mutex_lock(&hba->wb_mutex); down_write(&hba->clk_scaling_lock); if (!hba->clk_scaling.is_allowed || ufshcd_wait_for_doorbell_clr(hba, DOORBELL_CLR_TOUT_US)) { ret = -EBUSY; up_write(&hba->clk_scaling_lock); + mutex_unlock(&hba->wb_mutex); ufshcd_scsi_unblock_requests(hba); goto out; } @@ -1251,12 +1253,16 @@ out: return ret; } -static void ufshcd_clock_scaling_unprepare(struct ufs_hba *hba, bool writelock) +static void ufshcd_clock_scaling_unprepare(struct ufs_hba *hba, int err, bool scale_up) { - if (writelock) - up_write(&hba->clk_scaling_lock); - else - up_read(&hba->clk_scaling_lock); + up_write(&hba->clk_scaling_lock); + + /* Enable Write Booster if we have scaled up else disable it */ + if (ufshcd_enable_wb_if_scaling_up(hba) && !err) + ufshcd_wb_toggle(hba, scale_up); + + mutex_unlock(&hba->wb_mutex); + ufshcd_scsi_unblock_requests(hba); ufshcd_release(hba); } @@ -1273,7 +1279,6 @@ static void ufshcd_clock_scaling_unprepare(struct ufs_hba *hba, bool writelock) static int ufshcd_devfreq_scale(struct ufs_hba *hba, bool scale_up) { int ret = 0; - bool is_writelock = true; ret = ufshcd_clock_scaling_prepare(hba); if (ret) @@ -1302,15 +1307,8 @@ static int ufshcd_devfreq_scale(struct ufs_hba *hba, bool scale_up) } } - /* Enable Write Booster if we have scaled up else disable it */ - if (ufshcd_enable_wb_if_scaling_up(hba)) { - downgrade_write(&hba->clk_scaling_lock); - is_writelock = false; - ufshcd_wb_toggle(hba, scale_up); - } - out_unprepare: - ufshcd_clock_scaling_unprepare(hba, is_writelock); + ufshcd_clock_scaling_unprepare(hba, ret, scale_up); return ret; } @@ -6056,11 +6054,21 @@ void ufshcd_schedule_eh_work(struct ufs_hba *hba) } } +static void ufshcd_force_error_recovery(struct ufs_hba *hba) +{ + spin_lock_irq(hba->host->host_lock); + hba->force_reset = true; + ufshcd_schedule_eh_work(hba); + spin_unlock_irq(hba->host->host_lock); +} + static void ufshcd_clk_scaling_allow(struct ufs_hba *hba, bool allow) { + mutex_lock(&hba->wb_mutex); down_write(&hba->clk_scaling_lock); hba->clk_scaling.is_allowed = allow; up_write(&hba->clk_scaling_lock); + mutex_unlock(&hba->wb_mutex); } static void ufshcd_clk_scaling_suspend(struct ufs_hba *hba, bool suspend) @@ -9083,6 +9091,15 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) if (!hba->dev_info.b_rpm_dev_flush_capable) { ret = ufshcd_set_dev_pwr_mode(hba, req_dev_pwr_mode); + if (ret && pm_op != UFS_SHUTDOWN_PM) { + /* + * If return err in suspend flow, IO will hang. + * Trigger error handler and break suspend for + * error recovery. + */ + ufshcd_force_error_recovery(hba); + ret = -EBUSY; + } if (ret) goto enable_scaling; } @@ -9094,6 +9111,15 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) */ check_for_bkops = !ufshcd_is_ufs_dev_deepsleep(hba); ret = ufshcd_link_state_transition(hba, req_link_state, check_for_bkops); + if (ret && pm_op != UFS_SHUTDOWN_PM) { + /* + * If return err in suspend flow, IO will hang. + * Trigger error handler and break suspend for + * error recovery. + */ + ufshcd_force_error_recovery(hba); + ret = -EBUSY; + } if (ret) goto set_dev_active; @@ -9767,6 +9793,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) /* Initialize mutex for exception event control */ mutex_init(&hba->ee_ctrl_mutex); + mutex_init(&hba->wb_mutex); init_rwsem(&hba->clk_scaling_lock); ufshcd_init_clk_gating(hba); diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c index 5adcb349718c..ccfaebca6faa 100644 --- a/drivers/usb/cdns3/cdns3-gadget.c +++ b/drivers/usb/cdns3/cdns3-gadget.c @@ -2614,6 +2614,7 @@ int cdns3_gadget_ep_dequeue(struct usb_ep *ep, u8 req_on_hw_ring = 0; unsigned long flags; int ret = 0; + int val; if (!ep || !request || !ep->desc) return -EINVAL; @@ -2649,6 +2650,13 @@ found: /* Update ring only if removed request is on pending_req_list list */ if (req_on_hw_ring && link_trb) { + /* Stop DMA */ + writel(EP_CMD_DFLUSH, &priv_dev->regs->ep_cmd); + + /* wait for DFLUSH cleared */ + readl_poll_timeout_atomic(&priv_dev->regs->ep_cmd, val, + !(val & EP_CMD_DFLUSH), 1, 1000); + link_trb->buffer = cpu_to_le32(TRB_BUFFER(priv_ep->trb_pool_dma + ((priv_req->end_trb + 1) * TRB_SIZE))); link_trb->control = cpu_to_le32((le32_to_cpu(link_trb->control) & TRB_CYCLE) | @@ -2660,6 +2668,10 @@ found: cdns3_gadget_giveback(priv_ep, priv_req, -ECONNRESET); + req = cdns3_next_request(&priv_ep->pending_req_list); + if (req) + cdns3_rearm_transfer(priv_ep, 1); + not_found: spin_unlock_irqrestore(&priv_dev->lock, flags); return ret; diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 484b1cd23431..27c601296130 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -1294,12 +1294,12 @@ static void ci_extcon_wakeup_int(struct ci_hdrc *ci) cable_id = &ci->platdata->id_extcon; cable_vbus = &ci->platdata->vbus_extcon; - if ((!IS_ERR(cable_id->edev) || !IS_ERR(ci->role_switch)) + if ((!IS_ERR(cable_id->edev) || ci->role_switch) && ci->is_otg && (otgsc & OTGSC_IDIE) && (otgsc & OTGSC_IDIS)) ci_irq(ci); - if ((!IS_ERR(cable_vbus->edev) || !IS_ERR(ci->role_switch)) + if ((!IS_ERR(cable_vbus->edev) || ci->role_switch) && ci->is_otg && (otgsc & OTGSC_BSVIE) && (otgsc & OTGSC_BSVIS)) ci_irq(ci); diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index 60e8174686a1..d7c8461976ce 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -207,7 +207,7 @@ static int ulpi_read_id(struct ulpi *ulpi) /* Test the interface */ ret = ulpi_write(ulpi, ULPI_SCRATCH, 0xaa); if (ret < 0) - return ret; + goto err; ret = ulpi_read(ulpi, ULPI_SCRATCH); if (ret < 0) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 77e73fc8d673..9eca403af2a8 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -44,6 +44,9 @@ #define USB_PRODUCT_USB5534B 0x5534 #define USB_VENDOR_CYPRESS 0x04b4 #define USB_PRODUCT_CY7C65632 0x6570 +#define USB_VENDOR_TEXAS_INSTRUMENTS 0x0451 +#define USB_PRODUCT_TUSB8041_USB3 0x8140 +#define USB_PRODUCT_TUSB8041_USB2 0x8142 #define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND 0x01 #define HUB_QUIRK_DISABLE_AUTOSUSPEND 0x02 @@ -5854,6 +5857,16 @@ static const struct usb_device_id hub_id_table[] = { .idVendor = USB_VENDOR_GENESYS_LOGIC, .bInterfaceClass = USB_CLASS_HUB, .driver_info = HUB_QUIRK_CHECK_PORT_AUTOSUSPEND}, + { .match_flags = USB_DEVICE_ID_MATCH_VENDOR + | USB_DEVICE_ID_MATCH_PRODUCT, + .idVendor = USB_VENDOR_TEXAS_INSTRUMENTS, + .idProduct = USB_PRODUCT_TUSB8041_USB2, + .driver_info = HUB_QUIRK_DISABLE_AUTOSUSPEND}, + { .match_flags = USB_DEVICE_ID_MATCH_VENDOR + | USB_DEVICE_ID_MATCH_PRODUCT, + .idVendor = USB_VENDOR_TEXAS_INSTRUMENTS, + .idProduct = USB_PRODUCT_TUSB8041_USB3, + .driver_info = HUB_QUIRK_DISABLE_AUTOSUSPEND}, { .match_flags = USB_DEVICE_ID_MATCH_DEV_CLASS, .bDeviceClass = USB_CLASS_HUB}, { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index 6d93428432f1..533baa85083c 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -37,6 +37,71 @@ bool usb_acpi_power_manageable(struct usb_device *hdev, int index) } EXPORT_SYMBOL_GPL(usb_acpi_power_manageable); +#define UUID_USB_CONTROLLER_DSM "ce2ee385-00e6-48cb-9f05-2edb927c4899" +#define USB_DSM_DISABLE_U1_U2_FOR_PORT 5 + +/** + * usb_acpi_port_lpm_incapable - check if lpm should be disabled for a port. + * @hdev: USB device belonging to the usb hub + * @index: zero based port index + * + * Some USB3 ports may not support USB3 link power management U1/U2 states + * due to different retimer setup. ACPI provides _DSM method which returns 0x01 + * if U1 and U2 states should be disabled. Evaluate _DSM with: + * Arg0: UUID = ce2ee385-00e6-48cb-9f05-2edb927c4899 + * Arg1: Revision ID = 0 + * Arg2: Function Index = 5 + * Arg3: (empty) + * + * Return 1 if USB3 port is LPM incapable, negative on error, otherwise 0 + */ + +int usb_acpi_port_lpm_incapable(struct usb_device *hdev, int index) +{ + union acpi_object *obj; + acpi_handle port_handle; + int port1 = index + 1; + guid_t guid; + int ret; + + ret = guid_parse(UUID_USB_CONTROLLER_DSM, &guid); + if (ret) + return ret; + + port_handle = usb_get_hub_port_acpi_handle(hdev, port1); + if (!port_handle) { + dev_dbg(&hdev->dev, "port-%d no acpi handle\n", port1); + return -ENODEV; + } + + if (!acpi_check_dsm(port_handle, &guid, 0, + BIT(USB_DSM_DISABLE_U1_U2_FOR_PORT))) { + dev_dbg(&hdev->dev, "port-%d no _DSM function %d\n", + port1, USB_DSM_DISABLE_U1_U2_FOR_PORT); + return -ENODEV; + } + + obj = acpi_evaluate_dsm(port_handle, &guid, 0, + USB_DSM_DISABLE_U1_U2_FOR_PORT, NULL); + + if (!obj) + return -ENODEV; + + if (obj->type != ACPI_TYPE_INTEGER) { + dev_dbg(&hdev->dev, "evaluate port-%d _DSM failed\n", port1); + ACPI_FREE(obj); + return -EINVAL; + } + + if (obj->integer.value == 0x01) + ret = 1; + + ACPI_FREE(obj); + + return ret; +} +EXPORT_SYMBOL_GPL(usb_acpi_port_lpm_incapable); + /** * usb_acpi_set_power_state - control usb port's power via acpi power * resource diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index b2f72b0e75c6..be954a9abbe0 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -3,6 +3,7 @@ config USB_DWC3 tristate "DesignWare USB3 DRD Core Support" depends on (USB || USB_GADGET) && HAS_DMA + depends on (EXTCON || EXTCON=n) select USB_XHCI_PLATFORM if USB_XHCI_HCD select USB_ROLE_SWITCH if USB_DWC3_DUAL_ROLE help @@ -44,7 +45,6 @@ config USB_DWC3_GADGET config USB_DWC3_DUAL_ROLE bool "Dual Role mode" depends on ((USB=y || USB=USB_DWC3) && (USB_GADGET=y || USB_GADGET=USB_DWC3)) - depends on (EXTCON=y || EXTCON=USB_DWC3) help This is the default mode of working of DWC3 controller where both host and gadget features are enabled. diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c index 8607d4c23283..0745e9f11b2e 100644 --- a/drivers/usb/dwc3/dwc3-xilinx.c +++ b/drivers/usb/dwc3/dwc3-xilinx.c @@ -13,6 +13,7 @@ #include <linux/of.h> #include <linux/platform_device.h> #include <linux/dma-mapping.h> +#include <linux/gpio/consumer.h> #include <linux/of_gpio.h> #include <linux/of_platform.h> #include <linux/pm_runtime.h> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 789976567f9f..89dcfac01235 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1727,6 +1727,7 @@ static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool int else if (!ret) dep->flags |= DWC3_EP_END_TRANSFER_PENDING; + dep->flags &= ~DWC3_EP_DELAY_STOP; return ret; } @@ -3732,8 +3733,10 @@ void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, if (dep->number <= 1 && dwc->ep0state != EP0_DATA_PHASE) return; + if (interrupt && (dep->flags & DWC3_EP_DELAY_STOP)) + return; + if (!(dep->flags & DWC3_EP_TRANSFER_STARTED) || - (dep->flags & DWC3_EP_DELAY_STOP) || (dep->flags & DWC3_EP_END_TRANSFER_PENDING)) return; diff --git a/drivers/usb/fotg210/fotg210-core.c b/drivers/usb/fotg210/fotg210-core.c index 8a54edf921ac..ee740a6da463 100644 --- a/drivers/usb/fotg210/fotg210-core.c +++ b/drivers/usb/fotg210/fotg210-core.c @@ -144,10 +144,7 @@ static struct platform_driver fotg210_driver = { static int __init fotg210_init(void) { - if (usb_disabled()) - return -ENODEV; - - if (IS_ENABLED(CONFIG_USB_FOTG210_HCD)) + if (IS_ENABLED(CONFIG_USB_FOTG210_HCD) && !usb_disabled()) fotg210_hcd_init(); return platform_driver_register(&fotg210_driver); } diff --git a/drivers/usb/fotg210/fotg210-udc.c b/drivers/usb/fotg210/fotg210-udc.c index 66e1b7ee3346..87cca81bf4ac 100644 --- a/drivers/usb/fotg210/fotg210-udc.c +++ b/drivers/usb/fotg210/fotg210-udc.c @@ -1201,6 +1201,8 @@ int fotg210_udc_probe(struct platform_device *pdev) dev_info(dev, "found and initialized PHY\n"); } + ret = -ENOMEM; + for (i = 0; i < FOTG210_MAX_NUM_EP; i++) { fotg210->ep[i] = kzalloc(sizeof(struct fotg210_ep), GFP_KERNEL); if (!fotg210->ep[i]) diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index 96121d1c8df4..0853536cbf2e 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -393,6 +393,7 @@ static void gadget_info_attr_release(struct config_item *item) WARN_ON(!list_empty(&gi->string_list)); WARN_ON(!list_empty(&gi->available_func)); kfree(gi->composite.gadget_driver.function); + kfree(gi->composite.gadget_driver.driver.name); kfree(gi); } @@ -1572,7 +1573,6 @@ static const struct usb_gadget_driver configfs_driver_template = { .max_speed = USB_SPEED_SUPER_PLUS, .driver = { .owner = THIS_MODULE, - .name = "configfs-gadget", }, .match_existing_only = 1, }; @@ -1623,13 +1623,21 @@ static struct config_group *gadgets_make( gi->composite.gadget_driver = configfs_driver_template; + gi->composite.gadget_driver.driver.name = kasprintf(GFP_KERNEL, + "configfs-gadget.%s", name); + if (!gi->composite.gadget_driver.driver.name) + goto err; + gi->composite.gadget_driver.function = kstrdup(name, GFP_KERNEL); gi->composite.name = gi->composite.gadget_driver.function; if (!gi->composite.gadget_driver.function) - goto err; + goto out_free_driver_name; return &gi->group; + +out_free_driver_name: + kfree(gi->composite.gadget_driver.driver.name); err: kfree(gi); return ERR_PTR(-ENOMEM); diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 73dc10a77cde..523a961b910b 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -279,6 +279,9 @@ static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len) struct usb_request *req = ffs->ep0req; int ret; + if (!req) + return -EINVAL; + req->zero = len < le16_to_cpu(ffs->ev.setup.wLength); spin_unlock_irq(&ffs->ev.waitq.lock); @@ -1892,10 +1895,14 @@ static void functionfs_unbind(struct ffs_data *ffs) ENTER(); if (!WARN_ON(!ffs->gadget)) { + /* dequeue before freeing ep0req */ + usb_ep_dequeue(ffs->gadget->ep0, ffs->ep0req); + mutex_lock(&ffs->mutex); usb_ep_free_request(ffs->gadget->ep0, ffs->ep0req); ffs->ep0req = NULL; ffs->gadget = NULL; clear_bit(FFS_FL_BOUND, &ffs->flags); + mutex_unlock(&ffs->mutex); ffs_data_put(ffs); } } diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c index c36bcfa0e9b4..424bb3b666db 100644 --- a/drivers/usb/gadget/function/f_ncm.c +++ b/drivers/usb/gadget/function/f_ncm.c @@ -83,7 +83,9 @@ static inline struct f_ncm *func_to_ncm(struct usb_function *f) /* peak (theoretical) bulk transfer rate in bits-per-second */ static inline unsigned ncm_bitrate(struct usb_gadget *g) { - if (gadget_is_superspeed(g) && g->speed >= USB_SPEED_SUPER_PLUS) + if (!g) + return 0; + else if (gadget_is_superspeed(g) && g->speed >= USB_SPEED_SUPER_PLUS) return 4250000000U; else if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER) return 3750000000U; diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c index 01c3ead7d1b4..d605bc2e7e8f 100644 --- a/drivers/usb/gadget/legacy/inode.c +++ b/drivers/usb/gadget/legacy/inode.c @@ -229,6 +229,7 @@ static void put_ep (struct ep_data *data) */ static const char *CHIP; +static DEFINE_MUTEX(sb_mutex); /* Serialize superblock operations */ /*----------------------------------------------------------------------*/ @@ -2010,13 +2011,20 @@ gadgetfs_fill_super (struct super_block *sb, struct fs_context *fc) { struct inode *inode; struct dev_data *dev; + int rc; - if (the_device) - return -ESRCH; + mutex_lock(&sb_mutex); + + if (the_device) { + rc = -ESRCH; + goto Done; + } CHIP = usb_get_gadget_udc_name(); - if (!CHIP) - return -ENODEV; + if (!CHIP) { + rc = -ENODEV; + goto Done; + } /* superblock */ sb->s_blocksize = PAGE_SIZE; @@ -2053,13 +2061,17 @@ gadgetfs_fill_super (struct super_block *sb, struct fs_context *fc) * from binding to a controller. */ the_device = dev; - return 0; + rc = 0; + goto Done; -Enomem: + Enomem: kfree(CHIP); CHIP = NULL; + rc = -ENOMEM; - return -ENOMEM; + Done: + mutex_unlock(&sb_mutex); + return rc; } /* "mount -t gadgetfs path /dev/gadget" ends up here */ @@ -2081,6 +2093,7 @@ static int gadgetfs_init_fs_context(struct fs_context *fc) static void gadgetfs_kill_sb (struct super_block *sb) { + mutex_lock(&sb_mutex); kill_litter_super (sb); if (the_device) { put_dev (the_device); @@ -2088,6 +2101,7 @@ gadgetfs_kill_sb (struct super_block *sb) } kfree(CHIP); CHIP = NULL; + mutex_unlock(&sb_mutex); } /*----------------------------------------------------------------------*/ diff --git a/drivers/usb/gadget/legacy/webcam.c b/drivers/usb/gadget/legacy/webcam.c index 53e38f87472b..c06dd1af7a0c 100644 --- a/drivers/usb/gadget/legacy/webcam.c +++ b/drivers/usb/gadget/legacy/webcam.c @@ -293,6 +293,7 @@ static const struct uvc_descriptor_header * const uvc_fs_streaming_cls[] = { (const struct uvc_descriptor_header *) &uvc_format_yuv, (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p, (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p, + (const struct uvc_descriptor_header *) &uvc_color_matching, (const struct uvc_descriptor_header *) &uvc_format_mjpg, (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p, (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p, @@ -305,6 +306,7 @@ static const struct uvc_descriptor_header * const uvc_hs_streaming_cls[] = { (const struct uvc_descriptor_header *) &uvc_format_yuv, (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p, (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p, + (const struct uvc_descriptor_header *) &uvc_color_matching, (const struct uvc_descriptor_header *) &uvc_format_mjpg, (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p, (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p, @@ -317,6 +319,7 @@ static const struct uvc_descriptor_header * const uvc_ss_streaming_cls[] = { (const struct uvc_descriptor_header *) &uvc_format_yuv, (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p, (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p, + (const struct uvc_descriptor_header *) &uvc_color_matching, (const struct uvc_descriptor_header *) &uvc_format_mjpg, (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p, (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p, diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 9cea785934e5..38d06e5abfbb 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -29,7 +29,7 @@ #include "ehci-fsl.h" #define DRIVER_DESC "Freescale EHCI Host controller driver" -#define DRV_NAME "ehci-fsl" +#define DRV_NAME "fsl-ehci" static struct hc_driver __read_mostly fsl_ehci_hc_driver; diff --git a/drivers/usb/host/xen-hcd.c b/drivers/usb/host/xen-hcd.c index de1b09158318..46fdab940092 100644 --- a/drivers/usb/host/xen-hcd.c +++ b/drivers/usb/host/xen-hcd.c @@ -1530,15 +1530,13 @@ static void xenhcd_backend_changed(struct xenbus_device *dev, } } -static int xenhcd_remove(struct xenbus_device *dev) +static void xenhcd_remove(struct xenbus_device *dev) { struct xenhcd_info *info = dev_get_drvdata(&dev->dev); struct usb_hcd *hcd = xenhcd_info_to_hcd(info); xenhcd_destroy_rings(info); usb_put_hcd(hcd); - - return 0; } static int xenhcd_probe(struct xenbus_device *dev, diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 79d679b3e076..fb988e4ea924 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -78,9 +78,12 @@ static const char hcd_name[] = "xhci_hcd"; static struct hc_driver __read_mostly xhci_pci_hc_driver; static int xhci_pci_setup(struct usb_hcd *hcd); +static int xhci_pci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, + struct usb_tt *tt, gfp_t mem_flags); static const struct xhci_driver_overrides xhci_pci_overrides __initconst = { .reset = xhci_pci_setup, + .update_hub_device = xhci_pci_update_hub_device, }; /* called after powerup, by probe or system-pm "wakeup" */ @@ -352,8 +355,38 @@ static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) NULL); ACPI_FREE(obj); } + +static void xhci_find_lpm_incapable_ports(struct usb_hcd *hcd, struct usb_device *hdev) +{ + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + struct xhci_hub *rhub = &xhci->usb3_rhub; + int ret; + int i; + + /* This is not the usb3 roothub we are looking for */ + if (hcd != rhub->hcd) + return; + + if (hdev->maxchild > rhub->num_ports) { + dev_err(&hdev->dev, "USB3 roothub port number mismatch\n"); + return; + } + + for (i = 0; i < hdev->maxchild; i++) { + ret = usb_acpi_port_lpm_incapable(hdev, i); + + dev_dbg(&hdev->dev, "port-%d disable U1/U2 _DSM: %d\n", i + 1, ret); + + if (ret >= 0) { + rhub->ports[i]->lpm_incapable = ret; + continue; + } + } +} + #else static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) { } +static void xhci_find_lpm_incapable_ports(struct usb_hcd *hcd, struct usb_device *hdev) { } #endif /* CONFIG_ACPI */ /* called during probe() after chip reset completes */ @@ -386,6 +419,16 @@ static int xhci_pci_setup(struct usb_hcd *hcd) return xhci_pci_reinit(xhci, pdev); } +static int xhci_pci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, + struct usb_tt *tt, gfp_t mem_flags) +{ + /* Check if acpi claims some USB3 roothub ports are lpm incapable */ + if (!hdev->parent) + xhci_find_lpm_incapable_ports(hcd, hdev); + + return xhci_update_hub_device(hcd, hdev, tt, mem_flags); +} + /* * We need to register our own PCI probe function (instead of the USB core's * function) in order to create a second roothub under xHCI. @@ -455,6 +498,8 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) if (xhci->quirks & XHCI_DEFAULT_PM_RUNTIME_ALLOW) pm_runtime_allow(&dev->dev); + dma_set_max_seg_size(&dev->dev, UINT_MAX); + return 0; put_usb3_hcd: diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index ddc30037f9ce..f5b0e1ce22af 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1169,7 +1169,10 @@ static void xhci_kill_endpoint_urbs(struct xhci_hcd *xhci, struct xhci_virt_ep *ep; struct xhci_ring *ring; - ep = &xhci->devs[slot_id]->eps[ep_index]; + ep = xhci_get_virt_ep(xhci, slot_id, ep_index); + if (!ep) + return; + if ((ep->ep_state & EP_HAS_STREAMS) || (ep->ep_state & EP_GETTING_NO_STREAMS)) { int stream_id; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 79d7931c048a..2b280beb0011 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3974,6 +3974,7 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct xhci_virt_device *virt_dev; struct xhci_slot_ctx *slot_ctx; + unsigned long flags; int i, ret; /* @@ -4000,7 +4001,11 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) virt_dev->eps[i].ep_state &= ~EP_STOP_CMD_PENDING; virt_dev->udev = NULL; xhci_disable_slot(xhci, udev->slot_id); + + spin_lock_irqsave(&xhci->lock, flags); xhci_free_virt_device(xhci, udev->slot_id); + spin_unlock_irqrestore(&xhci->lock, flags); + } int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id) @@ -5044,6 +5049,7 @@ static int xhci_enable_usb3_lpm_timeout(struct usb_hcd *hcd, struct usb_device *udev, enum usb3_link_state state) { struct xhci_hcd *xhci; + struct xhci_port *port; u16 hub_encoded_timeout; int mel; int ret; @@ -5060,6 +5066,13 @@ static int xhci_enable_usb3_lpm_timeout(struct usb_hcd *hcd, if (xhci_check_tier_policy(xhci, udev, state) < 0) return USB3_LPM_DISABLED; + /* If connected to root port then check port can handle lpm */ + if (udev->parent && !udev->parent->parent) { + port = xhci->usb3_rhub.ports[udev->portnum - 1]; + if (port->lpm_incapable) + return USB3_LPM_DISABLED; + } + hub_encoded_timeout = xhci_calculate_lpm_timeout(hcd, udev, state); mel = calculate_max_exit_latency(udev, state, hub_encoded_timeout); if (mel < 0) { @@ -5119,7 +5132,7 @@ static int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd, /* Once a hub descriptor is fetched for a device, we need to update the xHC's * internal data structures for the device. */ -static int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, +int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, struct usb_tt *tt, gfp_t mem_flags) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); @@ -5219,6 +5232,7 @@ static int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, xhci_free_command(xhci, config_cmd); return ret; } +EXPORT_SYMBOL_GPL(xhci_update_hub_device); static int xhci_get_frame(struct usb_hcd *hcd) { @@ -5502,6 +5516,8 @@ void xhci_init_driver(struct hc_driver *drv, drv->check_bandwidth = over->check_bandwidth; if (over->reset_bandwidth) drv->reset_bandwidth = over->reset_bandwidth; + if (over->update_hub_device) + drv->update_hub_device = over->update_hub_device; } } EXPORT_SYMBOL_GPL(xhci_init_driver); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index c9f06c5e4e9d..dcee7f3207ad 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1735,6 +1735,7 @@ struct xhci_port { int hcd_portnum; struct xhci_hub *rhub; struct xhci_port_cap *port_cap; + unsigned int lpm_incapable:1; }; struct xhci_hub { @@ -1943,6 +1944,8 @@ struct xhci_driver_overrides { struct usb_host_endpoint *ep); int (*check_bandwidth)(struct usb_hcd *, struct usb_device *); void (*reset_bandwidth)(struct usb_hcd *, struct usb_device *); + int (*update_hub_device)(struct usb_hcd *hcd, struct usb_device *hdev, + struct usb_tt *tt, gfp_t mem_flags); }; #define XHCI_CFC_DELAY 10 @@ -2122,6 +2125,8 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep); int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev); void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev); +int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, + struct usb_tt *tt, gfp_t mem_flags); int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id); int xhci_ext_cap_init(struct xhci_hcd *xhci); diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index f9427a67789c..1e3df27bab58 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -814,7 +814,7 @@ static int iowarrior_probe(struct usb_interface *interface, break; case USB_DEVICE_ID_CODEMERCS_IOW100: - dev->report_size = 13; + dev->report_size = 12; break; } } diff --git a/drivers/usb/misc/onboard_usb_hub.c b/drivers/usb/misc/onboard_usb_hub.c index 94e7966e199d..969c4c4f2ae9 100644 --- a/drivers/usb/misc/onboard_usb_hub.c +++ b/drivers/usb/misc/onboard_usb_hub.c @@ -27,7 +27,10 @@ #include "onboard_usb_hub.h" +static void onboard_hub_attach_usb_driver(struct work_struct *work); + static struct usb_device_driver onboard_hub_usbdev_driver; +static DECLARE_WORK(attach_usb_driver_work, onboard_hub_attach_usb_driver); /************************** Platform driver **************************/ @@ -45,7 +48,6 @@ struct onboard_hub { bool is_powered_on; bool going_away; struct list_head udev_list; - struct work_struct attach_usb_driver_work; struct mutex lock; }; @@ -271,8 +273,7 @@ static int onboard_hub_probe(struct platform_device *pdev) * This needs to be done deferred to avoid self-deadlocks on systems * with nested onboard hubs. */ - INIT_WORK(&hub->attach_usb_driver_work, onboard_hub_attach_usb_driver); - schedule_work(&hub->attach_usb_driver_work); + schedule_work(&attach_usb_driver_work); return 0; } @@ -285,9 +286,6 @@ static int onboard_hub_remove(struct platform_device *pdev) hub->going_away = true; - if (&hub->attach_usb_driver_work != current_work()) - cancel_work_sync(&hub->attach_usb_driver_work); - mutex_lock(&hub->lock); /* unbind the USB devices to avoid dangling references to this device */ @@ -433,13 +431,13 @@ static int __init onboard_hub_init(void) { int ret; - ret = platform_driver_register(&onboard_hub_driver); + ret = usb_register_device_driver(&onboard_hub_usbdev_driver, THIS_MODULE); if (ret) return ret; - ret = usb_register_device_driver(&onboard_hub_usbdev_driver, THIS_MODULE); + ret = platform_driver_register(&onboard_hub_driver); if (ret) - platform_driver_unregister(&onboard_hub_driver); + usb_deregister_device_driver(&onboard_hub_usbdev_driver); return ret; } @@ -449,6 +447,8 @@ static void __exit onboard_hub_exit(void) { usb_deregister_device_driver(&onboard_hub_usbdev_driver); platform_driver_unregister(&onboard_hub_driver); + + cancel_work_sync(&attach_usb_driver_work); } module_exit(onboard_hub_exit); diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 476f55d1fec3..44a21ec865fb 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -411,8 +411,10 @@ static int omap2430_probe(struct platform_device *pdev) memset(musb_res, 0, sizeof(*musb_res) * ARRAY_SIZE(musb_res)); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) + if (!res) { + ret = -EINVAL; goto err2; + } musb_res[i].start = res->start; musb_res[i].end = res->end; diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 67372acc2352..832ad592b7ef 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -60,6 +60,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x0846, 0x1100) }, /* NetGear Managed Switch M4100 series, M5300 series, M7100 series */ { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */ { USB_DEVICE(0x08FD, 0x000A) }, /* Digianswer A/S , ZigBee/802.15.4 MAC Device */ + { USB_DEVICE(0x0908, 0x0070) }, /* Siemens SCALANCE LPE-9000 USB Serial Console */ { USB_DEVICE(0x0908, 0x01FF) }, /* Siemens RUGGEDCOM USB Serial Console */ { USB_DEVICE(0x0988, 0x0578) }, /* Teraoka AD2000 */ { USB_DEVICE(0x0B00, 0x3070) }, /* Ingenico 3070 */ diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index dee79c7d82d5..ee5ac4ef7e16 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -255,10 +255,16 @@ static void option_instat_callback(struct urb *urb); #define QUECTEL_PRODUCT_EP06 0x0306 #define QUECTEL_PRODUCT_EM05G 0x030a #define QUECTEL_PRODUCT_EM060K 0x030b +#define QUECTEL_PRODUCT_EM05G_CS 0x030c +#define QUECTEL_PRODUCT_EM05CN_SG 0x0310 #define QUECTEL_PRODUCT_EM05G_SG 0x0311 +#define QUECTEL_PRODUCT_EM05CN 0x0312 +#define QUECTEL_PRODUCT_EM05G_GR 0x0313 +#define QUECTEL_PRODUCT_EM05G_RS 0x0314 #define QUECTEL_PRODUCT_EM12 0x0512 #define QUECTEL_PRODUCT_RM500Q 0x0800 #define QUECTEL_PRODUCT_RM520N 0x0801 +#define QUECTEL_PRODUCT_EC200U 0x0901 #define QUECTEL_PRODUCT_EC200S_CN 0x6002 #define QUECTEL_PRODUCT_EC200T 0x6026 #define QUECTEL_PRODUCT_RM500K 0x7001 @@ -1159,8 +1165,18 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0xff, 0xff), .driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0, 0) }, + { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05CN, 0xff), + .driver_info = RSVD(6) | ZLP }, + { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05CN_SG, 0xff), + .driver_info = RSVD(6) | ZLP }, { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G, 0xff), .driver_info = RSVD(6) | ZLP }, + { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G_CS, 0xff), + .driver_info = RSVD(6) | ZLP }, + { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G_GR, 0xff), + .driver_info = RSVD(6) | ZLP }, + { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G_RS, 0xff), + .driver_info = RSVD(6) | ZLP }, { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G_SG, 0xff), .driver_info = RSVD(6) | ZLP }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0x00, 0x40) }, @@ -1180,6 +1196,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0xff, 0x30) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0, 0x40) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0, 0) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200U, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200S_CN, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200T, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500K, 0xff, 0x00, 0x00) }, diff --git a/drivers/usb/storage/uas-detect.h b/drivers/usb/storage/uas-detect.h index 3f720faa6f97..d73282c0ec50 100644 --- a/drivers/usb/storage/uas-detect.h +++ b/drivers/usb/storage/uas-detect.h @@ -116,6 +116,19 @@ static int uas_use_uas_driver(struct usb_interface *intf, if (le16_to_cpu(udev->descriptor.idVendor) == 0x0bc2) flags |= US_FL_NO_ATA_1X; + /* + * RTL9210-based enclosure from HIKSEMI, MD202 reportedly have issues + * with UAS. This isn't distinguishable with just idVendor and + * idProduct, use manufacturer and product too. + * + * Reported-by: Hongling Zeng <zenghongling@kylinos.cn> + */ + if (le16_to_cpu(udev->descriptor.idVendor) == 0x0bda && + le16_to_cpu(udev->descriptor.idProduct) == 0x9210 && + (udev->manufacturer && !strcmp(udev->manufacturer, "HIKSEMI")) && + (udev->product && !strcmp(udev->product, "MD202"))) + flags |= US_FL_IGNORE_UAS; + usb_stor_adjust_quirks(udev, &flags); if (flags & US_FL_IGNORE_UAS) { diff --git a/drivers/usb/storage/unusual_uas.h b/drivers/usb/storage/unusual_uas.h index 251778d14e2d..c7b763d6d102 100644 --- a/drivers/usb/storage/unusual_uas.h +++ b/drivers/usb/storage/unusual_uas.h @@ -83,13 +83,6 @@ UNUSUAL_DEV(0x0bc2, 0x331a, 0x0000, 0x9999, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NO_REPORT_LUNS), -/* Reported-by: Hongling Zeng <zenghongling@kylinos.cn> */ -UNUSUAL_DEV(0x0bda, 0x9210, 0x0000, 0x9999, - "Hiksemi", - "External HDD", - USB_SC_DEVICE, USB_PR_DEVICE, NULL, - US_FL_IGNORE_UAS), - /* Reported-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> */ UNUSUAL_DEV(0x13fd, 0x3940, 0x0000, 0x9999, "Initio Corporation", diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c index de66a2949e33..9a6860285fbe 100644 --- a/drivers/usb/typec/altmodes/displayport.c +++ b/drivers/usb/typec/altmodes/displayport.c @@ -419,6 +419,18 @@ static const char * const pin_assignments[] = { [DP_PIN_ASSIGN_F] = "F", }; +/* + * Helper function to extract a peripheral's currently supported + * Pin Assignments from its DisplayPort alternate mode state. + */ +static u8 get_current_pin_assignments(struct dp_altmode *dp) +{ + if (DP_CONF_CURRENTLY(dp->data.conf) == DP_CONF_UFP_U_AS_DFP_D) + return DP_CAP_PIN_ASSIGN_DFP_D(dp->alt->vdo); + else + return DP_CAP_PIN_ASSIGN_UFP_D(dp->alt->vdo); +} + static ssize_t pin_assignment_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) @@ -445,10 +457,7 @@ pin_assignment_store(struct device *dev, struct device_attribute *attr, goto out_unlock; } - if (DP_CONF_CURRENTLY(dp->data.conf) == DP_CONF_DFP_D) - assignments = DP_CAP_UFP_D_PIN_ASSIGN(dp->alt->vdo); - else - assignments = DP_CAP_DFP_D_PIN_ASSIGN(dp->alt->vdo); + assignments = get_current_pin_assignments(dp); if (!(DP_CONF_GET_PIN_ASSIGN(conf) & assignments)) { ret = -EINVAL; @@ -485,10 +494,7 @@ static ssize_t pin_assignment_show(struct device *dev, cur = get_count_order(DP_CONF_GET_PIN_ASSIGN(dp->data.conf)); - if (DP_CONF_CURRENTLY(dp->data.conf) == DP_CONF_DFP_D) - assignments = DP_CAP_UFP_D_PIN_ASSIGN(dp->alt->vdo); - else - assignments = DP_CAP_DFP_D_PIN_ASSIGN(dp->alt->vdo); + assignments = get_current_pin_assignments(dp); for (i = 0; assignments; assignments >>= 1, i++) { if (assignments & 1) { diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 904c7b4ce2f0..59b366b5c614 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -4594,14 +4594,13 @@ static void run_state_machine(struct tcpm_port *port) tcpm_set_state(port, ready_state(port), 0); break; case DR_SWAP_CHANGE_DR: - if (port->data_role == TYPEC_HOST) { - tcpm_unregister_altmodes(port); + tcpm_unregister_altmodes(port); + if (port->data_role == TYPEC_HOST) tcpm_set_roles(port, true, port->pwr_role, TYPEC_DEVICE); - } else { + else tcpm_set_roles(port, true, port->pwr_role, TYPEC_HOST); - } tcpm_ams_finish(port); tcpm_set_state(port, ready_state(port), 0); break; diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index eabe519013e7..1292241d581a 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -187,6 +187,7 @@ EXPORT_SYMBOL_GPL(ucsi_send_command); struct ucsi_work { struct delayed_work work; + struct list_head node; unsigned long delay; unsigned int count; struct ucsi_connector *con; @@ -202,6 +203,7 @@ static void ucsi_poll_worker(struct work_struct *work) mutex_lock(&con->lock); if (!con->partner) { + list_del(&uwork->node); mutex_unlock(&con->lock); kfree(uwork); return; @@ -209,10 +211,12 @@ static void ucsi_poll_worker(struct work_struct *work) ret = uwork->cb(con); - if (uwork->count-- && (ret == -EBUSY || ret == -ETIMEDOUT)) + if (uwork->count-- && (ret == -EBUSY || ret == -ETIMEDOUT)) { queue_delayed_work(con->wq, &uwork->work, uwork->delay); - else + } else { + list_del(&uwork->node); kfree(uwork); + } mutex_unlock(&con->lock); } @@ -236,6 +240,7 @@ static int ucsi_partner_task(struct ucsi_connector *con, uwork->con = con; uwork->cb = cb; + list_add_tail(&uwork->node, &con->partner_tasks); queue_delayed_work(con->wq, &uwork->work, delay); return 0; @@ -1056,6 +1061,7 @@ static int ucsi_register_port(struct ucsi *ucsi, int index) INIT_WORK(&con->work, ucsi_handle_connector_change); init_completion(&con->complete); mutex_init(&con->lock); + INIT_LIST_HEAD(&con->partner_tasks); con->num = index + 1; con->ucsi = ucsi; @@ -1420,8 +1426,20 @@ void ucsi_unregister(struct ucsi *ucsi) ucsi_unregister_altmodes(&ucsi->connector[i], UCSI_RECIPIENT_CON); ucsi_unregister_port_psy(&ucsi->connector[i]); - if (ucsi->connector[i].wq) + + if (ucsi->connector[i].wq) { + struct ucsi_work *uwork; + + mutex_lock(&ucsi->connector[i].lock); + /* + * queue delayed items immediately so they can execute + * and free themselves before the wq is destroyed + */ + list_for_each_entry(uwork, &ucsi->connector[i].partner_tasks, node) + mod_delayed_work(ucsi->connector[i].wq, &uwork->work, 0); + mutex_unlock(&ucsi->connector[i].lock); destroy_workqueue(ucsi->connector[i].wq); + } typec_unregister_port(ucsi->connector[i].port); } diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h index c968474ee547..60ce9fb6e745 100644 --- a/drivers/usb/typec/ucsi/ucsi.h +++ b/drivers/usb/typec/ucsi/ucsi.h @@ -322,6 +322,7 @@ struct ucsi_connector { struct work_struct work; struct completion complete; struct workqueue_struct *wq; + struct list_head partner_tasks; struct typec_port *port; struct typec_partner *partner; diff --git a/drivers/vdpa/mlx5/core/mlx5_vdpa.h b/drivers/vdpa/mlx5/core/mlx5_vdpa.h index 6af9fdbb86b7..058fbe28107e 100644 --- a/drivers/vdpa/mlx5/core/mlx5_vdpa.h +++ b/drivers/vdpa/mlx5/core/mlx5_vdpa.h @@ -116,8 +116,9 @@ int mlx5_vdpa_create_mkey(struct mlx5_vdpa_dev *mvdev, u32 *mkey, u32 *in, int inlen); int mlx5_vdpa_destroy_mkey(struct mlx5_vdpa_dev *mvdev, u32 mkey); int mlx5_vdpa_handle_set_map(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb, - bool *change_map); -int mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb); + bool *change_map, unsigned int asid); +int mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb, + unsigned int asid); void mlx5_vdpa_destroy_mr(struct mlx5_vdpa_dev *mvdev); #define mlx5_vdpa_warn(__dev, format, ...) \ diff --git a/drivers/vdpa/mlx5/core/mr.c b/drivers/vdpa/mlx5/core/mr.c index a639b9208d41..0a1e0b0dc37e 100644 --- a/drivers/vdpa/mlx5/core/mr.c +++ b/drivers/vdpa/mlx5/core/mr.c @@ -311,7 +311,6 @@ static int add_direct_chain(struct mlx5_vdpa_dev *mvdev, u64 start, u64 size, u8 u64 st; u64 sz; int err; - int i = 0; st = start; while (size) { @@ -336,7 +335,6 @@ static int add_direct_chain(struct mlx5_vdpa_dev *mvdev, u64 start, u64 size, u8 mr->num_directs++; mr->num_klms++; st += sz; - i++; } list_splice_tail(&tmp, &mr->head); return 0; @@ -511,7 +509,8 @@ out: mutex_unlock(&mr->mkey_mtx); } -static int _mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb) +static int _mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev, + struct vhost_iotlb *iotlb, unsigned int asid) { struct mlx5_vdpa_mr *mr = &mvdev->mr; int err; @@ -519,42 +518,49 @@ static int _mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb if (mr->initialized) return 0; - if (iotlb) - err = create_user_mr(mvdev, iotlb); - else - err = create_dma_mr(mvdev, mr); + if (mvdev->group2asid[MLX5_VDPA_DATAVQ_GROUP] == asid) { + if (iotlb) + err = create_user_mr(mvdev, iotlb); + else + err = create_dma_mr(mvdev, mr); - if (err) - return err; + if (err) + return err; + } - err = dup_iotlb(mvdev, iotlb); - if (err) - goto out_err; + if (mvdev->group2asid[MLX5_VDPA_CVQ_GROUP] == asid) { + err = dup_iotlb(mvdev, iotlb); + if (err) + goto out_err; + } mr->initialized = true; return 0; out_err: - if (iotlb) - destroy_user_mr(mvdev, mr); - else - destroy_dma_mr(mvdev, mr); + if (mvdev->group2asid[MLX5_VDPA_DATAVQ_GROUP] == asid) { + if (iotlb) + destroy_user_mr(mvdev, mr); + else + destroy_dma_mr(mvdev, mr); + } return err; } -int mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb) +int mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb, + unsigned int asid) { int err; mutex_lock(&mvdev->mr.mkey_mtx); - err = _mlx5_vdpa_create_mr(mvdev, iotlb); + err = _mlx5_vdpa_create_mr(mvdev, iotlb, asid); mutex_unlock(&mvdev->mr.mkey_mtx); return err; } int mlx5_vdpa_handle_set_map(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb, - bool *change_map) + bool *change_map, unsigned int asid) { struct mlx5_vdpa_mr *mr = &mvdev->mr; int err = 0; @@ -566,7 +572,7 @@ int mlx5_vdpa_handle_set_map(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *io *change_map = true; } if (!*change_map) - err = _mlx5_vdpa_create_mr(mvdev, iotlb); + err = _mlx5_vdpa_create_mr(mvdev, iotlb, asid); mutex_unlock(&mr->mkey_mtx); return err; diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c index 90913365def4..3a6dbbc6440d 100644 --- a/drivers/vdpa/mlx5/net/mlx5_vnet.c +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c @@ -1468,11 +1468,13 @@ static int mlx5_vdpa_add_mac_vlan_rules(struct mlx5_vdpa_net *ndev, u8 *mac, dmac_v = MLX5_ADDR_OF(fte_match_param, headers_v, outer_headers.dmac_47_16); eth_broadcast_addr(dmac_c); ether_addr_copy(dmac_v, mac); - MLX5_SET(fte_match_set_lyr_2_4, headers_c, cvlan_tag, 1); + if (ndev->mvdev.actual_features & BIT_ULL(VIRTIO_NET_F_CTRL_VLAN)) { + MLX5_SET(fte_match_set_lyr_2_4, headers_c, cvlan_tag, 1); + MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, first_vid); + } if (tagged) { MLX5_SET(fte_match_set_lyr_2_4, headers_v, cvlan_tag, 1); - MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, first_vid); - MLX5_SET(fte_match_set_lyr_2_4, headers_c, first_vid, vid); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_vid, vid); } flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR; @@ -1684,7 +1686,7 @@ static virtio_net_ctrl_ack handle_ctrl_mac(struct mlx5_vdpa_dev *mvdev, u8 cmd) /* Need recreate the flow table entry, so that the packet could forward back */ - mac_vlan_del(ndev, ndev->config.mac, 0, false); + mac_vlan_del(ndev, mac_back, 0, false); if (mac_vlan_add(ndev, ndev->config.mac, 0, false)) { mlx5_vdpa_warn(mvdev, "failed to insert forward rules, try to restore\n"); @@ -1821,6 +1823,9 @@ static virtio_net_ctrl_ack handle_ctrl_vlan(struct mlx5_vdpa_dev *mvdev, u8 cmd) size_t read; u16 id; + if (!(ndev->mvdev.actual_features & BIT_ULL(VIRTIO_NET_F_CTRL_VLAN))) + return status; + switch (cmd) { case VIRTIO_NET_CTRL_VLAN_ADD: read = vringh_iov_pull_iotlb(&cvq->vring, &cvq->riov, &vlan, sizeof(vlan)); @@ -2389,7 +2394,8 @@ static void restore_channels_info(struct mlx5_vdpa_net *ndev) } } -static int mlx5_vdpa_change_map(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb) +static int mlx5_vdpa_change_map(struct mlx5_vdpa_dev *mvdev, + struct vhost_iotlb *iotlb, unsigned int asid) { struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev); int err; @@ -2401,7 +2407,7 @@ static int mlx5_vdpa_change_map(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb teardown_driver(ndev); mlx5_vdpa_destroy_mr(mvdev); - err = mlx5_vdpa_create_mr(mvdev, iotlb); + err = mlx5_vdpa_create_mr(mvdev, iotlb, asid); if (err) goto err_mr; @@ -2582,7 +2588,7 @@ static int mlx5_vdpa_reset(struct vdpa_device *vdev) ++mvdev->generation; if (MLX5_CAP_GEN(mvdev->mdev, umem_uid_0)) { - if (mlx5_vdpa_create_mr(mvdev, NULL)) + if (mlx5_vdpa_create_mr(mvdev, NULL, 0)) mlx5_vdpa_warn(mvdev, "create MR failed\n"); } up_write(&ndev->reslock); @@ -2618,41 +2624,20 @@ static u32 mlx5_vdpa_get_generation(struct vdpa_device *vdev) return mvdev->generation; } -static int set_map_control(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb) -{ - u64 start = 0ULL, last = 0ULL - 1; - struct vhost_iotlb_map *map; - int err = 0; - - spin_lock(&mvdev->cvq.iommu_lock); - vhost_iotlb_reset(mvdev->cvq.iotlb); - - for (map = vhost_iotlb_itree_first(iotlb, start, last); map; - map = vhost_iotlb_itree_next(map, start, last)) { - err = vhost_iotlb_add_range(mvdev->cvq.iotlb, map->start, - map->last, map->addr, map->perm); - if (err) - goto out; - } - -out: - spin_unlock(&mvdev->cvq.iommu_lock); - return err; -} - -static int set_map_data(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb) +static int set_map_data(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb, + unsigned int asid) { bool change_map; int err; - err = mlx5_vdpa_handle_set_map(mvdev, iotlb, &change_map); + err = mlx5_vdpa_handle_set_map(mvdev, iotlb, &change_map, asid); if (err) { mlx5_vdpa_warn(mvdev, "set map failed(%d)\n", err); return err; } if (change_map) - err = mlx5_vdpa_change_map(mvdev, iotlb); + err = mlx5_vdpa_change_map(mvdev, iotlb, asid); return err; } @@ -2665,16 +2650,7 @@ static int mlx5_vdpa_set_map(struct vdpa_device *vdev, unsigned int asid, int err = -EINVAL; down_write(&ndev->reslock); - if (mvdev->group2asid[MLX5_VDPA_DATAVQ_GROUP] == asid) { - err = set_map_data(mvdev, iotlb); - if (err) - goto out; - } - - if (mvdev->group2asid[MLX5_VDPA_CVQ_GROUP] == asid) - err = set_map_control(mvdev, iotlb); - -out: + err = set_map_data(mvdev, iotlb, asid); up_write(&ndev->reslock); return err; } @@ -2840,8 +2816,8 @@ static int mlx5_vdpa_suspend(struct vdpa_device *vdev) int i; down_write(&ndev->reslock); - mlx5_notifier_unregister(mvdev->mdev, &ndev->nb); ndev->nb_registered = false; + mlx5_notifier_unregister(mvdev->mdev, &ndev->nb); flush_workqueue(ndev->mvdev.wq); for (i = 0; i < ndev->cur_num_vqs; i++) { mvq = &ndev->vqs[i]; @@ -3019,7 +2995,7 @@ static void update_carrier(struct work_struct *work) else ndev->config.status &= cpu_to_mlx5vdpa16(mvdev, ~VIRTIO_NET_S_LINK_UP); - if (ndev->config_cb.callback) + if (ndev->nb_registered && ndev->config_cb.callback) ndev->config_cb.callback(ndev->config_cb.private); kfree(wqent); @@ -3036,21 +3012,13 @@ static int event_handler(struct notifier_block *nb, unsigned long event, void *p switch (eqe->sub_type) { case MLX5_PORT_CHANGE_SUBTYPE_DOWN: case MLX5_PORT_CHANGE_SUBTYPE_ACTIVE: - down_read(&ndev->reslock); - if (!ndev->nb_registered) { - up_read(&ndev->reslock); - return NOTIFY_DONE; - } wqent = kzalloc(sizeof(*wqent), GFP_ATOMIC); - if (!wqent) { - up_read(&ndev->reslock); + if (!wqent) return NOTIFY_DONE; - } wqent->mvdev = &ndev->mvdev; INIT_WORK(&wqent->work, update_carrier); queue_work(ndev->mvdev.wq, &wqent->work); - up_read(&ndev->reslock); ret = NOTIFY_OK; break; default: @@ -3185,7 +3153,7 @@ static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name, goto err_mpfs; if (MLX5_CAP_GEN(mvdev->mdev, umem_uid_0)) { - err = mlx5_vdpa_create_mr(mvdev, NULL); + err = mlx5_vdpa_create_mr(mvdev, NULL, 0); if (err) goto err_res; } @@ -3237,8 +3205,8 @@ static void mlx5_vdpa_dev_del(struct vdpa_mgmt_dev *v_mdev, struct vdpa_device * struct workqueue_struct *wq; if (ndev->nb_registered) { - mlx5_notifier_unregister(mvdev->mdev, &ndev->nb); ndev->nb_registered = false; + mlx5_notifier_unregister(mvdev->mdev, &ndev->nb); } wq = mvdev->wq; mvdev->wq = NULL; diff --git a/drivers/vdpa/vdpa.c b/drivers/vdpa/vdpa.c index febdc99b51a7..8ef7aa1365cc 100644 --- a/drivers/vdpa/vdpa.c +++ b/drivers/vdpa/vdpa.c @@ -855,7 +855,7 @@ static int vdpa_dev_net_config_fill(struct vdpa_device *vdev, struct sk_buff *ms features_device = vdev->config->get_device_features(vdev); - if (nla_put_u64_64bit(msg, VDPA_ATTR_VDPA_DEV_SUPPORTED_FEATURES, features_device, + if (nla_put_u64_64bit(msg, VDPA_ATTR_DEV_FEATURES, features_device, VDPA_ATTR_PAD)) return -EMSGSIZE; @@ -935,7 +935,6 @@ static int vdpa_fill_stats_rec(struct vdpa_device *vdev, struct sk_buff *msg, { struct virtio_net_config config = {}; u64 features; - u16 max_vqp; u8 status; int err; @@ -946,15 +945,15 @@ static int vdpa_fill_stats_rec(struct vdpa_device *vdev, struct sk_buff *msg, } vdpa_get_config_unlocked(vdev, 0, &config, sizeof(config)); - max_vqp = __virtio16_to_cpu(true, config.max_virtqueue_pairs); - if (nla_put_u16(msg, VDPA_ATTR_DEV_NET_CFG_MAX_VQP, max_vqp)) - return -EMSGSIZE; - features = vdev->config->get_driver_features(vdev); if (nla_put_u64_64bit(msg, VDPA_ATTR_DEV_NEGOTIATED_FEATURES, features, VDPA_ATTR_PAD)) return -EMSGSIZE; + err = vdpa_dev_net_mq_config_fill(msg, features, &config); + if (err) + return err; + if (nla_put_u32(msg, VDPA_ATTR_DEV_QUEUE_INDEX, index)) return -EMSGSIZE; diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim.c b/drivers/vdpa/vdpa_sim/vdpa_sim.c index b071f0d842fb..cb88891b44a8 100644 --- a/drivers/vdpa/vdpa_sim/vdpa_sim.c +++ b/drivers/vdpa/vdpa_sim/vdpa_sim.c @@ -67,8 +67,7 @@ static void vdpasim_queue_ready(struct vdpasim *vdpasim, unsigned int idx) { struct vdpasim_virtqueue *vq = &vdpasim->vqs[idx]; - vringh_init_iotlb(&vq->vring, vdpasim->dev_attr.supported_features, - VDPASIM_QUEUE_MAX, false, + vringh_init_iotlb(&vq->vring, vdpasim->features, vq->num, false, (struct vring_desc *)(uintptr_t)vq->desc_addr, (struct vring_avail *) (uintptr_t)vq->driver_addr, @@ -690,7 +689,9 @@ static void vdpasim_free(struct vdpa_device *vdpa) } kvfree(vdpasim->buffer); - vhost_iotlb_free(vdpasim->iommu); + for (i = 0; i < vdpasim->dev_attr.nas; i++) + vhost_iotlb_reset(&vdpasim->iommu[i]); + kfree(vdpasim->iommu); kfree(vdpasim->vqs); kfree(vdpasim->config); } diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c b/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c index c6db1a1baf76..f745926237a8 100644 --- a/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c +++ b/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c @@ -427,8 +427,10 @@ static int __init vdpasim_blk_init(void) int ret; ret = device_register(&vdpasim_blk_mgmtdev); - if (ret) + if (ret) { + put_device(&vdpasim_blk_mgmtdev); return ret; + } ret = vdpa_mgmtdev_register(&mgmt_dev); if (ret) diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim_net.c b/drivers/vdpa/vdpa_sim/vdpa_sim_net.c index c3cb225ea469..584b975a98a7 100644 --- a/drivers/vdpa/vdpa_sim/vdpa_sim_net.c +++ b/drivers/vdpa/vdpa_sim/vdpa_sim_net.c @@ -62,6 +62,9 @@ static bool receive_filter(struct vdpasim *vdpasim, size_t len) if (len < ETH_ALEN + hdr_len) return false; + if (is_broadcast_ether_addr(vdpasim->buffer + hdr_len) || + is_multicast_ether_addr(vdpasim->buffer + hdr_len)) + return true; if (!strncmp(vdpasim->buffer + hdr_len, vio_config->mac, ETH_ALEN)) return true; @@ -305,8 +308,10 @@ static int __init vdpasim_net_init(void) int ret; ret = device_register(&vdpasim_net_mgmtdev); - if (ret) + if (ret) { + put_device(&vdpasim_net_mgmtdev); return ret; + } ret = vdpa_mgmtdev_register(&mgmt_dev); if (ret) diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vduse_dev.c index 0dd3c1f291da..0c3b48616a9f 100644 --- a/drivers/vdpa/vdpa_user/vduse_dev.c +++ b/drivers/vdpa/vdpa_user/vduse_dev.c @@ -1440,6 +1440,9 @@ static bool vduse_validate_config(struct vduse_dev_config *config) if (config->config_size > PAGE_SIZE) return false; + if (config->vq_num > 0xffff) + return false; + if (!device_is_allowed(config->device_id)) return false; diff --git a/drivers/vdpa/virtio_pci/vp_vdpa.c b/drivers/vdpa/virtio_pci/vp_vdpa.c index d448db0c4de3..8fe267ca3e76 100644 --- a/drivers/vdpa/virtio_pci/vp_vdpa.c +++ b/drivers/vdpa/virtio_pci/vp_vdpa.c @@ -647,7 +647,7 @@ static void vp_vdpa_remove(struct pci_dev *pdev) mdev = vp_vdpa_mgtdev->mdev; vp_modern_remove(mdev); vdpa_mgmtdev_unregister(&vp_vdpa_mgtdev->mgtdev); - kfree(&vp_vdpa_mgtdev->mgtdev.id_table); + kfree(vp_vdpa_mgtdev->mgtdev.id_table); kfree(mdev); kfree(vp_vdpa_mgtdev); } diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index 23c24fe98c00..2209372f236d 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -1856,24 +1856,33 @@ unwind: * significantly boosts non-hugetlbfs mappings and doesn't seem to hurt when * hugetlbfs is in use. */ -static void vfio_test_domain_fgsp(struct vfio_domain *domain) +static void vfio_test_domain_fgsp(struct vfio_domain *domain, struct list_head *regions) { - struct page *pages; int ret, order = get_order(PAGE_SIZE * 2); + struct vfio_iova *region; + struct page *pages; + dma_addr_t start; pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, order); if (!pages) return; - ret = iommu_map(domain->domain, 0, page_to_phys(pages), PAGE_SIZE * 2, - IOMMU_READ | IOMMU_WRITE | IOMMU_CACHE); - if (!ret) { - size_t unmapped = iommu_unmap(domain->domain, 0, PAGE_SIZE); + list_for_each_entry(region, regions, list) { + start = ALIGN(region->start, PAGE_SIZE * 2); + if (start >= region->end || (region->end - start < PAGE_SIZE * 2)) + continue; - if (unmapped == PAGE_SIZE) - iommu_unmap(domain->domain, PAGE_SIZE, PAGE_SIZE); - else - domain->fgsp = true; + ret = iommu_map(domain->domain, start, page_to_phys(pages), PAGE_SIZE * 2, + IOMMU_READ | IOMMU_WRITE | IOMMU_CACHE); + if (!ret) { + size_t unmapped = iommu_unmap(domain->domain, start, PAGE_SIZE); + + if (unmapped == PAGE_SIZE) + iommu_unmap(domain->domain, start + PAGE_SIZE, PAGE_SIZE); + else + domain->fgsp = true; + } + break; } __free_pages(pages, order); @@ -2326,7 +2335,7 @@ static int vfio_iommu_type1_attach_group(void *iommu_data, } } - vfio_test_domain_fgsp(domain); + vfio_test_domain_fgsp(domain, &iova_copy); /* replay mappings on new domains */ ret = vfio_iommu_replay(iommu, domain); diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c index 166044642fd5..ec32f785dfde 100644 --- a/drivers/vhost/vdpa.c +++ b/drivers/vhost/vdpa.c @@ -65,6 +65,10 @@ static DEFINE_IDA(vhost_vdpa_ida); static dev_t vhost_vdpa_major; +static void vhost_vdpa_iotlb_unmap(struct vhost_vdpa *v, + struct vhost_iotlb *iotlb, u64 start, + u64 last, u32 asid); + static inline u32 iotlb_to_asid(struct vhost_iotlb *iotlb) { struct vhost_vdpa_as *as = container_of(iotlb, struct @@ -135,7 +139,7 @@ static int vhost_vdpa_remove_as(struct vhost_vdpa *v, u32 asid) return -EINVAL; hlist_del(&as->hash_link); - vhost_iotlb_reset(&as->iotlb); + vhost_vdpa_iotlb_unmap(v, &as->iotlb, 0ULL, 0ULL - 1, asid); kfree(as); return 0; @@ -683,10 +687,20 @@ static long vhost_vdpa_unlocked_ioctl(struct file *filep, mutex_unlock(&d->mutex); return r; } +static void vhost_vdpa_general_unmap(struct vhost_vdpa *v, + struct vhost_iotlb_map *map, u32 asid) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + if (ops->dma_map) { + ops->dma_unmap(vdpa, asid, map->start, map->size); + } else if (ops->set_map == NULL) { + iommu_unmap(v->domain, map->start, map->size); + } +} -static void vhost_vdpa_pa_unmap(struct vhost_vdpa *v, - struct vhost_iotlb *iotlb, - u64 start, u64 last) +static void vhost_vdpa_pa_unmap(struct vhost_vdpa *v, struct vhost_iotlb *iotlb, + u64 start, u64 last, u32 asid) { struct vhost_dev *dev = &v->vdev; struct vhost_iotlb_map *map; @@ -703,13 +717,13 @@ static void vhost_vdpa_pa_unmap(struct vhost_vdpa *v, unpin_user_page(page); } atomic64_sub(PFN_DOWN(map->size), &dev->mm->pinned_vm); + vhost_vdpa_general_unmap(v, map, asid); vhost_iotlb_map_free(iotlb, map); } } -static void vhost_vdpa_va_unmap(struct vhost_vdpa *v, - struct vhost_iotlb *iotlb, - u64 start, u64 last) +static void vhost_vdpa_va_unmap(struct vhost_vdpa *v, struct vhost_iotlb *iotlb, + u64 start, u64 last, u32 asid) { struct vhost_iotlb_map *map; struct vdpa_map_file *map_file; @@ -718,20 +732,21 @@ static void vhost_vdpa_va_unmap(struct vhost_vdpa *v, map_file = (struct vdpa_map_file *)map->opaque; fput(map_file->file); kfree(map_file); + vhost_vdpa_general_unmap(v, map, asid); vhost_iotlb_map_free(iotlb, map); } } static void vhost_vdpa_iotlb_unmap(struct vhost_vdpa *v, - struct vhost_iotlb *iotlb, - u64 start, u64 last) + struct vhost_iotlb *iotlb, u64 start, + u64 last, u32 asid) { struct vdpa_device *vdpa = v->vdpa; if (vdpa->use_va) - return vhost_vdpa_va_unmap(v, iotlb, start, last); + return vhost_vdpa_va_unmap(v, iotlb, start, last, asid); - return vhost_vdpa_pa_unmap(v, iotlb, start, last); + return vhost_vdpa_pa_unmap(v, iotlb, start, last, asid); } static int perm_to_iommu_flags(u32 perm) @@ -798,17 +813,12 @@ static void vhost_vdpa_unmap(struct vhost_vdpa *v, const struct vdpa_config_ops *ops = vdpa->config; u32 asid = iotlb_to_asid(iotlb); - vhost_vdpa_iotlb_unmap(v, iotlb, iova, iova + size - 1); + vhost_vdpa_iotlb_unmap(v, iotlb, iova, iova + size - 1, asid); - if (ops->dma_map) { - ops->dma_unmap(vdpa, asid, iova, size); - } else if (ops->set_map) { + if (ops->set_map) { if (!v->in_batch) ops->set_map(vdpa, asid, iotlb); - } else { - iommu_unmap(v->domain, iova, size); } - /* If we are in the middle of batch processing, delay the free * of AS until BATCH_END. */ @@ -1162,14 +1172,14 @@ static void vhost_vdpa_cleanup(struct vhost_vdpa *v) struct vhost_vdpa_as *as; u32 asid; - vhost_dev_cleanup(&v->vdev); - kfree(v->vdev.vqs); - for (asid = 0; asid < v->vdpa->nas; asid++) { as = asid_to_as(v, asid); if (as) vhost_vdpa_remove_as(v, asid); } + + vhost_dev_cleanup(&v->vdev); + kfree(v->vdev.vqs); } static int vhost_vdpa_open(struct inode *inode, struct file *filep) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 5c9fe3c9c364..cbe72bfd2f1f 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -2053,7 +2053,7 @@ static int translate_desc(struct vhost_virtqueue *vq, u64 addr, u32 len, struct vhost_dev *dev = vq->dev; struct vhost_iotlb *umem = dev->iotlb ? dev->iotlb : dev->umem; struct iovec *_iov; - u64 s = 0; + u64 s = 0, last = addr + len - 1; int ret = 0; while ((u64)len > s) { @@ -2063,7 +2063,7 @@ static int translate_desc(struct vhost_virtqueue *vq, u64 addr, u32 len, break; } - map = vhost_iotlb_itree_first(umem, addr, addr + len - 1); + map = vhost_iotlb_itree_first(umem, addr, last); if (map == NULL || map->start > addr) { if (umem != dev->iotlb) { ret = -EFAULT; diff --git a/drivers/vhost/vringh.c b/drivers/vhost/vringh.c index c9f5c8ea3afb..33eb941fcf15 100644 --- a/drivers/vhost/vringh.c +++ b/drivers/vhost/vringh.c @@ -1102,7 +1102,7 @@ static int iotlb_translate(const struct vringh *vrh, struct vhost_iotlb_map *map; struct vhost_iotlb *iotlb = vrh->iotlb; int ret = 0; - u64 s = 0; + u64 s = 0, last = addr + len - 1; spin_lock(vrh->iotlb_lock); @@ -1114,8 +1114,7 @@ static int iotlb_translate(const struct vringh *vrh, break; } - map = vhost_iotlb_itree_first(iotlb, addr, - addr + len - 1); + map = vhost_iotlb_itree_first(iotlb, addr, last); if (!map || map->start > addr) { ret = -EINVAL; break; diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c index cd6f7776013a..a2b374372363 100644 --- a/drivers/vhost/vsock.c +++ b/drivers/vhost/vsock.c @@ -959,7 +959,14 @@ static int __init vhost_vsock_init(void) VSOCK_TRANSPORT_F_H2G); if (ret < 0) return ret; - return misc_register(&vhost_vsock_misc); + + ret = misc_register(&vhost_vsock_misc); + if (ret) { + vsock_core_unregister(&vhost_transport.transport); + return ret; + } + + return 0; }; static void __exit vhost_vsock_exit(void) diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig index df6e09f7d242..b2bed599e6c6 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -456,8 +456,8 @@ config FB_ATARI chipset found in Ataris. config FB_OF - bool "Open Firmware frame buffer device support" - depends on (FB = y) && PPC && (!PPC_PSERIES || PCI) + tristate "Open Firmware frame buffer device support" + depends on FB && PPC && (!PPC_PSERIES || PCI) depends on !DRM_OFDRM select APERTURE_HELPERS select FB_CFB_FILLRECT diff --git a/drivers/video/fbdev/aty/atyfb_base.c b/drivers/video/fbdev/aty/atyfb_base.c index 0ccf5d401ecb..d59215a4992e 100644 --- a/drivers/video/fbdev/aty/atyfb_base.c +++ b/drivers/video/fbdev/aty/atyfb_base.c @@ -3192,8 +3192,7 @@ static void aty_init_lcd(struct atyfb_par *par, u32 bios_base) * which we print to the screen. */ id = *(u8 *)par->lcd_table; - strncpy(model, (char *)par->lcd_table+1, 24); - model[23] = 0; + strscpy(model, (char *)par->lcd_table+1, sizeof(model)); width = par->lcd_width = *(u16 *)(par->lcd_table+25); height = par->lcd_height = *(u16 *)(par->lcd_table+27); diff --git a/drivers/video/fbdev/matrox/matroxfb_base.c b/drivers/video/fbdev/matrox/matroxfb_base.c index 0d3cee7ae726..a043a737ea9f 100644 --- a/drivers/video/fbdev/matrox/matroxfb_base.c +++ b/drivers/video/fbdev/matrox/matroxfb_base.c @@ -1378,8 +1378,8 @@ static struct video_board vbG200 = { .lowlevel = &matrox_G100 }; static struct video_board vbG200eW = { - .maxvram = 0x100000, - .maxdisplayable = 0x800000, + .maxvram = 0x1000000, + .maxdisplayable = 0x0800000, .accelID = FB_ACCEL_MATROX_MGAG200, .lowlevel = &matrox_G100 }; diff --git a/drivers/video/fbdev/omap/omapfb_main.c b/drivers/video/fbdev/omap/omapfb_main.c index 17cda5765683..1f3df2055ff0 100644 --- a/drivers/video/fbdev/omap/omapfb_main.c +++ b/drivers/video/fbdev/omap/omapfb_main.c @@ -1447,7 +1447,7 @@ static int fbinfo_init(struct omapfb_device *fbdev, struct fb_info *info) info->fbops = &omapfb_ops; info->flags = FBINFO_FLAG_DEFAULT; - strncpy(fix->id, MODULE_NAME, sizeof(fix->id)); + strscpy(fix->id, MODULE_NAME, sizeof(fix->id)); info->pseudo_palette = fbdev->pseudo_palette; @@ -1573,8 +1573,7 @@ static int omapfb_find_ctrl(struct omapfb_device *fbdev) fbdev->ctrl = NULL; - strncpy(name, conf->lcd.ctrl_name, sizeof(name) - 1); - name[sizeof(name) - 1] = '\0'; + strscpy(name, conf->lcd.ctrl_name, sizeof(name)); if (strcmp(name, "internal") == 0) { fbdev->ctrl = fbdev->int_ctrl; diff --git a/drivers/video/fbdev/omap2/omapfb/dss/dsi.c b/drivers/video/fbdev/omap2/omapfb/dss/dsi.c index 54b0f034c2ed..7cddb7b8ae34 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/dsi.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/dsi.c @@ -1536,22 +1536,28 @@ static void dsi_dump_dsidev_irqs(struct platform_device *dsidev, { struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); unsigned long flags; - struct dsi_irq_stats stats; + struct dsi_irq_stats *stats; + + stats = kzalloc(sizeof(*stats), GFP_KERNEL); + if (!stats) { + seq_printf(s, "out of memory\n"); + return; + } spin_lock_irqsave(&dsi->irq_stats_lock, flags); - stats = dsi->irq_stats; + *stats = dsi->irq_stats; memset(&dsi->irq_stats, 0, sizeof(dsi->irq_stats)); dsi->irq_stats.last_reset = jiffies; spin_unlock_irqrestore(&dsi->irq_stats_lock, flags); seq_printf(s, "period %u ms\n", - jiffies_to_msecs(jiffies - stats.last_reset)); + jiffies_to_msecs(jiffies - stats->last_reset)); - seq_printf(s, "irqs %d\n", stats.irq_count); + seq_printf(s, "irqs %d\n", stats->irq_count); #define PIS(x) \ - seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]) + seq_printf(s, "%-20s %10d\n", #x, stats->dsi_irqs[ffs(DSI_IRQ_##x)-1]) seq_printf(s, "-- DSI%d interrupts --\n", dsi->module_id + 1); PIS(VC0); @@ -1575,10 +1581,10 @@ static void dsi_dump_dsidev_irqs(struct platform_device *dsidev, #define PIS(x) \ seq_printf(s, "%-20s %10d %10d %10d %10d\n", #x, \ - stats.vc_irqs[0][ffs(DSI_VC_IRQ_##x)-1], \ - stats.vc_irqs[1][ffs(DSI_VC_IRQ_##x)-1], \ - stats.vc_irqs[2][ffs(DSI_VC_IRQ_##x)-1], \ - stats.vc_irqs[3][ffs(DSI_VC_IRQ_##x)-1]); + stats->vc_irqs[0][ffs(DSI_VC_IRQ_##x)-1], \ + stats->vc_irqs[1][ffs(DSI_VC_IRQ_##x)-1], \ + stats->vc_irqs[2][ffs(DSI_VC_IRQ_##x)-1], \ + stats->vc_irqs[3][ffs(DSI_VC_IRQ_##x)-1]); seq_printf(s, "-- VC interrupts --\n"); PIS(CS); @@ -1594,7 +1600,7 @@ static void dsi_dump_dsidev_irqs(struct platform_device *dsidev, #define PIS(x) \ seq_printf(s, "%-20s %10d\n", #x, \ - stats.cio_irqs[ffs(DSI_CIO_IRQ_##x)-1]); + stats->cio_irqs[ffs(DSI_CIO_IRQ_##x)-1]); seq_printf(s, "-- CIO interrupts --\n"); PIS(ERRSYNCESC1); @@ -1618,6 +1624,8 @@ static void dsi_dump_dsidev_irqs(struct platform_device *dsidev, PIS(ULPSACTIVENOT_ALL0); PIS(ULPSACTIVENOT_ALL1); #undef PIS + + kfree(stats); } static void dsi1_dump_irqs(struct seq_file *s) diff --git a/drivers/video/fbdev/xen-fbfront.c b/drivers/video/fbdev/xen-fbfront.c index 8752d389e382..d7f3e6281ce4 100644 --- a/drivers/video/fbdev/xen-fbfront.c +++ b/drivers/video/fbdev/xen-fbfront.c @@ -67,7 +67,7 @@ MODULE_PARM_DESC(video, "Video memory size in MB, width, height in pixels (default 2,800,600)"); static void xenfb_make_preferred_console(void); -static int xenfb_remove(struct xenbus_device *); +static void xenfb_remove(struct xenbus_device *); static void xenfb_init_shared_page(struct xenfb_info *, struct fb_info *); static int xenfb_connect_backend(struct xenbus_device *, struct xenfb_info *); static void xenfb_disconnect_backend(struct xenfb_info *); @@ -523,7 +523,7 @@ static int xenfb_resume(struct xenbus_device *dev) return xenfb_connect_backend(dev, info); } -static int xenfb_remove(struct xenbus_device *dev) +static void xenfb_remove(struct xenbus_device *dev) { struct xenfb_info *info = dev_get_drvdata(&dev->dev); @@ -538,8 +538,6 @@ static int xenfb_remove(struct xenbus_device *dev) vfree(info->gfns); vfree(info->fb); kfree(info); - - return 0; } static unsigned long vmalloc_to_gfn(void *address) diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 828ced060742..b9a80aedee1b 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -15,7 +15,7 @@ static ssize_t device_show(struct device *_d, struct device_attribute *attr, char *buf) { struct virtio_device *dev = dev_to_virtio(_d); - return sprintf(buf, "0x%04x\n", dev->id.device); + return sysfs_emit(buf, "0x%04x\n", dev->id.device); } static DEVICE_ATTR_RO(device); @@ -23,7 +23,7 @@ static ssize_t vendor_show(struct device *_d, struct device_attribute *attr, char *buf) { struct virtio_device *dev = dev_to_virtio(_d); - return sprintf(buf, "0x%04x\n", dev->id.vendor); + return sysfs_emit(buf, "0x%04x\n", dev->id.vendor); } static DEVICE_ATTR_RO(vendor); @@ -31,7 +31,7 @@ static ssize_t status_show(struct device *_d, struct device_attribute *attr, char *buf) { struct virtio_device *dev = dev_to_virtio(_d); - return sprintf(buf, "0x%08x\n", dev->config->get_status(dev)); + return sysfs_emit(buf, "0x%08x\n", dev->config->get_status(dev)); } static DEVICE_ATTR_RO(status); @@ -39,7 +39,7 @@ static ssize_t modalias_show(struct device *_d, struct device_attribute *attr, char *buf) { struct virtio_device *dev = dev_to_virtio(_d); - return sprintf(buf, "virtio:d%08Xv%08X\n", + return sysfs_emit(buf, "virtio:d%08Xv%08X\n", dev->id.device, dev->id.vendor); } static DEVICE_ATTR_RO(modalias); @@ -54,9 +54,9 @@ static ssize_t features_show(struct device *_d, /* We actually represent this as a bitstring, as it could be * arbitrary length in future. */ for (i = 0; i < sizeof(dev->features)*8; i++) - len += sprintf(buf+len, "%c", + len += sysfs_emit_at(buf, len, "%c", __virtio_test_bit(dev, i) ? '1' : '0'); - len += sprintf(buf+len, "\n"); + len += sysfs_emit_at(buf, len, "\n"); return len; } static DEVICE_ATTR_RO(features); diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c index c3b9f2761849..9e496e288cfa 100644 --- a/drivers/virtio/virtio_pci_modern.c +++ b/drivers/virtio/virtio_pci_modern.c @@ -303,14 +303,14 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, int err; if (index >= vp_modern_get_num_queues(mdev)) - return ERR_PTR(-ENOENT); + return ERR_PTR(-EINVAL); /* Check if queue is either not available or already active. */ num = vp_modern_get_queue_size(mdev, index); if (!num || vp_modern_get_queue_enable(mdev, index)) return ERR_PTR(-ENOENT); - if (num & (num - 1)) { + if (!is_power_of_2(num)) { dev_warn(&vp_dev->pci_dev->dev, "bad queue size %u", num); return ERR_PTR(-EINVAL); } diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 2e7689bb933b..723c4e29e1d3 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -1052,7 +1052,7 @@ static int vring_alloc_queue_split(struct vring_virtqueue_split *vring_split, dma_addr_t dma_addr; /* We assume num is a power of 2. */ - if (num & (num - 1)) { + if (!is_power_of_2(num)) { dev_warn(&vdev->dev, "Bad virtqueue length %u\n", num); return -EINVAL; } diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index f2ae2e563dc5..4a2ddf730a3a 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -1166,6 +1166,8 @@ int w1_process(void *data) /* remainder if it woke up early */ unsigned long jremain = 0; + atomic_inc(&dev->refcnt); + for (;;) { if (!jremain && dev->search_count) { @@ -1193,8 +1195,10 @@ int w1_process(void *data) */ mutex_unlock(&dev->list_mutex); - if (kthread_should_stop()) + if (kthread_should_stop()) { + __set_current_state(TASK_RUNNING); break; + } /* Only sleep when the search is active. */ if (dev->search_count) { diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c index b3e1792d9c49..3a71c5eb2f83 100644 --- a/drivers/w1/w1_int.c +++ b/drivers/w1/w1_int.c @@ -51,10 +51,9 @@ static struct w1_master *w1_alloc_dev(u32 id, int slave_count, int slave_ttl, dev->search_count = w1_search_count; dev->enable_pullup = w1_enable_pullup; - /* 1 for w1_process to decrement - * 1 for __w1_remove_master_device to decrement + /* For __w1_remove_master_device to decrement */ - atomic_set(&dev->refcnt, 2); + atomic_set(&dev->refcnt, 1); INIT_LIST_HEAD(&dev->slist); INIT_LIST_HEAD(&dev->async_list); diff --git a/drivers/xen/pvcalls-back.c b/drivers/xen/pvcalls-back.c index 28b2a1fa25ab..0d4f8f4f4948 100644 --- a/drivers/xen/pvcalls-back.c +++ b/drivers/xen/pvcalls-back.c @@ -1181,9 +1181,8 @@ static void pvcalls_back_changed(struct xenbus_device *dev, } } -static int pvcalls_back_remove(struct xenbus_device *dev) +static void pvcalls_back_remove(struct xenbus_device *dev) { - return 0; } static int pvcalls_back_uevent(struct xenbus_device *xdev, diff --git a/drivers/xen/pvcalls-front.c b/drivers/xen/pvcalls-front.c index 1826e8e67125..d5d589bda243 100644 --- a/drivers/xen/pvcalls-front.c +++ b/drivers/xen/pvcalls-front.c @@ -225,6 +225,8 @@ again: return IRQ_HANDLED; } +static void free_active_ring(struct sock_mapping *map); + static void pvcalls_front_free_map(struct pvcalls_bedata *bedata, struct sock_mapping *map) { @@ -240,7 +242,7 @@ static void pvcalls_front_free_map(struct pvcalls_bedata *bedata, for (i = 0; i < (1 << PVCALLS_RING_ORDER); i++) gnttab_end_foreign_access(map->active.ring->ref[i], NULL); gnttab_end_foreign_access(map->active.ref, NULL); - free_page((unsigned long)map->active.ring); + free_active_ring(map); kfree(map); } @@ -1085,7 +1087,7 @@ static const struct xenbus_device_id pvcalls_front_ids[] = { { "" } }; -static int pvcalls_front_remove(struct xenbus_device *dev) +static void pvcalls_front_remove(struct xenbus_device *dev) { struct pvcalls_bedata *bedata; struct sock_mapping *map = NULL, *n; @@ -1121,7 +1123,6 @@ static int pvcalls_front_remove(struct xenbus_device *dev) kfree(bedata->ring.sring); kfree(bedata); xenbus_switch_state(dev, XenbusStateClosed); - return 0; } static int pvcalls_front_probe(struct xenbus_device *dev, diff --git a/drivers/xen/xen-pciback/xenbus.c b/drivers/xen/xen-pciback/xenbus.c index d171091eec12..b11e401f1b1e 100644 --- a/drivers/xen/xen-pciback/xenbus.c +++ b/drivers/xen/xen-pciback/xenbus.c @@ -716,14 +716,12 @@ out: return err; } -static int xen_pcibk_xenbus_remove(struct xenbus_device *dev) +static void xen_pcibk_xenbus_remove(struct xenbus_device *dev) { struct xen_pcibk_device *pdev = dev_get_drvdata(&dev->dev); if (pdev != NULL) free_pdev(pdev); - - return 0; } static const struct xenbus_device_id xen_pcibk_ids[] = { diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c index 6106ed93817d..954188b0b858 100644 --- a/drivers/xen/xen-scsiback.c +++ b/drivers/xen/xen-scsiback.c @@ -1249,7 +1249,7 @@ static void scsiback_release_translation_entry(struct vscsibk_info *info) spin_unlock_irqrestore(&info->v2p_lock, flags); } -static int scsiback_remove(struct xenbus_device *dev) +static void scsiback_remove(struct xenbus_device *dev) { struct vscsibk_info *info = dev_get_drvdata(&dev->dev); @@ -1261,8 +1261,6 @@ static int scsiback_remove(struct xenbus_device *dev) gnttab_page_cache_shrink(&info->free_pages, 0); dev_set_drvdata(&dev->dev, NULL); - - return 0; } static int scsiback_probe(struct xenbus_device *dev, |