| .. | .. |
|---|
| 222 | 222 | |
|---|
| 223 | 223 | channel->glink = glink; |
|---|
| 224 | 224 | channel->name = kstrdup(name, GFP_KERNEL); |
|---|
| 225 | + if (!channel->name) { |
|---|
| 226 | + kfree(channel); |
|---|
| 227 | + return ERR_PTR(-ENOMEM); |
|---|
| 228 | + } |
|---|
| 225 | 229 | |
|---|
| 226 | 230 | init_completion(&channel->open_req); |
|---|
| 227 | 231 | init_completion(&channel->open_ack); |
|---|
| .. | .. |
|---|
| 553 | 557 | break; |
|---|
| 554 | 558 | case GLINK_VERSION_1: |
|---|
| 555 | 559 | glink->features &= features; |
|---|
| 556 | | - /* FALLTHROUGH */ |
|---|
| 560 | + fallthrough; |
|---|
| 557 | 561 | default: |
|---|
| 558 | 562 | qcom_glink_send_version_ack(glink); |
|---|
| 559 | 563 | break; |
|---|
| .. | .. |
|---|
| 584 | 588 | break; |
|---|
| 585 | 589 | |
|---|
| 586 | 590 | glink->features &= features; |
|---|
| 587 | | - /* FALLTHROUGH */ |
|---|
| 591 | + fallthrough; |
|---|
| 588 | 592 | default: |
|---|
| 589 | 593 | qcom_glink_send_version(glink); |
|---|
| 590 | 594 | break; |
|---|
| .. | .. |
|---|
| 914 | 918 | struct intent_pair intents[]; |
|---|
| 915 | 919 | } __packed * msg; |
|---|
| 916 | 920 | |
|---|
| 917 | | - const size_t msglen = sizeof(*msg) + sizeof(struct intent_pair) * count; |
|---|
| 921 | + const size_t msglen = struct_size(msg, intents, count); |
|---|
| 918 | 922 | int ret; |
|---|
| 919 | 923 | int i; |
|---|
| 920 | 924 | unsigned long flags; |
|---|
| .. | .. |
|---|
| 929 | 933 | spin_unlock_irqrestore(&glink->idr_lock, flags); |
|---|
| 930 | 934 | if (!channel) { |
|---|
| 931 | 935 | dev_err(glink->dev, "intents for non-existing channel\n"); |
|---|
| 936 | + qcom_glink_rx_advance(glink, ALIGN(msglen, 8)); |
|---|
| 932 | 937 | return; |
|---|
| 933 | 938 | } |
|---|
| 934 | 939 | |
|---|
| .. | .. |
|---|
| 1472 | 1477 | cancel_work_sync(&channel->intent_work); |
|---|
| 1473 | 1478 | |
|---|
| 1474 | 1479 | if (channel->rpdev) { |
|---|
| 1475 | | - strncpy(chinfo.name, channel->name, sizeof(chinfo.name)); |
|---|
| 1480 | + strscpy_pad(chinfo.name, channel->name, sizeof(chinfo.name)); |
|---|
| 1476 | 1481 | chinfo.src = RPMSG_ADDR_ANY; |
|---|
| 1477 | 1482 | chinfo.dst = RPMSG_ADDR_ANY; |
|---|
| 1478 | 1483 | |
|---|
| .. | .. |
|---|
| 1575 | 1580 | kfree(dcmd); |
|---|
| 1576 | 1581 | } |
|---|
| 1577 | 1582 | |
|---|
| 1583 | +static ssize_t rpmsg_name_show(struct device *dev, |
|---|
| 1584 | + struct device_attribute *attr, char *buf) |
|---|
| 1585 | +{ |
|---|
| 1586 | + int ret = 0; |
|---|
| 1587 | + const char *name; |
|---|
| 1588 | + |
|---|
| 1589 | + ret = of_property_read_string(dev->of_node, "label", &name); |
|---|
| 1590 | + if (ret < 0) |
|---|
| 1591 | + name = dev->of_node->name; |
|---|
| 1592 | + |
|---|
| 1593 | + return snprintf(buf, RPMSG_NAME_SIZE, "%s\n", name); |
|---|
| 1594 | +} |
|---|
| 1595 | +static DEVICE_ATTR_RO(rpmsg_name); |
|---|
| 1596 | + |
|---|
| 1597 | +static struct attribute *qcom_glink_attrs[] = { |
|---|
| 1598 | + &dev_attr_rpmsg_name.attr, |
|---|
| 1599 | + NULL |
|---|
| 1600 | +}; |
|---|
| 1601 | +ATTRIBUTE_GROUPS(qcom_glink); |
|---|
| 1602 | + |
|---|
| 1603 | +static void qcom_glink_device_release(struct device *dev) |
|---|
| 1604 | +{ |
|---|
| 1605 | + struct rpmsg_device *rpdev = to_rpmsg_device(dev); |
|---|
| 1606 | + struct glink_channel *channel = to_glink_channel(rpdev->ept); |
|---|
| 1607 | + |
|---|
| 1608 | + /* Release qcom_glink_alloc_channel() reference */ |
|---|
| 1609 | + kref_put(&channel->refcount, qcom_glink_channel_release); |
|---|
| 1610 | + kfree(rpdev); |
|---|
| 1611 | +} |
|---|
| 1612 | + |
|---|
| 1613 | +static int qcom_glink_create_chrdev(struct qcom_glink *glink) |
|---|
| 1614 | +{ |
|---|
| 1615 | + struct rpmsg_device *rpdev; |
|---|
| 1616 | + struct glink_channel *channel; |
|---|
| 1617 | + |
|---|
| 1618 | + rpdev = kzalloc(sizeof(*rpdev), GFP_KERNEL); |
|---|
| 1619 | + if (!rpdev) |
|---|
| 1620 | + return -ENOMEM; |
|---|
| 1621 | + |
|---|
| 1622 | + channel = qcom_glink_alloc_channel(glink, "rpmsg_chrdev"); |
|---|
| 1623 | + if (IS_ERR(channel)) { |
|---|
| 1624 | + kfree(rpdev); |
|---|
| 1625 | + return PTR_ERR(channel); |
|---|
| 1626 | + } |
|---|
| 1627 | + channel->rpdev = rpdev; |
|---|
| 1628 | + |
|---|
| 1629 | + rpdev->ept = &channel->ept; |
|---|
| 1630 | + rpdev->ops = &glink_device_ops; |
|---|
| 1631 | + rpdev->dev.parent = glink->dev; |
|---|
| 1632 | + rpdev->dev.release = qcom_glink_device_release; |
|---|
| 1633 | + |
|---|
| 1634 | + return rpmsg_chrdev_register_device(rpdev); |
|---|
| 1635 | +} |
|---|
| 1636 | + |
|---|
| 1578 | 1637 | struct qcom_glink *qcom_glink_native_probe(struct device *dev, |
|---|
| 1579 | 1638 | unsigned long features, |
|---|
| 1580 | 1639 | struct qcom_glink_pipe *rx, |
|---|
| .. | .. |
|---|
| 1605 | 1664 | idr_init(&glink->lcids); |
|---|
| 1606 | 1665 | idr_init(&glink->rcids); |
|---|
| 1607 | 1666 | |
|---|
| 1667 | + glink->dev->groups = qcom_glink_groups; |
|---|
| 1668 | + |
|---|
| 1669 | + ret = device_add_groups(dev, qcom_glink_groups); |
|---|
| 1670 | + if (ret) |
|---|
| 1671 | + dev_err(dev, "failed to add groups\n"); |
|---|
| 1672 | + |
|---|
| 1608 | 1673 | ret = of_property_read_string(dev->of_node, "label", &glink->name); |
|---|
| 1609 | 1674 | if (ret < 0) |
|---|
| 1610 | 1675 | glink->name = dev->of_node->name; |
|---|
| .. | .. |
|---|
| 1634 | 1699 | if (ret) |
|---|
| 1635 | 1700 | return ERR_PTR(ret); |
|---|
| 1636 | 1701 | |
|---|
| 1702 | + ret = qcom_glink_create_chrdev(glink); |
|---|
| 1703 | + if (ret) |
|---|
| 1704 | + dev_err(glink->dev, "failed to register chrdev\n"); |
|---|
| 1705 | + |
|---|
| 1637 | 1706 | return glink; |
|---|
| 1638 | 1707 | } |
|---|
| 1639 | 1708 | EXPORT_SYMBOL_GPL(qcom_glink_native_probe); |
|---|