summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2026-01-06 18:48:26 +0000
committerMark Brown <broonie@kernel.org>2026-01-06 18:48:26 +0000
commit49d3bd9fe2d93ec6eaf7d550e2eb9608b401c915 (patch)
treedd4bd4b6c37f81f50a9f5b8dfff546cb4ee0ca95 /drivers
parent04b61513dfe40f80f0dcc795003637b510522b3c (diff)
parent9bf0bd7bdea6c402007ffb784dd0c0f704aa2310 (diff)
ASoC: nau8821: Fixes and driver cleanup
Merge series from Cristian Ciocaltea <cristian.ciocaltea@collabora.com>: This series provides several fixes and cleanup patches for the Nuvoton NAU88L21 audio codec driver. Testing and validation has been performed on Valve Steam Deck.
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/rnbd/rnbd-clt.h2
-rw-r--r--drivers/block/ublk_drv.c38
-rw-r--r--drivers/bluetooth/btusb.c12
-rw-r--r--drivers/crypto/hisilicon/qm.c9
-rw-r--r--drivers/firewire/nosy.c10
-rw-r--r--drivers/firmware/efi/efi.c1
-rw-r--r--drivers/firmware/efi/libstub/gop.c8
-rw-r--r--drivers/gpu/drm/drm_gem_shmem_helper.c5
-rw-r--r--drivers/gpu/drm/drm_pagemap.c17
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c37
-rw-r--r--drivers/gpu/drm/imagination/pvr_gem.c11
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_catalog.c13
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu.c52
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu.h1
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_preempt.c4
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.h13
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c38
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h8
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c29
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h2
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c10
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h2
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h4
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h84
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.h3
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h10
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h20
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h23
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h2
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h1
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h20
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h47
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h21
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h16
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h4
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c137
-rw-r--r--drivers/gpu/drm/msm/disp/mdp_format.h6
-rw-r--r--drivers/gpu/drm/msm/dp/dp_debug.h2
-rw-r--r--drivers/gpu/drm/msm/dp/dp_drm.c1
-rw-r--r--drivers/gpu/drm/msm/dp/dp_link.h9
-rw-r--r--drivers/gpu/drm/msm/dp/dp_panel.h8
-rw-r--r--drivers/gpu/drm/msm/msm_fence.h36
-rw-r--r--drivers/gpu/drm/msm/msm_gem_vma.c5
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.h68
-rw-r--r--drivers/gpu/drm/msm/msm_iommu.c4
-rw-r--r--drivers/gpu/drm/msm/msm_perf.c10
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/atom.h13
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/wndw.c2
-rw-r--r--drivers/gpu/drm/xe/xe_guc_ct.c14
-rw-r--r--drivers/gpu/drm/xe/xe_migrate.c25
-rw-r--r--drivers/gpu/drm/xe/xe_migrate.h6
-rw-r--r--drivers/gpu/drm/xe/xe_svm.c51
-rw-r--r--drivers/infiniband/core/addr.c33
-rw-r--r--drivers/infiniband/core/cma.c3
-rw-r--r--drivers/infiniband/core/device.c4
-rw-r--r--drivers/infiniband/core/verbs.c2
-rw-r--r--drivers/infiniband/hw/bnxt_re/hw_counters.h6
-rw-r--r--drivers/infiniband/hw/bnxt_re/ib_verbs.c7
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_rcfw.c2
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_res.c8
-rw-r--r--drivers/infiniband/hw/efa/efa_verbs.c4
-rw-r--r--drivers/infiniband/hw/irdma/utils.c3
-rw-r--r--drivers/infiniband/hw/mana/cq.c4
-rw-r--r--drivers/infiniband/sw/rxe/rxe_net.c32
-rw-r--r--drivers/infiniband/sw/rxe/rxe_odp.c4
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs-clt.c1
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs-pri.h32
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs.h24
-rw-r--r--drivers/md/md.c61
-rw-r--r--drivers/md/raid5.c10
-rw-r--r--drivers/net/dsa/b53/b53_common.c3
-rw-r--r--drivers/net/ethernet/airoha/airoha_eth.c39
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c2
-rw-r--r--drivers/net/ethernet/broadcom/Kconfig8
-rw-r--r--drivers/net/ethernet/broadcom/bnge/bnge.h2
-rw-r--r--drivers/net/ethernet/broadcom/bnge/bnge_core.c2
-rw-r--r--drivers/net/ethernet/cadence/macb_main.c3
-rw-r--r--drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c8
-rw-r--r--drivers/net/ethernet/google/gve/gve_main.c2
-rw-r--r--drivers/net/ethernet/google/gve/gve_utils.c2
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_main.c10
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e.h11
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_ethtool.c12
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_main.c1
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c4
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_main.c4
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_lib.c2
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_virtchnl.c5
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c8
-rw-r--r--drivers/net/ethernet/microsoft/mana/gdma_main.c2
-rw-r--r--drivers/net/ethernet/smsc/smc91x.c10
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c17
-rw-r--r--drivers/net/ethernet/wangxun/Kconfig4
-rw-r--r--drivers/net/fjes/fjes_hw.c12
-rw-r--r--drivers/net/mdio/mdio-aspeed.c7
-rw-r--r--drivers/net/mdio/mdio-realtek-rtl9300.c6
-rw-r--r--drivers/net/phy/mediatek/mtk-ge-soc.c2
-rw-r--r--drivers/net/team/team_core.c2
-rw-r--r--drivers/net/usb/asix_common.c5
-rw-r--r--drivers/net/usb/ax88172a.c6
-rw-r--r--drivers/net/usb/rtl8150.c2
-rw-r--r--drivers/net/usb/sr9700.c9
-rw-r--r--drivers/net/usb/usbnet.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-drv.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/ptp.c7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ptp.c7
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c12
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c3
-rw-r--r--drivers/net/wireless/realtek/rtw88/sdio.c4
-rw-r--r--drivers/net/wireless/realtek/rtw88/usb.c3
-rw-r--r--drivers/net/wireless/ti/wlcore/tx.c5
-rw-r--r--drivers/parisc/sba_iommu.c4
-rw-r--r--drivers/platform/mellanox/mlxbf-pmc.c14
-rw-r--r--drivers/platform/x86/asus-armoury.h176
-rw-r--r--drivers/platform/x86/asus-nb-wmi.c1
-rw-r--r--drivers/platform/x86/dell/alienware-wmi-wmax.c32
-rw-r--r--drivers/platform/x86/dell/dell-lis3lv02d.c1
-rw-r--r--drivers/platform/x86/hp/hp-bioscfg/enum-attributes.c4
-rw-r--r--drivers/platform/x86/hp/hp-bioscfg/int-attributes.c2
-rw-r--r--drivers/platform/x86/hp/hp-bioscfg/order-list-attributes.c5
-rw-r--r--drivers/platform/x86/hp/hp-bioscfg/passwdobj-attributes.c5
-rw-r--r--drivers/platform/x86/hp/hp-bioscfg/string-attributes.c2
-rw-r--r--drivers/platform/x86/ibm_rtl.c2
-rw-r--r--drivers/platform/x86/intel/pmt/discovery.c8
-rw-r--r--drivers/platform/x86/lenovo/ideapad-laptop.c2
-rw-r--r--drivers/platform/x86/lenovo/think-lmi.c6
-rw-r--r--drivers/platform/x86/msi-laptop.c3
-rw-r--r--drivers/platform/x86/samsung-galaxybook.c9
-rw-r--r--drivers/platform/x86/uniwill/uniwill-acpi.c7
-rw-r--r--drivers/pmdomain/imx/gpc.c5
-rw-r--r--drivers/pmdomain/mediatek/mtk-pm-domains.c21
-rw-r--r--drivers/regulator/fp9931.c3
-rw-r--r--drivers/scsi/mpi3mr/mpi/mpi30_ioc.h1
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_fw.c2
-rw-r--r--drivers/scsi/scsi_debug.c2
-rw-r--r--drivers/scsi/sg.c20
-rw-r--r--drivers/spi/spi-cadence-quadspi.c23
-rw-r--r--drivers/spi/spi-sun6i.c11
-rw-r--r--drivers/tty/serial/8250/8250_loongson.c4
-rw-r--r--drivers/tty/serial/serial_base_bus.c11
-rw-r--r--drivers/tty/serial/sh-sci.c2
-rw-r--r--drivers/tty/serial/xilinx_uartps.c14
-rw-r--r--drivers/ufs/core/ufshcd.c5
-rw-r--r--drivers/usb/dwc3/dwc3-of-simple.c7
-rw-r--r--drivers/usb/dwc3/gadget.c2
-rw-r--r--drivers/usb/dwc3/host.c2
-rw-r--r--drivers/usb/gadget/udc/lpc32xx_udc.c42
-rw-r--r--drivers/usb/host/ohci-nxp.c18
-rw-r--r--drivers/usb/host/xhci-dbgtty.c2
-rw-r--r--drivers/usb/phy/phy-fsl-usb.c1
-rw-r--r--drivers/usb/phy/phy-isp1301.c7
-rw-r--r--drivers/usb/renesas_usbhs/pipe.c2
-rw-r--r--drivers/usb/storage/unusual_uas.h2
-rw-r--r--drivers/usb/typec/altmodes/displayport.c8
-rw-r--r--drivers/usb/typec/ucsi/Kconfig1
-rw-r--r--drivers/usb/typec/ucsi/cros_ec_ucsi.c5
-rw-r--r--drivers/usb/typec/ucsi/debugfs.c36
-rw-r--r--drivers/usb/typec/ucsi/displayport.c11
-rw-r--r--drivers/usb/typec/ucsi/ucsi.c118
-rw-r--r--drivers/usb/typec/ucsi/ucsi.h22
-rw-r--r--drivers/usb/typec/ucsi/ucsi_acpi.c25
-rw-r--r--drivers/usb/typec/ucsi/ucsi_ccg.c11
-rw-r--r--drivers/usb/typec/ucsi/ucsi_yoga_c630.c15
-rw-r--r--drivers/vfio/pci/nvgrace-gpu/main.c4
-rw-r--r--drivers/vfio/pci/pds/dirty.c7
-rw-r--r--drivers/vfio/pci/vfio_pci_rdwr.c25
-rw-r--r--drivers/vfio/pci/xe/main.c5
-rw-r--r--drivers/vhost/vsock.c15
169 files changed, 1362 insertions, 918 deletions
diff --git a/drivers/block/rnbd/rnbd-clt.h b/drivers/block/rnbd/rnbd-clt.h
index a48e040abe63..fbc1ed766025 100644
--- a/drivers/block/rnbd/rnbd-clt.h
+++ b/drivers/block/rnbd/rnbd-clt.h
@@ -112,7 +112,7 @@ struct rnbd_clt_dev {
struct rnbd_queue *hw_queues;
u32 device_id;
/* local Idr index - used to track minor number allocations. */
- u32 clt_device_id;
+ int clt_device_id;
struct mutex lock;
enum rnbd_clt_dev_state dev_state;
refcount_t refcount;
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index cfd2132410dd..837fedb02e0d 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -237,6 +237,7 @@ struct ublk_device {
bool canceling;
pid_t ublksrv_tgid;
struct delayed_work exit_work;
+ struct work_struct partition_scan_work;
struct ublk_queue *queues[];
};
@@ -254,6 +255,20 @@ static inline struct request *__ublk_check_and_get_req(struct ublk_device *ub,
u16 q_id, u16 tag, struct ublk_io *io, size_t offset);
static inline unsigned int ublk_req_build_flags(struct request *req);
+static void ublk_partition_scan_work(struct work_struct *work)
+{
+ struct ublk_device *ub =
+ container_of(work, struct ublk_device, partition_scan_work);
+
+ if (WARN_ON_ONCE(!test_and_clear_bit(GD_SUPPRESS_PART_SCAN,
+ &ub->ub_disk->state)))
+ return;
+
+ mutex_lock(&ub->ub_disk->open_mutex);
+ bdev_disk_changed(ub->ub_disk, false);
+ mutex_unlock(&ub->ub_disk->open_mutex);
+}
+
static inline struct ublksrv_io_desc *
ublk_get_iod(const struct ublk_queue *ubq, unsigned tag)
{
@@ -1607,8 +1622,7 @@ static bool ublk_check_and_reset_active_ref(struct ublk_device *ub)
{
int i, j;
- if (!(ub->dev_info.flags & (UBLK_F_SUPPORT_ZERO_COPY |
- UBLK_F_AUTO_BUF_REG)))
+ if (!ublk_dev_need_req_ref(ub))
return false;
for (i = 0; i < ub->dev_info.nr_hw_queues; i++) {
@@ -2027,6 +2041,7 @@ static void ublk_stop_dev(struct ublk_device *ub)
mutex_lock(&ub->mutex);
ublk_stop_dev_unlocked(ub);
mutex_unlock(&ub->mutex);
+ flush_work(&ub->partition_scan_work);
ublk_cancel_dev(ub);
}
@@ -2955,9 +2970,17 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub,
ublk_apply_params(ub);
- /* don't probe partitions if any daemon task is un-trusted */
- if (ub->unprivileged_daemons)
- set_bit(GD_SUPPRESS_PART_SCAN, &disk->state);
+ /*
+ * Suppress partition scan to avoid potential IO hang.
+ *
+ * If ublk server error occurs during partition scan, the IO may
+ * wait while holding ub->mutex, which can deadlock with other
+ * operations that need the mutex. Defer partition scan to async
+ * work.
+ * For unprivileged daemons, keep GD_SUPPRESS_PART_SCAN set
+ * permanently.
+ */
+ set_bit(GD_SUPPRESS_PART_SCAN, &disk->state);
ublk_get_device(ub);
ub->dev_info.state = UBLK_S_DEV_LIVE;
@@ -2974,6 +2997,10 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub,
set_bit(UB_STATE_USED, &ub->state);
+ /* Schedule async partition scan for trusted daemons */
+ if (!ub->unprivileged_daemons)
+ schedule_work(&ub->partition_scan_work);
+
out_put_cdev:
if (ret) {
ublk_detach_disk(ub);
@@ -3139,6 +3166,7 @@ static int ublk_ctrl_add_dev(const struct ublksrv_ctrl_cmd *header)
mutex_init(&ub->mutex);
spin_lock_init(&ub->lock);
mutex_init(&ub->cancel_mutex);
+ INIT_WORK(&ub->partition_scan_work, ublk_partition_scan_work);
ret = ublk_alloc_dev_number(ub, header->dev_id);
if (ret < 0)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 8ed3883ab8ee..ded09e94d296 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -4052,7 +4052,7 @@ static int btusb_probe(struct usb_interface *intf,
return -ENODEV;
}
- data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -4075,8 +4075,10 @@ static int btusb_probe(struct usb_interface *intf,
}
}
- if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep)
+ if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep) {
+ kfree(data);
return -ENODEV;
+ }
if (id->driver_info & BTUSB_AMP) {
data->cmdreq_type = USB_TYPE_CLASS | 0x01;
@@ -4131,8 +4133,10 @@ static int btusb_probe(struct usb_interface *intf,
data->recv_acl = hci_recv_frame;
hdev = hci_alloc_dev_priv(priv_size);
- if (!hdev)
+ if (!hdev) {
+ kfree(data);
return -ENOMEM;
+ }
hdev->bus = HCI_USB;
hci_set_drvdata(hdev, data);
@@ -4406,6 +4410,7 @@ out_free_dev:
if (data->reset_gpio)
gpiod_put(data->reset_gpio);
hci_free_dev(hdev);
+ kfree(data);
return err;
}
@@ -4454,6 +4459,7 @@ static void btusb_disconnect(struct usb_interface *intf)
}
hci_free_dev(hdev);
+ kfree(data);
}
#ifdef CONFIG_PM
diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c
index f8bfff5dd0bd..d47bf06a90f7 100644
--- a/drivers/crypto/hisilicon/qm.c
+++ b/drivers/crypto/hisilicon/qm.c
@@ -991,7 +991,7 @@ static void qm_get_complete_eqe_num(struct hisi_qm *qm)
return;
poll_data = &qm->poll_data[cqn];
- while (QM_EQE_PHASE(dw0) != qm->status.eqc_phase) {
+ do {
poll_data->qp_finish_id[eqe_num] = dw0 & QM_EQE_CQN_MASK;
eqe_num++;
@@ -1004,11 +1004,10 @@ static void qm_get_complete_eqe_num(struct hisi_qm *qm)
qm->status.eq_head++;
}
- if (eqe_num == (eq_depth >> 1) - 1)
- break;
-
dw0 = le32_to_cpu(eqe->dw0);
- }
+ if (QM_EQE_PHASE(dw0) != qm->status.eqc_phase)
+ break;
+ } while (eqe_num < (eq_depth >> 1) - 1);
poll_data->eqe_num = eqe_num;
queue_work(qm->wq, &poll_data->work);
diff --git a/drivers/firewire/nosy.c b/drivers/firewire/nosy.c
index ea31ac7ac1ca..e59053738a43 100644
--- a/drivers/firewire/nosy.c
+++ b/drivers/firewire/nosy.c
@@ -36,6 +36,8 @@
static char driver_name[] = KBUILD_MODNAME;
+#define RCV_BUFFER_SIZE (16 * 1024)
+
/* this is the physical layout of a PCL, its size is 128 bytes */
struct pcl {
__le32 next;
@@ -517,16 +519,14 @@ remove_card(struct pci_dev *dev)
lynx->rcv_start_pcl, lynx->rcv_start_pcl_bus);
dma_free_coherent(&lynx->pci_device->dev, sizeof(struct pcl),
lynx->rcv_pcl, lynx->rcv_pcl_bus);
- dma_free_coherent(&lynx->pci_device->dev, PAGE_SIZE, lynx->rcv_buffer,
- lynx->rcv_buffer_bus);
+ dma_free_coherent(&lynx->pci_device->dev, RCV_BUFFER_SIZE,
+ lynx->rcv_buffer, lynx->rcv_buffer_bus);
iounmap(lynx->registers);
pci_disable_device(dev);
lynx_put(lynx);
}
-#define RCV_BUFFER_SIZE (16 * 1024)
-
static int
add_card(struct pci_dev *dev, const struct pci_device_id *unused)
{
@@ -680,7 +680,7 @@ fail_deallocate_buffers:
dma_free_coherent(&lynx->pci_device->dev, sizeof(struct pcl),
lynx->rcv_pcl, lynx->rcv_pcl_bus);
if (lynx->rcv_buffer)
- dma_free_coherent(&lynx->pci_device->dev, PAGE_SIZE,
+ dma_free_coherent(&lynx->pci_device->dev, RCV_BUFFER_SIZE,
lynx->rcv_buffer, lynx->rcv_buffer_bus);
iounmap(lynx->registers);
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index a9070d00b833..55452e61af31 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -73,6 +73,7 @@ struct mm_struct efi_mm = {
MMAP_LOCK_INITIALIZER(efi_mm)
.page_table_lock = __SPIN_LOCK_UNLOCKED(efi_mm.page_table_lock),
.mmlist = LIST_HEAD_INIT(efi_mm.mmlist),
+ .user_ns = &init_user_ns,
.cpu_bitmap = { [BITS_TO_LONGS(NR_CPUS)] = 0},
#ifdef CONFIG_SCHED_MM_CID
.mm_cid.lock = __RAW_SPIN_LOCK_UNLOCKED(efi_mm.mm_cid.lock),
diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
index 72d74436a7a4..80dc8cfeb33e 100644
--- a/drivers/firmware/efi/libstub/gop.c
+++ b/drivers/firmware/efi/libstub/gop.c
@@ -513,15 +513,15 @@ efi_status_t efi_setup_graphics(struct screen_info *si, struct edid_info *edid)
status = efi_bs_call(handle_protocol, handle, &EFI_EDID_ACTIVE_PROTOCOL_GUID,
(void **)&active_edid);
if (status == EFI_SUCCESS) {
- gop_size_of_edid = active_edid->size_of_edid;
- gop_edid = active_edid->edid;
+ gop_size_of_edid = efi_table_attr(active_edid, size_of_edid);
+ gop_edid = efi_table_attr(active_edid, edid);
} else {
status = efi_bs_call(handle_protocol, handle,
&EFI_EDID_DISCOVERED_PROTOCOL_GUID,
(void **)&discovered_edid);
if (status == EFI_SUCCESS) {
- gop_size_of_edid = discovered_edid->size_of_edid;
- gop_edid = discovered_edid->edid;
+ gop_size_of_edid = efi_table_attr(discovered_edid, size_of_edid);
+ gop_edid = efi_table_attr(discovered_edid, edid);
}
}
diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c
index 93b9cff89080..f13eb5f36e8a 100644
--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -96,7 +96,8 @@ err_release:
/**
* drm_gem_shmem_init - Initialize an allocated object.
* @dev: DRM device
- * @obj: The allocated shmem GEM object.
+ * @shmem: The allocated shmem GEM object.
+ * @size: Buffer size in bytes
*
* Returns:
* 0 on success, or a negative error code on failure.
@@ -895,4 +896,4 @@ EXPORT_SYMBOL_GPL(drm_gem_shmem_prime_import_no_map);
MODULE_DESCRIPTION("DRM SHMEM memory-management helpers");
MODULE_IMPORT_NS("DMA_BUF");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/drm_pagemap.c b/drivers/gpu/drm/drm_pagemap.c
index 37d7cfbbb3e8..06c1bd8fc4d1 100644
--- a/drivers/gpu/drm/drm_pagemap.c
+++ b/drivers/gpu/drm/drm_pagemap.c
@@ -3,6 +3,7 @@
* Copyright © 2024-2025 Intel Corporation
*/
+#include <linux/dma-fence.h>
#include <linux/dma-mapping.h>
#include <linux/migrate.h>
#include <linux/pagemap.h>
@@ -408,10 +409,14 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,
drm_pagemap_get_devmem_page(page, zdd);
}
- err = ops->copy_to_devmem(pages, pagemap_addr, npages);
+ err = ops->copy_to_devmem(pages, pagemap_addr, npages,
+ devmem_allocation->pre_migrate_fence);
if (err)
goto err_finalize;
+ dma_fence_put(devmem_allocation->pre_migrate_fence);
+ devmem_allocation->pre_migrate_fence = NULL;
+
/* Upon success bind devmem allocation to range and zdd */
devmem_allocation->timeslice_expiration = get_jiffies_64() +
msecs_to_jiffies(timeslice_ms);
@@ -596,7 +601,7 @@ retry:
for (i = 0; i < npages; ++i)
pages[i] = migrate_pfn_to_page(src[i]);
- err = ops->copy_to_ram(pages, pagemap_addr, npages);
+ err = ops->copy_to_ram(pages, pagemap_addr, npages, NULL);
if (err)
goto err_finalize;
@@ -732,7 +737,7 @@ static int __drm_pagemap_migrate_to_ram(struct vm_area_struct *vas,
for (i = 0; i < npages; ++i)
pages[i] = migrate_pfn_to_page(migrate.src[i]);
- err = ops->copy_to_ram(pages, pagemap_addr, npages);
+ err = ops->copy_to_ram(pages, pagemap_addr, npages, NULL);
if (err)
goto err_finalize;
@@ -813,11 +818,14 @@ EXPORT_SYMBOL_GPL(drm_pagemap_pagemap_ops_get);
* @ops: Pointer to the operations structure for GPU SVM device memory
* @dpagemap: The struct drm_pagemap we're allocating from.
* @size: Size of device memory allocation
+ * @pre_migrate_fence: Fence to wait for or pipeline behind before migration starts.
+ * (May be NULL).
*/
void drm_pagemap_devmem_init(struct drm_pagemap_devmem *devmem_allocation,
struct device *dev, struct mm_struct *mm,
const struct drm_pagemap_devmem_ops *ops,
- struct drm_pagemap *dpagemap, size_t size)
+ struct drm_pagemap *dpagemap, size_t size,
+ struct dma_fence *pre_migrate_fence)
{
init_completion(&devmem_allocation->detached);
devmem_allocation->dev = dev;
@@ -825,6 +833,7 @@ void drm_pagemap_devmem_init(struct drm_pagemap_devmem *devmem_allocation,
devmem_allocation->ops = ops;
devmem_allocation->dpagemap = dpagemap;
devmem_allocation->size = size;
+ devmem_allocation->pre_migrate_fence = pre_migrate_fence;
}
EXPORT_SYMBOL_GPL(drm_pagemap_devmem_init);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index b057c2fa03a4..d49e96f9be51 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -951,13 +951,13 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb)
vma = eb_lookup_vma(eb, eb->exec[i].handle);
if (IS_ERR(vma)) {
err = PTR_ERR(vma);
- goto err;
+ return err;
}
err = eb_validate_vma(eb, &eb->exec[i], vma);
if (unlikely(err)) {
i915_vma_put(vma);
- goto err;
+ return err;
}
err = eb_add_vma(eb, &current_batch, i, vma);
@@ -966,19 +966,8 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb)
if (i915_gem_object_is_userptr(vma->obj)) {
err = i915_gem_object_userptr_submit_init(vma->obj);
- if (err) {
- if (i + 1 < eb->buffer_count) {
- /*
- * Execbuffer code expects last vma entry to be NULL,
- * since we already initialized this entry,
- * set the next value to NULL or we mess up
- * cleanup handling.
- */
- eb->vma[i + 1].vma = NULL;
- }
-
+ if (err)
return err;
- }
eb->vma[i].flags |= __EXEC_OBJECT_USERPTR_INIT;
eb->args->flags |= __EXEC_USERPTR_USED;
@@ -986,10 +975,6 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb)
}
return 0;
-
-err:
- eb->vma[i].vma = NULL;
- return err;
}
static int eb_lock_vmas(struct i915_execbuffer *eb)
@@ -3375,7 +3360,8 @@ i915_gem_do_execbuffer(struct drm_device *dev,
eb.exec = exec;
eb.vma = (struct eb_vma *)(exec + args->buffer_count + 1);
- eb.vma[0].vma = NULL;
+ memset(eb.vma, 0, (args->buffer_count + 1) * sizeof(struct eb_vma));
+
eb.batch_pool = NULL;
eb.invalid_flags = __EXEC_OBJECT_UNKNOWN_FLAGS;
@@ -3584,7 +3570,18 @@ i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data,
if (err)
return err;
- /* Allocate extra slots for use by the command parser */
+ /*
+ * Allocate extra slots for use by the command parser.
+ *
+ * Note that this allocation handles two different arrays (the
+ * exec2_list array, and the eventual eb.vma array introduced in
+ * i915_gem_do_execbuffer()), that reside in virtually contiguous
+ * memory. Also note that the allocation intentionally doesn't fill the
+ * area with zeros, because the exec2_list part doesn't need to be, as
+ * it's immediately overwritten by user data a few lines below.
+ * However, the eb.vma part is explicitly zeroed later in
+ * i915_gem_do_execbuffer().
+ */
exec2_list = kvmalloc_array(count + 2, eb_element_size(),
__GFP_NOWARN | GFP_KERNEL);
if (exec2_list == NULL) {
diff --git a/drivers/gpu/drm/imagination/pvr_gem.c b/drivers/gpu/drm/imagination/pvr_gem.c
index a66cf082af24..c07c9a915190 100644
--- a/drivers/gpu/drm/imagination/pvr_gem.c
+++ b/drivers/gpu/drm/imagination/pvr_gem.c
@@ -28,6 +28,16 @@ static void pvr_gem_object_free(struct drm_gem_object *obj)
drm_gem_shmem_object_free(obj);
}
+static struct dma_buf *pvr_gem_export(struct drm_gem_object *obj, int flags)
+{
+ struct pvr_gem_object *pvr_obj = gem_to_pvr_gem(obj);
+
+ if (pvr_obj->flags & DRM_PVR_BO_PM_FW_PROTECT)
+ return ERR_PTR(-EPERM);
+
+ return drm_gem_prime_export(obj, flags);
+}
+
static int pvr_gem_mmap(struct drm_gem_object *gem_obj, struct vm_area_struct *vma)
{
struct pvr_gem_object *pvr_obj = gem_to_pvr_gem(gem_obj);
@@ -42,6 +52,7 @@ static int pvr_gem_mmap(struct drm_gem_object *gem_obj, struct vm_area_struct *v
static const struct drm_gem_object_funcs pvr_gem_object_funcs = {
.free = pvr_gem_object_free,
.print_info = drm_gem_shmem_object_print_info,
+ .export = pvr_gem_export,
.pin = drm_gem_shmem_object_pin,
.unpin = drm_gem_shmem_object_unpin,
.get_sg_table = drm_gem_shmem_object_get_sg_table,
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
index 29107b362346..ac9a95aab2fb 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
@@ -1376,7 +1376,6 @@ static const uint32_t a7xx_pwrup_reglist_regs[] = {
REG_A6XX_UCHE_MODE_CNTL,
REG_A6XX_RB_NC_MODE_CNTL,
REG_A6XX_RB_CMP_DBG_ECO_CNTL,
- REG_A7XX_GRAS_NC_MODE_CNTL,
REG_A6XX_RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE_ENABLE,
REG_A6XX_UCHE_GBIF_GX_CONFIG,
REG_A6XX_UCHE_CLIENT_PF,
@@ -1392,6 +1391,7 @@ static const u32 a750_ifpc_reglist_regs[] = {
REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(2),
REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(3),
REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(4),
+ REG_A6XX_RBBM_PERFCTR_CNTL,
REG_A6XX_TPL1_NC_MODE_CNTL,
REG_A6XX_SP_NC_MODE_CNTL,
REG_A6XX_CP_DBG_ECO_CNTL,
@@ -1448,6 +1448,12 @@ static const u32 a750_ifpc_reglist_regs[] = {
DECLARE_ADRENO_REGLIST_LIST(a750_ifpc_reglist);
+static const struct adreno_reglist_pipe a7xx_dyn_pwrup_reglist_regs[] = {
+ { REG_A7XX_GRAS_NC_MODE_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+};
+
+DECLARE_ADRENO_REGLIST_PIPE_LIST(a7xx_dyn_pwrup_reglist);
+
static const struct adreno_info a7xx_gpus[] = {
{
.chip_ids = ADRENO_CHIP_IDS(0x07000200),
@@ -1491,6 +1497,7 @@ static const struct adreno_info a7xx_gpus[] = {
.hwcg = a730_hwcg,
.protect = &a730_protect,
.pwrup_reglist = &a7xx_pwrup_reglist,
+ .dyn_pwrup_reglist = &a7xx_dyn_pwrup_reglist,
.gbif_cx = a640_gbif,
.gmu_cgc_mode = 0x00020000,
},
@@ -1513,6 +1520,7 @@ static const struct adreno_info a7xx_gpus[] = {
.hwcg = a740_hwcg,
.protect = &a730_protect,
.pwrup_reglist = &a7xx_pwrup_reglist,
+ .dyn_pwrup_reglist = &a7xx_dyn_pwrup_reglist,
.gbif_cx = a640_gbif,
.gmu_chipid = 0x7020100,
.gmu_cgc_mode = 0x00020202,
@@ -1547,6 +1555,7 @@ static const struct adreno_info a7xx_gpus[] = {
.hwcg = a740_hwcg,
.protect = &a730_protect,
.pwrup_reglist = &a7xx_pwrup_reglist,
+ .dyn_pwrup_reglist = &a7xx_dyn_pwrup_reglist,
.ifpc_reglist = &a750_ifpc_reglist,
.gbif_cx = a640_gbif,
.gmu_chipid = 0x7050001,
@@ -1589,6 +1598,7 @@ static const struct adreno_info a7xx_gpus[] = {
.a6xx = &(const struct a6xx_info) {
.protect = &a730_protect,
.pwrup_reglist = &a7xx_pwrup_reglist,
+ .dyn_pwrup_reglist = &a7xx_dyn_pwrup_reglist,
.ifpc_reglist = &a750_ifpc_reglist,
.gbif_cx = a640_gbif,
.gmu_chipid = 0x7090100,
@@ -1623,6 +1633,7 @@ static const struct adreno_info a7xx_gpus[] = {
.hwcg = a740_hwcg,
.protect = &a730_protect,
.pwrup_reglist = &a7xx_pwrup_reglist,
+ .dyn_pwrup_reglist = &a7xx_dyn_pwrup_reglist,
.gbif_cx = a640_gbif,
.gmu_chipid = 0x70f0000,
.gmu_cgc_mode = 0x00020222,
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 0200a7e71cdf..2129d230a92b 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -849,9 +849,16 @@ static void a6xx_set_ubwc_config(struct msm_gpu *gpu)
min_acc_len_64b << 3 |
hbb_lo << 1 | ubwc_mode);
- if (adreno_is_a7xx(adreno_gpu))
- gpu_write(gpu, REG_A7XX_GRAS_NC_MODE_CNTL,
- FIELD_PREP(GENMASK(8, 5), hbb_lo));
+ if (adreno_is_a7xx(adreno_gpu)) {
+ for (u32 pipe_id = PIPE_BR; pipe_id <= PIPE_BV; pipe_id++) {
+ gpu_write(gpu, REG_A7XX_CP_APERTURE_CNTL_HOST,
+ A7XX_CP_APERTURE_CNTL_HOST_PIPE(pipe_id));
+ gpu_write(gpu, REG_A7XX_GRAS_NC_MODE_CNTL,
+ FIELD_PREP(GENMASK(8, 5), hbb_lo));
+ }
+ gpu_write(gpu, REG_A7XX_CP_APERTURE_CNTL_HOST,
+ A7XX_CP_APERTURE_CNTL_HOST_PIPE(PIPE_NONE));
+ }
gpu_write(gpu, REG_A6XX_UCHE_MODE_CNTL,
min_acc_len_64b << 23 | hbb_lo << 21);
@@ -865,23 +872,27 @@ static void a7xx_patch_pwrup_reglist(struct msm_gpu *gpu)
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
const struct adreno_reglist_list *reglist;
+ const struct adreno_reglist_pipe_list *dyn_pwrup_reglist;
void *ptr = a6xx_gpu->pwrup_reglist_ptr;
struct cpu_gpu_lock *lock = ptr;
u32 *dest = (u32 *)&lock->regs[0];
+ u32 dyn_pwrup_reglist_count = 0;
int i;
lock->gpu_req = lock->cpu_req = lock->turn = 0;
reglist = adreno_gpu->info->a6xx->ifpc_reglist;
- lock->ifpc_list_len = reglist->count;
+ if (reglist) {
+ lock->ifpc_list_len = reglist->count;
- /*
- * For each entry in each of the lists, write the offset and the current
- * register value into the GPU buffer
- */
- for (i = 0; i < reglist->count; i++) {
- *dest++ = reglist->regs[i];
- *dest++ = gpu_read(gpu, reglist->regs[i]);
+ /*
+ * For each entry in each of the lists, write the offset and the current
+ * register value into the GPU buffer
+ */
+ for (i = 0; i < reglist->count; i++) {
+ *dest++ = reglist->regs[i];
+ *dest++ = gpu_read(gpu, reglist->regs[i]);
+ }
}
reglist = adreno_gpu->info->a6xx->pwrup_reglist;
@@ -907,7 +918,24 @@ static void a7xx_patch_pwrup_reglist(struct msm_gpu *gpu)
* (<aperture, shifted 12 bits> <address> <data>), and the length is
* stored as number for triplets in dynamic_list_len.
*/
- lock->dynamic_list_len = 0;
+ dyn_pwrup_reglist = adreno_gpu->info->a6xx->dyn_pwrup_reglist;
+ if (dyn_pwrup_reglist) {
+ for (u32 pipe_id = PIPE_BR; pipe_id <= PIPE_BV; pipe_id++) {
+ gpu_write(gpu, REG_A7XX_CP_APERTURE_CNTL_HOST,
+ A7XX_CP_APERTURE_CNTL_HOST_PIPE(pipe_id));
+ for (i = 0; i < dyn_pwrup_reglist->count; i++) {
+ if ((dyn_pwrup_reglist->regs[i].pipe & BIT(pipe_id)) == 0)
+ continue;
+ *dest++ = A7XX_CP_APERTURE_CNTL_HOST_PIPE(pipe_id);
+ *dest++ = dyn_pwrup_reglist->regs[i].offset;
+ *dest++ = gpu_read(gpu, dyn_pwrup_reglist->regs[i].offset);
+ dyn_pwrup_reglist_count++;
+ }
+ }
+ gpu_write(gpu, REG_A7XX_CP_APERTURE_CNTL_HOST,
+ A7XX_CP_APERTURE_CNTL_HOST_PIPE(PIPE_NONE));
+ }
+ lock->dynamic_list_len = dyn_pwrup_reglist_count;
}
static int a7xx_preempt_start(struct msm_gpu *gpu)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
index 6820216ec5fc..4eaa04711246 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
@@ -45,6 +45,7 @@ struct a6xx_info {
const struct adreno_reglist *hwcg;
const struct adreno_protect *protect;
const struct adreno_reglist_list *pwrup_reglist;
+ const struct adreno_reglist_pipe_list *dyn_pwrup_reglist;
const struct adreno_reglist_list *ifpc_reglist;
const struct adreno_reglist *gbif_cx;
const struct adreno_reglist_pipe *nonctxt_reglist;
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
index afc5f4aa3b17..747a22afad9f 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
@@ -454,11 +454,11 @@ void a6xx_preempt_init(struct msm_gpu *gpu)
gpu->vm, &a6xx_gpu->preempt_postamble_bo,
&a6xx_gpu->preempt_postamble_iova);
- preempt_prepare_postamble(a6xx_gpu);
-
if (IS_ERR(a6xx_gpu->preempt_postamble_ptr))
goto fail;
+ preempt_prepare_postamble(a6xx_gpu);
+
timer_setup(&a6xx_gpu->preempt_timer, a6xx_preempt_timer, 0);
return;
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index 0f8d3de97636..1d0145f8b3ec 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -188,6 +188,19 @@ static const struct adreno_reglist_list name = { \
.count = ARRAY_SIZE(name ## _regs), \
};
+struct adreno_reglist_pipe_list {
+ /** @reg: List of register **/
+ const struct adreno_reglist_pipe *regs;
+ /** @count: Number of registers in the list **/
+ u32 count;
+};
+
+#define DECLARE_ADRENO_REGLIST_PIPE_LIST(name) \
+static const struct adreno_reglist_pipe_list name = { \
+ .regs = name ## _regs, \
+ .count = ARRAY_SIZE(name ## _regs), \
+};
+
struct adreno_gpu {
struct msm_gpu base;
const struct adreno_info *info;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index c39f1908ea65..2d06c950e814 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -200,7 +200,7 @@ static int dpu_crtc_get_lm_crc(struct drm_crtc *crtc,
struct dpu_crtc_state *crtc_state)
{
struct dpu_crtc_mixer *m;
- u32 crcs[CRTC_QUAD_MIXERS];
+ u32 crcs[CRTC_DUAL_MIXERS];
int rc = 0;
int i;
@@ -1328,7 +1328,6 @@ static struct msm_display_topology dpu_crtc_get_topology(
struct drm_display_mode *mode = &crtc_state->adjusted_mode;
struct msm_display_topology topology = {0};
struct drm_encoder *drm_enc;
- u32 num_rt_intf;
drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask)
dpu_encoder_update_topology(drm_enc, &topology, crtc_state->state,
@@ -1342,14 +1341,11 @@ static struct msm_display_topology dpu_crtc_get_topology(
* Dual display
* 2 LM, 2 INTF ( Split display using 2 interfaces)
*
- * If DSC is enabled, try to use 4:4:2 topology if there is enough
- * resource. Otherwise, use 2:2:2 topology.
- *
* Single display
* 1 LM, 1 INTF
* 2 LM, 1 INTF (stream merge to support high resolution interfaces)
*
- * If DSC is enabled, use 2:2:1 topology
+ * If DSC is enabled, use 2 LMs for 2:2:1 topology
*
* Add dspps to the reservation requirements if ctm is requested
*
@@ -1361,23 +1357,14 @@ static struct msm_display_topology dpu_crtc_get_topology(
* (mode->hdisplay > MAX_HDISPLAY_SPLIT) check.
*/
- num_rt_intf = topology.num_intf;
- if (topology.cwb_enabled)
- num_rt_intf--;
-
- if (topology.num_dsc) {
- if (dpu_kms->catalog->dsc_count >= num_rt_intf * 2)
- topology.num_dsc = num_rt_intf * 2;
- else
- topology.num_dsc = num_rt_intf;
- topology.num_lm = topology.num_dsc;
- } else if (num_rt_intf == 2) {
+ if (topology.num_intf == 2 && !topology.cwb_enabled)
+ topology.num_lm = 2;
+ else if (topology.num_dsc == 2)
topology.num_lm = 2;
- } else if (dpu_kms->catalog->caps->has_3d_merge) {
+ else if (dpu_kms->catalog->caps->has_3d_merge)
topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1;
- } else {
+ else
topology.num_lm = 1;
- }
if (crtc_state->ctm)
topology.num_dspp = topology.num_lm;
@@ -1620,17 +1607,6 @@ int dpu_crtc_vblank(struct drm_crtc *crtc, bool en)
return 0;
}
-/**
- * dpu_crtc_get_num_lm - Get mixer number in this CRTC pipeline
- * @state: Pointer to drm crtc state object
- */
-unsigned int dpu_crtc_get_num_lm(const struct drm_crtc_state *state)
-{
- struct dpu_crtc_state *cstate = to_dpu_crtc_state(state);
-
- return cstate->num_mixers;
-}
-
#ifdef CONFIG_DEBUG_FS
static int _dpu_debugfs_status_show(struct seq_file *s, void *data)
{
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
index 455073c7025b..94392b9b9245 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
@@ -210,7 +210,7 @@ struct dpu_crtc_state {
bool bw_control;
bool bw_split_vote;
- struct drm_rect lm_bounds[CRTC_QUAD_MIXERS];
+ struct drm_rect lm_bounds[CRTC_DUAL_MIXERS];
uint64_t input_fence_timeout_ns;
@@ -218,10 +218,10 @@ struct dpu_crtc_state {
/* HW Resources reserved for the crtc */
u32 num_mixers;
- struct dpu_crtc_mixer mixers[CRTC_QUAD_MIXERS];
+ struct dpu_crtc_mixer mixers[CRTC_DUAL_MIXERS];
u32 num_ctls;
- struct dpu_hw_ctl *hw_ctls[CRTC_QUAD_MIXERS];
+ struct dpu_hw_ctl *hw_ctls[CRTC_DUAL_MIXERS];
enum dpu_crtc_crc_source crc_source;
int crc_frame_skip_count;
@@ -267,6 +267,4 @@ static inline enum dpu_crtc_client_type dpu_crtc_get_client_type(
void dpu_crtc_frame_event_cb(struct drm_crtc *crtc, u32 event);
-unsigned int dpu_crtc_get_num_lm(const struct drm_crtc_state *state);
-
#endif /* _DPU_CRTC_H_ */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index d1cfe81a3373..9f3957f24c6a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -55,7 +55,7 @@
#define MAX_PHYS_ENCODERS_PER_VIRTUAL \
(MAX_H_TILES_PER_DISPLAY * NUM_PHYS_ENCODER_TYPES)
-#define MAX_CHANNELS_PER_ENC 4
+#define MAX_CHANNELS_PER_ENC 2
#define MAX_CWB_PER_ENC 2
#define IDLE_SHORT_TIMEOUT 1
@@ -661,6 +661,7 @@ void dpu_encoder_update_topology(struct drm_encoder *drm_enc,
struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
struct msm_drm_private *priv = dpu_enc->base.dev->dev_private;
struct msm_display_info *disp_info = &dpu_enc->disp_info;
+ struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms);
struct drm_connector *connector;
struct drm_connector_state *conn_state;
struct drm_framebuffer *fb;
@@ -674,12 +675,22 @@ void dpu_encoder_update_topology(struct drm_encoder *drm_enc,
dsc = dpu_encoder_get_dsc_config(drm_enc);
- /*
- * Set DSC number as 1 to mark the enabled status, will be adjusted
- * in dpu_crtc_get_topology()
- */
- if (dsc)
- topology->num_dsc = 1;
+ /* We only support 2 DSC mode (with 2 LM and 1 INTF) */
+ if (dsc) {
+ /*
+ * Use 2 DSC encoders, 2 layer mixers and 1 or 2 interfaces
+ * when Display Stream Compression (DSC) is enabled,
+ * and when enough DSC blocks are available.
+ * This is power-optimal and can drive up to (including) 4k
+ * screens.
+ */
+ WARN(topology->num_intf > 2,
+ "DSC topology cannot support more than 2 interfaces\n");
+ if (topology->num_intf >= 2 || dpu_kms->catalog->dsc_count >= 2)
+ topology->num_dsc = 2;
+ else
+ topology->num_dsc = 1;
+ }
connector = drm_atomic_get_new_connector_for_encoder(state, drm_enc);
if (!connector)
@@ -2169,8 +2180,8 @@ static void dpu_encoder_helper_reset_mixers(struct dpu_encoder_phys *phys_enc)
{
int i, num_lm;
struct dpu_global_state *global_state;
- struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC];
- struct dpu_hw_mixer *hw_mixer[MAX_CHANNELS_PER_ENC];
+ struct dpu_hw_blk *hw_lm[2];
+ struct dpu_hw_mixer *hw_mixer[2];
struct dpu_hw_ctl *ctl = phys_enc->hw_ctl;
/* reset all mixers for this encoder */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
index 09395d7910ac..61b22d949454 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -302,7 +302,7 @@ static inline enum dpu_3d_blend_mode dpu_encoder_helper_get_3d_blend_mode(
/* Use merge_3d unless DSC MERGE topology is used */
if (phys_enc->split_role == ENC_ROLE_SOLO &&
- (dpu_cstate->num_mixers != 1) &&
+ dpu_cstate->num_mixers == CRTC_DUAL_MIXERS &&
!dpu_encoder_use_dsc_merge(phys_enc->parent))
return BLEND_3D_H_ROW_INT;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
index 46f348972a97..6d28f2281c76 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
@@ -247,14 +247,12 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
if (hw_cdm)
intf_cfg.cdm = hw_cdm->idx;
- if (phys_enc->hw_pp->merge_3d && phys_enc->hw_pp->merge_3d->ops.setup_3d_mode)
- phys_enc->hw_pp->merge_3d->ops.setup_3d_mode(phys_enc->hw_pp->merge_3d,
- mode_3d);
+ if (hw_pp && hw_pp->merge_3d && hw_pp->merge_3d->ops.setup_3d_mode)
+ hw_pp->merge_3d->ops.setup_3d_mode(hw_pp->merge_3d, mode_3d);
/* setup which pp blk will connect to this wb */
- if (hw_pp && phys_enc->hw_wb->ops.bind_pingpong_blk)
- phys_enc->hw_wb->ops.bind_pingpong_blk(phys_enc->hw_wb,
- phys_enc->hw_pp->idx);
+ if (hw_pp && hw_wb->ops.bind_pingpong_blk)
+ hw_wb->ops.bind_pingpong_blk(hw_wb, hw_pp->idx);
phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, &intf_cfg);
} else if (phys_enc->hw_ctl && phys_enc->hw_ctl->ops.setup_intf_cfg) {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
index 336757103b5a..4964e70610d1 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -24,7 +24,7 @@
#define DPU_MAX_IMG_WIDTH 0x3fff
#define DPU_MAX_IMG_HEIGHT 0x3fff
-#define CRTC_QUAD_MIXERS 4
+#define CRTC_DUAL_MIXERS 2
#define MAX_XIN_COUNT 16
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
index 6bb3476a05f8..75e6dae0fcd9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
@@ -89,13 +89,13 @@ enum dpu_hw_cdwn_op_mode_method_h_v {
*/
struct dpu_hw_cdm_ops {
/**
- * Enable the CDM module
+ * @enable: Enable the CDM module
* @cdm Pointer to chroma down context
*/
int (*enable)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
/**
- * Enable/disable the connection with pingpong
+ * @bind_pingpong_blk: Enable/disable the connection with pingpong
* @cdm Pointer to chroma down context
* @pp pingpong block id.
*/
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
index 15931b22ec94..e535bf013825 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
@@ -12,9 +12,9 @@
#include "dpu_hw_sspp.h"
/**
- * dpu_ctl_mode_sel: Interface mode selection
- * DPU_CTL_MODE_SEL_VID: Video mode interface
- * DPU_CTL_MODE_SEL_CMD: Command mode interface
+ * enum dpu_ctl_mode_sel: Interface mode selection
+ * @DPU_CTL_MODE_SEL_VID: Video mode interface
+ * @DPU_CTL_MODE_SEL_CMD: Command mode interface
*/
enum dpu_ctl_mode_sel {
DPU_CTL_MODE_SEL_VID = 0,
@@ -37,6 +37,7 @@ struct dpu_hw_stage_cfg {
* struct dpu_hw_intf_cfg :Describes how the DPU writes data to output interface
* @intf : Interface id
* @intf_master: Master interface id in the dual pipe topology
+ * @wb: Writeback mode
* @mode_3d: 3d mux configuration
* @merge_3d: 3d merge block used
* @intf_mode_sel: Interface mode, cmd / vid
@@ -64,21 +65,21 @@ struct dpu_hw_intf_cfg {
*/
struct dpu_hw_ctl_ops {
/**
- * kickoff hw operation for Sw controlled interfaces
+ * @trigger_start: kickoff hw operation for Sw controlled interfaces
* DSI cmd mode and WB interface are SW controlled
* @ctx : ctl path ctx pointer
*/
void (*trigger_start)(struct dpu_hw_ctl *ctx);
/**
- * check if the ctl is started
+ * @is_started: check if the ctl is started
* @ctx : ctl path ctx pointer
* @Return: true if started, false if stopped
*/
bool (*is_started)(struct dpu_hw_ctl *ctx);
/**
- * kickoff prepare is in progress hw operation for sw
+ * @trigger_pending: kickoff prepare is in progress hw operation for sw
* controlled interfaces: DSI cmd mode and WB interface
* are SW controlled
* @ctx : ctl path ctx pointer
@@ -86,7 +87,7 @@ struct dpu_hw_ctl_ops {
void (*trigger_pending)(struct dpu_hw_ctl *ctx);
/**
- * Clear the value of the cached pending_flush_mask
+ * @clear_pending_flush: Clear the value of the cached pending_flush_mask
* No effect on hardware.
* Required to be implemented.
* @ctx : ctl path ctx pointer
@@ -94,14 +95,15 @@ struct dpu_hw_ctl_ops {
void (*clear_pending_flush)(struct dpu_hw_ctl *ctx);
/**
- * Query the value of the cached pending_flush_mask
+ * @get_pending_flush: Query the value of the cached pending_flush_mask
* No effect on hardware
* @ctx : ctl path ctx pointer
*/
u32 (*get_pending_flush)(struct dpu_hw_ctl *ctx);
/**
- * OR in the given flushbits to the cached pending_flush_mask
+ * @update_pending_flush: OR in the given flushbits to the cached
+ * pending_flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @flushbits : module flushmask
@@ -110,7 +112,8 @@ struct dpu_hw_ctl_ops {
u32 flushbits);
/**
- * OR in the given flushbits to the cached pending_(wb_)flush_mask
+ * @update_pending_flush_wb: OR in the given flushbits to the
+ * cached pending_(wb_)flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @blk : writeback block index
@@ -119,7 +122,8 @@ struct dpu_hw_ctl_ops {
enum dpu_wb blk);
/**
- * OR in the given flushbits to the cached pending_(cwb_)flush_mask
+ * @update_pending_flush_cwb: OR in the given flushbits to the
+ * cached pending_(cwb_)flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @blk : concurrent writeback block index
@@ -128,7 +132,8 @@ struct dpu_hw_ctl_ops {
enum dpu_cwb blk);
/**
- * OR in the given flushbits to the cached pending_(intf_)flush_mask
+ * @update_pending_flush_intf: OR in the given flushbits to the
+ * cached pending_(intf_)flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @blk : interface block index
@@ -137,7 +142,8 @@ struct dpu_hw_ctl_ops {
enum dpu_intf blk);
/**
- * OR in the given flushbits to the cached pending_(periph_)flush_mask
+ * @update_pending_flush_periph: OR in the given flushbits to the
+ * cached pending_(periph_)flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @blk : interface block index
@@ -146,7 +152,8 @@ struct dpu_hw_ctl_ops {
enum dpu_intf blk);
/**
- * OR in the given flushbits to the cached pending_(merge_3d_)flush_mask
+ * @update_pending_flush_merge_3d: OR in the given flushbits to the
+ * cached pending_(merge_3d_)flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @blk : interface block index
@@ -155,7 +162,8 @@ struct dpu_hw_ctl_ops {
enum dpu_merge_3d blk);
/**
- * OR in the given flushbits to the cached pending_flush_mask
+ * @update_pending_flush_sspp: OR in the given flushbits to the
+ * cached pending_flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @blk : SSPP block index
@@ -164,7 +172,8 @@ struct dpu_hw_ctl_ops {
enum dpu_sspp blk);
/**
- * OR in the given flushbits to the cached pending_flush_mask
+ * @update_pending_flush_mixer: OR in the given flushbits to the
+ * cached pending_flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @blk : LM block index
@@ -173,7 +182,8 @@ struct dpu_hw_ctl_ops {
enum dpu_lm blk);
/**
- * OR in the given flushbits to the cached pending_flush_mask
+ * @update_pending_flush_dspp: OR in the given flushbits to the
+ * cached pending_flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @blk : DSPP block index
@@ -183,7 +193,8 @@ struct dpu_hw_ctl_ops {
enum dpu_dspp blk, u32 dspp_sub_blk);
/**
- * OR in the given flushbits to the cached pending_(dsc_)flush_mask
+ * @update_pending_flush_dsc: OR in the given flushbits to the
+ * cached pending_(dsc_)flush_mask.
* No effect on hardware
* @ctx: ctl path ctx pointer
* @blk: interface block index
@@ -192,7 +203,8 @@ struct dpu_hw_ctl_ops {
enum dpu_dsc blk);
/**
- * OR in the given flushbits to the cached pending_(cdm_)flush_mask
+ * @update_pending_flush_cdm: OR in the given flushbits to the
+ * cached pending_(cdm_)flush_mask.
* No effect on hardware
* @ctx: ctl path ctx pointer
* @cdm_num: idx of cdm to be flushed
@@ -200,20 +212,20 @@ struct dpu_hw_ctl_ops {
void (*update_pending_flush_cdm)(struct dpu_hw_ctl *ctx, enum dpu_cdm cdm_num);
/**
- * Write the value of the pending_flush_mask to hardware
+ * @trigger_flush: Write the value of the pending_flush_mask to hardware
* @ctx : ctl path ctx pointer
*/
void (*trigger_flush)(struct dpu_hw_ctl *ctx);
/**
- * Read the value of the flush register
+ * @get_flush_register: Read the value of the flush register
* @ctx : ctl path ctx pointer
* @Return: value of the ctl flush register.
*/
u32 (*get_flush_register)(struct dpu_hw_ctl *ctx);
/**
- * Setup ctl_path interface config
+ * @setup_intf_cfg: Setup ctl_path interface config
* @ctx
* @cfg : interface config structure pointer
*/
@@ -221,17 +233,20 @@ struct dpu_hw_ctl_ops {
struct dpu_hw_intf_cfg *cfg);
/**
- * reset ctl_path interface config
+ * @reset_intf_cfg: reset ctl_path interface config
* @ctx : ctl path ctx pointer
* @cfg : interface config structure pointer
*/
void (*reset_intf_cfg)(struct dpu_hw_ctl *ctx,
struct dpu_hw_intf_cfg *cfg);
+ /**
+ * @reset: reset function for this ctl type
+ */
int (*reset)(struct dpu_hw_ctl *c);
- /*
- * wait_reset_status - checks ctl reset status
+ /**
+ * @wait_reset_status: checks ctl reset status
* @ctx : ctl path ctx pointer
*
* This function checks the ctl reset status bit.
@@ -242,13 +257,13 @@ struct dpu_hw_ctl_ops {
int (*wait_reset_status)(struct dpu_hw_ctl *ctx);
/**
- * Set all blend stages to disabled
+ * @clear_all_blendstages: Set all blend stages to disabled
* @ctx : ctl path ctx pointer
*/
void (*clear_all_blendstages)(struct dpu_hw_ctl *ctx);
/**
- * Configure layer mixer to pipe configuration
+ * @setup_blendstage: Configure layer mixer to pipe configuration
* @ctx : ctl path ctx pointer
* @lm : layer mixer enumeration
* @cfg : blend stage configuration
@@ -256,11 +271,16 @@ struct dpu_hw_ctl_ops {
void (*setup_blendstage)(struct dpu_hw_ctl *ctx,
enum dpu_lm lm, struct dpu_hw_stage_cfg *cfg);
+ /**
+ * @set_active_fetch_pipes: Set active pipes attached to this CTL
+ * @ctx: ctl path ctx pointer
+ * @active_pipes: bitmap of enum dpu_sspp
+ */
void (*set_active_fetch_pipes)(struct dpu_hw_ctl *ctx,
unsigned long *fetch_active);
/**
- * Set active pipes attached to this CTL
+ * @set_active_pipes: Set active pipes attached to this CTL
* @ctx: ctl path ctx pointer
* @active_pipes: bitmap of enum dpu_sspp
*/
@@ -268,13 +288,12 @@ struct dpu_hw_ctl_ops {
unsigned long *active_pipes);
/**
- * Set active layer mixers attached to this CTL
+ * @set_active_lms: Set active layer mixers attached to this CTL
* @ctx: ctl path ctx pointer
* @active_lms: bitmap of enum dpu_lm
*/
void (*set_active_lms)(struct dpu_hw_ctl *ctx,
unsigned long *active_lms);
-
};
/**
@@ -289,6 +308,9 @@ struct dpu_hw_ctl_ops {
* @pending_intf_flush_mask: pending INTF flush
* @pending_wb_flush_mask: pending WB flush
* @pending_cwb_flush_mask: pending CWB flush
+ * @pending_periph_flush_mask: pending PERIPH flush
+ * @pending_merge_3d_flush_mask: pending MERGE 3D flush
+ * @pending_dspp_flush_mask: pending DSPP flush
* @pending_dsc_flush_mask: pending DSC flush
* @pending_cdm_flush_mask: pending CDM flush
* @mdss_ver: MDSS revision information
@@ -320,7 +342,7 @@ struct dpu_hw_ctl {
};
/**
- * dpu_hw_ctl - convert base object dpu_hw_base to container
+ * to_dpu_hw_ctl - convert base object dpu_hw_base to container
* @hw: Pointer to base hardware block
* return: Pointer to hardware block container
*/
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.h
index 96b6edf6b2bb..ed7bfcee7f1c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.h
@@ -28,7 +28,6 @@ struct dpu_hw_cwb_setup_cfg {
};
/**
- *
* struct dpu_hw_cwb_ops : Interface to the cwb hw driver functions
* @config_cwb: configure CWB mux
*/
@@ -54,7 +53,7 @@ struct dpu_hw_cwb {
};
/**
- * dpu_hw_cwb - convert base object dpu_hw_base to container
+ * to_dpu_hw_cwb - convert base object dpu_hw_base to container
* @hw: Pointer to base hardware block
* return: Pointer to hardware block container
*/
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
index cc7cc6f6f7cd..39d93b9df051 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
@@ -21,13 +21,13 @@ struct dpu_hw_dsc;
*/
struct dpu_hw_dsc_ops {
/**
- * dsc_disable - disable dsc
+ * @dsc_disable: disable dsc
* @hw_dsc: Pointer to dsc context
*/
void (*dsc_disable)(struct dpu_hw_dsc *hw_dsc);
/**
- * dsc_config - configures dsc encoder
+ * @dsc_config: configures dsc encoder
* @hw_dsc: Pointer to dsc context
* @dsc: panel dsc parameters
* @mode: dsc topology mode to be set
@@ -39,13 +39,17 @@ struct dpu_hw_dsc_ops {
u32 initial_lines);
/**
- * dsc_config_thresh - programs panel thresholds
+ * @dsc_config_thresh: programs panel thresholds
* @hw_dsc: Pointer to dsc context
* @dsc: panel dsc parameters
*/
void (*dsc_config_thresh)(struct dpu_hw_dsc *hw_dsc,
struct drm_dsc_config *dsc);
+ /**
+ * @dsc_bind_pingpong_blk: binds pixel output from a DSC block
+ * to a pingpong block
+ */
void (*dsc_bind_pingpong_blk)(struct dpu_hw_dsc *hw_dsc,
enum dpu_pingpong pp);
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h
index 45c26cd49fa3..722b0f482e9b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h
@@ -22,7 +22,7 @@ struct dpu_hw_pcc_coeff {
};
/**
- * struct dpu_hw_pcc - pcc feature structure
+ * struct dpu_hw_pcc_cfg - pcc feature structure
* @r: red coefficients.
* @g: green coefficients.
* @b: blue coefficients.
@@ -40,7 +40,7 @@ struct dpu_hw_pcc_cfg {
*/
struct dpu_hw_dspp_ops {
/**
- * setup_pcc - setup dspp pcc
+ * @setup_pcc: setup_pcc - setup dspp pcc
* @ctx: Pointer to dspp context
* @cfg: Pointer to configuration
*/
@@ -69,7 +69,7 @@ struct dpu_hw_dspp {
};
/**
- * dpu_hw_dspp - convert base object dpu_hw_base to container
+ * to_dpu_hw_dspp - convert base object dpu_hw_base to container
* @hw: Pointer to base hardware block
* return: Pointer to hardware block container
*/
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
index f31067a9aaf1..5a19cd74fa94 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
@@ -57,11 +57,11 @@ struct dpu_hw_intf_cmd_mode_cfg {
/**
* struct dpu_hw_intf_ops : Interface to the interface Hw driver functions
* Assumption is these functions will be called after clocks are enabled
- * @ setup_timing_gen : programs the timing engine
- * @ setup_prog_fetch : enables/disables the programmable fetch logic
- * @ enable_timing: enable/disable timing engine
- * @ get_status: returns if timing engine is enabled or not
- * @ get_line_count: reads current vertical line counter
+ * @setup_timing_gen : programs the timing engine
+ * @setup_prg_fetch : enables/disables the programmable fetch logic
+ * @enable_timing: enable/disable timing engine
+ * @get_status: returns if timing engine is enabled or not
+ * @get_line_count: reads current vertical line counter
* @bind_pingpong_blk: enable/disable the connection with pingpong which will
* feed pixels to this interface
* @setup_misr: enable/disable MISR
@@ -70,12 +70,9 @@ struct dpu_hw_intf_cmd_mode_cfg {
* pointer and programs the tear check configuration
* @disable_tearcheck: Disables tearcheck block
* @connect_external_te: Read, modify, write to either set or clear listening to external TE
- * Return: 1 if TE was originally connected, 0 if not, or -ERROR
- * @get_vsync_info: Provides the programmed and current line_count
- * @setup_autorefresh: Configure and enable the autorefresh config
- * @get_autorefresh: Retrieve autorefresh config from hardware
- * Return: 0 on success, -ETIMEDOUT on timeout
+ * Returns 1 if TE was originally connected, 0 if not, or -ERROR
* @vsync_sel: Select vsync signal for tear-effect configuration
+ * @disable_autorefresh: Disable autorefresh if enabled
* @program_intf_cmd_cfg: Program the DPU to interface datapath for command mode
*/
struct dpu_hw_intf_ops {
@@ -109,9 +106,6 @@ struct dpu_hw_intf_ops {
void (*vsync_sel)(struct dpu_hw_intf *intf, enum dpu_vsync_source vsync_source);
- /**
- * Disable autorefresh if enabled
- */
void (*disable_autorefresh)(struct dpu_hw_intf *intf, uint32_t encoder_id, u16 vdisplay);
void (*program_intf_cmd_cfg)(struct dpu_hw_intf *intf,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h
index 1b9ecd082d7f..ecbb77711d83 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h
@@ -25,39 +25,38 @@ struct dpu_hw_color3_cfg {
};
/**
- *
* struct dpu_hw_lm_ops : Interface to the mixer Hw driver functions
* Assumption is these functions will be called after clocks are enabled
*/
struct dpu_hw_lm_ops {
- /*
- * Sets up mixer output width and height
+ /**
+ * @setup_mixer_out: Sets up mixer output width and height
* and border color if enabled
*/
void (*setup_mixer_out)(struct dpu_hw_mixer *ctx,
struct dpu_hw_mixer_cfg *cfg);
- /*
- * Alpha blending configuration
+ /**
+ * @setup_blend_config: Alpha blending configuration
* for the specified stage
*/
void (*setup_blend_config)(struct dpu_hw_mixer *ctx, uint32_t stage,
uint32_t fg_alpha, uint32_t bg_alpha, uint32_t blend_op);
- /*
- * Alpha color component selection from either fg or bg
+ /**
+ * @setup_alpha_out: Alpha color component selection from either fg or bg
*/
void (*setup_alpha_out)(struct dpu_hw_mixer *ctx, uint32_t mixer_op);
/**
- * Clear layer mixer to pipe configuration
+ * @clear_all_blendstages: Clear layer mixer to pipe configuration
* @ctx : mixer ctx pointer
* Returns: 0 on success or -error
*/
int (*clear_all_blendstages)(struct dpu_hw_mixer *ctx);
/**
- * Configure layer mixer to pipe configuration
+ * @setup_blendstage: Configure layer mixer to pipe configuration
* @ctx : mixer ctx pointer
* @lm : layer mixer enumeration
* @stage_cfg : blend stage configuration
@@ -67,19 +66,19 @@ struct dpu_hw_lm_ops {
struct dpu_hw_stage_cfg *stage_cfg);
/**
- * setup_border_color : enable/disable border color
+ * @setup_border_color : enable/disable border color
*/
void (*setup_border_color)(struct dpu_hw_mixer *ctx,
struct dpu_mdss_color *color,
u8 border_en);
/**
- * setup_misr: Enable/disable MISR
+ * @setup_misr: Enable/disable MISR
*/
void (*setup_misr)(struct dpu_hw_mixer *ctx);
/**
- * collect_misr: Read MISR signature
+ * @collect_misr: Read MISR signature
*/
int (*collect_misr)(struct dpu_hw_mixer *ctx, u32 *misr_value);
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
index 31451241f083..046b683d4c66 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
@@ -34,7 +34,7 @@
#define DPU_MAX_PLANES 4
#endif
-#define STAGES_PER_PLANE 2
+#define STAGES_PER_PLANE 1
#define PIPES_PER_STAGE 2
#define PIPES_PER_PLANE (PIPES_PER_STAGE * STAGES_PER_PLANE)
#ifndef DPU_MAX_DE_CURVES
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h
index 6833c0207523..b57f88187148 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h
@@ -12,7 +12,6 @@
struct dpu_hw_merge_3d;
/**
- *
* struct dpu_hw_merge_3d_ops : Interface to the merge_3d Hw driver functions
* Assumption is these functions will be called after clocks are enabled
* @setup_3d_mode : enable 3D merge
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
index dd99e1c21a1e..effd012d864a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
@@ -34,7 +34,6 @@ struct dpu_hw_dither_cfg {
};
/**
- *
* struct dpu_hw_pingpong_ops : Interface to the pingpong Hw driver functions
* Assumption is these functions will be called after clocks are enabled
* @enable_tearcheck: program and enable tear check block
@@ -44,51 +43,52 @@ struct dpu_hw_dither_cfg {
*/
struct dpu_hw_pingpong_ops {
/**
- * enables vysnc generation and sets up init value of
+ * @enable_tearcheck: enables vysnc generation and sets up init value of
* read pointer and programs the tear check cofiguration
*/
int (*enable_tearcheck)(struct dpu_hw_pingpong *pp,
struct dpu_hw_tear_check *cfg);
/**
- * disables tear check block
+ * @disable_tearcheck: disables tear check block
*/
int (*disable_tearcheck)(struct dpu_hw_pingpong *pp);
/**
- * read, modify, write to either set or clear listening to external TE
+ * @connect_external_te: read, modify, write to either set or clear
+ * listening to external TE
* @Return: 1 if TE was originally connected, 0 if not, or -ERROR
*/
int (*connect_external_te)(struct dpu_hw_pingpong *pp,
bool enable_external_te);
/**
- * Obtain current vertical line counter
+ * @get_line_count: Obtain current vertical line counter
*/
u32 (*get_line_count)(struct dpu_hw_pingpong *pp);
/**
- * Disable autorefresh if enabled
+ * @disable_autorefresh: Disable autorefresh if enabled
*/
void (*disable_autorefresh)(struct dpu_hw_pingpong *pp, uint32_t encoder_id, u16 vdisplay);
/**
- * Setup dither matix for pingpong block
+ * @setup_dither: Setup dither matix for pingpong block
*/
void (*setup_dither)(struct dpu_hw_pingpong *pp,
struct dpu_hw_dither_cfg *cfg);
/**
- * Enable DSC
+ * @enable_dsc: Enable DSC
*/
int (*enable_dsc)(struct dpu_hw_pingpong *pp);
/**
- * Disable DSC
+ * @disable_dsc: Disable DSC
*/
void (*disable_dsc)(struct dpu_hw_pingpong *pp);
/**
- * Setup DSC
+ * @setup_dsc: Setup DSC
*/
int (*setup_dsc)(struct dpu_hw_pingpong *pp);
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
index bdac5c04bf79..3822094f85bc 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
@@ -14,7 +14,7 @@ struct dpu_hw_sspp;
#define DPU_SSPP_MAX_PITCH_SIZE 0xffff
-/**
+/*
* Flags
*/
#define DPU_SSPP_FLIP_LR BIT(0)
@@ -23,7 +23,7 @@ struct dpu_hw_sspp;
#define DPU_SSPP_ROT_90 BIT(3)
#define DPU_SSPP_SOLID_FILL BIT(4)
-/**
+/*
* Component indices
*/
enum {
@@ -36,9 +36,10 @@ enum {
};
/**
- * DPU_SSPP_RECT_SOLO - multirect disabled
- * DPU_SSPP_RECT_0 - rect0 of a multirect pipe
- * DPU_SSPP_RECT_1 - rect1 of a multirect pipe
+ * enum dpu_sspp_multirect_index - multirect mode
+ * @DPU_SSPP_RECT_SOLO: multirect disabled
+ * @DPU_SSPP_RECT_0: rect0 of a multirect pipe
+ * @DPU_SSPP_RECT_1: rect1 of a multirect pipe
*
* Note: HW supports multirect with either RECT0 or
* RECT1. Considering no benefit of such configs over
@@ -143,7 +144,7 @@ struct dpu_hw_pixel_ext {
* struct dpu_sw_pipe_cfg : software pipe configuration
* @src_rect: src ROI, caller takes into account the different operations
* such as decimation, flip etc to program this field
- * @dest_rect: destination ROI.
+ * @dst_rect: destination ROI.
* @rotation: simplified drm rotation hint
*/
struct dpu_sw_pipe_cfg {
@@ -165,8 +166,8 @@ struct dpu_hw_pipe_ts_cfg {
/**
* struct dpu_sw_pipe - software pipe description
* @sspp: backing SSPP pipe
- * @index: index of the rectangle of SSPP
- * @mode: parallel or time multiplex multirect mode
+ * @multirect_index: index of the rectangle of SSPP
+ * @multirect_mode: parallel or time multiplex multirect mode
*/
struct dpu_sw_pipe {
struct dpu_hw_sspp *sspp;
@@ -181,7 +182,7 @@ struct dpu_sw_pipe {
*/
struct dpu_hw_sspp_ops {
/**
- * setup_format - setup pixel format cropping rectangle, flip
+ * @setup_format: setup pixel format cropping rectangle, flip
* @pipe: Pointer to software pipe context
* @cfg: Pointer to pipe config structure
* @flags: Extra flags for format config
@@ -190,7 +191,7 @@ struct dpu_hw_sspp_ops {
const struct msm_format *fmt, u32 flags);
/**
- * setup_rects - setup pipe ROI rectangles
+ * @setup_rects: setup pipe ROI rectangles
* @pipe: Pointer to software pipe context
* @cfg: Pointer to pipe config structure
*/
@@ -198,7 +199,7 @@ struct dpu_hw_sspp_ops {
struct dpu_sw_pipe_cfg *cfg);
/**
- * setup_pe - setup pipe pixel extension
+ * @setup_pe: setup pipe pixel extension
* @ctx: Pointer to pipe context
* @pe_ext: Pointer to pixel ext settings
*/
@@ -206,7 +207,7 @@ struct dpu_hw_sspp_ops {
struct dpu_hw_pixel_ext *pe_ext);
/**
- * setup_sourceaddress - setup pipe source addresses
+ * @setup_sourceaddress: setup pipe source addresses
* @pipe: Pointer to software pipe context
* @layout: format layout information for programming buffer to hardware
*/
@@ -214,14 +215,14 @@ struct dpu_hw_sspp_ops {
struct dpu_hw_fmt_layout *layout);
/**
- * setup_csc - setup color space coversion
+ * @setup_csc: setup color space coversion
* @ctx: Pointer to pipe context
* @data: Pointer to config structure
*/
void (*setup_csc)(struct dpu_hw_sspp *ctx, const struct dpu_csc_cfg *data);
/**
- * setup_solidfill - enable/disable colorfill
+ * @setup_solidfill: enable/disable colorfill
* @pipe: Pointer to software pipe context
* @const_color: Fill color value
* @flags: Pipe flags
@@ -229,23 +230,22 @@ struct dpu_hw_sspp_ops {
void (*setup_solidfill)(struct dpu_sw_pipe *pipe, u32 color);
/**
- * setup_multirect - setup multirect configuration
+ * @setup_multirect: setup multirect configuration
* @pipe: Pointer to software pipe context
*/
void (*setup_multirect)(struct dpu_sw_pipe *pipe);
/**
- * setup_sharpening - setup sharpening
+ * @setup_sharpening: setup sharpening
* @ctx: Pointer to pipe context
* @cfg: Pointer to config structure
*/
void (*setup_sharpening)(struct dpu_hw_sspp *ctx,
struct dpu_hw_sharp_cfg *cfg);
-
/**
- * setup_qos_lut - setup QoS LUTs
+ * @setup_qos_lut: setup QoS LUTs
* @ctx: Pointer to pipe context
* @cfg: LUT configuration
*/
@@ -253,7 +253,7 @@ struct dpu_hw_sspp_ops {
struct dpu_hw_qos_cfg *cfg);
/**
- * setup_qos_ctrl - setup QoS control
+ * @setup_qos_ctrl: setup QoS control
* @ctx: Pointer to pipe context
* @danger_safe_en: flags controlling enabling of danger/safe QoS/LUT
*/
@@ -261,7 +261,7 @@ struct dpu_hw_sspp_ops {
bool danger_safe_en);
/**
- * setup_clk_force_ctrl - setup clock force control
+ * @setup_clk_force_ctrl: setup clock force control
* @ctx: Pointer to pipe context
* @enable: enable clock force if true
*/
@@ -269,7 +269,7 @@ struct dpu_hw_sspp_ops {
bool enable);
/**
- * setup_histogram - setup histograms
+ * @setup_histogram: setup histograms
* @ctx: Pointer to pipe context
* @cfg: Pointer to histogram configuration
*/
@@ -277,7 +277,7 @@ struct dpu_hw_sspp_ops {
void *cfg);
/**
- * setup_scaler - setup scaler
+ * @setup_scaler: setup scaler
* @scaler3_cfg: Pointer to scaler configuration
* @format: pixel format parameters
*/
@@ -286,7 +286,7 @@ struct dpu_hw_sspp_ops {
const struct msm_format *format);
/**
- * setup_cdp - setup client driven prefetch
+ * @setup_cdp: setup client driven prefetch
* @pipe: Pointer to software pipe context
* @fmt: format used by the sw pipe
* @enable: whether the CDP should be enabled for this pipe
@@ -303,6 +303,7 @@ struct dpu_hw_sspp_ops {
* @ubwc: UBWC configuration data
* @idx: pipe index
* @cap: pointer to layer_cfg
+ * @mdss_ver: MDSS version info to use for feature checks
* @ops: pointer to operations possible for this pipe
*/
struct dpu_hw_sspp {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h
index 04efdcd21ceb..80279d87c2cd 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h
@@ -77,12 +77,11 @@ enum dpu_dp_phy_sel {
/**
* struct dpu_hw_mdp_ops - interface to the MDP TOP Hw driver functions
* Assumption is these functions will be called after clocks are enabled.
- * @setup_split_pipe : Programs the pipe control registers
- * @setup_pp_split : Programs the pp split control registers
- * @setup_traffic_shaper : programs traffic shaper control
*/
struct dpu_hw_mdp_ops {
- /** setup_split_pipe() : Registers are not double buffered, thisk
+ /**
+ * @setup_split_pipe : Programs the pipe control registers.
+ * Registers are not double buffered, this
* function should be called before timing control enable
* @mdp : mdp top context driver
* @cfg : upper and lower part of pipe configuration
@@ -91,7 +90,7 @@ struct dpu_hw_mdp_ops {
struct split_pipe_cfg *p);
/**
- * setup_traffic_shaper() : Setup traffic shaper control
+ * @setup_traffic_shaper : programs traffic shaper control.
* @mdp : mdp top context driver
* @cfg : traffic shaper configuration
*/
@@ -99,7 +98,7 @@ struct dpu_hw_mdp_ops {
struct traffic_shaper_cfg *cfg);
/**
- * setup_clk_force_ctrl - set clock force control
+ * @setup_clk_force_ctrl: set clock force control
* @mdp: mdp top context driver
* @clk_ctrl: clock to be controlled
* @enable: force on enable
@@ -109,7 +108,7 @@ struct dpu_hw_mdp_ops {
enum dpu_clk_ctrl_type clk_ctrl, bool enable);
/**
- * get_danger_status - get danger status
+ * @get_danger_status: get danger status
* @mdp: mdp top context driver
* @status: Pointer to danger safe status
*/
@@ -117,7 +116,7 @@ struct dpu_hw_mdp_ops {
struct dpu_danger_safe_status *status);
/**
- * setup_vsync_source - setup vsync source configuration details
+ * @setup_vsync_source: setup vsync source configuration details
* @mdp: mdp top context driver
* @cfg: vsync source selection configuration
*/
@@ -125,7 +124,7 @@ struct dpu_hw_mdp_ops {
struct dpu_vsync_source_cfg *cfg);
/**
- * get_safe_status - get safe status
+ * @get_safe_status: get safe status
* @mdp: mdp top context driver
* @status: Pointer to danger safe status
*/
@@ -133,14 +132,14 @@ struct dpu_hw_mdp_ops {
struct dpu_danger_safe_status *status);
/**
- * dp_phy_intf_sel - configure intf to phy mapping
+ * @dp_phy_intf_sel: configure intf to phy mapping
* @mdp: mdp top context driver
* @phys: list of phys the DP interfaces should be connected to. 0 disables the INTF.
*/
void (*dp_phy_intf_sel)(struct dpu_hw_mdp *mdp, enum dpu_dp_phy_sel phys[2]);
/**
- * intf_audio_select - select the external interface for audio
+ * @intf_audio_select: select the external interface for audio
* @mdp: mdp top context driver
*/
void (*intf_audio_select)(struct dpu_hw_mdp *mdp);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h
index 285121ec804c..9ac49448e432 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h
@@ -17,7 +17,7 @@ struct dpu_hw_vbif;
*/
struct dpu_hw_vbif_ops {
/**
- * set_limit_conf - set transaction limit config
+ * @set_limit_conf: set transaction limit config
* @vbif: vbif context driver
* @xin_id: client interface identifier
* @rd: true for read limit; false for write limit
@@ -27,7 +27,7 @@ struct dpu_hw_vbif_ops {
u32 xin_id, bool rd, u32 limit);
/**
- * get_limit_conf - get transaction limit config
+ * @get_limit_conf: get transaction limit config
* @vbif: vbif context driver
* @xin_id: client interface identifier
* @rd: true for read limit; false for write limit
@@ -37,7 +37,7 @@ struct dpu_hw_vbif_ops {
u32 xin_id, bool rd);
/**
- * set_halt_ctrl - set halt control
+ * @set_halt_ctrl: set halt control
* @vbif: vbif context driver
* @xin_id: client interface identifier
* @enable: halt control enable
@@ -46,7 +46,7 @@ struct dpu_hw_vbif_ops {
u32 xin_id, bool enable);
/**
- * get_halt_ctrl - get halt control
+ * @get_halt_ctrl: get halt control
* @vbif: vbif context driver
* @xin_id: client interface identifier
* @return: halt control enable
@@ -55,7 +55,7 @@ struct dpu_hw_vbif_ops {
u32 xin_id);
/**
- * set_qos_remap - set QoS priority remap
+ * @set_qos_remap: set QoS priority remap
* @vbif: vbif context driver
* @xin_id: client interface identifier
* @level: priority level
@@ -65,7 +65,7 @@ struct dpu_hw_vbif_ops {
u32 xin_id, u32 level, u32 remap_level);
/**
- * set_mem_type - set memory type
+ * @set_mem_type: set memory type
* @vbif: vbif context driver
* @xin_id: client interface identifier
* @value: memory type value
@@ -74,7 +74,7 @@ struct dpu_hw_vbif_ops {
u32 xin_id, u32 value);
/**
- * clear_errors - clear any vbif errors
+ * @clear_errors: clear any vbif errors
* This function clears any detected pending/source errors
* on the VBIF interface, and optionally returns the detected
* error mask(s).
@@ -86,7 +86,7 @@ struct dpu_hw_vbif_ops {
u32 *pnd_errors, u32 *src_errors);
/**
- * set_write_gather_en - set write_gather enable
+ * @set_write_gather_en: set write_gather enable
* @vbif: vbif context driver
* @xin_id: client interface identifier
*/
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h
index ee5e5ab786e1..cfdbb5bb2a0f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h
@@ -22,11 +22,11 @@ struct dpu_hw_wb_cfg {
};
/**
- *
* struct dpu_hw_wb_ops : Interface to the wb hw driver functions
* Assumption is these functions will be called after clocks are enabled
* @setup_outaddress: setup output address from the writeback job
* @setup_outformat: setup output format of writeback block from writeback job
+ * @setup_roi: setup ROI (Region of Interest) parameters
* @setup_qos_lut: setup qos LUT for writeback block based on input
* @setup_cdp: setup chroma down prefetch block for writeback block
* @setup_clk_force_ctrl: setup clock force control
@@ -61,7 +61,7 @@ struct dpu_hw_wb_ops {
* struct dpu_hw_wb : WB driver object
* @hw: block hardware details
* @idx: hardware index number within type
- * @wb_hw_caps: hardware capabilities
+ * @caps: hardware capabilities
* @ops: function pointers
*/
struct dpu_hw_wb {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index d07a6ab6e7ee..9b7a8b46bfa9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -826,12 +826,8 @@ static int dpu_plane_atomic_check_nosspp(struct drm_plane *plane,
struct dpu_plane_state *pstate = to_dpu_plane_state(new_plane_state);
struct dpu_sw_pipe_cfg *pipe_cfg;
struct dpu_sw_pipe_cfg *r_pipe_cfg;
- struct dpu_sw_pipe_cfg init_pipe_cfg;
struct drm_rect fb_rect = { 0 };
- const struct drm_display_mode *mode = &crtc_state->adjusted_mode;
uint32_t max_linewidth;
- u32 num_lm;
- int stage_id, num_stages;
min_scale = FRAC_16_16(1, MAX_UPSCALE_RATIO);
max_scale = MAX_DOWNSCALE_RATIO << 16;
@@ -854,10 +850,13 @@ static int dpu_plane_atomic_check_nosspp(struct drm_plane *plane,
return -EINVAL;
}
- num_lm = dpu_crtc_get_num_lm(crtc_state);
-
+ /* move the assignment here, to ease handling to another pairs later */
+ pipe_cfg = &pstate->pipe_cfg[0];
+ r_pipe_cfg = &pstate->pipe_cfg[1];
/* state->src is 16.16, src_rect is not */
- drm_rect_fp_to_int(&init_pipe_cfg.src_rect, &new_plane_state->src);
+ drm_rect_fp_to_int(&pipe_cfg->src_rect, &new_plane_state->src);
+
+ pipe_cfg->dst_rect = new_plane_state->dst;
fb_rect.x2 = new_plane_state->fb->width;
fb_rect.y2 = new_plane_state->fb->height;
@@ -882,94 +881,35 @@ static int dpu_plane_atomic_check_nosspp(struct drm_plane *plane,
max_linewidth = pdpu->catalog->caps->max_linewidth;
- drm_rect_rotate(&init_pipe_cfg.src_rect,
+ drm_rect_rotate(&pipe_cfg->src_rect,
new_plane_state->fb->width, new_plane_state->fb->height,
new_plane_state->rotation);
- /*
- * We have 1 mixer pair cfg for 1:1:1 and 2:2:1 topology, 2 mixer pair
- * configs for left and right half screen in case of 4:4:2 topology.
- * But we may have 2 rect to split wide plane that exceeds limit with 1
- * config for 2:2:1. So need to handle both wide plane splitting, and
- * two halves of screen splitting for quad-pipe case. Check dest
- * rectangle left/right clipping first, then check wide rectangle
- * splitting in every half next.
- */
- num_stages = (num_lm + 1) / 2;
- /* iterate mixer configs for this plane, to separate left/right with the id */
- for (stage_id = 0; stage_id < num_stages; stage_id++) {
- struct drm_rect mixer_rect = {
- .x1 = stage_id * mode->hdisplay / num_stages,
- .y1 = 0,
- .x2 = (stage_id + 1) * mode->hdisplay / num_stages,
- .y2 = mode->vdisplay
- };
- int cfg_idx = stage_id * PIPES_PER_STAGE;
-
- pipe_cfg = &pstate->pipe_cfg[cfg_idx];
- r_pipe_cfg = &pstate->pipe_cfg[cfg_idx + 1];
-
- drm_rect_fp_to_int(&pipe_cfg->src_rect, &new_plane_state->src);
- pipe_cfg->dst_rect = new_plane_state->dst;
-
- DPU_DEBUG_PLANE(pdpu, "checking src " DRM_RECT_FMT
- " vs clip window " DRM_RECT_FMT "\n",
- DRM_RECT_ARG(&pipe_cfg->src_rect),
- DRM_RECT_ARG(&mixer_rect));
-
- /*
- * If this plane does not fall into mixer rect, check next
- * mixer rect.
- */
- if (!drm_rect_clip_scaled(&pipe_cfg->src_rect,
- &pipe_cfg->dst_rect,
- &mixer_rect)) {
- memset(pipe_cfg, 0, 2 * sizeof(struct dpu_sw_pipe_cfg));
-
- continue;
+ if ((drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) ||
+ _dpu_plane_calc_clk(&crtc_state->adjusted_mode, pipe_cfg) > max_mdp_clk_rate) {
+ if (drm_rect_width(&pipe_cfg->src_rect) > 2 * max_linewidth) {
+ DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u\n",
+ DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth);
+ return -E2BIG;
}
- pipe_cfg->dst_rect.x1 -= mixer_rect.x1;
- pipe_cfg->dst_rect.x2 -= mixer_rect.x1;
-
- DPU_DEBUG_PLANE(pdpu, "Got clip src:" DRM_RECT_FMT " dst: " DRM_RECT_FMT "\n",
- DRM_RECT_ARG(&pipe_cfg->src_rect), DRM_RECT_ARG(&pipe_cfg->dst_rect));
-
- /* Split wide rect into 2 rect */
- if ((drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) ||
- _dpu_plane_calc_clk(mode, pipe_cfg) > max_mdp_clk_rate) {
-
- if (drm_rect_width(&pipe_cfg->src_rect) > 2 * max_linewidth) {
- DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u\n",
- DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth);
- return -E2BIG;
- }
-
- memcpy(r_pipe_cfg, pipe_cfg, sizeof(struct dpu_sw_pipe_cfg));
- pipe_cfg->src_rect.x2 = (pipe_cfg->src_rect.x1 + pipe_cfg->src_rect.x2) >> 1;
- pipe_cfg->dst_rect.x2 = (pipe_cfg->dst_rect.x1 + pipe_cfg->dst_rect.x2) >> 1;
- r_pipe_cfg->src_rect.x1 = pipe_cfg->src_rect.x2;
- r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2;
- DPU_DEBUG_PLANE(pdpu, "Split wide plane into:"
- DRM_RECT_FMT " and " DRM_RECT_FMT "\n",
- DRM_RECT_ARG(&pipe_cfg->src_rect),
- DRM_RECT_ARG(&r_pipe_cfg->src_rect));
- } else {
- memset(r_pipe_cfg, 0, sizeof(struct dpu_sw_pipe_cfg));
- }
+ *r_pipe_cfg = *pipe_cfg;
+ pipe_cfg->src_rect.x2 = (pipe_cfg->src_rect.x1 + pipe_cfg->src_rect.x2) >> 1;
+ pipe_cfg->dst_rect.x2 = (pipe_cfg->dst_rect.x1 + pipe_cfg->dst_rect.x2) >> 1;
+ r_pipe_cfg->src_rect.x1 = pipe_cfg->src_rect.x2;
+ r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2;
+ } else {
+ memset(r_pipe_cfg, 0, sizeof(*r_pipe_cfg));
+ }
- drm_rect_rotate_inv(&pipe_cfg->src_rect,
- new_plane_state->fb->width,
- new_plane_state->fb->height,
+ drm_rect_rotate_inv(&pipe_cfg->src_rect,
+ new_plane_state->fb->width, new_plane_state->fb->height,
+ new_plane_state->rotation);
+ if (drm_rect_width(&r_pipe_cfg->src_rect) != 0)
+ drm_rect_rotate_inv(&r_pipe_cfg->src_rect,
+ new_plane_state->fb->width, new_plane_state->fb->height,
new_plane_state->rotation);
- if (drm_rect_width(&r_pipe_cfg->src_rect) != 0)
- drm_rect_rotate_inv(&r_pipe_cfg->src_rect,
- new_plane_state->fb->width,
- new_plane_state->fb->height,
- new_plane_state->rotation);
- }
-
pstate->needs_qos_remap = drm_atomic_crtc_needs_modeset(crtc_state);
return 0;
@@ -1045,17 +985,20 @@ static int dpu_plane_atomic_check_sspp(struct drm_plane *plane,
drm_atomic_get_new_plane_state(state, plane);
struct dpu_plane *pdpu = to_dpu_plane(plane);
struct dpu_plane_state *pstate = to_dpu_plane_state(new_plane_state);
- struct dpu_sw_pipe *pipe;
- struct dpu_sw_pipe_cfg *pipe_cfg;
- int ret = 0, i;
+ struct dpu_sw_pipe *pipe = &pstate->pipe[0];
+ struct dpu_sw_pipe *r_pipe = &pstate->pipe[1];
+ struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg[0];
+ struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->pipe_cfg[1];
+ int ret = 0;
- for (i = 0; i < PIPES_PER_PLANE; i++) {
- pipe = &pstate->pipe[i];
- pipe_cfg = &pstate->pipe_cfg[i];
- if (!drm_rect_width(&pipe_cfg->src_rect))
- continue;
- DPU_DEBUG_PLANE(pdpu, "pipe %d is in use, validate it\n", i);
- ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg,
+ ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg,
+ &crtc_state->adjusted_mode,
+ new_plane_state);
+ if (ret)
+ return ret;
+
+ if (drm_rect_width(&r_pipe_cfg->src_rect) != 0) {
+ ret = dpu_plane_atomic_check_pipe(pdpu, r_pipe, r_pipe_cfg,
&crtc_state->adjusted_mode,
new_plane_state);
if (ret)
diff --git a/drivers/gpu/drm/msm/disp/mdp_format.h b/drivers/gpu/drm/msm/disp/mdp_format.h
index a00d646ff4d4..915954bf5dc7 100644
--- a/drivers/gpu/drm/msm/disp/mdp_format.h
+++ b/drivers/gpu/drm/msm/disp/mdp_format.h
@@ -24,7 +24,7 @@ enum msm_format_flags {
#define MSM_FORMAT_FLAG_UNPACK_TIGHT BIT(MSM_FORMAT_FLAG_UNPACK_TIGHT_BIT)
#define MSM_FORMAT_FLAG_UNPACK_ALIGN_MSB BIT(MSM_FORMAT_FLAG_UNPACK_ALIGN_MSB_BIT)
-/**
+/*
* DPU HW,Component order color map
*/
enum {
@@ -37,6 +37,10 @@ enum {
/**
* struct msm_format: defines the format configuration
* @pixel_format: format fourcc
+ * @bpc_g_y: element bit widths: BPC for G or Y
+ * @bpc_b_cb: element bit widths: BPC for B or Cb
+ * @bpc_r_cr: element bit widths: BPC for R or Cr
+ * @bpc_a: element bit widths: BPC for the alpha channel
* @element: element color ordering
* @fetch_type: how the color components are packed in pixel format
* @chroma_sample: chroma sub-samplng type
diff --git a/drivers/gpu/drm/msm/dp/dp_debug.h b/drivers/gpu/drm/msm/dp/dp_debug.h
index 6dc0ff4f0f65..a90083fec856 100644
--- a/drivers/gpu/drm/msm/dp/dp_debug.h
+++ b/drivers/gpu/drm/msm/dp/dp_debug.h
@@ -12,7 +12,7 @@
#if defined(CONFIG_DEBUG_FS)
/**
- * msm_dp_debug_get() - configure and get the DisplayPlot debug module data
+ * msm_dp_debug_init() - configure and get the DisplayPlot debug module data
*
* @dev: device instance of the caller
* @panel: instance of panel module
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c
index 9a461ab2f32f..fd6443d2b6ce 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.c
+++ b/drivers/gpu/drm/msm/dp/dp_drm.c
@@ -18,6 +18,7 @@
/**
* msm_dp_bridge_detect - callback to determine if connector is connected
* @bridge: Pointer to drm bridge structure
+ * @connector: Pointer to drm connector structure
* Returns: Bridge's 'is connected' status
*/
static enum drm_connector_status
diff --git a/drivers/gpu/drm/msm/dp/dp_link.h b/drivers/gpu/drm/msm/dp/dp_link.h
index b1eb2de6d2a7..8460e4ad2d35 100644
--- a/drivers/gpu/drm/msm/dp/dp_link.h
+++ b/drivers/gpu/drm/msm/dp/dp_link.h
@@ -80,11 +80,11 @@ struct msm_dp_link {
};
/**
- * mdss_dp_test_bit_depth_to_bpp() - convert test bit depth to bpp
+ * msm_dp_link_bit_depth_to_bpp() - convert test bit depth to bpp
* @tbd: test bit depth
*
- * Returns the bits per pixel (bpp) to be used corresponding to the
- * git bit depth value. This function assumes that bit depth has
+ * Returns: the bits per pixel (bpp) to be used corresponding to the
+ * bit depth value. This function assumes that bit depth has
* already been validated.
*/
static inline u32 msm_dp_link_bit_depth_to_bpp(u32 tbd)
@@ -120,7 +120,8 @@ bool msm_dp_link_send_edid_checksum(struct msm_dp_link *msm_dp_link, u8 checksum
/**
* msm_dp_link_get() - get the functionalities of dp test module
- *
+ * @dev: kernel device structure
+ * @aux: DisplayPort AUX channel
*
* return: a pointer to msm_dp_link struct
*/
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h
index 921a296852d4..177c1328fd99 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.h
+++ b/drivers/gpu/drm/msm/dp/dp_panel.h
@@ -63,9 +63,9 @@ void msm_dp_panel_disable_vsc_sdp(struct msm_dp_panel *msm_dp_panel);
/**
* is_link_rate_valid() - validates the link rate
- * @lane_rate: link rate requested by the sink
+ * @bw_code: link rate requested by the sink
*
- * Returns true if the requested link rate is supported.
+ * Returns: true if the requested link rate is supported.
*/
static inline bool is_link_rate_valid(u32 bw_code)
{
@@ -76,10 +76,10 @@ static inline bool is_link_rate_valid(u32 bw_code)
}
/**
- * msm_dp_link_is_lane_count_valid() - validates the lane count
+ * is_lane_count_valid() - validates the lane count
* @lane_count: lane count requested by the sink
*
- * Returns true if the requested lane count is supported.
+ * Returns: true if the requested lane count is supported.
*/
static inline bool is_lane_count_valid(u32 lane_count)
{
diff --git a/drivers/gpu/drm/msm/msm_fence.h b/drivers/gpu/drm/msm/msm_fence.h
index 148196375a0b..3317a485beef 100644
--- a/drivers/gpu/drm/msm/msm_fence.h
+++ b/drivers/gpu/drm/msm/msm_fence.h
@@ -16,34 +16,29 @@
* incrementing fence seqno at the end of each submit
*/
struct msm_fence_context {
+ /** @dev: the drm device */
struct drm_device *dev;
- /** name: human readable name for fence timeline */
+ /** @name: human readable name for fence timeline */
char name[32];
- /** context: see dma_fence_context_alloc() */
+ /** @context: see dma_fence_context_alloc() */
unsigned context;
- /** index: similar to context, but local to msm_fence_context's */
+ /** @index: similar to context, but local to msm_fence_context's */
unsigned index;
-
/**
- * last_fence:
- *
+ * @last_fence:
* Last assigned fence, incremented each time a fence is created
* on this fence context. If last_fence == completed_fence,
* there is no remaining pending work
*/
uint32_t last_fence;
-
/**
- * completed_fence:
- *
+ * @completed_fence:
* The last completed fence, updated from the CPU after interrupt
* from GPU
*/
uint32_t completed_fence;
-
/**
- * fenceptr:
- *
+ * @fenceptr:
* The address that the GPU directly writes with completed fence
* seqno. This can be ahead of completed_fence. We can peek at
* this to see if a fence has already signaled but the CPU hasn't
@@ -51,6 +46,9 @@ struct msm_fence_context {
*/
volatile uint32_t *fenceptr;
+ /**
+ * @spinlock: fence context spinlock
+ */
spinlock_t spinlock;
/*
@@ -59,18 +57,22 @@ struct msm_fence_context {
* don't queue, so maybe that is ok
*/
- /** next_deadline: Time of next deadline */
+ /** @next_deadline: Time of next deadline */
ktime_t next_deadline;
-
/**
- * next_deadline_fence:
- *
+ * @next_deadline_fence:
* Fence value for next pending deadline. The deadline timer is
* canceled when this fence is signaled.
*/
uint32_t next_deadline_fence;
-
+ /**
+ * @deadline_timer: tracks nearest deadline of a fence timeline and
+ * expires just before it.
+ */
struct hrtimer deadline_timer;
+ /**
+ * @deadline_work: work to do after deadline_timer expires
+ */
struct kthread_work deadline_work;
};
diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c b/drivers/gpu/drm/msm/msm_gem_vma.c
index 71d5238437eb..8f7c90167447 100644
--- a/drivers/gpu/drm/msm/msm_gem_vma.c
+++ b/drivers/gpu/drm/msm/msm_gem_vma.c
@@ -65,7 +65,7 @@ struct msm_vm_unmap_op {
};
/**
- * struct msm_vma_op - A MAP or UNMAP operation
+ * struct msm_vm_op - A MAP or UNMAP operation
*/
struct msm_vm_op {
/** @op: The operation type */
@@ -798,6 +798,9 @@ static const struct drm_sched_backend_ops msm_vm_bind_ops = {
* synchronous operations are supported. In a user managed VM, userspace
* handles virtual address allocation, and both async and sync operations
* are supported.
+ *
+ * Returns: pointer to the created &struct drm_gpuvm on success
+ * or an ERR_PTR(-errno) on failure.
*/
struct drm_gpuvm *
msm_gem_vm_create(struct drm_device *drm, struct msm_mmu *mmu, const char *name,
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index 2894fc118485..666cf499b7ec 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -116,15 +116,12 @@ struct msm_gpu_fault_info {
* struct msm_gpu_devfreq - devfreq related state
*/
struct msm_gpu_devfreq {
- /** devfreq: devfreq instance */
+ /** @devfreq: devfreq instance */
struct devfreq *devfreq;
-
- /** lock: lock for "suspended", "busy_cycles", and "time" */
+ /** @lock: lock for "suspended", "busy_cycles", and "time" */
struct mutex lock;
-
/**
- * idle_freq:
- *
+ * @idle_freq:
* Shadow frequency used while the GPU is idle. From the PoV of
* the devfreq governor, we are continuing to sample busyness and
* adjust frequency while the GPU is idle, but we use this shadow
@@ -132,43 +129,34 @@ struct msm_gpu_devfreq {
* it is inactive.
*/
unsigned long idle_freq;
-
/**
- * boost_constraint:
- *
+ * @boost_freq:
* A PM QoS constraint to boost min freq for a period of time
* until the boost expires.
*/
struct dev_pm_qos_request boost_freq;
-
/**
- * busy_cycles: Last busy counter value, for calculating elapsed busy
+ * @busy_cycles: Last busy counter value, for calculating elapsed busy
* cycles since last sampling period.
*/
u64 busy_cycles;
-
- /** time: Time of last sampling period. */
+ /** @time: Time of last sampling period. */
ktime_t time;
-
- /** idle_time: Time of last transition to idle: */
+ /** @idle_time: Time of last transition to idle. */
ktime_t idle_time;
-
/**
- * idle_work:
- *
+ * @idle_work:
* Used to delay clamping to idle freq on active->idle transition.
*/
struct msm_hrtimer_work idle_work;
-
/**
- * boost_work:
- *
+ * @boost_work:
* Used to reset the boost_constraint after the boost period has
* elapsed
*/
struct msm_hrtimer_work boost_work;
- /** suspended: tracks if we're suspended */
+ /** @suspended: tracks if we're suspended */
bool suspended;
};
@@ -358,57 +346,43 @@ struct msm_gpu_perfcntr {
struct msm_context {
/** @queuelock: synchronizes access to submitqueues list */
rwlock_t queuelock;
-
/** @submitqueues: list of &msm_gpu_submitqueue created by userspace */
struct list_head submitqueues;
-
/**
* @queueid:
- *
* Counter incremented each time a submitqueue is created, used to
* assign &msm_gpu_submitqueue.id
*/
int queueid;
-
/**
* @closed: The device file associated with this context has been closed.
- *
* Once the device is closed, any submits that have not been written
* to the ring buffer are no-op'd.
*/
bool closed;
-
/**
* @userspace_managed_vm:
- *
* Has userspace opted-in to userspace managed VM (ie. VM_BIND) via
* MSM_PARAM_EN_VM_BIND?
*/
bool userspace_managed_vm;
-
/**
* @vm:
- *
* The per-process GPU address-space. Do not access directly, use
* msm_context_vm().
*/
struct drm_gpuvm *vm;
-
- /** @kref: the reference count */
+ /** @ref: the reference count */
struct kref ref;
-
/**
* @seqno:
- *
* A unique per-process sequence number. Used to detect context
* switches, without relying on keeping a, potentially dangling,
* pointer to the previous context.
*/
int seqno;
-
/**
* @sysprof:
- *
* The value of MSM_PARAM_SYSPROF set by userspace. This is
* intended to be used by system profiling tools like Mesa's
* pps-producer (perfetto), and restricted to CAP_SYS_ADMIN.
@@ -423,40 +397,32 @@ struct msm_context {
* file is closed.
*/
int sysprof;
-
/**
* @comm: Overridden task comm, see MSM_PARAM_COMM
*
* Accessed under msm_gpu::lock
*/
char *comm;
-
/**
* @cmdline: Overridden task cmdline, see MSM_PARAM_CMDLINE
*
* Accessed under msm_gpu::lock
*/
char *cmdline;
-
/**
- * @elapsed:
- *
+ * @elapsed_ns:
* The total (cumulative) elapsed time GPU was busy with rendering
* from this context in ns.
*/
uint64_t elapsed_ns;
-
/**
* @cycles:
- *
* The total (cumulative) GPU cycles elapsed attributed to this
* context.
*/
uint64_t cycles;
-
/**
* @entities:
- *
* Table of per-priority-level sched entities used by submitqueues
* associated with this &drm_file. Because some userspace apps
* make assumptions about rendering from multiple gl contexts
@@ -466,10 +432,8 @@ struct msm_context {
* level.
*/
struct drm_sched_entity *entities[NR_SCHED_PRIORITIES * MSM_GPU_MAX_RINGS];
-
/**
* @ctx_mem:
- *
* Total amount of memory of GEM buffers with handles attached for
* this context.
*/
@@ -479,7 +443,7 @@ struct msm_context {
struct drm_gpuvm *msm_context_vm(struct drm_device *dev, struct msm_context *ctx);
/**
- * msm_context_is_vm_bind() - has userspace opted in to VM_BIND?
+ * msm_context_is_vmbind() - has userspace opted in to VM_BIND?
*
* @ctx: the drm_file context
*
@@ -487,6 +451,8 @@ struct drm_gpuvm *msm_context_vm(struct drm_device *dev, struct msm_context *ctx
* do sparse binding including having multiple, potentially partial,
* mappings in the VM. Therefore certain legacy uabi (ie. GET_IOVA,
* SET_IOVA) are rejected because they don't have a sensible meaning.
+ *
+ * Returns: %true if userspace is managing the VM, %false otherwise.
*/
static inline bool
msm_context_is_vmbind(struct msm_context *ctx)
@@ -518,6 +484,8 @@ msm_context_is_vmbind(struct msm_context *ctx)
* This allows generations without preemption (nr_rings==1) to have some
* amount of prioritization, and provides more priority levels for gens
* that do have preemption.
+ *
+ * Returns: %0 on success, %-errno on error.
*/
static inline int msm_gpu_convert_priority(struct msm_gpu *gpu, int prio,
unsigned *ring_nr, enum drm_sched_priority *sched_prio)
@@ -541,7 +509,7 @@ static inline int msm_gpu_convert_priority(struct msm_gpu *gpu, int prio,
}
/**
- * struct msm_gpu_submitqueues - Userspace created context.
+ * struct msm_gpu_submitqueue - Userspace created context.
*
* A submitqueue is associated with a gl context or vk queue (or equiv)
* in userspace.
diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
index a188617653e8..d5dede4ff761 100644
--- a/drivers/gpu/drm/msm/msm_iommu.c
+++ b/drivers/gpu/drm/msm/msm_iommu.c
@@ -364,7 +364,7 @@ msm_iommu_pagetable_prealloc_cleanup(struct msm_mmu *mmu, struct msm_mmu_preallo
}
/**
- * alloc_pt() - Custom page table allocator
+ * msm_iommu_pagetable_alloc_pt() - Custom page table allocator
* @cookie: Cookie passed at page table allocation time.
* @size: Size of the page table. This size should be fixed,
* and determined at creation time based on the granule size.
@@ -416,7 +416,7 @@ msm_iommu_pagetable_alloc_pt(void *cookie, size_t size, gfp_t gfp)
/**
- * free_pt() - Custom page table free function
+ * msm_iommu_pagetable_free_pt() - Custom page table free function
* @cookie: Cookie passed at page table allocation time.
* @data: Page table to free.
* @size: Size of the page table. This size should be fixed,
diff --git a/drivers/gpu/drm/msm/msm_perf.c b/drivers/gpu/drm/msm/msm_perf.c
index d3c7889aaf26..c369d4acc378 100644
--- a/drivers/gpu/drm/msm/msm_perf.c
+++ b/drivers/gpu/drm/msm/msm_perf.c
@@ -65,13 +65,13 @@ static int refill_buf(struct msm_perf_state *perf)
if ((perf->cnt++ % 32) == 0) {
/* Header line: */
- n = snprintf(ptr, rem, "%%BUSY");
+ n = scnprintf(ptr, rem, "%%BUSY");
ptr += n;
rem -= n;
for (i = 0; i < gpu->num_perfcntrs; i++) {
const struct msm_gpu_perfcntr *perfcntr = &gpu->perfcntrs[i];
- n = snprintf(ptr, rem, "\t%s", perfcntr->name);
+ n = scnprintf(ptr, rem, "\t%s", perfcntr->name);
ptr += n;
rem -= n;
}
@@ -93,21 +93,21 @@ static int refill_buf(struct msm_perf_state *perf)
return ret;
val = totaltime ? 1000 * activetime / totaltime : 0;
- n = snprintf(ptr, rem, "%3d.%d%%", val / 10, val % 10);
+ n = scnprintf(ptr, rem, "%3d.%d%%", val / 10, val % 10);
ptr += n;
rem -= n;
for (i = 0; i < ret; i++) {
/* cycle counters (I think).. convert to MHz.. */
val = cntrs[i] / 10000;
- n = snprintf(ptr, rem, "\t%5d.%02d",
+ n = scnprintf(ptr, rem, "\t%5d.%02d",
val / 100, val % 100);
ptr += n;
rem -= n;
}
}
- n = snprintf(ptr, rem, "\n");
+ n = scnprintf(ptr, rem, "\n");
ptr += n;
rem -= n;
diff --git a/drivers/gpu/drm/nouveau/dispnv50/atom.h b/drivers/gpu/drm/nouveau/dispnv50/atom.h
index 93f8f4f64578..b43c4f9bbcdf 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/atom.h
+++ b/drivers/gpu/drm/nouveau/dispnv50/atom.h
@@ -152,8 +152,21 @@ static inline struct nv50_head_atom *
nv50_head_atom_get(struct drm_atomic_state *state, struct drm_crtc *crtc)
{
struct drm_crtc_state *statec = drm_atomic_get_crtc_state(state, crtc);
+
if (IS_ERR(statec))
return (void *)statec;
+
+ return nv50_head_atom(statec);
+}
+
+static inline struct nv50_head_atom *
+nv50_head_atom_get_new(struct drm_atomic_state *state, struct drm_crtc *crtc)
+{
+ struct drm_crtc_state *statec = drm_atomic_get_new_crtc_state(state, crtc);
+
+ if (!statec)
+ return NULL;
+
return nv50_head_atom(statec);
}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
index ef9e410babbf..9a2c20fce0f3 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
@@ -583,7 +583,7 @@ nv50_wndw_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state)
asyw->image.offset[0] = nvbo->offset;
if (wndw->func->prepare) {
- asyh = nv50_head_atom_get(asyw->state.state, asyw->state.crtc);
+ asyh = nv50_head_atom_get_new(asyw->state.state, asyw->state.crtc);
if (IS_ERR(asyh))
return PTR_ERR(asyh);
diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c
index 4ac434ad216f..a5019d1e741b 100644
--- a/drivers/gpu/drm/xe/xe_guc_ct.c
+++ b/drivers/gpu/drm/xe/xe_guc_ct.c
@@ -104,7 +104,9 @@ static void g2h_fence_cancel(struct g2h_fence *g2h_fence)
{
g2h_fence->cancel = true;
g2h_fence->fail = true;
- g2h_fence->done = true;
+
+ /* WRITE_ONCE pairs with READ_ONCEs in guc_ct_send_recv. */
+ WRITE_ONCE(g2h_fence->done, true);
}
static bool g2h_fence_needs_alloc(struct g2h_fence *g2h_fence)
@@ -1203,10 +1205,13 @@ retry_same_fence:
return ret;
}
- ret = wait_event_timeout(ct->g2h_fence_wq, g2h_fence.done, HZ);
+ /* READ_ONCEs pairs with WRITE_ONCEs in parse_g2h_response
+ * and g2h_fence_cancel.
+ */
+ ret = wait_event_timeout(ct->g2h_fence_wq, READ_ONCE(g2h_fence.done), HZ);
if (!ret) {
LNL_FLUSH_WORK(&ct->g2h_worker);
- if (g2h_fence.done) {
+ if (READ_ONCE(g2h_fence.done)) {
xe_gt_warn(gt, "G2H fence %u, action %04x, done\n",
g2h_fence.seqno, action[0]);
ret = 1;
@@ -1454,7 +1459,8 @@ static int parse_g2h_response(struct xe_guc_ct *ct, u32 *msg, u32 len)
g2h_release_space(ct, GUC_CTB_HXG_MSG_MAX_LEN);
- g2h_fence->done = true;
+ /* WRITE_ONCE pairs with READ_ONCEs in guc_ct_send_recv. */
+ WRITE_ONCE(g2h_fence->done, true);
smp_mb();
wake_up_all(&ct->g2h_fence_wq);
diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c
index 2184af413b91..5a95b08a4723 100644
--- a/drivers/gpu/drm/xe/xe_migrate.c
+++ b/drivers/gpu/drm/xe/xe_migrate.c
@@ -2062,6 +2062,7 @@ static struct dma_fence *xe_migrate_vram(struct xe_migrate *m,
unsigned long sram_offset,
struct drm_pagemap_addr *sram_addr,
u64 vram_addr,
+ struct dma_fence *deps,
const enum xe_migrate_copy_dir dir)
{
struct xe_gt *gt = m->tile->primary_gt;
@@ -2150,6 +2151,14 @@ static struct dma_fence *xe_migrate_vram(struct xe_migrate *m,
xe_sched_job_add_migrate_flush(job, MI_INVALIDATE_TLB);
+ if (deps && !dma_fence_is_signaled(deps)) {
+ dma_fence_get(deps);
+ err = drm_sched_job_add_dependency(&job->drm, deps);
+ if (err)
+ dma_fence_wait(deps, false);
+ err = 0;
+ }
+
mutex_lock(&m->job_mutex);
xe_sched_job_arm(job);
fence = dma_fence_get(&job->drm.s_fence->finished);
@@ -2175,6 +2184,8 @@ err:
* @npages: Number of pages to migrate.
* @src_addr: Array of DMA information (source of migrate)
* @dst_addr: Device physical address of VRAM (destination of migrate)
+ * @deps: struct dma_fence representing the dependencies that need
+ * to be signaled before migration.
*
* Copy from an array dma addresses to a VRAM device physical address
*
@@ -2184,10 +2195,11 @@ err:
struct dma_fence *xe_migrate_to_vram(struct xe_migrate *m,
unsigned long npages,
struct drm_pagemap_addr *src_addr,
- u64 dst_addr)
+ u64 dst_addr,
+ struct dma_fence *deps)
{
return xe_migrate_vram(m, npages * PAGE_SIZE, 0, src_addr, dst_addr,
- XE_MIGRATE_COPY_TO_VRAM);
+ deps, XE_MIGRATE_COPY_TO_VRAM);
}
/**
@@ -2196,6 +2208,8 @@ struct dma_fence *xe_migrate_to_vram(struct xe_migrate *m,
* @npages: Number of pages to migrate.
* @src_addr: Device physical address of VRAM (source of migrate)
* @dst_addr: Array of DMA information (destination of migrate)
+ * @deps: struct dma_fence representing the dependencies that need
+ * to be signaled before migration.
*
* Copy from a VRAM device physical address to an array dma addresses
*
@@ -2205,10 +2219,11 @@ struct dma_fence *xe_migrate_to_vram(struct xe_migrate *m,
struct dma_fence *xe_migrate_from_vram(struct xe_migrate *m,
unsigned long npages,
u64 src_addr,
- struct drm_pagemap_addr *dst_addr)
+ struct drm_pagemap_addr *dst_addr,
+ struct dma_fence *deps)
{
return xe_migrate_vram(m, npages * PAGE_SIZE, 0, dst_addr, src_addr,
- XE_MIGRATE_COPY_TO_SRAM);
+ deps, XE_MIGRATE_COPY_TO_SRAM);
}
static void xe_migrate_dma_unmap(struct xe_device *xe,
@@ -2384,7 +2399,7 @@ int xe_migrate_access_memory(struct xe_migrate *m, struct xe_bo *bo,
__fence = xe_migrate_vram(m, current_bytes,
(unsigned long)buf & ~PAGE_MASK,
&pagemap_addr[current_page],
- vram_addr, write ?
+ vram_addr, NULL, write ?
XE_MIGRATE_COPY_TO_VRAM :
XE_MIGRATE_COPY_TO_SRAM);
if (IS_ERR(__fence)) {
diff --git a/drivers/gpu/drm/xe/xe_migrate.h b/drivers/gpu/drm/xe/xe_migrate.h
index 260e298e5dd7..b76441f062b4 100644
--- a/drivers/gpu/drm/xe/xe_migrate.h
+++ b/drivers/gpu/drm/xe/xe_migrate.h
@@ -116,12 +116,14 @@ int xe_migrate_init(struct xe_migrate *m);
struct dma_fence *xe_migrate_to_vram(struct xe_migrate *m,
unsigned long npages,
struct drm_pagemap_addr *src_addr,
- u64 dst_addr);
+ u64 dst_addr,
+ struct dma_fence *deps);
struct dma_fence *xe_migrate_from_vram(struct xe_migrate *m,
unsigned long npages,
u64 src_addr,
- struct drm_pagemap_addr *dst_addr);
+ struct drm_pagemap_addr *dst_addr,
+ struct dma_fence *deps);
struct dma_fence *xe_migrate_copy(struct xe_migrate *m,
struct xe_bo *src_bo,
diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c
index 55c5a0eb82e1..f97e0af6a9b0 100644
--- a/drivers/gpu/drm/xe/xe_svm.c
+++ b/drivers/gpu/drm/xe/xe_svm.c
@@ -476,7 +476,8 @@ static void xe_svm_copy_us_stats_incr(struct xe_gt *gt,
static int xe_svm_copy(struct page **pages,
struct drm_pagemap_addr *pagemap_addr,
- unsigned long npages, const enum xe_svm_copy_dir dir)
+ unsigned long npages, const enum xe_svm_copy_dir dir,
+ struct dma_fence *pre_migrate_fence)
{
struct xe_vram_region *vr = NULL;
struct xe_gt *gt = NULL;
@@ -565,7 +566,8 @@ static int xe_svm_copy(struct page **pages,
__fence = xe_migrate_from_vram(vr->migrate,
i - pos + incr,
vram_addr,
- &pagemap_addr[pos]);
+ &pagemap_addr[pos],
+ pre_migrate_fence);
} else {
vm_dbg(&xe->drm,
"COPY TO VRAM - 0x%016llx -> 0x%016llx, NPAGES=%ld",
@@ -574,13 +576,14 @@ static int xe_svm_copy(struct page **pages,
__fence = xe_migrate_to_vram(vr->migrate,
i - pos + incr,
&pagemap_addr[pos],
- vram_addr);
+ vram_addr,
+ pre_migrate_fence);
}
if (IS_ERR(__fence)) {
err = PTR_ERR(__fence);
goto err_out;
}
-
+ pre_migrate_fence = NULL;
dma_fence_put(fence);
fence = __fence;
}
@@ -603,20 +606,22 @@ static int xe_svm_copy(struct page **pages,
vram_addr, (u64)pagemap_addr[pos].addr, 1);
__fence = xe_migrate_from_vram(vr->migrate, 1,
vram_addr,
- &pagemap_addr[pos]);
+ &pagemap_addr[pos],
+ pre_migrate_fence);
} else {
vm_dbg(&xe->drm,
"COPY TO VRAM - 0x%016llx -> 0x%016llx, NPAGES=%d",
(u64)pagemap_addr[pos].addr, vram_addr, 1);
__fence = xe_migrate_to_vram(vr->migrate, 1,
&pagemap_addr[pos],
- vram_addr);
+ vram_addr,
+ pre_migrate_fence);
}
if (IS_ERR(__fence)) {
err = PTR_ERR(__fence);
goto err_out;
}
-
+ pre_migrate_fence = NULL;
dma_fence_put(fence);
fence = __fence;
}
@@ -629,6 +634,8 @@ err_out:
dma_fence_wait(fence, false);
dma_fence_put(fence);
}
+ if (pre_migrate_fence)
+ dma_fence_wait(pre_migrate_fence, false);
/*
* XXX: We can't derive the GT here (or anywhere in this functions, but
@@ -645,16 +652,20 @@ err_out:
static int xe_svm_copy_to_devmem(struct page **pages,
struct drm_pagemap_addr *pagemap_addr,
- unsigned long npages)
+ unsigned long npages,
+ struct dma_fence *pre_migrate_fence)
{
- return xe_svm_copy(pages, pagemap_addr, npages, XE_SVM_COPY_TO_VRAM);
+ return xe_svm_copy(pages, pagemap_addr, npages, XE_SVM_COPY_TO_VRAM,
+ pre_migrate_fence);
}
static int xe_svm_copy_to_ram(struct page **pages,
struct drm_pagemap_addr *pagemap_addr,
- unsigned long npages)
+ unsigned long npages,
+ struct dma_fence *pre_migrate_fence)
{
- return xe_svm_copy(pages, pagemap_addr, npages, XE_SVM_COPY_TO_SRAM);
+ return xe_svm_copy(pages, pagemap_addr, npages, XE_SVM_COPY_TO_SRAM,
+ pre_migrate_fence);
}
static struct xe_bo *to_xe_bo(struct drm_pagemap_devmem *devmem_allocation)
@@ -667,6 +678,7 @@ static void xe_svm_devmem_release(struct drm_pagemap_devmem *devmem_allocation)
struct xe_bo *bo = to_xe_bo(devmem_allocation);
struct xe_device *xe = xe_bo_device(bo);
+ dma_fence_put(devmem_allocation->pre_migrate_fence);
xe_bo_put_async(bo);
xe_pm_runtime_put(xe);
}
@@ -861,6 +873,7 @@ static int xe_drm_pagemap_populate_mm(struct drm_pagemap *dpagemap,
unsigned long timeslice_ms)
{
struct xe_vram_region *vr = container_of(dpagemap, typeof(*vr), dpagemap);
+ struct dma_fence *pre_migrate_fence = NULL;
struct xe_device *xe = vr->xe;
struct device *dev = xe->drm.dev;
struct drm_buddy_block *block;
@@ -887,8 +900,20 @@ static int xe_drm_pagemap_populate_mm(struct drm_pagemap *dpagemap,
break;
}
+ /* Ensure that any clearing or async eviction will complete before migration. */
+ if (!dma_resv_test_signaled(bo->ttm.base.resv, DMA_RESV_USAGE_KERNEL)) {
+ err = dma_resv_get_singleton(bo->ttm.base.resv, DMA_RESV_USAGE_KERNEL,
+ &pre_migrate_fence);
+ if (err)
+ dma_resv_wait_timeout(bo->ttm.base.resv, DMA_RESV_USAGE_KERNEL,
+ false, MAX_SCHEDULE_TIMEOUT);
+ else if (pre_migrate_fence)
+ dma_fence_enable_sw_signaling(pre_migrate_fence);
+ }
+
drm_pagemap_devmem_init(&bo->devmem_allocation, dev, mm,
- &dpagemap_devmem_ops, dpagemap, end - start);
+ &dpagemap_devmem_ops, dpagemap, end - start,
+ pre_migrate_fence);
blocks = &to_xe_ttm_vram_mgr_resource(bo->ttm.resource)->blocks;
list_for_each_entry(block, blocks, link)
@@ -941,7 +966,7 @@ bool xe_svm_range_needs_migrate_to_vram(struct xe_svm_range *range, struct xe_vm
xe_assert(vm->xe, IS_DGFX(vm->xe));
if (xe_svm_range_in_vram(range)) {
- drm_info(&vm->xe->drm, "Range is already in VRAM\n");
+ drm_dbg(&vm->xe->drm, "Range is already in VRAM\n");
return false;
}
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index 61596cda2b65..35ba852a172a 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -80,37 +80,25 @@ static const struct nla_policy ib_nl_addr_policy[LS_NLA_TYPE_MAX] = {
.min = sizeof(struct rdma_nla_ls_gid)},
};
-static inline bool ib_nl_is_good_ip_resp(const struct nlmsghdr *nlh)
+static void ib_nl_process_ip_rsep(const struct nlmsghdr *nlh)
{
struct nlattr *tb[LS_NLA_TYPE_MAX] = {};
+ union ib_gid gid;
+ struct addr_req *req;
+ int found = 0;
int ret;
if (nlh->nlmsg_flags & RDMA_NL_LS_F_ERR)
- return false;
+ return;
ret = nla_parse_deprecated(tb, LS_NLA_TYPE_MAX - 1, nlmsg_data(nlh),
nlmsg_len(nlh), ib_nl_addr_policy, NULL);
if (ret)
- return false;
-
- return true;
-}
-
-static void ib_nl_process_good_ip_rsep(const struct nlmsghdr *nlh)
-{
- const struct nlattr *head, *curr;
- union ib_gid gid;
- struct addr_req *req;
- int len, rem;
- int found = 0;
-
- head = (const struct nlattr *)nlmsg_data(nlh);
- len = nlmsg_len(nlh);
+ return;
- nla_for_each_attr(curr, head, len, rem) {
- if (curr->nla_type == LS_NLA_TYPE_DGID)
- memcpy(&gid, nla_data(curr), nla_len(curr));
- }
+ if (!tb[LS_NLA_TYPE_DGID])
+ return;
+ memcpy(&gid, nla_data(tb[LS_NLA_TYPE_DGID]), sizeof(gid));
spin_lock_bh(&lock);
list_for_each_entry(req, &req_list, list) {
@@ -137,8 +125,7 @@ int ib_nl_handle_ip_res_resp(struct sk_buff *skb,
!(NETLINK_CB(skb).sk))
return -EPERM;
- if (ib_nl_is_good_ip_resp(nlh))
- ib_nl_process_good_ip_rsep(nlh);
+ ib_nl_process_ip_rsep(nlh);
return 0;
}
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 95e89f5c147c..f00f1d3fbd9c 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -2009,6 +2009,7 @@ static void destroy_mc(struct rdma_id_private *id_priv,
ib_sa_free_multicast(mc->sa_mc);
if (rdma_protocol_roce(id_priv->id.device, id_priv->id.port_num)) {
+ struct rdma_cm_event *event = &mc->iboe_join.event;
struct rdma_dev_addr *dev_addr =
&id_priv->id.route.addr.dev_addr;
struct net_device *ndev = NULL;
@@ -2031,6 +2032,8 @@ static void destroy_mc(struct rdma_id_private *id_priv,
dev_put(ndev);
cancel_work_sync(&mc->iboe_join.work);
+ if (event->event == RDMA_CM_EVENT_MULTICAST_JOIN)
+ rdma_destroy_ah_attr(&event->param.ud.ah_attr);
}
kfree(mc);
}
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 13e8a1714bbd..1174ab7da629 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -2881,8 +2881,10 @@ int ib_del_sub_device_and_put(struct ib_device *sub)
{
struct ib_device *parent = sub->parent;
- if (!parent)
+ if (!parent) {
+ ib_device_put(sub);
return -EOPNOTSUPP;
+ }
mutex_lock(&parent->subdev_lock);
list_del(&sub->subdev_list);
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index 11b1a194de44..ee390928511a 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -738,7 +738,7 @@ int ib_get_gids_from_rdma_hdr(const union rdma_network_hdr *hdr,
(struct in6_addr *)dgid);
return 0;
} else if (net_type == RDMA_NETWORK_IPV6 ||
- net_type == RDMA_NETWORK_IB || RDMA_NETWORK_ROCE_V1) {
+ net_type == RDMA_NETWORK_IB || net_type == RDMA_NETWORK_ROCE_V1) {
*dgid = hdr->ibgrh.dgid;
*sgid = hdr->ibgrh.sgid;
return 0;
diff --git a/drivers/infiniband/hw/bnxt_re/hw_counters.h b/drivers/infiniband/hw/bnxt_re/hw_counters.h
index 09d371d442aa..cebec033f4a0 100644
--- a/drivers/infiniband/hw/bnxt_re/hw_counters.h
+++ b/drivers/infiniband/hw/bnxt_re/hw_counters.h
@@ -89,6 +89,9 @@ enum bnxt_re_hw_stats {
BNXT_RE_RES_SRQ_LOAD_ERR,
BNXT_RE_RES_TX_PCI_ERR,
BNXT_RE_RES_RX_PCI_ERR,
+ BNXT_RE_REQ_CQE_ERROR,
+ BNXT_RE_RESP_CQE_ERROR,
+ BNXT_RE_RESP_REMOTE_ACCESS_ERRS,
BNXT_RE_OUT_OF_SEQ_ERR,
BNXT_RE_TX_ATOMIC_REQ,
BNXT_RE_TX_READ_REQ,
@@ -110,9 +113,6 @@ enum bnxt_re_hw_stats {
BNXT_RE_TX_CNP,
BNXT_RE_RX_CNP,
BNXT_RE_RX_ECN,
- BNXT_RE_REQ_CQE_ERROR,
- BNXT_RE_RESP_CQE_ERROR,
- BNXT_RE_RESP_REMOTE_ACCESS_ERRS,
BNXT_RE_NUM_EXT_COUNTERS
};
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
index f19b55c13d58..ff91511bd338 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
@@ -2919,14 +2919,9 @@ int bnxt_re_post_send(struct ib_qp *ib_qp, const struct ib_send_wr *wr,
wqe.rawqp1.lflags |=
SQ_SEND_RAWETH_QP1_LFLAGS_ROCE_CRC;
}
- switch (wr->send_flags) {
- case IB_SEND_IP_CSUM:
+ if (wr->send_flags & IB_SEND_IP_CSUM)
wqe.rawqp1.lflags |=
SQ_SEND_RAWETH_QP1_LFLAGS_IP_CHKSUM;
- break;
- default:
- break;
- }
fallthrough;
case IB_WR_SEND_WITH_INV:
rc = bnxt_re_build_send_wqe(qp, wr, &wqe);
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
index 295a9610f3e6..4dad0cfcfa98 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
@@ -1112,7 +1112,7 @@ static int bnxt_qplib_map_creq_db(struct bnxt_qplib_rcfw *rcfw, u32 reg_offt)
creq_db->dbinfo.flags = 0;
creq_db->reg.bar_id = RCFW_COMM_CONS_PCI_BAR_REGION;
creq_db->reg.bar_base = pci_resource_start(pdev, creq_db->reg.bar_id);
- if (!creq_db->reg.bar_id)
+ if (!creq_db->reg.bar_base)
dev_err(&pdev->dev,
"QPLIB: CREQ BAR region %d resc start is 0!",
creq_db->reg.bar_id);
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.c b/drivers/infiniband/hw/bnxt_re/qplib_res.c
index 875d7b52c06a..4d674a3aee1a 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_res.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_res.c
@@ -64,9 +64,7 @@ static void __free_pbl(struct bnxt_qplib_res *res, struct bnxt_qplib_pbl *pbl,
for (i = 0; i < pbl->pg_count; i++) {
if (pbl->pg_arr[i])
dma_free_coherent(&pdev->dev, pbl->pg_size,
- (void *)((unsigned long)
- pbl->pg_arr[i] &
- PAGE_MASK),
+ pbl->pg_arr[i],
pbl->pg_map_arr[i]);
else
dev_warn(&pdev->dev,
@@ -237,7 +235,7 @@ int bnxt_qplib_alloc_init_hwq(struct bnxt_qplib_hwq *hwq,
if (npbl % BIT(MAX_PDL_LVL_SHIFT))
npde++;
/* Alloc PDE pages */
- sginfo.pgsize = npde * pg_size;
+ sginfo.pgsize = npde * ROCE_PG_SIZE_4K;
sginfo.npages = 1;
rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_0], &sginfo);
if (rc)
@@ -245,7 +243,7 @@ int bnxt_qplib_alloc_init_hwq(struct bnxt_qplib_hwq *hwq,
/* Alloc PBL pages */
sginfo.npages = npbl;
- sginfo.pgsize = PAGE_SIZE;
+ sginfo.pgsize = ROCE_PG_SIZE_4K;
rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_1], &sginfo);
if (rc)
goto fail;
diff --git a/drivers/infiniband/hw/efa/efa_verbs.c b/drivers/infiniband/hw/efa/efa_verbs.c
index 22d3e25c3b9d..755bba8d58bb 100644
--- a/drivers/infiniband/hw/efa/efa_verbs.c
+++ b/drivers/infiniband/hw/efa/efa_verbs.c
@@ -1320,13 +1320,9 @@ static int umem_to_page_list(struct efa_dev *dev,
u32 hp_cnt,
u8 hp_shift)
{
- u32 pages_in_hp = BIT(hp_shift - PAGE_SHIFT);
struct ib_block_iter biter;
unsigned int hp_idx = 0;
- ibdev_dbg(&dev->ibdev, "hp_cnt[%u], pages_in_hp[%u]\n",
- hp_cnt, pages_in_hp);
-
rdma_umem_for_each_dma_block(umem, &biter, BIT(hp_shift))
page_list[hp_idx++] = rdma_block_iter_dma_address(&biter);
diff --git a/drivers/infiniband/hw/irdma/utils.c b/drivers/infiniband/hw/irdma/utils.c
index cc2a12f735d3..13d7499131d4 100644
--- a/drivers/infiniband/hw/irdma/utils.c
+++ b/drivers/infiniband/hw/irdma/utils.c
@@ -251,7 +251,7 @@ int irdma_net_event(struct notifier_block *notifier, unsigned long event,
void *ptr)
{
struct neighbour *neigh = ptr;
- struct net_device *real_dev, *netdev = (struct net_device *)neigh->dev;
+ struct net_device *real_dev, *netdev;
struct irdma_device *iwdev;
struct ib_device *ibdev;
__be32 *p;
@@ -260,6 +260,7 @@ int irdma_net_event(struct notifier_block *notifier, unsigned long event,
switch (event) {
case NETEVENT_NEIGH_UPDATE:
+ netdev = neigh->dev;
real_dev = rdma_vlan_dev_real_dev(netdev);
if (!real_dev)
real_dev = netdev;
diff --git a/drivers/infiniband/hw/mana/cq.c b/drivers/infiniband/hw/mana/cq.c
index 1becc8779123..7600412b0739 100644
--- a/drivers/infiniband/hw/mana/cq.c
+++ b/drivers/infiniband/hw/mana/cq.c
@@ -56,6 +56,10 @@ int mana_ib_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
doorbell = mana_ucontext->doorbell;
} else {
is_rnic_cq = true;
+ if (attr->cqe > U32_MAX / COMP_ENTRY_SIZE / 2 + 1) {
+ ibdev_dbg(ibdev, "CQE %d exceeding limit\n", attr->cqe);
+ return -EINVAL;
+ }
buf_size = MANA_PAGE_ALIGN(roundup_pow_of_two(attr->cqe * COMP_ENTRY_SIZE));
cq->cqe = buf_size / COMP_ENTRY_SIZE;
err = mana_ib_create_kernel_queue(mdev, buf_size, GDMA_CQ, &cq->queue);
diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c
index 0195d361e5e3..0bd0902b11f7 100644
--- a/drivers/infiniband/sw/rxe/rxe_net.c
+++ b/drivers/infiniband/sw/rxe/rxe_net.c
@@ -64,7 +64,39 @@ static inline void rxe_reclassify_recv_socket(struct socket *sock)
break;
default:
WARN_ON_ONCE(1);
+ return;
}
+ /*
+ * sock_lock_init_class_and_name() calls
+ * sk_owner_set(sk, THIS_MODULE); in order
+ * to make sure the referenced global
+ * variables rxe_recv_slock_key and
+ * rxe_recv_sk_key are not removed
+ * before the socket is closed.
+ *
+ * However this prevents rxe_net_exit()
+ * from being called and 'rmmod rdma_rxe'
+ * is refused because of the references.
+ *
+ * For the global sockets in recv_sockets,
+ * we are sure that rxe_net_exit() will call
+ * rxe_release_udp_tunnel -> udp_tunnel_sock_release.
+ *
+ * So we don't need the additional reference to
+ * our own (THIS_MODULE).
+ */
+ sk_owner_put(sk);
+ /*
+ * We also call sk_owner_clear() otherwise
+ * sk_owner_put(sk) in sk_prot_free will
+ * fail, which is called via
+ * sk_free -> __sk_free -> sk_destruct
+ * and sk_destruct calls __sk_destruct
+ * directly or via call_rcu()
+ * so sk_prot_free() might be called
+ * after rxe_net_exit().
+ */
+ sk_owner_clear(sk);
#endif /* CONFIG_DEBUG_LOCK_ALLOC */
}
diff --git a/drivers/infiniband/sw/rxe/rxe_odp.c b/drivers/infiniband/sw/rxe/rxe_odp.c
index ae71812bea82..c928cbf2e35f 100644
--- a/drivers/infiniband/sw/rxe/rxe_odp.c
+++ b/drivers/infiniband/sw/rxe/rxe_odp.c
@@ -179,8 +179,10 @@ static int rxe_odp_map_range_and_lock(struct rxe_mr *mr, u64 iova, int length, u
return err;
need_fault = rxe_check_pagefault(umem_odp, iova, length);
- if (need_fault)
+ if (need_fault) {
+ mutex_unlock(&umem_odp->umem_mutex);
return -EFAULT;
+ }
}
return 0;
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c
index 71387811b281..2b397a544cb9 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c
+++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c
@@ -1464,6 +1464,7 @@ static void query_fast_reg_mode(struct rtrs_clt_path *clt_path)
mr_page_shift = max(12, ffs(ib_dev->attrs.page_size_cap) - 1);
max_pages_per_mr = ib_dev->attrs.max_mr_size;
do_div(max_pages_per_mr, (1ull << mr_page_shift));
+ max_pages_per_mr = min_not_zero((u32)max_pages_per_mr, U32_MAX);
clt_path->max_pages_per_mr =
min3(clt_path->max_pages_per_mr, (u32)max_pages_per_mr,
ib_dev->attrs.max_fast_reg_page_list_len);
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-pri.h b/drivers/infiniband/ulp/rtrs/rtrs-pri.h
index ef29bd483b5a..59529d593869 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-pri.h
+++ b/drivers/infiniband/ulp/rtrs/rtrs-pri.h
@@ -150,7 +150,7 @@ enum rtrs_msg_types {
/**
* enum rtrs_msg_flags - RTRS message flags.
- * @RTRS_NEED_INVAL: Send invalidation in response.
+ * @RTRS_MSG_NEED_INVAL_F: Send invalidation in response.
* @RTRS_MSG_NEW_RKEY_F: Send refreshed rkey in response.
*/
enum rtrs_msg_flags {
@@ -179,16 +179,19 @@ struct rtrs_sg_desc {
* @recon_cnt: Reconnections counter
* @sess_uuid: UUID of a session (path)
* @paths_uuid: UUID of a group of sessions (paths)
- *
+ * @first_conn: %1 if the connection request is the first for that session,
+ * otherwise %0
* NOTE: max size 56 bytes, see man rdma_connect().
*/
struct rtrs_msg_conn_req {
- /* Is set to 0 by cma.c in case of AF_IB, do not touch that.
- * see https://www.spinics.net/lists/linux-rdma/msg22397.html
+ /**
+ * @__cma_version: Is set to 0 by cma.c in case of AF_IB, do not touch
+ * that. See https://www.spinics.net/lists/linux-rdma/msg22397.html
*/
u8 __cma_version;
- /* On sender side that should be set to 0, or cma_save_ip_info()
- * extract garbage and will fail.
+ /**
+ * @__ip_version: On sender side that should be set to 0, or
+ * cma_save_ip_info() extract garbage and will fail.
*/
u8 __ip_version;
__le16 magic;
@@ -199,6 +202,7 @@ struct rtrs_msg_conn_req {
uuid_t sess_uuid;
uuid_t paths_uuid;
u8 first_conn : 1;
+ /* private: */
u8 reserved_bits : 7;
u8 reserved[11];
};
@@ -211,6 +215,7 @@ struct rtrs_msg_conn_req {
* @queue_depth: max inflight messages (queue-depth) in this session
* @max_io_size: max io size server supports
* @max_hdr_size: max msg header size server supports
+ * @flags: RTRS message flags for this message
*
* NOTE: size is 56 bytes, max possible is 136 bytes, see man rdma_accept().
*/
@@ -222,22 +227,24 @@ struct rtrs_msg_conn_rsp {
__le32 max_io_size;
__le32 max_hdr_size;
__le32 flags;
+ /* private: */
u8 reserved[36];
};
/**
- * struct rtrs_msg_info_req
+ * struct rtrs_msg_info_req - client additional info request
* @type: @RTRS_MSG_INFO_REQ
* @pathname: Path name chosen by client
*/
struct rtrs_msg_info_req {
__le16 type;
u8 pathname[NAME_MAX];
+ /* private: */
u8 reserved[15];
};
/**
- * struct rtrs_msg_info_rsp
+ * struct rtrs_msg_info_rsp - server additional info response
* @type: @RTRS_MSG_INFO_RSP
* @sg_cnt: Number of @desc entries
* @desc: RDMA buffers where the client can write to server
@@ -245,12 +252,14 @@ struct rtrs_msg_info_req {
struct rtrs_msg_info_rsp {
__le16 type;
__le16 sg_cnt;
+ /* private: */
u8 reserved[4];
+ /* public: */
struct rtrs_sg_desc desc[];
};
/**
- * struct rtrs_msg_rkey_rsp
+ * struct rtrs_msg_rkey_rsp - server refreshed rkey response
* @type: @RTRS_MSG_RKEY_RSP
* @buf_id: RDMA buf_id of the new rkey
* @rkey: new remote key for RDMA buffers id from server
@@ -264,6 +273,7 @@ struct rtrs_msg_rkey_rsp {
/**
* struct rtrs_msg_rdma_read - RDMA data transfer request from client
* @type: always @RTRS_MSG_READ
+ * @flags: RTRS message flags (enum rtrs_msg_flags)
* @usr_len: length of user payload
* @sg_cnt: number of @desc entries
* @desc: RDMA buffers where the server can write the result to
@@ -277,7 +287,7 @@ struct rtrs_msg_rdma_read {
};
/**
- * struct_msg_rdma_write - Message transferred to server with RDMA-Write
+ * struct rtrs_msg_rdma_write - Message transferred to server with RDMA-Write
* @type: always @RTRS_MSG_WRITE
* @usr_len: length of user payload
*/
@@ -287,7 +297,7 @@ struct rtrs_msg_rdma_write {
};
/**
- * struct_msg_rdma_hdr - header for read or write request
+ * struct rtrs_msg_rdma_hdr - header for read or write request
* @type: @RTRS_MSG_WRITE | @RTRS_MSG_READ
*/
struct rtrs_msg_rdma_hdr {
diff --git a/drivers/infiniband/ulp/rtrs/rtrs.h b/drivers/infiniband/ulp/rtrs/rtrs.h
index b48b53a7c143..b5bd35712de0 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs.h
+++ b/drivers/infiniband/ulp/rtrs/rtrs.h
@@ -24,8 +24,8 @@ struct rtrs_srv_op;
/**
* enum rtrs_clt_link_ev - Events about connectivity state of a client
- * @RTRS_CLT_LINK_EV_RECONNECTED Client was reconnected.
- * @RTRS_CLT_LINK_EV_DISCONNECTED Client was disconnected.
+ * @RTRS_CLT_LINK_EV_RECONNECTED: Client was reconnected.
+ * @RTRS_CLT_LINK_EV_DISCONNECTED: Client was disconnected.
*/
enum rtrs_clt_link_ev {
RTRS_CLT_LINK_EV_RECONNECTED,
@@ -33,7 +33,9 @@ enum rtrs_clt_link_ev {
};
/**
- * Source and destination address of a path to be established
+ * struct rtrs_addr - Source and destination address of a path to be established
+ * @src: source address
+ * @dst: destination address
*/
struct rtrs_addr {
struct sockaddr_storage *src;
@@ -41,7 +43,7 @@ struct rtrs_addr {
};
/**
- * rtrs_clt_ops - it holds the link event callback and private pointer.
+ * struct rtrs_clt_ops - it holds the link event callback and private pointer.
* @priv: User supplied private data.
* @link_ev: Event notification callback function for connection state changes
* @priv: User supplied data that was passed to rtrs_clt_open()
@@ -67,10 +69,10 @@ enum wait_type {
};
/**
- * enum rtrs_clt_con_type() type of ib connection to use with a given
+ * enum rtrs_clt_con_type - type of ib connection to use with a given
* rtrs_permit
- * @ADMIN_CON - use connection reserved for "service" messages
- * @IO_CON - use a connection reserved for IO
+ * @RTRS_ADMIN_CON: use connection reserved for "service" messages
+ * @RTRS_IO_CON: use a connection reserved for IO
*/
enum rtrs_clt_con_type {
RTRS_ADMIN_CON,
@@ -85,7 +87,7 @@ void rtrs_clt_put_permit(struct rtrs_clt_sess *sess,
struct rtrs_permit *permit);
/**
- * rtrs_clt_req_ops - it holds the request confirmation callback
+ * struct rtrs_clt_req_ops - it holds the request confirmation callback
* and a private pointer.
* @priv: User supplied private data.
* @conf_fn: callback function to be called as confirmation
@@ -105,7 +107,11 @@ int rtrs_clt_request(int dir, struct rtrs_clt_req_ops *ops,
int rtrs_clt_rdma_cq_direct(struct rtrs_clt_sess *clt, unsigned int index);
/**
- * rtrs_attrs - RTRS session attributes
+ * struct rtrs_attrs - RTRS session attributes
+ * @queue_depth: queue_depth saved from rtrs_clt_sess message
+ * @max_io_size: max_io_size from rtrs_clt_sess message, capped to
+ * @max_segments * %SZ_4K
+ * @max_segments: max_segments saved from rtrs_clt_sess message
*/
struct rtrs_attrs {
u32 queue_depth;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index e5922a682953..6d73f6e196a9 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1999,7 +1999,6 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *freshest, struc
mddev->layout = le32_to_cpu(sb->layout);
mddev->raid_disks = le32_to_cpu(sb->raid_disks);
mddev->dev_sectors = le64_to_cpu(sb->size);
- mddev->logical_block_size = le32_to_cpu(sb->logical_block_size);
mddev->events = ev1;
mddev->bitmap_info.offset = 0;
mddev->bitmap_info.space = 0;
@@ -2015,6 +2014,9 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *freshest, struc
mddev->max_disks = (4096-256)/2;
+ if (!mddev->logical_block_size)
+ mddev->logical_block_size = le32_to_cpu(sb->logical_block_size);
+
if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET) &&
mddev->bitmap_info.file == NULL) {
mddev->bitmap_info.offset =
@@ -3882,7 +3884,6 @@ out_free_rdev:
static int analyze_sbs(struct mddev *mddev)
{
- int i;
struct md_rdev *rdev, *freshest, *tmp;
freshest = NULL;
@@ -3909,11 +3910,9 @@ static int analyze_sbs(struct mddev *mddev)
super_types[mddev->major_version].
validate_super(mddev, NULL/*freshest*/, freshest);
- i = 0;
rdev_for_each_safe(rdev, tmp, mddev) {
if (mddev->max_disks &&
- (rdev->desc_nr >= mddev->max_disks ||
- i > mddev->max_disks)) {
+ rdev->desc_nr >= mddev->max_disks) {
pr_warn("md: %s: %pg: only %d devices permitted\n",
mdname(mddev), rdev->bdev,
mddev->max_disks);
@@ -4407,7 +4406,7 @@ raid_disks_store(struct mddev *mddev, const char *buf, size_t len)
if (err < 0)
return err;
- err = mddev_lock(mddev);
+ err = mddev_suspend_and_lock(mddev);
if (err)
return err;
if (mddev->pers)
@@ -4432,7 +4431,7 @@ raid_disks_store(struct mddev *mddev, const char *buf, size_t len)
} else
mddev->raid_disks = n;
out_unlock:
- mddev_unlock(mddev);
+ mddev_unlock_and_resume(mddev);
return err ? err : len;
}
static struct md_sysfs_entry md_raid_disks =
@@ -5981,13 +5980,33 @@ lbs_store(struct mddev *mddev, const char *buf, size_t len)
if (mddev->major_version == 0)
return -EINVAL;
- if (mddev->pers)
- return -EBUSY;
-
err = kstrtouint(buf, 10, &lbs);
if (err < 0)
return -EINVAL;
+ if (mddev->pers) {
+ unsigned int curr_lbs;
+
+ if (mddev->logical_block_size)
+ return -EBUSY;
+ /*
+ * To fix forward compatibility issues, LBS is not
+ * configured for arrays from old kernels (<=6.18) by default.
+ * If the user confirms no rollback to old kernels,
+ * enable LBS by writing current LBS — to prevent data
+ * loss from LBS changes.
+ */
+ curr_lbs = queue_logical_block_size(mddev->gendisk->queue);
+ if (lbs != curr_lbs)
+ return -EINVAL;
+
+ mddev->logical_block_size = curr_lbs;
+ set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
+ pr_info("%s: logical block size configured successfully, array will not be assembled in old kernels (<= 6.18)\n",
+ mdname(mddev));
+ return len;
+ }
+
err = mddev_lock(mddev);
if (err)
goto unlock;
@@ -6163,7 +6182,27 @@ int mddev_stack_rdev_limits(struct mddev *mddev, struct queue_limits *lim,
mdname(mddev));
return -EINVAL;
}
- mddev->logical_block_size = lim->logical_block_size;
+
+ /* Only 1.x meta needs to set logical block size */
+ if (mddev->major_version == 0)
+ return 0;
+
+ /*
+ * Fix forward compatibility issue. Only set LBS by default for
+ * new arrays, mddev->events == 0 indicates the array was just
+ * created. When assembling an array, read LBS from the superblock
+ * instead — LBS is 0 in superblocks created by old kernels.
+ */
+ if (!mddev->events) {
+ pr_info("%s: array will not be assembled in old kernels that lack configurable LBS support (<= 6.18)\n",
+ mdname(mddev));
+ mddev->logical_block_size = lim->logical_block_size;
+ }
+
+ if (!mddev->logical_block_size)
+ pr_warn("%s: echo current LBS to md/logical_block_size to prevent data loss issues from LBS changes.\n"
+ "\tNote: After setting, array will not be assembled in old kernels (<= 6.18)\n",
+ mdname(mddev));
return 0;
}
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index e57ce3295292..8dc98f545969 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -7187,12 +7187,14 @@ raid5_store_group_thread_cnt(struct mddev *mddev, const char *page, size_t len)
err = mddev_suspend_and_lock(mddev);
if (err)
return err;
+ conf = mddev->private;
+ if (!conf) {
+ mddev_unlock_and_resume(mddev);
+ return -ENODEV;
+ }
raid5_quiesce(mddev, true);
- conf = mddev->private;
- if (!conf)
- err = -ENODEV;
- else if (new != conf->worker_cnt_per_group) {
+ if (new != conf->worker_cnt_per_group) {
old_groups = conf->worker_groups;
if (old_groups)
flush_workqueue(raid5_wq);
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index a1a177713d99..2c4131ed7e30 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -2169,6 +2169,9 @@ static int b53_fdb_copy(int port, const struct b53_arl_entry *ent,
if (!ent->is_valid)
return 0;
+ if (is_multicast_ether_addr(ent->mac))
+ return 0;
+
if (port != ent->port)
return 0;
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 75893c90a0a1..315d97036ac1 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -2924,19 +2924,26 @@ static int airoha_alloc_gdm_port(struct airoha_eth *eth,
port->id = id;
eth->ports[p] = port;
- err = airoha_metadata_dst_alloc(port);
- if (err)
- return err;
+ return airoha_metadata_dst_alloc(port);
+}
- err = register_netdev(dev);
- if (err)
- goto free_metadata_dst;
+static int airoha_register_gdm_devices(struct airoha_eth *eth)
+{
+ int i;
- return 0;
+ for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
+ struct airoha_gdm_port *port = eth->ports[i];
+ int err;
-free_metadata_dst:
- airoha_metadata_dst_free(port);
- return err;
+ if (!port)
+ continue;
+
+ err = register_netdev(port->dev);
+ if (err)
+ return err;
+ }
+
+ return 0;
}
static int airoha_probe(struct platform_device *pdev)
@@ -3027,6 +3034,10 @@ static int airoha_probe(struct platform_device *pdev)
}
}
+ err = airoha_register_gdm_devices(eth);
+ if (err)
+ goto error_napi_stop;
+
return 0;
error_napi_stop:
@@ -3040,10 +3051,12 @@ error_hw_cleanup:
for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
struct airoha_gdm_port *port = eth->ports[i];
- if (port && port->dev->reg_state == NETREG_REGISTERED) {
+ if (!port)
+ continue;
+
+ if (port->dev->reg_state == NETREG_REGISTERED)
unregister_netdev(port->dev);
- airoha_metadata_dst_free(port);
- }
+ airoha_metadata_dst_free(port);
}
free_netdev(eth->napi_dev);
platform_set_drvdata(pdev, NULL);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index a68757e8fd22..c63ddb12237e 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -1928,6 +1928,7 @@ static void xgbe_set_rx_adap_mode(struct xgbe_prv_data *pdata,
{
if (pdata->rx_adapt_retries++ >= MAX_RX_ADAPT_RETRIES) {
pdata->rx_adapt_retries = 0;
+ pdata->mode_set = false;
return;
}
@@ -1974,6 +1975,7 @@ static void xgbe_rx_adaptation(struct xgbe_prv_data *pdata)
*/
netif_dbg(pdata, link, pdata->netdev, "Block_lock done");
pdata->rx_adapt_done = true;
+ pdata->rx_adapt_retries = 0;
pdata->mode_set = false;
return;
}
diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig
index 666522d64775..ca565ace6e6a 100644
--- a/drivers/net/ethernet/broadcom/Kconfig
+++ b/drivers/net/ethernet/broadcom/Kconfig
@@ -255,14 +255,14 @@ config BNXT_HWMON
devices, via the hwmon sysfs interface.
config BNGE
- tristate "Broadcom Ethernet device support"
+ tristate "Broadcom ThorUltra Ethernet device support"
depends on PCI
select NET_DEVLINK
select PAGE_POOL
help
- This driver supports Broadcom 50/100/200/400/800 gigabit Ethernet cards.
- The module will be called bng_en. To compile this driver as a module,
- choose M here.
+ This driver supports Broadcom ThorUltra 50/100/200/400/800 gigabit
+ Ethernet cards. The module will be called bng_en. To compile this
+ driver as a module, choose M here.
config BCMASP
tristate "Broadcom ASP 2.0 Ethernet support"
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethernet/broadcom/bnge/bnge.h
index 411744894349..32fc16a37d02 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge.h
+++ b/drivers/net/ethernet/broadcom/bnge/bnge.h
@@ -5,7 +5,7 @@
#define _BNGE_H_
#define DRV_NAME "bng_en"
-#define DRV_SUMMARY "Broadcom 800G Ethernet Linux Driver"
+#define DRV_SUMMARY "Broadcom ThorUltra NIC Ethernet Driver"
#include <linux/etherdevice.h>
#include <linux/bnxt/hsi.h>
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_core.c b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
index c94e132bebc8..b4090283df0f 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_core.c
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
@@ -19,7 +19,7 @@ char bnge_driver_name[] = DRV_NAME;
static const struct {
char *name;
} board_info[] = {
- [BCM57708] = { "Broadcom BCM57708 50Gb/100Gb/200Gb/400Gb/800Gb Ethernet" },
+ [BCM57708] = { "Broadcom BCM57708 ThorUltra 50Gb/100Gb/200Gb/400Gb/800Gb Ethernet" },
};
static const struct pci_device_id bnge_pci_tbl[] = {
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index e461f5072884..6511ecd5856b 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -708,7 +708,6 @@ static void macb_mac_link_up(struct phylink_config *config,
/* Initialize rings & buffers as clearing MACB_BIT(TE) in link down
* cleared the pipeline and control registers.
*/
- bp->macbgem_ops.mog_init_rings(bp);
macb_init_buffers(bp);
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue)
@@ -2954,6 +2953,8 @@ static int macb_open(struct net_device *dev)
goto pm_exit;
}
+ bp->macbgem_ops.mog_init_rings(bp);
+
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
napi_enable(&queue->napi_rx);
napi_enable(&queue->napi_tx);
diff --git a/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c b/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c
index 443983fdecd9..7fd39f895290 100644
--- a/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c
+++ b/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c
@@ -577,11 +577,17 @@ static int imx94_enetc_mdio_phyaddr_config(struct netc_blk_ctrl *priv,
}
addr = netc_get_phy_addr(np);
- if (addr <= 0) {
+ if (addr < 0) {
dev_err(dev, "Failed to get PHY address\n");
return addr;
}
+ /* The default value of LaBCR[MDIO_PHYAD_PRTAD] is 0,
+ * so no need to set the register.
+ */
+ if (!addr)
+ return 0;
+
if (phy_mask & BIT(addr)) {
dev_err(dev,
"Find same PHY address in EMDIO and ENETC node\n");
diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
index a7a088a77f37..7eb64e1e4d85 100644
--- a/drivers/net/ethernet/google/gve/gve_main.c
+++ b/drivers/net/ethernet/google/gve/gve_main.c
@@ -558,7 +558,7 @@ static int gve_alloc_notify_blocks(struct gve_priv *priv)
block->priv = priv;
err = request_irq(priv->msix_vectors[msix_idx].vector,
gve_is_gqi(priv) ? gve_intr : gve_intr_dqo,
- 0, block->name, block);
+ IRQF_NO_AUTOEN, block->name, block);
if (err) {
dev_err(&priv->pdev->dev,
"Failed to receive msix vector %d\n", i);
diff --git a/drivers/net/ethernet/google/gve/gve_utils.c b/drivers/net/ethernet/google/gve/gve_utils.c
index ace9b8698021..b53b7fcdcdaf 100644
--- a/drivers/net/ethernet/google/gve/gve_utils.c
+++ b/drivers/net/ethernet/google/gve/gve_utils.c
@@ -112,11 +112,13 @@ void gve_add_napi(struct gve_priv *priv, int ntfy_idx,
netif_napi_add_locked(priv->dev, &block->napi, gve_poll);
netif_napi_set_irq_locked(&block->napi, block->irq);
+ enable_irq(block->irq);
}
void gve_remove_napi(struct gve_priv *priv, int ntfy_idx)
{
struct gve_notify_block *block = &priv->ntfy_blocks[ntfy_idx];
+ disable_irq(block->irq);
netif_napi_del_locked(&block->napi);
}
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index 292389aceb2d..7f078ec9c14c 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -4094,7 +4094,15 @@ static bool e1000_tbi_should_accept(struct e1000_adapter *adapter,
u32 length, const u8 *data)
{
struct e1000_hw *hw = &adapter->hw;
- u8 last_byte = *(data + length - 1);
+ u8 last_byte;
+
+ /* Guard against OOB on data[length - 1] */
+ if (unlikely(!length))
+ return false;
+ /* Upper bound: length must not exceed rx_buffer_len */
+ if (unlikely(length > adapter->rx_buffer_len))
+ return false;
+ last_byte = *(data + length - 1);
if (TBI_ACCEPT(hw, status, errors, length, last_byte)) {
unsigned long irq_flags;
diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
index d2d03db2acec..dcb50c2e1aa2 100644
--- a/drivers/net/ethernet/intel/i40e/i40e.h
+++ b/drivers/net/ethernet/intel/i40e/i40e.h
@@ -1422,4 +1422,15 @@ static inline struct i40e_veb *i40e_pf_get_main_veb(struct i40e_pf *pf)
return (pf->lan_veb != I40E_NO_VEB) ? pf->veb[pf->lan_veb] : NULL;
}
+static inline u32 i40e_get_max_num_descriptors(const struct i40e_pf *pf)
+{
+ const struct i40e_hw *hw = &pf->hw;
+
+ switch (hw->mac.type) {
+ case I40E_MAC_XL710:
+ return I40E_MAX_NUM_DESCRIPTORS_XL710;
+ default:
+ return I40E_MAX_NUM_DESCRIPTORS;
+ }
+}
#endif /* _I40E_H_ */
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
index f2c2646ea298..6a47ea0927e9 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
@@ -2013,18 +2013,6 @@ static void i40e_get_drvinfo(struct net_device *netdev,
drvinfo->n_priv_flags += I40E_GL_PRIV_FLAGS_STR_LEN;
}
-static u32 i40e_get_max_num_descriptors(struct i40e_pf *pf)
-{
- struct i40e_hw *hw = &pf->hw;
-
- switch (hw->mac.type) {
- case I40E_MAC_XL710:
- return I40E_MAX_NUM_DESCRIPTORS_XL710;
- default:
- return I40E_MAX_NUM_DESCRIPTORS;
- }
-}
-
static void i40e_get_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring,
struct kernel_ethtool_ringparam *kernel_ring,
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index d8192aa23254..0b1cc0481027 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -2234,6 +2234,7 @@ static void i40e_set_rx_mode(struct net_device *netdev)
vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
set_bit(__I40E_MACVLAN_SYNC_PENDING, vsi->back->state);
}
+ i40e_service_event_schedule(vsi->back);
}
/**
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index 8b30a3accd31..1fa877b52f61 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -656,7 +656,7 @@ static int i40e_config_vsi_tx_queue(struct i40e_vf *vf, u16 vsi_id,
/* ring_len has to be multiple of 8 */
if (!IS_ALIGNED(info->ring_len, 8) ||
- info->ring_len > I40E_MAX_NUM_DESCRIPTORS_XL710) {
+ info->ring_len > i40e_get_max_num_descriptors(pf)) {
ret = -EINVAL;
goto error_context;
}
@@ -726,7 +726,7 @@ static int i40e_config_vsi_rx_queue(struct i40e_vf *vf, u16 vsi_id,
/* ring_len has to be multiple of 32 */
if (!IS_ALIGNED(info->ring_len, 32) ||
- info->ring_len > I40E_MAX_NUM_DESCRIPTORS_XL710) {
+ info->ring_len > i40e_get_max_num_descriptors(pf)) {
ret = -EINVAL;
goto error_param;
}
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index c2fbe443ef85..4b0fc8f354bc 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -1726,11 +1726,11 @@ static int iavf_config_rss_reg(struct iavf_adapter *adapter)
u16 i;
dw = (u32 *)adapter->rss_key;
- for (i = 0; i <= adapter->rss_key_size / 4; i++)
+ for (i = 0; i < adapter->rss_key_size / 4; i++)
wr32(hw, IAVF_VFQF_HKEY(i), dw[i]);
dw = (u32 *)adapter->rss_lut;
- for (i = 0; i <= adapter->rss_lut_size / 4; i++)
+ for (i = 0; i < adapter->rss_lut_size / 4; i++)
wr32(hw, IAVF_VFQF_HLUT(i), dw[i]);
iavf_flush(hw);
diff --git a/drivers/net/ethernet/intel/idpf/idpf_lib.c b/drivers/net/ethernet/intel/idpf/idpf_lib.c
index 7a7e101afeb6..7ce4eb71a433 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_lib.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c
@@ -1271,7 +1271,7 @@ void idpf_mbx_task(struct work_struct *work)
idpf_mb_irq_enable(adapter);
else
queue_delayed_work(adapter->mbx_wq, &adapter->mbx_task,
- msecs_to_jiffies(300));
+ usecs_to_jiffies(300));
idpf_recv_mb_msg(adapter);
}
diff --git a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
index 44cd4b466c48..5bbe7d9294c1 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
@@ -1016,6 +1016,9 @@ static int idpf_send_get_lan_memory_regions(struct idpf_adapter *adapter)
struct idpf_vc_xn_params xn_params = {
.vc_op = VIRTCHNL2_OP_GET_LAN_MEMORY_REGIONS,
.recv_buf.iov_len = IDPF_CTLQ_MAX_BUF_LEN,
+ .send_buf.iov_len =
+ sizeof(struct virtchnl2_get_lan_memory_regions) +
+ sizeof(struct virtchnl2_mem_region),
.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC,
};
int num_regions, size;
@@ -1028,6 +1031,8 @@ static int idpf_send_get_lan_memory_regions(struct idpf_adapter *adapter)
return -ENOMEM;
xn_params.recv_buf.iov_base = rcvd_regions;
+ rcvd_regions->num_memory_regions = cpu_to_le16(1);
+ xn_params.send_buf.iov_base = rcvd_regions;
reply_sz = idpf_vc_xn_exec(adapter, &xn_params);
if (reply_sz < 0)
return reply_sz;
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
index b90e23dc49de..b6449f0a9e7d 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
@@ -418,6 +418,14 @@ static int otx2_set_ringparam(struct net_device *netdev,
*/
if (rx_count < pfvf->hw.rq_skid)
rx_count = pfvf->hw.rq_skid;
+
+ if (ring->rx_pending < 16) {
+ netdev_err(netdev,
+ "rx ring size %u invalid, min is 16\n",
+ ring->rx_pending);
+ return -EINVAL;
+ }
+
rx_count = Q_COUNT(Q_SIZE(rx_count, 3));
/* Due pipelining impact minimum 2000 unused SQ CQE's
diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c
index efb4e412ec7e..0055c231acf6 100644
--- a/drivers/net/ethernet/microsoft/mana/gdma_main.c
+++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c
@@ -481,7 +481,7 @@ static void mana_serv_reset(struct pci_dev *pdev)
/* Perform PCI rescan on device if we failed on HWC */
dev_err(&pdev->dev, "MANA service: resume failed, rescanning\n");
mana_serv_rescan(pdev);
- goto out;
+ return;
}
if (ret)
diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c
index 9d1a83a5fa7e..d16c178d1034 100644
--- a/drivers/net/ethernet/smsc/smc91x.c
+++ b/drivers/net/ethernet/smsc/smc91x.c
@@ -516,15 +516,7 @@ static inline void smc_rcv(struct net_device *dev)
* any other concurrent access and C would always interrupt B. But life
* isn't that easy in a SMP world...
*/
-#define smc_special_trylock(lock, flags) \
-({ \
- int __ret; \
- local_irq_save(flags); \
- __ret = spin_trylock(lock); \
- if (!__ret) \
- local_irq_restore(flags); \
- __ret; \
-})
+#define smc_special_trylock(lock, flags) spin_trylock_irqsave(lock, flags)
#define smc_special_lock(lock, flags) spin_lock_irqsave(lock, flags)
#define smc_special_unlock(lock, flags) spin_unlock_irqrestore(lock, flags)
#else
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index da206b24aaed..b3730312aeed 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -89,6 +89,7 @@ MODULE_PARM_DESC(phyaddr, "Physical device address");
#define STMMAC_XDP_CONSUMED BIT(0)
#define STMMAC_XDP_TX BIT(1)
#define STMMAC_XDP_REDIRECT BIT(2)
+#define STMMAC_XSK_CONSUMED BIT(3)
static int flow_ctrl = 0xdead;
module_param(flow_ctrl, int, 0644);
@@ -5126,6 +5127,7 @@ static int stmmac_xdp_get_tx_queue(struct stmmac_priv *priv,
static int stmmac_xdp_xmit_back(struct stmmac_priv *priv,
struct xdp_buff *xdp)
{
+ bool zc = !!(xdp->rxq->mem.type == MEM_TYPE_XSK_BUFF_POOL);
struct xdp_frame *xdpf = xdp_convert_buff_to_frame(xdp);
int cpu = smp_processor_id();
struct netdev_queue *nq;
@@ -5142,9 +5144,18 @@ static int stmmac_xdp_xmit_back(struct stmmac_priv *priv,
/* Avoids TX time-out as we are sharing with slow path */
txq_trans_cond_update(nq);
- res = stmmac_xdp_xmit_xdpf(priv, queue, xdpf, false);
- if (res == STMMAC_XDP_TX)
+ /* For zero copy XDP_TX action, dma_map is true */
+ res = stmmac_xdp_xmit_xdpf(priv, queue, xdpf, zc);
+ if (res == STMMAC_XDP_TX) {
stmmac_flush_tx_descriptors(priv, queue);
+ } else if (res == STMMAC_XDP_CONSUMED && zc) {
+ /* xdp has been freed by xdp_convert_buff_to_frame(),
+ * no need to call xsk_buff_free() again, so return
+ * STMMAC_XSK_CONSUMED.
+ */
+ res = STMMAC_XSK_CONSUMED;
+ xdp_return_frame(xdpf);
+ }
__netif_tx_unlock(nq);
@@ -5494,6 +5505,8 @@ read_again:
break;
case STMMAC_XDP_CONSUMED:
xsk_buff_free(buf->xdp);
+ fallthrough;
+ case STMMAC_XSK_CONSUMED:
rx_dropped++;
break;
case STMMAC_XDP_TX:
diff --git a/drivers/net/ethernet/wangxun/Kconfig b/drivers/net/ethernet/wangxun/Kconfig
index d138dea7d208..ec278f99d295 100644
--- a/drivers/net/ethernet/wangxun/Kconfig
+++ b/drivers/net/ethernet/wangxun/Kconfig
@@ -21,6 +21,7 @@ config LIBWX
depends on PTP_1588_CLOCK_OPTIONAL
select PAGE_POOL
select DIMLIB
+ select PHYLINK
help
Common library for Wangxun(R) Ethernet drivers.
@@ -29,7 +30,6 @@ config NGBE
depends on PCI
depends on PTP_1588_CLOCK_OPTIONAL
select LIBWX
- select PHYLINK
help
This driver supports Wangxun(R) GbE PCI Express family of
adapters.
@@ -48,7 +48,6 @@ config TXGBE
depends on PTP_1588_CLOCK_OPTIONAL
select MARVELL_10G_PHY
select REGMAP
- select PHYLINK
select HWMON if TXGBE=y
select SFP
select GPIOLIB
@@ -71,7 +70,6 @@ config TXGBEVF
depends on PCI_MSI
depends on PTP_1588_CLOCK_OPTIONAL
select LIBWX
- select PHYLINK
help
This driver supports virtual functions for SP1000A, WX1820AL,
WX5XXX, WX5XXXAL.
diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index b9b5554ea862..5ad2673f213d 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -334,7 +334,7 @@ int fjes_hw_init(struct fjes_hw *hw)
ret = fjes_hw_reset(hw);
if (ret)
- return ret;
+ goto err_iounmap;
fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true);
@@ -347,8 +347,10 @@ int fjes_hw_init(struct fjes_hw *hw)
hw->max_epid = fjes_hw_get_max_epid(hw);
hw->my_epid = fjes_hw_get_my_epid(hw);
- if ((hw->max_epid == 0) || (hw->my_epid >= hw->max_epid))
- return -ENXIO;
+ if ((hw->max_epid == 0) || (hw->my_epid >= hw->max_epid)) {
+ ret = -ENXIO;
+ goto err_iounmap;
+ }
ret = fjes_hw_setup(hw);
@@ -356,6 +358,10 @@ int fjes_hw_init(struct fjes_hw *hw)
hw->hw_info.trace_size = FJES_DEBUG_BUFFER_SIZE;
return ret;
+
+err_iounmap:
+ fjes_hw_iounmap(hw);
+ return ret;
}
void fjes_hw_exit(struct fjes_hw *hw)
diff --git a/drivers/net/mdio/mdio-aspeed.c b/drivers/net/mdio/mdio-aspeed.c
index e55be6dc9ae7..d6b9004c61dc 100644
--- a/drivers/net/mdio/mdio-aspeed.c
+++ b/drivers/net/mdio/mdio-aspeed.c
@@ -63,6 +63,13 @@ static int aspeed_mdio_op(struct mii_bus *bus, u8 st, u8 op, u8 phyad, u8 regad,
iowrite32(ctrl, ctx->base + ASPEED_MDIO_CTRL);
+ /* Workaround for read-after-write issue.
+ * The controller may return stale data if a read follows immediately
+ * after a write. A dummy read forces the hardware to update its
+ * internal state, ensuring that the next real read returns correct data.
+ */
+ ioread32(ctx->base + ASPEED_MDIO_CTRL);
+
return readl_poll_timeout(ctx->base + ASPEED_MDIO_CTRL, ctrl,
!(ctrl & ASPEED_MDIO_CTRL_FIRE),
ASPEED_MDIO_INTERVAL_US,
diff --git a/drivers/net/mdio/mdio-realtek-rtl9300.c b/drivers/net/mdio/mdio-realtek-rtl9300.c
index 33694c3ff9a7..405a07075dd1 100644
--- a/drivers/net/mdio/mdio-realtek-rtl9300.c
+++ b/drivers/net/mdio/mdio-realtek-rtl9300.c
@@ -354,7 +354,6 @@ static int rtl9300_mdiobus_probe_one(struct device *dev, struct rtl9300_mdio_pri
struct fwnode_handle *node)
{
struct rtl9300_mdio_chan *chan;
- struct fwnode_handle *child;
struct mii_bus *bus;
u32 mdio_bus;
int err;
@@ -371,7 +370,7 @@ static int rtl9300_mdiobus_probe_one(struct device *dev, struct rtl9300_mdio_pri
* compatible = "ethernet-phy-ieee802.3-c45". This does mean we can't
* support both c45 and c22 on the same MDIO bus.
*/
- fwnode_for_each_child_node(node, child)
+ fwnode_for_each_child_node_scoped(node, child)
if (fwnode_device_is_compatible(child, "ethernet-phy-ieee802.3-c45"))
priv->smi_bus_is_c45[mdio_bus] = true;
@@ -409,7 +408,6 @@ static int rtl9300_mdiobus_map_ports(struct device *dev)
{
struct rtl9300_mdio_priv *priv = dev_get_drvdata(dev);
struct device *parent = dev->parent;
- struct fwnode_handle *port;
int err;
struct fwnode_handle *ports __free(fwnode_handle) =
@@ -418,7 +416,7 @@ static int rtl9300_mdiobus_map_ports(struct device *dev)
return dev_err_probe(dev, -EINVAL, "%pfwP missing ethernet-ports\n",
dev_fwnode(parent));
- fwnode_for_each_child_node(ports, port) {
+ fwnode_for_each_child_node_scoped(ports, port) {
struct device_node *mdio_dn;
u32 addr;
u32 bus;
diff --git a/drivers/net/phy/mediatek/mtk-ge-soc.c b/drivers/net/phy/mediatek/mtk-ge-soc.c
index cd09fbf92ef2..2c4bbc236202 100644
--- a/drivers/net/phy/mediatek/mtk-ge-soc.c
+++ b/drivers/net/phy/mediatek/mtk-ge-soc.c
@@ -1167,9 +1167,9 @@ static int mt798x_phy_calibration(struct phy_device *phydev)
}
buf = (u32 *)nvmem_cell_read(cell, &len);
+ nvmem_cell_put(cell);
if (IS_ERR(buf))
return PTR_ERR(buf);
- nvmem_cell_put(cell);
if (!buf[0] || !buf[1] || !buf[2] || !buf[3] || len < 4 * sizeof(u32)) {
phydev_err(phydev, "invalid efuse data\n");
diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c
index 4d5c9ae8f221..c08a5c1bd6e4 100644
--- a/drivers/net/team/team_core.c
+++ b/drivers/net/team/team_core.c
@@ -878,7 +878,7 @@ static void __team_queue_override_enabled_check(struct team *team)
static void team_queue_override_port_prio_changed(struct team *team,
struct team_port *port)
{
- if (!port->queue_id || team_port_enabled(port))
+ if (!port->queue_id || !team_port_enabled(port))
return;
__team_queue_override_port_del(team, port);
__team_queue_override_port_add(team, port);
diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c
index 7fd763917ae2..6ab3486072cb 100644
--- a/drivers/net/usb/asix_common.c
+++ b/drivers/net/usb/asix_common.c
@@ -335,6 +335,11 @@ int asix_read_phy_addr(struct usbnet *dev, bool internal)
offset = (internal ? 1 : 0);
ret = buf[offset];
+ if (ret >= PHY_MAX_ADDR) {
+ netdev_err(dev->net, "invalid PHY address: %d\n", ret);
+ return -ENODEV;
+ }
+
netdev_dbg(dev->net, "%s PHY address 0x%x\n",
internal ? "internal" : "external", ret);
diff --git a/drivers/net/usb/ax88172a.c b/drivers/net/usb/ax88172a.c
index f613e4bc68c8..758a423a459b 100644
--- a/drivers/net/usb/ax88172a.c
+++ b/drivers/net/usb/ax88172a.c
@@ -210,11 +210,7 @@ static int ax88172a_bind(struct usbnet *dev, struct usb_interface *intf)
ret = asix_read_phy_addr(dev, priv->use_embdphy);
if (ret < 0)
goto free;
- if (ret >= PHY_MAX_ADDR) {
- netdev_err(dev->net, "Invalid PHY address %#x\n", ret);
- ret = -ENODEV;
- goto free;
- }
+
priv->phy_addr = ret;
ax88172a_reset_phy(dev, priv->use_embdphy);
diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c
index 278e6cb6f4d9..e40b0669d9f4 100644
--- a/drivers/net/usb/rtl8150.c
+++ b/drivers/net/usb/rtl8150.c
@@ -211,6 +211,8 @@ static int async_set_registers(rtl8150_t *dev, u16 indx, u16 size, u16 reg)
if (res == -ENODEV)
netif_device_detach(dev->netdev);
dev_err(&dev->udev->dev, "%s failed with %d\n", __func__, res);
+ kfree(req);
+ usb_free_urb(async_urb);
}
return res;
}
diff --git a/drivers/net/usb/sr9700.c b/drivers/net/usb/sr9700.c
index 091bc2aca7e8..820c4c506979 100644
--- a/drivers/net/usb/sr9700.c
+++ b/drivers/net/usb/sr9700.c
@@ -52,7 +52,7 @@ static int sr_read_reg(struct usbnet *dev, u8 reg, u8 *value)
static int sr_write_reg(struct usbnet *dev, u8 reg, u8 value)
{
- return usbnet_write_cmd(dev, SR_WR_REGS, SR_REQ_WR_REG,
+ return usbnet_write_cmd(dev, SR_WR_REG, SR_REQ_WR_REG,
value, reg, NULL, 0);
}
@@ -65,7 +65,7 @@ static void sr_write_async(struct usbnet *dev, u8 reg, u16 length,
static void sr_write_reg_async(struct usbnet *dev, u8 reg, u8 value)
{
- usbnet_write_cmd_async(dev, SR_WR_REGS, SR_REQ_WR_REG,
+ usbnet_write_cmd_async(dev, SR_WR_REG, SR_REQ_WR_REG,
value, reg, NULL, 0);
}
@@ -539,6 +539,11 @@ static const struct usb_device_id products[] = {
USB_DEVICE(0x0fe6, 0x9700), /* SR9700 device */
.driver_info = (unsigned long)&sr9700_driver_info,
},
+ {
+ /* SR9700 with virtual driver CD-ROM - interface 0 is the CD-ROM device */
+ USB_DEVICE_INTERFACE_NUMBER(0x0fe6, 0x9702, 1),
+ .driver_info = (unsigned long)&sr9700_driver_info,
+ },
{}, /* END */
};
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 1d9faa70ba3b..36742e64cff7 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -831,7 +831,6 @@ int usbnet_stop(struct net_device *net)
clear_bit(EVENT_DEV_OPEN, &dev->flags);
netif_stop_queue(net);
- netdev_reset_queue(net);
netif_info(dev, ifdown, dev->net,
"stop stats: rx/tx %lu/%lu, errs %lu/%lu\n",
@@ -875,6 +874,8 @@ int usbnet_stop(struct net_device *net)
timer_delete_sync(&dev->delay);
cancel_work_sync(&dev->kevent);
+ netdev_reset_queue(net);
+
if (!pm)
usb_autopm_put_interface(dev->intf);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
index 3391f07b01de..f8fc6f30fbe5 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
@@ -1597,7 +1597,7 @@ static void _iwl_op_mode_stop(struct iwl_drv *drv)
*/
static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
{
- unsigned int min_core, max_core, loaded_core;
+ int min_core, max_core, loaded_core;
struct iwl_drv *drv = context;
struct iwl_fw *fw = &drv->fw;
const struct iwl_ucode_header *ucode;
@@ -1676,7 +1676,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
if (loaded_core < min_core || loaded_core > max_core) {
IWL_ERR(drv,
"Driver unable to support your firmware API. "
- "Driver supports FW core %u..%u, firmware is %u.\n",
+ "Driver supports FW core %d..%d, firmware is %d.\n",
min_core, max_core, loaded_core);
goto try_again;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/ptp.c b/drivers/net/wireless/intel/iwlwifi/mld/ptp.c
index ffeb37a7f830..231920425c06 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/ptp.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/ptp.c
@@ -121,6 +121,12 @@ static int iwl_mld_ptp_gettime(struct ptp_clock_info *ptp,
return 0;
}
+static int iwl_mld_ptp_settime(struct ptp_clock_info *ptp,
+ const struct timespec64 *ts)
+{
+ return -EOPNOTSUPP;
+}
+
static int iwl_mld_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
{
struct iwl_mld *mld = container_of(ptp, struct iwl_mld,
@@ -279,6 +285,7 @@ void iwl_mld_ptp_init(struct iwl_mld *mld)
mld->ptp_data.ptp_clock_info.owner = THIS_MODULE;
mld->ptp_data.ptp_clock_info.gettime64 = iwl_mld_ptp_gettime;
+ mld->ptp_data.ptp_clock_info.settime64 = iwl_mld_ptp_settime;
mld->ptp_data.ptp_clock_info.max_adj = 0x7fffffff;
mld->ptp_data.ptp_clock_info.adjtime = iwl_mld_ptp_adjtime;
mld->ptp_data.ptp_clock_info.adjfine = iwl_mld_ptp_adjfine;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ptp.c b/drivers/net/wireless/intel/iwlwifi/mvm/ptp.c
index 06a4c9f74797..ad156b82eaa9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ptp.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ptp.c
@@ -220,6 +220,12 @@ static int iwl_mvm_ptp_gettime(struct ptp_clock_info *ptp,
return 0;
}
+static int iwl_mvm_ptp_settime(struct ptp_clock_info *ptp,
+ const struct timespec64 *ts)
+{
+ return -EOPNOTSUPP;
+}
+
static int iwl_mvm_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
{
struct iwl_mvm *mvm = container_of(ptp, struct iwl_mvm,
@@ -281,6 +287,7 @@ void iwl_mvm_ptp_init(struct iwl_mvm *mvm)
mvm->ptp_data.ptp_clock_info.adjfine = iwl_mvm_ptp_adjfine;
mvm->ptp_data.ptp_clock_info.adjtime = iwl_mvm_ptp_adjtime;
mvm->ptp_data.ptp_clock_info.gettime64 = iwl_mvm_ptp_gettime;
+ mvm->ptp_data.ptp_clock_info.settime64 = iwl_mvm_ptp_settime;
mvm->ptp_data.scaled_freq = SCALE_FACTOR;
/* Give a short 'friendly name' to identify the PHC clock */
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
index ea99167765b0..0457712286d5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
@@ -3019,7 +3019,7 @@ int mt76_connac2_load_ram(struct mt76_dev *dev, const char *fw_wm,
}
hdr = (const void *)(fw->data + fw->size - sizeof(*hdr));
- dev_info(dev->dev, "WM Firmware Version: %.10s, Build Time: %.15s\n",
+ dev_info(dev->dev, "WM Firmware Version: %.10s, Build Time: %.15s",
hdr->fw_ver, hdr->build_date);
ret = mt76_connac_mcu_send_ram_firmware(dev, hdr, fw->data, false);
@@ -3048,7 +3048,7 @@ int mt76_connac2_load_ram(struct mt76_dev *dev, const char *fw_wm,
}
hdr = (const void *)(fw->data + fw->size - sizeof(*hdr));
- dev_info(dev->dev, "WA Firmware Version: %.10s, Build Time: %.15s\n",
+ dev_info(dev->dev, "WA Firmware Version: %.10s, Build Time: %.15s",
hdr->fw_ver, hdr->build_date);
ret = mt76_connac_mcu_send_ram_firmware(dev, hdr, fw->data, true);
@@ -3101,7 +3101,6 @@ int mt76_connac2_load_patch(struct mt76_dev *dev, const char *fw_name)
int i, ret, sem, max_len = mt76_is_sdio(dev) ? 2048 : 4096;
const struct mt76_connac2_patch_hdr *hdr;
const struct firmware *fw = NULL;
- char build_date[17];
sem = mt76_connac_mcu_patch_sem_ctrl(dev, true);
switch (sem) {
@@ -3125,11 +3124,8 @@ int mt76_connac2_load_patch(struct mt76_dev *dev, const char *fw_name)
}
hdr = (const void *)fw->data;
- strscpy(build_date, hdr->build_date, sizeof(build_date));
- build_date[16] = '\0';
- strim(build_date);
- dev_info(dev->dev, "HW/SW Version: 0x%x, Build Time: %.16s\n",
- be32_to_cpu(hdr->hw_sw_ver), build_date);
+ dev_info(dev->dev, "HW/SW Version: 0x%x, Build Time: %.16s",
+ be32_to_cpu(hdr->hw_sw_ver), hdr->build_date);
for (i = 0; i < be32_to_cpu(hdr->desc.n_region); i++) {
struct mt76_connac2_patch_sec *sec;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
index aa702ba7c9f5..d6c35e8d02a5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
@@ -511,7 +511,8 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw,
if (sta) {
sta_entry = (struct rtl_sta_info *)sta->drv_priv;
tid = ieee80211_get_tid(hdr);
- agg_state = sta_entry->tids[tid].agg.agg_state;
+ if (tid < MAX_TID_COUNT)
+ agg_state = sta_entry->tids[tid].agg.agg_state;
ampdu_density = sta->deflink.ht_cap.ampdu_density;
}
diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c
index 99d7c629eac6..e35de52d8eb4 100644
--- a/drivers/net/wireless/realtek/rtw88/sdio.c
+++ b/drivers/net/wireless/realtek/rtw88/sdio.c
@@ -144,8 +144,10 @@ static u32 rtw_sdio_to_io_address(struct rtw_dev *rtwdev, u32 addr,
static bool rtw_sdio_use_direct_io(struct rtw_dev *rtwdev, u32 addr)
{
+ bool might_indirect_under_power_off = rtwdev->chip->id == RTW_CHIP_TYPE_8822C;
+
if (!test_bit(RTW_FLAG_POWERON, rtwdev->flags) &&
- !rtw_sdio_is_bus_addr(addr))
+ !rtw_sdio_is_bus_addr(addr) && might_indirect_under_power_off)
return false;
return !rtw_sdio_is_sdio30_supported(rtwdev) ||
diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
index 009202c627d2..3b5126ffc81a 100644
--- a/drivers/net/wireless/realtek/rtw88/usb.c
+++ b/drivers/net/wireless/realtek/rtw88/usb.c
@@ -965,8 +965,7 @@ static int rtw_usb_init_rx(struct rtw_dev *rtwdev)
struct sk_buff *rx_skb;
int i;
- rtwusb->rxwq = alloc_workqueue("rtw88_usb: rx wq", WQ_BH | WQ_UNBOUND,
- 0);
+ rtwusb->rxwq = alloc_workqueue("rtw88_usb: rx wq", WQ_BH, 0);
if (!rtwusb->rxwq) {
rtw_err(rtwdev, "failed to create RX work queue\n");
return -ENOMEM;
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c
index f76087be2f75..6241866d39df 100644
--- a/drivers/net/wireless/ti/wlcore/tx.c
+++ b/drivers/net/wireless/ti/wlcore/tx.c
@@ -207,6 +207,11 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif,
total_blocks = wlcore_hw_calc_tx_blocks(wl, total_len, spare_blocks);
if (total_blocks <= wl->tx_blocks_available) {
+ if (skb_headroom(skb) < (total_len - skb->len) &&
+ pskb_expand_head(skb, (total_len - skb->len), 0, GFP_ATOMIC)) {
+ wl1271_free_tx_id(wl, id);
+ return -EAGAIN;
+ }
desc = skb_push(skb, total_len - skb->len);
wlcore_hw_set_tx_desc_blocks(wl, desc, total_blocks,
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index a6eb6bffa5ea..eefb2bac8443 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -578,8 +578,8 @@ sba_io_pdir_entry(__le64 *pdir_ptr, space_t sid, phys_addr_t pba,
pba &= IOVP_MASK;
pba |= (ci >> PAGE_SHIFT) & 0xff; /* move CI (8 bits) into lowest byte */
- pba |= SBA_PDIR_VALID_BIT; /* set "valid" bit */
- *pdir_ptr = cpu_to_le64(pba); /* swap and store into I/O Pdir */
+ /* set "valid" bit, swap and store into I/O Pdir */
+ *pdir_ptr = cpu_to_le64((unsigned long)pba | SBA_PDIR_VALID_BIT);
/*
* If the PDC_MODEL capabilities has Non-coherent IO-PDIR bit set
diff --git a/drivers/platform/mellanox/mlxbf-pmc.c b/drivers/platform/mellanox/mlxbf-pmc.c
index 16a2fd9fdd9b..5ec1ad471696 100644
--- a/drivers/platform/mellanox/mlxbf-pmc.c
+++ b/drivers/platform/mellanox/mlxbf-pmc.c
@@ -801,18 +801,18 @@ static const struct mlxbf_pmc_events mlxbf_pmc_llt_miss_events[] = {
{11, "GDC_MISS_MACHINE_CHI_TXDAT"},
{12, "GDC_MISS_MACHINE_CHI_RXDAT"},
{13, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_0"},
- {14, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_1 "},
+ {14, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_1"},
{15, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_2"},
- {16, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_3 "},
- {17, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_0 "},
- {18, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_1 "},
- {19, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_2 "},
- {20, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_3 "},
+ {16, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_3"},
+ {17, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_0"},
+ {18, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_1"},
+ {19, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_2"},
+ {20, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_3"},
{21, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_0"},
{22, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_1"},
{23, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_2"},
{24, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_3"},
- {25, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_0 "},
+ {25, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_0"},
{26, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_1"},
{27, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_2"},
{28, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_3"},
diff --git a/drivers/platform/x86/asus-armoury.h b/drivers/platform/x86/asus-armoury.h
index a1bb2005c3f3..3ac7aea37838 100644
--- a/drivers/platform/x86/asus-armoury.h
+++ b/drivers/platform/x86/asus-armoury.h
@@ -449,12 +449,27 @@ static const struct dmi_system_id power_limits[] = {
.ac_data = &(struct power_limits) {
.ppt_pl1_spl_min = 15,
.ppt_pl1_spl_max = 80,
- .ppt_pl2_sppt_min = 25,
+ .ppt_pl2_sppt_min = 35,
.ppt_pl2_sppt_max = 80,
.ppt_pl3_fppt_min = 35,
- .ppt_pl3_fppt_max = 80
+ .ppt_pl3_fppt_max = 80,
+ .nv_dynamic_boost_min = 5,
+ .nv_dynamic_boost_max = 25,
+ .nv_temp_target_min = 75,
+ .nv_temp_target_max = 87,
+ },
+ .dc_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 15,
+ .ppt_pl1_spl_def = 45,
+ .ppt_pl1_spl_max = 65,
+ .ppt_pl2_sppt_min = 35,
+ .ppt_pl2_sppt_def = 54,
+ .ppt_pl2_sppt_max = 65,
+ .ppt_pl3_fppt_min = 35,
+ .ppt_pl3_fppt_max = 65,
+ .nv_temp_target_min = 75,
+ .nv_temp_target_max = 87,
},
- .dc_data = NULL,
},
},
{
@@ -554,6 +569,42 @@ static const struct dmi_system_id power_limits[] = {
},
{
.matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "FA608UM"),
+ },
+ .driver_data = &(struct power_data) {
+ .ac_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 15,
+ .ppt_pl1_spl_def = 45,
+ .ppt_pl1_spl_max = 90,
+ .ppt_pl2_sppt_min = 35,
+ .ppt_pl2_sppt_def = 54,
+ .ppt_pl2_sppt_max = 90,
+ .ppt_pl3_fppt_min = 35,
+ .ppt_pl3_fppt_def = 90,
+ .ppt_pl3_fppt_max = 65,
+ .nv_dynamic_boost_min = 10,
+ .nv_dynamic_boost_max = 15,
+ .nv_temp_target_min = 75,
+ .nv_temp_target_max = 87,
+ .nv_tgp_min = 55,
+ .nv_tgp_max = 100,
+ },
+ .dc_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 15,
+ .ppt_pl1_spl_def = 45,
+ .ppt_pl1_spl_max = 65,
+ .ppt_pl2_sppt_min = 35,
+ .ppt_pl2_sppt_def = 54,
+ .ppt_pl2_sppt_max = 65,
+ .ppt_pl3_fppt_min = 35,
+ .ppt_pl3_fppt_max = 65,
+ .nv_temp_target_min = 75,
+ .nv_temp_target_max = 87,
+ },
+ },
+ },
+ {
+ .matches = {
DMI_MATCH(DMI_BOARD_NAME, "FA608WI"),
},
.driver_data = &(struct power_data) {
@@ -824,6 +875,38 @@ static const struct dmi_system_id power_limits[] = {
},
{
.matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "GA403WR"),
+ },
+ .driver_data = &(struct power_data) {
+ .ac_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 15,
+ .ppt_pl1_spl_max = 80,
+ .ppt_pl2_sppt_min = 25,
+ .ppt_pl2_sppt_max = 80,
+ .ppt_pl3_fppt_min = 35,
+ .ppt_pl3_fppt_max = 80,
+ .nv_dynamic_boost_min = 0,
+ .nv_dynamic_boost_max = 25,
+ .nv_temp_target_min = 75,
+ .nv_temp_target_max = 87,
+ .nv_tgp_min = 80,
+ .nv_tgp_max = 95,
+ },
+ .dc_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 15,
+ .ppt_pl1_spl_max = 35,
+ .ppt_pl2_sppt_min = 25,
+ .ppt_pl2_sppt_max = 35,
+ .ppt_pl3_fppt_min = 35,
+ .ppt_pl3_fppt_max = 65,
+ .nv_temp_target_min = 75,
+ .nv_temp_target_max = 87,
+ },
+ .requires_fan_curve = true,
+ },
+ },
+ {
+ .matches = {
DMI_MATCH(DMI_BOARD_NAME, "GA503QR"),
},
.driver_data = &(struct power_data) {
@@ -952,6 +1035,35 @@ static const struct dmi_system_id power_limits[] = {
},
{
.matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "GU605CR"),
+ },
+ .driver_data = &(struct power_data) {
+ .ac_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 30,
+ .ppt_pl1_spl_max = 85,
+ .ppt_pl2_sppt_min = 38,
+ .ppt_pl2_sppt_max = 110,
+ .nv_dynamic_boost_min = 5,
+ .nv_dynamic_boost_max = 20,
+ .nv_temp_target_min = 75,
+ .nv_temp_target_max = 87,
+ .nv_tgp_min = 80,
+ .nv_tgp_def = 90,
+ .nv_tgp_max = 105,
+ },
+ .dc_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 30,
+ .ppt_pl1_spl_max = 85,
+ .ppt_pl2_sppt_min = 38,
+ .ppt_pl2_sppt_max = 110,
+ .nv_temp_target_min = 75,
+ .nv_temp_target_max = 87,
+ },
+ .requires_fan_curve = true,
+ },
+ },
+ {
+ .matches = {
DMI_MATCH(DMI_BOARD_NAME, "GU605CW"),
},
.driver_data = &(struct power_data) {
@@ -1262,6 +1374,35 @@ static const struct dmi_system_id power_limits[] = {
},
{
.matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "G615LR"),
+ },
+ .driver_data = &(struct power_data) {
+ .ac_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 28,
+ .ppt_pl1_spl_def = 140,
+ .ppt_pl1_spl_max = 175,
+ .ppt_pl2_sppt_min = 28,
+ .ppt_pl2_sppt_max = 175,
+ .nv_temp_target_min = 75,
+ .nv_temp_target_max = 87,
+ .nv_dynamic_boost_min = 5,
+ .nv_dynamic_boost_max = 25,
+ .nv_tgp_min = 65,
+ .nv_tgp_max = 115,
+ },
+ .dc_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 25,
+ .ppt_pl1_spl_max = 55,
+ .ppt_pl2_sppt_min = 25,
+ .ppt_pl2_sppt_max = 70,
+ .nv_temp_target_min = 75,
+ .nv_temp_target_max = 87,
+ },
+ .requires_fan_curve = true,
+ },
+ },
+ {
+ .matches = {
DMI_MATCH(DMI_BOARD_NAME, "G634J"),
},
.driver_data = &(struct power_data) {
@@ -1428,6 +1569,35 @@ static const struct dmi_system_id power_limits[] = {
},
{
.matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "G835LW"),
+ },
+ .driver_data = &(struct power_data) {
+ .ac_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 28,
+ .ppt_pl1_spl_def = 140,
+ .ppt_pl1_spl_max = 175,
+ .ppt_pl2_sppt_min = 28,
+ .ppt_pl2_sppt_max = 175,
+ .nv_dynamic_boost_min = 5,
+ .nv_dynamic_boost_max = 25,
+ .nv_temp_target_min = 75,
+ .nv_temp_target_max = 87,
+ .nv_tgp_min = 80,
+ .nv_tgp_max = 150,
+ },
+ .dc_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 25,
+ .ppt_pl1_spl_max = 55,
+ .ppt_pl2_sppt_min = 25,
+ .ppt_pl2_sppt_max = 70,
+ .nv_temp_target_min = 75,
+ .nv_temp_target_max = 87,
+ },
+ .requires_fan_curve = true,
+ },
+ },
+ {
+ .matches = {
DMI_MATCH(DMI_BOARD_NAME, "H7606W"),
},
.driver_data = &(struct power_data) {
diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c
index 6a62bc5b02fd..a38a65f5c550 100644
--- a/drivers/platform/x86/asus-nb-wmi.c
+++ b/drivers/platform/x86/asus-nb-wmi.c
@@ -580,6 +580,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
{ KE_KEY, 0x2a, { KEY_SELECTIVE_SCREENSHOT } },
{ KE_IGNORE, 0x2b, }, /* PrintScreen (also send via PS/2) on newer models */
{ KE_IGNORE, 0x2c, }, /* CapsLock (also send via PS/2) on newer models */
+ { KE_KEY, 0x2d, { KEY_DISPLAYTOGGLE } },
{ KE_KEY, 0x30, { KEY_VOLUMEUP } },
{ KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
{ KE_KEY, 0x32, { KEY_MUTE } },
diff --git a/drivers/platform/x86/dell/alienware-wmi-wmax.c b/drivers/platform/x86/dell/alienware-wmi-wmax.c
index 1418bd326edf..e69b50162bb1 100644
--- a/drivers/platform/x86/dell/alienware-wmi-wmax.c
+++ b/drivers/platform/x86/dell/alienware-wmi-wmax.c
@@ -90,6 +90,30 @@ static struct awcc_quirks empty_quirks;
static const struct dmi_system_id awcc_dmi_table[] __initconst = {
{
+ .ident = "Alienware 16 Area-51",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Alienware 16 Area-51"),
+ },
+ .driver_data = &g_series_quirks,
+ },
+ {
+ .ident = "Alienware 16X Aurora",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Alienware 16X Aurora"),
+ },
+ .driver_data = &g_series_quirks,
+ },
+ {
+ .ident = "Alienware 18 Area-51",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Alienware 18 Area-51"),
+ },
+ .driver_data = &g_series_quirks,
+ },
+ {
.ident = "Alienware 16 Aurora",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
@@ -162,6 +186,14 @@ static const struct dmi_system_id awcc_dmi_table[] __initconst = {
.driver_data = &generic_quirks,
},
{
+ .ident = "Alienware x16",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Alienware x16"),
+ },
+ .driver_data = &g_series_quirks,
+ },
+ {
.ident = "Alienware x17",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
diff --git a/drivers/platform/x86/dell/dell-lis3lv02d.c b/drivers/platform/x86/dell/dell-lis3lv02d.c
index 77905a9ddde9..fe52bcd896f7 100644
--- a/drivers/platform/x86/dell/dell-lis3lv02d.c
+++ b/drivers/platform/x86/dell/dell-lis3lv02d.c
@@ -44,6 +44,7 @@ static const struct dmi_system_id lis3lv02d_devices[] __initconst = {
/*
* Additional individual entries were added after verification.
*/
+ DELL_LIS3LV02D_DMI_ENTRY("Latitude 5400", 0x29),
DELL_LIS3LV02D_DMI_ENTRY("Latitude 5480", 0x29),
DELL_LIS3LV02D_DMI_ENTRY("Latitude 5500", 0x29),
DELL_LIS3LV02D_DMI_ENTRY("Latitude E6330", 0x29),
diff --git a/drivers/platform/x86/hp/hp-bioscfg/enum-attributes.c b/drivers/platform/x86/hp/hp-bioscfg/enum-attributes.c
index c50ad5880503..f346aad8e9d8 100644
--- a/drivers/platform/x86/hp/hp-bioscfg/enum-attributes.c
+++ b/drivers/platform/x86/hp/hp-bioscfg/enum-attributes.c
@@ -207,7 +207,7 @@ static int hp_populate_enumeration_elements_from_package(union acpi_object *enum
case PREREQUISITES:
size = min_t(u32, enum_data->common.prerequisites_size, MAX_PREREQUISITES_SIZE);
for (reqs = 0; reqs < size; reqs++) {
- if (elem >= enum_obj_count) {
+ if (elem + reqs >= enum_obj_count) {
pr_err("Error enum-objects package is too small\n");
return -EINVAL;
}
@@ -255,7 +255,7 @@ static int hp_populate_enumeration_elements_from_package(union acpi_object *enum
for (pos_values = 0; pos_values < size && pos_values < MAX_VALUES_SIZE;
pos_values++) {
- if (elem >= enum_obj_count) {
+ if (elem + pos_values >= enum_obj_count) {
pr_err("Error enum-objects package is too small\n");
return -EINVAL;
}
diff --git a/drivers/platform/x86/hp/hp-bioscfg/int-attributes.c b/drivers/platform/x86/hp/hp-bioscfg/int-attributes.c
index 6c7f4d5fa9cb..63b1fda2be4e 100644
--- a/drivers/platform/x86/hp/hp-bioscfg/int-attributes.c
+++ b/drivers/platform/x86/hp/hp-bioscfg/int-attributes.c
@@ -227,7 +227,7 @@ static int hp_populate_integer_elements_from_package(union acpi_object *integer_
size = min_t(u32, integer_data->common.prerequisites_size, MAX_PREREQUISITES_SIZE);
for (reqs = 0; reqs < size; reqs++) {
- if (elem >= integer_obj_count) {
+ if (elem + reqs >= integer_obj_count) {
pr_err("Error elem-objects package is too small\n");
return -EINVAL;
}
diff --git a/drivers/platform/x86/hp/hp-bioscfg/order-list-attributes.c b/drivers/platform/x86/hp/hp-bioscfg/order-list-attributes.c
index c6e57bb9d8b7..6a31f47ce3f5 100644
--- a/drivers/platform/x86/hp/hp-bioscfg/order-list-attributes.c
+++ b/drivers/platform/x86/hp/hp-bioscfg/order-list-attributes.c
@@ -216,6 +216,11 @@ static int hp_populate_ordered_list_elements_from_package(union acpi_object *ord
size = min_t(u32, ordered_list_data->common.prerequisites_size,
MAX_PREREQUISITES_SIZE);
for (reqs = 0; reqs < size; reqs++) {
+ if (elem + reqs >= order_obj_count) {
+ pr_err("Error elem-objects package is too small\n");
+ return -EINVAL;
+ }
+
ret = hp_convert_hexstr_to_str(order_obj[elem + reqs].string.pointer,
order_obj[elem + reqs].string.length,
&str_value, &value_len);
diff --git a/drivers/platform/x86/hp/hp-bioscfg/passwdobj-attributes.c b/drivers/platform/x86/hp/hp-bioscfg/passwdobj-attributes.c
index 187b372123ed..ec79d9d50377 100644
--- a/drivers/platform/x86/hp/hp-bioscfg/passwdobj-attributes.c
+++ b/drivers/platform/x86/hp/hp-bioscfg/passwdobj-attributes.c
@@ -303,6 +303,11 @@ static int hp_populate_password_elements_from_package(union acpi_object *passwor
MAX_PREREQUISITES_SIZE);
for (reqs = 0; reqs < size; reqs++) {
+ if (elem + reqs >= password_obj_count) {
+ pr_err("Error elem-objects package is too small\n");
+ return -EINVAL;
+ }
+
ret = hp_convert_hexstr_to_str(password_obj[elem + reqs].string.pointer,
password_obj[elem + reqs].string.length,
&str_value, &value_len);
diff --git a/drivers/platform/x86/hp/hp-bioscfg/string-attributes.c b/drivers/platform/x86/hp/hp-bioscfg/string-attributes.c
index 27758b779b2d..7b885d25650c 100644
--- a/drivers/platform/x86/hp/hp-bioscfg/string-attributes.c
+++ b/drivers/platform/x86/hp/hp-bioscfg/string-attributes.c
@@ -217,7 +217,7 @@ static int hp_populate_string_elements_from_package(union acpi_object *string_ob
MAX_PREREQUISITES_SIZE);
for (reqs = 0; reqs < size; reqs++) {
- if (elem >= string_obj_count) {
+ if (elem + reqs >= string_obj_count) {
pr_err("Error elem-objects package is too small\n");
return -EINVAL;
}
diff --git a/drivers/platform/x86/ibm_rtl.c b/drivers/platform/x86/ibm_rtl.c
index 231b37909801..139956168cf9 100644
--- a/drivers/platform/x86/ibm_rtl.c
+++ b/drivers/platform/x86/ibm_rtl.c
@@ -273,7 +273,7 @@ static int __init ibm_rtl_init(void) {
/* search for the _RTL_ signature at the start of the table */
for (i = 0 ; i < ebda_size/sizeof(unsigned int); i++) {
struct ibm_rtl_table __iomem * tmp;
- tmp = (struct ibm_rtl_table __iomem *) (ebda_map+i);
+ tmp = (struct ibm_rtl_table __iomem *) (ebda_map + i*sizeof(unsigned int));
if ((readq(&tmp->signature) & RTL_MASK) == RTL_SIGNATURE) {
phys_addr_t addr;
unsigned int plen;
diff --git a/drivers/platform/x86/intel/pmt/discovery.c b/drivers/platform/x86/intel/pmt/discovery.c
index 32713a194a55..e500aa327d23 100644
--- a/drivers/platform/x86/intel/pmt/discovery.c
+++ b/drivers/platform/x86/intel/pmt/discovery.c
@@ -503,8 +503,10 @@ static int pmt_features_discovery(struct pmt_features_priv *priv,
ret = kobject_init_and_add(&feature->kobj, ktype, &priv->dev->kobj,
"%s", pmt_feature_names[feature->id]);
- if (ret)
+ if (ret) {
+ kobject_put(&feature->kobj);
return ret;
+ }
kobject_uevent(&feature->kobj, KOBJ_ADD);
pmt_features_add_feat(feature);
@@ -546,9 +548,9 @@ static int pmt_features_probe(struct auxiliary_device *auxdev, const struct auxi
priv->dev = device_create(&intel_pmt_class, &auxdev->dev, MKDEV(0, 0), priv,
"%s-%s", "features", dev_name(priv->parent));
if (IS_ERR(priv->dev))
- return dev_err_probe(priv->dev, PTR_ERR(priv->dev),
+ return dev_err_probe(&auxdev->dev, PTR_ERR(priv->dev),
"Could not create %s-%s device node\n",
- "features", dev_name(priv->dev));
+ "features", dev_name(priv->parent));
/* Initialize each feature */
for (i = 0; i < ivdev->num_resources; i++) {
diff --git a/drivers/platform/x86/lenovo/ideapad-laptop.c b/drivers/platform/x86/lenovo/ideapad-laptop.c
index 5171a077f62c..7d5f7a2f6564 100644
--- a/drivers/platform/x86/lenovo/ideapad-laptop.c
+++ b/drivers/platform/x86/lenovo/ideapad-laptop.c
@@ -1367,7 +1367,7 @@ static const struct key_entry ideapad_keymap[] = {
/* Performance toggle also Fn+Q, handled inside ideapad_wmi_notify() */
{ KE_KEY, 0x3d | IDEAPAD_WMI_KEY, { KEY_PROG4 } },
/* shift + prtsc */
- { KE_KEY, 0x2d | IDEAPAD_WMI_KEY, { KEY_CUT } },
+ { KE_KEY, 0x2d | IDEAPAD_WMI_KEY, { KEY_SELECTIVE_SCREENSHOT } },
{ KE_KEY, 0x29 | IDEAPAD_WMI_KEY, { KEY_TOUCHPAD_TOGGLE } },
{ KE_KEY, 0x2a | IDEAPAD_WMI_KEY, { KEY_ROOT_MENU } },
diff --git a/drivers/platform/x86/lenovo/think-lmi.c b/drivers/platform/x86/lenovo/think-lmi.c
index 540b472b1bf3..c45f0206b4ab 100644
--- a/drivers/platform/x86/lenovo/think-lmi.c
+++ b/drivers/platform/x86/lenovo/think-lmi.c
@@ -195,7 +195,7 @@ static const struct tlmi_cert_guids thinkpad_cert_guid = {
};
static const struct tlmi_cert_guids thinkcenter_cert_guid = {
- .thumbprint = NULL,
+ .thumbprint = LENOVO_CERT_THUMBPRINT_GUID, /* Same GUID as TP */
.set_bios_setting = LENOVO_TC_SET_BIOS_SETTING_CERT_GUID,
.save_bios_setting = LENOVO_TC_SAVE_BIOS_SETTING_CERT_GUID,
.cert_to_password = LENOVO_TC_CERT_TO_PASSWORD_GUID,
@@ -709,6 +709,10 @@ static ssize_t cert_thumbprint(char *buf, const char *arg, int count)
if (!tlmi_priv.cert_guid->thumbprint)
return -EOPNOTSUPP;
+ /* Older ThinkCenter BIOS may not have support */
+ if (!wmi_has_guid(tlmi_priv.cert_guid->thumbprint))
+ return -EOPNOTSUPP;
+
status = wmi_evaluate_method(tlmi_priv.cert_guid->thumbprint, 0, 0, &input, &output);
if (ACPI_FAILURE(status)) {
kfree(output.pointer);
diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c
index c4b150fa093f..ddef6b78d2fa 100644
--- a/drivers/platform/x86/msi-laptop.c
+++ b/drivers/platform/x86/msi-laptop.c
@@ -1130,6 +1130,9 @@ static void __exit msi_cleanup(void)
sysfs_remove_group(&msipf_device->dev.kobj, &msipf_attribute_group);
if (!quirks->old_ec_model && threeg_exists)
device_remove_file(&msipf_device->dev, &dev_attr_threeg);
+ if (quirks->old_ec_model)
+ sysfs_remove_group(&msipf_device->dev.kobj,
+ &msipf_old_attribute_group);
platform_device_unregister(msipf_device);
platform_driver_unregister(&msipf_driver);
backlight_device_unregister(msibl_device);
diff --git a/drivers/platform/x86/samsung-galaxybook.c b/drivers/platform/x86/samsung-galaxybook.c
index 3c13e13d4885..755cb82bdb60 100644
--- a/drivers/platform/x86/samsung-galaxybook.c
+++ b/drivers/platform/x86/samsung-galaxybook.c
@@ -442,12 +442,13 @@ static int galaxybook_battery_ext_property_get(struct power_supply *psy,
union power_supply_propval *val)
{
struct samsung_galaxybook *galaxybook = ext_data;
+ u8 value;
int err;
if (psp != POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD)
return -EINVAL;
- err = charge_control_end_threshold_acpi_get(galaxybook, (u8 *)&val->intval);
+ err = charge_control_end_threshold_acpi_get(galaxybook, &value);
if (err)
return err;
@@ -455,8 +456,10 @@ static int galaxybook_battery_ext_property_get(struct power_supply *psy,
* device stores "no end threshold" as 0 instead of 100;
* if device has 0, report 100
*/
- if (val->intval == 0)
- val->intval = 100;
+ if (value == 0)
+ value = 100;
+
+ val->intval = value;
return 0;
}
diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c
index bd7e63dd5181..0f935532f250 100644
--- a/drivers/platform/x86/uniwill/uniwill-acpi.c
+++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
@@ -1845,6 +1845,13 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
},
},
{
+ .ident = "TUXEDO Book BA15 Gen10 AMD",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "PF5PU1G"),
+ },
+ },
+ {
.ident = "TUXEDO Pulse 14 Gen1 AMD",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
diff --git a/drivers/pmdomain/imx/gpc.c b/drivers/pmdomain/imx/gpc.c
index a34b260274f7..de695f1944ab 100644
--- a/drivers/pmdomain/imx/gpc.c
+++ b/drivers/pmdomain/imx/gpc.c
@@ -402,13 +402,12 @@ clk_err:
static int imx_gpc_probe(struct platform_device *pdev)
{
const struct imx_gpc_dt_data *of_id_data = device_get_match_data(&pdev->dev);
- struct device_node *pgc_node;
+ struct device_node *pgc_node __free(device_node)
+ = of_get_child_by_name(pdev->dev.of_node, "pgc");
struct regmap *regmap;
void __iomem *base;
int ret;
- pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc");
-
/* bail out if DT too old and doesn't provide the necessary info */
if (!of_property_present(pdev->dev.of_node, "#power-domain-cells") &&
!pgc_node)
diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.c b/drivers/pmdomain/mediatek/mtk-pm-domains.c
index 80561d27f2b2..f64f24d520dd 100644
--- a/drivers/pmdomain/mediatek/mtk-pm-domains.c
+++ b/drivers/pmdomain/mediatek/mtk-pm-domains.c
@@ -984,18 +984,6 @@ static void scpsys_domain_cleanup(struct scpsys *scpsys)
}
}
-static struct device_node *scpsys_get_legacy_regmap(struct device_node *np, const char *pn)
-{
- struct device_node *local_node;
-
- for_each_child_of_node(np, local_node) {
- if (of_property_present(local_node, pn))
- return local_node;
- }
-
- return NULL;
-}
-
static int scpsys_get_bus_protection_legacy(struct device *dev, struct scpsys *scpsys)
{
const u8 bp_blocks[3] = {
@@ -1017,7 +1005,8 @@ static int scpsys_get_bus_protection_legacy(struct device *dev, struct scpsys *s
* this makes it then possible to allocate the array of bus_prot
* regmaps and convert all to the new style handling.
*/
- node = scpsys_get_legacy_regmap(np, "mediatek,infracfg");
+ of_node_get(np);
+ node = of_find_node_with_property(np, "mediatek,infracfg");
if (node) {
regmap[0] = syscon_regmap_lookup_by_phandle(node, "mediatek,infracfg");
of_node_put(node);
@@ -1030,7 +1019,8 @@ static int scpsys_get_bus_protection_legacy(struct device *dev, struct scpsys *s
regmap[0] = NULL;
}
- node = scpsys_get_legacy_regmap(np, "mediatek,smi");
+ of_node_get(np);
+ node = of_find_node_with_property(np, "mediatek,smi");
if (node) {
smi_np = of_parse_phandle(node, "mediatek,smi", 0);
of_node_put(node);
@@ -1048,7 +1038,8 @@ static int scpsys_get_bus_protection_legacy(struct device *dev, struct scpsys *s
regmap[1] = NULL;
}
- node = scpsys_get_legacy_regmap(np, "mediatek,infracfg-nao");
+ of_node_get(np);
+ node = of_find_node_with_property(np, "mediatek,infracfg-nao");
if (node) {
regmap[2] = syscon_regmap_lookup_by_phandle(node, "mediatek,infracfg-nao");
num_regmaps++;
diff --git a/drivers/regulator/fp9931.c b/drivers/regulator/fp9931.c
index fef0bb07fd5d..69b3c712e5d5 100644
--- a/drivers/regulator/fp9931.c
+++ b/drivers/regulator/fp9931.c
@@ -391,6 +391,7 @@ static const struct regulator_desc regulators[] = {
{
.name = "v3p3",
.of_match = of_match_ptr("v3p3"),
+ .regulators_node = of_match_ptr("regulators"),
.id = 0,
.ops = &fp9931_v3p3ops,
.type = REGULATOR_VOLTAGE,
@@ -403,6 +404,7 @@ static const struct regulator_desc regulators[] = {
{
.name = "vposneg",
.of_match = of_match_ptr("vposneg"),
+ .regulators_node = of_match_ptr("regulators"),
.id = 1,
.ops = &fp9931_vposneg_ops,
.type = REGULATOR_VOLTAGE,
@@ -415,6 +417,7 @@ static const struct regulator_desc regulators[] = {
{
.name = "vcom",
.of_match = of_match_ptr("vcom"),
+ .regulators_node = of_match_ptr("regulators"),
.id = 2,
.ops = &fp9931_vcom_ops,
.type = REGULATOR_VOLTAGE,
diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h b/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h
index b42933fcd423..6561f98c3cb2 100644
--- a/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h
+++ b/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h
@@ -166,6 +166,7 @@ struct mpi3_ioc_facts_data {
#define MPI3_IOCFACTS_FLAGS_SIGNED_NVDATA_REQUIRED (0x00010000)
#define MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_MASK (0x0000ff00)
#define MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_SHIFT (8)
+#define MPI3_IOCFACTS_FLAGS_MAX_REQ_PER_REPLY_QUEUE_LIMIT (0x00000040)
#define MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_MASK (0x00000030)
#define MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_SHIFT (4)
#define MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_NOT_STARTED (0x00000000)
diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c
index 8fe6e0bf342e..8c4bb7169a87 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_fw.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c
@@ -3158,6 +3158,8 @@ static void mpi3mr_process_factsdata(struct mpi3mr_ioc *mrioc,
mrioc->facts.dma_mask = (facts_flags &
MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_MASK) >>
MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_SHIFT;
+ mrioc->facts.max_req_limit = (facts_flags &
+ MPI3_IOCFACTS_FLAGS_MAX_REQ_PER_REPLY_QUEUE_LIMIT);
mrioc->facts.protocol_flags = facts_data->protocol_flags;
mrioc->facts.mpi_version = le32_to_cpu(facts_data->mpi_version.word);
mrioc->facts.max_reqs = le16_to_cpu(facts_data->max_outstanding_requests);
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 1f2a53ba5dd9..c5085e6d2e75 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -7459,7 +7459,7 @@ MODULE_PARM_DESC(lbprz,
MODULE_PARM_DESC(lbpu, "enable LBP, support UNMAP command (def=0)");
MODULE_PARM_DESC(lbpws, "enable LBP, support WRITE SAME(16) with UNMAP bit (def=0)");
MODULE_PARM_DESC(lbpws10, "enable LBP, support WRITE SAME(10) with UNMAP bit (def=0)");
-MODULE_PARM_DESC(atomic_write, "enable ATOMIC WRITE support, support WRITE ATOMIC(16) (def=0)");
+MODULE_PARM_DESC(atomic_wr, "enable ATOMIC WRITE support, support WRITE ATOMIC(16) (def=0)");
MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)");
MODULE_PARM_DESC(lun_format, "LUN format: 0->peripheral (def); 1 --> flat address method");
MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)");
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index b3af9b78fa12..57fba34832ad 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -731,6 +731,8 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf,
sg_remove_request(sfp, srp);
return -EFAULT;
}
+ hp->duration = jiffies_to_msecs(jiffies);
+
if (hp->interface_id != 'S') {
sg_remove_request(sfp, srp);
return -ENOSYS;
@@ -815,7 +817,6 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
return -ENODEV;
}
- hp->duration = jiffies_to_msecs(jiffies);
if (hp->interface_id != '\0' && /* v3 (or later) interface */
(SG_FLAG_Q_AT_TAIL & hp->flags))
at_head = 0;
@@ -1338,9 +1339,6 @@ sg_rq_end_io(struct request *rq, blk_status_t status)
"sg_cmd_done: pack_id=%d, res=0x%x\n",
srp->header.pack_id, result));
srp->header.resid = resid;
- ms = jiffies_to_msecs(jiffies);
- srp->header.duration = (ms > srp->header.duration) ?
- (ms - srp->header.duration) : 0;
if (0 != result) {
struct scsi_sense_hdr sshdr;
@@ -1389,6 +1387,9 @@ sg_rq_end_io(struct request *rq, blk_status_t status)
done = 0;
}
srp->done = done;
+ ms = jiffies_to_msecs(jiffies);
+ srp->header.duration = (ms > srp->header.duration) ?
+ (ms - srp->header.duration) : 0;
write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
if (likely(done)) {
@@ -2533,6 +2534,7 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
const sg_io_hdr_t *hp;
const char * cp;
unsigned int ms;
+ unsigned int duration;
k = 0;
list_for_each_entry(fp, &sdp->sfds, sfd_siblings) {
@@ -2570,13 +2572,17 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
seq_printf(s, " id=%d blen=%d",
srp->header.pack_id, blen);
if (srp->done)
- seq_printf(s, " dur=%d", hp->duration);
+ seq_printf(s, " dur=%u", hp->duration);
else {
ms = jiffies_to_msecs(jiffies);
- seq_printf(s, " t_o/elap=%d/%d",
+ duration = READ_ONCE(hp->duration);
+ if (duration)
+ duration = (ms > duration ?
+ ms - duration : 0);
+ seq_printf(s, " t_o/elap=%u/%u",
(new_interface ? hp->timeout :
jiffies_to_msecs(fp->timeout)),
- (ms > hp->duration ? ms - hp->duration : 0));
+ duration);
}
seq_printf(s, "ms sgat=%d op=0x%02x\n", usg,
(int) srp->data.cmd_opcode);
diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c
index f8823e83a622..965b4cea3388 100644
--- a/drivers/spi/spi-cadence-quadspi.c
+++ b/drivers/spi/spi-cadence-quadspi.c
@@ -300,6 +300,9 @@ struct cqspi_driver_platdata {
CQSPI_REG_IRQ_IND_SRAM_FULL | \
CQSPI_REG_IRQ_IND_COMP)
+#define CQSPI_IRQ_MASK_RD_SLOW_SRAM (CQSPI_REG_IRQ_WATERMARK | \
+ CQSPI_REG_IRQ_IND_COMP)
+
#define CQSPI_IRQ_MASK_WR (CQSPI_REG_IRQ_IND_COMP | \
CQSPI_REG_IRQ_WATERMARK | \
CQSPI_REG_IRQ_UNDERFLOW)
@@ -381,7 +384,7 @@ static irqreturn_t cqspi_irq_handler(int this_irq, void *dev)
else if (!cqspi->slow_sram)
irq_status &= CQSPI_IRQ_MASK_RD | CQSPI_IRQ_MASK_WR;
else
- irq_status &= CQSPI_REG_IRQ_WATERMARK | CQSPI_IRQ_MASK_WR;
+ irq_status &= CQSPI_IRQ_MASK_RD_SLOW_SRAM | CQSPI_IRQ_MASK_WR;
if (irq_status)
complete(&cqspi->transfer_complete);
@@ -757,7 +760,7 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata,
*/
if (use_irq && cqspi->slow_sram)
- writel(CQSPI_REG_IRQ_WATERMARK, reg_base + CQSPI_REG_IRQMASK);
+ writel(CQSPI_IRQ_MASK_RD_SLOW_SRAM, reg_base + CQSPI_REG_IRQMASK);
else if (use_irq)
writel(CQSPI_IRQ_MASK_RD, reg_base + CQSPI_REG_IRQMASK);
else
@@ -769,17 +772,19 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata,
readl(reg_base + CQSPI_REG_INDIRECTRD); /* Flush posted write. */
while (remaining > 0) {
+ ret = 0;
if (use_irq &&
!wait_for_completion_timeout(&cqspi->transfer_complete,
msecs_to_jiffies(CQSPI_READ_TIMEOUT_MS)))
ret = -ETIMEDOUT;
/*
- * Disable all read interrupts until
- * we are out of "bytes to read"
+ * Prevent lost interrupt and race condition by reinitializing early.
+ * A spurious wakeup and another wait cycle can occur here,
+ * which is preferable to waiting until timeout if interrupt is lost.
*/
- if (cqspi->slow_sram)
- writel(0x0, reg_base + CQSPI_REG_IRQMASK);
+ if (use_irq)
+ reinit_completion(&cqspi->transfer_complete);
bytes_to_read = cqspi_get_rd_sram_level(cqspi);
@@ -811,12 +816,6 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata,
remaining -= bytes_to_read;
bytes_to_read = cqspi_get_rd_sram_level(cqspi);
}
-
- if (use_irq && remaining > 0) {
- reinit_completion(&cqspi->transfer_complete);
- if (cqspi->slow_sram)
- writel(CQSPI_REG_IRQ_WATERMARK, reg_base + CQSPI_REG_IRQMASK);
- }
}
/* Check indirect done status */
diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index 871dfd3e77be..d1de6c99e762 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -795,10 +795,13 @@ static const struct sun6i_spi_cfg sun50i_r329_spi_cfg = {
static const struct of_device_id sun6i_spi_match[] = {
{ .compatible = "allwinner,sun6i-a31-spi", .data = &sun6i_a31_spi_cfg },
{ .compatible = "allwinner,sun8i-h3-spi", .data = &sun8i_h3_spi_cfg },
- {
- .compatible = "allwinner,sun50i-r329-spi",
- .data = &sun50i_r329_spi_cfg
- },
+ { .compatible = "allwinner,sun50i-r329-spi", .data = &sun50i_r329_spi_cfg },
+ /*
+ * A523's SPI controller has a combined RX buffer + FIFO counter
+ * at offset 0x400, instead of split buffer count in FIFO status
+ * register. But in practice we only care about the FIFO level.
+ */
+ { .compatible = "allwinner,sun55i-a523-spi", .data = &sun50i_r329_spi_cfg },
{}
};
MODULE_DEVICE_TABLE(of, sun6i_spi_match);
diff --git a/drivers/tty/serial/8250/8250_loongson.c b/drivers/tty/serial/8250/8250_loongson.c
index 53153a116c01..47df3c4c9d21 100644
--- a/drivers/tty/serial/8250/8250_loongson.c
+++ b/drivers/tty/serial/8250/8250_loongson.c
@@ -128,8 +128,8 @@ static int loongson_uart_probe(struct platform_device *pdev)
port->private_data = priv;
port->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &priv->res);
- if (!port->membase)
- return -ENOMEM;
+ if (IS_ERR(port->membase))
+ return PTR_ERR(port->membase);
port->mapbase = priv->res->start;
port->mapsize = resource_size(priv->res);
diff --git a/drivers/tty/serial/serial_base_bus.c b/drivers/tty/serial/serial_base_bus.c
index 22749ab0428a..1e1ad28d83fc 100644
--- a/drivers/tty/serial/serial_base_bus.c
+++ b/drivers/tty/serial/serial_base_bus.c
@@ -13,7 +13,7 @@
#include <linux/device.h>
#include <linux/idr.h>
#include <linux/module.h>
-#include <linux/of.h>
+#include <linux/property.h>
#include <linux/serial_core.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
@@ -60,6 +60,7 @@ void serial_base_driver_unregister(struct device_driver *driver)
driver_unregister(driver);
}
+/* On failure the caller must put device @dev with put_device() */
static int serial_base_device_init(struct uart_port *port,
struct device *dev,
struct device *parent_dev,
@@ -73,7 +74,9 @@ static int serial_base_device_init(struct uart_port *port,
dev->parent = parent_dev;
dev->bus = &serial_base_bus_type;
dev->release = release;
- device_set_of_node_from_dev(dev, parent_dev);
+ dev->of_node_reused = true;
+
+ device_set_node(dev, fwnode_handle_get(dev_fwnode(parent_dev)));
if (!serial_base_initialized) {
dev_dbg(port->dev, "uart_add_one_port() called before arch_initcall()?\n");
@@ -94,7 +97,7 @@ static void serial_base_ctrl_release(struct device *dev)
{
struct serial_ctrl_device *ctrl_dev = to_serial_base_ctrl_device(dev);
- of_node_put(dev->of_node);
+ fwnode_handle_put(dev_fwnode(dev));
kfree(ctrl_dev);
}
@@ -142,7 +145,7 @@ static void serial_base_port_release(struct device *dev)
{
struct serial_port_device *port_dev = to_serial_base_port_device(dev);
- of_node_put(dev->of_node);
+ fwnode_handle_put(dev_fwnode(dev));
kfree(port_dev);
}
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 53edbf1d8963..fbfe5575bd3c 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -1914,7 +1914,7 @@ static void sci_dma_check_tx_occurred(struct sci_port *s)
struct dma_tx_state state;
enum dma_status status;
- if (!s->chan_tx)
+ if (!s->chan_tx || s->cookie_tx <= 0)
return;
status = dmaengine_tx_status(s->chan_tx, s->cookie_tx, &state);
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
index c793fc74c26b..c593d20a1b5b 100644
--- a/drivers/tty/serial/xilinx_uartps.c
+++ b/drivers/tty/serial/xilinx_uartps.c
@@ -428,10 +428,17 @@ static void cdns_uart_handle_tx(void *dev_id)
struct tty_port *tport = &port->state->port;
unsigned int numbytes;
unsigned char ch;
+ ktime_t rts_delay;
if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) {
/* Disable the TX Empty interrupt */
writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IDR);
+ /* Set RTS line after delay */
+ if (cdns_uart->port->rs485.flags & SER_RS485_ENABLED) {
+ cdns_uart->tx_timer.function = &cdns_rs485_rx_callback;
+ rts_delay = ns_to_ktime(cdns_calc_after_tx_delay(cdns_uart));
+ hrtimer_start(&cdns_uart->tx_timer, rts_delay, HRTIMER_MODE_REL);
+ }
return;
}
@@ -448,13 +455,6 @@ static void cdns_uart_handle_tx(void *dev_id)
/* Enable the TX Empty interrupt */
writel(CDNS_UART_IXR_TXEMPTY, cdns_uart->port->membase + CDNS_UART_IER);
-
- if (cdns_uart->port->rs485.flags & SER_RS485_ENABLED &&
- (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port))) {
- hrtimer_update_function(&cdns_uart->tx_timer, cdns_rs485_rx_callback);
- hrtimer_start(&cdns_uart->tx_timer,
- ns_to_ktime(cdns_calc_after_tx_delay(cdns_uart)), HRTIMER_MODE_REL);
- }
}
/**
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 80c0b49f30b0..0babb7035200 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -10359,7 +10359,7 @@ static int ufshcd_suspend(struct ufs_hba *hba)
ret = ufshcd_setup_clocks(hba, false);
if (ret) {
ufshcd_enable_irq(hba);
- return ret;
+ goto out;
}
if (ufshcd_is_clkgating_allowed(hba)) {
hba->clk_gating.state = CLKS_OFF;
@@ -10371,6 +10371,9 @@ static int ufshcd_suspend(struct ufs_hba *hba)
/* Put the host controller in low power mode if possible */
ufshcd_hba_vreg_set_lpm(hba);
ufshcd_pm_qos_update(hba, false);
+out:
+ if (ret)
+ ufshcd_update_evt_hist(hba, UFS_EVT_SUSPEND_ERR, (u32)ret);
return ret;
}
diff --git a/drivers/usb/dwc3/dwc3-of-simple.c b/drivers/usb/dwc3/dwc3-of-simple.c
index a4954a21be93..c116143335d9 100644
--- a/drivers/usb/dwc3/dwc3-of-simple.c
+++ b/drivers/usb/dwc3/dwc3-of-simple.c
@@ -70,11 +70,11 @@ static int dwc3_of_simple_probe(struct platform_device *pdev)
simple->num_clocks = ret;
ret = clk_bulk_prepare_enable(simple->num_clocks, simple->clks);
if (ret)
- goto err_resetc_assert;
+ goto err_clk_put_all;
ret = of_platform_populate(np, NULL, NULL, dev);
if (ret)
- goto err_clk_put;
+ goto err_clk_disable;
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
@@ -82,8 +82,9 @@ static int dwc3_of_simple_probe(struct platform_device *pdev)
return 0;
-err_clk_put:
+err_clk_disable:
clk_bulk_disable_unprepare(simple->num_clocks, simple->clks);
+err_clk_put_all:
clk_bulk_put_all(simple->num_clocks, simple->clks);
err_resetc_assert:
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index bc3fe31638b9..8a35a6901db7 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -4826,7 +4826,7 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
if (!dwc->gadget)
return;
- dwc3_enable_susphy(dwc, false);
+ dwc3_enable_susphy(dwc, true);
usb_del_gadget(dwc->gadget);
dwc3_gadget_free_endpoints(dwc);
usb_put_gadget(dwc->gadget);
diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index cf6512ed17a6..96b588bd08cd 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -227,7 +227,7 @@ void dwc3_host_exit(struct dwc3 *dwc)
if (dwc->sys_wakeup)
device_init_wakeup(&dwc->xhci->dev, false);
- dwc3_enable_susphy(dwc, false);
+ dwc3_enable_susphy(dwc, true);
platform_device_unregister(dwc->xhci);
dwc->xhci = NULL;
}
diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c
index 1a7d3c4f652f..83c7e243dcf9 100644
--- a/drivers/usb/gadget/udc/lpc32xx_udc.c
+++ b/drivers/usb/gadget/udc/lpc32xx_udc.c
@@ -3020,7 +3020,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
pdev->dev.dma_mask = &lpc32xx_usbd_dmamask;
retval = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
if (retval)
- return retval;
+ goto err_put_client;
udc->board = &lpc32xx_usbddata;
@@ -3038,28 +3038,32 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
/* Get IRQs */
for (i = 0; i < 4; i++) {
udc->udp_irq[i] = platform_get_irq(pdev, i);
- if (udc->udp_irq[i] < 0)
- return udc->udp_irq[i];
+ if (udc->udp_irq[i] < 0) {
+ retval = udc->udp_irq[i];
+ goto err_put_client;
+ }
}
udc->udp_baseaddr = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(udc->udp_baseaddr)) {
dev_err(udc->dev, "IO map failure\n");
- return PTR_ERR(udc->udp_baseaddr);
+ retval = PTR_ERR(udc->udp_baseaddr);
+ goto err_put_client;
}
/* Get USB device clock */
udc->usb_slv_clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(udc->usb_slv_clk)) {
dev_err(udc->dev, "failed to acquire USB device clock\n");
- return PTR_ERR(udc->usb_slv_clk);
+ retval = PTR_ERR(udc->usb_slv_clk);
+ goto err_put_client;
}
/* Enable USB device clock */
retval = clk_prepare_enable(udc->usb_slv_clk);
if (retval < 0) {
dev_err(udc->dev, "failed to start USB device clock\n");
- return retval;
+ goto err_put_client;
}
/* Setup deferred workqueue data */
@@ -3080,7 +3084,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
if (!udc->udca_v_base) {
dev_err(udc->dev, "error getting UDCA region\n");
retval = -ENOMEM;
- goto i2c_fail;
+ goto err_disable_clk;
}
udc->udca_p_base = dma_handle;
dev_dbg(udc->dev, "DMA buffer(0x%x bytes), P:0x%08x, V:0x%p\n",
@@ -3093,7 +3097,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
if (!udc->dd_cache) {
dev_err(udc->dev, "error getting DD DMA region\n");
retval = -ENOMEM;
- goto dma_alloc_fail;
+ goto err_free_dma;
}
/* Clear USB peripheral and initialize gadget endpoints */
@@ -3107,14 +3111,14 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
if (retval < 0) {
dev_err(udc->dev, "LP request irq %d failed\n",
udc->udp_irq[IRQ_USB_LP]);
- goto irq_req_fail;
+ goto err_destroy_pool;
}
retval = devm_request_irq(dev, udc->udp_irq[IRQ_USB_HP],
lpc32xx_usb_hp_irq, 0, "udc_hp", udc);
if (retval < 0) {
dev_err(udc->dev, "HP request irq %d failed\n",
udc->udp_irq[IRQ_USB_HP]);
- goto irq_req_fail;
+ goto err_destroy_pool;
}
retval = devm_request_irq(dev, udc->udp_irq[IRQ_USB_DEVDMA],
@@ -3122,7 +3126,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
if (retval < 0) {
dev_err(udc->dev, "DEV request irq %d failed\n",
udc->udp_irq[IRQ_USB_DEVDMA]);
- goto irq_req_fail;
+ goto err_destroy_pool;
}
/* The transceiver interrupt is used for VBUS detection and will
@@ -3133,7 +3137,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
if (retval < 0) {
dev_err(udc->dev, "VBUS request irq %d failed\n",
udc->udp_irq[IRQ_USB_ATX]);
- goto irq_req_fail;
+ goto err_destroy_pool;
}
/* Initialize wait queue */
@@ -3142,7 +3146,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
retval = usb_add_gadget_udc(dev, &udc->gadget);
if (retval < 0)
- goto add_gadget_fail;
+ goto err_destroy_pool;
dev_set_drvdata(dev, udc);
device_init_wakeup(dev, 1);
@@ -3154,14 +3158,16 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
dev_info(udc->dev, "%s version %s\n", driver_name, DRIVER_VERSION);
return 0;
-add_gadget_fail:
-irq_req_fail:
+err_destroy_pool:
dma_pool_destroy(udc->dd_cache);
-dma_alloc_fail:
+err_free_dma:
dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE,
udc->udca_v_base, udc->udca_p_base);
-i2c_fail:
+err_disable_clk:
clk_disable_unprepare(udc->usb_slv_clk);
+err_put_client:
+ put_device(&udc->isp1301_i2c_client->dev);
+
dev_err(udc->dev, "%s probe failed, %d\n", driver_name, retval);
return retval;
@@ -3190,6 +3196,8 @@ static void lpc32xx_udc_remove(struct platform_device *pdev)
udc->udca_v_base, udc->udca_p_base);
clk_disable_unprepare(udc->usb_slv_clk);
+
+ put_device(&udc->isp1301_i2c_client->dev);
}
#ifdef CONFIG_PM
diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c
index 24d5a1dc5056..7663f2aa35e9 100644
--- a/drivers/usb/host/ohci-nxp.c
+++ b/drivers/usb/host/ohci-nxp.c
@@ -169,13 +169,13 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev)
ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (ret)
- goto fail_disable;
+ goto err_put_client;
dev_dbg(&pdev->dev, "%s: " DRIVER_DESC " (nxp)\n", hcd_name);
if (usb_disabled()) {
dev_err(&pdev->dev, "USB is disabled\n");
ret = -ENODEV;
- goto fail_disable;
+ goto err_put_client;
}
/* Enable USB host clock */
@@ -183,7 +183,7 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev)
if (IS_ERR(usb_host_clk)) {
dev_err(&pdev->dev, "failed to acquire and start USB OHCI clock\n");
ret = PTR_ERR(usb_host_clk);
- goto fail_disable;
+ goto err_put_client;
}
isp1301_configure();
@@ -192,13 +192,13 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev)
if (!hcd) {
dev_err(&pdev->dev, "Failed to allocate HC buffer\n");
ret = -ENOMEM;
- goto fail_disable;
+ goto err_put_client;
}
hcd->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(hcd->regs)) {
ret = PTR_ERR(hcd->regs);
- goto fail_resource;
+ goto err_put_hcd;
}
hcd->rsrc_start = res->start;
hcd->rsrc_len = resource_size(res);
@@ -206,7 +206,7 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
ret = -ENXIO;
- goto fail_resource;
+ goto err_put_hcd;
}
ohci_nxp_start_hc();
@@ -220,9 +220,10 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev)
}
ohci_nxp_stop_hc();
-fail_resource:
+err_put_hcd:
usb_put_hcd(hcd);
-fail_disable:
+err_put_client:
+ put_device(&isp1301_i2c_client->dev);
isp1301_i2c_client = NULL;
return ret;
}
@@ -234,6 +235,7 @@ static void ohci_hcd_nxp_remove(struct platform_device *pdev)
usb_remove_hcd(hcd);
ohci_nxp_stop_hc();
usb_put_hcd(hcd);
+ put_device(&isp1301_i2c_client->dev);
isp1301_i2c_client = NULL;
}
diff --git a/drivers/usb/host/xhci-dbgtty.c b/drivers/usb/host/xhci-dbgtty.c
index 57cdda4e09c8..90282e51e23e 100644
--- a/drivers/usb/host/xhci-dbgtty.c
+++ b/drivers/usb/host/xhci-dbgtty.c
@@ -554,7 +554,7 @@ static void xhci_dbc_tty_unregister_device(struct xhci_dbc *dbc)
* Hang up the TTY. This wakes up any blocked
* writers and causes subsequent writes to fail.
*/
- tty_vhangup(port->port.tty);
+ tty_port_tty_vhangup(&port->port);
tty_unregister_device(dbc_tty_driver, port->minor);
xhci_dbc_tty_exit_port(port);
diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c
index 40ac68e52cee..e266a47c4d48 100644
--- a/drivers/usb/phy/phy-fsl-usb.c
+++ b/drivers/usb/phy/phy-fsl-usb.c
@@ -988,6 +988,7 @@ static void fsl_otg_remove(struct platform_device *pdev)
{
struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ disable_delayed_work_sync(&fsl_otg_dev->otg_event);
usb_remove_phy(&fsl_otg_dev->phy);
free_irq(fsl_otg_dev->irq, fsl_otg_dev);
diff --git a/drivers/usb/phy/phy-isp1301.c b/drivers/usb/phy/phy-isp1301.c
index f9b5c411aee4..2940f0c84e1b 100644
--- a/drivers/usb/phy/phy-isp1301.c
+++ b/drivers/usb/phy/phy-isp1301.c
@@ -149,7 +149,12 @@ struct i2c_client *isp1301_get_client(struct device_node *node)
return client;
/* non-DT: only one ISP1301 chip supported */
- return isp1301_i2c_client;
+ if (isp1301_i2c_client) {
+ get_device(&isp1301_i2c_client->dev);
+ return isp1301_i2c_client;
+ }
+
+ return NULL;
}
EXPORT_SYMBOL_GPL(isp1301_get_client);
diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c
index 75fff2e4cbc6..56fc3ff5016f 100644
--- a/drivers/usb/renesas_usbhs/pipe.c
+++ b/drivers/usb/renesas_usbhs/pipe.c
@@ -713,11 +713,13 @@ struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv,
/* make sure pipe is not busy */
ret = usbhsp_pipe_barrier(pipe);
if (ret < 0) {
+ usbhsp_put_pipe(pipe);
dev_err(dev, "pipe setup failed %d\n", usbhs_pipe_number(pipe));
return NULL;
}
if (usbhsp_setup_pipecfg(pipe, is_host, dir_in, &pipecfg)) {
+ usbhsp_put_pipe(pipe);
dev_err(dev, "can't setup pipe\n");
return NULL;
}
diff --git a/drivers/usb/storage/unusual_uas.h b/drivers/usb/storage/unusual_uas.h
index b695f5ba9a40..939a98c2d3f7 100644
--- a/drivers/usb/storage/unusual_uas.h
+++ b/drivers/usb/storage/unusual_uas.h
@@ -98,7 +98,7 @@ UNUSUAL_DEV(0x125f, 0xa94a, 0x0160, 0x0160,
US_FL_NO_ATA_1X),
/* Reported-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> */
-UNUSUAL_DEV(0x13fd, 0x3940, 0x0309, 0x0309,
+UNUSUAL_DEV(0x13fd, 0x3940, 0x0000, 0x0309,
"Initio Corporation",
"INIC-3069",
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
index 8d111ad3b71b..d96ab106a980 100644
--- a/drivers/usb/typec/altmodes/displayport.c
+++ b/drivers/usb/typec/altmodes/displayport.c
@@ -766,12 +766,16 @@ int dp_altmode_probe(struct typec_altmode *alt)
if (!(DP_CAP_PIN_ASSIGN_DFP_D(port->vdo) &
DP_CAP_PIN_ASSIGN_UFP_D(alt->vdo)) &&
!(DP_CAP_PIN_ASSIGN_UFP_D(port->vdo) &
- DP_CAP_PIN_ASSIGN_DFP_D(alt->vdo)))
+ DP_CAP_PIN_ASSIGN_DFP_D(alt->vdo))) {
+ typec_altmode_put_plug(plug);
return -ENODEV;
+ }
dp = devm_kzalloc(&alt->dev, sizeof(*dp), GFP_KERNEL);
- if (!dp)
+ if (!dp) {
+ typec_altmode_put_plug(plug);
return -ENOMEM;
+ }
INIT_WORK(&dp->work, dp_altmode_work);
mutex_init(&dp->lock);
diff --git a/drivers/usb/typec/ucsi/Kconfig b/drivers/usb/typec/ucsi/Kconfig
index 7fcb1e1de5d6..b812be4d0e67 100644
--- a/drivers/usb/typec/ucsi/Kconfig
+++ b/drivers/usb/typec/ucsi/Kconfig
@@ -96,6 +96,7 @@ config UCSI_LENOVO_YOGA_C630
config UCSI_HUAWEI_GAOKUN
tristate "UCSI Interface Driver for Huawei Matebook E Go"
depends on EC_HUAWEI_GAOKUN
+ depends on DRM || !DRM
select DRM_AUX_HPD_BRIDGE if DRM_BRIDGE && OF
help
This driver enables UCSI support on the Huawei Matebook E Go tablet,
diff --git a/drivers/usb/typec/ucsi/cros_ec_ucsi.c b/drivers/usb/typec/ucsi/cros_ec_ucsi.c
index d753f2188e25..eed2a7d0ebc6 100644
--- a/drivers/usb/typec/ucsi/cros_ec_ucsi.c
+++ b/drivers/usb/typec/ucsi/cros_ec_ucsi.c
@@ -105,12 +105,13 @@ static int cros_ucsi_async_control(struct ucsi *ucsi, u64 cmd)
return 0;
}
-static int cros_ucsi_sync_control(struct ucsi *ucsi, u64 cmd, u32 *cci)
+static int cros_ucsi_sync_control(struct ucsi *ucsi, u64 cmd, u32 *cci,
+ void *data, size_t size)
{
struct cros_ucsi_data *udata = ucsi_get_drvdata(ucsi);
int ret;
- ret = ucsi_sync_control_common(ucsi, cmd, cci);
+ ret = ucsi_sync_control_common(ucsi, cmd, cci, data, size);
switch (ret) {
case -EBUSY:
/* EC may return -EBUSY if CCI.busy is set.
diff --git a/drivers/usb/typec/ucsi/debugfs.c b/drivers/usb/typec/ucsi/debugfs.c
index 174f4d53b777..f3684ab787fe 100644
--- a/drivers/usb/typec/ucsi/debugfs.c
+++ b/drivers/usb/typec/ucsi/debugfs.c
@@ -37,9 +37,7 @@ static int ucsi_cmd(void *data, u64 val)
case UCSI_SET_USB:
case UCSI_SET_POWER_LEVEL:
case UCSI_READ_POWER_LEVEL:
- case UCSI_SET_PDOS:
- ucsi->message_in_size = 0;
- ret = ucsi_send_command(ucsi, val);
+ ret = ucsi_send_command(ucsi, val, NULL, 0);
break;
case UCSI_GET_CAPABILITY:
case UCSI_GET_CONNECTOR_CAPABILITY:
@@ -54,9 +52,9 @@ static int ucsi_cmd(void *data, u64 val)
case UCSI_GET_ATTENTION_VDO:
case UCSI_GET_CAM_CS:
case UCSI_GET_LPM_PPM_INFO:
- ucsi->message_in_size = sizeof(ucsi->debugfs->response);
- ret = ucsi_send_command(ucsi, val);
- memcpy(&ucsi->debugfs->response, ucsi->message_in, sizeof(ucsi->debugfs->response));
+ ret = ucsi_send_command(ucsi, val,
+ &ucsi->debugfs->response,
+ sizeof(ucsi->debugfs->response));
break;
default:
ret = -EOPNOTSUPP;
@@ -111,30 +109,6 @@ static int ucsi_vbus_volt_show(struct seq_file *m, void *v)
}
DEFINE_SHOW_ATTRIBUTE(ucsi_vbus_volt);
-static ssize_t ucsi_message_out_write(struct file *file,
- const char __user *data, size_t count, loff_t *ppos)
-{
- struct ucsi *ucsi = file->private_data;
- int ret;
-
- char *buf __free(kfree) = memdup_user_nul(data, count);
- if (IS_ERR(buf))
- return PTR_ERR(buf);
-
- ucsi->message_out_size = min(count / 2, UCSI_MAX_MESSAGE_OUT_LENGTH);
- ret = hex2bin(ucsi->message_out, buf, ucsi->message_out_size);
- if (ret)
- return ret;
-
- return count;
-}
-
-static const struct file_operations ucsi_message_out_fops = {
- .open = simple_open,
- .write = ucsi_message_out_write,
- .llseek = generic_file_llseek,
-};
-
void ucsi_debugfs_register(struct ucsi *ucsi)
{
ucsi->debugfs = kzalloc(sizeof(*ucsi->debugfs), GFP_KERNEL);
@@ -147,8 +121,6 @@ void ucsi_debugfs_register(struct ucsi *ucsi)
debugfs_create_file("peak_current", 0400, ucsi->debugfs->dentry, ucsi, &ucsi_peak_curr_fops);
debugfs_create_file("avg_current", 0400, ucsi->debugfs->dentry, ucsi, &ucsi_avg_curr_fops);
debugfs_create_file("vbus_voltage", 0400, ucsi->debugfs->dentry, ucsi, &ucsi_vbus_volt_fops);
- debugfs_create_file("message_out", 0200, ucsi->debugfs->dentry, ucsi,
- &ucsi_message_out_fops);
}
void ucsi_debugfs_unregister(struct ucsi *ucsi)
diff --git a/drivers/usb/typec/ucsi/displayport.c b/drivers/usb/typec/ucsi/displayport.c
index a09b4900ec76..8aae80b457d7 100644
--- a/drivers/usb/typec/ucsi/displayport.c
+++ b/drivers/usb/typec/ucsi/displayport.c
@@ -67,14 +67,11 @@ static int ucsi_displayport_enter(struct typec_altmode *alt, u32 *vdo)
}
command = UCSI_GET_CURRENT_CAM | UCSI_CONNECTOR_NUMBER(dp->con->num);
- ucsi->message_in_size = sizeof(cur);
- ret = ucsi_send_command(ucsi, command);
+ ret = ucsi_send_command(ucsi, command, &cur, sizeof(cur));
if (ret < 0) {
if (ucsi->version > 0x0100)
goto err_unlock;
cur = 0xff;
- } else {
- memcpy(&cur, ucsi->message_in, ucsi->message_in_size);
}
if (cur != 0xff) {
@@ -129,8 +126,7 @@ static int ucsi_displayport_exit(struct typec_altmode *alt)
}
command = UCSI_CMD_SET_NEW_CAM(dp->con->num, 0, dp->offset, 0);
- dp->con->ucsi->message_in_size = 0;
- ret = ucsi_send_command(dp->con->ucsi, command);
+ ret = ucsi_send_command(dp->con->ucsi, command, NULL, 0);
if (ret < 0)
goto out_unlock;
@@ -197,8 +193,7 @@ static int ucsi_displayport_configure(struct ucsi_dp *dp)
command = UCSI_CMD_SET_NEW_CAM(dp->con->num, 1, dp->offset, pins);
- dp->con->ucsi->message_in_size = 0;
- return ucsi_send_command(dp->con->ucsi, command);
+ return ucsi_send_command(dp->con->ucsi, command, NULL, 0);
}
static int ucsi_displayport_vdm(struct typec_altmode *alt,
diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index 9b3df776137a..a7b388dc7fa0 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -55,7 +55,8 @@ void ucsi_notify_common(struct ucsi *ucsi, u32 cci)
}
EXPORT_SYMBOL_GPL(ucsi_notify_common);
-int ucsi_sync_control_common(struct ucsi *ucsi, u64 command, u32 *cci)
+int ucsi_sync_control_common(struct ucsi *ucsi, u64 command, u32 *cci,
+ void *data, size_t size)
{
bool ack = UCSI_COMMAND(command) == UCSI_ACK_CC_CI;
int ret;
@@ -67,20 +68,6 @@ int ucsi_sync_control_common(struct ucsi *ucsi, u64 command, u32 *cci)
reinit_completion(&ucsi->complete);
- if (ucsi->message_out_size > 0) {
- if (!ucsi->ops->write_message_out) {
- ucsi->message_out_size = 0;
- ret = -EOPNOTSUPP;
- goto out_clear_bit;
- }
-
- ret = ucsi->ops->write_message_out(ucsi, ucsi->message_out,
- ucsi->message_out_size);
- ucsi->message_out_size = 0;
- if (ret)
- goto out_clear_bit;
- }
-
ret = ucsi->ops->async_control(ucsi, command);
if (ret)
goto out_clear_bit;
@@ -97,10 +84,9 @@ out_clear_bit:
if (!ret && cci)
ret = ucsi->ops->read_cci(ucsi, cci);
- if (!ret && ucsi->message_in_size > 0 &&
+ if (!ret && data &&
(*cci & UCSI_CCI_COMMAND_COMPLETE))
- ret = ucsi->ops->read_message_in(ucsi, ucsi->message_in,
- ucsi->message_in_size);
+ ret = ucsi->ops->read_message_in(ucsi, data, size);
return ret;
}
@@ -117,25 +103,23 @@ static int ucsi_acknowledge(struct ucsi *ucsi, bool conn_ack)
ctrl |= UCSI_ACK_CONNECTOR_CHANGE;
}
- ucsi->message_in_size = 0;
- return ucsi->ops->sync_control(ucsi, ctrl, NULL);
+ return ucsi->ops->sync_control(ucsi, ctrl, NULL, NULL, 0);
}
-static int ucsi_run_command(struct ucsi *ucsi, u64 command, u32 *cci, bool conn_ack)
+static int ucsi_run_command(struct ucsi *ucsi, u64 command, u32 *cci,
+ void *data, size_t size, bool conn_ack)
{
int ret, err;
*cci = 0;
- if (ucsi->message_in_size > UCSI_MAX_DATA_LENGTH(ucsi))
+ if (size > UCSI_MAX_DATA_LENGTH(ucsi))
return -EINVAL;
- ret = ucsi->ops->sync_control(ucsi, command, cci);
+ ret = ucsi->ops->sync_control(ucsi, command, cci, data, size);
- if (*cci & UCSI_CCI_BUSY) {
- ucsi->message_in_size = 0;
- return ucsi_run_command(ucsi, UCSI_CANCEL, cci, false) ?: -EBUSY;
- }
+ if (*cci & UCSI_CCI_BUSY)
+ return ucsi_run_command(ucsi, UCSI_CANCEL, cci, NULL, 0, false) ?: -EBUSY;
if (ret)
return ret;
@@ -167,13 +151,10 @@ static int ucsi_read_error(struct ucsi *ucsi, u8 connector_num)
int ret;
command = UCSI_GET_ERROR_STATUS | UCSI_CONNECTOR_NUMBER(connector_num);
- ucsi->message_in_size = sizeof(error);
- ret = ucsi_run_command(ucsi, command, &cci, false);
+ ret = ucsi_run_command(ucsi, command, &cci, &error, sizeof(error), false);
if (ret < 0)
return ret;
- memcpy(&error, ucsi->message_in, sizeof(error));
-
switch (error) {
case UCSI_ERROR_INCOMPATIBLE_PARTNER:
return -EOPNOTSUPP;
@@ -219,7 +200,8 @@ static int ucsi_read_error(struct ucsi *ucsi, u8 connector_num)
return -EIO;
}
-static int ucsi_send_command_common(struct ucsi *ucsi, u64 cmd, bool conn_ack)
+static int ucsi_send_command_common(struct ucsi *ucsi, u64 cmd,
+ void *data, size_t size, bool conn_ack)
{
u8 connector_num;
u32 cci;
@@ -247,7 +229,7 @@ static int ucsi_send_command_common(struct ucsi *ucsi, u64 cmd, bool conn_ack)
mutex_lock(&ucsi->ppm_lock);
- ret = ucsi_run_command(ucsi, cmd, &cci, conn_ack);
+ ret = ucsi_run_command(ucsi, cmd, &cci, data, size, conn_ack);
if (cci & UCSI_CCI_ERROR)
ret = ucsi_read_error(ucsi, connector_num);
@@ -256,9 +238,10 @@ static int ucsi_send_command_common(struct ucsi *ucsi, u64 cmd, bool conn_ack)
return ret;
}
-int ucsi_send_command(struct ucsi *ucsi, u64 command)
+int ucsi_send_command(struct ucsi *ucsi, u64 command,
+ void *data, size_t size)
{
- return ucsi_send_command_common(ucsi, command, false);
+ return ucsi_send_command_common(ucsi, command, data, size, false);
}
EXPORT_SYMBOL_GPL(ucsi_send_command);
@@ -336,8 +319,7 @@ void ucsi_altmode_update_active(struct ucsi_connector *con)
int i;
command = UCSI_GET_CURRENT_CAM | UCSI_CONNECTOR_NUMBER(con->num);
- con->ucsi->message_in_size = sizeof(cur);
- ret = ucsi_send_command(con->ucsi, command);
+ ret = ucsi_send_command(con->ucsi, command, &cur, sizeof(cur));
if (ret < 0) {
if (con->ucsi->version > 0x0100) {
dev_err(con->ucsi->dev,
@@ -345,8 +327,6 @@ void ucsi_altmode_update_active(struct ucsi_connector *con)
return;
}
cur = 0xff;
- } else {
- memcpy(&cur, con->ucsi->message_in, sizeof(cur));
}
if (cur < UCSI_MAX_ALTMODES)
@@ -530,8 +510,7 @@ ucsi_register_altmodes_nvidia(struct ucsi_connector *con, u8 recipient)
command |= UCSI_GET_ALTMODE_RECIPIENT(recipient);
command |= UCSI_GET_ALTMODE_CONNECTOR_NUMBER(con->num);
command |= UCSI_GET_ALTMODE_OFFSET(i);
- ucsi->message_in_size = sizeof(alt);
- len = ucsi_send_command(con->ucsi, command);
+ len = ucsi_send_command(con->ucsi, command, &alt, sizeof(alt));
/*
* We are collecting all altmodes first and then registering.
* Some type-C device will return zero length data beyond last
@@ -540,8 +519,6 @@ ucsi_register_altmodes_nvidia(struct ucsi_connector *con, u8 recipient)
if (len < 0)
return len;
- memcpy(&alt, ucsi->message_in, sizeof(alt));
-
/* We got all altmodes, now break out and register them */
if (!len || !alt.svid)
break;
@@ -609,15 +586,12 @@ static int ucsi_register_altmodes(struct ucsi_connector *con, u8 recipient)
command |= UCSI_GET_ALTMODE_RECIPIENT(recipient);
command |= UCSI_GET_ALTMODE_CONNECTOR_NUMBER(con->num);
command |= UCSI_GET_ALTMODE_OFFSET(i);
- con->ucsi->message_in_size = sizeof(alt);
- len = ucsi_send_command(con->ucsi, command);
+ len = ucsi_send_command(con->ucsi, command, alt, sizeof(alt));
if (len == -EBUSY)
continue;
if (len <= 0)
return len;
- memcpy(&alt, con->ucsi->message_in, sizeof(alt));
-
/*
* This code is requesting one alt mode at a time, but some PPMs
* may still return two. If that happens both alt modes need be
@@ -685,9 +659,7 @@ static int ucsi_get_connector_status(struct ucsi_connector *con, bool conn_ack)
UCSI_MAX_DATA_LENGTH(con->ucsi));
int ret;
- con->ucsi->message_in_size = size;
- ret = ucsi_send_command_common(con->ucsi, command, conn_ack);
- memcpy(&con->status, con->ucsi->message_in, size);
+ ret = ucsi_send_command_common(con->ucsi, command, &con->status, size, conn_ack);
return ret < 0 ? ret : 0;
}
@@ -710,9 +682,8 @@ static int ucsi_read_pdos(struct ucsi_connector *con,
command |= UCSI_GET_PDOS_PDO_OFFSET(offset);
command |= UCSI_GET_PDOS_NUM_PDOS(num_pdos - 1);
command |= is_source(role) ? UCSI_GET_PDOS_SRC_PDOS : 0;
- ucsi->message_in_size = num_pdos * sizeof(u32);
- ret = ucsi_send_command(ucsi, command);
- memcpy(pdos + offset, ucsi->message_in, num_pdos * sizeof(u32));
+ ret = ucsi_send_command(ucsi, command, pdos + offset,
+ num_pdos * sizeof(u32));
if (ret < 0 && ret != -ETIMEDOUT)
dev_err(ucsi->dev, "UCSI_GET_PDOS failed (%d)\n", ret);
@@ -799,9 +770,7 @@ static int ucsi_get_pd_message(struct ucsi_connector *con, u8 recipient,
command |= UCSI_GET_PD_MESSAGE_BYTES(len);
command |= UCSI_GET_PD_MESSAGE_TYPE(type);
- con->ucsi->message_in_size = len;
- ret = ucsi_send_command(con->ucsi, command);
- memcpy(data + offset, con->ucsi->message_in, len);
+ ret = ucsi_send_command(con->ucsi, command, data + offset, len);
if (ret < 0)
return ret;
}
@@ -966,9 +935,7 @@ static int ucsi_register_cable(struct ucsi_connector *con)
int ret;
command = UCSI_GET_CABLE_PROPERTY | UCSI_CONNECTOR_NUMBER(con->num);
- con->ucsi->message_in_size = sizeof(cable_prop);
- ret = ucsi_send_command(con->ucsi, command);
- memcpy(&cable_prop, con->ucsi->message_in, sizeof(cable_prop));
+ ret = ucsi_send_command(con->ucsi, command, &cable_prop, sizeof(cable_prop));
if (ret < 0) {
dev_err(con->ucsi->dev, "GET_CABLE_PROPERTY failed (%d)\n", ret);
return ret;
@@ -1029,9 +996,7 @@ static int ucsi_check_connector_capability(struct ucsi_connector *con)
return 0;
command = UCSI_GET_CONNECTOR_CAPABILITY | UCSI_CONNECTOR_NUMBER(con->num);
- con->ucsi->message_in_size = sizeof(con->cap);
- ret = ucsi_send_command(con->ucsi, command);
- memcpy(&con->cap, con->ucsi->message_in, sizeof(con->cap));
+ ret = ucsi_send_command(con->ucsi, command, &con->cap, sizeof(con->cap));
if (ret < 0) {
dev_err(con->ucsi->dev, "GET_CONNECTOR_CAPABILITY failed (%d)\n", ret);
return ret;
@@ -1415,8 +1380,7 @@ static int ucsi_reset_connector(struct ucsi_connector *con, bool hard)
else if (con->ucsi->version >= UCSI_VERSION_2_0)
command |= hard ? 0 : UCSI_CONNECTOR_RESET_DATA_VER_2_0;
- con->ucsi->message_in_size = 0;
- return ucsi_send_command(con->ucsi, command);
+ return ucsi_send_command(con->ucsi, command, NULL, 0);
}
static int ucsi_reset_ppm(struct ucsi *ucsi)
@@ -1497,8 +1461,7 @@ static int ucsi_role_cmd(struct ucsi_connector *con, u64 command)
{
int ret;
- con->ucsi->message_in_size = 0;
- ret = ucsi_send_command(con->ucsi, command);
+ ret = ucsi_send_command(con->ucsi, command, NULL, 0);
if (ret == -ETIMEDOUT) {
u64 c;
@@ -1506,8 +1469,7 @@ static int ucsi_role_cmd(struct ucsi_connector *con, u64 command)
ucsi_reset_ppm(con->ucsi);
c = UCSI_SET_NOTIFICATION_ENABLE | con->ucsi->ntfy;
- con->ucsi->message_in_size = 0;
- ucsi_send_command(con->ucsi, c);
+ ucsi_send_command(con->ucsi, c, NULL, 0);
ucsi_reset_connector(con, true);
}
@@ -1660,13 +1622,10 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
/* Get connector capability */
command = UCSI_GET_CONNECTOR_CAPABILITY;
command |= UCSI_CONNECTOR_NUMBER(con->num);
- ucsi->message_in_size = sizeof(con->cap);
- ret = ucsi_send_command(ucsi, command);
+ ret = ucsi_send_command(ucsi, command, &con->cap, sizeof(con->cap));
if (ret < 0)
goto out_unlock;
- memcpy(&con->cap, ucsi->message_in, sizeof(con->cap));
-
if (UCSI_CONCAP(con, OPMODE_DRP))
cap->data = TYPEC_PORT_DRD;
else if (UCSI_CONCAP(con, OPMODE_DFP))
@@ -1863,20 +1822,17 @@ static int ucsi_init(struct ucsi *ucsi)
/* Enable basic notifications */
ntfy = UCSI_ENABLE_NTFY_CMD_COMPLETE | UCSI_ENABLE_NTFY_ERROR;
command = UCSI_SET_NOTIFICATION_ENABLE | ntfy;
- ucsi->message_in_size = 0;
- ret = ucsi_send_command(ucsi, command);
+ ret = ucsi_send_command(ucsi, command, NULL, 0);
if (ret < 0)
goto err_reset;
/* Get PPM capabilities */
command = UCSI_GET_CAPABILITY;
- ucsi->message_in_size = BITS_TO_BYTES(UCSI_GET_CAPABILITY_SIZE);
- ret = ucsi_send_command(ucsi, command);
+ ret = ucsi_send_command(ucsi, command, &ucsi->cap,
+ BITS_TO_BYTES(UCSI_GET_CAPABILITY_SIZE));
if (ret < 0)
goto err_reset;
- memcpy(&ucsi->cap, ucsi->message_in, BITS_TO_BYTES(UCSI_GET_CAPABILITY_SIZE));
-
if (!ucsi->cap.num_connectors) {
ret = -ENODEV;
goto err_reset;
@@ -1906,8 +1862,7 @@ static int ucsi_init(struct ucsi *ucsi)
/* Enable all supported notifications */
ntfy = ucsi_get_supported_notifications(ucsi);
command = UCSI_SET_NOTIFICATION_ENABLE | ntfy;
- ucsi->message_in_size = 0;
- ret = ucsi_send_command(ucsi, command);
+ ret = ucsi_send_command(ucsi, command, NULL, 0);
if (ret < 0)
goto err_unregister;
@@ -1958,8 +1913,7 @@ static void ucsi_resume_work(struct work_struct *work)
/* Restore UCSI notification enable mask after system resume */
command = UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy;
- ucsi->message_in_size = 0;
- ret = ucsi_send_command(ucsi, command);
+ ret = ucsi_send_command(ucsi, command, NULL, 0);
if (ret < 0) {
dev_err(ucsi->dev, "failed to re-enable notifications (%d)\n", ret);
return;
diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
index f946b728c373..410389ef173a 100644
--- a/drivers/usb/typec/ucsi/ucsi.h
+++ b/drivers/usb/typec/ucsi/ucsi.h
@@ -29,10 +29,6 @@ struct dentry;
#define UCSI_MESSAGE_OUT 32
#define UCSIv2_MESSAGE_OUT 272
-/* Define maximum lengths for message buffers */
-#define UCSI_MAX_MESSAGE_IN_LENGTH 256
-#define UCSI_MAX_MESSAGE_OUT_LENGTH 256
-
/* UCSI versions */
#define UCSI_VERSION_1_0 0x0100
#define UCSI_VERSION_1_1 0x0110
@@ -69,7 +65,6 @@ struct dentry;
* @read_cci: Read CCI register
* @poll_cci: Read CCI register while polling with notifications disabled
* @read_message_in: Read message data from UCSI
- * @write_message_out: Write message data to UCSI
* @sync_control: Blocking control operation
* @async_control: Non-blocking control operation
* @update_altmodes: Squashes duplicate DP altmodes
@@ -85,8 +80,8 @@ struct ucsi_operations {
int (*read_cci)(struct ucsi *ucsi, u32 *cci);
int (*poll_cci)(struct ucsi *ucsi, u32 *cci);
int (*read_message_in)(struct ucsi *ucsi, void *val, size_t val_len);
- int (*write_message_out)(struct ucsi *ucsi, void *data, size_t data_len);
- int (*sync_control)(struct ucsi *ucsi, u64 command, u32 *cci);
+ int (*sync_control)(struct ucsi *ucsi, u64 command, u32 *cci,
+ void *data, size_t size);
int (*async_control)(struct ucsi *ucsi, u64 command);
bool (*update_altmodes)(struct ucsi *ucsi, u8 recipient,
struct ucsi_altmode *orig,
@@ -137,7 +132,6 @@ void ucsi_connector_change(struct ucsi *ucsi, u8 num);
#define UCSI_GET_PD_MESSAGE 0x15
#define UCSI_GET_CAM_CS 0x18
#define UCSI_SET_SINK_PATH 0x1c
-#define UCSI_SET_PDOS 0x1d
#define UCSI_READ_POWER_LEVEL 0x1e
#define UCSI_SET_USB 0x21
#define UCSI_GET_LPM_PPM_INFO 0x22
@@ -499,12 +493,6 @@ struct ucsi {
unsigned long quirks;
#define UCSI_NO_PARTNER_PDOS BIT(0) /* Don't read partner's PDOs */
#define UCSI_DELAY_DEVICE_PDOS BIT(1) /* Reading PDOs fails until the parter is in PD mode */
-
- /* Fixed-size buffers for incoming and outgoing messages */
- u8 message_in[UCSI_MAX_MESSAGE_IN_LENGTH];
- size_t message_in_size;
- u8 message_out[UCSI_MAX_MESSAGE_OUT_LENGTH];
- size_t message_out_size;
};
#define UCSI_MAX_DATA_LENGTH(u) (((u)->version < UCSI_VERSION_2_0) ? 0x10 : 0xff)
@@ -567,13 +555,15 @@ struct ucsi_connector {
struct usb_pd_identity cable_identity;
};
-int ucsi_send_command(struct ucsi *ucsi, u64 command);
+int ucsi_send_command(struct ucsi *ucsi, u64 command,
+ void *retval, size_t size);
void ucsi_altmode_update_active(struct ucsi_connector *con);
int ucsi_resume(struct ucsi *ucsi);
void ucsi_notify_common(struct ucsi *ucsi, u32 cci);
-int ucsi_sync_control_common(struct ucsi *ucsi, u64 command, u32 *cci);
+int ucsi_sync_control_common(struct ucsi *ucsi, u64 command, u32 *cci,
+ void *data, size_t size);
#if IS_ENABLED(CONFIG_POWER_SUPPLY)
int ucsi_register_port_psy(struct ucsi_connector *con);
diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c
index f9beeb835238..6b92f296e985 100644
--- a/drivers/usb/typec/ucsi/ucsi_acpi.c
+++ b/drivers/usb/typec/ucsi/ucsi_acpi.c
@@ -86,21 +86,6 @@ static int ucsi_acpi_read_message_in(struct ucsi *ucsi, void *val, size_t val_le
return 0;
}
-static int ucsi_acpi_write_message_out(struct ucsi *ucsi, void *data, size_t data_len)
-{
- struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
-
- if (!data || !data_len)
- return -EINVAL;
-
- if (ucsi->version <= UCSI_VERSION_1_2)
- memcpy(ua->base + UCSI_MESSAGE_OUT, data, data_len);
- else
- memcpy(ua->base + UCSIv2_MESSAGE_OUT, data, data_len);
-
- return 0;
-}
-
static int ucsi_acpi_async_control(struct ucsi *ucsi, u64 command)
{
struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
@@ -116,19 +101,19 @@ static const struct ucsi_operations ucsi_acpi_ops = {
.read_cci = ucsi_acpi_read_cci,
.poll_cci = ucsi_acpi_poll_cci,
.read_message_in = ucsi_acpi_read_message_in,
- .write_message_out = ucsi_acpi_write_message_out,
.sync_control = ucsi_sync_control_common,
.async_control = ucsi_acpi_async_control
};
-static int ucsi_gram_sync_control(struct ucsi *ucsi, u64 command, u32 *cci)
+static int ucsi_gram_sync_control(struct ucsi *ucsi, u64 command, u32 *cci,
+ void *val, size_t len)
{
u16 bogus_change = UCSI_CONSTAT_POWER_LEVEL_CHANGE |
UCSI_CONSTAT_PDOS_CHANGE;
struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
int ret;
- ret = ucsi_sync_control_common(ucsi, command, cci);
+ ret = ucsi_sync_control_common(ucsi, command, cci, val, len);
if (ret < 0)
return ret;
@@ -140,8 +125,8 @@ static int ucsi_gram_sync_control(struct ucsi *ucsi, u64 command, u32 *cci)
if (UCSI_COMMAND(ua->cmd) == UCSI_GET_CONNECTOR_STATUS &&
ua->check_bogus_event) {
/* Clear the bogus change */
- if (*(u16 *)ucsi->message_in == bogus_change)
- *(u16 *)ucsi->message_in = 0;
+ if (*(u16 *)val == bogus_change)
+ *(u16 *)val = 0;
ua->check_bogus_event = false;
}
diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c
index ead1b2a25c79..d83a0051c737 100644
--- a/drivers/usb/typec/ucsi/ucsi_ccg.c
+++ b/drivers/usb/typec/ucsi/ucsi_ccg.c
@@ -606,7 +606,8 @@ static int ucsi_ccg_async_control(struct ucsi *ucsi, u64 command)
return ccg_write(uc, reg, (u8 *)&command, sizeof(command));
}
-static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command, u32 *cci)
+static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command, u32 *cci,
+ void *data, size_t size)
{
struct ucsi_ccg *uc = ucsi_get_drvdata(ucsi);
struct ucsi_connector *con;
@@ -628,16 +629,16 @@ static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command, u32 *cci)
ucsi_ccg_update_set_new_cam_cmd(uc, con, &command);
}
- ret = ucsi_sync_control_common(ucsi, command, cci);
+ ret = ucsi_sync_control_common(ucsi, command, cci, data, size);
switch (UCSI_COMMAND(command)) {
case UCSI_GET_CURRENT_CAM:
if (uc->has_multiple_dp)
- ucsi_ccg_update_get_current_cam_cmd(uc, (u8 *)ucsi->message_in);
+ ucsi_ccg_update_get_current_cam_cmd(uc, (u8 *)data);
break;
case UCSI_GET_ALTERNATE_MODES:
if (UCSI_ALTMODE_RECIPIENT(command) == UCSI_RECIPIENT_SOP) {
- struct ucsi_altmode *alt = (struct ucsi_altmode *)ucsi->message_in;
+ struct ucsi_altmode *alt = data;
if (alt[0].svid == USB_TYPEC_NVIDIA_VLINK_SID)
ucsi_ccg_nvidia_altmode(uc, alt, command);
@@ -645,7 +646,7 @@ static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command, u32 *cci)
break;
case UCSI_GET_CAPABILITY:
if (uc->fw_build == CCG_FW_BUILD_NVIDIA_TEGRA) {
- struct ucsi_capability *cap = (struct ucsi_capability *)ucsi->message_in;
+ struct ucsi_capability *cap = data;
cap->features &= ~UCSI_CAP_ALT_MODE_DETAILS;
}
diff --git a/drivers/usb/typec/ucsi/ucsi_yoga_c630.c b/drivers/usb/typec/ucsi/ucsi_yoga_c630.c
index 299081444caa..0187c1c4b21a 100644
--- a/drivers/usb/typec/ucsi/ucsi_yoga_c630.c
+++ b/drivers/usb/typec/ucsi/ucsi_yoga_c630.c
@@ -88,7 +88,8 @@ static int yoga_c630_ucsi_async_control(struct ucsi *ucsi, u64 command)
static int yoga_c630_ucsi_sync_control(struct ucsi *ucsi,
u64 command,
- u32 *cci)
+ u32 *cci,
+ void *data, size_t size)
{
int ret;
@@ -106,8 +107,8 @@ static int yoga_c630_ucsi_sync_control(struct ucsi *ucsi,
};
dev_dbg(ucsi->dev, "faking DP altmode for con1\n");
- memset(ucsi->message_in, 0, ucsi->message_in_size);
- memcpy(ucsi->message_in, &alt, min(sizeof(alt), ucsi->message_in_size));
+ memset(data, 0, size);
+ memcpy(data, &alt, min(sizeof(alt), size));
*cci = UCSI_CCI_COMMAND_COMPLETE | UCSI_SET_CCI_LENGTH(sizeof(alt));
return 0;
}
@@ -120,18 +121,18 @@ static int yoga_c630_ucsi_sync_control(struct ucsi *ucsi,
if (UCSI_COMMAND(command) == UCSI_GET_ALTERNATE_MODES &&
UCSI_GET_ALTMODE_GET_CONNECTOR_NUMBER(command) == 2) {
dev_dbg(ucsi->dev, "ignoring altmodes for con2\n");
- memset(ucsi->message_in, 0, ucsi->message_in_size);
+ memset(data, 0, size);
*cci = UCSI_CCI_COMMAND_COMPLETE;
return 0;
}
- ret = ucsi_sync_control_common(ucsi, command, cci);
+ ret = ucsi_sync_control_common(ucsi, command, cci, data, size);
if (ret < 0)
return ret;
/* UCSI_GET_CURRENT_CAM is off-by-one on all ports */
- if (UCSI_COMMAND(command) == UCSI_GET_CURRENT_CAM && ucsi->message_in_size > 0)
- ucsi->message_in[0]--;
+ if (UCSI_COMMAND(command) == UCSI_GET_CURRENT_CAM && data)
+ ((u8 *)data)[0]--;
return ret;
}
diff --git a/drivers/vfio/pci/nvgrace-gpu/main.c b/drivers/vfio/pci/nvgrace-gpu/main.c
index 84d142a47ec6..b45a24d00387 100644
--- a/drivers/vfio/pci/nvgrace-gpu/main.c
+++ b/drivers/vfio/pci/nvgrace-gpu/main.c
@@ -561,7 +561,7 @@ nvgrace_gpu_map_and_read(struct nvgrace_gpu_pci_core_device *nvdev,
ret = vfio_pci_core_do_io_rw(&nvdev->core_device, false,
nvdev->resmem.ioaddr,
buf, offset, mem_count,
- 0, 0, false);
+ 0, 0, false, VFIO_PCI_IO_WIDTH_8);
}
return ret;
@@ -693,7 +693,7 @@ nvgrace_gpu_map_and_write(struct nvgrace_gpu_pci_core_device *nvdev,
ret = vfio_pci_core_do_io_rw(&nvdev->core_device, false,
nvdev->resmem.ioaddr,
(char __user *)buf, pos, mem_count,
- 0, 0, true);
+ 0, 0, true, VFIO_PCI_IO_WIDTH_8);
}
return ret;
diff --git a/drivers/vfio/pci/pds/dirty.c b/drivers/vfio/pci/pds/dirty.c
index 481992142f79..4915a7c1c491 100644
--- a/drivers/vfio/pci/pds/dirty.c
+++ b/drivers/vfio/pci/pds/dirty.c
@@ -292,8 +292,11 @@ static int pds_vfio_dirty_enable(struct pds_vfio_pci_device *pds_vfio,
len = num_ranges * sizeof(*region_info);
node = interval_tree_iter_first(ranges, 0, ULONG_MAX);
- if (!node)
- return -EINVAL;
+ if (!node) {
+ err = -EINVAL;
+ goto out_free_region_info;
+ }
+
for (int i = 0; i < num_ranges; i++) {
struct pds_lm_dirty_region_info *ri = &region_info[i];
u64 region_size = node->last - node->start + 1;
diff --git a/drivers/vfio/pci/vfio_pci_rdwr.c b/drivers/vfio/pci/vfio_pci_rdwr.c
index 6192788c8ba3..b38627b35c35 100644
--- a/drivers/vfio/pci/vfio_pci_rdwr.c
+++ b/drivers/vfio/pci/vfio_pci_rdwr.c
@@ -135,7 +135,8 @@ VFIO_IORDWR(64)
ssize_t vfio_pci_core_do_io_rw(struct vfio_pci_core_device *vdev, bool test_mem,
void __iomem *io, char __user *buf,
loff_t off, size_t count, size_t x_start,
- size_t x_end, bool iswrite)
+ size_t x_end, bool iswrite,
+ enum vfio_pci_io_width max_width)
{
ssize_t done = 0;
int ret;
@@ -150,20 +151,19 @@ ssize_t vfio_pci_core_do_io_rw(struct vfio_pci_core_device *vdev, bool test_mem,
else
fillable = 0;
- if (fillable >= 8 && !(off % 8)) {
+ if (fillable >= 8 && !(off % 8) && max_width >= 8) {
ret = vfio_pci_iordwr64(vdev, iswrite, test_mem,
io, buf, off, &filled);
if (ret)
return ret;
- } else
- if (fillable >= 4 && !(off % 4)) {
+ } else if (fillable >= 4 && !(off % 4) && max_width >= 4) {
ret = vfio_pci_iordwr32(vdev, iswrite, test_mem,
io, buf, off, &filled);
if (ret)
return ret;
- } else if (fillable >= 2 && !(off % 2)) {
+ } else if (fillable >= 2 && !(off % 2) && max_width >= 2) {
ret = vfio_pci_iordwr16(vdev, iswrite, test_mem,
io, buf, off, &filled);
if (ret)
@@ -234,6 +234,7 @@ ssize_t vfio_pci_bar_rw(struct vfio_pci_core_device *vdev, char __user *buf,
void __iomem *io;
struct resource *res = &vdev->pdev->resource[bar];
ssize_t done;
+ enum vfio_pci_io_width max_width = VFIO_PCI_IO_WIDTH_8;
if (pci_resource_start(pdev, bar))
end = pci_resource_len(pdev, bar);
@@ -262,6 +263,16 @@ ssize_t vfio_pci_bar_rw(struct vfio_pci_core_device *vdev, char __user *buf,
if (!io)
return -ENOMEM;
x_end = end;
+
+ /*
+ * Certain devices (e.g. Intel X710) don't support qword
+ * access to the ROM bar. Otherwise PCI AER errors might be
+ * triggered.
+ *
+ * Disable qword access to the ROM bar universally, which
+ * worked reliably for years before qword access is enabled.
+ */
+ max_width = VFIO_PCI_IO_WIDTH_4;
} else {
int ret = vfio_pci_core_setup_barmap(vdev, bar);
if (ret) {
@@ -278,7 +289,7 @@ ssize_t vfio_pci_bar_rw(struct vfio_pci_core_device *vdev, char __user *buf,
}
done = vfio_pci_core_do_io_rw(vdev, res->flags & IORESOURCE_MEM, io, buf, pos,
- count, x_start, x_end, iswrite);
+ count, x_start, x_end, iswrite, max_width);
if (done >= 0)
*ppos += done;
@@ -352,7 +363,7 @@ ssize_t vfio_pci_vga_rw(struct vfio_pci_core_device *vdev, char __user *buf,
* to the memory enable bit in the command register.
*/
done = vfio_pci_core_do_io_rw(vdev, false, iomem, buf, off, count,
- 0, 0, iswrite);
+ 0, 0, iswrite, VFIO_PCI_IO_WIDTH_4);
vga_put(vdev->pdev, rsrc);
diff --git a/drivers/vfio/pci/xe/main.c b/drivers/vfio/pci/xe/main.c
index 0156b53c678b..2a5eb9260ec7 100644
--- a/drivers/vfio/pci/xe/main.c
+++ b/drivers/vfio/pci/xe/main.c
@@ -250,6 +250,7 @@ xe_vfio_pci_alloc_file(struct xe_vfio_pci_core_device *xe_vdev,
struct xe_vfio_pci_migration_file *migf;
const struct file_operations *fops;
int flags;
+ int ret;
migf = kzalloc(sizeof(*migf), GFP_KERNEL_ACCOUNT);
if (!migf)
@@ -259,8 +260,9 @@ xe_vfio_pci_alloc_file(struct xe_vfio_pci_core_device *xe_vdev,
flags = type == XE_VFIO_FILE_SAVE ? O_RDONLY : O_WRONLY;
migf->filp = anon_inode_getfile("xe_vfio_mig", fops, migf, flags);
if (IS_ERR(migf->filp)) {
+ ret = PTR_ERR(migf->filp);
kfree(migf);
- return ERR_CAST(migf->filp);
+ return ERR_PTR(ret);
}
mutex_init(&migf->lock);
@@ -504,6 +506,7 @@ static const struct vfio_device_ops xe_vfio_pci_ops = {
.open_device = xe_vfio_pci_open_device,
.close_device = xe_vfio_pci_close_device,
.ioctl = vfio_pci_core_ioctl,
+ .get_region_info_caps = vfio_pci_ioctl_get_region_info,
.device_feature = vfio_pci_core_ioctl_feature,
.read = vfio_pci_core_read,
.write = vfio_pci_core_write,
diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
index 0298ddc34824..552cfb53498a 100644
--- a/drivers/vhost/vsock.c
+++ b/drivers/vhost/vsock.c
@@ -66,14 +66,15 @@ static u32 vhost_transport_get_local_cid(void)
return VHOST_VSOCK_DEFAULT_HOST_CID;
}
-/* Callers that dereference the return value must hold vhost_vsock_mutex or the
- * RCU read lock.
+/* Callers must be in an RCU read section or hold the vhost_vsock_mutex.
+ * The return value can only be dereferenced while within the section.
*/
static struct vhost_vsock *vhost_vsock_get(u32 guest_cid)
{
struct vhost_vsock *vsock;
- hash_for_each_possible_rcu(vhost_vsock_hash, vsock, hash, guest_cid) {
+ hash_for_each_possible_rcu(vhost_vsock_hash, vsock, hash, guest_cid,
+ lockdep_is_held(&vhost_vsock_mutex)) {
u32 other_cid = vsock->guest_cid;
/* Skip instances that have no CID yet */
@@ -709,9 +710,15 @@ static void vhost_vsock_reset_orphans(struct sock *sk)
* executing.
*/
+ rcu_read_lock();
+
/* If the peer is still valid, no need to reset connection */
- if (vhost_vsock_get(vsk->remote_addr.svm_cid))
+ if (vhost_vsock_get(vsk->remote_addr.svm_cid)) {
+ rcu_read_unlock();
return;
+ }
+
+ rcu_read_unlock();
/* If the close timeout is pending, let it expire. This avoids races
* with the timeout callback.