diff options
author | Jakub Kicinski <kuba@kernel.org> | 2024-10-31 17:30:16 -0700 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2024-10-31 18:10:07 -0700 |
commit | 5b1c965956744d9b22fae7e9bca1c8e72355e1d0 (patch) | |
tree | 504f731de0a7ac9111de5c106cd360e4ff1c04af /drivers | |
parent | 9e114ec8084020e10e1cb7b43dbbf6e69940866b (diff) | |
parent | 5635f189425e328097714c38341944fc40731f3d (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Cross-merge networking fixes after downstream PR (net-6.12-rc6).
Conflicts:
drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
cbe84e9ad5e2 ("wifi: iwlwifi: mvm: really send iwl_txpower_constraints_cmd")
188a1bf89432 ("wifi: mac80211: re-order assigning channel in activate links")
https://lore.kernel.org/all/20241028123621.7bbb131b@canb.auug.org.au/
net/mac80211/cfg.c
c4382d5ca1af ("wifi: mac80211: update the right link for tx power")
8dd0498983ee ("wifi: mac80211: Fix setting txpower with emulate_chanctx")
drivers/net/ethernet/intel/ice/ice_ptp_hw.h
6e58c3310622 ("ice: fix crash on probe for DPLL enabled E810 LOM")
e4291b64e118 ("ice: Align E810T GPIO to other products")
ebb2693f8fbd ("ice: Read SDP section from NVM for pin definitions")
ac532f4f4251 ("ice: Cleanup unused declarations")
https://lore.kernel.org/all/20241030120524.1ee1af18@canb.auug.org.au/
No adjacent changes.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers')
117 files changed, 1078 insertions, 2103 deletions
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 51470208e6da..7773e6b860e7 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -130,6 +130,17 @@ static const struct dmi_system_id dmi_lid_quirks[] = { }, .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN, }, + { + /* + * Samsung galaxybook2 ,initial _LID device notification returns + * lid closed. + */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), + DMI_MATCH(DMI_PRODUCT_NAME, "750XED"), + }, + .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN, + }, {} }; diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index b73b3aa92f3f..c3fc2c05d868 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -1916,9 +1916,15 @@ unsigned int cppc_perf_to_khz(struct cppc_perf_caps *caps, unsigned int perf) u64 mul, div; if (caps->lowest_freq && caps->nominal_freq) { - mul = caps->nominal_freq - caps->lowest_freq; + /* Avoid special case when nominal_freq is equal to lowest_freq */ + if (caps->lowest_freq == caps->nominal_freq) { + mul = caps->nominal_freq; + div = caps->nominal_perf; + } else { + mul = caps->nominal_freq - caps->lowest_freq; + div = caps->nominal_perf - caps->lowest_perf; + } mul *= KHZ_PER_MHZ; - div = caps->nominal_perf - caps->lowest_perf; offset = caps->nominal_freq * KHZ_PER_MHZ - div64_u64(caps->nominal_perf * mul, div); } else { @@ -1939,11 +1945,17 @@ unsigned int cppc_khz_to_perf(struct cppc_perf_caps *caps, unsigned int freq) { s64 retval, offset = 0; static u64 max_khz; - u64 mul, div; + u64 mul, div; if (caps->lowest_freq && caps->nominal_freq) { - mul = caps->nominal_perf - caps->lowest_perf; - div = caps->nominal_freq - caps->lowest_freq; + /* Avoid special case when nominal_freq is equal to lowest_freq */ + if (caps->lowest_freq == caps->nominal_freq) { + mul = caps->nominal_perf; + div = caps->nominal_freq; + } else { + mul = caps->nominal_perf - caps->lowest_perf; + div = caps->nominal_freq - caps->lowest_freq; + } /* * We don't need to convert to kHz for computing offset and can * directly use nominal_freq and lowest_freq as the div64_u64 diff --git a/drivers/acpi/prmt.c b/drivers/acpi/prmt.c index 1cfaa5957ac4..747f83f7114d 100644 --- a/drivers/acpi/prmt.c +++ b/drivers/acpi/prmt.c @@ -52,7 +52,7 @@ struct prm_context_buffer { static LIST_HEAD(prm_module_list); struct prm_handler_info { - guid_t guid; + efi_guid_t guid; efi_status_t (__efiapi *handler_addr)(u64, void *); u64 static_data_buffer_addr; u64 acpi_param_buffer_addr; @@ -72,17 +72,21 @@ struct prm_module_info { struct prm_handler_info handlers[] __counted_by(handler_count); }; -static u64 efi_pa_va_lookup(u64 pa) +static u64 efi_pa_va_lookup(efi_guid_t *guid, u64 pa) { efi_memory_desc_t *md; u64 pa_offset = pa & ~PAGE_MASK; u64 page = pa & PAGE_MASK; for_each_efi_memory_desc(md) { - if (md->phys_addr < pa && pa < md->phys_addr + PAGE_SIZE * md->num_pages) + if ((md->attribute & EFI_MEMORY_RUNTIME) && + (md->phys_addr < pa && pa < md->phys_addr + PAGE_SIZE * md->num_pages)) { return pa_offset + md->virt_addr + page - md->phys_addr; + } } + pr_warn("Failed to find VA for GUID: %pUL, PA: 0x%llx", guid, pa); + return 0; } @@ -148,9 +152,15 @@ acpi_parse_prmt(union acpi_subtable_headers *header, const unsigned long end) th = &tm->handlers[cur_handler]; guid_copy(&th->guid, (guid_t *)handler_info->handler_guid); - th->handler_addr = (void *)efi_pa_va_lookup(handler_info->handler_address); - th->static_data_buffer_addr = efi_pa_va_lookup(handler_info->static_data_buffer_address); - th->acpi_param_buffer_addr = efi_pa_va_lookup(handler_info->acpi_param_buffer_address); + th->handler_addr = + (void *)efi_pa_va_lookup(&th->guid, handler_info->handler_address); + + th->static_data_buffer_addr = + efi_pa_va_lookup(&th->guid, handler_info->static_data_buffer_address); + + th->acpi_param_buffer_addr = + efi_pa_va_lookup(&th->guid, handler_info->acpi_param_buffer_address); + } while (++cur_handler < tm->handler_count && (handler_info = get_next_handler(handler_info))); return 0; @@ -277,6 +287,13 @@ static acpi_status acpi_platformrt_space_handler(u32 function, if (!handler || !module) goto invalid_guid; + if (!handler->handler_addr || + !handler->static_data_buffer_addr || + !handler->acpi_param_buffer_addr) { + buffer->prm_status = PRM_HANDLER_ERROR; + return AE_OK; + } + ACPI_COPY_NAMESEG(context.signature, "PRMC"); context.revision = 0x0; context.reserved = 0x0; diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 129bceb1f4a2..7fe842dae1ec 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -503,6 +503,13 @@ static const struct dmi_system_id irq1_level_low_skip_override[] = { DMI_MATCH(DMI_BOARD_NAME, "17U70P"), }, }, + { + /* LG Electronics 16T90SP */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"), + DMI_MATCH(DMI_BOARD_NAME, "16T90SP"), + }, + }, { } }; diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index fa41ea57a978..3b303d4ae37a 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -651,6 +651,7 @@ void ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap, /* the scmd has an associated qc */ if (!(qc->flags & ATA_QCFLAG_EH)) { /* which hasn't failed yet, timeout */ + set_host_byte(scmd, DID_TIME_OUT); qc->err_mask |= AC_ERR_TIMEOUT; qc->flags |= ATA_QCFLAG_EH; nr_timedout++; diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 854546000c92..1ff99a7091bb 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -674,6 +674,16 @@ EXPORT_SYMBOL_GPL(tpm_chip_register); */ void tpm_chip_unregister(struct tpm_chip *chip) { +#ifdef CONFIG_TCG_TPM2_HMAC + int rc; + + rc = tpm_try_get_ops(chip); + if (!rc) { + tpm2_end_auth_session(chip); + tpm_put_ops(chip); + } +#endif + tpm_del_legacy_sysfs(chip); if (tpm_is_hwrng_enabled(chip)) hwrng_unregister(&chip->hwrng); diff --git a/drivers/char/tpm/tpm-dev-common.c b/drivers/char/tpm/tpm-dev-common.c index c3fbbf4d3db7..48ff87444f85 100644 --- a/drivers/char/tpm/tpm-dev-common.c +++ b/drivers/char/tpm/tpm-dev-common.c @@ -27,6 +27,9 @@ static ssize_t tpm_dev_transmit(struct tpm_chip *chip, struct tpm_space *space, struct tpm_header *header = (void *)buf; ssize_t ret, len; + if (chip->flags & TPM_CHIP_FLAG_TPM2) + tpm2_end_auth_session(chip); + ret = tpm2_prepare_space(chip, space, buf, bufsiz); /* If the command is not implemented by the TPM, synthesize a * response with a TPM2_RC_COMMAND_CODE return for user-space. diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index 5da134f12c9a..8134f002b121 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -379,10 +379,12 @@ int tpm_pm_suspend(struct device *dev) rc = tpm_try_get_ops(chip); if (!rc) { - if (chip->flags & TPM_CHIP_FLAG_TPM2) + if (chip->flags & TPM_CHIP_FLAG_TPM2) { + tpm2_end_auth_session(chip); tpm2_shutdown(chip, TPM2_SU_STATE); - else + } else { rc = tpm1_pm_suspend(chip, tpm_suspend_pcr); + } tpm_put_ops(chip); } diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c index 511c67061728..0739830904b2 100644 --- a/drivers/char/tpm/tpm2-sessions.c +++ b/drivers/char/tpm/tpm2-sessions.c @@ -333,6 +333,9 @@ void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf, } #ifdef CONFIG_TCG_TPM2_HMAC + /* The first write to /dev/tpm{rm0} will flush the session. */ + attributes |= TPM2_SA_CONTINUE_SESSION; + /* * The Architecture Guide requires us to strip trailing zeros * before computing the HMAC @@ -484,7 +487,8 @@ static void tpm2_KDFe(u8 z[EC_PT_SZ], const char *str, u8 *pt_u, u8 *pt_v, sha256_final(&sctx, out); } -static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip) +static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip, + struct tpm2_auth *auth) { struct crypto_kpp *kpp; struct kpp_request *req; @@ -543,7 +547,7 @@ static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip) sg_set_buf(&s[0], chip->null_ec_key_x, EC_PT_SZ); sg_set_buf(&s[1], chip->null_ec_key_y, EC_PT_SZ); kpp_request_set_input(req, s, EC_PT_SZ*2); - sg_init_one(d, chip->auth->salt, EC_PT_SZ); + sg_init_one(d, auth->salt, EC_PT_SZ); kpp_request_set_output(req, d, EC_PT_SZ); crypto_kpp_compute_shared_secret(req); kpp_request_free(req); @@ -554,8 +558,7 @@ static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip) * This works because KDFe fully consumes the secret before it * writes the salt */ - tpm2_KDFe(chip->auth->salt, "SECRET", x, chip->null_ec_key_x, - chip->auth->salt); + tpm2_KDFe(auth->salt, "SECRET", x, chip->null_ec_key_x, auth->salt); out: crypto_free_kpp(kpp); @@ -853,7 +856,9 @@ int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf, if (rc) /* manually close the session if it wasn't consumed */ tpm2_flush_context(chip, auth->handle); - memzero_explicit(auth, sizeof(*auth)); + + kfree_sensitive(auth); + chip->auth = NULL; } else { /* reset for next use */ auth->session = TPM_HEADER_SIZE; @@ -881,7 +886,8 @@ void tpm2_end_auth_session(struct tpm_chip *chip) return; tpm2_flush_context(chip, auth->handle); - memzero_explicit(auth, sizeof(*auth)); + kfree_sensitive(auth); + chip->auth = NULL; } EXPORT_SYMBOL(tpm2_end_auth_session); @@ -915,33 +921,37 @@ static int tpm2_parse_start_auth_session(struct tpm2_auth *auth, static int tpm2_load_null(struct tpm_chip *chip, u32 *null_key) { - int rc; unsigned int offset = 0; /* dummy offset for null seed context */ u8 name[SHA256_DIGEST_SIZE + 2]; + u32 tmp_null_key; + int rc; rc = tpm2_load_context(chip, chip->null_key_context, &offset, - null_key); - if (rc != -EINVAL) - return rc; + &tmp_null_key); + if (rc != -EINVAL) { + if (!rc) + *null_key = tmp_null_key; + goto err; + } - /* an integrity failure may mean the TPM has been reset */ - dev_err(&chip->dev, "NULL key integrity failure!\n"); - /* check the null name against what we know */ - tpm2_create_primary(chip, TPM2_RH_NULL, NULL, name); - if (memcmp(name, chip->null_key_name, sizeof(name)) == 0) - /* name unchanged, assume transient integrity failure */ - return rc; - /* - * Fatal TPM failure: the NULL seed has actually changed, so - * the TPM must have been illegally reset. All in-kernel TPM - * operations will fail because the NULL primary can't be - * loaded to salt the sessions, but disable the TPM anyway so - * userspace programmes can't be compromised by it. - */ - dev_err(&chip->dev, "NULL name has changed, disabling TPM due to interference\n"); + /* Try to re-create null key, given the integrity failure: */ + rc = tpm2_create_primary(chip, TPM2_RH_NULL, &tmp_null_key, name); + if (rc) + goto err; + + /* Return null key if the name has not been changed: */ + if (!memcmp(name, chip->null_key_name, sizeof(name))) { + *null_key = tmp_null_key; + return 0; + } + + /* Deduce from the name change TPM interference: */ + dev_err(&chip->dev, "null key integrity check failed\n"); + tpm2_flush_context(chip, tmp_null_key); chip->flags |= TPM_CHIP_FLAG_DISABLE; - return rc; +err: + return rc ? -ENODEV : 0; } /** @@ -958,16 +968,20 @@ static int tpm2_load_null(struct tpm_chip *chip, u32 *null_key) */ int tpm2_start_auth_session(struct tpm_chip *chip) { + struct tpm2_auth *auth; struct tpm_buf buf; - struct tpm2_auth *auth = chip->auth; - int rc; u32 null_key; + int rc; - if (!auth) { - dev_warn_once(&chip->dev, "auth session is not active\n"); + if (chip->auth) { + dev_warn_once(&chip->dev, "auth session is active\n"); return 0; } + auth = kzalloc(sizeof(*auth), GFP_KERNEL); + if (!auth) + return -ENOMEM; + rc = tpm2_load_null(chip, &null_key); if (rc) goto out; @@ -988,7 +1002,7 @@ int tpm2_start_auth_session(struct tpm_chip *chip) tpm_buf_append(&buf, auth->our_nonce, sizeof(auth->our_nonce)); /* append encrypted salt and squirrel away unencrypted in auth */ - tpm_buf_append_salt(&buf, chip); + tpm_buf_append_salt(&buf, chip, auth); /* session type (HMAC, audit or policy) */ tpm_buf_append_u8(&buf, TPM2_SE_HMAC); @@ -1010,10 +1024,13 @@ int tpm2_start_auth_session(struct tpm_chip *chip) tpm_buf_destroy(&buf); - if (rc) - goto out; + if (rc == TPM2_RC_SUCCESS) { + chip->auth = auth; + return 0; + } - out: +out: + kfree_sensitive(auth); return rc; } EXPORT_SYMBOL(tpm2_start_auth_session); @@ -1347,18 +1364,21 @@ static int tpm2_create_null_primary(struct tpm_chip *chip) * * Derive and context save the null primary and allocate memory in the * struct tpm_chip for the authorizations. + * + * Return: + * * 0 - OK + * * -errno - A system error + * * TPM_RC - A TPM error */ int tpm2_sessions_init(struct tpm_chip *chip) { int rc; rc = tpm2_create_null_primary(chip); - if (rc) - dev_err(&chip->dev, "TPM: security failed (NULL seed derivation): %d\n", rc); - - chip->auth = kmalloc(sizeof(*chip->auth), GFP_KERNEL); - if (!chip->auth) - return -ENOMEM; + if (rc) { + dev_err(&chip->dev, "null key creation failed with %d\n", rc); + return rc; + } return rc; } diff --git a/drivers/firewire/core-topology.c b/drivers/firewire/core-topology.c index 6adadb11962e..892b94cfd626 100644 --- a/drivers/firewire/core-topology.c +++ b/drivers/firewire/core-topology.c @@ -204,7 +204,7 @@ static struct fw_node *build_tree(struct fw_card *card, const u32 *sid, int self // the node->ports array where the parent node should be. Later, // when we handle the parent node, we fix up the reference. ++parent_count; - node->color = i; + node->color = port_index; break; case PHY_PACKET_SELF_ID_PORT_STATUS_CHILD: diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c index f85ace0384d2..1f5a296f5ed2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c @@ -147,6 +147,7 @@ static union acpi_object *amdgpu_atif_call(struct amdgpu_atif *atif, struct acpi_buffer *params) { acpi_status status; + union acpi_object *obj; union acpi_object atif_arg_elements[2]; struct acpi_object_list atif_arg; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -169,16 +170,24 @@ static union acpi_object *amdgpu_atif_call(struct amdgpu_atif *atif, status = acpi_evaluate_object(atif->handle, NULL, &atif_arg, &buffer); + obj = (union acpi_object *)buffer.pointer; - /* Fail only if calling the method fails and ATIF is supported */ + /* Fail if calling the method fails and ATIF is supported */ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { DRM_DEBUG_DRIVER("failed to evaluate ATIF got %s\n", acpi_format_exception(status)); - kfree(buffer.pointer); + kfree(obj); return NULL; } - return buffer.pointer; + if (obj->type != ACPI_TYPE_BUFFER) { + DRM_DEBUG_DRIVER("bad object returned from ATIF: %d\n", + obj->type); + kfree(obj); + return NULL; + } + + return obj; } /** diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c index a8763496aed3..9288f37a3cc5 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c @@ -51,6 +51,12 @@ MODULE_FIRMWARE("amdgpu/sdma_7_0_1.bin"); #define SDMA0_HYP_DEC_REG_END 0x589a #define SDMA1_HYP_DEC_REG_OFFSET 0x20 +/*define for compression field for sdma7*/ +#define SDMA_PKT_CONSTANT_FILL_HEADER_compress_offset 0 +#define SDMA_PKT_CONSTANT_FILL_HEADER_compress_mask 0x00000001 +#define SDMA_PKT_CONSTANT_FILL_HEADER_compress_shift 16 +#define SDMA_PKT_CONSTANT_FILL_HEADER_COMPRESS(x) (((x) & SDMA_PKT_CONSTANT_FILL_HEADER_compress_mask) << SDMA_PKT_CONSTANT_FILL_HEADER_compress_shift) + static const struct amdgpu_hwip_reg_entry sdma_reg_list_7_0[] = { SOC15_REG_ENTRY_STR(GC, 0, regSDMA0_STATUS_REG), SOC15_REG_ENTRY_STR(GC, 0, regSDMA0_STATUS1_REG), @@ -1724,7 +1730,8 @@ static void sdma_v7_0_emit_fill_buffer(struct amdgpu_ib *ib, uint64_t dst_offset, uint32_t byte_count) { - ib->ptr[ib->length_dw++] = SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_CONST_FILL); + ib->ptr[ib->length_dw++] = SDMA_PKT_CONSTANT_FILL_HEADER_OP(SDMA_OP_CONST_FILL) | + SDMA_PKT_CONSTANT_FILL_HEADER_COMPRESS(1); ib->ptr[ib->length_dw++] = lower_32_bits(dst_offset); ib->ptr[ib->length_dw++] = upper_32_bits(dst_offset); ib->ptr[ib->length_dw++] = src_data; 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 6b5e2206e687..13421a58210d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8374,7 +8374,8 @@ static void manage_dm_interrupts(struct amdgpu_device *adev, if (amdgpu_ip_version(adev, DCE_HWIP, 0) < IP_VERSION(3, 5, 0) || acrtc_state->stream->link->psr_settings.psr_version < - DC_PSR_VERSION_UNSUPPORTED) { + DC_PSR_VERSION_UNSUPPORTED || + !(adev->flags & AMD_IS_APU)) { timing = &acrtc_state->stream->timing; /* at least 2 frames */ 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 069e0195e50a..eea317dcbe8c 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 @@ -44,6 +44,7 @@ #include "dm_helpers.h" #include "ddc_service_types.h" +#include "clk_mgr.h" static u32 edid_extract_panel_id(struct edid *edid) { @@ -1121,6 +1122,8 @@ bool dm_helpers_dp_handle_test_pattern_request( struct pipe_ctx *pipe_ctx = NULL; struct amdgpu_dm_connector *aconnector = link->priv; struct drm_device *dev = aconnector->base.dev; + struct dc_state *dc_state = ctx->dc->current_state; + struct clk_mgr *clk_mgr = ctx->dc->clk_mgr; int i; for (i = 0; i < MAX_PIPES; i++) { @@ -1221,6 +1224,16 @@ bool dm_helpers_dp_handle_test_pattern_request( pipe_ctx->stream->test_pattern.type = test_pattern; pipe_ctx->stream->test_pattern.color_space = test_pattern_color_space; + /* Temp W/A for compliance test failure */ + dc_state->bw_ctx.bw.dcn.clk.p_state_change_support = false; + dc_state->bw_ctx.bw.dcn.clk.dramclk_khz = clk_mgr->dc_mode_softmax_enabled ? + clk_mgr->bw_params->dc_mode_softmax_memclk : clk_mgr->bw_params->max_memclk_mhz; + dc_state->bw_ctx.bw.dcn.clk.idle_dramclk_khz = dc_state->bw_ctx.bw.dcn.clk.dramclk_khz; + ctx->dc->clk_mgr->funcs->update_clocks( + ctx->dc->clk_mgr, + dc_state, + false); + dc_link_dp_set_test_pattern( (struct dc_link *) link, test_pattern, 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 3cd52e7a9c77..95838c7ab054 100644 --- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c +++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c @@ -841,6 +841,8 @@ bool is_psr_su_specific_panel(struct dc_link *link) isPSRSUSupported = false; else if (dpcd_caps->sink_dev_id_str[1] == 0x08 && dpcd_caps->sink_dev_id_str[0] == 0x03) isPSRSUSupported = false; + else if (dpcd_caps->sink_dev_id_str[1] == 0x08 && dpcd_caps->sink_dev_id_str[0] == 0x01) + isPSRSUSupported = false; else if (dpcd_caps->psr_info.force_psrsu_cap == 0x1) isPSRSUSupported = true; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 9ad9cf7a9c98..80e60ea2d11e 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1234,6 +1234,14 @@ static void smu_init_xgmi_plpd_mode(struct smu_context *smu) } } +static bool smu_is_workload_profile_available(struct smu_context *smu, + u32 profile) +{ + if (profile >= PP_SMC_POWER_PROFILE_COUNT) + return false; + return smu->workload_map && smu->workload_map[profile].valid_mapping; +} + static int smu_sw_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; @@ -1265,7 +1273,8 @@ static int smu_sw_init(void *handle) smu->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 5; smu->workload_prority[PP_SMC_POWER_PROFILE_CUSTOM] = 6; - if (smu->is_apu) + if (smu->is_apu || + !smu_is_workload_profile_available(smu, PP_SMC_POWER_PROFILE_FULLSCREEN3D)) smu->workload_mask = 1 << smu->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT]; else smu->workload_mask = 1 << smu->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D]; diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu14_driver_if_v14_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu14_driver_if_v14_0.h index ee457a6f0813..c2fd0a4a13e5 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu14_driver_if_v14_0.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu14_driver_if_v14_0.h @@ -25,7 +25,7 @@ #define SMU14_DRIVER_IF_V14_0_H //Increment this version if SkuTable_t or BoardTable_t change -#define PPTABLE_VERSION 0x18 +#define PPTABLE_VERSION 0x1B #define NUM_GFXCLK_DPM_LEVELS 16 #define NUM_SOCCLK_DPM_LEVELS 8 @@ -145,7 +145,7 @@ typedef enum { } FEATURE_BTC_e; // Debug Overrides Bitmask -#define DEBUG_OVERRIDE_DISABLE_VOLT_LINK_VCN_FCLK 0x00000001 +#define DEBUG_OVERRIDE_NOT_USE 0x00000001 #define DEBUG_OVERRIDE_DISABLE_VOLT_LINK_DCN_FCLK 0x00000002 #define DEBUG_OVERRIDE_DISABLE_VOLT_LINK_MP0_FCLK 0x00000004 #define DEBUG_OVERRIDE_DISABLE_VOLT_LINK_VCN_DCFCLK 0x00000008 @@ -161,6 +161,7 @@ typedef enum { #define DEBUG_OVERRIDE_ENABLE_SOC_VF_BRINGUP_MODE 0x00002000 #define DEBUG_OVERRIDE_ENABLE_PER_WGP_RESIENCY 0x00004000 #define DEBUG_OVERRIDE_DISABLE_MEMORY_VOLTAGE_SCALING 0x00008000 +#define DEBUG_OVERRIDE_DFLL_BTC_FCW_LOG 0x00010000 // VR Mapping Bit Defines #define VR_MAPPING_VR_SELECT_MASK 0x01 @@ -391,6 +392,21 @@ typedef struct { EccInfo_t EccInfo[24]; } EccInfoTable_t; +#define EPCS_HIGH_POWER 600 +#define EPCS_NORMAL_POWER 450 +#define EPCS_LOW_POWER 300 +#define EPCS_SHORTED_POWER 150 +#define EPCS_NO_BOOTUP 0 + +typedef enum{ + EPCS_SHORTED_LIMIT, + EPCS_LOW_POWER_LIMIT, + EPCS_NORMAL_POWER_LIMIT, + EPCS_HIGH_POWER_LIMIT, + EPCS_NOT_CONFIGURED, + EPCS_STATUS_COUNT, +} EPCS_STATUS_e; + //D3HOT sequences typedef enum { BACO_SEQUENCE, @@ -662,7 +678,7 @@ typedef enum { } PP_GRTAVFS_FW_SEP_FUSE_e; #define PP_NUM_RTAVFS_PWL_ZONES 5 - +#define PP_NUM_PSM_DIDT_PWL_ZONES 3 // VBIOS or PPLIB configures telemetry slope and offset. Only slope expected to be set for SVI3 // Slope Q1.7, Offset Q1.2 @@ -746,10 +762,10 @@ typedef struct { uint16_t Padding; //Frequency changes - int16_t GfxclkFmin; // MHz - int16_t GfxclkFmax; // MHz - uint16_t UclkFmin; // MHz - uint16_t UclkFmax; // MHz + int16_t GfxclkFoffset; + uint16_t Padding1; + uint16_t UclkFmin; + uint16_t UclkFmax; uint16_t FclkFmin; uint16_t FclkFmax; @@ -770,19 +786,23 @@ typedef struct { uint8_t MaxOpTemp; uint8_t AdvancedOdModeEnabled; - uint8_t Padding1[3]; + uint8_t Padding2[3]; uint16_t GfxVoltageFullCtrlMode; uint16_t SocVoltageFullCtrlMode; uint16_t GfxclkFullCtrlMode; uint16_t UclkFullCtrlMode; uint16_t FclkFullCtrlMode; - uint16_t Padding2; + uint16_t Padding3; int16_t GfxEdc; int16_t GfxPccLimitControl; - uint32_t Spare[10]; + uint16_t GfxclkFmaxVmax; + uint8_t GfxclkFmaxVmaxTemperature; + uint8_t Padding4[1]; + + uint32_t Spare[9]; uint32_t MmHubPadding[8]; // SMU internal use. Adding here instead of external as a workaround } OverDriveTable_t; @@ -802,8 +822,8 @@ typedef struct { uint16_t VddSocVmax; //gfxclk - int16_t GfxclkFmin; // MHz - int16_t GfxclkFmax; // MHz + int16_t GfxclkFoffset; + uint16_t Padding; //uclk uint16_t UclkFmin; // MHz uint16_t UclkFmax; // MHz @@ -828,7 +848,7 @@ typedef struct { uint8_t FanZeroRpmEnable; //temperature uint8_t MaxOpTemp; - uint8_t Padding[2]; + uint8_t Padding1[2]; //Full Ctrl uint16_t GfxVoltageFullCtrlMode; @@ -839,7 +859,7 @@ typedef struct { //EDC int16_t GfxEdc; int16_t GfxPccLimitControl; - int16_t Padding1; + int16_t Padding2; uint32_t Spare[5]; } OverDriveLimits_t; @@ -987,8 +1007,9 @@ typedef struct { uint16_t BaseClockDc; uint16_t GameClockDc; uint16_t BoostClockDc; - - uint32_t Reserved[4]; + uint16_t MaxReportedClock; + uint16_t Padding; + uint32_t Reserved[3]; } DriverReportedClocks_t; typedef struct { @@ -1132,7 +1153,7 @@ typedef struct { uint32_t DcModeMaxFreq [PPCLK_COUNT ]; // In MHz uint16_t GfxclkAibFmax; - uint16_t GfxclkFreqCap; + uint16_t GfxDpmPadding; //GFX Idle Power Settings uint16_t GfxclkFgfxoffEntry; // Entry in RLC stage (PLL), in Mhz @@ -1172,8 +1193,7 @@ typedef struct { uint32_t DvoFmaxLowScaler; //Unitless float // GFX DCS - uint16_t DcsGfxOffVoltage; //Voltage in mV(Q2) applied to VDDGFX when entering DCS GFXOFF phase - uint16_t PaddingDcs; + uint32_t PaddingDcs; uint16_t DcsMinGfxOffTime; //Minimum amount of time PMFW shuts GFX OFF as part of GFX DCS phase uint16_t DcsMaxGfxOffTime; //Maximum amount of time PMFW can shut GFX OFF as part of GFX DCS phase at a stretch. @@ -1205,8 +1225,7 @@ typedef struct { uint16_t DalDcModeMaxUclkFreq; uint8_t PaddingsMem[2]; //FCLK Section - uint16_t FclkDpmDisallowPstateFreq; //Frequency which FW will target when indicated that display config cannot support P-state. Set to 0 use FW calculated value - uint16_t PaddingFclk; + uint32_t PaddingFclk; // Link DPM Settings uint8_t PcieGenSpeed[NUM_LINK_LEVELS]; ///< 0:PciE-gen1 1:PciE-gen2 2:PciE-gen3 3:PciE-gen4 4:PciE-gen5 @@ -1215,12 +1234,19 @@ typedef struct { // SECTION: VDD_GFX AVFS uint8_t OverrideGfxAvfsFuses; - uint8_t GfxAvfsPadding[3]; + uint8_t GfxAvfsPadding[1]; + uint16_t DroopGBStDev; uint32_t SocHwRtAvfsFuses[PP_GRTAVFS_HW_FUSE_COUNT]; //new added for Soc domain uint32_t GfxL2HwRtAvfsFuses[PP_GRTAVFS_HW_FUSE_COUNT]; //see fusedoc for encoding //uint32_t GfxSeHwRtAvfsFuses[PP_GRTAVFS_HW_FUSE_COUNT]; - uint32_t spare_HwRtAvfsFuses[PP_GRTAVFS_HW_FUSE_COUNT]; + + uint16_t PsmDidt_Vcross[PP_NUM_PSM_DIDT_PWL_ZONES-1]; + uint32_t PsmDidt_StaticDroop_A[PP_NUM_PSM_DIDT_PWL_ZONES]; + uint32_t PsmDidt_StaticDroop_B[PP_NUM_PSM_DIDT_PWL_ZONES]; + uint32_t PsmDidt_DynDroop_A[PP_NUM_PSM_DIDT_PWL_ZONES]; + uint32_t PsmDidt_DynDroop_B[PP_NUM_PSM_DIDT_PWL_ZONES]; + uint32_t spare_HwRtAvfsFuses[19]; uint32_t SocCommonRtAvfs[PP_GRTAVFS_FW_COMMON_FUSE_COUNT]; uint32_t GfxCommonRtAvfs[PP_GRTAVFS_FW_COMMON_FUSE_COUNT]; @@ -1246,11 +1272,7 @@ typedef struct { uint32_t dGbV_dT_vmin; uint32_t dGbV_dT_vmax; - //Unused: PMFW-9370 - uint32_t V2F_vmin_range_low; - uint32_t V2F_vmin_range_high; - uint32_t V2F_vmax_range_low; - uint32_t V2F_vmax_range_high; + uint32_t PaddingV2F[4]; AvfsDcBtcParams_t DcBtcGfxParams; QuadraticInt_t SSCurve_GFX; @@ -1327,18 +1349,18 @@ typedef struct { uint16_t PsmDidtReleaseTimer; uint32_t PsmDidtStallPattern; //Will be written to both pattern 1 and didt_static_level_prog // CAC EDC - uint32_t Leakage_C0; // in IEEE float - uint32_t Leakage_C1; // in IEEE float - uint32_t Leakage_C2; // in IEEE float - uint32_t Leakage_C3; // in IEEE float - uint32_t Leakage_C4; // in IEEE float - uint32_t Leakage_C5; // in IEEE float - uint32_t GFX_CLK_SCALAR; // in IEEE float - uint32_t GFX_CLK_INTERCEPT; // in IEEE float - uint32_t GFX_CAC_M; // in IEEE float - uint32_t GFX_CAC_B; // in IEEE float - uint32_t VDD_GFX_CurrentLimitGuardband; // in IEEE float - uint32_t DynToTotalCacScalar; // in IEEE + uint32_t CacEdcCacLeakageC0; + uint32_t CacEdcCacLeakageC1; + uint32_t CacEdcCacLeakageC2; + uint32_t CacEdcCacLeakageC3; + uint32_t CacEdcCacLeakageC4; + uint32_t CacEdcCacLeakageC5; + uint32_t CacEdcGfxClkScalar; + uint32_t CacEdcGfxClkIntercept; + uint32_t CacEdcCac_m; + uint32_t CacEdcCac_b; + uint32_t CacEdcCurrLimitGuardband; + uint32_t CacEdcDynToTotalCacRatio; // GFX EDC XVMIN uint32_t XVmin_Gfx_EdcThreshScalar; uint32_t XVmin_Gfx_EdcEnableFreq; @@ -1467,7 +1489,7 @@ typedef struct { uint8_t VddqOffEnabled; uint8_t PaddingUmcFlags[2]; - uint32_t PostVoltageSetBacoDelay; // in microseconds. Amount of time FW will wait after power good is established or PSI0 command is issued + uint32_t Paddign1; uint32_t BacoEntryDelay; // in milliseconds. Amount of time FW will wait to trigger BACO entry after receiving entry notification from OS uint8_t FuseWritePowerMuxPresent; @@ -1530,7 +1552,7 @@ typedef struct { int16_t FuzzyFan_ErrorSetDelta; int16_t FuzzyFan_ErrorRateSetDelta; int16_t FuzzyFan_PwmSetDelta; - uint16_t FuzzyFan_Reserved; + uint16_t FanPadding2; uint16_t FwCtfLimit[TEMP_COUNT]; @@ -1547,9 +1569,10 @@ typedef struct { uint16_t FanSpare[1]; uint8_t FanIntakeSensorSupport; uint8_t FanIntakePadding; - uint32_t FanAmbientPerfBoostThreshold; uint32_t FanSpare2[12]; + uint32_t ODFeatureCtrlMask; + uint16_t TemperatureLimit_Hynix; // In degrees Celsius. Memory temperature limit associated with Hynix uint16_t TemperatureLimit_Micron; // In degrees Celsius. Memory temperature limit associated with Micron uint16_t TemperatureFwCtfLimit_Hynix; @@ -1637,7 +1660,7 @@ typedef struct { uint16_t AverageDclk0Frequency ; uint16_t AverageVclk1Frequency ; uint16_t AverageDclk1Frequency ; - uint16_t PCIeBusy ; + uint16_t AveragePCIeBusy ; uint16_t dGPU_W_MAX ; uint16_t padding ; @@ -1665,12 +1688,12 @@ typedef struct { uint16_t AverageGfxActivity ; uint16_t AverageUclkActivity ; - uint16_t Vcn0ActivityPercentage ; + uint16_t AverageVcn0ActivityPercentage; uint16_t Vcn1ActivityPercentage ; uint32_t EnergyAccumulator; uint16_t AverageSocketPower; - uint16_t MovingAverageTotalBoardPower; + uint16_t AverageTotalBoardPower; uint16_t AvgTemperature[TEMP_COUNT]; uint16_t AvgTemperatureFanIntake; @@ -1684,7 +1707,8 @@ typedef struct { uint8_t ThrottlingPercentage[THROTTLER_COUNT]; - uint8_t padding1[3]; + uint8_t VmaxThrottlingPercentage; + uint8_t padding1[2]; //metrics for D3hot entry/exit and driver ARM msgs uint32_t D3HotEntryCountPerMode[D3HOT_SEQUENCE_COUNT]; @@ -1693,7 +1717,7 @@ typedef struct { uint16_t ApuSTAPMSmartShiftLimit; uint16_t ApuSTAPMLimit; - uint16_t MovingAvgApuSocketPower; + uint16_t AvgApuSocketPower; uint16_t AverageUclkActivity_MAX; @@ -1823,6 +1847,17 @@ typedef struct { #define TABLE_TRANSFER_FAILED 0xFF #define TABLE_TRANSFER_PENDING 0xAB +#define TABLE_PPT_FAILED 0x100 +#define TABLE_TDC_FAILED 0x200 +#define TABLE_TEMP_FAILED 0x400 +#define TABLE_FAN_TARGET_TEMP_FAILED 0x800 +#define TABLE_FAN_STOP_TEMP_FAILED 0x1000 +#define TABLE_FAN_START_TEMP_FAILED 0x2000 +#define TABLE_FAN_PWM_MIN_FAILED 0x4000 +#define TABLE_ACOUSTIC_TARGET_RPM_FAILED 0x8000 +#define TABLE_ACOUSTIC_LIMIT_RPM_FAILED 0x10000 +#define TABLE_MGPU_ACOUSTIC_TARGET_RPM_FAILED 0x20000 + // Table types #define TABLE_PPTABLE 0 #define TABLE_COMBO_PPTABLE 1 @@ -1849,5 +1884,6 @@ typedef struct { #define IH_INTERRUPT_CONTEXT_ID_THERMAL_THROTTLING 0x7 #define IH_INTERRUPT_CONTEXT_ID_FAN_ABNORMAL 0x8 #define IH_INTERRUPT_CONTEXT_ID_FAN_RECOVERY 0x9 +#define IH_INTERRUPT_CONTEXT_ID_DYNAMIC_TABLE 0xA #endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h index 46b456590a08..727d5b405435 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h @@ -28,7 +28,7 @@ #define SMU14_DRIVER_IF_VERSION_INV 0xFFFFFFFF #define SMU14_DRIVER_IF_VERSION_SMU_V14_0_0 0x7 #define SMU14_DRIVER_IF_VERSION_SMU_V14_0_1 0x6 -#define SMU14_DRIVER_IF_VERSION_SMU_V14_0_2 0x26 +#define SMU14_DRIVER_IF_VERSION_SMU_V14_0_2 0x2E #define FEATURE_MASK(feature) (1ULL << feature) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c index 5899d01fa73d..e83ea2bc7f9c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c @@ -1077,12 +1077,9 @@ static void smu_v14_0_2_get_od_setting_limits(struct smu_context *smu, switch (od_feature_bit) { case PP_OD_FEATURE_GFXCLK_FMIN: - od_min_setting = overdrive_lowerlimits->GfxclkFmin; - od_max_setting = overdrive_upperlimits->GfxclkFmin; - break; case PP_OD_FEATURE_GFXCLK_FMAX: - od_min_setting = overdrive_lowerlimits->GfxclkFmax; - od_max_setting = overdrive_upperlimits->GfxclkFmax; + od_min_setting = overdrive_lowerlimits->GfxclkFoffset; + od_max_setting = overdrive_upperlimits->GfxclkFoffset; break; case PP_OD_FEATURE_UCLK_FMIN: od_min_setting = overdrive_lowerlimits->UclkFmin; @@ -1269,10 +1266,16 @@ static int smu_v14_0_2_print_clk_levels(struct smu_context *smu, PP_OD_FEATURE_GFXCLK_BIT)) break; - size += sysfs_emit_at(buf, size, "OD_SCLK:\n"); - size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMhz\n", - od_table->OverDriveTable.GfxclkFmin, - od_table->OverDriveTable.GfxclkFmax); + PPTable_t *pptable = smu->smu_table.driver_pptable; + const OverDriveLimits_t * const overdrive_upperlimits = + &pptable->SkuTable.OverDriveLimitsBasicMax; + const OverDriveLimits_t * const overdrive_lowerlimits = + &pptable->SkuTable.OverDriveLimitsBasicMin; + + size += sysfs_emit_at(buf, size, "OD_SCLK_OFFSET:\n"); + size += sysfs_emit_at(buf, size, "0: %dMhz\n1: %uMhz\n", + overdrive_lowerlimits->GfxclkFoffset, + overdrive_upperlimits->GfxclkFoffset); break; case SMU_OD_MCLK: @@ -1414,7 +1417,7 @@ static int smu_v14_0_2_print_clk_levels(struct smu_context *smu, PP_OD_FEATURE_GFXCLK_FMAX, NULL, &max_value); - size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n", + size += sysfs_emit_at(buf, size, "SCLK_OFFSET: %7dMhz %10uMhz\n", min_value, max_value); } @@ -1796,7 +1799,7 @@ static int smu_v14_0_2_set_power_profile_mode(struct smu_context *smu, DpmActivityMonitorCoeffInt_t *activity_monitor = &(activity_monitor_external.DpmActivityMonitorCoeffInt); int workload_type, ret = 0; - + uint32_t current_profile_mode = smu->power_profile_mode; smu->power_profile_mode = input[size]; if (smu->power_profile_mode >= PP_SMC_POWER_PROFILE_COUNT) { @@ -1854,6 +1857,11 @@ static int smu_v14_0_2_set_power_profile_mode(struct smu_context *smu, } } + if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_COMPUTE) + smu_v14_0_deep_sleep_control(smu, false); + else if (current_profile_mode == PP_SMC_POWER_PROFILE_COMPUTE) + smu_v14_0_deep_sleep_control(smu, true); + /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ workload_type = smu_cmn_to_asic_specific_index(smu, CMN2ASIC_MAPPING_WORKLOAD, @@ -2158,7 +2166,7 @@ static ssize_t smu_v14_0_2_get_gpu_metrics(struct smu_context *smu, gpu_metrics->average_gfx_activity = metrics->AverageGfxActivity; gpu_metrics->average_umc_activity = metrics->AverageUclkActivity; - gpu_metrics->average_mm_activity = max(metrics->Vcn0ActivityPercentage, + gpu_metrics->average_mm_activity = max(metrics->AverageVcn0ActivityPercentage, metrics->Vcn1ActivityPercentage); gpu_metrics->average_socket_power = metrics->AverageSocketPower; @@ -2217,8 +2225,7 @@ static void smu_v14_0_2_dump_od_table(struct smu_context *smu, { struct amdgpu_device *adev = smu->adev; - dev_dbg(adev->dev, "OD: Gfxclk: (%d, %d)\n", od_table->OverDriveTable.GfxclkFmin, - od_table->OverDriveTable.GfxclkFmax); + dev_dbg(adev->dev, "OD: Gfxclk offset: (%d)\n", od_table->OverDriveTable.GfxclkFoffset); dev_dbg(adev->dev, "OD: Uclk: (%d, %d)\n", od_table->OverDriveTable.UclkFmin, od_table->OverDriveTable.UclkFmax); } @@ -2309,10 +2316,8 @@ static int smu_v14_0_2_set_default_od_settings(struct smu_context *smu) memcpy(user_od_table, boot_od_table, sizeof(OverDriveTableExternal_t)); - user_od_table->OverDriveTable.GfxclkFmin = - user_od_table_bak.OverDriveTable.GfxclkFmin; - user_od_table->OverDriveTable.GfxclkFmax = - user_od_table_bak.OverDriveTable.GfxclkFmax; + user_od_table->OverDriveTable.GfxclkFoffset = + user_od_table_bak.OverDriveTable.GfxclkFoffset; user_od_table->OverDriveTable.UclkFmin = user_od_table_bak.OverDriveTable.UclkFmin; user_od_table->OverDriveTable.UclkFmax = @@ -2441,22 +2446,6 @@ static int smu_v14_0_2_od_edit_dpm_table(struct smu_context *smu, } switch (input[i]) { - case 0: - smu_v14_0_2_get_od_setting_limits(smu, - PP_OD_FEATURE_GFXCLK_FMIN, - &minimum, - &maximum); - if (input[i + 1] < minimum || - input[i + 1] > maximum) { - dev_info(adev->dev, "GfxclkFmin (%ld) must be within [%u, %u]!\n", - input[i + 1], minimum, maximum); - return -EINVAL; - } - - od_table->OverDriveTable.GfxclkFmin = input[i + 1]; - od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_GFXCLK_BIT; - break; - case 1: smu_v14_0_2_get_od_setting_limits(smu, PP_OD_FEATURE_GFXCLK_FMAX, @@ -2469,7 +2458,7 @@ static int smu_v14_0_2_od_edit_dpm_table(struct smu_context *smu, return -EINVAL; } - od_table->OverDriveTable.GfxclkFmax = input[i + 1]; + od_table->OverDriveTable.GfxclkFoffset = input[i + 1]; od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_GFXCLK_BIT; break; @@ -2480,13 +2469,6 @@ static int smu_v14_0_2_od_edit_dpm_table(struct smu_context *smu, } } - if (od_table->OverDriveTable.GfxclkFmin > od_table->OverDriveTable.GfxclkFmax) { - dev_err(adev->dev, - "Invalid setting: GfxclkFmin(%u) is bigger than GfxclkFmax(%u)\n", - (uint32_t)od_table->OverDriveTable.GfxclkFmin, - (uint32_t)od_table->OverDriveTable.GfxclkFmax); - return -EINVAL; - } break; case PP_OD_EDIT_MCLK_VDDC_TABLE: diff --git a/drivers/gpu/drm/bridge/aux-bridge.c b/drivers/gpu/drm/bridge/aux-bridge.c index b29980f95379..295e9d031e2d 100644 --- a/drivers/gpu/drm/bridge/aux-bridge.c +++ b/drivers/gpu/drm/bridge/aux-bridge.c @@ -58,9 +58,10 @@ int drm_aux_bridge_register(struct device *parent) adev->id = ret; adev->name = "aux_bridge"; adev->dev.parent = parent; - adev->dev.of_node = of_node_get(parent->of_node); adev->dev.release = drm_aux_bridge_release; + device_set_of_node_from_dev(&adev->dev, parent); + ret = auxiliary_device_init(adev); if (ret) { ida_free(&drm_aux_bridge_ida, adev->id); diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index 290e2532fab1..f3afdab55c11 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -2391,6 +2391,7 @@ static int tc_probe_bridge_endpoint(struct tc_data *tc) if (tc->pre_emphasis[0] < 0 || tc->pre_emphasis[0] > 2 || tc->pre_emphasis[1] < 0 || tc->pre_emphasis[1] > 2) { dev_err(dev, "Incorrect Pre-Emphasis setting, use either 0=0dB 1=3.5dB 2=6dB\n"); + of_node_put(node); return -EINVAL; } } diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index faa253b27664..14ac351fd76d 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -123,9 +123,8 @@ config DRM_I915_USERPTR config DRM_I915_GVT_KVMGT tristate "Enable KVM host support Intel GVT-g graphics virtualization" depends on DRM_I915 - depends on X86 + depends on KVM_X86 depends on 64BIT - depends on KVM depends on VFIO select DRM_I915_GVT select KVM_EXTERNAL_WRITE_TRACKING diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index 0a9ffc19e92f..10fd4601b9f2 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -890,7 +890,7 @@ void xe_device_l2_flush(struct xe_device *xe) spin_lock(>->global_invl_lock); xe_mmio_write32(gt, XE2_GLOBAL_INVAL, 0x1); - if (xe_mmio_wait32(gt, XE2_GLOBAL_INVAL, 0x1, 0x0, 150, NULL, true)) + if (xe_mmio_wait32(gt, XE2_GLOBAL_INVAL, 0x1, 0x0, 500, NULL, true)) xe_gt_err_once(gt, "Global invalidation timeout\n"); spin_unlock(>->global_invl_lock); diff --git a/drivers/gpu/drm/xe/xe_force_wake.c b/drivers/gpu/drm/xe/xe_force_wake.c index b263fff15273..7d9fc489dcb8 100644 --- a/drivers/gpu/drm/xe/xe_force_wake.c +++ b/drivers/gpu/drm/xe/xe_force_wake.c @@ -115,9 +115,15 @@ static int __domain_wait(struct xe_gt *gt, struct xe_force_wake_domain *domain, XE_FORCE_WAKE_ACK_TIMEOUT_MS * USEC_PER_MSEC, &value, true); if (ret) - xe_gt_notice(gt, "Force wake domain %d failed to ack %s (%pe) reg[%#x] = %#x\n", - domain->id, str_wake_sleep(wake), ERR_PTR(ret), - domain->reg_ack.addr, value); + xe_gt_err(gt, "Force wake domain %d failed to ack %s (%pe) reg[%#x] = %#x\n", + domain->id, str_wake_sleep(wake), ERR_PTR(ret), + domain->reg_ack.addr, value); + if (value == ~0) { + xe_gt_err(gt, + "Force wake domain %d: %s. MMIO unreliable (forcewake register returns 0xFFFFFFFF)!\n", + domain->id, str_wake_sleep(wake)); + ret = -EIO; + } return ret; } diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c index d16eb9ab49fb..17986bfd8818 100644 --- a/drivers/gpu/drm/xe/xe_guc_ct.c +++ b/drivers/gpu/drm/xe/xe_guc_ct.c @@ -898,6 +898,24 @@ retry_same_fence: ret = wait_event_timeout(ct->g2h_fence_wq, g2h_fence.done, HZ); /* + * Occasionally it is seen that the G2H worker starts running after a delay of more than + * a second even after being queued and activated by the Linux workqueue subsystem. This + * leads to G2H timeout error. The root cause of issue lies with scheduling latency of + * Lunarlake Hybrid CPU. Issue dissappears if we disable Lunarlake atom cores from BIOS + * and this is beyond xe kmd. + * + * TODO: Drop this change once workqueue scheduling delay issue is fixed on LNL Hybrid CPU. + */ + if (!ret) { + flush_work(&ct->g2h_worker); + if (g2h_fence.done) { + xe_gt_warn(gt, "G2H fence %u, action %04x, done\n", + g2h_fence.seqno, action[0]); + ret = 1; + } + } + + /* * Ensure we serialize with completion side to prevent UAF with fence going out of scope on * the stack, since we have no clue if it will fire after the timeout before we can erase * from the xa. Also we have some dependent loads and stores below for which we need the diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c index 8a9254e5af6e..d333be9c4227 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit.c +++ b/drivers/gpu/drm/xe/xe_guc_submit.c @@ -1726,8 +1726,13 @@ void xe_guc_submit_stop(struct xe_guc *guc) mutex_lock(&guc->submission_state.lock); - xa_for_each(&guc->submission_state.exec_queue_lookup, index, q) + xa_for_each(&guc->submission_state.exec_queue_lookup, index, q) { + /* Prevent redundant attempts to stop parallel queues */ + if (q->guc->id != index) + continue; + guc_exec_queue_stop(guc, q); + } mutex_unlock(&guc->submission_state.lock); @@ -1765,8 +1770,13 @@ int xe_guc_submit_start(struct xe_guc *guc) mutex_lock(&guc->submission_state.lock); atomic_dec(&guc->submission_state.stopped); - xa_for_each(&guc->submission_state.exec_queue_lookup, index, q) + xa_for_each(&guc->submission_state.exec_queue_lookup, index, q) { + /* Prevent redundant attempts to start parallel queues */ + if (q->guc->id != index) + continue; + guc_exec_queue_start(q); + } mutex_unlock(&guc->submission_state.lock); wake_up_all(&guc->ct.wq); diff --git a/drivers/gpu/drm/xe/xe_sync.c b/drivers/gpu/drm/xe/xe_sync.c index c6cf227ead40..2e72c06fd40d 100644 --- a/drivers/gpu/drm/xe/xe_sync.c +++ b/drivers/gpu/drm/xe/xe_sync.c @@ -54,8 +54,9 @@ static struct xe_user_fence *user_fence_create(struct xe_device *xe, u64 addr, { struct xe_user_fence *ufence; u64 __user *ptr = u64_to_user_ptr(addr); + u64 __maybe_unused prefetch_val; - if (!access_ok(ptr, sizeof(*ptr))) + if (get_user(prefetch_val, ptr)) return ERR_PTR(-EFAULT); ufence = kzalloc(sizeof(*ufence), GFP_KERNEL); diff --git a/drivers/md/md.c b/drivers/md/md.c index 179ee4afe937..67108c397c5a 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -546,6 +546,26 @@ static int mddev_set_closing_and_sync_blockdev(struct mddev *mddev, int opener_n return 0; } +/* + * The only difference from bio_chain_endio() is that the current + * bi_status of bio does not affect the bi_status of parent. + */ +static void md_end_flush(struct bio *bio) +{ + struct bio *parent = bio->bi_private; + + /* + * If any flush io error before the power failure, + * disk data may be lost. + */ + if (bio->bi_status) + pr_err("md: %pg flush io error %d\n", bio->bi_bdev, + blk_status_to_errno(bio->bi_status)); + + bio_put(bio); + bio_endio(parent); +} + bool md_flush_request(struct mddev *mddev, struct bio *bio) { struct md_rdev *rdev; @@ -565,7 +585,9 @@ bool md_flush_request(struct mddev *mddev, struct bio *bio) new = bio_alloc_bioset(rdev->bdev, 0, REQ_OP_WRITE | REQ_PREFLUSH, GFP_NOIO, &mddev->bio_set); - bio_chain(new, bio); + new->bi_private = bio; + new->bi_end_io = md_end_flush; + bio_inc_remaining(bio); submit_bio(new); } diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index f3bf1116794a..862b1fb71d86 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -4061,9 +4061,12 @@ static int raid10_run(struct mddev *mddev) } if (!mddev_is_dm(conf->mddev)) { - ret = raid10_set_queue_limits(mddev); - if (ret) + int err = raid10_set_queue_limits(mddev); + + if (err) { + ret = err; goto out_free_conf; + } } /* need to check that every block has at least one working mirror */ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 807eb3bbb11c..841e5af7b2be 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -1293,8 +1293,10 @@ static ssize_t hns3_dbg_read(struct file *filp, char __user *buffer, /* save the buffer addr until the last read operation */ *save_buf = read_buf; + } - /* get data ready for the first time to read */ + /* get data ready for the first time to read */ + if (!*ppos) { ret = hns3_dbg_read_cmd(dbg_data, hns3_dbg_cmd[index].cmd, read_buf, hns3_dbg_cmd[index].buf_len); if (ret) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 4cbc4d069a1f..b09f0cca34dc 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -11,6 +11,7 @@ #include <linux/irq.h> #include <linux/ip.h> #include <linux/ipv6.h> +#include <linux/iommu.h> #include <linux/module.h> #include <linux/pci.h> #include <linux/skbuff.h> @@ -380,6 +381,24 @@ static const struct hns3_rx_ptype hns3_rx_ptype_tbl[] = { #define HNS3_INVALID_PTYPE \ ARRAY_SIZE(hns3_rx_ptype_tbl) +static void hns3_dma_map_sync(struct device *dev, unsigned long iova) +{ + struct iommu_domain *domain = iommu_get_domain_for_dev(dev); + struct iommu_iotlb_gather iotlb_gather; + size_t granule; + + if (!domain || !iommu_is_dma_domain(domain)) + return; + + granule = 1 << __ffs(domain->pgsize_bitmap); + iova = ALIGN_DOWN(iova, granule); + iotlb_gather.start = iova; + iotlb_gather.end = iova + granule - 1; + iotlb_gather.pgsize = granule; + + iommu_iotlb_sync(domain, &iotlb_gather); +} + static irqreturn_t hns3_irq_handle(int irq, void *vector) { struct hns3_enet_tqp_vector *tqp_vector = vector; @@ -1032,6 +1051,8 @@ static bool hns3_can_use_tx_sgl(struct hns3_enet_ring *ring, static void hns3_init_tx_spare_buffer(struct hns3_enet_ring *ring) { u32 alloc_size = ring->tqp->handle->kinfo.tx_spare_buf_size; + struct net_device *netdev = ring_to_netdev(ring); + struct hns3_nic_priv *priv = netdev_priv(netdev); struct hns3_tx_spare *tx_spare; struct page *page; dma_addr_t dma; @@ -1073,6 +1094,7 @@ static void hns3_init_tx_spare_buffer(struct hns3_enet_ring *ring) tx_spare->buf = page_address(page); tx_spare->len = PAGE_SIZE << order; ring->tx_spare = tx_spare; + ring->tx_copybreak = priv->tx_copybreak; return; dma_mapping_error: @@ -1724,7 +1746,9 @@ static int hns3_map_and_fill_desc(struct hns3_enet_ring *ring, void *priv, unsigned int type) { struct hns3_desc_cb *desc_cb = &ring->desc_cb[ring->next_to_use]; + struct hnae3_handle *handle = ring->tqp->handle; struct device *dev = ring_to_dev(ring); + struct hnae3_ae_dev *ae_dev; unsigned int size; dma_addr_t dma; @@ -1756,6 +1780,13 @@ static int hns3_map_and_fill_desc(struct hns3_enet_ring *ring, void *priv, return -ENOMEM; } + /* Add a SYNC command to sync io-pgtale to avoid errors in pgtable + * prefetch + */ + ae_dev = hns3_get_ae_dev(handle); + if (ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V3) + hns3_dma_map_sync(dev, dma); + desc_cb->priv = priv; desc_cb->length = size; desc_cb->dma = dma; @@ -2452,7 +2483,6 @@ static int hns3_nic_set_features(struct net_device *netdev, return ret; } - netdev->features = features; return 0; } @@ -4868,6 +4898,30 @@ static void hns3_nic_dealloc_vector_data(struct hns3_nic_priv *priv) devm_kfree(&pdev->dev, priv->tqp_vector); } +static void hns3_update_tx_spare_buf_config(struct hns3_nic_priv *priv) +{ +#define HNS3_MIN_SPARE_BUF_SIZE (2 * 1024 * 1024) +#define HNS3_MAX_PACKET_SIZE (64 * 1024) + + struct iommu_domain *domain = iommu_get_domain_for_dev(priv->dev); + struct hnae3_ae_dev *ae_dev = hns3_get_ae_dev(priv->ae_handle); + struct hnae3_handle *handle = priv->ae_handle; + + if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V3) + return; + + if (!(domain && iommu_is_dma_domain(domain))) + return; + + priv->min_tx_copybreak = HNS3_MAX_PACKET_SIZE; + priv->min_tx_spare_buf_size = HNS3_MIN_SPARE_BUF_SIZE; + + if (priv->tx_copybreak < priv->min_tx_copybreak) + priv->tx_copybreak = priv->min_tx_copybreak; + if (handle->kinfo.tx_spare_buf_size < priv->min_tx_spare_buf_size) + handle->kinfo.tx_spare_buf_size = priv->min_tx_spare_buf_size; +} + static void hns3_ring_get_cfg(struct hnae3_queue *q, struct hns3_nic_priv *priv, unsigned int ring_type) { @@ -5101,6 +5155,7 @@ int hns3_init_all_ring(struct hns3_nic_priv *priv) int i, j; int ret; + hns3_update_tx_spare_buf_config(priv); for (i = 0; i < ring_num; i++) { ret = hns3_alloc_ring_memory(&priv->ring[i]); if (ret) { @@ -5305,6 +5360,8 @@ static int hns3_client_init(struct hnae3_handle *handle) priv->ae_handle = handle; priv->tx_timeout_count = 0; priv->max_non_tso_bd_num = ae_dev->dev_specs.max_non_tso_bd_num; + priv->min_tx_copybreak = 0; + priv->min_tx_spare_buf_size = 0; set_bit(HNS3_NIC_STATE_DOWN, &priv->state); handle->msg_enable = netif_msg_init(debug, DEFAULT_MSG_LEVEL); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index d36c4ed16d8d..caf7a4df8585 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -596,6 +596,8 @@ struct hns3_nic_priv { struct hns3_enet_coalesce rx_coal; u32 tx_copybreak; u32 rx_copybreak; + u32 min_tx_copybreak; + u32 min_tx_spare_buf_size; }; union l3_hdr_info { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index b1e988347347..97eaeec1952b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -1933,6 +1933,31 @@ static int hns3_set_tx_spare_buf_size(struct net_device *netdev, return ret; } +static int hns3_check_tx_copybreak(struct net_device *netdev, u32 copybreak) +{ + struct hns3_nic_priv *priv = netdev_priv(netdev); + + if (copybreak < priv->min_tx_copybreak) { + netdev_err(netdev, "tx copybreak %u should be no less than %u!\n", + copybreak, priv->min_tx_copybreak); + return -EINVAL; + } + return 0; +} + +static int hns3_check_tx_spare_buf_size(struct net_device *netdev, u32 buf_size) +{ + struct hns3_nic_priv *priv = netdev_priv(netdev); + + if (buf_size < priv->min_tx_spare_buf_size) { + netdev_err(netdev, + "tx spare buf size %u should be no less than %u!\n", + buf_size, priv->min_tx_spare_buf_size); + return -EINVAL; + } + return 0; +} + static int hns3_set_tunable(struct net_device *netdev, const struct ethtool_tunable *tuna, const void *data) @@ -1949,6 +1974,10 @@ static int hns3_set_tunable(struct net_device *netdev, switch (tuna->id) { case ETHTOOL_TX_COPYBREAK: + ret = hns3_check_tx_copybreak(netdev, *(u32 *)data); + if (ret) + return ret; + priv->tx_copybreak = *(u32 *)data; for (i = 0; i < h->kinfo.num_tqps; i++) @@ -1963,6 +1992,10 @@ static int hns3_set_tunable(struct net_device *netdev, break; case ETHTOOL_TX_COPYBREAK_BUF_SIZE: + ret = hns3_check_tx_spare_buf_size(netdev, *(u32 *)data); + if (ret) + return ret; + old_tx_spare_buf_size = h->kinfo.tx_spare_buf_size; new_tx_spare_buf_size = *(u32 *)data; netdev_info(netdev, "request to set tx spare buf size from %u to %u\n", diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index bd86efd92a5a..728f4777e51f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -6,6 +6,7 @@ #include <linux/etherdevice.h> #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/netdevice.h> @@ -3584,6 +3585,17 @@ static int hclge_set_vf_link_state(struct hnae3_handle *handle, int vf, return ret; } +static void hclge_set_reset_pending(struct hclge_dev *hdev, + enum hnae3_reset_type reset_type) +{ + /* When an incorrect reset type is executed, the get_reset_level + * function generates the HNAE3_NONE_RESET flag. As a result, this + * type do not need to pending. + */ + if (reset_type != HNAE3_NONE_RESET) + set_bit(reset_type, &hdev->reset_pending); +} + static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval) { u32 cmdq_src_reg, msix_src_reg, hw_err_src_reg; @@ -3604,7 +3616,7 @@ static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval) */ if (BIT(HCLGE_VECTOR0_IMPRESET_INT_B) & msix_src_reg) { dev_info(&hdev->pdev->dev, "IMP reset interrupt\n"); - set_bit(HNAE3_IMP_RESET, &hdev->reset_pending); + hclge_set_reset_pending(hdev, HNAE3_IMP_RESET); set_bit(HCLGE_COMM_STATE_CMD_DISABLE, &hdev->hw.hw.comm_state); *clearval = BIT(HCLGE_VECTOR0_IMPRESET_INT_B); hdev->rst_stats.imp_rst_cnt++; @@ -3614,7 +3626,7 @@ static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval) if (BIT(HCLGE_VECTOR0_GLOBALRESET_INT_B) & msix_src_reg) { dev_info(&hdev->pdev->dev, "global reset interrupt\n"); set_bit(HCLGE_COMM_STATE_CMD_DISABLE, &hdev->hw.hw.comm_state); - set_bit(HNAE3_GLOBAL_RESET, &hdev->reset_pending); + hclge_set_reset_pending(hdev, HNAE3_GLOBAL_RESET); *clearval = BIT(HCLGE_VECTOR0_GLOBALRESET_INT_B); hdev->rst_stats.global_rst_cnt++; return HCLGE_VECTOR0_EVENT_RST; @@ -3769,7 +3781,7 @@ static int hclge_misc_irq_init(struct hclge_dev *hdev) snprintf(hdev->misc_vector.name, HNAE3_INT_NAME_LEN, "%s-misc-%s", HCLGE_NAME, pci_name(hdev->pdev)); ret = request_irq(hdev->misc_vector.vector_irq, hclge_misc_irq_handle, - 0, hdev->misc_vector.name, hdev); + IRQ_NOAUTOEN, hdev->misc_vector.name, hdev); if (ret) { hclge_free_vector(hdev, 0); dev_err(&hdev->pdev->dev, "request misc irq(%d) fail\n", @@ -4062,7 +4074,7 @@ static void hclge_do_reset(struct hclge_dev *hdev) case HNAE3_FUNC_RESET: dev_info(&pdev->dev, "PF reset requested\n"); /* schedule again to check later */ - set_bit(HNAE3_FUNC_RESET, &hdev->reset_pending); + hclge_set_reset_pending(hdev, HNAE3_FUNC_RESET); hclge_reset_task_schedule(hdev); break; default: @@ -4096,6 +4108,8 @@ static enum hnae3_reset_type hclge_get_reset_level(struct hnae3_ae_dev *ae_dev, clear_bit(HNAE3_FLR_RESET, addr); } + clear_bit(HNAE3_NONE_RESET, addr); + if (hdev->reset_type != HNAE3_NONE_RESET && rst_level < hdev->reset_type) return HNAE3_NONE_RESET; @@ -4237,7 +4251,7 @@ static bool hclge_reset_err_handle(struct hclge_dev *hdev) return false; } else if (hdev->rst_stats.reset_fail_cnt < MAX_RESET_FAIL_CNT) { hdev->rst_stats.reset_fail_cnt++; - set_bit(hdev->reset_type, &hdev->reset_pending); + hclge_set_reset_pending(hdev, hdev->reset_type); dev_info(&hdev->pdev->dev, "re-schedule reset task(%u)\n", hdev->rst_stats.reset_fail_cnt); @@ -4480,8 +4494,20 @@ static void hclge_reset_event(struct pci_dev *pdev, struct hnae3_handle *handle) static void hclge_set_def_reset_request(struct hnae3_ae_dev *ae_dev, enum hnae3_reset_type rst_type) { +#define HCLGE_SUPPORT_RESET_TYPE \ + (BIT(HNAE3_FLR_RESET) | BIT(HNAE3_FUNC_RESET) | \ + BIT(HNAE3_GLOBAL_RESET) | BIT(HNAE3_IMP_RESET)) + struct hclge_dev *hdev = ae_dev->priv; + if (!(BIT(rst_type) & HCLGE_SUPPORT_RESET_TYPE)) { + /* To prevent reset triggered by hclge_reset_event */ + set_bit(HNAE3_NONE_RESET, &hdev->default_reset_request); + dev_warn(&hdev->pdev->dev, "unsupported reset type %d\n", + rst_type); + return; + } + set_bit(rst_type, &hdev->default_reset_request); } @@ -11891,9 +11917,6 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) hclge_init_rxd_adv_layout(hdev); - /* Enable MISC vector(vector0) */ - hclge_enable_vector(&hdev->misc_vector, true); - ret = hclge_init_wol(hdev); if (ret) dev_warn(&pdev->dev, @@ -11906,6 +11929,10 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) hclge_state_init(hdev); hdev->last_reset_time = jiffies; + /* Enable MISC vector(vector0) */ + enable_irq(hdev->misc_vector.vector_irq); + hclge_enable_vector(&hdev->misc_vector, true); + dev_info(&hdev->pdev->dev, "%s driver initialization finished.\n", HCLGE_DRIVER_NAME); @@ -12311,7 +12338,7 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev) /* Disable MISC vector(vector0) */ hclge_enable_vector(&hdev->misc_vector, false); - synchronize_irq(hdev->misc_vector.vector_irq); + disable_irq(hdev->misc_vector.vector_irq); /* Disable all hw interrupts */ hclge_config_mac_tnl_int(hdev, false); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c index 5505caea88e9..bab16c2191b2 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c @@ -58,6 +58,9 @@ bool hclge_ptp_set_tx_info(struct hnae3_handle *handle, struct sk_buff *skb) struct hclge_dev *hdev = vport->back; struct hclge_ptp *ptp = hdev->ptp; + if (!ptp) + return false; + if (!test_bit(HCLGE_PTP_FLAG_TX_EN, &ptp->flags) || test_and_set_bit(HCLGE_STATE_PTP_TX_HANDLING, &hdev->state)) { ptp->tx_skipped++; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c index 43c1c18fa81f..8c057192aae6 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c @@ -510,9 +510,9 @@ out: static int hclge_fetch_pf_reg(struct hclge_dev *hdev, void *data, struct hnae3_knic_private_info *kinfo) { -#define HCLGE_RING_REG_OFFSET 0x200 #define HCLGE_RING_INT_REG_OFFSET 0x4 + struct hnae3_queue *tqp; int i, j, reg_num; int data_num_sum; u32 *reg = data; @@ -533,10 +533,11 @@ static int hclge_fetch_pf_reg(struct hclge_dev *hdev, void *data, reg_num = ARRAY_SIZE(ring_reg_addr_list); for (j = 0; j < kinfo->num_tqps; j++) { reg += hclge_reg_get_tlv(HCLGE_REG_TAG_RING, reg_num, reg); + tqp = kinfo->tqp[j]; for (i = 0; i < reg_num; i++) - *reg++ = hclge_read_dev(&hdev->hw, - ring_reg_addr_list[i] + - HCLGE_RING_REG_OFFSET * j); + *reg++ = readl_relaxed(tqp->io_base - + HCLGE_TQP_REG_OFFSET + + ring_reg_addr_list[i]); } data_num_sum += (reg_num + HCLGE_REG_TLV_SPACE) * kinfo->num_tqps; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 094a7c7b5592..896f1eb172d3 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -1395,6 +1395,17 @@ static int hclgevf_notify_roce_client(struct hclgevf_dev *hdev, return ret; } +static void hclgevf_set_reset_pending(struct hclgevf_dev *hdev, + enum hnae3_reset_type reset_type) +{ + /* When an incorrect reset type is executed, the get_reset_level + * function generates the HNAE3_NONE_RESET flag. As a result, this + * type do not need to pending. + */ + if (reset_type != HNAE3_NONE_RESET) + set_bit(reset_type, &hdev->reset_pending); +} + static int hclgevf_reset_wait(struct hclgevf_dev *hdev) { #define HCLGEVF_RESET_WAIT_US 20000 @@ -1544,7 +1555,7 @@ static void hclgevf_reset_err_handle(struct hclgevf_dev *hdev) hdev->rst_stats.rst_fail_cnt); if (hdev->rst_stats.rst_fail_cnt < HCLGEVF_RESET_MAX_FAIL_CNT) - set_bit(hdev->reset_type, &hdev->reset_pending); + hclgevf_set_reset_pending(hdev, hdev->reset_type); if (hclgevf_is_reset_pending(hdev)) { set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state); @@ -1664,6 +1675,8 @@ static enum hnae3_reset_type hclgevf_get_reset_level(unsigned long *addr) clear_bit(HNAE3_FLR_RESET, addr); } + clear_bit(HNAE3_NONE_RESET, addr); + return rst_level; } @@ -1673,14 +1686,15 @@ static void hclgevf_reset_event(struct pci_dev *pdev, struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev); struct hclgevf_dev *hdev = ae_dev->priv; - dev_info(&hdev->pdev->dev, "received reset request from VF enet\n"); - if (hdev->default_reset_request) hdev->reset_level = hclgevf_get_reset_level(&hdev->default_reset_request); else hdev->reset_level = HNAE3_VF_FUNC_RESET; + dev_info(&hdev->pdev->dev, "received reset request from VF enet, reset level is %d\n", + hdev->reset_level); + /* reset of this VF requested */ set_bit(HCLGEVF_RESET_REQUESTED, &hdev->reset_state); hclgevf_reset_task_schedule(hdev); @@ -1691,8 +1705,20 @@ static void hclgevf_reset_event(struct pci_dev *pdev, static void hclgevf_set_def_reset_request(struct hnae3_ae_dev *ae_dev, enum hnae3_reset_type rst_type) { +#define HCLGEVF_SUPPORT_RESET_TYPE \ + (BIT(HNAE3_VF_RESET) | BIT(HNAE3_VF_FUNC_RESET) | \ + BIT(HNAE3_VF_PF_FUNC_RESET) | BIT(HNAE3_VF_FULL_RESET) | \ + BIT(HNAE3_FLR_RESET) | BIT(HNAE3_VF_EXP_RESET)) + struct hclgevf_dev *hdev = ae_dev->priv; + if (!(BIT(rst_type) & HCLGEVF_SUPPORT_RESET_TYPE)) { + /* To prevent reset triggered by hclge_reset_event */ + set_bit(HNAE3_NONE_RESET, &hdev->default_reset_request); + dev_info(&hdev->pdev->dev, "unsupported reset type %d\n", + rst_type); + return; + } set_bit(rst_type, &hdev->default_reset_request); } @@ -1849,14 +1875,14 @@ static void hclgevf_reset_service_task(struct hclgevf_dev *hdev) */ if (hdev->reset_attempts > HCLGEVF_MAX_RESET_ATTEMPTS_CNT) { /* prepare for full reset of stack + pcie interface */ - set_bit(HNAE3_VF_FULL_RESET, &hdev->reset_pending); + hclgevf_set_reset_pending(hdev, HNAE3_VF_FULL_RESET); /* "defer" schedule the reset task again */ set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state); } else { hdev->reset_attempts++; - set_bit(hdev->reset_level, &hdev->reset_pending); + hclgevf_set_reset_pending(hdev, hdev->reset_level); set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state); } hclgevf_reset_task_schedule(hdev); @@ -1979,7 +2005,7 @@ static enum hclgevf_evt_cause hclgevf_check_evt_cause(struct hclgevf_dev *hdev, rst_ing_reg = hclgevf_read_dev(&hdev->hw, HCLGEVF_RST_ING); dev_info(&hdev->pdev->dev, "receive reset interrupt 0x%x!\n", rst_ing_reg); - set_bit(HNAE3_VF_RESET, &hdev->reset_pending); + hclgevf_set_reset_pending(hdev, HNAE3_VF_RESET); set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state); set_bit(HCLGE_COMM_STATE_CMD_DISABLE, &hdev->hw.hw.comm_state); *clearval = ~(1U << HCLGEVF_VECTOR0_RST_INT_B); @@ -2289,6 +2315,7 @@ static void hclgevf_state_init(struct hclgevf_dev *hdev) clear_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state); INIT_DELAYED_WORK(&hdev->service_task, hclgevf_service_task); + timer_setup(&hdev->reset_timer, hclgevf_reset_timer, 0); mutex_init(&hdev->mbx_resp.mbx_mutex); sema_init(&hdev->reset_sem, 1); @@ -2988,7 +3015,6 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev) HCLGEVF_DRIVER_NAME); hclgevf_task_schedule(hdev, round_jiffies_relative(HZ)); - timer_setup(&hdev->reset_timer, hclgevf_reset_timer, 0); return 0; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c index 6db415d8b917..7d9d9dbc7560 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c @@ -123,10 +123,10 @@ int hclgevf_get_regs_len(struct hnae3_handle *handle) void hclgevf_get_regs(struct hnae3_handle *handle, u32 *version, void *data) { -#define HCLGEVF_RING_REG_OFFSET 0x200 #define HCLGEVF_RING_INT_REG_OFFSET 0x4 struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); + struct hnae3_queue *tqp; int i, j, reg_um; u32 *reg = data; @@ -147,10 +147,11 @@ void hclgevf_get_regs(struct hnae3_handle *handle, u32 *version, reg_um = ARRAY_SIZE(ring_reg_addr_list); for (j = 0; j < hdev->num_tqps; j++) { reg += hclgevf_reg_get_tlv(HCLGEVF_REG_TAG_RING, reg_um, reg); + tqp = &hdev->htqp[j].q; for (i = 0; i < reg_um; i++) - *reg++ = hclgevf_read_dev(&hdev->hw, - ring_reg_addr_list[i] + - HCLGEVF_RING_REG_OFFSET * j); + *reg++ = readl_relaxed(tqp->io_base - + HCLGEVF_TQP_REG_OFFSET + + ring_reg_addr_list[i]); } reg_um = ARRAY_SIZE(tqp_intr_reg_addr_list); diff --git a/drivers/net/ethernet/intel/ice/devlink/devlink_port.c b/drivers/net/ethernet/intel/ice/devlink/devlink_port.c index 928c8bdb6649..c6779d9dffff 100644 --- a/drivers/net/ethernet/intel/ice/devlink/devlink_port.c +++ b/drivers/net/ethernet/intel/ice/devlink/devlink_port.c @@ -989,5 +989,11 @@ ice_devlink_port_new(struct devlink *devlink, if (err) return err; + if (!ice_is_eswitch_mode_switchdev(pf)) { + NL_SET_ERR_MSG_MOD(extack, + "SF ports are only supported in eswitch switchdev mode"); + return -EOPNOTSUPP; + } + return ice_alloc_dynamic_port(pf, new_attr, extack, devlink_port); } diff --git a/drivers/net/ethernet/intel/ice/ice_dpll.c b/drivers/net/ethernet/intel/ice/ice_dpll.c index 74c0e7319a4c..d5ad6d84007c 100644 --- a/drivers/net/ethernet/intel/ice/ice_dpll.c +++ b/drivers/net/ethernet/intel/ice/ice_dpll.c @@ -10,6 +10,7 @@ #define ICE_DPLL_PIN_IDX_INVALID 0xff #define ICE_DPLL_RCLK_NUM_PER_PF 1 #define ICE_DPLL_PIN_ESYNC_PULSE_HIGH_PERCENT 25 +#define ICE_DPLL_PIN_GEN_RCLK_FREQ 1953125 /** * enum ice_dpll_pin_type - enumerate ice pin types: @@ -2064,6 +2065,73 @@ static int ice_dpll_init_worker(struct ice_pf *pf) } /** + * ice_dpll_init_info_pins_generic - initializes generic pins info + * @pf: board private structure + * @input: if input pins initialized + * + * Init information for generic pins, cache them in PF's pins structures. + * + * Return: + * * 0 - success + * * negative - init failure reason + */ +static int ice_dpll_init_info_pins_generic(struct ice_pf *pf, bool input) +{ + struct ice_dpll *de = &pf->dplls.eec, *dp = &pf->dplls.pps; + static const char labels[][sizeof("99")] = { + "0", "1", "2", "3", "4", "5", "6", "7", "8", + "9", "10", "11", "12", "13", "14", "15" }; + u32 cap = DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE; + enum ice_dpll_pin_type pin_type; + int i, pin_num, ret = -EINVAL; + struct ice_dpll_pin *pins; + u32 phase_adj_max; + + if (input) { + pin_num = pf->dplls.num_inputs; + pins = pf->dplls.inputs; + phase_adj_max = pf->dplls.input_phase_adj_max; + pin_type = ICE_DPLL_PIN_TYPE_INPUT; + cap |= DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE; + } else { + pin_num = pf->dplls.num_outputs; + pins = pf->dplls.outputs; + phase_adj_max = pf->dplls.output_phase_adj_max; + pin_type = ICE_DPLL_PIN_TYPE_OUTPUT; + } + if (pin_num > ARRAY_SIZE(labels)) + return ret; + + for (i = 0; i < pin_num; i++) { + pins[i].idx = i; + pins[i].prop.board_label = labels[i]; + pins[i].prop.phase_range.min = phase_adj_max; + pins[i].prop.phase_range.max = -phase_adj_max; + pins[i].prop.capabilities = cap; + pins[i].pf = pf; + ret = ice_dpll_pin_state_update(pf, &pins[i], pin_type, NULL); + if (ret) + break; + if (input && pins[i].freq == ICE_DPLL_PIN_GEN_RCLK_FREQ) + pins[i].prop.type = DPLL_PIN_TYPE_MUX; + else + pins[i].prop.type = DPLL_PIN_TYPE_EXT; + if (!input) + continue; + ret = ice_aq_get_cgu_ref_prio(&pf->hw, de->dpll_idx, i, + &de->input_prio[i]); + if (ret) + break; + ret = ice_aq_get_cgu_ref_prio(&pf->hw, dp->dpll_idx, i, + &dp->input_prio[i]); + if (ret) + break; + } + + return ret; +} + +/** * ice_dpll_init_info_direct_pins - initializes direct pins info * @pf: board private structure * @pin_type: type of pins being initialized @@ -2101,6 +2169,8 @@ ice_dpll_init_info_direct_pins(struct ice_pf *pf, default: return -EINVAL; } + if (num_pins != ice_cgu_get_num_pins(hw, input)) + return ice_dpll_init_info_pins_generic(pf, input); for (i = 0; i < num_pins; i++) { caps = 0; diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c index da88c6ccfaeb..dfd49732bd5b 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c @@ -34,7 +34,6 @@ static const struct ice_cgu_pin_desc ice_e810t_sfp_cgu_inputs[] = { ARRAY_SIZE(ice_cgu_pin_freq_common), ice_cgu_pin_freq_common }, { "GNSS-1PPS", ZL_REF4P, DPLL_PIN_TYPE_GNSS, ARRAY_SIZE(ice_cgu_pin_freq_1_hz), ice_cgu_pin_freq_1_hz }, - { "OCXO", ZL_REF4N, DPLL_PIN_TYPE_INT_OSCILLATOR, 0, }, }; static const struct ice_cgu_pin_desc ice_e810t_qsfp_cgu_inputs[] = { @@ -52,7 +51,6 @@ static const struct ice_cgu_pin_desc ice_e810t_qsfp_cgu_inputs[] = { ARRAY_SIZE(ice_cgu_pin_freq_common), ice_cgu_pin_freq_common }, { "GNSS-1PPS", ZL_REF4P, DPLL_PIN_TYPE_GNSS, ARRAY_SIZE(ice_cgu_pin_freq_1_hz), ice_cgu_pin_freq_1_hz }, - { "OCXO", ZL_REF4N, DPLL_PIN_TYPE_INT_OSCILLATOR, }, }; static const struct ice_cgu_pin_desc ice_e810t_sfp_cgu_outputs[] = { @@ -6048,6 +6046,25 @@ ice_cgu_get_pin_desc(struct ice_hw *hw, bool input, int *size) } /** + * ice_cgu_get_num_pins - get pin description array size + * @hw: pointer to the hw struct + * @input: if request is done against input or output pins + * + * Return: size of pin description array for given hw. + */ +int ice_cgu_get_num_pins(struct ice_hw *hw, bool input) +{ + const struct ice_cgu_pin_desc *t; + int size; + + t = ice_cgu_get_pin_desc(hw, input, &size); + if (t) + return size; + + return 0; +} + +/** * ice_cgu_get_pin_type - get pin's type * @hw: pointer to the hw struct * @pin: pin index diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h index 656daff3447e..47af7c5c79b8 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h +++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h @@ -406,6 +406,7 @@ int ice_read_sma_ctrl(struct ice_hw *hw, u8 *data); int ice_write_sma_ctrl(struct ice_hw *hw, u8 data); int ice_read_pca9575_reg(struct ice_hw *hw, u8 offset, u8 *data); int ice_ptp_read_sdp_ac(struct ice_hw *hw, __le16 *entries, uint *num_entries); +int ice_cgu_get_num_pins(struct ice_hw *hw, bool input); enum dpll_pin_type ice_cgu_get_pin_type(struct ice_hw *hw, u8 pin, bool input); struct dpll_pin_frequency * ice_cgu_get_pin_freq_supp(struct ice_hw *hw, u8 pin, bool input, u8 *num); diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index f1d088168723..b83df5f94b1f 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -907,7 +907,7 @@ static int igb_request_msix(struct igb_adapter *adapter) int i, err = 0, vector = 0, free_vector = 0; err = request_irq(adapter->msix_entries[vector].vector, - igb_msix_other, 0, netdev->name, adapter); + igb_msix_other, IRQF_NO_THREAD, netdev->name, adapter); if (err) goto err_out; diff --git a/drivers/net/ethernet/mediatek/mtk_wed_wo.h b/drivers/net/ethernet/mediatek/mtk_wed_wo.h index 87a67fa3868d..c01b1e8428f6 100644 --- a/drivers/net/ethernet/mediatek/mtk_wed_wo.h +++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h @@ -91,8 +91,8 @@ enum mtk_wed_dummy_cr_idx { #define MT7981_FIRMWARE_WO "mediatek/mt7981_wo.bin" #define MT7986_FIRMWARE_WO0 "mediatek/mt7986_wo_0.bin" #define MT7986_FIRMWARE_WO1 "mediatek/mt7986_wo_1.bin" -#define MT7988_FIRMWARE_WO0 "mediatek/mt7988_wo_0.bin" -#define MT7988_FIRMWARE_WO1 "mediatek/mt7988_wo_1.bin" +#define MT7988_FIRMWARE_WO0 "mediatek/mt7988/mt7988_wo_0.bin" +#define MT7988_FIRMWARE_WO1 "mediatek/mt7988/mt7988_wo_1.bin" #define MTK_WO_MCU_CFG_LS_BASE 0 #define MTK_WO_MCU_CFG_LS_HW_VER_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x000) diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index 060e5b939211..d6f37456fb31 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -389,15 +389,27 @@ static void mlxsw_pci_wqe_frag_unmap(struct mlxsw_pci *mlxsw_pci, char *wqe, dma_unmap_single(&pdev->dev, mapaddr, frag_len, direction); } -static struct sk_buff *mlxsw_pci_rdq_build_skb(struct page *pages[], +static struct sk_buff *mlxsw_pci_rdq_build_skb(struct mlxsw_pci_queue *q, + struct page *pages[], u16 byte_count) { + struct mlxsw_pci_queue *cq = q->u.rdq.cq; unsigned int linear_data_size; + struct page_pool *page_pool; struct sk_buff *skb; int page_index = 0; bool linear_only; void *data; + linear_only = byte_count + MLXSW_PCI_RX_BUF_SW_OVERHEAD <= PAGE_SIZE; + linear_data_size = linear_only ? byte_count : + PAGE_SIZE - + MLXSW_PCI_RX_BUF_SW_OVERHEAD; + + page_pool = cq->u.cq.page_pool; + page_pool_dma_sync_for_cpu(page_pool, pages[page_index], + MLXSW_PCI_SKB_HEADROOM, linear_data_size); + data = page_address(pages[page_index]); net_prefetch(data); @@ -405,11 +417,6 @@ static struct sk_buff *mlxsw_pci_rdq_build_skb(struct page *pages[], if (unlikely(!skb)) return ERR_PTR(-ENOMEM); - linear_only = byte_count + MLXSW_PCI_RX_BUF_SW_OVERHEAD <= PAGE_SIZE; - linear_data_size = linear_only ? byte_count : - PAGE_SIZE - - MLXSW_PCI_RX_BUF_SW_OVERHEAD; - skb_reserve(skb, MLXSW_PCI_SKB_HEADROOM); skb_put(skb, linear_data_size); @@ -425,6 +432,7 @@ static struct sk_buff *mlxsw_pci_rdq_build_skb(struct page *pages[], page = pages[page_index]; frag_size = min(byte_count, PAGE_SIZE); + page_pool_dma_sync_for_cpu(page_pool, page, 0, frag_size); skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, 0, frag_size, PAGE_SIZE); byte_count -= frag_size; @@ -760,7 +768,7 @@ static void mlxsw_pci_cqe_rdq_handle(struct mlxsw_pci *mlxsw_pci, if (err) goto out; - skb = mlxsw_pci_rdq_build_skb(pages, byte_count); + skb = mlxsw_pci_rdq_build_skb(q, pages, byte_count); if (IS_ERR(skb)) { dev_err_ratelimited(&pdev->dev, "Failed to build skb for RDQ\n"); mlxsw_pci_rdq_pages_recycle(q, pages, num_sg_entries); @@ -988,12 +996,13 @@ static int mlxsw_pci_cq_page_pool_init(struct mlxsw_pci_queue *q, if (cq_type != MLXSW_PCI_CQ_RDQ) return 0; - pp_params.flags = PP_FLAG_DMA_MAP; + pp_params.flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV; pp_params.pool_size = MLXSW_PCI_WQE_COUNT * mlxsw_pci->num_sg_entries; pp_params.nid = dev_to_node(&mlxsw_pci->pdev->dev); pp_params.dev = &mlxsw_pci->pdev->dev; pp_params.napi = &q->u.cq.napi; pp_params.dma_dir = DMA_FROM_DEVICE; + pp_params.max_len = PAGE_SIZE; page_pool = page_pool_create(&pp_params); if (IS_ERR(page_pool)) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c index d761a1235994..7ea798a4949e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c @@ -481,11 +481,33 @@ mlxsw_sp_ipip_ol_netdev_change_gre6(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_ipip_entry *ipip_entry, struct netlink_ext_ack *extack) { + u32 new_kvdl_index, old_kvdl_index = ipip_entry->dip_kvdl_index; + struct in6_addr old_addr6 = ipip_entry->parms.daddr.addr6; struct mlxsw_sp_ipip_parms new_parms; + int err; new_parms = mlxsw_sp_ipip_netdev_parms_init_gre6(ipip_entry->ol_dev); - return mlxsw_sp_ipip_ol_netdev_change_gre(mlxsw_sp, ipip_entry, - &new_parms, extack); + + err = mlxsw_sp_ipv6_addr_kvdl_index_get(mlxsw_sp, + &new_parms.daddr.addr6, + &new_kvdl_index); + if (err) + return err; + ipip_entry->dip_kvdl_index = new_kvdl_index; + + err = mlxsw_sp_ipip_ol_netdev_change_gre(mlxsw_sp, ipip_entry, + &new_parms, extack); + if (err) + goto err_change_gre; + + mlxsw_sp_ipv6_addr_put(mlxsw_sp, &old_addr6); + + return 0; + +err_change_gre: + ipip_entry->dip_kvdl_index = old_kvdl_index; + mlxsw_sp_ipv6_addr_put(mlxsw_sp, &new_parms.daddr.addr6); + return err; } static int diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c index 5b174cb95eb8..d94081c7658e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c @@ -16,6 +16,7 @@ #include "spectrum.h" #include "spectrum_ptp.h" #include "core.h" +#include "txheader.h" #define MLXSW_SP1_PTP_CLOCK_CYCLES_SHIFT 29 #define MLXSW_SP1_PTP_CLOCK_FREQ_KHZ 156257 /* 6.4nSec */ @@ -1684,6 +1685,12 @@ int mlxsw_sp_ptp_txhdr_construct(struct mlxsw_core *mlxsw_core, struct sk_buff *skb, const struct mlxsw_tx_info *tx_info) { + if (skb_cow_head(skb, MLXSW_TXHDR_LEN)) { + this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped); + dev_kfree_skb_any(skb); + return -ENOMEM; + } + mlxsw_sp_txhdr_construct(skb, tx_info); return 0; } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c index 7c895e0ae71f..22a044d93e17 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c @@ -203,8 +203,12 @@ static void _dwmac4_dump_dma_regs(struct stmmac_priv *priv, readl(ioaddr + DMA_CHAN_TX_CONTROL(dwmac4_addrs, channel)); reg_space[DMA_CHAN_RX_CONTROL(default_addrs, channel) / 4] = readl(ioaddr + DMA_CHAN_RX_CONTROL(dwmac4_addrs, channel)); + reg_space[DMA_CHAN_TX_BASE_ADDR_HI(default_addrs, channel) / 4] = + readl(ioaddr + DMA_CHAN_TX_BASE_ADDR_HI(dwmac4_addrs, channel)); reg_space[DMA_CHAN_TX_BASE_ADDR(default_addrs, channel) / 4] = readl(ioaddr + DMA_CHAN_TX_BASE_ADDR(dwmac4_addrs, channel)); + reg_space[DMA_CHAN_RX_BASE_ADDR_HI(default_addrs, channel) / 4] = + readl(ioaddr + DMA_CHAN_RX_BASE_ADDR_HI(dwmac4_addrs, channel)); reg_space[DMA_CHAN_RX_BASE_ADDR(default_addrs, channel) / 4] = readl(ioaddr + DMA_CHAN_RX_BASE_ADDR(dwmac4_addrs, channel)); reg_space[DMA_CHAN_TX_END_ADDR(default_addrs, channel) / 4] = @@ -225,8 +229,12 @@ static void _dwmac4_dump_dma_regs(struct stmmac_priv *priv, readl(ioaddr + DMA_CHAN_CUR_TX_DESC(dwmac4_addrs, channel)); reg_space[DMA_CHAN_CUR_RX_DESC(default_addrs, channel) / 4] = readl(ioaddr + DMA_CHAN_CUR_RX_DESC(dwmac4_addrs, channel)); + reg_space[DMA_CHAN_CUR_TX_BUF_ADDR_HI(default_addrs, channel) / 4] = + readl(ioaddr + DMA_CHAN_CUR_TX_BUF_ADDR_HI(dwmac4_addrs, channel)); reg_space[DMA_CHAN_CUR_TX_BUF_ADDR(default_addrs, channel) / 4] = readl(ioaddr + DMA_CHAN_CUR_TX_BUF_ADDR(dwmac4_addrs, channel)); + reg_space[DMA_CHAN_CUR_RX_BUF_ADDR_HI(default_addrs, channel) / 4] = + readl(ioaddr + DMA_CHAN_CUR_RX_BUF_ADDR_HI(dwmac4_addrs, channel)); reg_space[DMA_CHAN_CUR_RX_BUF_ADDR(default_addrs, channel) / 4] = readl(ioaddr + DMA_CHAN_CUR_RX_BUF_ADDR(dwmac4_addrs, channel)); reg_space[DMA_CHAN_STATUS(default_addrs, channel) / 4] = diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h index 17d9120db5fe..4f980dcd3958 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h @@ -127,7 +127,9 @@ static inline u32 dma_chanx_base_addr(const struct dwmac4_addrs *addrs, #define DMA_CHAN_SLOT_CTRL_STATUS(addrs, x) (dma_chanx_base_addr(addrs, x) + 0x3c) #define DMA_CHAN_CUR_TX_DESC(addrs, x) (dma_chanx_base_addr(addrs, x) + 0x44) #define DMA_CHAN_CUR_RX_DESC(addrs, x) (dma_chanx_base_addr(addrs, x) + 0x4c) +#define DMA_CHAN_CUR_TX_BUF_ADDR_HI(addrs, x) (dma_chanx_base_addr(addrs, x) + 0x50) #define DMA_CHAN_CUR_TX_BUF_ADDR(addrs, x) (dma_chanx_base_addr(addrs, x) + 0x54) +#define DMA_CHAN_CUR_RX_BUF_ADDR_HI(addrs, x) (dma_chanx_base_addr(addrs, x) + 0x58) #define DMA_CHAN_CUR_RX_BUF_ADDR(addrs, x) (dma_chanx_base_addr(addrs, x) + 0x5c) #define DMA_CHAN_STATUS(addrs, x) (dma_chanx_base_addr(addrs, x) + 0x60) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index d3895d7eecfc..208dbc68aaf9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -4304,11 +4304,6 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) if (dma_mapping_error(priv->device, des)) goto dma_map_err; - tx_q->tx_skbuff_dma[first_entry].buf = des; - tx_q->tx_skbuff_dma[first_entry].len = skb_headlen(skb); - tx_q->tx_skbuff_dma[first_entry].map_as_page = false; - tx_q->tx_skbuff_dma[first_entry].buf_type = STMMAC_TXBUF_T_SKB; - if (priv->dma_cap.addr64 <= 32) { first->des0 = cpu_to_le32(des); @@ -4327,6 +4322,23 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) stmmac_tso_allocator(priv, des, tmp_pay_len, (nfrags == 0), queue); + /* In case two or more DMA transmit descriptors are allocated for this + * non-paged SKB data, the DMA buffer address should be saved to + * tx_q->tx_skbuff_dma[].buf corresponding to the last descriptor, + * and leave the other tx_q->tx_skbuff_dma[].buf as NULL to guarantee + * that stmmac_tx_clean() does not unmap the entire DMA buffer too early + * since the tail areas of the DMA buffer can be accessed by DMA engine + * sooner or later. + * By saving the DMA buffer address to tx_q->tx_skbuff_dma[].buf + * corresponding to the last descriptor, stmmac_tx_clean() will unmap + * this DMA buffer right after the DMA engine completely finishes the + * full buffer transmission. + */ + tx_q->tx_skbuff_dma[tx_q->cur_tx].buf = des; + tx_q->tx_skbuff_dma[tx_q->cur_tx].len = skb_headlen(skb); + tx_q->tx_skbuff_dma[tx_q->cur_tx].map_as_page = false; + tx_q->tx_skbuff_dma[tx_q->cur_tx].buf_type = STMMAC_TXBUF_T_SKB; + /* Prepare fragments */ for (i = 0; i < nfrags; i++) { const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index a60bfb1abb7f..70f981887518 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -1702,20 +1702,24 @@ static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[]) return -EINVAL; if (data[IFLA_GTP_FD0]) { - u32 fd0 = nla_get_u32(data[IFLA_GTP_FD0]); + int fd0 = nla_get_u32(data[IFLA_GTP_FD0]); - sk0 = gtp_encap_enable_socket(fd0, UDP_ENCAP_GTP0, gtp); - if (IS_ERR(sk0)) - return PTR_ERR(sk0); + if (fd0 >= 0) { + sk0 = gtp_encap_enable_socket(fd0, UDP_ENCAP_GTP0, gtp); + if (IS_ERR(sk0)) + return PTR_ERR(sk0); + } } if (data[IFLA_GTP_FD1]) { - u32 fd1 = nla_get_u32(data[IFLA_GTP_FD1]); + int fd1 = nla_get_u32(data[IFLA_GTP_FD1]); - sk1u = gtp_encap_enable_socket(fd1, UDP_ENCAP_GTP1U, gtp); - if (IS_ERR(sk1u)) { - gtp_encap_disable_sock(sk0); - return PTR_ERR(sk1u); + if (fd1 >= 0) { + sk1u = gtp_encap_enable_socket(fd1, UDP_ENCAP_GTP1U, gtp); + if (IS_ERR(sk1u)) { + gtp_encap_disable_sock(sk0); + return PTR_ERR(sk1u); + } } } diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 26034f80d4a4..ee2159282573 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -3798,8 +3798,7 @@ static void macsec_free_netdev(struct net_device *dev) { struct macsec_dev *macsec = macsec_priv(dev); - if (macsec->secy.tx_sc.md_dst) - metadata_dst_free(macsec->secy.tx_sc.md_dst); + dst_release(&macsec->secy.tx_sc.md_dst->dst); free_percpu(macsec->stats); free_percpu(macsec->secy.tx_sc.stats); diff --git a/drivers/net/mctp/mctp-i2c.c b/drivers/net/mctp/mctp-i2c.c index 4dc057c121f5..e70fb6687994 100644 --- a/drivers/net/mctp/mctp-i2c.c +++ b/drivers/net/mctp/mctp-i2c.c @@ -588,6 +588,9 @@ static int mctp_i2c_header_create(struct sk_buff *skb, struct net_device *dev, if (len > MCTP_I2C_MAXMTU) return -EMSGSIZE; + if (!daddr || !saddr) + return -EINVAL; + lldst = *((u8 *)daddr); llsrc = *((u8 *)saddr); diff --git a/drivers/net/netdevsim/fib.c b/drivers/net/netdevsim/fib.c index 41e80f78b316..16c382c42227 100644 --- a/drivers/net/netdevsim/fib.c +++ b/drivers/net/netdevsim/fib.c @@ -1377,10 +1377,12 @@ static ssize_t nsim_nexthop_bucket_activity_write(struct file *file, if (pos != 0) return -EINVAL; - if (size > sizeof(buf)) + if (size > sizeof(buf) - 1) return -EINVAL; if (copy_from_user(buf, user_buf, size)) return -EFAULT; + buf[size] = 0; + if (sscanf(buf, "%u %hu", &nhid, &bucket_index) != 2) return -EINVAL; diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index f137c82f1c0f..0c011d8f5d4d 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -1076,6 +1076,7 @@ static const struct usb_device_id products[] = { USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x581d, USB_CLASS_VENDOR_SPEC, 1, 7), .driver_info = (unsigned long)&qmi_wwan_info, }, + {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0122)}, /* Quectel RG650V */ {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0125)}, /* Quectel EC25, EC20 R2.0 Mini PCIe */ {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0306)}, /* Quectel EP06/EG06/EM06 */ {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0512)}, /* Quectel EG12/EM12 */ diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index a5612c799f5e..468c73974046 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -10069,6 +10069,7 @@ static const struct usb_device_id rtl8152_table[] = { { USB_DEVICE(VENDOR_ID_LENOVO, 0x3062) }, { USB_DEVICE(VENDOR_ID_LENOVO, 0x3069) }, { USB_DEVICE(VENDOR_ID_LENOVO, 0x3082) }, + { USB_DEVICE(VENDOR_ID_LENOVO, 0x3098) }, { USB_DEVICE(VENDOR_ID_LENOVO, 0x7205) }, { USB_DEVICE(VENDOR_ID_LENOVO, 0x720c) }, { USB_DEVICE(VENDOR_ID_LENOVO, 0x7214) }, diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index dbaf26d6a7a6..16d07d619b4d 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -3043,9 +3043,14 @@ ath10k_wmi_tlv_op_cleanup_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu) { struct ath10k_skb_cb *cb = ATH10K_SKB_CB(msdu); + struct ath10k_mgmt_tx_pkt_addr *pkt_addr; struct ath10k_wmi *wmi = &ar->wmi; - idr_remove(&wmi->mgmt_pending_tx, cb->msdu_id); + spin_lock_bh(&ar->data_lock); + pkt_addr = idr_remove(&wmi->mgmt_pending_tx, cb->msdu_id); + spin_unlock_bh(&ar->data_lock); + + kfree(pkt_addr); return 0; } diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 4861179b2217..5e061f7525a6 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -2441,6 +2441,7 @@ wmi_process_mgmt_tx_comp(struct ath10k *ar, struct mgmt_tx_compl_params *param) dma_unmap_single(ar->dev, pkt_addr->paddr, msdu->len, DMA_TO_DEVICE); info = IEEE80211_SKB_CB(msdu); + kfree(pkt_addr); if (param->status) { info->flags &= ~IEEE80211_TX_STAT_ACK; @@ -9612,6 +9613,7 @@ static int ath10k_wmi_mgmt_tx_clean_up_pending(int msdu_id, void *ptr, dma_unmap_single(ar->dev, pkt_addr->paddr, msdu->len, DMA_TO_DEVICE); ieee80211_free_txskb(ar->hw, msdu); + kfree(pkt_addr); return 0; } diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c index c087d8a0f5b2..40088e62572e 100644 --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c @@ -5291,8 +5291,11 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id, hal_status == HAL_TLV_STATUS_PPDU_DONE) { rx_mon_stats->status_ppdu_done++; pmon->mon_ppdu_status = DP_PPDU_STATUS_DONE; - ath11k_dp_rx_mon_dest_process(ar, mac_id, budget, napi); - pmon->mon_ppdu_status = DP_PPDU_STATUS_START; + if (!ab->hw_params.full_monitor_mode) { + ath11k_dp_rx_mon_dest_process(ar, mac_id, + budget, napi); + pmon->mon_ppdu_status = DP_PPDU_STATUS_START; + } } if (ppdu_info->peer_id == HAL_INVALID_PEERID || diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index f29ac6de7139..19702b6f09c3 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -306,7 +306,7 @@ static void wil_rx_add_radiotap_header(struct wil6210_priv *wil, struct sk_buff *skb) { struct wil6210_rtap { - struct ieee80211_radiotap_header rthdr; + struct ieee80211_radiotap_header_fixed rthdr; /* fields should be in the order of bits in rthdr.it_present */ /* flags */ u8 flags; diff --git a/drivers/net/wireless/broadcom/brcm80211/Kconfig b/drivers/net/wireless/broadcom/brcm80211/Kconfig index 3a1a35b5672f..19d0c003f626 100644 --- a/drivers/net/wireless/broadcom/brcm80211/Kconfig +++ b/drivers/net/wireless/broadcom/brcm80211/Kconfig @@ -27,6 +27,7 @@ source "drivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig" config BRCM_TRACING bool "Broadcom device tracing" depends on BRCMSMAC || BRCMFMAC + depends on TRACING help If you say Y here, the Broadcom wireless drivers will register with ftrace to dump event information into the trace ringbuffer. diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c index 15bf35f2de2a..215814861cbd 100644 --- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c @@ -2515,7 +2515,7 @@ static void isr_rx_monitor(struct ipw2100_priv *priv, int i, * to build this manually element by element, we can write it much * more efficiently than we can parse it. ORDER MATTERS HERE */ struct ipw_rt_hdr { - struct ieee80211_radiotap_header rt_hdr; + struct ieee80211_radiotap_header_fixed rt_hdr; s8 rt_dbmsignal; /* signal in dbM, kluged to signed */ } *ipw_rt; diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.h b/drivers/net/wireless/intel/ipw2x00/ipw2200.h index d3db54e6d37c..19310fd0d8eb 100644 --- a/drivers/net/wireless/intel/ipw2x00/ipw2200.h +++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.h @@ -1141,7 +1141,7 @@ struct ipw_prom_priv { * structure is provided regardless of any bits unset. */ struct ipw_rt_hdr { - struct ieee80211_radiotap_header rt_hdr; + struct ieee80211_radiotap_header_fixed rt_hdr; u64 rt_tsf; /* TSF */ /* XXX */ u8 rt_flags; /* radiotap packet flags */ u8 rt_rate; /* rate in 500kb/s */ diff --git a/drivers/net/wireless/intel/iwlegacy/common.c b/drivers/net/wireless/intel/iwlegacy/common.c index 9d33a66a49b5..958dd4f9bc69 100644 --- a/drivers/net/wireless/intel/iwlegacy/common.c +++ b/drivers/net/wireless/intel/iwlegacy/common.c @@ -3122,6 +3122,7 @@ il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd) struct il_cmd_meta *out_meta; dma_addr_t phys_addr; unsigned long flags; + u8 *out_payload; u32 idx; u16 fix_size; @@ -3157,6 +3158,16 @@ il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd) out_cmd = txq->cmd[idx]; out_meta = &txq->meta[idx]; + /* The payload is in the same place in regular and huge + * command buffers, but we need to let the compiler know when + * we're using a larger payload buffer to avoid "field- + * spanning write" warnings at run-time for huge commands. + */ + if (cmd->flags & CMD_SIZE_HUGE) + out_payload = ((struct il_device_cmd_huge *)out_cmd)->cmd.payload; + else + out_payload = out_cmd->cmd.payload; + if (WARN_ON(out_meta->flags & CMD_MAPPED)) { spin_unlock_irqrestore(&il->hcmd_lock, flags); return -ENOSPC; @@ -3170,7 +3181,7 @@ il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd) out_meta->callback = cmd->callback; out_cmd->hdr.cmd = cmd->id; - memcpy(&out_cmd->cmd.payload, cmd->data, cmd->len); + memcpy(out_payload, cmd->data, cmd->len); /* At this point, the out_cmd now has all of the incoming cmd * information */ @@ -4962,6 +4973,8 @@ il_pci_resume(struct device *device) */ pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); + _il_wr(il, CSR_INT, 0xffffffff); + _il_wr(il, CSR_FH_INT_STATUS, 0xffffffff); il_enable_interrupts(il); if (!(_il_rd(il, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) diff --git a/drivers/net/wireless/intel/iwlegacy/common.h b/drivers/net/wireless/intel/iwlegacy/common.h index 2147781b5fff..725c2a88ddb7 100644 --- a/drivers/net/wireless/intel/iwlegacy/common.h +++ b/drivers/net/wireless/intel/iwlegacy/common.h @@ -560,6 +560,18 @@ struct il_device_cmd { #define TFD_MAX_PAYLOAD_SIZE (sizeof(struct il_device_cmd)) +/** + * struct il_device_cmd_huge + * + * For use when sending huge commands. + */ +struct il_device_cmd_huge { + struct il_cmd_header hdr; /* uCode API */ + union { + u8 payload[IL_MAX_CMD_SIZE - sizeof(struct il_cmd_header)]; + } __packed cmd; +} __packed; + struct il_host_cmd { const void *data; unsigned long reply_page; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c index a7cea0a55b35..0bc32291815e 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c @@ -429,38 +429,28 @@ out_free: return ret; } -static int iwl_acpi_sar_set_profile(union acpi_object *table, - struct iwl_sar_profile *profile, - bool enabled, u8 num_chains, - u8 num_sub_bands) +static int +iwl_acpi_parse_chains_table(union acpi_object *table, + struct iwl_sar_profile_chain *chains, + u8 num_chains, u8 num_sub_bands) { - int i, j, idx = 0; - - /* - * The table from ACPI is flat, but we store it in a - * structured array. - */ - for (i = 0; i < BIOS_SAR_MAX_CHAINS_PER_PROFILE; i++) { - for (j = 0; j < BIOS_SAR_MAX_SUB_BANDS_NUM; j++) { + for (u8 chain = 0; chain < num_chains; chain++) { + for (u8 subband = 0; subband < BIOS_SAR_MAX_SUB_BANDS_NUM; + subband++) { /* if we don't have the values, use the default */ - if (i >= num_chains || j >= num_sub_bands) { - profile->chains[i].subbands[j] = 0; + if (subband >= num_sub_bands) { + chains[chain].subbands[subband] = 0; + } else if (table->type != ACPI_TYPE_INTEGER || + table->integer.value > U8_MAX) { + return -EINVAL; } else { - if (table[idx].type != ACPI_TYPE_INTEGER || - table[idx].integer.value > U8_MAX) - return -EINVAL; - - profile->chains[i].subbands[j] = - table[idx].integer.value; - - idx++; + chains[chain].subbands[subband] = + table->integer.value; + table++; } } } - /* Only if all values were valid can the profile be enabled */ - profile->enabled = enabled; - return 0; } @@ -543,9 +533,11 @@ read_table: /* The profile from WRDS is officially profile 1, but goes * into sar_profiles[0] (because we don't have a profile 0). */ - ret = iwl_acpi_sar_set_profile(table, &fwrt->sar_profiles[0], - flags & IWL_SAR_ENABLE_MSK, - num_chains, num_sub_bands); + ret = iwl_acpi_parse_chains_table(table, fwrt->sar_profiles[0].chains, + num_chains, num_sub_bands); + if (!ret && flags & IWL_SAR_ENABLE_MSK) + fwrt->sar_profiles[0].enabled = true; + out_free: kfree(data); return ret; @@ -557,7 +549,7 @@ int iwl_acpi_get_ewrd_table(struct iwl_fw_runtime *fwrt) bool enabled; int i, n_profiles, tbl_rev, pos; int ret = 0; - u8 num_chains, num_sub_bands; + u8 num_sub_bands; data = iwl_acpi_get_object(fwrt->dev, ACPI_EWRD_METHOD); if (IS_ERR(data)) @@ -573,7 +565,6 @@ int iwl_acpi_get_ewrd_table(struct iwl_fw_runtime *fwrt) goto out_free; } - num_chains = ACPI_SAR_NUM_CHAINS_REV2; num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV2; goto read_table; @@ -589,7 +580,6 @@ int iwl_acpi_get_ewrd_table(struct iwl_fw_runtime *fwrt) goto out_free; } - num_chains = ACPI_SAR_NUM_CHAINS_REV1; num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV1; goto read_table; @@ -605,7 +595,6 @@ int iwl_acpi_get_ewrd_table(struct iwl_fw_runtime *fwrt) goto out_free; } - num_chains = ACPI_SAR_NUM_CHAINS_REV0; num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV0; goto read_table; @@ -637,23 +626,54 @@ read_table: /* the tables start at element 3 */ pos = 3; + BUILD_BUG_ON(ACPI_SAR_NUM_CHAINS_REV0 != ACPI_SAR_NUM_CHAINS_REV1); + BUILD_BUG_ON(ACPI_SAR_NUM_CHAINS_REV2 != 2 * ACPI_SAR_NUM_CHAINS_REV0); + + /* parse non-cdb chains for all profiles */ for (i = 0; i < n_profiles; i++) { union acpi_object *table = &wifi_pkg->package.elements[pos]; + /* The EWRD profiles officially go from 2 to 4, but we * save them in sar_profiles[1-3] (because we don't * have profile 0). So in the array we start from 1. */ - ret = iwl_acpi_sar_set_profile(table, - &fwrt->sar_profiles[i + 1], - enabled, num_chains, - num_sub_bands); + ret = iwl_acpi_parse_chains_table(table, + fwrt->sar_profiles[i + 1].chains, + ACPI_SAR_NUM_CHAINS_REV0, + num_sub_bands); if (ret < 0) - break; + goto out_free; /* go to the next table */ - pos += num_chains * num_sub_bands; + pos += ACPI_SAR_NUM_CHAINS_REV0 * num_sub_bands; } + /* non-cdb table revisions */ + if (tbl_rev < 2) + goto set_enabled; + + /* parse cdb chains for all profiles */ + for (i = 0; i < n_profiles; i++) { + struct iwl_sar_profile_chain *chains; + union acpi_object *table; + + table = &wifi_pkg->package.elements[pos]; + chains = &fwrt->sar_profiles[i + 1].chains[ACPI_SAR_NUM_CHAINS_REV0]; + ret = iwl_acpi_parse_chains_table(table, + chains, + ACPI_SAR_NUM_CHAINS_REV0, + num_sub_bands); + if (ret < 0) + goto out_free; + + /* go to the next table */ + pos += ACPI_SAR_NUM_CHAINS_REV0 * num_sub_bands; + } + +set_enabled: + for (i = 0; i < n_profiles; i++) + fwrt->sar_profiles[i + 1].enabled = enabled; + out_free: kfree(data); return ret; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/init.c b/drivers/net/wireless/intel/iwlwifi/fw/init.c index d8b083be5b6b..de87e0e3e072 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/init.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/init.c @@ -39,10 +39,12 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans, } IWL_EXPORT_SYMBOL(iwl_fw_runtime_init); +/* Assumes the appropriate lock is held by the caller */ void iwl_fw_runtime_suspend(struct iwl_fw_runtime *fwrt) { iwl_fw_suspend_timestamp(fwrt); - iwl_dbg_tlv_time_point(fwrt, IWL_FW_INI_TIME_POINT_HOST_D3_START, NULL); + iwl_dbg_tlv_time_point_sync(fwrt, IWL_FW_INI_TIME_POINT_HOST_D3_START, + NULL); } IWL_EXPORT_SYMBOL(iwl_fw_runtime_suspend); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 2abfc986701f..c620911a1193 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -1413,25 +1413,35 @@ _iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op) const struct iwl_op_mode_ops *ops = op->ops; struct dentry *dbgfs_dir = NULL; struct iwl_op_mode *op_mode = NULL; + int retry, max_retry = !!iwlwifi_mod_params.fw_restart * IWL_MAX_INIT_RETRY; /* also protects start/stop from racing against each other */ lockdep_assert_held(&iwlwifi_opmode_table_mtx); + for (retry = 0; retry <= max_retry; retry++) { + #ifdef CONFIG_IWLWIFI_DEBUGFS - drv->dbgfs_op_mode = debugfs_create_dir(op->name, - drv->dbgfs_drv); - dbgfs_dir = drv->dbgfs_op_mode; + drv->dbgfs_op_mode = debugfs_create_dir(op->name, + drv->dbgfs_drv); + dbgfs_dir = drv->dbgfs_op_mode; #endif - op_mode = ops->start(drv->trans, drv->trans->cfg, - &drv->fw, dbgfs_dir); - if (op_mode) - return op_mode; + op_mode = ops->start(drv->trans, drv->trans->cfg, + &drv->fw, dbgfs_dir); + + if (op_mode) + return op_mode; + + if (test_bit(STATUS_TRANS_DEAD, &drv->trans->status)) + break; + + IWL_ERR(drv, "retry init count %d\n", retry); #ifdef CONFIG_IWLWIFI_DEBUGFS - debugfs_remove_recursive(drv->dbgfs_op_mode); - drv->dbgfs_op_mode = NULL; + debugfs_remove_recursive(drv->dbgfs_op_mode); + drv->dbgfs_op_mode = NULL; #endif + } return NULL; } diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h index 1549ff429549..6a1d31892417 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h @@ -98,6 +98,9 @@ void iwl_drv_stop(struct iwl_drv *drv); #define VISIBLE_IF_IWLWIFI_KUNIT static #endif +/* max retry for init flow */ +#define IWL_MAX_INIT_RETRY 2 + #define FW_NAME_PRE_BUFSIZE 64 struct iwl_trans; const char *iwl_drv_get_fwname_pre(struct iwl_trans *trans, char *buf); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 9f41b9af5269..89b273e02849 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -1398,7 +1398,9 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) iwl_mvm_pause_tcm(mvm, true); + mutex_lock(&mvm->mutex); iwl_fw_runtime_suspend(&mvm->fwrt); + mutex_unlock(&mvm->mutex); return __iwl_mvm_suspend(hw, wowlan, false); } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 08546e673cf5..f30b0fc8eca9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -1307,8 +1307,8 @@ static void iwl_mvm_disconnect_iterator(void *data, u8 *mac, void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags) { u32 error_log_size = mvm->fw->ucode_capa.error_log_size; + u32 status = 0; int ret; - u32 resp; struct iwl_fw_error_recovery_cmd recovery_cmd = { .flags = cpu_to_le32(flags), @@ -1316,7 +1316,6 @@ void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags) }; struct iwl_host_cmd host_cmd = { .id = WIDE_ID(SYSTEM_GROUP, FW_ERROR_RECOVERY_CMD), - .flags = CMD_WANT_SKB, .data = {&recovery_cmd, }, .len = {sizeof(recovery_cmd), }, }; @@ -1336,7 +1335,7 @@ void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags) recovery_cmd.buf_size = cpu_to_le32(error_log_size); } - ret = iwl_mvm_send_cmd(mvm, &host_cmd); + ret = iwl_mvm_send_cmd_status(mvm, &host_cmd, &status); kfree(mvm->error_recovery_buf); mvm->error_recovery_buf = NULL; @@ -1347,11 +1346,10 @@ void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags) /* skb respond is only relevant in ERROR_RECOVERY_UPDATE_DB */ if (flags & ERROR_RECOVERY_UPDATE_DB) { - resp = le32_to_cpu(*(__le32 *)host_cmd.resp_pkt->data); - if (resp) { + if (status) { IWL_ERR(mvm, "Failed to send recovery cmd blob was invalid %d\n", - resp); + status); ieee80211_iterate_interfaces(mvm->hw, 0, iwl_mvm_disconnect_iterator, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 4db7c3ee6bf5..a7d49b5d7993 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -1293,12 +1293,14 @@ int iwl_mvm_mac_start(struct ieee80211_hw *hw) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); int ret; + int retry, max_retry = 0; mutex_lock(&mvm->mutex); /* we are starting the mac not in error flow, and restart is enabled */ if (!test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status) && iwlwifi_mod_params.fw_restart) { + max_retry = IWL_MAX_INIT_RETRY; /* * This will prevent mac80211 recovery flows to trigger during * init failures @@ -1306,7 +1308,13 @@ int iwl_mvm_mac_start(struct ieee80211_hw *hw) set_bit(IWL_MVM_STATUS_STARTING, &mvm->status); } - ret = __iwl_mvm_mac_start(mvm); + for (retry = 0; retry <= max_retry; retry++) { + ret = __iwl_mvm_mac_start(mvm); + if (!ret) + break; + + IWL_ERR(mvm, "mac start retry %d\n", retry); + } clear_bit(IWL_MVM_STATUS_STARTING, &mvm->status); mutex_unlock(&mvm->mutex); @@ -1992,7 +2000,6 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, mvm->p2p_device_vif = NULL; } - iwl_mvm_unset_link_mapping(mvm, vif, &vif->bss_conf); iwl_mvm_mac_ctxt_remove(mvm, vif); RCU_INIT_POINTER(mvm->vif_id_to_mac[mvmvif->id], NULL); @@ -2001,6 +2008,7 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, mvm->monitor_on = false; out: + iwl_mvm_unset_link_mapping(mvm, vif, &vif->bss_conf); if (vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_ADHOC) { iwl_mvm_dealloc_int_sta(mvm, &mvmvif->deflink.mcast_sta); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c index a5c38f389c69..5cacfbf589dc 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c @@ -41,8 +41,6 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw, /* reset deflink MLO parameters */ mvmvif->deflink.fw_link_id = IWL_MVM_FW_LINK_ID_INVALID; mvmvif->deflink.active = 0; - /* the first link always points to the default one */ - mvmvif->link[0] = &mvmvif->deflink; ret = iwl_mvm_mld_mac_ctxt_add(mvm, vif); if (ret) @@ -60,9 +58,19 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw, IEEE80211_VIF_SUPPORTS_CQM_RSSI; } - ret = iwl_mvm_add_link(mvm, vif, &vif->bss_conf); - if (ret) - goto out_free_bf; + /* We want link[0] to point to the default link, unless we have MLO and + * in this case this will be modified later by .change_vif_links() + * If we are in the restart flow with an MLD connection, we will wait + * to .change_vif_links() to setup the links. + */ + if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) || + !ieee80211_vif_is_mld(vif)) { + mvmvif->link[0] = &mvmvif->deflink; + + ret = iwl_mvm_add_link(mvm, vif, &vif->bss_conf); + if (ret) + goto out_free_bf; + } /* Save a pointer to p2p device vif, so it can later be used to * update the p2p device MAC when a GO is started/stopped @@ -1186,7 +1194,11 @@ iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw, mutex_lock(&mvm->mutex); - if (old_links == 0) { + /* If we're in RESTART flow, the default link wasn't added in + * drv_add_interface(), and link[0] doesn't point to it. + */ + if (old_links == 0 && !test_bit(IWL_MVM_STATUS_IN_HW_RESTART, + &mvm->status)) { err = iwl_mvm_disable_link(mvm, vif, &vif->bss_conf); if (err) goto out_err; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index 3ce9150213a7..ddcbd80a49fb 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -1774,7 +1774,7 @@ iwl_mvm_umac_scan_cfg_channels_v7_6g(struct iwl_mvm *mvm, &cp->channel_config[ch_cnt]; u32 s_ssid_bitmap = 0, bssid_bitmap = 0, flags = 0; - u8 j, k, n_s_ssids = 0, n_bssids = 0; + u8 k, n_s_ssids = 0, n_bssids = 0; u8 max_s_ssids, max_bssids; bool force_passive = false, found = false, allow_passive = true, unsolicited_probe_on_chan = false, psc_no_listen = false; @@ -1799,7 +1799,7 @@ iwl_mvm_umac_scan_cfg_channels_v7_6g(struct iwl_mvm *mvm, cfg->v5.iter_count = 1; cfg->v5.iter_interval = 0; - for (j = 0; j < params->n_6ghz_params; j++) { + for (u32 j = 0; j < params->n_6ghz_params; j++) { s8 tmp_psd_20; if (!(scan_6ghz_params[j].channel_idx == i)) @@ -1873,7 +1873,7 @@ iwl_mvm_umac_scan_cfg_channels_v7_6g(struct iwl_mvm *mvm, * SSID. * TODO: improve this logic */ - for (j = 0; j < params->n_6ghz_params; j++) { + for (u32 j = 0; j < params->n_6ghz_params; j++) { if (!(scan_6ghz_params[j].channel_idx == i)) continue; diff --git a/drivers/net/wireless/marvell/libertas/radiotap.h b/drivers/net/wireless/marvell/libertas/radiotap.h index 1ed5608d353f..d543bfe739dc 100644 --- a/drivers/net/wireless/marvell/libertas/radiotap.h +++ b/drivers/net/wireless/marvell/libertas/radiotap.h @@ -2,7 +2,7 @@ #include <net/ieee80211_radiotap.h> struct tx_radiotap_hdr { - struct ieee80211_radiotap_header hdr; + struct ieee80211_radiotap_header_fixed hdr; u8 rate; u8 txpower; u8 rts_retries; @@ -31,7 +31,7 @@ struct tx_radiotap_hdr { #define IEEE80211_FC_DSTODS 0x0300 struct rx_radiotap_hdr { - struct ieee80211_radiotap_header hdr; + struct ieee80211_radiotap_header_fixed hdr; u8 flags; u8 rate; u8 antsignal; diff --git a/drivers/net/wireless/mediatek/mt76/mcu.c b/drivers/net/wireless/mediatek/mt76/mcu.c index 98da82b74094..3353012e8542 100644 --- a/drivers/net/wireless/mediatek/mt76/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mcu.c @@ -84,13 +84,16 @@ int mt76_mcu_skb_send_and_get_msg(struct mt76_dev *dev, struct sk_buff *skb, mutex_lock(&dev->mcu.mutex); if (dev->mcu_ops->mcu_skb_prepare_msg) { + orig_skb = skb; ret = dev->mcu_ops->mcu_skb_prepare_msg(dev, skb, cmd, &seq); if (ret < 0) goto out; } retry: - orig_skb = skb_get(skb); + /* orig skb might be needed for retry, mcu_skb_send_msg consumes it */ + if (orig_skb) + skb_get(orig_skb); ret = dev->mcu_ops->mcu_skb_send_msg(dev, skb, cmd, &seq); if (ret < 0) goto out; @@ -105,7 +108,7 @@ retry: do { skb = mt76_mcu_get_response(dev, expires); if (!skb && !test_bit(MT76_MCU_RESET, &dev->phy.state) && - retry++ < dev->mcu_ops->max_retry) { + orig_skb && retry++ < dev->mcu_ops->max_retry) { dev_err(dev->dev, "Retry message %08x (seq %d)\n", cmd, seq); skb = orig_skb; diff --git a/drivers/net/wireless/microchip/wilc1000/mon.c b/drivers/net/wireless/microchip/wilc1000/mon.c index 03b7229a0ff5..c3d27aaec297 100644 --- a/drivers/net/wireless/microchip/wilc1000/mon.c +++ b/drivers/net/wireless/microchip/wilc1000/mon.c @@ -7,12 +7,12 @@ #include "cfg80211.h" struct wilc_wfi_radiotap_hdr { - struct ieee80211_radiotap_header hdr; + struct ieee80211_radiotap_header_fixed hdr; u8 rate; } __packed; struct wilc_wfi_radiotap_cb_hdr { - struct ieee80211_radiotap_header hdr; + struct ieee80211_radiotap_header_fixed hdr; u8 rate; u8 dump; u16 tx_flags; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192du/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192du/sw.c index d069a81ac617..cc699efa9c79 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192du/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192du/sw.c @@ -352,7 +352,6 @@ static const struct usb_device_id rtl8192d_usb_ids[] = { {RTL_USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x8194, rtl92du_hal_cfg)}, {RTL_USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x8111, rtl92du_hal_cfg)}, {RTL_USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x0193, rtl92du_hal_cfg)}, - {RTL_USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x8171, rtl92du_hal_cfg)}, {RTL_USB_DEVICE(USB_VENDOR_ID_REALTEK, 0xe194, rtl92du_hal_cfg)}, {RTL_USB_DEVICE(0x2019, 0xab2c, rtl92du_hal_cfg)}, {RTL_USB_DEVICE(0x2019, 0xab2d, rtl92du_hal_cfg)}, diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c index ba314d90ab3f..ce43e44c5852 100644 --- a/drivers/net/wireless/realtek/rtw88/usb.c +++ b/drivers/net/wireless/realtek/rtw88/usb.c @@ -772,7 +772,6 @@ static void rtw_usb_dynamic_rx_agg_v1(struct rtw_dev *rtwdev, bool enable) u8 size, timeout; u16 val16; - rtw_write32_set(rtwdev, REG_RXDMA_AGG_PG_TH, BIT_EN_PRE_CALC); rtw_write8_set(rtwdev, REG_TXDMA_PQ_MAP, BIT_RXDMA_AGG_EN); rtw_write8_clr(rtwdev, REG_RXDMA_AGG_PG_TH + 3, BIT(7)); diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c index 989e6e882c6e..b60c8bd4537b 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.c +++ b/drivers/net/wireless/realtek/rtw89/coex.c @@ -6506,6 +6506,8 @@ static void _update_wl_info_v7(struct rtw89_dev *rtwdev, u8 rid) /* todo DBCC related event */ rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC] wl_info phy_now=%d\n", phy_now); + rtw89_debug(rtwdev, RTW89_DBG_BTC, + "[BTC] rlink cnt_2g=%d cnt_5g=%d\n", cnt_2g, cnt_5g); if (wl_rinfo->dbcc_en != rtwdev->dbcc_en) { wl_rinfo->dbcc_chg = 1; diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c index 5ed7eaa18c85..fc17f9ff757c 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.c +++ b/drivers/net/wireless/realtek/rtw89/pci.c @@ -3050,24 +3050,54 @@ static void rtw89_pci_declaim_device(struct rtw89_dev *rtwdev, pci_disable_device(pdev); } -static void rtw89_pci_cfg_dac(struct rtw89_dev *rtwdev) +static bool rtw89_pci_chip_is_manual_dac(struct rtw89_dev *rtwdev) { - struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; const struct rtw89_chip_info *chip = rtwdev->chip; - if (!rtwpci->enable_dac) - return; - switch (chip->chip_id) { case RTL8852A: case RTL8852B: case RTL8851B: case RTL8852BT: - break; + return true; default: - return; + return false; + } +} + +static bool rtw89_pci_is_dac_compatible_bridge(struct rtw89_dev *rtwdev) +{ + struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; + struct pci_dev *bridge = pci_upstream_bridge(rtwpci->pdev); + + if (!rtw89_pci_chip_is_manual_dac(rtwdev)) + return true; + + if (!bridge) + return false; + + switch (bridge->vendor) { + case PCI_VENDOR_ID_INTEL: + return true; + case PCI_VENDOR_ID_ASMEDIA: + if (bridge->device == 0x2806) + return true; + break; } + return false; +} + +static void rtw89_pci_cfg_dac(struct rtw89_dev *rtwdev) +{ + struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; + + if (!rtwpci->enable_dac) + return; + + if (!rtw89_pci_chip_is_manual_dac(rtwdev)) + return; + rtw89_pci_config_byte_set(rtwdev, RTW89_PCIE_L1_CTRL, RTW89_PCIE_BIT_EN_64BITS); } @@ -3085,6 +3115,9 @@ static int rtw89_pci_setup_mapping(struct rtw89_dev *rtwdev, goto err; } + if (!rtw89_pci_is_dac_compatible_bridge(rtwdev)) + goto no_dac; + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(36)); if (!ret) { rtwpci->enable_dac = true; @@ -3097,6 +3130,7 @@ static int rtw89_pci_setup_mapping(struct rtw89_dev *rtwdev, goto err_release_regions; } } +no_dac: resource_len = pci_resource_len(pdev, bar_id); rtwpci->mmap = pci_iomap(pdev, bar_id, resource_len); diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c index 2a36b58f7a15..347a15544afe 100644 --- a/drivers/net/wireless/virtual/mac80211_hwsim.c +++ b/drivers/net/wireless/virtual/mac80211_hwsim.c @@ -763,7 +763,7 @@ static const struct rhashtable_params hwsim_rht_params = { }; struct hwsim_radiotap_hdr { - struct ieee80211_radiotap_header hdr; + struct ieee80211_radiotap_header_fixed hdr; __le64 rt_tsft; u8 rt_flags; u8 rt_rate; @@ -772,7 +772,7 @@ struct hwsim_radiotap_hdr { } __packed; struct hwsim_radiotap_ack_hdr { - struct ieee80211_radiotap_header hdr; + struct ieee80211_radiotap_header_fixed hdr; u8 rt_flags; u8 pad; __le16 rt_channel; diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 4f68414c3086..f1615805f5b0 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -3105,7 +3105,9 @@ int pci_host_probe(struct pci_host_bridge *bridge) list_for_each_entry(child, &bus->children, node) pcie_bus_configure_settings(child); + pci_lock_rescan_remove(); pci_bus_add_devices(bus); + pci_unlock_rescan_remove(); return 0; } EXPORT_SYMBOL_GPL(pci_host_probe); diff --git a/drivers/pci/pwrctl/pci-pwrctl-pwrseq.c b/drivers/pci/pwrctl/pci-pwrctl-pwrseq.c index a23a4312574b..0e6bd47671c2 100644 --- a/drivers/pci/pwrctl/pci-pwrctl-pwrseq.c +++ b/drivers/pci/pwrctl/pci-pwrctl-pwrseq.c @@ -6,9 +6,9 @@ #include <linux/device.h> #include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of.h> #include <linux/pci-pwrctl.h> #include <linux/platform_device.h> +#include <linux/property.h> #include <linux/pwrseq/consumer.h> #include <linux/slab.h> #include <linux/types.h> @@ -18,6 +18,40 @@ struct pci_pwrctl_pwrseq_data { struct pwrseq_desc *pwrseq; }; +struct pci_pwrctl_pwrseq_pdata { + const char *target; + /* + * Called before doing anything else to perform device-specific + * verification between requesting the power sequencing handle. + */ + int (*validate_device)(struct device *dev); +}; + +static int pci_pwrctl_pwrseq_qcm_wcn_validate_device(struct device *dev) +{ + /* + * Old device trees for some platforms already define wifi nodes for + * the WCN family of chips since before power sequencing was added + * upstream. + * + * These nodes don't consume the regulator outputs from the PMU, and + * if we allow this driver to bind to one of such "incomplete" nodes, + * we'll see a kernel log error about the indefinite probe deferral. + * + * Check the existence of the regulator supply that exists on all + * WCN models before moving forward. + */ + if (!device_property_present(dev, "vddaon-supply")) + return -ENODEV; + + return 0; +} + +static const struct pci_pwrctl_pwrseq_pdata pci_pwrctl_pwrseq_qcom_wcn_pdata = { + .target = "wlan", + .validate_device = pci_pwrctl_pwrseq_qcm_wcn_validate_device, +}; + static void devm_pci_pwrctl_pwrseq_power_off(void *data) { struct pwrseq_desc *pwrseq = data; @@ -27,15 +61,26 @@ static void devm_pci_pwrctl_pwrseq_power_off(void *data) static int pci_pwrctl_pwrseq_probe(struct platform_device *pdev) { + const struct pci_pwrctl_pwrseq_pdata *pdata; struct pci_pwrctl_pwrseq_data *data; struct device *dev = &pdev->dev; int ret; + pdata = device_get_match_data(dev); + if (!pdata || !pdata->target) + return -EINVAL; + + if (pdata->validate_device) { + ret = pdata->validate_device(dev); + if (ret) + return ret; + } + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; - data->pwrseq = devm_pwrseq_get(dev, of_device_get_match_data(dev)); + data->pwrseq = devm_pwrseq_get(dev, pdata->target); if (IS_ERR(data->pwrseq)) return dev_err_probe(dev, PTR_ERR(data->pwrseq), "Failed to get the power sequencer\n"); @@ -64,17 +109,17 @@ static const struct of_device_id pci_pwrctl_pwrseq_of_match[] = { { /* ATH11K in QCA6390 package. */ .compatible = "pci17cb,1101", - .data = "wlan", + .data = &pci_pwrctl_pwrseq_qcom_wcn_pdata, }, { /* ATH11K in WCN6855 package. */ .compatible = "pci17cb,1103", - .data = "wlan", + .data = &pci_pwrctl_pwrseq_qcom_wcn_pdata, }, { /* ATH12K in WCN7850 package. */ .compatible = "pci17cb,1107", - .data = "wlan", + .data = &pci_pwrctl_pwrseq_qcom_wcn_pdata, }, { } }; diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 7a48220b4f5a..abdca3f05c5c 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -3908,6 +3908,16 @@ static int platform_profile_setup(struct asus_wmi *asus) if (!asus->throttle_thermal_policy_dev) return 0; + /* + * We need to set the default thermal profile during probe or otherwise + * the system will often remain in silent mode, causing low performance. + */ + err = throttle_thermal_policy_set_default(asus); + if (err < 0) { + pr_warn("Failed to set default thermal profile\n"); + return err; + } + dev_info(dev, "Using throttle_thermal_policy for platform_profile support\n"); asus->platform_profile_handler.profile_get = asus_wmi_platform_profile_get; diff --git a/drivers/platform/x86/dell/dell-wmi-base.c b/drivers/platform/x86/dell/dell-wmi-base.c index 502783a7adb1..24fd7ffadda9 100644 --- a/drivers/platform/x86/dell/dell-wmi-base.c +++ b/drivers/platform/x86/dell/dell-wmi-base.c @@ -264,6 +264,15 @@ static const struct key_entry dell_wmi_keymap_type_0010[] = { /*Speaker Mute*/ { KE_KEY, 0x109, { KEY_MUTE} }, + /* S2Idle screen off */ + { KE_IGNORE, 0x120, { KEY_RESERVED }}, + + /* Leaving S4 or S2Idle suspend */ + { KE_IGNORE, 0x130, { KEY_RESERVED }}, + + /* Entering S2Idle suspend */ + { KE_IGNORE, 0x140, { KEY_RESERVED }}, + /* Mic mute */ { KE_KEY, 0x150, { KEY_MICMUTE } }, diff --git a/drivers/platform/x86/intel/pmc/adl.c b/drivers/platform/x86/intel/pmc/adl.c index 9d9c07f44ff6..e7878558fd90 100644 --- a/drivers/platform/x86/intel/pmc/adl.c +++ b/drivers/platform/x86/intel/pmc/adl.c @@ -295,8 +295,6 @@ const struct pmc_reg_map adl_reg_map = { .ppfear_buckets = CNP_PPFEAR_NUM_ENTRIES, .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, - .acpi_pm_tmr_ctl_offset = SPT_PMC_ACPI_PM_TMR_CTL_OFFSET, - .acpi_pm_tmr_disable_bit = SPT_PMC_BIT_ACPI_PM_TMR_DISABLE, .ltr_ignore_max = ADL_NUM_IP_IGN_ALLOWED, .lpm_num_modes = ADL_LPM_NUM_MODES, .lpm_num_maps = ADL_LPM_NUM_MAPS, diff --git a/drivers/platform/x86/intel/pmc/cnp.c b/drivers/platform/x86/intel/pmc/cnp.c index 513c02670c5a..dd72974bf71e 100644 --- a/drivers/platform/x86/intel/pmc/cnp.c +++ b/drivers/platform/x86/intel/pmc/cnp.c @@ -200,8 +200,6 @@ const struct pmc_reg_map cnp_reg_map = { .ppfear_buckets = CNP_PPFEAR_NUM_ENTRIES, .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, - .acpi_pm_tmr_ctl_offset = SPT_PMC_ACPI_PM_TMR_CTL_OFFSET, - .acpi_pm_tmr_disable_bit = SPT_PMC_BIT_ACPI_PM_TMR_DISABLE, .ltr_ignore_max = CNP_NUM_IP_IGN_ALLOWED, .etr3_offset = ETR3_OFFSET, }; diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c index ecb47f8b4f83..4e9c8c96c8cc 100644 --- a/drivers/platform/x86/intel/pmc/core.c +++ b/drivers/platform/x86/intel/pmc/core.c @@ -11,7 +11,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include <linux/acpi_pmtmr.h> #include <linux/bitfield.h> #include <linux/debugfs.h> #include <linux/delay.h> @@ -1258,39 +1257,6 @@ static bool pmc_core_is_pson_residency_enabled(struct pmc_dev *pmcdev) return val == 1; } -/* - * Enable or disable ACPI PM Timer - * - * This function is intended to be a callback for ACPI PM suspend/resume event. - * The ACPI PM Timer is enabled on resume only if it was enabled during suspend. - */ -static void pmc_core_acpi_pm_timer_suspend_resume(void *data, bool suspend) -{ - struct pmc_dev *pmcdev = data; - struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; - const struct pmc_reg_map *map = pmc->map; - bool enabled; - u32 reg; - - if (!map->acpi_pm_tmr_ctl_offset) - return; - - guard(mutex)(&pmcdev->lock); - - if (!suspend && !pmcdev->enable_acpi_pm_timer_on_resume) - return; - - reg = pmc_core_reg_read(pmc, map->acpi_pm_tmr_ctl_offset); - enabled = !(reg & map->acpi_pm_tmr_disable_bit); - if (suspend) - reg |= map->acpi_pm_tmr_disable_bit; - else - reg &= ~map->acpi_pm_tmr_disable_bit; - pmc_core_reg_write(pmc, map->acpi_pm_tmr_ctl_offset, reg); - - pmcdev->enable_acpi_pm_timer_on_resume = suspend && enabled; -} - static void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev) { debugfs_remove_recursive(pmcdev->dbgfs_dir); @@ -1486,7 +1452,6 @@ static int pmc_core_probe(struct platform_device *pdev) struct pmc_dev *pmcdev; const struct x86_cpu_id *cpu_id; int (*core_init)(struct pmc_dev *pmcdev); - const struct pmc_reg_map *map; struct pmc *primary_pmc; int ret; @@ -1545,11 +1510,6 @@ static int pmc_core_probe(struct platform_device *pdev) pm_report_max_hw_sleep(FIELD_MAX(SLP_S0_RES_COUNTER_MASK) * pmc_core_adjust_slp_s0_step(primary_pmc, 1)); - map = primary_pmc->map; - if (map->acpi_pm_tmr_ctl_offset) - acpi_pmtmr_register_suspend_resume_callback(pmc_core_acpi_pm_timer_suspend_resume, - pmcdev); - device_initialized = true; dev_info(&pdev->dev, " initialized\n"); @@ -1559,12 +1519,6 @@ static int pmc_core_probe(struct platform_device *pdev) static void pmc_core_remove(struct platform_device *pdev) { struct pmc_dev *pmcdev = platform_get_drvdata(pdev); - const struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; - const struct pmc_reg_map *map = pmc->map; - - if (map->acpi_pm_tmr_ctl_offset) - acpi_pmtmr_unregister_suspend_resume_callback(); - pmc_core_dbgfs_unregister(pmcdev); pmc_core_clean_structure(pdev); } diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h index 75fd593a7b0f..b9d3291d0bf2 100644 --- a/drivers/platform/x86/intel/pmc/core.h +++ b/drivers/platform/x86/intel/pmc/core.h @@ -68,8 +68,6 @@ struct telem_endpoint; #define SPT_PMC_LTR_SCC 0x3A0 #define SPT_PMC_LTR_ISH 0x3A4 -#define SPT_PMC_ACPI_PM_TMR_CTL_OFFSET 0x18FC - /* Sunrise Point: PGD PFET Enable Ack Status Registers */ enum ppfear_regs { SPT_PMC_XRAM_PPFEAR0A = 0x590, @@ -150,8 +148,6 @@ enum ppfear_regs { #define SPT_PMC_VRIC1_SLPS0LVEN BIT(13) #define SPT_PMC_VRIC1_XTALSDQDIS BIT(22) -#define SPT_PMC_BIT_ACPI_PM_TMR_DISABLE BIT(1) - /* Cannonlake Power Management Controller register offsets */ #define CNP_PMC_SLPS0_DBG_OFFSET 0x10B4 #define CNP_PMC_PM_CFG_OFFSET 0x1818 @@ -355,8 +351,6 @@ struct pmc_reg_map { const u8 *lpm_reg_index; const u32 pson_residency_offset; const u32 pson_residency_counter_step; - const u32 acpi_pm_tmr_ctl_offset; - const u32 acpi_pm_tmr_disable_bit; }; /** @@ -432,8 +426,6 @@ struct pmc_dev { u32 die_c6_offset; struct telem_endpoint *punit_ep; struct pmc_info *regmap_list; - - bool enable_acpi_pm_timer_on_resume; }; enum pmc_index { diff --git a/drivers/platform/x86/intel/pmc/core_ssram.c b/drivers/platform/x86/intel/pmc/core_ssram.c index c259c96b7dfd..8504154b649f 100644 --- a/drivers/platform/x86/intel/pmc/core_ssram.c +++ b/drivers/platform/x86/intel/pmc/core_ssram.c @@ -29,7 +29,7 @@ #define LPM_REG_COUNT 28 #define LPM_MODE_OFFSET 1 -DEFINE_FREE(pmc_core_iounmap, void __iomem *, iounmap(_T)); +DEFINE_FREE(pmc_core_iounmap, void __iomem *, if (_T) iounmap(_T)) static u32 pmc_core_find_guid(struct pmc_info *list, const struct pmc_reg_map *map) { @@ -262,6 +262,8 @@ pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, int pmc_idx, u32 offset) ssram_base = ssram_pcidev->resource[0].start; tmp_ssram = ioremap(ssram_base, SSRAM_HDR_SIZE); + if (!tmp_ssram) + return -ENOMEM; if (pmc_idx != PMC_IDX_MAIN) { /* diff --git a/drivers/platform/x86/intel/pmc/icl.c b/drivers/platform/x86/intel/pmc/icl.c index cbbd44054468..71b0fd6cb7d8 100644 --- a/drivers/platform/x86/intel/pmc/icl.c +++ b/drivers/platform/x86/intel/pmc/icl.c @@ -46,8 +46,6 @@ const struct pmc_reg_map icl_reg_map = { .ppfear_buckets = ICL_PPFEAR_NUM_ENTRIES, .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, - .acpi_pm_tmr_ctl_offset = SPT_PMC_ACPI_PM_TMR_CTL_OFFSET, - .acpi_pm_tmr_disable_bit = SPT_PMC_BIT_ACPI_PM_TMR_DISABLE, .ltr_ignore_max = ICL_NUM_IP_IGN_ALLOWED, .etr3_offset = ETR3_OFFSET, }; diff --git a/drivers/platform/x86/intel/pmc/mtl.c b/drivers/platform/x86/intel/pmc/mtl.c index 91f2fa728f5c..c7d15d864039 100644 --- a/drivers/platform/x86/intel/pmc/mtl.c +++ b/drivers/platform/x86/intel/pmc/mtl.c @@ -462,8 +462,6 @@ const struct pmc_reg_map mtl_socm_reg_map = { .ppfear_buckets = MTL_SOCM_PPFEAR_NUM_ENTRIES, .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, - .acpi_pm_tmr_ctl_offset = SPT_PMC_ACPI_PM_TMR_CTL_OFFSET, - .acpi_pm_tmr_disable_bit = SPT_PMC_BIT_ACPI_PM_TMR_DISABLE, .lpm_num_maps = ADL_LPM_NUM_MAPS, .ltr_ignore_max = MTL_SOCM_NUM_IP_IGN_ALLOWED, .lpm_res_counter_step_x2 = TGL_PMC_LPM_RES_COUNTER_STEP_X2, diff --git a/drivers/platform/x86/intel/pmc/tgl.c b/drivers/platform/x86/intel/pmc/tgl.c index 371b4e30f142..e0580de18077 100644 --- a/drivers/platform/x86/intel/pmc/tgl.c +++ b/drivers/platform/x86/intel/pmc/tgl.c @@ -197,8 +197,6 @@ const struct pmc_reg_map tgl_reg_map = { .ppfear_buckets = ICL_PPFEAR_NUM_ENTRIES, .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, - .acpi_pm_tmr_ctl_offset = SPT_PMC_ACPI_PM_TMR_CTL_OFFSET, - .acpi_pm_tmr_disable_bit = SPT_PMC_BIT_ACPI_PM_TMR_DISABLE, .ltr_ignore_max = TGL_NUM_IP_IGN_ALLOWED, .lpm_num_maps = TGL_LPM_NUM_MAPS, .lpm_res_counter_step_x2 = TGL_PMC_LPM_RES_COUNTER_STEP_X2, diff --git a/drivers/powercap/dtpm_devfreq.c b/drivers/powercap/dtpm_devfreq.c index f40bce8176df..d1dff6ccab12 100644 --- a/drivers/powercap/dtpm_devfreq.c +++ b/drivers/powercap/dtpm_devfreq.c @@ -178,7 +178,7 @@ static int __dtpm_devfreq_setup(struct devfreq *devfreq, struct dtpm *parent) ret = dev_pm_qos_add_request(dev, &dtpm_devfreq->qos_req, DEV_PM_QOS_MAX_FREQUENCY, PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE); - if (ret) { + if (ret < 0) { pr_err("Failed to add QoS request: %d\n", ret); goto out_dtpm_unregister; } diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index de15fc0df104..b52513eeeafa 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -3651,7 +3651,7 @@ static int do_device_access(struct sdeb_store_info *sip, struct scsi_cmnd *scp, enum dma_data_direction dir; struct scsi_data_buffer *sdb = &scp->sdb; u8 *fsp; - int i; + int i, total = 0; /* * Even though reads are inherently atomic (in this driver), we expect @@ -3688,18 +3688,16 @@ static int do_device_access(struct sdeb_store_info *sip, struct scsi_cmnd *scp, fsp + (block * sdebug_sector_size), sdebug_sector_size, sg_skip, do_write); sdeb_data_sector_unlock(sip, do_write); - if (ret != sdebug_sector_size) { - ret += (i * sdebug_sector_size); + total += ret; + if (ret != sdebug_sector_size) break; - } sg_skip += sdebug_sector_size; if (++block >= sdebug_store_sectors) block = 0; } - ret = num * sdebug_sector_size; sdeb_data_unlock(sip, atomic); - return ret; + return total; } /* Returns number of bytes copied or -1 if error. */ diff --git a/drivers/soundwire/intel_ace2x.c b/drivers/soundwire/intel_ace2x.c index fff312c6968d..4f3dd70d6a1a 100644 --- a/drivers/soundwire/intel_ace2x.c +++ b/drivers/soundwire/intel_ace2x.c @@ -376,11 +376,12 @@ static int intel_hw_params(struct snd_pcm_substream *substream, static int intel_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai); struct sdw_intel *sdw = cdns_to_intel(cdns); struct sdw_cdns_dai_runtime *dai_runtime; + struct snd_pcm_hw_params *hw_params; int ch, dir; - int ret = 0; dai_runtime = cdns->dai_runtime_array[dai->id]; if (!dai_runtime) { @@ -389,12 +390,8 @@ static int intel_prepare(struct snd_pcm_substream *substream, return -EIO; } + hw_params = &rtd->dpcm[substream->stream].hw_params; if (dai_runtime->suspended) { - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_pcm_hw_params *hw_params; - - hw_params = &rtd->dpcm[substream->stream].hw_params; - dai_runtime->suspended = false; /* @@ -415,15 +412,11 @@ static int intel_prepare(struct snd_pcm_substream *substream, /* the SHIM will be configured in the callback functions */ sdw_cdns_config_stream(cdns, ch, dir, dai_runtime->pdi); - - /* Inform DSP about PDI stream number */ - ret = intel_params_stream(sdw, substream, dai, - hw_params, - sdw->instance, - dai_runtime->pdi->intel_alh_id); } - return ret; + /* Inform DSP about PDI stream number */ + return intel_params_stream(sdw, substream, dai, hw_params, sdw->instance, + dai_runtime->pdi->intel_alh_id); } static int diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 191de1917f83..3fa990fb59c7 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -1003,6 +1003,7 @@ static int dspi_setup(struct spi_device *spi) u32 cs_sck_delay = 0, sck_cs_delay = 0; struct fsl_dspi_platform_data *pdata; unsigned char pasc = 0, asc = 0; + struct gpio_desc *gpio_cs; struct chip_data *chip; unsigned long clkrate; bool cs = true; @@ -1077,7 +1078,10 @@ static int dspi_setup(struct spi_device *spi) chip->ctar_val |= SPI_CTAR_LSBFE; } - gpiod_direction_output(spi_get_csgpiod(spi, 0), false); + gpio_cs = spi_get_csgpiod(spi, 0); + if (gpio_cs) + gpiod_direction_output(gpio_cs, false); + dspi_deassert_cs(spi, &cs); spi_set_ctldata(spi, chip); diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c index f6e40f90418f..768d7482102a 100644 --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -1116,6 +1116,11 @@ static int spi_geni_probe(struct platform_device *pdev) init_completion(&mas->tx_reset_done); init_completion(&mas->rx_reset_done); spin_lock_init(&mas->lock); + + ret = geni_icc_get(&mas->se, NULL); + if (ret) + return ret; + pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, 250); ret = devm_pm_runtime_enable(dev); @@ -1125,9 +1130,6 @@ static int spi_geni_probe(struct platform_device *pdev) if (device_property_read_bool(&pdev->dev, "spi-slave")) spi->target = true; - ret = geni_icc_get(&mas->se, NULL); - if (ret) - return ret; /* Set the bus quota to a reasonable value for register access */ mas->se.icc_paths[GENI_TO_CORE].avg_bw = Bps_to_icc(CORE_2X_50_MHZ); mas->se.icc_paths[CPU_TO_GENI].avg_bw = GENI_DEFAULT_BW; diff --git a/drivers/spi/spi-mtk-snfi.c b/drivers/spi/spi-mtk-snfi.c index ddd98ddb7913..c5677fd94e5e 100644 --- a/drivers/spi/spi-mtk-snfi.c +++ b/drivers/spi/spi-mtk-snfi.c @@ -1187,7 +1187,7 @@ cleanup: /** * mtk_snand_is_page_ops() - check if the op is a controller supported page op. - * @op spi-mem op to check + * @op: spi-mem op to check * * Check whether op can be executed with read_from_cache or program_load * mode in the controller. diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c index 4c4ff074e3f6..fc72a89fb3a7 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -2044,6 +2044,7 @@ static const struct stm32_spi_cfg stm32mp25_spi_cfg = { .baud_rate_div_max = STM32H7_SPI_MBR_DIV_MAX, .has_fifo = true, .prevent_dma_burst = true, + .has_device_mode = true, }; static const struct of_device_id stm32_spi_of_match[] = { diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index a63dcf48e59d..f5846598d80e 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -8219,7 +8219,7 @@ static void ufshcd_update_rtc(struct ufs_hba *hba) err = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR, QUERY_ATTR_IDN_SECONDS_PASSED, 0, 0, &val); - ufshcd_rpm_put_sync(hba); + ufshcd_rpm_put(hba); if (err) dev_err(hba->dev, "%s: Failed to update rtc %d\n", __func__, err); diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig index ea36c6956bf3..de035071fedb 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -1236,7 +1236,6 @@ config FB_3DFX_I2C config FB_VOODOO1 tristate "3Dfx Voodoo Graphics (sst1) support" depends on FB && PCI - depends on FB_DEVICE select FB_IOMEM_HELPERS help Say Y here if you have a 3Dfx Voodoo Graphics (Voodoo1/sst1) or @@ -1374,6 +1373,7 @@ config FB_VT8500 config FB_WM8505 bool "Wondermedia WM8xxx-series frame buffer support" depends on (FB = y) && HAS_IOMEM && (ARCH_VT8500 || COMPILE_TEST) + select FB_IOMEM_FOPS select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS) select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS) select FB_SYS_IMAGEBLIT @@ -1660,19 +1660,6 @@ config FB_SH7760 and 8, 15 or 16 bpp color; 90 degrees clockwise display rotation for panels <= 320 pixel horizontal resolution. -config FB_DA8XX - tristate "DA8xx/OMAP-L1xx/AM335x Framebuffer support" - depends on FB && HAVE_CLK && HAS_IOMEM - depends on ARCH_DAVINCI_DA8XX || SOC_AM33XX || COMPILE_TEST - select FB_CFB_REV_PIXELS_IN_BYTE - select FB_IOMEM_HELPERS - select FB_MODE_HELPERS - select VIDEOMODE_HELPERS - help - This is the frame buffer device driver for the TI LCD controller - found on DA8xx/OMAP-L1xx/AM335x SoCs. - If unsure, say N. - config FB_VIRTUAL tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)" depends on FB diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile index 3eecd51267fa..b3d12f977c06 100644 --- a/drivers/video/fbdev/Makefile +++ b/drivers/video/fbdev/Makefile @@ -121,7 +121,6 @@ obj-$(CONFIG_FB_VESA) += vesafb.o obj-$(CONFIG_FB_EFI) += efifb.o obj-$(CONFIG_FB_VGA16) += vga16fb.o obj-$(CONFIG_FB_OF) += offb.o -obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o obj-$(CONFIG_FB_SSD1307) += ssd1307fb.o obj-$(CONFIG_FB_SIMPLE) += simplefb.o diff --git a/drivers/video/fbdev/bw2.c b/drivers/video/fbdev/bw2.c index 4a64940e0c00..e757462af0a6 100644 --- a/drivers/video/fbdev/bw2.c +++ b/drivers/video/fbdev/bw2.c @@ -147,7 +147,7 @@ bw2_blank(int blank, struct fb_info *info) return 0; } -static struct sbus_mmap_map bw2_mmap_map[] = { +static const struct sbus_mmap_map bw2_mmap_map[] = { { .size = SBUS_MMAP_FBSIZE(1) }, diff --git a/drivers/video/fbdev/cg14.c b/drivers/video/fbdev/cg14.c index 430e1a7b352b..5389f8f07346 100644 --- a/drivers/video/fbdev/cg14.c +++ b/drivers/video/fbdev/cg14.c @@ -360,7 +360,7 @@ static void cg14_init_fix(struct fb_info *info, int linebytes, info->fix.accel = FB_ACCEL_SUN_CG14; } -static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] = { +static const struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] = { { .voff = CG14_REGS, .poff = 0x80000000, diff --git a/drivers/video/fbdev/cg3.c b/drivers/video/fbdev/cg3.c index e4c53c6632ba..a58a483014e6 100644 --- a/drivers/video/fbdev/cg3.c +++ b/drivers/video/fbdev/cg3.c @@ -209,7 +209,7 @@ static int cg3_blank(int blank, struct fb_info *info) return 0; } -static struct sbus_mmap_map cg3_mmap_map[] = { +static const struct sbus_mmap_map cg3_mmap_map[] = { { .voff = CG3_MMAP_OFFSET, .poff = CG3_RAM_OFFSET, diff --git a/drivers/video/fbdev/cg6.c b/drivers/video/fbdev/cg6.c index 0b60df51e7bc..56d74468040a 100644 --- a/drivers/video/fbdev/cg6.c +++ b/drivers/video/fbdev/cg6.c @@ -545,7 +545,7 @@ static int cg6_blank(int blank, struct fb_info *info) return 0; } -static struct sbus_mmap_map cg6_mmap_map[] = { +static const struct sbus_mmap_map cg6_mmap_map[] = { { .voff = CG6_FBC, .poff = CG6_FBC_OFFSET, diff --git a/drivers/video/fbdev/da8xx-fb.c b/drivers/video/fbdev/da8xx-fb.c deleted file mode 100644 index fad1e13c6332..000000000000 --- a/drivers/video/fbdev/da8xx-fb.c +++ /dev/null @@ -1,1665 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (C) 2008-2009 MontaVista Software Inc. - * Copyright (C) 2008-2009 Texas Instruments Inc - * - * Based on the LCD driver for TI Avalanche processors written by - * Ajay Singh and Shalom Hai. - */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/fb.h> -#include <linux/dma-mapping.h> -#include <linux/device.h> -#include <linux/platform_device.h> -#include <linux/uaccess.h> -#include <linux/pm_runtime.h> -#include <linux/interrupt.h> -#include <linux/wait.h> -#include <linux/clk.h> -#include <linux/cpufreq.h> -#include <linux/console.h> -#include <linux/regulator/consumer.h> -#include <linux/spinlock.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/lcm.h> -#include <video/da8xx-fb.h> -#include <asm/div64.h> - -#define DRIVER_NAME "da8xx_lcdc" - -#define LCD_VERSION_1 1 -#define LCD_VERSION_2 2 - -/* LCD Status Register */ -#define LCD_END_OF_FRAME1 BIT(9) -#define LCD_END_OF_FRAME0 BIT(8) -#define LCD_PL_LOAD_DONE BIT(6) -#define LCD_FIFO_UNDERFLOW BIT(5) -#define LCD_SYNC_LOST BIT(2) -#define LCD_FRAME_DONE BIT(0) - -/* LCD DMA Control Register */ -#define LCD_DMA_BURST_SIZE(x) ((x) << 4) -#define LCD_DMA_BURST_1 0x0 -#define LCD_DMA_BURST_2 0x1 -#define LCD_DMA_BURST_4 0x2 -#define LCD_DMA_BURST_8 0x3 -#define LCD_DMA_BURST_16 0x4 -#define LCD_V1_END_OF_FRAME_INT_ENA BIT(2) -#define LCD_V2_END_OF_FRAME0_INT_ENA BIT(8) -#define LCD_V2_END_OF_FRAME1_INT_ENA BIT(9) -#define LCD_DUAL_FRAME_BUFFER_ENABLE BIT(0) - -/* LCD Control Register */ -#define LCD_CLK_DIVISOR(x) ((x) << 8) -#define LCD_RASTER_MODE 0x01 - -/* LCD Raster Control Register */ -#define LCD_PALETTE_LOAD_MODE(x) ((x) << 20) -#define PALETTE_AND_DATA 0x00 -#define PALETTE_ONLY 0x01 -#define DATA_ONLY 0x02 - -#define LCD_MONO_8BIT_MODE BIT(9) -#define LCD_RASTER_ORDER BIT(8) -#define LCD_TFT_MODE BIT(7) -#define LCD_V1_UNDERFLOW_INT_ENA BIT(6) -#define LCD_V2_UNDERFLOW_INT_ENA BIT(5) -#define LCD_V1_PL_INT_ENA BIT(4) -#define LCD_V2_PL_INT_ENA BIT(6) -#define LCD_MONOCHROME_MODE BIT(1) -#define LCD_RASTER_ENABLE BIT(0) -#define LCD_TFT_ALT_ENABLE BIT(23) -#define LCD_STN_565_ENABLE BIT(24) -#define LCD_V2_DMA_CLK_EN BIT(2) -#define LCD_V2_LIDD_CLK_EN BIT(1) -#define LCD_V2_CORE_CLK_EN BIT(0) -#define LCD_V2_LPP_B10 26 -#define LCD_V2_TFT_24BPP_MODE BIT(25) -#define LCD_V2_TFT_24BPP_UNPACK BIT(26) - -/* LCD Raster Timing 2 Register */ -#define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16) -#define LCD_AC_BIAS_FREQUENCY(x) ((x) << 8) -#define LCD_SYNC_CTRL BIT(25) -#define LCD_SYNC_EDGE BIT(24) -#define LCD_INVERT_PIXEL_CLOCK BIT(22) -#define LCD_INVERT_LINE_CLOCK BIT(21) -#define LCD_INVERT_FRAME_CLOCK BIT(20) - -/* LCD Block */ -#define LCD_PID_REG 0x0 -#define LCD_CTRL_REG 0x4 -#define LCD_STAT_REG 0x8 -#define LCD_RASTER_CTRL_REG 0x28 -#define LCD_RASTER_TIMING_0_REG 0x2C -#define LCD_RASTER_TIMING_1_REG 0x30 -#define LCD_RASTER_TIMING_2_REG 0x34 -#define LCD_DMA_CTRL_REG 0x40 -#define LCD_DMA_FRM_BUF_BASE_ADDR_0_REG 0x44 -#define LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG 0x48 -#define LCD_DMA_FRM_BUF_BASE_ADDR_1_REG 0x4C -#define LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG 0x50 - -/* Interrupt Registers available only in Version 2 */ -#define LCD_RAW_STAT_REG 0x58 -#define LCD_MASKED_STAT_REG 0x5c -#define LCD_INT_ENABLE_SET_REG 0x60 -#define LCD_INT_ENABLE_CLR_REG 0x64 -#define LCD_END_OF_INT_IND_REG 0x68 - -/* Clock registers available only on Version 2 */ -#define LCD_CLK_ENABLE_REG 0x6c -#define LCD_CLK_RESET_REG 0x70 -#define LCD_CLK_MAIN_RESET BIT(3) - -#define LCD_NUM_BUFFERS 2 - -#define PALETTE_SIZE 256 - -#define CLK_MIN_DIV 2 -#define CLK_MAX_DIV 255 - -static void __iomem *da8xx_fb_reg_base; -static unsigned int lcd_revision; -static irq_handler_t lcdc_irq_handler; -static wait_queue_head_t frame_done_wq; -static int frame_done_flag; - -static unsigned int lcdc_read(unsigned int addr) -{ - return (unsigned int)__raw_readl(da8xx_fb_reg_base + (addr)); -} - -static void lcdc_write(unsigned int val, unsigned int addr) -{ - __raw_writel(val, da8xx_fb_reg_base + (addr)); -} - -struct da8xx_fb_par { - struct device *dev; - dma_addr_t p_palette_base; - unsigned char *v_palette_base; - dma_addr_t vram_phys; - unsigned long vram_size; - void *vram_virt; - unsigned int dma_start; - unsigned int dma_end; - struct clk *lcdc_clk; - int irq; - unsigned int palette_sz; - int blank; - wait_queue_head_t vsync_wait; - int vsync_flag; - int vsync_timeout; - spinlock_t lock_for_chan_update; - - /* - * LCDC has 2 ping pong DMA channels, channel 0 - * and channel 1. - */ - unsigned int which_dma_channel_done; -#ifdef CONFIG_CPU_FREQ - struct notifier_block freq_transition; -#endif - unsigned int lcdc_clk_rate; - struct regulator *lcd_supply; - u32 pseudo_palette[16]; - struct fb_videomode mode; - struct lcd_ctrl_config cfg; -}; - -static struct fb_var_screeninfo da8xx_fb_var; - -static struct fb_fix_screeninfo da8xx_fb_fix = { - .id = "DA8xx FB Drv", - .type = FB_TYPE_PACKED_PIXELS, - .type_aux = 0, - .visual = FB_VISUAL_PSEUDOCOLOR, - .xpanstep = 0, - .ypanstep = 1, - .ywrapstep = 0, - .accel = FB_ACCEL_NONE -}; - -static struct fb_videomode known_lcd_panels[] = { - /* Sharp LCD035Q3DG01 */ - [0] = { - .name = "Sharp_LCD035Q3DG01", - .xres = 320, - .yres = 240, - .pixclock = KHZ2PICOS(4607), - .left_margin = 6, - .right_margin = 8, - .upper_margin = 2, - .lower_margin = 2, - .hsync_len = 0, - .vsync_len = 0, - .sync = FB_SYNC_CLK_INVERT, - }, - /* Sharp LK043T1DG01 */ - [1] = { - .name = "Sharp_LK043T1DG01", - .xres = 480, - .yres = 272, - .pixclock = KHZ2PICOS(7833), - .left_margin = 2, - .right_margin = 2, - .upper_margin = 2, - .lower_margin = 2, - .hsync_len = 41, - .vsync_len = 10, - .sync = 0, - .flag = 0, - }, - [2] = { - /* Hitachi SP10Q010 */ - .name = "SP10Q010", - .xres = 320, - .yres = 240, - .pixclock = KHZ2PICOS(7833), - .left_margin = 10, - .right_margin = 10, - .upper_margin = 10, - .lower_margin = 10, - .hsync_len = 10, - .vsync_len = 10, - .sync = 0, - .flag = 0, - }, - [3] = { - /* Densitron 84-0023-001T */ - .name = "Densitron_84-0023-001T", - .xres = 320, - .yres = 240, - .pixclock = KHZ2PICOS(6400), - .left_margin = 0, - .right_margin = 0, - .upper_margin = 0, - .lower_margin = 0, - .hsync_len = 30, - .vsync_len = 3, - .sync = 0, - }, -}; - -static bool da8xx_fb_is_raster_enabled(void) -{ - return !!(lcdc_read(LCD_RASTER_CTRL_REG) & LCD_RASTER_ENABLE); -} - -/* Enable the Raster Engine of the LCD Controller */ -static void lcd_enable_raster(void) -{ - u32 reg; - - /* Put LCDC in reset for several cycles */ - if (lcd_revision == LCD_VERSION_2) - /* Write 1 to reset LCDC */ - lcdc_write(LCD_CLK_MAIN_RESET, LCD_CLK_RESET_REG); - mdelay(1); - - /* Bring LCDC out of reset */ - if (lcd_revision == LCD_VERSION_2) - lcdc_write(0, LCD_CLK_RESET_REG); - mdelay(1); - - /* Above reset sequence doesnot reset register context */ - reg = lcdc_read(LCD_RASTER_CTRL_REG); - if (!(reg & LCD_RASTER_ENABLE)) - lcdc_write(reg | LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG); -} - -/* Disable the Raster Engine of the LCD Controller */ -static void lcd_disable_raster(enum da8xx_frame_complete wait_for_frame_done) -{ - u32 reg; - int ret; - - reg = lcdc_read(LCD_RASTER_CTRL_REG); - if (reg & LCD_RASTER_ENABLE) - lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG); - else - /* return if already disabled */ - return; - - if ((wait_for_frame_done == DA8XX_FRAME_WAIT) && - (lcd_revision == LCD_VERSION_2)) { - frame_done_flag = 0; - ret = wait_event_interruptible_timeout(frame_done_wq, - frame_done_flag != 0, - msecs_to_jiffies(50)); - if (ret == 0) - pr_err("LCD Controller timed out\n"); - } -} - -static void lcd_blit(int load_mode, struct da8xx_fb_par *par) -{ - u32 start; - u32 end; - u32 reg_ras; - u32 reg_dma; - u32 reg_int; - - /* init reg to clear PLM (loading mode) fields */ - reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); - reg_ras &= ~(3 << 20); - - reg_dma = lcdc_read(LCD_DMA_CTRL_REG); - - if (load_mode == LOAD_DATA) { - start = par->dma_start; - end = par->dma_end; - - reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY); - if (lcd_revision == LCD_VERSION_1) { - reg_dma |= LCD_V1_END_OF_FRAME_INT_ENA; - } else { - reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | - LCD_V2_END_OF_FRAME0_INT_ENA | - LCD_V2_END_OF_FRAME1_INT_ENA | - LCD_FRAME_DONE | LCD_SYNC_LOST; - lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); - } - reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE; - - lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); - lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); - lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); - lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); - } else if (load_mode == LOAD_PALETTE) { - start = par->p_palette_base; - end = start + par->palette_sz - 1; - - reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY); - - if (lcd_revision == LCD_VERSION_1) { - reg_ras |= LCD_V1_PL_INT_ENA; - } else { - reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | - LCD_V2_PL_INT_ENA; - lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); - } - - lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); - lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); - } - - lcdc_write(reg_dma, LCD_DMA_CTRL_REG); - lcdc_write(reg_ras, LCD_RASTER_CTRL_REG); - - /* - * The Raster enable bit must be set after all other control fields are - * set. - */ - lcd_enable_raster(); -} - -/* Configure the Burst Size and fifo threhold of DMA */ -static int lcd_cfg_dma(int burst_size, int fifo_th) -{ - u32 reg; - - reg = lcdc_read(LCD_DMA_CTRL_REG) & 0x00000001; - switch (burst_size) { - case 1: - reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_1); - break; - case 2: - reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_2); - break; - case 4: - reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_4); - break; - case 8: - reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_8); - break; - case 16: - default: - reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16); - break; - } - - reg |= (fifo_th << 8); - - lcdc_write(reg, LCD_DMA_CTRL_REG); - - return 0; -} - -static void lcd_cfg_ac_bias(int period, int transitions_per_int) -{ - u32 reg; - - /* Set the AC Bias Period and Number of Transisitons per Interrupt */ - reg = lcdc_read(LCD_RASTER_TIMING_2_REG) & 0xFFF00000; - reg |= LCD_AC_BIAS_FREQUENCY(period) | - LCD_AC_BIAS_TRANSITIONS_PER_INT(transitions_per_int); - lcdc_write(reg, LCD_RASTER_TIMING_2_REG); -} - -static void lcd_cfg_horizontal_sync(int back_porch, int pulse_width, - int front_porch) -{ - u32 reg; - - reg = lcdc_read(LCD_RASTER_TIMING_0_REG) & 0x3ff; - reg |= (((back_porch-1) & 0xff) << 24) - | (((front_porch-1) & 0xff) << 16) - | (((pulse_width-1) & 0x3f) << 10); - lcdc_write(reg, LCD_RASTER_TIMING_0_REG); - - /* - * LCDC Version 2 adds some extra bits that increase the allowable - * size of the horizontal timing registers. - * remember that the registers use 0 to represent 1 so all values - * that get set into register need to be decremented by 1 - */ - if (lcd_revision == LCD_VERSION_2) { - /* Mask off the bits we want to change */ - reg = lcdc_read(LCD_RASTER_TIMING_2_REG) & ~0x780000ff; - reg |= ((front_porch-1) & 0x300) >> 8; - reg |= ((back_porch-1) & 0x300) >> 4; - reg |= ((pulse_width-1) & 0x3c0) << 21; - lcdc_write(reg, LCD_RASTER_TIMING_2_REG); - } -} - -static void lcd_cfg_vertical_sync(int back_porch, int pulse_width, - int front_porch) -{ - u32 reg; - - reg = lcdc_read(LCD_RASTER_TIMING_1_REG) & 0x3ff; - reg |= ((back_porch & 0xff) << 24) - | ((front_porch & 0xff) << 16) - | (((pulse_width-1) & 0x3f) << 10); - lcdc_write(reg, LCD_RASTER_TIMING_1_REG); -} - -static int lcd_cfg_display(const struct lcd_ctrl_config *cfg, - struct fb_videomode *panel) -{ - u32 reg; - u32 reg_int; - - reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(LCD_TFT_MODE | - LCD_MONO_8BIT_MODE | - LCD_MONOCHROME_MODE); - - switch (cfg->panel_shade) { - case MONOCHROME: - reg |= LCD_MONOCHROME_MODE; - if (cfg->mono_8bit_mode) - reg |= LCD_MONO_8BIT_MODE; - break; - case COLOR_ACTIVE: - reg |= LCD_TFT_MODE; - if (cfg->tft_alt_mode) - reg |= LCD_TFT_ALT_ENABLE; - break; - - case COLOR_PASSIVE: - /* AC bias applicable only for Pasive panels */ - lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt); - if (cfg->bpp == 12 && cfg->stn_565_mode) - reg |= LCD_STN_565_ENABLE; - break; - - default: - return -EINVAL; - } - - /* enable additional interrupts here */ - if (lcd_revision == LCD_VERSION_1) { - reg |= LCD_V1_UNDERFLOW_INT_ENA; - } else { - reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | - LCD_V2_UNDERFLOW_INT_ENA; - lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); - } - - lcdc_write(reg, LCD_RASTER_CTRL_REG); - - reg = lcdc_read(LCD_RASTER_TIMING_2_REG); - - reg |= LCD_SYNC_CTRL; - - if (cfg->sync_edge) - reg |= LCD_SYNC_EDGE; - else - reg &= ~LCD_SYNC_EDGE; - - if ((panel->sync & FB_SYNC_HOR_HIGH_ACT) == 0) - reg |= LCD_INVERT_LINE_CLOCK; - else - reg &= ~LCD_INVERT_LINE_CLOCK; - - if ((panel->sync & FB_SYNC_VERT_HIGH_ACT) == 0) - reg |= LCD_INVERT_FRAME_CLOCK; - else - reg &= ~LCD_INVERT_FRAME_CLOCK; - - lcdc_write(reg, LCD_RASTER_TIMING_2_REG); - - return 0; -} - -static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height, - u32 bpp, u32 raster_order) -{ - u32 reg; - - if (bpp > 16 && lcd_revision == LCD_VERSION_1) - return -EINVAL; - - /* Set the Panel Width */ - /* Pixels per line = (PPL + 1)*16 */ - if (lcd_revision == LCD_VERSION_1) { - /* - * 0x3F in bits 4..9 gives max horizontal resolution = 1024 - * pixels. - */ - width &= 0x3f0; - } else { - /* - * 0x7F in bits 4..10 gives max horizontal resolution = 2048 - * pixels. - */ - width &= 0x7f0; - } - - reg = lcdc_read(LCD_RASTER_TIMING_0_REG); - reg &= 0xfffffc00; - if (lcd_revision == LCD_VERSION_1) { - reg |= ((width >> 4) - 1) << 4; - } else { - width = (width >> 4) - 1; - reg |= ((width & 0x3f) << 4) | ((width & 0x40) >> 3); - } - lcdc_write(reg, LCD_RASTER_TIMING_0_REG); - - /* Set the Panel Height */ - /* Set bits 9:0 of Lines Per Pixel */ - reg = lcdc_read(LCD_RASTER_TIMING_1_REG); - reg = ((height - 1) & 0x3ff) | (reg & 0xfffffc00); - lcdc_write(reg, LCD_RASTER_TIMING_1_REG); - - /* Set bit 10 of Lines Per Pixel */ - if (lcd_revision == LCD_VERSION_2) { - reg = lcdc_read(LCD_RASTER_TIMING_2_REG); - reg |= ((height - 1) & 0x400) << 16; - lcdc_write(reg, LCD_RASTER_TIMING_2_REG); - } - - /* Set the Raster Order of the Frame Buffer */ - reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8); - if (raster_order) - reg |= LCD_RASTER_ORDER; - - par->palette_sz = 16 * 2; - - switch (bpp) { - case 1: - case 2: - case 4: - case 16: - break; - case 24: - reg |= LCD_V2_TFT_24BPP_MODE; - break; - case 32: - reg |= LCD_V2_TFT_24BPP_MODE; - reg |= LCD_V2_TFT_24BPP_UNPACK; - break; - case 8: - par->palette_sz = 256 * 2; - break; - - default: - return -EINVAL; - } - - lcdc_write(reg, LCD_RASTER_CTRL_REG); - - return 0; -} - -#define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF - (val)) >> 16) -static int fb_setcolreg(unsigned regno, unsigned red, unsigned green, - unsigned blue, unsigned transp, - struct fb_info *info) -{ - struct da8xx_fb_par *par = info->par; - unsigned short *palette = (unsigned short *) par->v_palette_base; - u_short pal; - int update_hw = 0; - - if (regno > 255) - return 1; - - if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) - return 1; - - if (info->var.bits_per_pixel > 16 && lcd_revision == LCD_VERSION_1) - return -EINVAL; - - switch (info->fix.visual) { - case FB_VISUAL_TRUECOLOR: - red = CNVT_TOHW(red, info->var.red.length); - green = CNVT_TOHW(green, info->var.green.length); - blue = CNVT_TOHW(blue, info->var.blue.length); - break; - case FB_VISUAL_PSEUDOCOLOR: - switch (info->var.bits_per_pixel) { - case 4: - if (regno > 15) - return -EINVAL; - - if (info->var.grayscale) { - pal = regno; - } else { - red >>= 4; - green >>= 8; - blue >>= 12; - - pal = red & 0x0f00; - pal |= green & 0x00f0; - pal |= blue & 0x000f; - } - if (regno == 0) - pal |= 0x2000; - palette[regno] = pal; - break; - - case 8: - red >>= 4; - green >>= 8; - blue >>= 12; - - pal = (red & 0x0f00); - pal |= (green & 0x00f0); - pal |= (blue & 0x000f); - - if (palette[regno] != pal) { - update_hw = 1; - palette[regno] = pal; - } - break; - } - break; - } - - /* Truecolor has hardware independent palette */ - if (info->fix.visual == FB_VISUAL_TRUECOLOR) { - u32 v; - - if (regno > 15) - return -EINVAL; - - v = (red << info->var.red.offset) | - (green << info->var.green.offset) | - (blue << info->var.blue.offset); - - ((u32 *) (info->pseudo_palette))[regno] = v; - if (palette[0] != 0x4000) { - update_hw = 1; - palette[0] = 0x4000; - } - } - - /* Update the palette in the h/w as needed. */ - if (update_hw) - lcd_blit(LOAD_PALETTE, par); - - return 0; -} -#undef CNVT_TOHW - -static void da8xx_fb_lcd_reset(void) -{ - /* DMA has to be disabled */ - lcdc_write(0, LCD_DMA_CTRL_REG); - lcdc_write(0, LCD_RASTER_CTRL_REG); - - if (lcd_revision == LCD_VERSION_2) { - lcdc_write(0, LCD_INT_ENABLE_SET_REG); - /* Write 1 to reset */ - lcdc_write(LCD_CLK_MAIN_RESET, LCD_CLK_RESET_REG); - lcdc_write(0, LCD_CLK_RESET_REG); - } -} - -static int da8xx_fb_config_clk_divider(struct da8xx_fb_par *par, - unsigned lcdc_clk_div, - unsigned lcdc_clk_rate) -{ - int ret; - - if (par->lcdc_clk_rate != lcdc_clk_rate) { - ret = clk_set_rate(par->lcdc_clk, lcdc_clk_rate); - if (ret) { - dev_err(par->dev, - "unable to set clock rate at %u\n", - lcdc_clk_rate); - return ret; - } - par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk); - } - - /* Configure the LCD clock divisor. */ - lcdc_write(LCD_CLK_DIVISOR(lcdc_clk_div) | - (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG); - - if (lcd_revision == LCD_VERSION_2) - lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN | - LCD_V2_CORE_CLK_EN, LCD_CLK_ENABLE_REG); - - return 0; -} - -static unsigned int da8xx_fb_calc_clk_divider(struct da8xx_fb_par *par, - unsigned pixclock, - unsigned *lcdc_clk_rate) -{ - unsigned lcdc_clk_div; - - pixclock = PICOS2KHZ(pixclock) * 1000; - - *lcdc_clk_rate = par->lcdc_clk_rate; - - if (pixclock < (*lcdc_clk_rate / CLK_MAX_DIV)) { - *lcdc_clk_rate = clk_round_rate(par->lcdc_clk, - pixclock * CLK_MAX_DIV); - lcdc_clk_div = CLK_MAX_DIV; - } else if (pixclock > (*lcdc_clk_rate / CLK_MIN_DIV)) { - *lcdc_clk_rate = clk_round_rate(par->lcdc_clk, - pixclock * CLK_MIN_DIV); - lcdc_clk_div = CLK_MIN_DIV; - } else { - lcdc_clk_div = *lcdc_clk_rate / pixclock; - } - - return lcdc_clk_div; -} - -static int da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par, - struct fb_videomode *mode) -{ - unsigned lcdc_clk_rate; - unsigned lcdc_clk_div = da8xx_fb_calc_clk_divider(par, mode->pixclock, - &lcdc_clk_rate); - - return da8xx_fb_config_clk_divider(par, lcdc_clk_div, lcdc_clk_rate); -} - -static unsigned da8xx_fb_round_clk(struct da8xx_fb_par *par, - unsigned pixclock) -{ - unsigned lcdc_clk_div, lcdc_clk_rate; - - lcdc_clk_div = da8xx_fb_calc_clk_divider(par, pixclock, &lcdc_clk_rate); - return KHZ2PICOS(lcdc_clk_rate / (1000 * lcdc_clk_div)); -} - -static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, - struct fb_videomode *panel) -{ - u32 bpp; - int ret = 0; - - ret = da8xx_fb_calc_config_clk_divider(par, panel); - if (ret) { - dev_err(par->dev, "unable to configure clock\n"); - return ret; - } - - if (panel->sync & FB_SYNC_CLK_INVERT) - lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) | - LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG); - else - lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) & - ~LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG); - - /* Configure the DMA burst size and fifo threshold. */ - ret = lcd_cfg_dma(cfg->dma_burst_sz, cfg->fifo_th); - if (ret < 0) - return ret; - - /* Configure the vertical and horizontal sync properties. */ - lcd_cfg_vertical_sync(panel->upper_margin, panel->vsync_len, - panel->lower_margin); - lcd_cfg_horizontal_sync(panel->left_margin, panel->hsync_len, - panel->right_margin); - - /* Configure for disply */ - ret = lcd_cfg_display(cfg, panel); - if (ret < 0) - return ret; - - bpp = cfg->bpp; - - if (bpp == 12) - bpp = 16; - ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->xres, - (unsigned int)panel->yres, bpp, - cfg->raster_order); - if (ret < 0) - return ret; - - /* Configure FDD */ - lcdc_write((lcdc_read(LCD_RASTER_CTRL_REG) & 0xfff00fff) | - (cfg->fdd << 12), LCD_RASTER_CTRL_REG); - - return 0; -} - -/* IRQ handler for version 2 of LCDC */ -static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg) -{ - struct da8xx_fb_par *par = arg; - u32 stat = lcdc_read(LCD_MASKED_STAT_REG); - - if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { - lcd_disable_raster(DA8XX_FRAME_NOWAIT); - lcdc_write(stat, LCD_MASKED_STAT_REG); - lcd_enable_raster(); - } else if (stat & LCD_PL_LOAD_DONE) { - /* - * Must disable raster before changing state of any control bit. - * And also must be disabled before clearing the PL loading - * interrupt via the following write to the status register. If - * this is done after then one gets multiple PL done interrupts. - */ - lcd_disable_raster(DA8XX_FRAME_NOWAIT); - - lcdc_write(stat, LCD_MASKED_STAT_REG); - - /* Disable PL completion interrupt */ - lcdc_write(LCD_V2_PL_INT_ENA, LCD_INT_ENABLE_CLR_REG); - - /* Setup and start data loading mode */ - lcd_blit(LOAD_DATA, par); - } else { - lcdc_write(stat, LCD_MASKED_STAT_REG); - - if (stat & LCD_END_OF_FRAME0) { - par->which_dma_channel_done = 0; - lcdc_write(par->dma_start, - LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); - lcdc_write(par->dma_end, - LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); - par->vsync_flag = 1; - wake_up_interruptible(&par->vsync_wait); - } - - if (stat & LCD_END_OF_FRAME1) { - par->which_dma_channel_done = 1; - lcdc_write(par->dma_start, - LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); - lcdc_write(par->dma_end, - LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); - par->vsync_flag = 1; - wake_up_interruptible(&par->vsync_wait); - } - - /* Set only when controller is disabled and at the end of - * active frame - */ - if (stat & BIT(0)) { - frame_done_flag = 1; - wake_up_interruptible(&frame_done_wq); - } - } - - lcdc_write(0, LCD_END_OF_INT_IND_REG); - return IRQ_HANDLED; -} - -/* IRQ handler for version 1 LCDC */ -static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg) -{ - struct da8xx_fb_par *par = arg; - u32 stat = lcdc_read(LCD_STAT_REG); - u32 reg_ras; - - if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { - lcd_disable_raster(DA8XX_FRAME_NOWAIT); - lcdc_write(stat, LCD_STAT_REG); - lcd_enable_raster(); - } else if (stat & LCD_PL_LOAD_DONE) { - /* - * Must disable raster before changing state of any control bit. - * And also must be disabled before clearing the PL loading - * interrupt via the following write to the status register. If - * this is done after then one gets multiple PL done interrupts. - */ - lcd_disable_raster(DA8XX_FRAME_NOWAIT); - - lcdc_write(stat, LCD_STAT_REG); - - /* Disable PL completion inerrupt */ - reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); - reg_ras &= ~LCD_V1_PL_INT_ENA; - lcdc_write(reg_ras, LCD_RASTER_CTRL_REG); - - /* Setup and start data loading mode */ - lcd_blit(LOAD_DATA, par); - } else { - lcdc_write(stat, LCD_STAT_REG); - - if (stat & LCD_END_OF_FRAME0) { - par->which_dma_channel_done = 0; - lcdc_write(par->dma_start, - LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); - lcdc_write(par->dma_end, - LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); - par->vsync_flag = 1; - wake_up_interruptible(&par->vsync_wait); - } - - if (stat & LCD_END_OF_FRAME1) { - par->which_dma_channel_done = 1; - lcdc_write(par->dma_start, - LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); - lcdc_write(par->dma_end, - LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); - par->vsync_flag = 1; - wake_up_interruptible(&par->vsync_wait); - } - } - - return IRQ_HANDLED; -} - -static int fb_check_var(struct fb_var_screeninfo *var, - struct fb_info *info) -{ - int err = 0; - struct da8xx_fb_par *par = info->par; - int bpp = var->bits_per_pixel >> 3; - unsigned long line_size = var->xres_virtual * bpp; - - if (var->bits_per_pixel > 16 && lcd_revision == LCD_VERSION_1) - return -EINVAL; - - switch (var->bits_per_pixel) { - case 1: - case 8: - var->red.offset = 0; - var->red.length = 8; - var->green.offset = 0; - var->green.length = 8; - var->blue.offset = 0; - var->blue.length = 8; - var->transp.offset = 0; - var->transp.length = 0; - var->nonstd = 0; - break; - case 4: - var->red.offset = 0; - var->red.length = 4; - var->green.offset = 0; - var->green.length = 4; - var->blue.offset = 0; - var->blue.length = 4; - var->transp.offset = 0; - var->transp.length = 0; - var->nonstd = FB_NONSTD_REV_PIX_IN_B; - break; - case 16: /* RGB 565 */ - var->red.offset = 11; - var->red.length = 5; - var->green.offset = 5; - var->green.length = 6; - var->blue.offset = 0; - var->blue.length = 5; - var->transp.offset = 0; - var->transp.length = 0; - var->nonstd = 0; - break; - case 24: - var->red.offset = 16; - var->red.length = 8; - var->green.offset = 8; - var->green.length = 8; - var->blue.offset = 0; - var->blue.length = 8; - var->nonstd = 0; - break; - case 32: - var->transp.offset = 24; - var->transp.length = 8; - var->red.offset = 16; - var->red.length = 8; - var->green.offset = 8; - var->green.length = 8; - var->blue.offset = 0; - var->blue.length = 8; - var->nonstd = 0; - break; - default: - err = -EINVAL; - } - - var->red.msb_right = 0; - var->green.msb_right = 0; - var->blue.msb_right = 0; - var->transp.msb_right = 0; - - if (line_size * var->yres_virtual > par->vram_size) - var->yres_virtual = par->vram_size / line_size; - - if (var->yres > var->yres_virtual) - var->yres = var->yres_virtual; - - if (var->xres > var->xres_virtual) - var->xres = var->xres_virtual; - - if (var->xres + var->xoffset > var->xres_virtual) - var->xoffset = var->xres_virtual - var->xres; - if (var->yres + var->yoffset > var->yres_virtual) - var->yoffset = var->yres_virtual - var->yres; - - var->pixclock = da8xx_fb_round_clk(par, var->pixclock); - - return err; -} - -#ifdef CONFIG_CPU_FREQ -static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb, - unsigned long val, void *data) -{ - struct da8xx_fb_par *par; - - par = container_of(nb, struct da8xx_fb_par, freq_transition); - if (val == CPUFREQ_POSTCHANGE) { - if (par->lcdc_clk_rate != clk_get_rate(par->lcdc_clk)) { - par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk); - lcd_disable_raster(DA8XX_FRAME_WAIT); - da8xx_fb_calc_config_clk_divider(par, &par->mode); - if (par->blank == FB_BLANK_UNBLANK) - lcd_enable_raster(); - } - } - - return 0; -} - -static int lcd_da8xx_cpufreq_register(struct da8xx_fb_par *par) -{ - par->freq_transition.notifier_call = lcd_da8xx_cpufreq_transition; - - return cpufreq_register_notifier(&par->freq_transition, - CPUFREQ_TRANSITION_NOTIFIER); -} - -static void lcd_da8xx_cpufreq_deregister(struct da8xx_fb_par *par) -{ - cpufreq_unregister_notifier(&par->freq_transition, - CPUFREQ_TRANSITION_NOTIFIER); -} -#endif - -static void fb_remove(struct platform_device *dev) -{ - struct fb_info *info = platform_get_drvdata(dev); - struct da8xx_fb_par *par = info->par; - int ret; - -#ifdef CONFIG_CPU_FREQ - lcd_da8xx_cpufreq_deregister(par); -#endif - if (par->lcd_supply) { - ret = regulator_disable(par->lcd_supply); - if (ret) - dev_warn(&dev->dev, "Failed to disable regulator (%pe)\n", - ERR_PTR(ret)); - } - - lcd_disable_raster(DA8XX_FRAME_WAIT); - lcdc_write(0, LCD_RASTER_CTRL_REG); - - /* disable DMA */ - lcdc_write(0, LCD_DMA_CTRL_REG); - - unregister_framebuffer(info); - fb_dealloc_cmap(&info->cmap); - pm_runtime_put_sync(&dev->dev); - pm_runtime_disable(&dev->dev); - framebuffer_release(info); -} - -/* - * Function to wait for vertical sync which for this LCD peripheral - * translates into waiting for the current raster frame to complete. - */ -static int fb_wait_for_vsync(struct fb_info *info) -{ - struct da8xx_fb_par *par = info->par; - int ret; - - /* - * Set flag to 0 and wait for isr to set to 1. It would seem there is a - * race condition here where the ISR could have occurred just before or - * just after this set. But since we are just coarsely waiting for - * a frame to complete then that's OK. i.e. if the frame completed - * just before this code executed then we have to wait another full - * frame time but there is no way to avoid such a situation. On the - * other hand if the frame completed just after then we don't need - * to wait long at all. Either way we are guaranteed to return to the - * user immediately after a frame completion which is all that is - * required. - */ - par->vsync_flag = 0; - ret = wait_event_interruptible_timeout(par->vsync_wait, - par->vsync_flag != 0, - par->vsync_timeout); - if (ret < 0) - return ret; - if (ret == 0) - return -ETIMEDOUT; - - return 0; -} - -static int fb_ioctl(struct fb_info *info, unsigned int cmd, - unsigned long arg) -{ - struct lcd_sync_arg sync_arg; - - switch (cmd) { - case FBIOGET_CONTRAST: - case FBIOPUT_CONTRAST: - case FBIGET_BRIGHTNESS: - case FBIPUT_BRIGHTNESS: - case FBIGET_COLOR: - case FBIPUT_COLOR: - return -ENOTTY; - case FBIPUT_HSYNC: - if (copy_from_user(&sync_arg, (char *)arg, - sizeof(struct lcd_sync_arg))) - return -EFAULT; - lcd_cfg_horizontal_sync(sync_arg.back_porch, - sync_arg.pulse_width, - sync_arg.front_porch); - break; - case FBIPUT_VSYNC: - if (copy_from_user(&sync_arg, (char *)arg, - sizeof(struct lcd_sync_arg))) - return -EFAULT; - lcd_cfg_vertical_sync(sync_arg.back_porch, - sync_arg.pulse_width, - sync_arg.front_porch); - break; - case FBIO_WAITFORVSYNC: - return fb_wait_for_vsync(info); - default: - return -EINVAL; - } - return 0; -} - -static int cfb_blank(int blank, struct fb_info *info) -{ - struct da8xx_fb_par *par = info->par; - int ret = 0; - - if (par->blank == blank) - return 0; - - par->blank = blank; - switch (blank) { - case FB_BLANK_UNBLANK: - lcd_enable_raster(); - - if (par->lcd_supply) { - ret = regulator_enable(par->lcd_supply); - if (ret) - return ret; - } - break; - case FB_BLANK_NORMAL: - case FB_BLANK_VSYNC_SUSPEND: - case FB_BLANK_HSYNC_SUSPEND: - case FB_BLANK_POWERDOWN: - if (par->lcd_supply) { - ret = regulator_disable(par->lcd_supply); - if (ret) - return ret; - } - - lcd_disable_raster(DA8XX_FRAME_WAIT); - break; - default: - ret = -EINVAL; - } - - return ret; -} - -/* - * Set new x,y offsets in the virtual display for the visible area and switch - * to the new mode. - */ -static int da8xx_pan_display(struct fb_var_screeninfo *var, - struct fb_info *fbi) -{ - int ret = 0; - struct fb_var_screeninfo new_var; - struct da8xx_fb_par *par = fbi->par; - struct fb_fix_screeninfo *fix = &fbi->fix; - unsigned int end; - unsigned int start; - unsigned long irq_flags; - - if (var->xoffset != fbi->var.xoffset || - var->yoffset != fbi->var.yoffset) { - memcpy(&new_var, &fbi->var, sizeof(new_var)); - new_var.xoffset = var->xoffset; - new_var.yoffset = var->yoffset; - if (fb_check_var(&new_var, fbi)) - ret = -EINVAL; - else { - memcpy(&fbi->var, &new_var, sizeof(new_var)); - - start = fix->smem_start + - new_var.yoffset * fix->line_length + - new_var.xoffset * fbi->var.bits_per_pixel / 8; - end = start + fbi->var.yres * fix->line_length - 1; - par->dma_start = start; - par->dma_end = end; - spin_lock_irqsave(&par->lock_for_chan_update, - irq_flags); - if (par->which_dma_channel_done == 0) { - lcdc_write(par->dma_start, - LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); - lcdc_write(par->dma_end, - LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); - } else if (par->which_dma_channel_done == 1) { - lcdc_write(par->dma_start, - LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); - lcdc_write(par->dma_end, - LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); - } - spin_unlock_irqrestore(&par->lock_for_chan_update, - irq_flags); - } - } - - return ret; -} - -static int da8xxfb_set_par(struct fb_info *info) -{ - struct da8xx_fb_par *par = info->par; - int ret; - bool raster = da8xx_fb_is_raster_enabled(); - - if (raster) - lcd_disable_raster(DA8XX_FRAME_WAIT); - - fb_var_to_videomode(&par->mode, &info->var); - - par->cfg.bpp = info->var.bits_per_pixel; - - info->fix.visual = (par->cfg.bpp <= 8) ? - FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; - info->fix.line_length = (par->mode.xres * par->cfg.bpp) / 8; - - ret = lcd_init(par, &par->cfg, &par->mode); - if (ret < 0) { - dev_err(par->dev, "lcd init failed\n"); - return ret; - } - - par->dma_start = info->fix.smem_start + - info->var.yoffset * info->fix.line_length + - info->var.xoffset * info->var.bits_per_pixel / 8; - par->dma_end = par->dma_start + - info->var.yres * info->fix.line_length - 1; - - lcdc_write(par->dma_start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); - lcdc_write(par->dma_end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); - lcdc_write(par->dma_start, LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); - lcdc_write(par->dma_end, LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); - - if (raster) - lcd_enable_raster(); - - return 0; -} - -static const struct fb_ops da8xx_fb_ops = { - .owner = THIS_MODULE, - FB_DEFAULT_IOMEM_OPS, - .fb_check_var = fb_check_var, - .fb_set_par = da8xxfb_set_par, - .fb_setcolreg = fb_setcolreg, - .fb_pan_display = da8xx_pan_display, - .fb_ioctl = fb_ioctl, - .fb_blank = cfb_blank, -}; - -static struct fb_videomode *da8xx_fb_get_videomode(struct platform_device *dev) -{ - struct da8xx_lcdc_platform_data *fb_pdata = dev_get_platdata(&dev->dev); - struct fb_videomode *lcdc_info; - int i; - - for (i = 0, lcdc_info = known_lcd_panels; - i < ARRAY_SIZE(known_lcd_panels); i++, lcdc_info++) { - if (strcmp(fb_pdata->type, lcdc_info->name) == 0) - break; - } - - if (i == ARRAY_SIZE(known_lcd_panels)) { - dev_err(&dev->dev, "no panel found\n"); - return NULL; - } - dev_info(&dev->dev, "found %s panel\n", lcdc_info->name); - - return lcdc_info; -} - -static int fb_probe(struct platform_device *device) -{ - struct da8xx_lcdc_platform_data *fb_pdata = - dev_get_platdata(&device->dev); - struct lcd_ctrl_config *lcd_cfg; - struct fb_videomode *lcdc_info; - struct fb_info *da8xx_fb_info; - struct da8xx_fb_par *par; - struct clk *tmp_lcdc_clk; - int ret; - unsigned long ulcm; - - if (fb_pdata == NULL) { - dev_err(&device->dev, "Can not get platform data\n"); - return -ENOENT; - } - - lcdc_info = da8xx_fb_get_videomode(device); - if (lcdc_info == NULL) - return -ENODEV; - - da8xx_fb_reg_base = devm_platform_ioremap_resource(device, 0); - if (IS_ERR(da8xx_fb_reg_base)) - return PTR_ERR(da8xx_fb_reg_base); - - tmp_lcdc_clk = devm_clk_get(&device->dev, "fck"); - if (IS_ERR(tmp_lcdc_clk)) - return dev_err_probe(&device->dev, PTR_ERR(tmp_lcdc_clk), - "Can not get device clock\n"); - - pm_runtime_enable(&device->dev); - pm_runtime_get_sync(&device->dev); - - /* Determine LCD IP Version */ - switch (lcdc_read(LCD_PID_REG)) { - case 0x4C100102: - lcd_revision = LCD_VERSION_1; - break; - case 0x4F200800: - case 0x4F201000: - lcd_revision = LCD_VERSION_2; - break; - default: - dev_warn(&device->dev, "Unknown PID Reg value 0x%x, " - "defaulting to LCD revision 1\n", - lcdc_read(LCD_PID_REG)); - lcd_revision = LCD_VERSION_1; - break; - } - - lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data; - - if (!lcd_cfg) { - ret = -EINVAL; - goto err_pm_runtime_disable; - } - - da8xx_fb_info = framebuffer_alloc(sizeof(struct da8xx_fb_par), - &device->dev); - if (!da8xx_fb_info) { - ret = -ENOMEM; - goto err_pm_runtime_disable; - } - - par = da8xx_fb_info->par; - par->dev = &device->dev; - par->lcdc_clk = tmp_lcdc_clk; - par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk); - - par->lcd_supply = devm_regulator_get_optional(&device->dev, "lcd"); - if (IS_ERR(par->lcd_supply)) { - if (PTR_ERR(par->lcd_supply) == -EPROBE_DEFER) { - ret = -EPROBE_DEFER; - goto err_release_fb; - } - - par->lcd_supply = NULL; - } else { - ret = regulator_enable(par->lcd_supply); - if (ret) - goto err_release_fb; - } - - fb_videomode_to_var(&da8xx_fb_var, lcdc_info); - par->cfg = *lcd_cfg; - - da8xx_fb_lcd_reset(); - - /* allocate frame buffer */ - par->vram_size = lcdc_info->xres * lcdc_info->yres * lcd_cfg->bpp; - ulcm = lcm((lcdc_info->xres * lcd_cfg->bpp)/8, PAGE_SIZE); - par->vram_size = roundup(par->vram_size/8, ulcm); - par->vram_size = par->vram_size * LCD_NUM_BUFFERS; - - par->vram_virt = dmam_alloc_coherent(par->dev, - par->vram_size, - &par->vram_phys, - GFP_KERNEL | GFP_DMA); - if (!par->vram_virt) { - dev_err(&device->dev, - "GLCD: kmalloc for frame buffer failed\n"); - ret = -EINVAL; - goto err_disable_reg; - } - - da8xx_fb_info->screen_base = (char __iomem *) par->vram_virt; - da8xx_fb_fix.smem_start = par->vram_phys; - da8xx_fb_fix.smem_len = par->vram_size; - da8xx_fb_fix.line_length = (lcdc_info->xres * lcd_cfg->bpp) / 8; - - par->dma_start = par->vram_phys; - par->dma_end = par->dma_start + lcdc_info->yres * - da8xx_fb_fix.line_length - 1; - - /* allocate palette buffer */ - par->v_palette_base = dmam_alloc_coherent(par->dev, PALETTE_SIZE, - &par->p_palette_base, - GFP_KERNEL | GFP_DMA); - if (!par->v_palette_base) { - dev_err(&device->dev, - "GLCD: kmalloc for palette buffer failed\n"); - ret = -EINVAL; - goto err_release_fb; - } - - par->irq = platform_get_irq(device, 0); - if (par->irq < 0) { - ret = -ENOENT; - goto err_release_fb; - } - - da8xx_fb_var.grayscale = - lcd_cfg->panel_shade == MONOCHROME ? 1 : 0; - da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp; - - /* Initialize fbinfo */ - da8xx_fb_info->fix = da8xx_fb_fix; - da8xx_fb_info->var = da8xx_fb_var; - da8xx_fb_info->fbops = &da8xx_fb_ops; - da8xx_fb_info->pseudo_palette = par->pseudo_palette; - da8xx_fb_info->fix.visual = (da8xx_fb_info->var.bits_per_pixel <= 8) ? - FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; - - ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0); - if (ret) - goto err_disable_reg; - da8xx_fb_info->cmap.len = par->palette_sz; - - /* initialize var_screeninfo */ - da8xx_fb_var.activate = FB_ACTIVATE_FORCE; - fb_set_var(da8xx_fb_info, &da8xx_fb_var); - - platform_set_drvdata(device, da8xx_fb_info); - - /* initialize the vsync wait queue */ - init_waitqueue_head(&par->vsync_wait); - par->vsync_timeout = HZ / 5; - par->which_dma_channel_done = -1; - spin_lock_init(&par->lock_for_chan_update); - - /* Register the Frame Buffer */ - if (register_framebuffer(da8xx_fb_info) < 0) { - dev_err(&device->dev, - "GLCD: Frame Buffer Registration Failed!\n"); - ret = -EINVAL; - goto err_dealloc_cmap; - } - -#ifdef CONFIG_CPU_FREQ - ret = lcd_da8xx_cpufreq_register(par); - if (ret) { - dev_err(&device->dev, "failed to register cpufreq\n"); - goto err_cpu_freq; - } -#endif - - if (lcd_revision == LCD_VERSION_1) - lcdc_irq_handler = lcdc_irq_handler_rev01; - else { - init_waitqueue_head(&frame_done_wq); - lcdc_irq_handler = lcdc_irq_handler_rev02; - } - - ret = devm_request_irq(&device->dev, par->irq, lcdc_irq_handler, 0, - DRIVER_NAME, par); - if (ret) - goto irq_freq; - return 0; - -irq_freq: -#ifdef CONFIG_CPU_FREQ - lcd_da8xx_cpufreq_deregister(par); -err_cpu_freq: -#endif - unregister_framebuffer(da8xx_fb_info); - -err_dealloc_cmap: - fb_dealloc_cmap(&da8xx_fb_info->cmap); - -err_disable_reg: - if (par->lcd_supply) - regulator_disable(par->lcd_supply); -err_release_fb: - framebuffer_release(da8xx_fb_info); - -err_pm_runtime_disable: - pm_runtime_put_sync(&device->dev); - pm_runtime_disable(&device->dev); - - return ret; -} - -#ifdef CONFIG_PM_SLEEP -static struct lcdc_context { - u32 clk_enable; - u32 ctrl; - u32 dma_ctrl; - u32 raster_timing_0; - u32 raster_timing_1; - u32 raster_timing_2; - u32 int_enable_set; - u32 dma_frm_buf_base_addr_0; - u32 dma_frm_buf_ceiling_addr_0; - u32 dma_frm_buf_base_addr_1; - u32 dma_frm_buf_ceiling_addr_1; - u32 raster_ctrl; -} reg_context; - -static void lcd_context_save(void) -{ - if (lcd_revision == LCD_VERSION_2) { - reg_context.clk_enable = lcdc_read(LCD_CLK_ENABLE_REG); - reg_context.int_enable_set = lcdc_read(LCD_INT_ENABLE_SET_REG); - } - - reg_context.ctrl = lcdc_read(LCD_CTRL_REG); - reg_context.dma_ctrl = lcdc_read(LCD_DMA_CTRL_REG); - reg_context.raster_timing_0 = lcdc_read(LCD_RASTER_TIMING_0_REG); - reg_context.raster_timing_1 = lcdc_read(LCD_RASTER_TIMING_1_REG); - reg_context.raster_timing_2 = lcdc_read(LCD_RASTER_TIMING_2_REG); - reg_context.dma_frm_buf_base_addr_0 = - lcdc_read(LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); - reg_context.dma_frm_buf_ceiling_addr_0 = - lcdc_read(LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); - reg_context.dma_frm_buf_base_addr_1 = - lcdc_read(LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); - reg_context.dma_frm_buf_ceiling_addr_1 = - lcdc_read(LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); - reg_context.raster_ctrl = lcdc_read(LCD_RASTER_CTRL_REG); - return; -} - -static void lcd_context_restore(void) -{ - if (lcd_revision == LCD_VERSION_2) { - lcdc_write(reg_context.clk_enable, LCD_CLK_ENABLE_REG); - lcdc_write(reg_context.int_enable_set, LCD_INT_ENABLE_SET_REG); - } - - lcdc_write(reg_context.ctrl, LCD_CTRL_REG); - lcdc_write(reg_context.dma_ctrl, LCD_DMA_CTRL_REG); - lcdc_write(reg_context.raster_timing_0, LCD_RASTER_TIMING_0_REG); - lcdc_write(reg_context.raster_timing_1, LCD_RASTER_TIMING_1_REG); - lcdc_write(reg_context.raster_timing_2, LCD_RASTER_TIMING_2_REG); - lcdc_write(reg_context.dma_frm_buf_base_addr_0, - LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); - lcdc_write(reg_context.dma_frm_buf_ceiling_addr_0, - LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); - lcdc_write(reg_context.dma_frm_buf_base_addr_1, - LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); - lcdc_write(reg_context.dma_frm_buf_ceiling_addr_1, - LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); - lcdc_write(reg_context.raster_ctrl, LCD_RASTER_CTRL_REG); - return; -} - -static int fb_suspend(struct device *dev) -{ - struct fb_info *info = dev_get_drvdata(dev); - struct da8xx_fb_par *par = info->par; - int ret; - - console_lock(); - if (par->lcd_supply) { - ret = regulator_disable(par->lcd_supply); - if (ret) - return ret; - } - - fb_set_suspend(info, 1); - lcd_disable_raster(DA8XX_FRAME_WAIT); - lcd_context_save(); - pm_runtime_put_sync(dev); - console_unlock(); - - return 0; -} -static int fb_resume(struct device *dev) -{ - struct fb_info *info = dev_get_drvdata(dev); - struct da8xx_fb_par *par = info->par; - int ret; - - console_lock(); - pm_runtime_get_sync(dev); - lcd_context_restore(); - if (par->blank == FB_BLANK_UNBLANK) { - lcd_enable_raster(); - - if (par->lcd_supply) { - ret = regulator_enable(par->lcd_supply); - if (ret) - return ret; - } - } - - fb_set_suspend(info, 0); - console_unlock(); - - return 0; -} -#endif - -static SIMPLE_DEV_PM_OPS(fb_pm_ops, fb_suspend, fb_resume); - -static struct platform_driver da8xx_fb_driver = { - .probe = fb_probe, - .remove = fb_remove, - .driver = { - .name = DRIVER_NAME, - .pm = &fb_pm_ops, - }, -}; -module_platform_driver(da8xx_fb_driver); - -MODULE_DESCRIPTION("Framebuffer driver for TI da8xx/omap-l1xx"); -MODULE_AUTHOR("Texas Instruments"); -MODULE_LICENSE("GPL"); diff --git a/drivers/video/fbdev/ffb.c b/drivers/video/fbdev/ffb.c index 0b7e7b38c05a..34b6abff9493 100644 --- a/drivers/video/fbdev/ffb.c +++ b/drivers/video/fbdev/ffb.c @@ -710,7 +710,7 @@ static int ffb_blank(int blank, struct fb_info *info) return 0; } -static struct sbus_mmap_map ffb_mmap_map[] = { +static const struct sbus_mmap_map ffb_mmap_map[] = { { .voff = FFB_SFB8R_VOFF, .poff = FFB_SFB8R_POFF, diff --git a/drivers/video/fbdev/leo.c b/drivers/video/fbdev/leo.c index 271e2e8c6a84..b9fb059df2c7 100644 --- a/drivers/video/fbdev/leo.c +++ b/drivers/video/fbdev/leo.c @@ -338,7 +338,7 @@ static int leo_blank(int blank, struct fb_info *info) return 0; } -static struct sbus_mmap_map leo_mmap_map[] = { +static const struct sbus_mmap_map leo_mmap_map[] = { { .voff = LEO_SS0_MAP, .poff = LEO_OFF_SS0, diff --git a/drivers/video/fbdev/nvidia/nv_hw.c b/drivers/video/fbdev/nvidia/nv_hw.c index 9b0a324bb1b4..75afaa07e7eb 100644 --- a/drivers/video/fbdev/nvidia/nv_hw.c +++ b/drivers/video/fbdev/nvidia/nv_hw.c @@ -1509,10 +1509,10 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) NV_WR32(par->PFIFO, 0x0495 * 4, 0x00000001); NV_WR32(par->PFIFO, 0x0140 * 4, 0x00000001); - if (!state) { - par->CurrentState = NULL; - return; - } + if (!state) { + par->CurrentState = NULL; + return; + } if (par->Architecture >= NV_ARCH_10) { if (par->twoHeads) { diff --git a/drivers/video/fbdev/p9100.c b/drivers/video/fbdev/p9100.c index 124468f0e9ef..0bc0f78fe4b9 100644 --- a/drivers/video/fbdev/p9100.c +++ b/drivers/video/fbdev/p9100.c @@ -206,7 +206,7 @@ p9100_blank(int blank, struct fb_info *info) return 0; } -static struct sbus_mmap_map p9100_mmap_map[] = { +static const struct sbus_mmap_map p9100_mmap_map[] = { { CG3_MMAP_OFFSET, 0, SBUS_MMAP_FBSIZE(1) }, { 0, 0, 0 } }; diff --git a/drivers/video/fbdev/sbuslib.c b/drivers/video/fbdev/sbuslib.c index 634e3d159452..4c79654bda30 100644 --- a/drivers/video/fbdev/sbuslib.c +++ b/drivers/video/fbdev/sbuslib.c @@ -38,7 +38,7 @@ static unsigned long sbusfb_mmapsize(long size, unsigned long fbsize) return fbsize * (-size); } -int sbusfb_mmap_helper(struct sbus_mmap_map *map, +int sbusfb_mmap_helper(const struct sbus_mmap_map *map, unsigned long physbase, unsigned long fbsize, unsigned long iospace, diff --git a/drivers/video/fbdev/sbuslib.h b/drivers/video/fbdev/sbuslib.h index 6466b4cbcd7b..e9af2dc93f94 100644 --- a/drivers/video/fbdev/sbuslib.h +++ b/drivers/video/fbdev/sbuslib.h @@ -19,7 +19,7 @@ struct sbus_mmap_map { extern void sbusfb_fill_var(struct fb_var_screeninfo *var, struct device_node *dp, int bpp); -extern int sbusfb_mmap_helper(struct sbus_mmap_map *map, +extern int sbusfb_mmap_helper(const struct sbus_mmap_map *map, unsigned long physbase, unsigned long fbsize, unsigned long iospace, struct vm_area_struct *vma); diff --git a/drivers/video/fbdev/sstfb.c b/drivers/video/fbdev/sstfb.c index f8ae54ca0cc3..2ea947f57efb 100644 --- a/drivers/video/fbdev/sstfb.c +++ b/drivers/video/fbdev/sstfb.c @@ -716,6 +716,7 @@ static void sstfb_setvgapass( struct fb_info *info, int enable ) pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, tmp); } +#ifdef CONFIG_FB_DEVICE static ssize_t store_vgapass(struct device *device, struct device_attribute *attr, const char *buf, size_t count) { @@ -739,7 +740,8 @@ static ssize_t show_vgapass(struct device *device, struct device_attribute *attr static struct device_attribute device_attrs[] = { __ATTR(vgapass, S_IRUGO|S_IWUSR, show_vgapass, store_vgapass) - }; +}; +#endif static int sstfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) @@ -1436,9 +1438,10 @@ static int sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) sstfb_clear_screen(info); +#ifdef CONFIG_FB_DEVICE if (device_create_file(info->dev, &device_attrs[0])) printk(KERN_WARNING "sstfb: can't create sysfs entry.\n"); - +#endif fb_info(info, "%s frame buffer device at 0x%p\n", fix->id, info->screen_base); @@ -1468,7 +1471,9 @@ static void sstfb_remove(struct pci_dev *pdev) info = pci_get_drvdata(pdev); par = info->par; +#ifdef CONFIG_FB_DEVICE device_remove_file(info->dev, &device_attrs[0]); +#endif sst_shutdown(info); iounmap(info->screen_base); iounmap(par->mmio_vbase); diff --git a/drivers/video/fbdev/tcx.c b/drivers/video/fbdev/tcx.c index 6eb8bb2e3501..f9a0085ad72b 100644 --- a/drivers/video/fbdev/tcx.c +++ b/drivers/video/fbdev/tcx.c @@ -236,7 +236,7 @@ tcx_blank(int blank, struct fb_info *info) return 0; } -static struct sbus_mmap_map __tcx_mmap_map[TCX_MMAP_ENTRIES] = { +static const struct sbus_mmap_map __tcx_mmap_map[TCX_MMAP_ENTRIES] = { { .voff = TCX_RAM8BIT, .size = SBUS_MMAP_FBSIZE(1) |