kernel-fxtec-pro1x/drivers/rpmsg/qcom_glink_smem.c
Ivaylo Georgiev cda8925044 Merge android-4.19-q.86 (10f1d14) into msm-4.19
* refs/heads/tmp-10f1d14:
  Linux 4.19.86
  x86/resctrl: Fix rdt_find_domain() return value and checks
  mmc: tmio: fix SCC error handling to avoid false positive CRC error
  powerpc/time: Fix clockevent_decrementer initalisation for PR KVM
  tools: PCI: Fix broken pcitest compilation
  PM / devfreq: Fix static checker warning in try_then_request_governor
  ACPI / LPSS: Use acpi_lpss_* instead of acpi_subsys_* functions for hibernate
  tcp: start receiver buffer autotuning sooner
  ARM: dts: omap5: Fix dual-role mode on Super-Speed port
  mlxsw: spectrum_switchdev: Check notification relevance based on upper device
  spi: rockchip: initialize dma_slave_config properly
  mac80211: minstrel: fix sampling/reporting of CCK rates in HT mode
  mac80211: minstrel: fix CCK rate group streams value
  mac80211: minstrel: fix using short preamble CCK rates on HT clients
  misc: cxl: Fix possible null pointer dereference
  netfilter: nft_compat: do not dump private area
  net: sched: avoid writing on noop_qdisc
  selftests: forwarding: Have lldpad_app_wait_set() wait for unknown, too
  hwmon: (npcm-750-pwm-fan) Change initial pwm target to 255
  hwmon: (ina3221) Fix INA3221_CONFIG_MODE macros
  hwmon: (pwm-fan) Silence error on probe deferral
  hwmon: (nct6775) Fix names of DIMM temperature sources
  hwmon: (k10temp) Support all Family 15h Model 6xh and Model 7xh processors
  scsi: arcmsr: clean up clang warning on extraneous parentheses
  pinctrl: gemini: Fix up TVC clock group
  orangefs: rate limit the client not running info message
  x86/mm: Do not warn about PCI BIOS W+X mappings
  ARM: 8802/1: Call syscall_trace_exit even when system call skipped
  spi: spidev: Fix OF tree warning logic
  pinctrl: gemini: Mask and set properly
  spi: fsl-lpspi: Prevent FIFO under/overrun by default
  gpio: syscon: Fix possible NULL ptr usage
  net: fix generic XDP to handle if eth header was mangled
  bpf: btf: Fix a missing check bug
  x86/kexec: Correct KEXEC_BACKUP_SRC_END off-by-one error
  lightnvm: pblk: consider max hw sectors supported for max_write_pgs
  lightnvm: pblk: fix error handling of pblk_lines_init()
  lightnvm: do no update csecs and sos on 1.2
  lightnvm: pblk: guarantee mw_cunits on read buffer
  lightnvm: pblk: fix write amplificiation calculation
  lightnvm: pblk: guarantee emeta on line close
  lightnvm: pblk: fix incorrect min_write_pgs
  lightnvm: pblk: fix rqd.error return value in pblk_blk_erase_sync
  ALSA: hda/ca0132 - Fix input effect controls for desktop cards
  media: venus: vdec: fix decoded data size
  media: cx231xx: fix potential sign-extension overflow on large shift
  GFS2: Flush the GFS2 delete workqueue before stopping the kernel threads
  media: isif: fix a NULL pointer dereference bug
  printk: Give error on attempt to set log buffer length to over 2G
  mfd: ti_am335x_tscadc: Keep ADC interface on if child is wakeup capable
  backlight: lm3639: Unconditionally call led_classdev_unregister
  proc/vmcore: Fix i386 build error of missing copy_oldmem_page_encrypted()
  s390/kasan: avoid user access code instrumentation
  s390/kasan: avoid instrumentation of early C code
  s390/kasan: avoid vdso instrumentation
  mmc: mmci: expand startbiterr to irqmask and error check
  x86/intel_rdt: CBM overlap should also check for overlap with CDP peer
  x86/intel_rdt: Introduce utility to obtain CDP peer
  mtd: devices: m25p80: Make sure WRITE_EN is issued before each write
  mtd: spi-nor: cadence-quadspi: Use proper enum for dma_[un]map_single
  media: cx18: Don't check for address of video_dev
  media: dw9807-vcm: Fix probe error handling
  media: dw9714: Fix error handling in probe function
  platform/x86: mlx-platform: Properly use mlxplat_mlxcpld_msn201x_items
  bcache: recal cached_dev_sectors on detach
  bcache: account size of buckets used in uuid write to ca->meta_sectors_written
  reset: Fix potential use-after-free in __of_reset_control_get()
  fbdev: fix broken menu dependencies
  fbdev: sbuslib: integer overflow in sbusfb_ioctl_helper()
  fbdev: sbuslib: use checked version of put_user()
  atmel_lcdfb: support native-mode display-timings
  mmc: renesas_sdhi_internal_dmac: set scatter/gather max segment size
  mmc: tmio: Fix SCC error detection
  mmc: renesas_sdhi_internal_dmac: Whitelist r8a774a1
  x86/fsgsbase/64: Fix ptrace() to read the FS/GS base accurately
  xsk: proper AF_XDP socket teardown ordering
  iwlwifi: mvm: don't send keys when entering D3
  ACPI / SBS: Fix rare oops when removing modules
  xfrm: use correct size to initialise sp->ovec
  crypto: mxs-dcp - Fix AES issues
  crypto: mxs-dcp - Fix SHA null hashes and output length
  dmaengine: rcar-dmac: set scatter/gather max segment size
  x86/olpc: Fix build error with CONFIG_MFD_CS5535=m
  kexec: Allocate decrypted control pages for kdump if SME is enabled
  remoteproc: qcom: q6v5: Fix a race condition on fatal crash
  remoteproc: Check for NULL firmwares in sysfs interface
  tc-testing: fix build of eBPF programs
  net: hns3: Fix for rx vlan id handle to support Rev 0x21 hardware
  soc: fsl: bman_portals: defer probe after bman's probe
  Input: silead - try firmware reload after unsuccessful resume
  Input: st1232 - set INPUT_PROP_DIRECT property
  i2c: zx2967: use core to detect 'no zero length' quirk
  i2c: tegra: use core to detect 'no zero length' quirk
  i2c: qup: use core to detect 'no zero length' quirk
  i2c: omap: use core to detect 'no zero length' quirk
  gfs2: slow the deluge of io error messages
  media: cec-gpio: select correct Signal Free Time
  media: ov5640: fix framerate update
  dmaengine: ioat: fix prototype of ioat_enumerate_channels
  NFSv4.x: fix lock recovery during delegation recall
  printk: Correct wrong casting
  i2c: brcmstb: Allow enabling the driver on DSL SoCs
  clk: samsung: Use clk_hw API for calling clk framework from clk notifiers
  clk: samsung: exynos5420: Define CLK_SECKEY gate clock only or Exynos5420
  clk: samsung: Use NOIRQ stage for Exynos5433 clocks suspend/resume
  qtnfmac: drop error reports for out-of-bounds key indexes
  qtnfmac: inform wireless core about supported extended capabilities
  qtnfmac: pass sgi rate info flag to wireless core
  qtnfmac: request userspace to do OBSS scanning if FW can not
  brcmfmac: fix full timeout waiting for action frame on-channel tx
  brcmfmac: reduce timeout for action frame scan
  cpu/SMT: State SMT is disabled even with nosmt and without "=force"
  mtd: physmap_of: Release resources on error
  usb: dwc2: disable power_down on rockchip devices
  USB: serial: cypress_m8: fix interrupt-out transfer length
  KVM: PPC: Book3S PR: Exiting split hack mode needs to fixup both PC and LR
  bnxt_en: return proper error when FW returns HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED
  ALSA: hda/sigmatel - Disable automute for Elo VuPoint
  media: i2c: adv748x: Support probing a single output
  media: rcar-vin: fix redeclaration of symbol
  media: pxa_camera: Fix check for pdev->dev.of_node
  media: rc: ir-rc6-decoder: enable toggle bit for Kathrein RCU-676 remote
  qed: Avoid implicit enum conversion in qed_ooo_submit_tx_buffers
  ata: ep93xx: Use proper enums for directions
  powerpc/64s/radix: Explicitly flush ERAT with local LPID invalidation
  powerpc/time: Use clockevents_register_device(), fixing an issue with large decrementer
  ASoC: qdsp6: q6asm-dai: checking NULL vs IS_ERR()
  cpuidle: menu: Fix wakeup statistics updates for polling state
  ACPICA: Never run _REG on system_memory and system_IO
  OPP: Return error on error from dev_pm_opp_get_opp_count()
  msm/gpu/a6xx: Force of_dma_configure to setup DMA for GMU
  rpmsg: glink: smem: Support rx peak for size less than 4 bytes
  IB/mlx4: Avoid implicit enumerated type conversion
  RDMA/hns: Limit the size of extend sge of sq
  RDMA/hns: Bugfix for CM test
  RDMA/hns: Submit bad wr when post send wr exception
  RDMA/hns: Bugfix for reserved qp number
  IB/rxe: avoid srq memory leak
  IB/mthca: Fix error return code in __mthca_init_one()
  ixgbe: Fix crash with VFs and flow director on interface flap
  i40e: Use proper enum in i40e_ndo_set_vf_link_state
  ixgbe: Fix ixgbe TX hangs with XDP_TX beyond queue limit
  md: allow metadata updates while suspending an array - fix
  ice: Fix forward to queue group logic
  clocksource/drivers/sh_cmt: Fix clocksource width for 32-bit machines
  clocksource/drivers/sh_cmt: Fixup for 64-bit machines
  tools: PCI: Fix compilation warnings
  PM / hibernate: Check the success of generating md5 digest before hibernation
  mtd: rawnand: sh_flctl: Use proper enum for flctl_dma_fifo0_transfer
  ARM: dts: at91: sama5d2_ptc_ek: fix bootloader env offsets
  ARM: dts: at91: at91sam9x5cm: fix addressable nand flash size
  ARM: dts: at91: sama5d4_xplained: fix addressable nand flash size
  powerpc/xive: Move a dereference below a NULL test
  powerpc/pseries: Fix how we iterate over the DTL entries
  powerpc/pseries: Fix DTL buffer registration
  cxgb4: Use proper enum in IEEE_FAUX_SYNC
  cxgb4: Use proper enum in cxgb4_dcb_handle_fw_update
  mei: samples: fix a signedness bug in amt_host_if_call()
  x86/PCI: Apply VMD's AERSID fixup generically
  sunrpc: Fix connect metrics
  clk: keystone: Enable TISCI clocks if K3_ARCH
  ext4: fix build error when DX_DEBUG is defined
  ALSA: hda: Fix mismatch for register mask and value in ext controller.
  dmaengine: timb_dma: Use proper enum in td_prep_slave_sg
  dmaengine: ep93xx: Return proper enum in ep93xx_dma_chan_direction
  printk: CON_PRINTBUFFER console registration is a bit racy
  printk: Do not miss new messages when replaying the log
  KVM: PPC: Inform the userspace about TCE update failures
  watchdog: w83627hf_wdt: Support NCT6796D, NCT6797D, NCT6798D
  watchdog: sama5d4: fix timeout-sec usage
  watchdog: renesas_wdt: stop when unregistering
  watchdog: core: fix null pointer dereference when releasing cdev
  irqchip/irq-mvebu-icu: Fix wrong private data retrieval
  nl80211: Fix a GET_KEY reply attribute
  usb: dwc3: gadget: Check ENBLSLPM before sending ep command
  usb: gadget: udc: fotg210-udc: Fix a sleep-in-atomic-context bug in fotg210_get_status()
  selftests/tls: Fix recv(MSG_PEEK) & splice() test cases
  ath9k: fix reporting calculated new FFT upper max
  PM / devfreq: stopping the governor before device_unregister()
  PM / devfreq: Fix handling of min/max_freq == 0
  PM / devfreq: Fix devfreq_add_device() when drivers are built as modules.
  ata: ahci_brcm: Allow using driver or DSL SoCs
  rtlwifi: btcoex: Use proper enumerated types for Wi-Fi only interface
  ath10k: fix vdev-start timeout on error
  arm64/numa: Report correct memblock range for the dummy node
  kvm: arm/arm64: Fix stage2_flush_memslot for 4 level page table
  iommu/arm-smmu-v3: Fix unexpected CMD_SYNC timeout
  iommu/io-pgtable-arm: Fix race handling in split_blk_unmap()
  mt76: fix handling ps-poll frames
  mt76x2: disable WLAN core before probe
  mt76x2: fix tx power configuration for VHT mcs 9
  IB/hfi1: Ensure ucast_dlid access doesnt exceed bounds
  IB/hfi1: Error path MAD response size is incorrect
  f2fs: keep lazytime on remount
  ACPI / LPSS: Resume BYT/CHT I2C controllers from resume_noirq
  ACPI / LPSS: Make acpi_lpss_find_device() also find PCI devices
  SUNRPC: Fix priority queue fairness
  tcp: up initial rmem to 128KB and SYN rwin to around 64KB
  ARM: dts: sun8i: h3: bpi-m2-plus: Fix address for external RGMII Ethernet PHY
  ARM: dts: sun8i: h3-h5: ir register size should be the whole memory block
  f2fs: return correct errno in f2fs_gc
  net: hns3: Fix loss of coal configuration while doing reset
  net: hns3: Fix for netdev not up problem when setting mtu
  ARM: dts: omap5: enable OTG role for DWC3 controller
  ARM: dts: dra7: Enable workaround for errata i870 in PCIe host mode
  net: xen-netback: fix return type of ndo_start_xmit function
  net: ovs: fix return type of ndo_start_xmit function
  bpf, x32: Fix bug for BPF_JMP | {BPF_JSGT, BPF_JSLE, BPF_JSLT, BPF_JSGE}
  bpf, x32: Fix bug with ALU64 {LSH, RSH, ARSH} BPF_K shift by 0
  bpf, x32: Fix bug with ALU64 {LSH, RSH, ARSH} BPF_X shift by 0
  bpf, x32: Fix bug for BPF_ALU64 | BPF_NEG
  fbdev: Ditch fb_edid_add_monspecs
  arm64: uaccess: Ensure PAN is re-enabled after unhandled uaccess fault
  mm/memory_hotplug: fix updating the node span
  mm/memory_hotplug: don't access uninitialized memmaps in shrink_pgdat_span()
  idr: Fix idr_get_next race with idr_remove
  net: cdc_ncm: Signedness bug in cdc_ncm_set_dgram_size()
  Revert "OPP: Protect dev_list with opp_table lock"
  tee: optee: add missing of_node_put after of_device_is_available
  i2c: mediatek: modify threshold passed to i2c_get_dma_safe_msg_buf()
  spi: mediatek: use correct mata->xfer_len when in fifo transfer

Conflicts:
	drivers/rpmsg/qcom_glink_smem.c
	drivers/usb/dwc3/gadget.c

Change-Id: I6e0f156d860bf2afcaabcf70d653676eb7d3de4e
Signed-off-by: Ivaylo Georgiev <irgeorgiev@codeaurora.org>
2020-01-28 03:10:58 -08:00

336 lines
7.6 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2016, Linaro Ltd
* Copyright (c) 2018-2019, The Linux Foundation, All rights reserved.
*/
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/mfd/syscon.h>
#include <linux/slab.h>
#include <linux/rpmsg.h>
#include <linux/idr.h>
#include <linux/circ_buf.h>
#include <linux/soc/qcom/smem.h>
#include <linux/sizes.h>
#include <linux/delay.h>
#include <linux/regmap.h>
#include <linux/workqueue.h>
#include <linux/list.h>
#include <linux/rpmsg/qcom_glink.h>
#include "qcom_glink_native.h"
#define FIFO_FULL_RESERVE 8
#define FIFO_ALIGNMENT 8
#define TX_BLOCKED_CMD_RESERVE 8 /* size of struct read_notif_request */
#define SMEM_GLINK_NATIVE_XPRT_DESCRIPTOR 478
#define SMEM_GLINK_NATIVE_XPRT_FIFO_0 479
#define SMEM_GLINK_NATIVE_XPRT_FIFO_1 480
struct glink_smem_pipe {
struct qcom_glink_pipe native;
__le32 *tail;
__le32 *head;
void *fifo;
int remote_pid;
};
#define to_smem_pipe(p) container_of(p, struct glink_smem_pipe, native)
static void glink_smem_rx_reset(struct qcom_glink_pipe *np)
{
struct glink_smem_pipe *pipe = to_smem_pipe(np);
*pipe->tail = 0;
}
static size_t glink_smem_rx_avail(struct qcom_glink_pipe *np)
{
struct glink_smem_pipe *pipe = to_smem_pipe(np);
size_t len;
void *fifo;
u32 head;
u32 tail;
if (!pipe->fifo) {
fifo = qcom_smem_get(pipe->remote_pid,
SMEM_GLINK_NATIVE_XPRT_FIFO_1, &len);
if (IS_ERR(fifo)) {
pr_err("failed to acquire RX fifo handle: %ld\n",
PTR_ERR(fifo));
return 0;
}
pipe->fifo = fifo;
pipe->native.length = len;
}
head = le32_to_cpu(*pipe->head);
tail = le32_to_cpu(*pipe->tail);
if (head < tail)
len = pipe->native.length - tail + head;
else
len = head - tail;
if (WARN_ON_ONCE(len > pipe->native.length))
len = 0;
return len;
}
static void glink_smem_rx_peak(struct qcom_glink_pipe *np,
void *data, unsigned int offset, size_t count)
{
struct glink_smem_pipe *pipe = to_smem_pipe(np);
size_t len;
u32 tail;
tail = le32_to_cpu(*pipe->tail);
if (WARN_ON_ONCE(tail > pipe->native.length))
return;
tail += offset;
if (tail >= pipe->native.length)
tail -= pipe->native.length;
len = min_t(size_t, count, pipe->native.length - tail);
if (len)
memcpy_fromio(data, pipe->fifo + tail, len);
if (len != count)
memcpy_fromio(data + len, pipe->fifo, (count - len));
}
static void glink_smem_rx_advance(struct qcom_glink_pipe *np,
size_t count)
{
struct glink_smem_pipe *pipe = to_smem_pipe(np);
u32 tail;
tail = le32_to_cpu(*pipe->tail);
tail += count;
if (tail >= pipe->native.length)
tail %= pipe->native.length;
*pipe->tail = cpu_to_le32(tail);
}
static void glink_smem_tx_reset(struct qcom_glink_pipe *np)
{
struct glink_smem_pipe *pipe = to_smem_pipe(np);
*pipe->head = 0;
}
static size_t glink_smem_tx_avail(struct qcom_glink_pipe *np)
{
struct glink_smem_pipe *pipe = to_smem_pipe(np);
u32 head;
u32 tail;
u32 avail;
head = le32_to_cpu(*pipe->head);
tail = le32_to_cpu(*pipe->tail);
if (tail <= head)
avail = pipe->native.length - head + tail;
else
avail = tail - head;
if (avail < (FIFO_FULL_RESERVE + TX_BLOCKED_CMD_RESERVE))
avail = 0;
else
avail -= FIFO_FULL_RESERVE + TX_BLOCKED_CMD_RESERVE;
if (WARN_ON_ONCE(avail > pipe->native.length))
avail = 0;
return avail;
}
static unsigned int glink_smem_tx_write_one(struct glink_smem_pipe *pipe,
unsigned int head,
const void *data, size_t count)
{
size_t len;
if (WARN_ON_ONCE(head > pipe->native.length))
return head;
len = min_t(size_t, count, pipe->native.length - head);
if (len)
memcpy(pipe->fifo + head, data, len);
if (len != count)
memcpy(pipe->fifo, data + len, count - len);
head += count;
if (head >= pipe->native.length)
head -= pipe->native.length;
return head;
}
static void glink_smem_tx_write(struct qcom_glink_pipe *glink_pipe,
const void *hdr, size_t hlen,
const void *data, size_t dlen)
{
struct glink_smem_pipe *pipe = to_smem_pipe(glink_pipe);
unsigned int head;
head = le32_to_cpu(*pipe->head);
head = glink_smem_tx_write_one(pipe, head, hdr, hlen);
head = glink_smem_tx_write_one(pipe, head, data, dlen);
/* Ensure head is always aligned to 8 bytes */
head = ALIGN(head, 8);
if (head >= pipe->native.length)
head -= pipe->native.length;
/* Ensure ordering of fifo and head update */
wmb();
*pipe->head = cpu_to_le32(head);
}
static void qcom_glink_smem_release(struct device *dev)
{
kfree(dev);
}
struct qcom_glink *qcom_glink_smem_register(struct device *parent,
struct device_node *node)
{
struct glink_smem_pipe *rx_pipe;
struct glink_smem_pipe *tx_pipe;
struct qcom_glink *glink;
struct device *dev;
u32 remote_pid;
__le32 *descs;
size_t size;
int ret;
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return ERR_PTR(-ENOMEM);
dev->parent = parent;
dev->of_node = node;
dev->release = qcom_glink_smem_release;
dev_set_name(dev, "%s:%s", node->parent->name, node->name);
ret = device_register(dev);
if (ret) {
pr_err("failed to register glink edge\n");
put_device(dev);
return ERR_PTR(ret);
}
ret = of_property_read_u32(dev->of_node, "qcom,remote-pid",
&remote_pid);
if (ret) {
dev_err(dev, "failed to parse qcom,remote-pid\n");
goto err_put_dev;
}
rx_pipe = devm_kzalloc(dev, sizeof(*rx_pipe), GFP_KERNEL);
tx_pipe = devm_kzalloc(dev, sizeof(*tx_pipe), GFP_KERNEL);
if (!rx_pipe || !tx_pipe) {
ret = -ENOMEM;
goto err_put_dev;
}
ret = qcom_smem_alloc(remote_pid,
SMEM_GLINK_NATIVE_XPRT_DESCRIPTOR, 32);
if (ret && ret != -EEXIST) {
dev_err(dev, "failed to allocate glink descriptors\n");
goto err_put_dev;
}
descs = qcom_smem_get(remote_pid,
SMEM_GLINK_NATIVE_XPRT_DESCRIPTOR, &size);
if (IS_ERR(descs)) {
dev_err(dev, "failed to acquire xprt descriptor\n");
ret = PTR_ERR(descs);
goto err_put_dev;
}
if (size != 32) {
dev_err(dev, "glink descriptor of invalid size\n");
ret = -EINVAL;
goto err_put_dev;
}
tx_pipe->tail = &descs[0];
tx_pipe->head = &descs[1];
rx_pipe->tail = &descs[2];
rx_pipe->head = &descs[3];
ret = qcom_smem_alloc(remote_pid, SMEM_GLINK_NATIVE_XPRT_FIFO_0,
SZ_16K);
if (ret && ret != -EEXIST) {
dev_err(dev, "failed to allocate TX fifo\n");
goto err_put_dev;
}
tx_pipe->fifo = qcom_smem_get(remote_pid, SMEM_GLINK_NATIVE_XPRT_FIFO_0,
&tx_pipe->native.length);
if (IS_ERR(tx_pipe->fifo)) {
dev_err(dev, "failed to acquire TX fifo\n");
ret = PTR_ERR(tx_pipe->fifo);
goto err_put_dev;
}
rx_pipe->native.reset = glink_smem_rx_reset;
rx_pipe->native.avail = glink_smem_rx_avail;
rx_pipe->native.peak = glink_smem_rx_peak;
rx_pipe->native.advance = glink_smem_rx_advance;
rx_pipe->remote_pid = remote_pid;
tx_pipe->native.reset = glink_smem_tx_reset;
tx_pipe->native.avail = glink_smem_tx_avail;
tx_pipe->native.write = glink_smem_tx_write;
tx_pipe->remote_pid = remote_pid;
*rx_pipe->tail = 0;
*tx_pipe->head = 0;
glink = qcom_glink_native_probe(dev,
GLINK_FEATURE_INTENT_REUSE,
&rx_pipe->native, &tx_pipe->native,
false);
if (IS_ERR(glink)) {
ret = PTR_ERR(glink);
goto err_put_dev;
}
return glink;
err_put_dev:
device_unregister(dev);
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(qcom_glink_smem_register);
void qcom_glink_smem_unregister(struct qcom_glink *glink)
{
qcom_glink_native_remove(glink);
qcom_glink_native_unregister(glink);
}
EXPORT_SYMBOL_GPL(qcom_glink_smem_unregister);
MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@linaro.org>");
MODULE_DESCRIPTION("Qualcomm GLINK SMEM driver");
MODULE_LICENSE("GPL v2");