switch (colorop->type) {
case DRM_COLOROP_1D_CURVE:
- drm_printf(p, "\tcurve_1d_type=%s\n",
- drm_get_colorop_curve_1d_type_name(state->curve_1d_type));
+ drm_printf_indent(p, 1, "curve_1d_type=%s\n",
+ drm_get_colorop_curve_1d_type_name(state->curve_1d_type));
break;
case DRM_COLOROP_1D_LUT:
- drm_printf(p, "\tsize=%d\n", colorop->size);
- drm_printf(p, "\tinterpolation=%s\n",
- drm_get_colorop_lut1d_interpolation_name(state->lut1d_interpolation));
- drm_printf(p, "\tdata blob id=%d\n", state->data ? state->data->base.id : 0);
+ drm_printf_indent(p, 1, "size=%d\n", colorop->size);
+ drm_printf_indent(p, 1, "interpolation=%s\n",
- drm_get_colorop_lut1d_interpolation_name(colorop->lut1d_interpolation));
++ drm_get_colorop_lut1d_interpolation_name(state->lut1d_interpolation));
+ drm_printf_indent(p, 1, "data blob id=%d\n", state->data ? state->data->base.id : 0);
break;
case DRM_COLOROP_CTM_3X4:
- drm_printf(p, "\tdata blob id=%d\n", state->data ? state->data->base.id : 0);
+ drm_printf_indent(p, 1, "data blob id=%d\n", state->data ? state->data->base.id : 0);
break;
case DRM_COLOROP_MULTIPLIER:
- drm_printf(p, "\tmultiplier=%llu\n", state->multiplier);
+ drm_printf_indent(p, 1, "multiplier=%llu\n", state->multiplier);
break;
case DRM_COLOROP_3D_LUT:
- drm_printf(p, "\tsize=%d\n", colorop->size);
- drm_printf(p, "\tinterpolation=%s\n",
- drm_get_colorop_lut3d_interpolation_name(state->lut3d_interpolation));
- drm_printf(p, "\tdata blob id=%d\n", state->data ? state->data->base.id : 0);
+ drm_printf_indent(p, 1, "size=%d\n", colorop->size);
+ drm_printf_indent(p, 1, "interpolation=%s\n",
- drm_get_colorop_lut3d_interpolation_name(colorop->lut3d_interpolation));
++ drm_get_colorop_lut3d_interpolation_name(state->lut3d_interpolation));
+ drm_printf_indent(p, 1, "data blob id=%d\n", state->data ? state->data->base.id : 0);
break;
default:
break;
colorop_state->bypass = true;
if (colorop->curve_1d_type_property) {
- drm_object_property_get_default_value(&colorop->base,
- colorop->curve_1d_type_property,
- &val);
- colorop_state->curve_1d_type = val;
+ if (!drm_object_property_get_default_value(&colorop->base,
+ colorop->curve_1d_type_property,
+ &val))
+ colorop_state->curve_1d_type = val;
}
+
+ if (colorop->lut1d_interpolation_property) {
+ if (!drm_object_property_get_default_value(&colorop->base,
+ colorop->lut1d_interpolation_property,
+ &val))
+ colorop_state->lut1d_interpolation = val;
+ }
+
+ if (colorop->lut3d_interpolation_property) {
+ if (!drm_object_property_get_default_value(&colorop->base,
+ colorop->lut3d_interpolation_property,
+ &val))
+ colorop_state->lut3d_interpolation = val;
+ }
}
/**
return 0;
}
- int ret;
+ static void panthor_vm_init_op_ctx(struct panthor_vm_op_ctx *op_ctx,
+ u64 size, u64 va, u32 flags)
+ {
+ memset(op_ctx, 0, sizeof(*op_ctx));
+ op_ctx->flags = flags;
+ op_ctx->va.range = size;
+ op_ctx->va.addr = va;
+ }
+
+ static int panthor_vm_op_ctx_prealloc_pts(struct panthor_vm_op_ctx *op_ctx)
+ {
+ u64 size = op_ctx->va.range;
+ u64 va = op_ctx->va.addr;
- ret = kmem_cache_alloc_bulk(pt_cache, GFP_KERNEL, pt_count,
- op_ctx->rsvd_page_tables.pages);
- op_ctx->rsvd_page_tables.count = ret;
- if (ret != pt_count)
+
+ /* L1, L2 and L3 page tables.
+ * We could optimize L3 allocation by iterating over the sgt and merging
+ * 2M contiguous blocks, but it's simpler to over-provision and return
+ * the pages if they're not used.
+ */
+ u64 pt_count = ((ALIGN(va + size, 1ull << 39) - ALIGN_DOWN(va, 1ull << 39)) >> 39) +
+ ((ALIGN(va + size, 1ull << 30) - ALIGN_DOWN(va, 1ull << 30)) >> 30) +
+ ((ALIGN(va + size, 1ull << 21) - ALIGN_DOWN(va, 1ull << 21)) >> 21);
+
+ op_ctx->rsvd_page_tables.pages = kzalloc_objs(*op_ctx->rsvd_page_tables.pages,
+ pt_count);
+ if (!op_ctx->rsvd_page_tables.pages)
+ return -ENOMEM;
+
++ if (!kmem_cache_alloc_bulk(pt_cache, GFP_KERNEL, pt_count,
++ op_ctx->rsvd_page_tables.pages)) {
++ op_ctx->rsvd_page_tables.count = 0;
+ return -ENOMEM;
++ }
++ op_ctx->rsvd_page_tables.count = pt_count;
+
+ return 0;
+ }
+
#define PANTHOR_VM_BIND_OP_MAP_FLAGS \
(DRM_PANTHOR_VM_BIND_OP_MAP_READONLY | \
DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC | \
}
}
- impl FwSecBiosBuilder {
- fn setup_falcon_data(
- &mut self,
- pci_at_image: &PciAtBiosImage,
- first_fwsec: &FwSecBiosBuilder,
- ) -> Result {
- let mut offset = usize::from_safe_cast(pci_at_image.falcon_data_ptr()?);
- let mut pmu_in_first_fwsec = false;
-
- // The falcon data pointer assumes that the PciAt and FWSEC images
- // are contiguous in memory. However, testing shows the EFI image sits in
- // between them. So calculate the offset from the end of the PciAt image
- // rather than the start of it. Compensate.
- offset -= pci_at_image.base.data.len();
-
- // The offset is now from the start of the first Fwsec image, however
- // the offset points to a location in the second Fwsec image. Since
- // the fwsec images are contiguous, subtract the length of the first Fwsec
- // image from the offset to get the offset to the start of the second
- // Fwsec image.
- if offset < first_fwsec.base.data.len() {
- pmu_in_first_fwsec = true;
- } else {
- offset -= first_fwsec.base.data.len();
- }
-
- self.falcon_data_offset = Some(offset);
-
- if pmu_in_first_fwsec {
- self.pmu_lookup_table = Some(PmuLookupTable::new(
- &self.base.dev,
- &first_fwsec.base.data[offset..],
- )?);
- } else {
- self.pmu_lookup_table = Some(PmuLookupTable::new(
- &self.base.dev,
- &self.base.data[offset..],
- )?);
- }
-
- match self
- .pmu_lookup_table
- .as_ref()
- .ok_or(EINVAL)?
- .find_entry_by_type(FALCON_UCODE_ENTRY_APPID_FWSEC_PROD)
- {
- Ok(entry) => {
- let mut ucode_offset = usize::from_safe_cast(entry.data);
- ucode_offset -= pci_at_image.base.data.len();
- if ucode_offset < first_fwsec.base.data.len() {
- dev_err!(self.base.dev, "Falcon Ucode offset not in second Fwsec.\n");
- return Err(EINVAL);
- }
- ucode_offset -= first_fwsec.base.data.len();
- self.falcon_ucode_offset = Some(ucode_offset);
- }
- Err(e) => {
- dev_err!(
- self.base.dev,
- "PmuLookupTableEntry not found, error: {:?}\n",
- e
- );
- return Err(EINVAL);
- }
- }
- Ok(())
- }
-
- /// Build the final FwSecBiosImage from this builder
- fn build(self) -> Result<FwSecBiosImage> {
- let ret = FwSecBiosImage {
- base: self.base,
- falcon_ucode_offset: self.falcon_ucode_offset.ok_or(EINVAL)?,
- };
+ impl FwSecBiosImage {
+ /// Build the final `FwSecBiosImage` from the PCI-AT and FWSEC BIOS images.
+ fn new(
+ dev: &device::Device,
+ pci_at_image: PciAtBiosImage,
+ data: KVVec<u8>,
+ ) -> Result<FwSecBiosImage> {
+ let offset = pci_at_image.falcon_data_offset(dev)?;
+
+ let pmu_lookup_data = data.get(offset..).ok_or(EINVAL)?;
+ let pmu_lookup_table = PmuLookupTable::new(dev, pmu_lookup_data)?;
+
+ let entry = pmu_lookup_table
+ .find_entry_by_type(PmuLookupTableEntry::APPID_FWSEC_PROD)
+ .inspect_err(|e| {
+ dev_err!(dev, "PmuLookupTableEntry not found, error: {:?}\n", e);
+ })?;
- if cfg!(debug_assertions) {
- // Print the desc header for debugging
- let desc = ret.header()?;
- dev_dbg!(ret.base.dev, "PmuLookupTableEntry desc: {:#?}\n", desc);
- }
+ let falcon_ucode_offset = usize::from_safe_cast(entry.data)
+ .checked_sub(pci_at_image.base.data.len())
+ .ok_or(EINVAL)
+ .inspect_err(|_| {
+ dev_err!(dev, "Falcon Ucode offset not in Fwsec.\n");
+ })?;
- Ok(ret)
+ Ok(FwSecBiosImage {
+ dev: dev.into(),
+ data,
+ falcon_ucode_offset,
+ })
}
- }
- impl FwSecBiosImage {
/// Get the FwSec header ([`FalconUCodeDesc`]).
pub(crate) fn header(&self) -> Result<FalconUCodeDesc> {
- // Get the falcon ucode offset that was found in setup_falcon_data.
- let falcon_ucode_offset = self.falcon_ucode_offset;
+ let data = self.data.get(self.falcon_ucode_offset..).ok_or(EINVAL)?;
- // Read the first 4 bytes to get the version.
- let hdr_bytes: [u8; 4] = self.base.data[falcon_ucode_offset..falcon_ucode_offset + 4]
- .try_into()
- .map_err(|_| EINVAL)?;
- let hdr = u32::from_le_bytes(hdr_bytes);
- let ver = (hdr & 0xff00) >> 8;
-
- let data = self.base.data.get(falcon_ucode_offset..).ok_or(EINVAL)?;
+ // Read the version byte from the header.
+ let ver = data.get(1).copied().ok_or(EINVAL)?;
match ver {
2 => {
- let v2 = FalconUCodeDescV2::from_bytes_copy_prefix(data)
- .ok_or(EINVAL)?
+ let v2 = FalconUCodeDescV2::read_from_prefix(data)
+ .map_err(|_| EINVAL)?
.0;
Ok(FalconUCodeDesc::V2(v2))
}
*/
struct drm_property_blob *data;
- /** @state: backpointer to global drm_atomic_state */
- struct drm_atomic_state *state;
+ /**
+ * @lut1d_interpolation:
+ *
+ * Interpolation for DRM_COLOROP_1D_LUT
+ */
+ enum drm_colorop_lut1d_interpolation_type lut1d_interpolation;
+
+ /**
+ * @lut3d_interpolation:
+ *
+ * Interpolation for DRM_COLOROP_3D_LUT
+ */
+ enum drm_colorop_lut3d_interpolation_type lut3d_interpolation;
+
+ /** @state: backpointer to global drm_atomic_commit */
+ struct drm_atomic_commit *state;
};
/**