Commit 6761a0ae authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull char/misc driver fixes from Greg KH:
 "Here are some small misc driver fixes for 5.15-rc4. They are in two
  "groups":

   - ipack driver fixes for issues found by Johan Hovold

   - interconnect driver fixes for reported problems

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

* tag 'char-misc-5.15-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc:
  ipack: ipoctal: fix module reference leak
  ipack: ipoctal: fix missing allocation-failure check
  ipack: ipoctal: fix tty-registration error handling
  ipack: ipoctal: fix tty registration race
  ipack: ipoctal: fix stack information leak
  interconnect: qcom: sdm660: Add missing a2noc qos clocks
  dt-bindings: interconnect: sdm660: Add missing a2noc qos clocks
  interconnect: qcom: sdm660: Correct NOC_QOS_PRIORITY shift and mask
  interconnect: qcom: sdm660: Fix id of slv_cnoc_mnoc_cfg
parents 84928ce3 bb8a4fcb
Loading
Loading
Loading
Loading
+42 −4
Original line number Diff line number Diff line
@@ -31,11 +31,11 @@ properties:

  clocks:
    minItems: 1
    maxItems: 3
    maxItems: 7

  clock-names:
    minItems: 1
    maxItems: 3
    maxItems: 7

required:
  - compatible
@@ -72,6 +72,32 @@ allOf:
          contains:
            enum:
              - qcom,sdm660-a2noc
    then:
      properties:
        clocks:
          items:
            - description: Bus Clock.
            - description: Bus A Clock.
            - description: IPA Clock.
            - description: UFS AXI Clock.
            - description: Aggregate2 UFS AXI Clock.
            - description: Aggregate2 USB3 AXI Clock.
            - description: Config NoC USB2 AXI Clock.
        clock-names:
          items:
            - const: bus
            - const: bus_a
            - const: ipa
            - const: ufs_axi
            - const: aggre2_ufs_axi
            - const: aggre2_usb3_axi
            - const: cfg_noc_usb2_axi

  - if:
      properties:
        compatible:
          contains:
            enum:
              - qcom,sdm660-bimc
              - qcom,sdm660-cnoc
              - qcom,sdm660-gnoc
@@ -91,6 +117,7 @@ examples:
  - |
      #include <dt-bindings/clock/qcom,rpmcc.h>
      #include <dt-bindings/clock/qcom,mmcc-sdm660.h>
      #include <dt-bindings/clock/qcom,gcc-sdm660.h>

      bimc: interconnect@1008000 {
              compatible = "qcom,sdm660-bimc";
@@ -123,9 +150,20 @@ examples:
              compatible = "qcom,sdm660-a2noc";
              reg = <0x01704000 0xc100>;
              #interconnect-cells = <1>;
              clock-names = "bus", "bus_a";
              clock-names = "bus",
                            "bus_a",
                            "ipa",
                            "ufs_axi",
                            "aggre2_ufs_axi",
                            "aggre2_usb3_axi",
                            "cfg_noc_usb2_axi";
              clocks = <&rpmcc RPM_SMD_AGGR2_NOC_CLK>,
                       <&rpmcc RPM_SMD_AGGR2_NOC_A_CLK>;
                       <&rpmcc RPM_SMD_AGGR2_NOC_A_CLK>,
                       <&rpmcc RPM_SMD_IPA_CLK>,
                       <&gcc GCC_UFS_AXI_CLK>,
                       <&gcc GCC_AGGRE2_UFS_AXI_CLK>,
                       <&gcc GCC_AGGRE2_USB3_AXI_CLK>,
                       <&gcc GCC_CFG_NOC_USB2_AXI_CLK>;
      };

      mnoc: interconnect@1745000 {
+19 −6
Original line number Diff line number Diff line
@@ -44,9 +44,9 @@
#define NOC_PERM_MODE_BYPASS		(1 << NOC_QOS_MODE_BYPASS)

#define NOC_QOS_PRIORITYn_ADDR(n)	(0x8 + (n * 0x1000))
#define NOC_QOS_PRIORITY_MASK		0xf
#define NOC_QOS_PRIORITY_P1_MASK	0xc
#define NOC_QOS_PRIORITY_P0_MASK	0x3
#define NOC_QOS_PRIORITY_P1_SHIFT	0x2
#define NOC_QOS_PRIORITY_P0_SHIFT	0x3

#define NOC_QOS_MODEn_ADDR(n)		(0xc + (n * 0x1000))
#define NOC_QOS_MODEn_MASK		0x3
@@ -173,6 +173,16 @@ static const struct clk_bulk_data bus_mm_clocks[] = {
	{ .id = "iface" },
};

static const struct clk_bulk_data bus_a2noc_clocks[] = {
	{ .id = "bus" },
	{ .id = "bus_a" },
	{ .id = "ipa" },
	{ .id = "ufs_axi" },
	{ .id = "aggre2_ufs_axi" },
	{ .id = "aggre2_usb3_axi" },
	{ .id = "cfg_noc_usb2_axi" },
};

/**
 * struct qcom_icc_provider - Qualcomm specific interconnect provider
 * @provider: generic interconnect provider
@@ -307,7 +317,7 @@ DEFINE_QNODE(slv_bimc_cfg, SDM660_SLAVE_BIMC_CFG, 4, -1, 56, true, -1, 0, -1, 0)
DEFINE_QNODE(slv_prng, SDM660_SLAVE_PRNG, 4, -1, 44, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_spdm, SDM660_SLAVE_SPDM, 4, -1, 60, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_qdss_cfg, SDM660_SLAVE_QDSS_CFG, 4, -1, 63, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_cnoc_mnoc_cfg, SDM660_SLAVE_BLSP_1, 4, -1, 66, true, -1, 0, -1, SDM660_MASTER_CNOC_MNOC_CFG);
DEFINE_QNODE(slv_cnoc_mnoc_cfg, SDM660_SLAVE_CNOC_MNOC_CFG, 4, -1, 66, true, -1, 0, -1, SDM660_MASTER_CNOC_MNOC_CFG);
DEFINE_QNODE(slv_snoc_cfg, SDM660_SLAVE_SNOC_CFG, 4, -1, 70, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_qm_cfg, SDM660_SLAVE_QM_CFG, 4, -1, 212, true, -1, 0, -1, 0);
DEFINE_QNODE(slv_clk_ctl, SDM660_SLAVE_CLK_CTL, 4, -1, 47, true, -1, 0, -1, 0);
@@ -624,13 +634,12 @@ static int qcom_icc_noc_set_qos_priority(struct regmap *rmap,
	/* Must be updated one at a time, P1 first, P0 last */
	val = qos->areq_prio << NOC_QOS_PRIORITY_P1_SHIFT;
	rc = regmap_update_bits(rmap, NOC_QOS_PRIORITYn_ADDR(qos->qos_port),
				NOC_QOS_PRIORITY_MASK, val);
				NOC_QOS_PRIORITY_P1_MASK, val);
	if (rc)
		return rc;

	val = qos->prio_level << NOC_QOS_PRIORITY_P0_SHIFT;
	return regmap_update_bits(rmap, NOC_QOS_PRIORITYn_ADDR(qos->qos_port),
				  NOC_QOS_PRIORITY_MASK, val);
				  NOC_QOS_PRIORITY_P0_MASK, qos->prio_level);
}

static int qcom_icc_set_noc_qos(struct icc_node *src, u64 max_bw)
@@ -810,6 +819,10 @@ static int qnoc_probe(struct platform_device *pdev)
		qp->bus_clks = devm_kmemdup(dev, bus_mm_clocks,
					    sizeof(bus_mm_clocks), GFP_KERNEL);
		qp->num_clks = ARRAY_SIZE(bus_mm_clocks);
	} else if (of_device_is_compatible(dev->of_node, "qcom,sdm660-a2noc")) {
		qp->bus_clks = devm_kmemdup(dev, bus_a2noc_clocks,
					    sizeof(bus_a2noc_clocks), GFP_KERNEL);
		qp->num_clks = ARRAY_SIZE(bus_a2noc_clocks);
	} else {
		if (of_device_is_compatible(dev->of_node, "qcom,sdm660-bimc"))
			qp->is_bimc_node = true;
+47 −16
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ struct ipoctal_channel {
	unsigned int			pointer_read;
	unsigned int			pointer_write;
	struct tty_port			tty_port;
	bool				tty_registered;
	union scc2698_channel __iomem	*regs;
	union scc2698_block __iomem	*block_regs;
	unsigned int			board_id;
@@ -81,22 +82,34 @@ static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty)
	return 0;
}

static int ipoctal_open(struct tty_struct *tty, struct file *file)
static int ipoctal_install(struct tty_driver *driver, struct tty_struct *tty)
{
	struct ipoctal_channel *channel = dev_get_drvdata(tty->dev);
	struct ipoctal *ipoctal = chan_to_ipoctal(channel, tty->index);
	int err;

	tty->driver_data = channel;
	int res;

	if (!ipack_get_carrier(ipoctal->dev))
		return -EBUSY;

	err = tty_port_open(&channel->tty_port, tty, file);
	if (err)
	res = tty_standard_install(driver, tty);
	if (res)
		goto err_put_carrier;

	tty->driver_data = channel;

	return 0;

err_put_carrier:
	ipack_put_carrier(ipoctal->dev);

	return err;
	return res;
}

static int ipoctal_open(struct tty_struct *tty, struct file *file)
{
	struct ipoctal_channel *channel = tty->driver_data;

	return tty_port_open(&channel->tty_port, tty, file);
}

static void ipoctal_reset_stats(struct ipoctal_stats *stats)
@@ -264,7 +277,6 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
	int res;
	int i;
	struct tty_driver *tty;
	char name[20];
	struct ipoctal_channel *channel;
	struct ipack_region *region;
	void __iomem *addr;
@@ -355,8 +367,11 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
	/* Fill struct tty_driver with ipoctal data */
	tty->owner = THIS_MODULE;
	tty->driver_name = KBUILD_MODNAME;
	sprintf(name, KBUILD_MODNAME ".%d.%d.", bus_nr, slot);
	tty->name = name;
	tty->name = kasprintf(GFP_KERNEL, KBUILD_MODNAME ".%d.%d.", bus_nr, slot);
	if (!tty->name) {
		res = -ENOMEM;
		goto err_put_driver;
	}
	tty->major = 0;

	tty->minor_start = 0;
@@ -371,8 +386,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
	res = tty_register_driver(tty);
	if (res) {
		dev_err(&ipoctal->dev->dev, "Can't register tty driver.\n");
		tty_driver_kref_put(tty);
		return res;
		goto err_free_name;
	}

	/* Save struct tty_driver for use it when uninstalling the device */
@@ -383,7 +397,9 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,

		channel = &ipoctal->channel[i];
		tty_port_init(&channel->tty_port);
		tty_port_alloc_xmit_buf(&channel->tty_port);
		res = tty_port_alloc_xmit_buf(&channel->tty_port);
		if (res)
			continue;
		channel->tty_port.ops = &ipoctal_tty_port_ops;

		ipoctal_reset_stats(&channel->stats);
@@ -391,13 +407,15 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
		spin_lock_init(&channel->lock);
		channel->pointer_read = 0;
		channel->pointer_write = 0;
		tty_dev = tty_port_register_device(&channel->tty_port, tty, i, NULL);
		tty_dev = tty_port_register_device_attr(&channel->tty_port, tty,
							i, NULL, channel, NULL);
		if (IS_ERR(tty_dev)) {
			dev_err(&ipoctal->dev->dev, "Failed to register tty device.\n");
			tty_port_free_xmit_buf(&channel->tty_port);
			tty_port_destroy(&channel->tty_port);
			continue;
		}
		dev_set_drvdata(tty_dev, channel);
		channel->tty_registered = true;
	}

	/*
@@ -409,6 +427,13 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
				       ipoctal_irq_handler, ipoctal);

	return 0;

err_free_name:
	kfree(tty->name);
err_put_driver:
	tty_driver_kref_put(tty);

	return res;
}

static inline int ipoctal_copy_write_buffer(struct ipoctal_channel *channel,
@@ -648,6 +673,7 @@ static void ipoctal_cleanup(struct tty_struct *tty)

static const struct tty_operations ipoctal_fops = {
	.ioctl =		NULL,
	.install =		ipoctal_install,
	.open =			ipoctal_open,
	.close =		ipoctal_close,
	.write =		ipoctal_write_tty,
@@ -690,12 +716,17 @@ static void __ipoctal_remove(struct ipoctal *ipoctal)

	for (i = 0; i < NR_CHANNELS; i++) {
		struct ipoctal_channel *channel = &ipoctal->channel[i];

		if (!channel->tty_registered)
			continue;

		tty_unregister_device(ipoctal->tty_drv, i);
		tty_port_free_xmit_buf(&channel->tty_port);
		tty_port_destroy(&channel->tty_port);
	}

	tty_unregister_driver(ipoctal->tty_drv);
	kfree(ipoctal->tty_drv->name);
	tty_driver_kref_put(ipoctal->tty_drv);
	kfree(ipoctal);
}