Commit 6761a0ae authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'char-misc-5.15-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc

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
......@@ -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 {
......
......@@ -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;
......
......@@ -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)
ipack_put_carrier(ipoctal->dev);
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 res;
}
static int ipoctal_open(struct tty_struct *tty, struct file *file)
{
struct ipoctal_channel *channel = tty->driver_data;
return err;
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);
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment