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

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: ...@@ -31,11 +31,11 @@ properties:
clocks: clocks:
minItems: 1 minItems: 1
maxItems: 3 maxItems: 7
clock-names: clock-names:
minItems: 1 minItems: 1
maxItems: 3 maxItems: 7
required: required:
- compatible - compatible
...@@ -72,6 +72,32 @@ allOf: ...@@ -72,6 +72,32 @@ allOf:
contains: contains:
enum: enum:
- qcom,sdm660-a2noc - 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-bimc
- qcom,sdm660-cnoc - qcom,sdm660-cnoc
- qcom,sdm660-gnoc - qcom,sdm660-gnoc
...@@ -91,6 +117,7 @@ examples: ...@@ -91,6 +117,7 @@ examples:
- | - |
#include <dt-bindings/clock/qcom,rpmcc.h> #include <dt-bindings/clock/qcom,rpmcc.h>
#include <dt-bindings/clock/qcom,mmcc-sdm660.h> #include <dt-bindings/clock/qcom,mmcc-sdm660.h>
#include <dt-bindings/clock/qcom,gcc-sdm660.h>
bimc: interconnect@1008000 { bimc: interconnect@1008000 {
compatible = "qcom,sdm660-bimc"; compatible = "qcom,sdm660-bimc";
...@@ -123,9 +150,20 @@ examples: ...@@ -123,9 +150,20 @@ examples:
compatible = "qcom,sdm660-a2noc"; compatible = "qcom,sdm660-a2noc";
reg = <0x01704000 0xc100>; reg = <0x01704000 0xc100>;
#interconnect-cells = <1>; #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>, 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 { mnoc: interconnect@1745000 {
......
...@@ -44,9 +44,9 @@ ...@@ -44,9 +44,9 @@
#define NOC_PERM_MODE_BYPASS (1 << NOC_QOS_MODE_BYPASS) #define NOC_PERM_MODE_BYPASS (1 << NOC_QOS_MODE_BYPASS)
#define NOC_QOS_PRIORITYn_ADDR(n) (0x8 + (n * 0x1000)) #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_P1_SHIFT 0x2
#define NOC_QOS_PRIORITY_P0_SHIFT 0x3
#define NOC_QOS_MODEn_ADDR(n) (0xc + (n * 0x1000)) #define NOC_QOS_MODEn_ADDR(n) (0xc + (n * 0x1000))
#define NOC_QOS_MODEn_MASK 0x3 #define NOC_QOS_MODEn_MASK 0x3
...@@ -173,6 +173,16 @@ static const struct clk_bulk_data bus_mm_clocks[] = { ...@@ -173,6 +173,16 @@ static const struct clk_bulk_data bus_mm_clocks[] = {
{ .id = "iface" }, { .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 * struct qcom_icc_provider - Qualcomm specific interconnect provider
* @provider: generic 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) ...@@ -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_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_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_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_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_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); 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, ...@@ -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 */ /* Must be updated one at a time, P1 first, P0 last */
val = qos->areq_prio << NOC_QOS_PRIORITY_P1_SHIFT; val = qos->areq_prio << NOC_QOS_PRIORITY_P1_SHIFT;
rc = regmap_update_bits(rmap, NOC_QOS_PRIORITYn_ADDR(qos->qos_port), 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) if (rc)
return rc; return rc;
val = qos->prio_level << NOC_QOS_PRIORITY_P0_SHIFT;
return regmap_update_bits(rmap, NOC_QOS_PRIORITYn_ADDR(qos->qos_port), 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) 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) ...@@ -810,6 +819,10 @@ static int qnoc_probe(struct platform_device *pdev)
qp->bus_clks = devm_kmemdup(dev, bus_mm_clocks, qp->bus_clks = devm_kmemdup(dev, bus_mm_clocks,
sizeof(bus_mm_clocks), GFP_KERNEL); sizeof(bus_mm_clocks), GFP_KERNEL);
qp->num_clks = ARRAY_SIZE(bus_mm_clocks); 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 { } else {
if (of_device_is_compatible(dev->of_node, "qcom,sdm660-bimc")) if (of_device_is_compatible(dev->of_node, "qcom,sdm660-bimc"))
qp->is_bimc_node = true; qp->is_bimc_node = true;
......
...@@ -33,6 +33,7 @@ struct ipoctal_channel { ...@@ -33,6 +33,7 @@ struct ipoctal_channel {
unsigned int pointer_read; unsigned int pointer_read;
unsigned int pointer_write; unsigned int pointer_write;
struct tty_port tty_port; struct tty_port tty_port;
bool tty_registered;
union scc2698_channel __iomem *regs; union scc2698_channel __iomem *regs;
union scc2698_block __iomem *block_regs; union scc2698_block __iomem *block_regs;
unsigned int board_id; unsigned int board_id;
...@@ -81,22 +82,34 @@ static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty) ...@@ -81,22 +82,34 @@ static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty)
return 0; 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_channel *channel = dev_get_drvdata(tty->dev);
struct ipoctal *ipoctal = chan_to_ipoctal(channel, tty->index); struct ipoctal *ipoctal = chan_to_ipoctal(channel, tty->index);
int err; int res;
tty->driver_data = channel;
if (!ipack_get_carrier(ipoctal->dev)) if (!ipack_get_carrier(ipoctal->dev))
return -EBUSY; return -EBUSY;
err = tty_port_open(&channel->tty_port, tty, file); res = tty_standard_install(driver, tty);
if (err) if (res)
ipack_put_carrier(ipoctal->dev); 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) 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, ...@@ -264,7 +277,6 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
int res; int res;
int i; int i;
struct tty_driver *tty; struct tty_driver *tty;
char name[20];
struct ipoctal_channel *channel; struct ipoctal_channel *channel;
struct ipack_region *region; struct ipack_region *region;
void __iomem *addr; void __iomem *addr;
...@@ -355,8 +367,11 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, ...@@ -355,8 +367,11 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
/* Fill struct tty_driver with ipoctal data */ /* Fill struct tty_driver with ipoctal data */
tty->owner = THIS_MODULE; tty->owner = THIS_MODULE;
tty->driver_name = KBUILD_MODNAME; tty->driver_name = KBUILD_MODNAME;
sprintf(name, KBUILD_MODNAME ".%d.%d.", bus_nr, slot); tty->name = kasprintf(GFP_KERNEL, KBUILD_MODNAME ".%d.%d.", bus_nr, slot);
tty->name = name; if (!tty->name) {
res = -ENOMEM;
goto err_put_driver;
}
tty->major = 0; tty->major = 0;
tty->minor_start = 0; tty->minor_start = 0;
...@@ -371,8 +386,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, ...@@ -371,8 +386,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
res = tty_register_driver(tty); res = tty_register_driver(tty);
if (res) { if (res) {
dev_err(&ipoctal->dev->dev, "Can't register tty driver.\n"); dev_err(&ipoctal->dev->dev, "Can't register tty driver.\n");
tty_driver_kref_put(tty); goto err_free_name;
return res;
} }
/* Save struct tty_driver for use it when uninstalling the device */ /* 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, ...@@ -383,7 +397,9 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
channel = &ipoctal->channel[i]; channel = &ipoctal->channel[i];
tty_port_init(&channel->tty_port); 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; channel->tty_port.ops = &ipoctal_tty_port_ops;
ipoctal_reset_stats(&channel->stats); ipoctal_reset_stats(&channel->stats);
...@@ -391,13 +407,15 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, ...@@ -391,13 +407,15 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
spin_lock_init(&channel->lock); spin_lock_init(&channel->lock);
channel->pointer_read = 0; channel->pointer_read = 0;
channel->pointer_write = 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)) { if (IS_ERR(tty_dev)) {
dev_err(&ipoctal->dev->dev, "Failed to register tty device.\n"); 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); tty_port_destroy(&channel->tty_port);
continue; 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, ...@@ -409,6 +427,13 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
ipoctal_irq_handler, ipoctal); ipoctal_irq_handler, ipoctal);
return 0; 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, static inline int ipoctal_copy_write_buffer(struct ipoctal_channel *channel,
...@@ -648,6 +673,7 @@ static void ipoctal_cleanup(struct tty_struct *tty) ...@@ -648,6 +673,7 @@ static void ipoctal_cleanup(struct tty_struct *tty)
static const struct tty_operations ipoctal_fops = { static const struct tty_operations ipoctal_fops = {
.ioctl = NULL, .ioctl = NULL,
.install = ipoctal_install,
.open = ipoctal_open, .open = ipoctal_open,
.close = ipoctal_close, .close = ipoctal_close,
.write = ipoctal_write_tty, .write = ipoctal_write_tty,
...@@ -690,12 +716,17 @@ static void __ipoctal_remove(struct ipoctal *ipoctal) ...@@ -690,12 +716,17 @@ static void __ipoctal_remove(struct ipoctal *ipoctal)
for (i = 0; i < NR_CHANNELS; i++) { for (i = 0; i < NR_CHANNELS; i++) {
struct ipoctal_channel *channel = &ipoctal->channel[i]; struct ipoctal_channel *channel = &ipoctal->channel[i];
if (!channel->tty_registered)
continue;
tty_unregister_device(ipoctal->tty_drv, i); tty_unregister_device(ipoctal->tty_drv, i);
tty_port_free_xmit_buf(&channel->tty_port); tty_port_free_xmit_buf(&channel->tty_port);
tty_port_destroy(&channel->tty_port); tty_port_destroy(&channel->tty_port);
} }
tty_unregister_driver(ipoctal->tty_drv); tty_unregister_driver(ipoctal->tty_drv);
kfree(ipoctal->tty_drv->name);
tty_driver_kref_put(ipoctal->tty_drv); tty_driver_kref_put(ipoctal->tty_drv);
kfree(ipoctal); kfree(ipoctal);
} }
......
Markdown is supported
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