diff options
56 files changed, 731 insertions, 401 deletions
diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt index d00a5c1ce502..9e512d1ea763 100644 --- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt @@ -139,8 +139,8 @@ conditions. time. This should be a list of 2-tuples of the format: <offset reg_value>. -- qcom,bus-master-id : The master ID of the bus, if a bus vote is needed. - See include/dt-bindings/msm/msm-bus-ids.h. +Optional bus bindings as defined in +Documentation/devicetree/bindings/arm/msm/msm_bus.txt may also be present. Example: diff --git a/Documentation/devicetree/bindings/platform/msm/ipa.txt b/Documentation/devicetree/bindings/platform/msm/ipa.txt index 80f2d8f43e35..ed784f7f58a5 100644 --- a/Documentation/devicetree/bindings/platform/msm/ipa.txt +++ b/Documentation/devicetree/bindings/platform/msm/ipa.txt @@ -81,6 +81,8 @@ memory allocation over a PCIe bridge - qcom,ipa-polling-iteration: IPA Polling Iteration Count,default is 40. - qcom,ipa-tz-unlock-reg: Register start addresses and ranges which need to be unlocked by TZ. +- qcom,ipa-uc-monitor-holb: Boolean context flag to indicate whether + monitoring of holb via IPA uc is required. IPA pipe sub nodes (A2 static pipes configurations): diff --git a/arch/arm/boot/dts/qcom/msm-arm-smmu-8998.dtsi b/arch/arm/boot/dts/qcom/msm-arm-smmu-8998.dtsi index 0ba86e81887f..ecfff13f9355 100644 --- a/arch/arm/boot/dts/qcom/msm-arm-smmu-8998.dtsi +++ b/arch/arm/boot/dts/qcom/msm-arm-smmu-8998.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -29,9 +29,14 @@ <GIC_SPI 367 IRQ_TYPE_EDGE_RISING>, <GIC_SPI 368 IRQ_TYPE_EDGE_RISING>, <GIC_SPI 369 IRQ_TYPE_EDGE_RISING>; - clocks = <&clock_gcc clk_aggre1_noc_clk>; - clock-names = "smmu_aggre1_noc_clk"; - #clock-cells = <1>; + qcom,msm-bus,name = "smmu-bus-client-anoc1"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,active-only; + qcom,msm-bus,num-paths = <1>; + /* aggre1_noc_clk */ + qcom,msm-bus,vectors-KBps = + <84 10062 0 0>, + <84 10062 0 1000>; }; anoc2_smmu: arm,smmu-anoc2@16c0000 { @@ -52,9 +57,14 @@ <GIC_SPI 463 IRQ_TYPE_EDGE_RISING>, <GIC_SPI 464 IRQ_TYPE_EDGE_RISING>, <GIC_SPI 465 IRQ_TYPE_EDGE_RISING>; - clocks = <&clock_gcc clk_aggre2_noc_clk>; - clock-names = "smmu_aggre2_noc_clk"; - #clock-cells = <1>; + qcom,msm-bus,name = "smmu-bus-client-anoc2"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,active-only; + qcom,msm-bus,num-paths = <1>; + /* aggre2_noc_clk */ + qcom,msm-bus,vectors-KBps = + <117 10065 0 0>, + <117 10065 0 1000>; }; lpass_q6_smmu: arm,smmu-lpass_q6@5100000 { @@ -116,15 +126,20 @@ <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>; vdd-supply = <&gdsc_bimc_smmu>; clocks = <&clock_mmss clk_mmss_mnoc_ahb_clk>, - <&clock_gcc clk_mmssnoc_axi_clk>, <&clock_mmss clk_mmss_bimc_smmu_ahb_clk>, <&clock_mmss clk_mmss_bimc_smmu_axi_clk>; clock-names = "mmss_mnoc_ahb_clk", - "mmssnoc_axi_clk", "mmss_bimc_smmu_ahb_clk", "mmss_bimc_smmu_axi_clk"; #clock-cells = <1>; - qcom,bus-master-id = <MSM_BUS_MNOC_BIMC_MAS>; + qcom,msm-bus,name = "smmu-bus-client-mmss"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,active-only; + qcom,msm-bus,num-paths = <2>; + /* ahb_clk_src, mmssnoc_axi_clk */ + qcom,msm-bus,vectors-KBps = + <102 722 0 0>, <29 512 0 0>, + <102 722 0 1000>, <29 512 0 1000>; }; kgsl_smmu: arm,smmu-kgsl@5040000 { diff --git a/arch/arm/boot/dts/qcom/sdm660-cdp.dtsi b/arch/arm/boot/dts/qcom/sdm660-cdp.dtsi index 729e55ec9d6c..676e970a7e73 100644 --- a/arch/arm/boot/dts/qcom/sdm660-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-cdp.dtsi @@ -109,6 +109,22 @@ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; }; +&dsi_dual_nt35597_video { + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; +}; + +&dsi_dual_nt35597_cmd { + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; + qcom,partial-update-enabled = "single_roi"; + qcom,panel-roi-alignment = <720 128 720 128 1440 128>; +}; + &sdhc_1 { /* device core power supply */ vdd-supply = <&pm660l_l4>; diff --git a/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi b/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi index f4290d1aef0b..a25343981ace 100644 --- a/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi @@ -18,6 +18,8 @@ #include "dsi-panel-sharp-dualmipi-wqxga-video.dtsi" #include "dsi-panel-nt35597-truly-dsc-wqxga-video.dtsi" #include "dsi-panel-nt35597-truly-dsc-wqxga-cmd.dtsi" +#include "dsi-panel-nt35597-dualmipi-wqxga-video.dtsi" +#include "dsi-panel-nt35597-dualmipi-wqxga-cmd.dtsi" &soc { dsi_panel_pwr_supply: dsi_panel_pwr_supply { @@ -121,3 +123,19 @@ 20 12 05 06 03 13 04 a0]; qcom,config-select = <&dsi_nt35597_truly_dsc_cmd_config2>; }; + +&dsi_dual_nt35597_video { + qcom,mdss-dsi-panel-timings-phy-v2 = [23 1e 07 08 05 03 04 a0 + 23 1e 07 08 05 03 04 a0 + 23 1e 07 08 05 03 04 a0 + 23 1e 07 08 05 03 04 a0 + 23 18 07 08 04 03 04 a0]; +}; + +&dsi_dual_nt35597_cmd { + qcom,mdss-dsi-panel-timings-phy-v2 = [23 1e 07 08 05 03 04 a0 + 23 1e 07 08 05 03 04 a0 + 23 1e 07 08 05 03 04 a0 + 23 1e 07 08 05 03 04 a0 + 23 18 07 08 04 03 04 a0]; +}; diff --git a/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi b/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi index ec14815a4be6..1e7f5ea6efc5 100644 --- a/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -245,6 +245,9 @@ mdss_fb0: qcom,mdss_fb_primary { cell-index = <0>; compatible = "qcom,mdss-fb"; + qcom,cont-splash-memory { + linux,contiguous-region = <&cont_splash_mem>; + }; }; mdss_fb1: qcom,mdss_fb_wfd { @@ -367,6 +370,7 @@ "byte_clk_rcg", "pixel_clk_rcg", "byte_intf_clk"; + qcom,null-insertion-enabled; qcom,platform-strength-ctrl = [ff 06 ff 06 ff 06 @@ -407,6 +411,7 @@ "byte_clk_rcg", "pixel_clk_rcg", "byte_intf_clk"; + qcom,null-insertion-enabled; qcom,platform-strength-ctrl = [ff 06 ff 06 ff 06 diff --git a/arch/arm/boot/dts/qcom/sdm660.dtsi b/arch/arm/boot/dts/qcom/sdm660.dtsi index 612ced1087dc..26e08666cbec 100644 --- a/arch/arm/boot/dts/qcom/sdm660.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660.dtsi @@ -343,6 +343,11 @@ size = <0 0x2000000>; linux,cma-default; }; + + cont_splash_mem: splash_region@9d400000 { + reg = <0x0 0x9d400000 0x0 0x02400000>; + label = "cont_splash_mem"; + }; }; bluetooth: bt_wcn3990 { @@ -436,7 +441,6 @@ interrupt-controller; #interrupt-cells = <4>; cell-index = <0>; - qcom,not-wakeup; /* Needed until Full-boot-chain enabled */ status = "ok"; }; diff --git a/arch/arm/configs/sdm660-perf_defconfig b/arch/arm/configs/sdm660-perf_defconfig index a2584f6831e2..724cbc77d1a0 100644 --- a/arch/arm/configs/sdm660-perf_defconfig +++ b/arch/arm/configs/sdm660-perf_defconfig @@ -582,8 +582,6 @@ CONFIG_PRINTK_TIME=y CONFIG_DEBUG_INFO=y CONFIG_MAGIC_SYSRQ=y CONFIG_PAGE_EXTENSION=y -CONFIG_LOCKUP_DETECTOR=y -CONFIG_WQ_WATCHDOG=y CONFIG_PANIC_TIMEOUT=5 # CONFIG_SCHED_DEBUG is not set CONFIG_PANIC_ON_SCHED_BUG=y diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 8e3bff9c7fe9..ebbe31fee7ae 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -607,7 +607,7 @@ source "drivers/char/xillybus/Kconfig" config MSM_ADSPRPC tristate "QTI ADSP RPC driver" - depends on MSM_SMD + depends on MSM_GLINK help Provides a communication mechanism that allows for clients to make remote method invocations across processor boundary to diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 03429b18825b..95dca75efde9 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -25,7 +25,6 @@ #include <linux/hash.h> #include <linux/msm_ion.h> #include <soc/qcom/secure_buffer.h> -#include <soc/qcom/smd.h> #include <soc/qcom/glink.h> #include <soc/qcom/subsystem_notif.h> #include <soc/qcom/subsystem_restart.h> @@ -48,6 +47,7 @@ #include "adsprpc_compat.h" #include "adsprpc_shared.h" #include <soc/qcom/ramdump.h> +#include <linux/debugfs.h> #define TZ_PIL_PROTECT_MEM_SUBSYS_ID 0x0C #define TZ_PIL_CLEAR_PROTECT_MEM_SUBSYS_ID 0x0D @@ -55,6 +55,7 @@ #define ADSP_MMAP_HEAP_ADDR 4 #define FASTRPC_ENOSUCH 39 #define VMID_SSC_Q6 5 +#define DEBUGFS_SIZE 1024 #define RPC_TIMEOUT (5 * HZ) #define BALIGN 128 @@ -90,6 +91,8 @@ static int fastrpc_glink_open(int cid); static void fastrpc_glink_close(void *chan, int cid); +static struct dentry *debugfs_root; +static struct dentry *debugfs_global_file; static inline uint64_t buf_page_start(uint64_t buf) { @@ -207,7 +210,6 @@ struct fastrpc_channel_ctx { struct completion work; struct notifier_block nb; struct kref kref; - int channel; int sesscount; int ssrcount; void *handle; @@ -231,7 +233,6 @@ struct fastrpc_apps { spinlock_t hlock; struct ion_client *client; struct device *dev; - bool glink; }; struct fastrpc_mmap { @@ -283,6 +284,7 @@ struct fastrpc_file { int pd; struct fastrpc_apps *apps; struct fastrpc_perf perf; + struct dentry *debugfs_file; }; static struct fastrpc_apps gfa; @@ -291,21 +293,18 @@ static struct fastrpc_channel_ctx gcinfo[NUM_CHANNELS] = { { .name = "adsprpc-smd", .subsys = "adsp", - .channel = SMD_APPS_QDSP, .link.link_info.edge = "lpass", .link.link_info.transport = "smem", }, { .name = "mdsprpc-smd", .subsys = "modem", - .channel = SMD_APPS_MODEM, .link.link_info.edge = "mpss", .link.link_info.transport = "smem", }, { .name = "sdsprpc-smd", .subsys = "slpi", - .channel = SMD_APPS_DSPS, .link.link_info.edge = "dsps", .link.link_info.transport = "smem", .vmid = VMID_SSC_Q6, @@ -1348,7 +1347,7 @@ static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx, struct smq_msg *msg = &ctx->msg; struct fastrpc_file *fl = ctx->fl; struct fastrpc_channel_ctx *channel_ctx = &fl->apps->channel[fl->cid]; - int err = 0, len; + int err = 0; VERIFY(err, 0 != channel_ctx->chan); if (err) @@ -1363,64 +1362,21 @@ static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx, msg->invoke.page.addr = ctx->buf ? ctx->buf->phys : 0; msg->invoke.page.size = buf_page_size(ctx->used); - if (fl->apps->glink) { - if (fl->ssrcount != channel_ctx->ssrcount) { - err = -ECONNRESET; - goto bail; - } - VERIFY(err, channel_ctx->link.port_state == - FASTRPC_LINK_CONNECTED); - if (err) - goto bail; - err = glink_tx(channel_ctx->chan, - (void *)&fl->apps->channel[fl->cid], msg, sizeof(*msg), - GLINK_TX_REQ_INTENT); - } else { - spin_lock(&fl->apps->hlock); - len = smd_write((smd_channel_t *) - channel_ctx->chan, - msg, sizeof(*msg)); - spin_unlock(&fl->apps->hlock); - VERIFY(err, len == sizeof(*msg)); + if (fl->ssrcount != channel_ctx->ssrcount) { + err = -ECONNRESET; + goto bail; } + VERIFY(err, channel_ctx->link.port_state == + FASTRPC_LINK_CONNECTED); + if (err) + goto bail; + err = glink_tx(channel_ctx->chan, + (void *)&fl->apps->channel[fl->cid], msg, sizeof(*msg), + GLINK_TX_REQ_INTENT); bail: return err; } -static void fastrpc_smd_read_handler(int cid) -{ - struct fastrpc_apps *me = &gfa; - struct smq_invoke_rsp rsp = {0}; - int ret = 0; - - do { - ret = smd_read_from_cb(me->channel[cid].chan, &rsp, - sizeof(rsp)); - if (ret != sizeof(rsp)) - break; - rsp.ctx = rsp.ctx & ~1; - context_notify_user(uint64_to_ptr(rsp.ctx), rsp.retval); - } while (ret == sizeof(rsp)); -} - -static void smd_event_handler(void *priv, unsigned event) -{ - struct fastrpc_apps *me = &gfa; - int cid = (int)(uintptr_t)priv; - - switch (event) { - case SMD_EVENT_OPEN: - complete(&me->channel[cid].work); - break; - case SMD_EVENT_CLOSE: - fastrpc_notify_drivers(me, cid); - break; - case SMD_EVENT_DATA: - fastrpc_smd_read_handler(cid); - break; - } -} - static void fastrpc_init(struct fastrpc_apps *me) { int i; @@ -1883,11 +1839,7 @@ static void fastrpc_channel_close(struct kref *kref) ctx = container_of(kref, struct fastrpc_channel_ctx, kref); cid = ctx - &gcinfo[0]; - if (!me->glink) { - smd_close(ctx->chan); - } else { - fastrpc_glink_close(ctx->chan, cid); - } + fastrpc_glink_close(ctx->chan, cid); ctx->chan = 0; mutex_unlock(&me->smd_mutex); pr_info("'closed /dev/%s c %d %d'\n", gcinfo[cid].name, @@ -2042,6 +1994,8 @@ static int fastrpc_device_release(struct inode *inode, struct file *file) struct fastrpc_file *fl = (struct fastrpc_file *)file->private_data; if (fl) { + if (fl->debugfs_file != NULL) + debugfs_remove(fl->debugfs_file); fastrpc_file_free(fl); file->private_data = 0; } @@ -2158,9 +2112,124 @@ bail: return err; } +static int fastrpc_debugfs_open(struct inode *inode, struct file *filp) +{ + filp->private_data = inode->i_private; + return 0; +} + +static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer, + size_t count, loff_t *position) +{ + struct fastrpc_file *fl = filp->private_data; + struct hlist_node *n; + struct fastrpc_buf *buf = 0; + struct fastrpc_mmap *map = 0; + struct smq_invoke_ctx *ictx = 0; + struct fastrpc_channel_ctx *chan; + struct fastrpc_session_ctx *sess; + unsigned int len = 0; + int i, j, ret = 0; + char *fileinfo = NULL; + + fileinfo = kzalloc(DEBUGFS_SIZE, GFP_KERNEL); + if (!fileinfo) + goto bail; + if (fl == NULL) { + for (i = 0; i < NUM_CHANNELS; i++) { + chan = &gcinfo[i]; + len += scnprintf(fileinfo + len, + DEBUGFS_SIZE - len, "%s\n\n", + chan->name); + len += scnprintf(fileinfo + len, + DEBUGFS_SIZE - len, "%s %d\n", + "sesscount:", chan->sesscount); + for (j = 0; j < chan->sesscount; j++) { + sess = &chan->session[j]; + len += scnprintf(fileinfo + len, + DEBUGFS_SIZE - len, + "%s%d\n\n", "SESSION", j); + len += scnprintf(fileinfo + len, + DEBUGFS_SIZE - len, + "%s %d\n", "sid:", + sess->smmu.cb); + len += scnprintf(fileinfo + len, + DEBUGFS_SIZE - len, + "%s %d\n", "SECURE:", + sess->smmu.secure); + } + } + } else { + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s %d\n\n", + "PROCESS_ID:", fl->tgid); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s %d\n\n", + "CHANNEL_ID:", fl->cid); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s %d\n\n", + "SSRCOUNT:", fl->ssrcount); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s\n", + "LIST OF BUFS:"); + spin_lock(&fl->hlock); + hlist_for_each_entry_safe(buf, n, &fl->bufs, hn) { + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s %p %s %p %s %llx\n", "buf:", + buf, "buf->virt:", buf->virt, + "buf->phys:", buf->phys); + } + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "\n%s\n", + "LIST OF MAPS:"); + hlist_for_each_entry_safe(map, n, &fl->maps, hn) { + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s %p %s %lx %s %llx\n", + "map:", map, + "map->va:", map->va, + "map->phys:", map->phys); + } + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "\n%s\n", + "LIST OF PENDING SMQCONTEXTS:"); + hlist_for_each_entry_safe(ictx, n, &fl->clst.pending, hn) { + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s %p %s %u %s %u %s %u\n", + "smqcontext:", ictx, + "sc:", ictx->sc, + "tid:", ictx->pid, + "handle", ictx->rpra->h); + } + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "\n%s\n", + "LIST OF INTERRUPTED SMQCONTEXTS:"); + hlist_for_each_entry_safe(ictx, n, &fl->clst.interrupted, hn) { + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s %p %s %u %s %u %s %u\n", + "smqcontext:", ictx, + "sc:", ictx->sc, + "tid:", ictx->pid, + "handle", ictx->rpra->h); + } + spin_unlock(&fl->hlock); + } + if (len > DEBUGFS_SIZE) + len = DEBUGFS_SIZE; + ret = simple_read_from_buffer(buffer, count, position, fileinfo, len); + kfree(fileinfo); +bail: + return ret; +} + +static const struct file_operations debugfs_fops = { + .open = fastrpc_debugfs_open, + .read = fastrpc_debugfs_read, +}; + static int fastrpc_device_open(struct inode *inode, struct file *filp) { int cid = MINOR(inode->i_rdev); + struct dentry *debugfs_file; int err = 0; struct fastrpc_apps *me = &gfa; struct fastrpc_file *fl = 0; @@ -2173,6 +2242,8 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) mutex_lock(&me->smd_mutex); + debugfs_file = debugfs_create_file(current->comm, 0644, debugfs_root, + fl, &debugfs_fops); context_list_ctor(&fl->clst); spin_lock_init(&fl->hlock); INIT_HLIST_HEAD(&fl->maps); @@ -2181,6 +2252,8 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) fl->tgid = current->tgid; fl->apps = me; fl->cid = cid; + if (debugfs_file != NULL) + fl->debugfs_file = debugfs_file; memset(&fl->perf, 0, sizeof(fl->perf)); VERIFY(err, !fastrpc_session_alloc_locked(&me->channel[cid], 0, @@ -2191,16 +2264,8 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) fl->ssrcount = me->channel[cid].ssrcount; if ((kref_get_unless_zero(&me->channel[cid].kref) == 0) || (me->channel[cid].chan == 0)) { - if (me->glink) { - fastrpc_glink_register(cid, me); - VERIFY(err, 0 == fastrpc_glink_open(cid)); - } else { - VERIFY(err, !smd_named_open_on_edge(FASTRPC_SMD_GUID, - gcinfo[cid].channel, - (smd_channel_t **)&me->channel[cid].chan, - (void *)(uintptr_t)cid, - smd_event_handler)); - } + fastrpc_glink_register(cid, me); + VERIFY(err, 0 == fastrpc_glink_open(cid)); if (err) goto bail; @@ -2387,11 +2452,7 @@ static int fastrpc_restart_notifier_cb(struct notifier_block *nb, mutex_lock(&me->smd_mutex); ctx->ssrcount++; if (ctx->chan) { - if (me->glink) { - fastrpc_glink_close(ctx->chan, cid); - } else { - smd_close(ctx->chan); - } + fastrpc_glink_close(ctx->chan, cid); ctx->chan = 0; pr_info("'restart notifier: closed /dev/%s c %d %d'\n", gcinfo[cid].name, MAJOR(me->dev_no), cid); @@ -2496,6 +2557,8 @@ static int fastrpc_cb_probe(struct device *dev) sess->dev = dev; sess->smmu.enabled = 1; chan->sesscount++; + debugfs_global_file = debugfs_create_file("global", 0644, debugfs_root, + NULL, &debugfs_fops); bail: return err; } @@ -2610,8 +2673,6 @@ static int fastrpc_probe(struct platform_device *pdev) return 0; } - me->glink = of_property_read_bool(dev->of_node, "qcom,fastrpc-glink"); - VERIFY(err, !of_platform_populate(pdev->dev.of_node, fastrpc_match_table, NULL, &pdev->dev)); @@ -2706,6 +2767,7 @@ static int __init fastrpc_device_init(void) VERIFY(err, !IS_ERR_OR_NULL(me->client)); if (err) goto device_create_bail; + debugfs_root = debugfs_create_dir("adsprpc", NULL); return 0; device_create_bail: for (i = 0; i < NUM_CHANNELS; i++) { @@ -2744,6 +2806,7 @@ static void __exit fastrpc_device_exit(void) cdev_del(&me->cdev); unregister_chrdev_region(me->dev_no, NUM_CHANNELS); ion_client_destroy(me->client); + debugfs_remove_recursive(debugfs_root); } late_initcall(fastrpc_device_init); diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h index 409d2724042c..9d235b7abc58 100644 --- a/drivers/char/diag/diagchar.h +++ b/drivers/char/diag/diagchar.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -514,7 +514,7 @@ struct diagchar_dev { struct list_head cmd_reg_list; struct mutex cmd_reg_mutex; uint32_t cmd_reg_count; - struct mutex diagfwd_channel_mutex; + struct mutex diagfwd_channel_mutex[NUM_PERIPHERALS]; /* Sizes that reflect memory pool sizes */ unsigned int poolsize; unsigned int poolsize_hdlc; diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c index f8b08527d633..facdb0f40e44 100644 --- a/drivers/char/diag/diagchar_core.c +++ b/drivers/char/diag/diagchar_core.c @@ -3371,7 +3371,7 @@ static int diagchar_cleanup(void) static int __init diagchar_init(void) { dev_t dev; - int error, ret; + int error, ret, i; pr_debug("diagfwd initializing ..\n"); ret = 0; @@ -3418,7 +3418,8 @@ static int __init diagchar_init(void) mutex_init(&driver->diag_file_mutex); mutex_init(&driver->delayed_rsp_mutex); mutex_init(&apps_data_mutex); - mutex_init(&driver->diagfwd_channel_mutex); + for (i = 0; i < NUM_PERIPHERALS; i++) + mutex_init(&driver->diagfwd_channel_mutex[i]); init_waitqueue_head(&driver->wait_q); INIT_WORK(&(driver->diag_drain_work), diag_drain_work_fn); INIT_WORK(&(driver->update_user_clients), diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c index c1f954cdb080..3f9f7a999fdf 100644 --- a/drivers/char/diag/diagfwd_peripheral.c +++ b/drivers/char/diag/diagfwd_peripheral.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -655,7 +655,7 @@ void diagfwd_close_transport(uint8_t transport, uint8_t peripheral) return; } - mutex_lock(&driver->diagfwd_channel_mutex); + mutex_lock(&driver->diagfwd_channel_mutex[peripheral]); fwd_info = &early_init_info[transport][peripheral]; if (fwd_info->p_ops && fwd_info->p_ops->close) fwd_info->p_ops->close(fwd_info->ctxt); @@ -679,7 +679,7 @@ void diagfwd_close_transport(uint8_t transport, uint8_t peripheral) diagfwd_late_open(dest_info); diagfwd_cntl_open(dest_info); init_fn(peripheral); - mutex_unlock(&driver->diagfwd_channel_mutex); + mutex_unlock(&driver->diagfwd_channel_mutex[peripheral]); diagfwd_queue_read(&peripheral_info[TYPE_DATA][peripheral]); diagfwd_queue_read(&peripheral_info[TYPE_CMD][peripheral]); } diff --git a/drivers/char/diag/diagfwd_socket.c b/drivers/char/diag/diagfwd_socket.c index 888949816dfe..22a60cdff7e7 100644 --- a/drivers/char/diag/diagfwd_socket.c +++ b/drivers/char/diag/diagfwd_socket.c @@ -1088,9 +1088,9 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len) (info->data_ready > 0) || (!info->hdl) || (atomic_read(&info->diag_state) == 0)); if (err) { - mutex_lock(&driver->diagfwd_channel_mutex); + mutex_lock(&driver->diagfwd_channel_mutex[info->peripheral]); diagfwd_channel_read_done(info->fwd_ctxt, buf, 0); - mutex_unlock(&driver->diagfwd_channel_mutex); + mutex_unlock(&driver->diagfwd_channel_mutex[info->peripheral]); return -ERESTARTSYS; } @@ -1102,9 +1102,9 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len) DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "%s closing read thread. diag state is closed\n", info->name); - mutex_lock(&driver->diagfwd_channel_mutex); + mutex_lock(&driver->diagfwd_channel_mutex[info->peripheral]); diagfwd_channel_read_done(info->fwd_ctxt, buf, 0); - mutex_unlock(&driver->diagfwd_channel_mutex); + mutex_unlock(&driver->diagfwd_channel_mutex[info->peripheral]); return 0; } @@ -1171,10 +1171,10 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len) if (total_recd > 0) { DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "%s read total bytes: %d\n", info->name, total_recd); - mutex_lock(&driver->diagfwd_channel_mutex); + mutex_lock(&driver->diagfwd_channel_mutex[info->peripheral]); err = diagfwd_channel_read_done(info->fwd_ctxt, buf, total_recd); - mutex_unlock(&driver->diagfwd_channel_mutex); + mutex_unlock(&driver->diagfwd_channel_mutex[info->peripheral]); if (err) goto fail; } else { @@ -1187,9 +1187,9 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len) return 0; fail: - mutex_lock(&driver->diagfwd_channel_mutex); + mutex_lock(&driver->diagfwd_channel_mutex[info->peripheral]); diagfwd_channel_read_done(info->fwd_ctxt, buf, 0); - mutex_unlock(&driver->diagfwd_channel_mutex); + mutex_unlock(&driver->diagfwd_channel_mutex[info->peripheral]); return -EIO; } diff --git a/drivers/gpu/msm/adreno_a5xx_snapshot.c b/drivers/gpu/msm/adreno_a5xx_snapshot.c index bd93ded07131..bc7c0badf189 100644 --- a/drivers/gpu/msm/adreno_a5xx_snapshot.c +++ b/drivers/gpu/msm/adreno_a5xx_snapshot.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -943,11 +943,13 @@ void a5xx_snapshot(struct adreno_device *adreno_dev, a5xx_snapshot_debugbus(device, snapshot); /* Preemption record */ - FOR_EACH_RINGBUFFER(adreno_dev, rb, i) { - kgsl_snapshot_add_section(device, - KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2, - snapshot, snapshot_preemption_record, - &rb->preemption_desc); + if (adreno_is_preemption_enabled(adreno_dev)) { + FOR_EACH_RINGBUFFER(adreno_dev, rb, i) { + kgsl_snapshot_add_section(device, + KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2, + snapshot, snapshot_preemption_record, + &rb->preemption_desc); + } } } diff --git a/drivers/gpu/msm/kgsl_pool.c b/drivers/gpu/msm/kgsl_pool.c index bd1e432d8c7d..bb92b8b79d93 100644 --- a/drivers/gpu/msm/kgsl_pool.c +++ b/drivers/gpu/msm/kgsl_pool.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -299,6 +299,7 @@ int kgsl_pool_alloc_page(int *page_size, struct page **pages, struct page *p = NULL; int order = get_order(*page_size); int pool_idx; + size_t size = 0; if ((pages == NULL) || pages_len < (*page_size >> PAGE_SHIFT)) return -EINVAL; @@ -311,11 +312,8 @@ int kgsl_pool_alloc_page(int *page_size, struct page **pages, if (page == NULL) { /* Retry with lower order pages */ if (order > 0) { - size_t size = PAGE_SIZE << --order; - *page_size = kgsl_get_page_size(size, - ilog2(size)); - *align = ilog2(*page_size); - return -EAGAIN; + size = PAGE_SIZE << --order; + goto eagain; } else return -ENOMEM; @@ -325,8 +323,25 @@ int kgsl_pool_alloc_page(int *page_size, struct page **pages, } pool = _kgsl_get_pool_from_order(order); - if (pool == NULL) - return -EINVAL; + if (pool == NULL) { + /* Retry with lower order pages */ + if (order > 0) { + size = PAGE_SIZE << --order; + goto eagain; + } else { + /* + * Fall back to direct allocation in case + * pool with zero order is not present + */ + gfp_t gfp_mask = kgsl_gfp_mask(order); + + page = alloc_pages(gfp_mask, order); + if (page == NULL) + return -ENOMEM; + _kgsl_pool_zero_page(page, order); + goto done; + } + } pool_idx = kgsl_pool_idx_lookup(order); page = _kgsl_pool_get_page(pool); @@ -337,10 +352,9 @@ int kgsl_pool_alloc_page(int *page_size, struct page **pages, /* Only allocate non-reserved memory for certain pools */ if (!pool->allocation_allowed && pool_idx > 0) { - *page_size = PAGE_SIZE << + size = PAGE_SIZE << kgsl_pools[pool_idx-1].pool_order; - *align = ilog2(*page_size); - return -EAGAIN; + goto eagain; } page = alloc_pages(gfp_mask, order); @@ -348,10 +362,9 @@ int kgsl_pool_alloc_page(int *page_size, struct page **pages, if (!page) { if (pool_idx > 0) { /* Retry with lower order pages */ - *page_size = PAGE_SIZE << + size = PAGE_SIZE << kgsl_pools[pool_idx-1].pool_order; - *align = ilog2(*page_size); - return -EAGAIN; + goto eagain; } else return -ENOMEM; } @@ -367,6 +380,12 @@ done: } return pcount; + +eagain: + *page_size = kgsl_get_page_size(size, + ilog2(size)); + *align = ilog2(*page_size); + return -EAGAIN; } void kgsl_pool_free_page(struct page *page) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index fbe2302c4037..ce15e150277e 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -410,8 +410,8 @@ struct arm_smmu_device { struct mutex power_lock; unsigned int power_count; - struct msm_bus_client_handle *bus_client; - char *bus_client_name; + u32 bus_client; + struct msm_bus_scale_pdata *bus_pdata; enum tz_smmu_device_id sec_id; }; @@ -912,14 +912,14 @@ static int arm_smmu_request_bus(struct arm_smmu_device *smmu) { if (!smmu->bus_client) return 0; - return msm_bus_scale_update_bw(smmu->bus_client, 0, 1000); + return msm_bus_scale_client_update_request(smmu->bus_client, 1); } static int arm_smmu_unrequest_bus(struct arm_smmu_device *smmu) { if (!smmu->bus_client) return 0; - return msm_bus_scale_update_bw(smmu->bus_client, 0, 0); + return msm_bus_scale_client_update_request(smmu->bus_client, 0); } static int arm_smmu_disable_regulators(struct arm_smmu_device *smmu) @@ -3571,34 +3571,37 @@ static int arm_smmu_init_clocks(struct arm_smmu_device *smmu) static int arm_smmu_init_bus_scaling(struct platform_device *pdev, struct arm_smmu_device *smmu) { - u32 master_id; - - if (of_property_read_u32(pdev->dev.of_node, "qcom,bus-master-id", - &master_id)) { - dev_dbg(smmu->dev, "No bus scaling info\n"); + if (!of_find_property(pdev->dev.of_node, "qcom,msm-bus,name", NULL)) { + dev_dbg(&pdev->dev, "No bus scaling info\n"); return 0; } - smmu->bus_client_name = devm_kasprintf( - smmu->dev, GFP_KERNEL, "smmu-bus-client-%s", - dev_name(smmu->dev)); - - if (!smmu->bus_client_name) - return -ENOMEM; - - smmu->bus_client = msm_bus_scale_register( - master_id, MSM_BUS_SLAVE_EBI_CH0, smmu->bus_client_name, true); - if (IS_ERR(&smmu->bus_client)) { - int ret = PTR_ERR(smmu->bus_client); + smmu->bus_pdata = msm_bus_cl_get_pdata(pdev); + if (!smmu->bus_pdata) { + dev_err(&pdev->dev, "Unable to read bus-scaling from DT\n"); + return -EINVAL; + } - if (ret != -EPROBE_DEFER) - dev_err(smmu->dev, "Bus client registration failed\n"); - return ret; + smmu->bus_client = msm_bus_scale_register_client(smmu->bus_pdata); + if (!smmu->bus_client) { + dev_err(&pdev->dev, "Bus client registration failed\n"); + return -EINVAL; } return 0; } +static void arm_smmu_exit_bus_scaling(struct arm_smmu_device *smmu) +{ + if (smmu->bus_client) + msm_bus_scale_unregister_client(smmu->bus_client); + if (smmu->bus_pdata) + msm_bus_cl_clear_pdata(smmu->bus_pdata); + + smmu->bus_client = 0; + smmu->bus_pdata = NULL; +} + static int arm_smmu_parse_impl_def_registers(struct arm_smmu_device *smmu) { struct device *dev = smmu->dev; @@ -4035,6 +4038,7 @@ out_free_irqs: free_irq(smmu->irqs[i], smmu); out_put_masters: + arm_smmu_exit_bus_scaling(smmu); for (node = rb_first(&smmu->masters); node; node = rb_next(node)) { struct arm_smmu_master *master = container_of(node, struct arm_smmu_master, node); @@ -4086,7 +4090,7 @@ static int arm_smmu_device_remove(struct platform_device *pdev) arm_smmu_power_off(smmu); mutex_unlock(&smmu->attach_lock); - msm_bus_scale_unregister(smmu->bus_client); + arm_smmu_exit_bus_scaling(smmu); return 0; } diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index e7205546fa6b..080a26d744ee 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -16,7 +16,6 @@ */ #include "hif.h" -#include "pci.h" #include "ce.h" #include "debug.h" @@ -63,56 +62,56 @@ static inline void ath10k_ce_dest_ring_write_index_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - ath10k_pci_write32(ar, ce_ctrl_addr + DST_WR_INDEX_ADDRESS, n); + ar->bus_write32(ar, ce_ctrl_addr + DST_WR_INDEX_ADDRESS, n); } static inline u32 ath10k_ce_dest_ring_write_index_get(struct ath10k *ar, u32 ce_ctrl_addr) { - return ath10k_pci_read32(ar, ce_ctrl_addr + DST_WR_INDEX_ADDRESS); + return ar->bus_read32(ar, ce_ctrl_addr + DST_WR_INDEX_ADDRESS); } static inline void ath10k_ce_src_ring_write_index_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - ath10k_pci_write32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS, n); + ar->bus_write32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS, n); } static inline u32 ath10k_ce_src_ring_write_index_get(struct ath10k *ar, u32 ce_ctrl_addr) { - return ath10k_pci_read32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS); + return ar->bus_read32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS); } static inline u32 ath10k_ce_src_ring_read_index_get(struct ath10k *ar, u32 ce_ctrl_addr) { - return ath10k_pci_read32(ar, ce_ctrl_addr + CURRENT_SRRI_ADDRESS); + return ar->bus_read32(ar, ce_ctrl_addr + CURRENT_SRRI_ADDRESS); } static inline void ath10k_ce_src_ring_base_addr_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int addr) { - ath10k_pci_write32(ar, ce_ctrl_addr + SR_BA_ADDRESS, addr); + ar->bus_write32(ar, ce_ctrl_addr + SR_BA_ADDRESS, addr); } static inline void ath10k_ce_src_ring_size_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - ath10k_pci_write32(ar, ce_ctrl_addr + SR_SIZE_ADDRESS, n); + ar->bus_write32(ar, ce_ctrl_addr + SR_SIZE_ADDRESS, n); } static inline void ath10k_ce_src_ring_dmax_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - u32 ctrl1_addr = ath10k_pci_read32((ar), + u32 ctrl1_addr = ar->bus_read32((ar), (ce_ctrl_addr) + CE_CTRL1_ADDRESS); - ath10k_pci_write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS, + ar->bus_write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS, (ctrl1_addr & ~CE_CTRL1_DMAX_LENGTH_MASK) | CE_CTRL1_DMAX_LENGTH_SET(n)); } @@ -121,9 +120,9 @@ static inline void ath10k_ce_src_ring_byte_swap_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - u32 ctrl1_addr = ath10k_pci_read32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS); + u32 ctrl1_addr = ar->bus_read32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS); - ath10k_pci_write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS, + ar->bus_write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS, (ctrl1_addr & ~CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) | CE_CTRL1_SRC_RING_BYTE_SWAP_EN_SET(n)); } @@ -132,9 +131,9 @@ static inline void ath10k_ce_dest_ring_byte_swap_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - u32 ctrl1_addr = ath10k_pci_read32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS); + u32 ctrl1_addr = ar->bus_read32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS); - ath10k_pci_write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS, + ar->bus_write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS, (ctrl1_addr & ~CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK) | CE_CTRL1_DST_RING_BYTE_SWAP_EN_SET(n)); } @@ -142,30 +141,30 @@ static inline void ath10k_ce_dest_ring_byte_swap_set(struct ath10k *ar, static inline u32 ath10k_ce_dest_ring_read_index_get(struct ath10k *ar, u32 ce_ctrl_addr) { - return ath10k_pci_read32(ar, ce_ctrl_addr + CURRENT_DRRI_ADDRESS); + return ar->bus_read32(ar, ce_ctrl_addr + CURRENT_DRRI_ADDRESS); } static inline void ath10k_ce_dest_ring_base_addr_set(struct ath10k *ar, u32 ce_ctrl_addr, u32 addr) { - ath10k_pci_write32(ar, ce_ctrl_addr + DR_BA_ADDRESS, addr); + ar->bus_write32(ar, ce_ctrl_addr + DR_BA_ADDRESS, addr); } static inline void ath10k_ce_dest_ring_size_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - ath10k_pci_write32(ar, ce_ctrl_addr + DR_SIZE_ADDRESS, n); + ar->bus_write32(ar, ce_ctrl_addr + DR_SIZE_ADDRESS, n); } static inline void ath10k_ce_src_ring_highmark_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS); + u32 addr = ar->bus_read32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS); - ath10k_pci_write32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS, + ar->bus_write32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS, (addr & ~SRC_WATERMARK_HIGH_MASK) | SRC_WATERMARK_HIGH_SET(n)); } @@ -174,9 +173,9 @@ static inline void ath10k_ce_src_ring_lowmark_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS); + u32 addr = ar->bus_read32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS); - ath10k_pci_write32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS, + ar->bus_write32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS, (addr & ~SRC_WATERMARK_LOW_MASK) | SRC_WATERMARK_LOW_SET(n)); } @@ -185,9 +184,9 @@ static inline void ath10k_ce_dest_ring_highmark_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS); + u32 addr = ar->bus_read32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS); - ath10k_pci_write32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS, + ar->bus_write32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS, (addr & ~DST_WATERMARK_HIGH_MASK) | DST_WATERMARK_HIGH_SET(n)); } @@ -196,9 +195,9 @@ static inline void ath10k_ce_dest_ring_lowmark_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS); + u32 addr = ar->bus_read32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS); - ath10k_pci_write32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS, + ar->bus_write32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS, (addr & ~DST_WATERMARK_LOW_MASK) | DST_WATERMARK_LOW_SET(n)); } @@ -206,50 +205,50 @@ static inline void ath10k_ce_dest_ring_lowmark_set(struct ath10k *ar, static inline void ath10k_ce_copy_complete_inter_enable(struct ath10k *ar, u32 ce_ctrl_addr) { - u32 host_ie_addr = ath10k_pci_read32(ar, + u32 host_ie_addr = ar->bus_read32(ar, ce_ctrl_addr + HOST_IE_ADDRESS); - ath10k_pci_write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS, + ar->bus_write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS, host_ie_addr | HOST_IE_COPY_COMPLETE_MASK); } static inline void ath10k_ce_copy_complete_intr_disable(struct ath10k *ar, u32 ce_ctrl_addr) { - u32 host_ie_addr = ath10k_pci_read32(ar, + u32 host_ie_addr = ar->bus_read32(ar, ce_ctrl_addr + HOST_IE_ADDRESS); - ath10k_pci_write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS, + ar->bus_write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS, host_ie_addr & ~HOST_IE_COPY_COMPLETE_MASK); } static inline void ath10k_ce_watermark_intr_disable(struct ath10k *ar, u32 ce_ctrl_addr) { - u32 host_ie_addr = ath10k_pci_read32(ar, + u32 host_ie_addr = ar->bus_read32(ar, ce_ctrl_addr + HOST_IE_ADDRESS); - ath10k_pci_write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS, + ar->bus_write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS, host_ie_addr & ~CE_WATERMARK_MASK); } static inline void ath10k_ce_error_intr_enable(struct ath10k *ar, u32 ce_ctrl_addr) { - u32 misc_ie_addr = ath10k_pci_read32(ar, + u32 misc_ie_addr = ar->bus_read32(ar, ce_ctrl_addr + MISC_IE_ADDRESS); - ath10k_pci_write32(ar, ce_ctrl_addr + MISC_IE_ADDRESS, + ar->bus_write32(ar, ce_ctrl_addr + MISC_IE_ADDRESS, misc_ie_addr | CE_ERROR_MASK); } static inline void ath10k_ce_error_intr_disable(struct ath10k *ar, u32 ce_ctrl_addr) { - u32 misc_ie_addr = ath10k_pci_read32(ar, + u32 misc_ie_addr = ar->bus_read32(ar, ce_ctrl_addr + MISC_IE_ADDRESS); - ath10k_pci_write32(ar, ce_ctrl_addr + MISC_IE_ADDRESS, + ar->bus_write32(ar, ce_ctrl_addr + MISC_IE_ADDRESS, misc_ie_addr & ~CE_ERROR_MASK); } @@ -257,7 +256,7 @@ static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int mask) { - ath10k_pci_write32(ar, ce_ctrl_addr + HOST_IS_ADDRESS, mask); + ar->bus_write32(ar, ce_ctrl_addr + HOST_IS_ADDRESS, mask); } /* @@ -325,11 +324,10 @@ exit: void __ath10k_ce_send_revert(struct ath10k_ce_pipe *pipe) { struct ath10k *ar = pipe->ar; - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_ce_ring *src_ring = pipe->src_ring; u32 ctrl_addr = pipe->ctrl_addr; - lockdep_assert_held(&ar_pci->ce_lock); + lockdep_assert_held(&ar->ce_lock); /* * This function must be called only if there is an incomplete @@ -357,13 +355,12 @@ int ath10k_ce_send(struct ath10k_ce_pipe *ce_state, unsigned int flags) { struct ath10k *ar = ce_state->ar; - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int ret; - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ar->ce_lock); ret = ath10k_ce_send_nolock(ce_state, per_transfer_context, buffer, nbytes, transfer_id, flags); - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ar->ce_lock); return ret; } @@ -371,14 +368,13 @@ int ath10k_ce_send(struct ath10k_ce_pipe *ce_state, int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe) { struct ath10k *ar = pipe->ar; - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int delta; - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ar->ce_lock); delta = CE_RING_DELTA(pipe->src_ring->nentries_mask, pipe->src_ring->write_index, pipe->src_ring->sw_index - 1); - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ar->ce_lock); return delta; } @@ -386,13 +382,12 @@ int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe) int __ath10k_ce_rx_num_free_bufs(struct ath10k_ce_pipe *pipe) { struct ath10k *ar = pipe->ar; - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_ce_ring *dest_ring = pipe->dest_ring; unsigned int nentries_mask = dest_ring->nentries_mask; unsigned int write_index = dest_ring->write_index; unsigned int sw_index = dest_ring->sw_index; - lockdep_assert_held(&ar_pci->ce_lock); + lockdep_assert_held(&ar->ce_lock); return CE_RING_DELTA(nentries_mask, write_index, sw_index - 1); } @@ -400,7 +395,6 @@ int __ath10k_ce_rx_num_free_bufs(struct ath10k_ce_pipe *pipe) int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr) { struct ath10k *ar = pipe->ar; - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_ce_ring *dest_ring = pipe->dest_ring; unsigned int nentries_mask = dest_ring->nentries_mask; unsigned int write_index = dest_ring->write_index; @@ -409,7 +403,7 @@ int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr) struct ce_desc *desc = CE_DEST_RING_TO_DESC(base, write_index); u32 ctrl_addr = pipe->ctrl_addr; - lockdep_assert_held(&ar_pci->ce_lock); + lockdep_assert_held(&ar->ce_lock); if ((pipe->id != 5) && CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) == 0) @@ -442,12 +436,11 @@ void ath10k_ce_rx_update_write_idx(struct ath10k_ce_pipe *pipe, u32 nentries) int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr) { struct ath10k *ar = pipe->ar; - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int ret; - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ar->ce_lock); ret = __ath10k_ce_rx_post_buf(pipe, ctx, paddr); - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ar->ce_lock); return ret; } @@ -510,14 +503,13 @@ int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state, unsigned int *nbytesp) { struct ath10k *ar = ce_state->ar; - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int ret; - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ar->ce_lock); ret = ath10k_ce_completed_recv_next_nolock(ce_state, per_transfer_contextp, nbytesp); - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ar->ce_lock); return ret; } @@ -532,7 +524,6 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state, unsigned int write_index; int ret; struct ath10k *ar; - struct ath10k_pci *ar_pci; dest_ring = ce_state->dest_ring; @@ -540,9 +531,8 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state, return -EIO; ar = ce_state->ar; - ar_pci = ath10k_pci_priv(ar); - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ar->ce_lock); nentries_mask = dest_ring->nentries_mask; sw_index = dest_ring->sw_index; @@ -570,7 +560,7 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state, ret = -EIO; } - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ar->ce_lock); return ret; } @@ -638,7 +628,6 @@ int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state, unsigned int write_index; int ret; struct ath10k *ar; - struct ath10k_pci *ar_pci; src_ring = ce_state->src_ring; @@ -646,9 +635,8 @@ int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state, return -EIO; ar = ce_state->ar; - ar_pci = ath10k_pci_priv(ar); - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ar->ce_lock); nentries_mask = src_ring->nentries_mask; sw_index = src_ring->sw_index; @@ -679,7 +667,7 @@ int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state, ret = -EIO; } - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ar->ce_lock); return ret; } @@ -688,13 +676,12 @@ int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state, void **per_transfer_contextp) { struct ath10k *ar = ce_state->ar; - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int ret; - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ar->ce_lock); ret = ath10k_ce_completed_send_next_nolock(ce_state, per_transfer_contextp); - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ar->ce_lock); return ret; } @@ -707,17 +694,17 @@ int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state, */ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id) { - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; + struct ath10k_ce_pipe *ce_state = + ((struct ath10k_ce_pipe *)ar->ce_states + ce_id); u32 ctrl_addr = ce_state->ctrl_addr; - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ar->ce_lock); /* Clear the copy-complete interrupts that will be handled here. */ ath10k_ce_engine_int_status_clear(ar, ctrl_addr, HOST_IS_COPY_COMPLETE_MASK); - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ar->ce_lock); if (ce_state->recv_cb) ce_state->recv_cb(ce_state); @@ -725,7 +712,7 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id) if (ce_state->send_cb) ce_state->send_cb(ce_state); - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ar->ce_lock); /* * Misc CE interrupts are not being handled, but still need @@ -733,7 +720,7 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id) */ ath10k_ce_engine_int_status_clear(ar, ctrl_addr, CE_WATERMARK_MASK); - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ar->ce_lock); } /* @@ -799,22 +786,22 @@ int ath10k_ce_disable_interrupts(struct ath10k *ar) void ath10k_ce_enable_interrupts(struct ath10k *ar) { - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int ce_id; /* Skip the last copy engine, CE7 the diagnostic window, as that * uses polling and isn't initialized for interrupts. */ for (ce_id = 0; ce_id < CE_COUNT - 1; ce_id++) - ath10k_ce_per_engine_handler_adjust(&ar_pci->ce_states[ce_id]); + ath10k_ce_per_engine_handler_adjust( + ((struct ath10k_ce_pipe *)ar->ce_states + ce_id)); } static int ath10k_ce_init_src_ring(struct ath10k *ar, unsigned int ce_id, const struct ce_attr *attr) { - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; + struct ath10k_ce_pipe *ce_state = + ((struct ath10k_ce_pipe *)ar->ce_states + ce_id); struct ath10k_ce_ring *src_ring = ce_state->src_ring; u32 nentries, ctrl_addr = ath10k_ce_base_address(ar, ce_id); @@ -850,8 +837,8 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar, unsigned int ce_id, const struct ce_attr *attr) { - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; + struct ath10k_ce_pipe *ce_state = + ((struct ath10k_ce_pipe *)ar->ce_states + ce_id); struct ath10k_ce_ring *dest_ring = ce_state->dest_ring; u32 nentries, ctrl_addr = ath10k_ce_base_address(ar, ce_id); @@ -1040,8 +1027,8 @@ void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id) int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, const struct ce_attr *attr) { - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; + struct ath10k_ce_pipe *ce_state = + ((struct ath10k_ce_pipe *)ar->ce_states + ce_id); int ret; /* @@ -1097,8 +1084,8 @@ int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id) { - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; + struct ath10k_ce_pipe *ce_state = + ((struct ath10k_ce_pipe *)ar->ce_states + ce_id); if (ce_state->src_ring) { dma_free_coherent(ar->dev, diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index dfc098606bee..0e1ab73b0e11 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -425,7 +425,7 @@ static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id) #define CE_INTERRUPT_SUMMARY(ar) \ CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_GET( \ - ath10k_pci_read32((ar), CE_WRAPPER_BASE_ADDRESS + \ + ar->bus_read32((ar), CE_WRAPPER_BASE_ADDRESS + \ CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS)) #endif /* _CE_H_ */ diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 521f1c55c19e..bea1a0bd865b 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -74,6 +74,7 @@ struct ath10k; enum ath10k_bus { ATH10K_BUS_PCI, ATH10K_BUS_AHB, + ATH10K_BUS_SNOC, }; static inline const char *ath10k_bus_str(enum ath10k_bus bus) @@ -83,6 +84,8 @@ static inline const char *ath10k_bus_str(enum ath10k_bus bus) return "pci"; case ATH10K_BUS_AHB: return "ahb"; + case ATH10K_BUS_SNOC: + return "snoc"; } return "unknown"; @@ -912,6 +915,10 @@ struct ath10k { struct net_device napi_dev; struct napi_struct napi; + void (*bus_write32)(void *ar, u32 offset, u32 value); + u32 (*bus_read32)(void *ar, u32 offset); + spinlock_t ce_lock; /* lock for CE access */ + void *ce_states; /* must be last */ u8 drv_priv[0] __aligned(sizeof(void *)); }; diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index c458fa96a6d4..b1db01a167ac 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h @@ -38,6 +38,7 @@ enum ath10k_debug_mask { ATH10K_DBG_WMI_PRINT = 0x00002000, ATH10K_DBG_PCI_PS = 0x00004000, ATH10K_DBG_AHB = 0x00008000, + ATH10K_DBG_SNOC = 0x00009000, ATH10K_DBG_ANY = 0xffffffff, }; diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h index b2566b06e1e1..9e79d52e18cf 100644 --- a/drivers/net/wireless/ath/ath10k/hif.h +++ b/drivers/net/wireless/ath/ath10k/hif.h @@ -74,9 +74,9 @@ struct ath10k_hif_ops { u16 (*get_free_queue_number)(struct ath10k *ar, u8 pipe_id); - u32 (*read32)(struct ath10k *ar, u32 address); + u32 (*read32)(void *ar, u32 address); - void (*write32)(struct ath10k *ar, u32 address, u32 value); + void (*write32)(void *ar, u32 address, u32 value); /* Power up the device and enter BMI transfer mode for FW download */ int (*power_up)(struct ath10k *ar); diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 6038b7486f1d..7e12291852d2 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -224,6 +224,7 @@ enum ath10k_hw_rev { ATH10K_HW_QCA9377, ATH10K_HW_QCA4019, ATH10K_HW_QCA9887, + ATH10K_HW_WCN3990, }; struct ath10k_hw_regs { diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 9fbeb7e5ab2d..0c250f8d45ce 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -669,14 +669,14 @@ static u32 ath10k_bus_pci_read32(struct ath10k *ar, u32 offset) return val; } -inline void ath10k_pci_write32(struct ath10k *ar, u32 offset, u32 value) +inline void ath10k_pci_write32(void *ar, u32 offset, u32 value) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); ar_pci->bus_ops->write32(ar, offset, value); } -inline u32 ath10k_pci_read32(struct ath10k *ar, u32 offset) +inline u32 ath10k_pci_read32(void *ar, u32 offset) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); @@ -3246,6 +3246,16 @@ static int ath10k_pci_probe(struct pci_dev *pdev, ar->id.subsystem_vendor = pdev->subsystem_vendor; ar->id.subsystem_device = pdev->subsystem_device; + spin_lock_init(&ar_pci->ce_lock); + spin_lock_init(&ar_pci->ps_lock); + + ar->bus_write32 = ath10k_pci_write32; + ar->bus_read32 = ath10k_pci_read32; + ar->ce_lock = ar_pci->ce_lock; + ar->ce_states = ar_pci->ce_states; + + setup_timer(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry, + (unsigned long)ar); setup_timer(&ar_pci->ps_timer, ath10k_pci_ps_timer, (unsigned long)ar); diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index 9854ad56b2de..06d0bd3993d3 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -263,11 +263,11 @@ static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar) /* Wait up to this many Ms for a Diagnostic Access CE operation to complete */ #define DIAG_ACCESS_CE_TIMEOUT_MS 10 -void ath10k_pci_write32(struct ath10k *ar, u32 offset, u32 value); +void ath10k_pci_write32(void *ar, u32 offset, u32 value); void ath10k_pci_soc_write32(struct ath10k *ar, u32 addr, u32 val); void ath10k_pci_reg_write32(struct ath10k *ar, u32 addr, u32 val); -u32 ath10k_pci_read32(struct ath10k *ar, u32 offset); +u32 ath10k_pci_read32(void *ar, u32 offset); u32 ath10k_pci_soc_read32(struct ath10k *ar, u32 addr); u32 ath10k_pci_reg_read32(struct ath10k *ar, u32 addr); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index a680a970b7f7..e4281438c04f 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1657,13 +1657,14 @@ static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw, static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, - u16 tid, u16 *ssn, u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { struct ath9k_htc_priv *priv = hw->priv; struct ath9k_htc_sta *ista; int ret = 0; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; mutex_lock(&priv->mutex); ath9k_htc_ps_wakeup(priv); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index d184e682e636..5cc0ddc254eb 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1860,14 +1860,16 @@ static void ath9k_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) static int ath9k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, - u16 tid, u16 *ssn, u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { struct ath_softc *sc = hw->priv; struct ath_common *common = ath9k_hw_common(sc->sc_ah); bool flush = false; int ret = 0; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; mutex_lock(&sc->mutex); diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 19d3d64416bf..4d1527a2e292 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c @@ -1413,10 +1413,12 @@ static void carl9170_ampdu_work(struct work_struct *work) static int carl9170_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, - u16 tid, u16 *ssn, u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; struct ar9170 *ar = hw->priv; struct carl9170_sta_info *sta_info = (void *) sta->drv_priv; struct carl9170_sta_tid *tid_info; diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 7c169abdbafe..a27279c2c695 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -857,12 +857,14 @@ static int wcn36xx_resume(struct ieee80211_hw *hw) static int wcn36xx_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { struct wcn36xx *wcn = hw->priv; struct wcn36xx_sta *sta_priv = NULL; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n", action, tid); diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index bec2dc1ca2e4..61ae2768132a 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -818,13 +818,15 @@ brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, static int brcms_ops_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { struct brcms_info *wl = hw->priv; struct scb *scb = &wl->wlc->pri_scb; int status; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u8 buf_size = params->buf_size; if (WARN_ON(scb->magic != SCB_MAGIC)) return -EIDRM; diff --git a/drivers/net/wireless/cw1200/sta.h b/drivers/net/wireless/cw1200/sta.h index bebb3379017f..a0bacaa39b31 100644 --- a/drivers/net/wireless/cw1200/sta.h +++ b/drivers/net/wireless/cw1200/sta.h @@ -109,9 +109,7 @@ void cw1200_bss_info_changed(struct ieee80211_hw *dev, u32 changed); int cw1200_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu); + struct ieee80211_ampdu_params *params); void cw1200_suspend_resume(struct cw1200_common *priv, struct wsm_suspend_resume *arg); diff --git a/drivers/net/wireless/iwlegacy/4965.h b/drivers/net/wireless/iwlegacy/4965.h index 8ab8706f9422..e432715e02d8 100644 --- a/drivers/net/wireless/iwlegacy/4965.h +++ b/drivers/net/wireless/iwlegacy/4965.h @@ -182,9 +182,7 @@ void il4965_mac_update_tkip_key(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u32 iv32, u16 *phase1key); int il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 * ssn, - u8 buf_size, bool amsdu); + struct ieee80211_ampdu_params *params); int il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 0cd95120bc78..d59769e858f4 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -1817,10 +1817,12 @@ static int mac80211_hwsim_testmode_cmd(struct ieee80211_hw *hw, static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + switch (action) { case IEEE80211_AMPDU_TX_START: ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); diff --git a/drivers/net/wireless/mediatek/mt7601u/main.c b/drivers/net/wireless/mediatek/mt7601u/main.c index f715eee39851..e70dd9523911 100644 --- a/drivers/net/wireless/mediatek/mt7601u/main.c +++ b/drivers/net/wireless/mediatek/mt7601u/main.c @@ -334,11 +334,13 @@ static int mt7601u_set_rts_threshold(struct ieee80211_hw *hw, u32 value) static int mt76_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size, - bool amsdu) + struct ieee80211_ampdu_params *params) { struct mt7601u_dev *dev = hw->priv; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv; WARN_ON(msta->wcid.idx > GROUP_WCID(0)); diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 30e3aaae32e2..088429d0a634 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -5421,11 +5421,13 @@ static int mwl8k_get_survey(struct ieee80211_hw *hw, int idx, static int mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { - + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; + u8 buf_size = params->buf_size; int i, rc = 0; struct mwl8k_priv *priv = hw->priv; struct mwl8k_ampdu_stream *stream; diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 6aed923a709a..7d820c395375 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -5375,13 +5375,13 @@ static int rtl8xxxu_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, static int rtl8xxxu_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size, - bool amsdu) + struct ieee80211_ampdu_params *params) { struct rtl8xxxu_priv *priv = hw->priv; struct device *dev = &priv->udev->dev; u8 ampdu_factor, ampdu_density; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; switch (action) { case IEEE80211_AMPDU_TX_START: diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c index c925a4dff599..a4527880b2b7 100644 --- a/drivers/net/wireless/realtek/rtlwifi/core.c +++ b/drivers/net/wireless/realtek/rtlwifi/core.c @@ -1371,11 +1371,13 @@ static void rtl_op_sta_notify(struct ieee80211_hw *hw, static int rtl_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { struct rtl_priv *rtlpriv = rtl_priv(hw); + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; switch (action) { case IEEE80211_AMPDU_TX_START: diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index b5bcc933a2a6..4df992de7d07 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c @@ -659,29 +659,24 @@ static int rsi_mac80211_set_key(struct ieee80211_hw *hw, * informs the f/w regarding this. * @hw: Pointer to the ieee80211_hw structure. * @vif: Pointer to the ieee80211_vif structure. - * @action: ieee80211_ampdu_mlme_action enum. - * @sta: Pointer to the ieee80211_sta structure. - * @tid: Traffic identifier. - * @ssn: Pointer to ssn value. - * @buf_size: Buffer size (for kernel version > 2.6.38). - * @amsdu: is AMSDU in AMPDU allowed + * @params: Pointer to A-MPDU action parameters * * Return: status: 0 on success, negative error code on failure. */ static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, - unsigned short tid, - unsigned short *ssn, - unsigned char buf_size, - bool amsdu) + struct ieee80211_ampdu_params *params) { int status = -EOPNOTSUPP; struct rsi_hw *adapter = hw->priv; struct rsi_common *common = adapter->priv; u16 seq_no = 0; u8 ii = 0; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; + u8 buf_size = params->buf_size; for (ii = 0; ii < RSI_MAX_VIFS; ii++) { if (vif == adapter->vifs[ii]) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 9733b31a780d..69c1c09687a3 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -7935,10 +7935,11 @@ u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) EXPORT_SYMBOL_GPL(rt2800_get_tsf); int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; struct rt2x00_sta *sta_priv = (struct rt2x00_sta *)sta->drv_priv; int ret = 0; diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 440790b92b19..83f1a44fb9b4 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h @@ -218,9 +218,7 @@ int rt2800_conf_tx(struct ieee80211_hw *hw, const struct ieee80211_tx_queue_params *params); u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif); int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu); + struct ieee80211_ampdu_params *params); int rt2800_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey); void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev); diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index ec7f6af3fab2..30165ea0fa25 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -5261,14 +5261,16 @@ out: static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { struct wl1271 *wl = hw->priv; struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret; u8 hlid, *ba_bitmap; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; wl1271_debug(DEBUG_MAC80211, "mac80211 ampdu action %d tid %d", action, tid); diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c index 09ec8458fcad..1e79fd954969 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c @@ -3774,6 +3774,8 @@ static int ipa_init(const struct ipa_plat_drv_res *resource_p, ipa_ctx->ipa_wrapper_size = resource_p->ipa_mem_size; ipa_ctx->ipa_hw_type = resource_p->ipa_hw_type; ipa_ctx->ipa_hw_mode = resource_p->ipa_hw_mode; + ipa_ctx->ipa_uc_monitor_holb = + resource_p->ipa_uc_monitor_holb; ipa_ctx->use_ipa_teth_bridge = resource_p->use_ipa_teth_bridge; ipa_ctx->ipa_bam_remote_mode = resource_p->ipa_bam_remote_mode; ipa_ctx->modem_cfg_emb_pipe_flt = resource_p->modem_cfg_emb_pipe_flt; @@ -4316,6 +4318,7 @@ static int get_ipa_dts_configuration(struct platform_device *pdev, ipa_drv_res->ipa_pipe_mem_size = IPA_PIPE_MEM_SIZE; ipa_drv_res->ipa_hw_type = 0; ipa_drv_res->ipa_hw_mode = 0; + ipa_drv_res->ipa_uc_monitor_holb = false; ipa_drv_res->ipa_bam_remote_mode = false; ipa_drv_res->modem_cfg_emb_pipe_flt = false; ipa_drv_res->ipa_wdi2 = false; @@ -4340,6 +4343,14 @@ static int get_ipa_dts_configuration(struct platform_device *pdev, IPADBG(": found ipa_drv_res->ipa_hw_mode = %d", ipa_drv_res->ipa_hw_mode); + /* Check ipa_uc_monitor_holb enabled or disabled */ + ipa_drv_res->ipa_uc_monitor_holb = + of_property_read_bool(pdev->dev.of_node, + "qcom,ipa-uc-monitor-holb"); + IPADBG(": ipa uc monitor holb = %s\n", + ipa_drv_res->ipa_uc_monitor_holb + ? "Enabled" : "Disabled"); + /* Get IPA WAN / LAN RX pool sizes */ result = of_property_read_u32(pdev->dev.of_node, "qcom,wan-rx-ring-size", diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h index 2c2a9c617b16..b45e748b66a6 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h @@ -47,7 +47,7 @@ #define IPA_QMAP_HEADER_LENGTH (4) #define IPA_DL_CHECKSUM_LENGTH (8) #define IPA_NUM_DESC_PER_SW_TX (2) -#define IPA_GENERIC_RX_POOL_SZ 1000 +#define IPA_GENERIC_RX_POOL_SZ 192 #define IPA_UC_FINISH_MAX 6 #define IPA_UC_WAIT_MIN_SLEEP 1000 #define IPA_UC_WAII_MAX_SLEEP 1200 @@ -1174,6 +1174,7 @@ struct ipa_context { u32 ipa_rx_min_timeout_usec; u32 ipa_rx_max_timeout_usec; u32 ipa_polling_iteration; + bool ipa_uc_monitor_holb; }; /** @@ -1229,6 +1230,7 @@ struct ipa_plat_drv_res { bool tethered_flow_control; u32 ipa_rx_polling_sleep_msec; u32 ipa_polling_iteration; + bool ipa_uc_monitor_holb; }; struct ipa_mem_partition { diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_uc.c b/drivers/platform/msm/ipa/ipa_v2/ipa_uc.c index 13db6b08ba9d..3dd2eb093317 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_uc.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_uc.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -768,8 +768,12 @@ int ipa_uc_monitor_holb(enum ipa_client_type ipa_client, bool enable) int ep_idx; int ret; - /* HOLB monitoring is applicable only to 2.6L. */ - if (ipa_ctx->ipa_hw_type != IPA_HW_v2_6L) { + /* + * HOLB monitoring is applicable to 2.6L. + * And also could be enabled from dtsi node. + */ + if (ipa_ctx->ipa_hw_type != IPA_HW_v2_6L || + !ipa_ctx->ipa_uc_monitor_holb) { IPADBG("Not applicable on this target\n"); return 0; } diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c index e3d20422d591..2cd8d5c975f4 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c @@ -195,7 +195,7 @@ static const int ep_mapping[3][IPA_CLIENT_MAX] = { [IPA_2_6L][IPA_CLIENT_HSIC1_PROD] = -1, - [IPA_2_6L][IPA_CLIENT_WLAN1_PROD] = -1, + [IPA_2_6L][IPA_CLIENT_WLAN1_PROD] = 18, [IPA_2_6L][IPA_CLIENT_HSIC2_PROD] = -1, [IPA_2_6L][IPA_CLIENT_USB2_PROD] = -1, [IPA_2_6L][IPA_CLIENT_HSIC3_PROD] = -1, @@ -228,16 +228,16 @@ static const int ep_mapping[3][IPA_CLIENT_MAX] = { [IPA_2_6L][IPA_CLIENT_TEST4_PROD] = 14, [IPA_2_6L][IPA_CLIENT_HSIC1_CONS] = -1, - [IPA_2_6L][IPA_CLIENT_WLAN1_CONS] = -1, + [IPA_2_6L][IPA_CLIENT_WLAN1_CONS] = 17, [IPA_2_6L][IPA_CLIENT_HSIC2_CONS] = -1, [IPA_2_6L][IPA_CLIENT_USB2_CONS] = -1, - [IPA_2_6L][IPA_CLIENT_WLAN2_CONS] = -1, + [IPA_2_6L][IPA_CLIENT_WLAN2_CONS] = 16, [IPA_2_6L][IPA_CLIENT_HSIC3_CONS] = -1, [IPA_2_6L][IPA_CLIENT_USB3_CONS] = -1, - [IPA_2_6L][IPA_CLIENT_WLAN3_CONS] = -1, + [IPA_2_6L][IPA_CLIENT_WLAN3_CONS] = 15, [IPA_2_6L][IPA_CLIENT_HSIC4_CONS] = -1, [IPA_2_6L][IPA_CLIENT_USB4_CONS] = -1, - [IPA_2_6L][IPA_CLIENT_WLAN4_CONS] = -1, + [IPA_2_6L][IPA_CLIENT_WLAN4_CONS] = 19, [IPA_2_6L][IPA_CLIENT_HSIC5_CONS] = -1, [IPA_2_6L][IPA_CLIENT_USB_CONS] = 0, [IPA_2_6L][IPA_CLIENT_USB_DPL_CONS] = 10, diff --git a/drivers/scsi/ufs/ufs-qcom-ice.c b/drivers/scsi/ufs/ufs-qcom-ice.c index 070d27df6b49..85f82b2251c1 100644 --- a/drivers/scsi/ufs/ufs-qcom-ice.c +++ b/drivers/scsi/ufs/ufs-qcom-ice.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -14,6 +14,7 @@ #include <linux/io.h> #include <linux/of.h> #include <linux/blkdev.h> +#include <linux/spinlock.h> #include <crypto/ice.h> #include "ufs-qcom-ice.h" @@ -168,6 +169,7 @@ out: static void ufs_qcom_ice_cfg_work(struct work_struct *work) { + unsigned long flags; struct ice_data_setting ice_set; struct ufs_qcom_host *qcom_host = container_of(work, struct ufs_qcom_host, ice_cfg_work); @@ -185,12 +187,17 @@ static void ufs_qcom_ice_cfg_work(struct work_struct *work) qcom_host->ice.vops->config_start(qcom_host->ice.pdev, qcom_host->req_pending, &ice_set, false); + spin_lock_irqsave(&qcom_host->ice_work_lock, flags); + qcom_host->req_pending = NULL; + spin_unlock_irqrestore(&qcom_host->ice_work_lock, flags); + /* * Resume with requests processing. We assume config_start has been * successful, but even if it wasn't we still must resume in order to * allow for the request to be retried. */ ufshcd_scsi_unblock_requests(qcom_host->hba); + } /** @@ -246,6 +253,7 @@ int ufs_qcom_ice_req_setup(struct ufs_qcom_host *qcom_host, struct ice_data_setting ice_set; char cmd_op = cmd->cmnd[0]; int err; + unsigned long flags; if (!qcom_host->ice.pdev || !qcom_host->ice.vops) { dev_dbg(qcom_host->hba->dev, "%s: ice device is not enabled\n", @@ -272,14 +280,36 @@ int ufs_qcom_ice_req_setup(struct ufs_qcom_host *qcom_host, dev_dbg(qcom_host->hba->dev, "%s: scheduling task for ice setup\n", __func__); - qcom_host->req_pending = cmd->request; - if (schedule_work(&qcom_host->ice_cfg_work)) + + spin_lock_irqsave( + &qcom_host->ice_work_lock, flags); + + if (!qcom_host->req_pending) { ufshcd_scsi_block_requests( qcom_host->hba); + qcom_host->req_pending = cmd->request; + if (!schedule_work( + &qcom_host->ice_cfg_work)) { + qcom_host->req_pending = NULL; + + spin_unlock_irqrestore( + &qcom_host->ice_work_lock, + flags); + + ufshcd_scsi_unblock_requests( + qcom_host->hba); + return err; + } + } + + spin_unlock_irqrestore( + &qcom_host->ice_work_lock, flags); + } else { - dev_err(qcom_host->hba->dev, - "%s: error in ice_vops->config %d\n", - __func__, err); + if (err != -EBUSY) + dev_err(qcom_host->hba->dev, + "%s: error in ice_vops->config %d\n", + __func__, err); } return err; @@ -320,6 +350,7 @@ int ufs_qcom_ice_cfg_start(struct ufs_qcom_host *qcom_host, unsigned int bypass = 0; struct request *req; char cmd_op; + unsigned long flags; if (!qcom_host->ice.pdev || !qcom_host->ice.vops) { dev_dbg(dev, "%s: ice device is not enabled\n", __func__); @@ -365,12 +396,43 @@ int ufs_qcom_ice_cfg_start(struct ufs_qcom_host *qcom_host, * request processing. */ if (err == -EAGAIN) { - qcom_host->req_pending = req; - if (schedule_work(&qcom_host->ice_cfg_work)) + + dev_dbg(qcom_host->hba->dev, + "%s: scheduling task for ice setup\n", + __func__); + + spin_lock_irqsave( + &qcom_host->ice_work_lock, flags); + + if (!qcom_host->req_pending) { ufshcd_scsi_block_requests( + qcom_host->hba); + qcom_host->req_pending = cmd->request; + if (!schedule_work( + &qcom_host->ice_cfg_work)) { + qcom_host->req_pending = NULL; + + spin_unlock_irqrestore( + &qcom_host->ice_work_lock, + flags); + + ufshcd_scsi_unblock_requests( qcom_host->hba); + return err; + } + } + + spin_unlock_irqrestore( + &qcom_host->ice_work_lock, flags); + + } else { + if (err != -EBUSY) + dev_err(qcom_host->hba->dev, + "%s: error in ice_vops->config %d\n", + __func__, err); } - goto out; + + return err; } } diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 2b0731b8358c..03b222d8be93 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016, Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1981,6 +1981,8 @@ static int ufs_qcom_init(struct ufs_hba *hba) /* Make a two way bind between the qcom host and the hba */ host->hba = hba; + spin_lock_init(&host->ice_work_lock); + ufshcd_set_variant(hba, host); err = ufs_qcom_ice_get_dev(host); diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h index 394de8302fd2..74d8a7a30ad6 100644 --- a/drivers/scsi/ufs/ufs-qcom.h +++ b/drivers/scsi/ufs/ufs-qcom.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -370,6 +370,7 @@ struct ufs_qcom_host { u32 dbg_print_en; struct ufs_qcom_testbus testbus; + spinlock_t ice_work_lock; struct work_struct ice_cfg_work; struct request *req_pending; }; diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 1e6db2a76fa5..d4acc3c911f5 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -48,6 +48,7 @@ #include "ufshci.h" #include "ufs_quirks.h" #include "ufs-debugfs.h" +#include "ufs-qcom.h" #define CREATE_TRACE_POINTS #include <trace/events/ufs.h> @@ -2884,11 +2885,11 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) "%s: failed to compose upiu %d\n", __func__, err); - lrbp->cmd = NULL; - clear_bit_unlock(tag, &hba->lrb_in_use); - ufshcd_release_all(hba); - ufshcd_vops_pm_qos_req_end(hba, cmd->request, true); - goto out; + lrbp->cmd = NULL; + clear_bit_unlock(tag, &hba->lrb_in_use); + ufshcd_release_all(hba); + ufshcd_vops_pm_qos_req_end(hba, cmd->request, true); + goto out; } err = ufshcd_map_sg(lrbp); diff --git a/include/net/mac80211.h b/include/net/mac80211.h index ee5270f984ba..e4a54cd23211 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -2685,6 +2685,33 @@ enum ieee80211_ampdu_mlme_action { }; /** + * struct ieee80211_ampdu_params - AMPDU action parameters + * + * @action: the ampdu action, value from %ieee80211_ampdu_mlme_action. + * @sta: peer of this AMPDU session + * @tid: tid of the BA session + * @ssn: start sequence number of the session. TX/RX_STOP can pass 0. When + * action is set to %IEEE80211_AMPDU_RX_START the driver passes back the + * actual ssn value used to start the session and writes the value here. + * @buf_size: reorder buffer size (number of subframes). Valid only when the + * action is set to %IEEE80211_AMPDU_RX_START or + * %IEEE80211_AMPDU_TX_OPERATIONAL + * @amsdu: indicates the peer's ability to receive A-MSDU within A-MPDU. + * valid when the action is set to %IEEE80211_AMPDU_TX_OPERATIONAL + * @timeout: BA session timeout. Valid only when the action is set to + * %IEEE80211_AMPDU_RX_START + */ +struct ieee80211_ampdu_params { + enum ieee80211_ampdu_mlme_action action; + struct ieee80211_sta *sta; + u16 tid; + u16 ssn; + u8 buf_size; + bool amsdu; + u16 timeout; +}; + +/** * enum ieee80211_frame_release_type - frame release reason * @IEEE80211_FRAME_RELEASE_PSPOLL: frame released for PS-Poll * @IEEE80211_FRAME_RELEASE_UAPSD: frame(s) released due to @@ -3028,13 +3055,9 @@ enum ieee80211_reconfig_type { * @ampdu_action: Perform a certain A-MPDU action * The RA/TID combination determines the destination and TID we want * the ampdu action to be performed for. The action is defined through - * ieee80211_ampdu_mlme_action. Starting sequence number (@ssn) - * is the first frame we expect to perform the action on. Notice - * that TX/RX_STOP can pass NULL for this parameter. - * The @buf_size parameter is only valid when the action is set to - * %IEEE80211_AMPDU_TX_OPERATIONAL and indicates the peer's reorder - * buffer size (number of subframes) for this session -- the driver - * may neither send aggregates containing more subframes than this + * ieee80211_ampdu_mlme_action. + * When the action is set to %IEEE80211_AMPDU_TX_OPERATIONAL the driver + * may neither send aggregates containing more subframes than @buf_size * nor send aggregates in a way that lost frames would exceed the * buffer size. If just limiting the aggregate size, this would be * possible with a buf_size of 8: @@ -3045,9 +3068,6 @@ enum ieee80211_reconfig_type { * buffer size of 8. Correct ways to retransmit #1 would be: * - TX: 1 or 18 or 81 * Even "189" would be wrong since 1 could be lost again. - * The @amsdu parameter is valid when the action is set to - * %IEEE80211_AMPDU_TX_OPERATIONAL and indicates the peer's ability - * to receive A-MSDU within A-MPDU. * * Returns a negative error code on failure. * The callback can sleep. @@ -3389,9 +3409,7 @@ struct ieee80211_ops { int (*tx_last_beacon)(struct ieee80211_hw *hw); int (*ampdu_action)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu); + struct ieee80211_ampdu_params *params); int (*get_survey)(struct ieee80211_hw *hw, int idx, struct survey_info *survey); void (*rfkill_poll)(struct ieee80211_hw *hw); diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 367784be5df2..f598ff80b30e 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -7,6 +7,7 @@ * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> * Copyright 2007, Michael Wu <flamingice@sourmilk.net> * Copyright 2007-2010, Intel Corporation + * Copyright(c) 2015 Intel Deutschland GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -61,6 +62,14 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, { struct ieee80211_local *local = sta->local; struct tid_ampdu_rx *tid_rx; + struct ieee80211_ampdu_params params = { + .sta = &sta->sta, + .action = IEEE80211_AMPDU_RX_STOP, + .tid = tid, + .amsdu = false, + .timeout = 0, + .ssn = 0, + }; lockdep_assert_held(&sta->ampdu_mlme.mtx); @@ -78,8 +87,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, initiator == WLAN_BACK_RECIPIENT ? "recipient" : "inititator", (int)reason); - if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, - &sta->sta, tid, NULL, 0, false)) + if (drv_ampdu_action(local, sta->sdata, ¶ms)) sdata_info(sta->sdata, "HW problem - can not stop rx aggregation for %pM tid %d\n", sta->sta.addr, tid); @@ -237,6 +245,15 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta, { struct ieee80211_local *local = sta->sdata->local; struct tid_ampdu_rx *tid_agg_rx; + struct ieee80211_ampdu_params params = { + .sta = &sta->sta, + .action = IEEE80211_AMPDU_RX_START, + .tid = tid, + .amsdu = false, + .timeout = timeout, + .ssn = start_seq_num, + }; + int i, ret = -EOPNOTSUPP; u16 status = WLAN_STATUS_REQUEST_DECLINED; @@ -275,6 +292,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta, /* make sure the size doesn't exceed the maximum supported by the hw */ if (buf_size > local->hw.max_rx_aggregation_subframes) buf_size = local->hw.max_rx_aggregation_subframes; + params.buf_size = buf_size; /* examine state machine */ mutex_lock(&sta->ampdu_mlme.mtx); @@ -322,8 +340,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta, for (i = 0; i < buf_size; i++) __skb_queue_head_init(&tid_agg_rx->reorder_buf[i]); - ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, - &sta->sta, tid, &start_seq_num, 0, false); + ret = drv_ampdu_action(local, sta->sdata, ¶ms); ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n", sta->sta.addr, tid, ret); if (ret) { diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index ff757181b0a8..4932e9f243a2 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -7,6 +7,7 @@ * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> * Copyright 2007, Michael Wu <flamingice@sourmilk.net> * Copyright 2007-2010, Intel Corporation + * Copyright(c) 2015 Intel Deutschland GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -295,7 +296,14 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, { struct ieee80211_local *local = sta->local; struct tid_ampdu_tx *tid_tx; - enum ieee80211_ampdu_mlme_action action; + struct ieee80211_ampdu_params params = { + .sta = &sta->sta, + .tid = tid, + .buf_size = 0, + .amsdu = false, + .timeout = 0, + .ssn = 0, + }; int ret; lockdep_assert_held(&sta->ampdu_mlme.mtx); @@ -304,10 +312,10 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, case AGG_STOP_DECLINED: case AGG_STOP_LOCAL_REQUEST: case AGG_STOP_PEER_REQUEST: - action = IEEE80211_AMPDU_TX_STOP_CONT; + params.action = IEEE80211_AMPDU_TX_STOP_CONT; break; case AGG_STOP_DESTROY_STA: - action = IEEE80211_AMPDU_TX_STOP_FLUSH; + params.action = IEEE80211_AMPDU_TX_STOP_FLUSH; break; default: WARN_ON_ONCE(1); @@ -330,9 +338,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, spin_unlock_bh(&sta->lock); if (reason != AGG_STOP_DESTROY_STA) return -EALREADY; - ret = drv_ampdu_action(local, sta->sdata, - IEEE80211_AMPDU_TX_STOP_FLUSH_CONT, - &sta->sta, tid, NULL, 0, false); + params.action = IEEE80211_AMPDU_TX_STOP_FLUSH_CONT; + ret = drv_ampdu_action(local, sta->sdata, ¶ms); WARN_ON_ONCE(ret); return 0; } @@ -381,8 +388,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, WLAN_BACK_INITIATOR; tid_tx->tx_stop = reason == AGG_STOP_LOCAL_REQUEST; - ret = drv_ampdu_action(local, sta->sdata, action, - &sta->sta, tid, NULL, 0, false); + ret = drv_ampdu_action(local, sta->sdata, ¶ms); /* HW shall not deny going back to legacy */ if (WARN_ON(ret)) { @@ -445,7 +451,14 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) struct tid_ampdu_tx *tid_tx; struct ieee80211_local *local = sta->local; struct ieee80211_sub_if_data *sdata = sta->sdata; - u16 start_seq_num; + struct ieee80211_ampdu_params params = { + .sta = &sta->sta, + .action = IEEE80211_AMPDU_TX_START, + .tid = tid, + .buf_size = 0, + .amsdu = false, + .timeout = 0, + }; int ret; tid_tx = rcu_dereference_protected_tid_tx(sta, tid); @@ -467,10 +480,8 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) */ synchronize_net(); - start_seq_num = sta->tid_seq[tid] >> 4; - - ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START, - &sta->sta, tid, &start_seq_num, 0, false); + params.ssn = sta->tid_seq[tid] >> 4; + ret = drv_ampdu_action(local, sdata, ¶ms); if (ret) { ht_dbg(sdata, "BA request denied - HW unavailable for %pM tid %d\n", @@ -499,7 +510,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) /* send AddBA request */ ieee80211_send_addba_request(sdata, sta->sta.addr, tid, - tid_tx->dialog_token, start_seq_num, + tid_tx->dialog_token, params.ssn, IEEE80211_MAX_AMPDU_BUF, tid_tx->timeout); } @@ -684,18 +695,24 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, struct sta_info *sta, u16 tid) { struct tid_ampdu_tx *tid_tx; + struct ieee80211_ampdu_params params = { + .sta = &sta->sta, + .action = IEEE80211_AMPDU_TX_OPERATIONAL, + .tid = tid, + .timeout = 0, + .ssn = 0, + }; lockdep_assert_held(&sta->ampdu_mlme.mtx); tid_tx = rcu_dereference_protected_tid_tx(sta, tid); + params.buf_size = tid_tx->buf_size; + params.amsdu = tid_tx->amsdu; ht_dbg(sta->sdata, "Aggregation is on for %pM tid %d\n", sta->sta.addr, tid); - drv_ampdu_action(local, sta->sdata, - IEEE80211_AMPDU_TX_OPERATIONAL, - &sta->sta, tid, NULL, tid_tx->buf_size, - tid_tx->amsdu); + drv_ampdu_action(local, sta->sdata, ¶ms); /* * synchronize with TX path, while splicing the TX path diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c index ca1fe5576103..c258f1041d33 100644 --- a/net/mac80211/driver-ops.c +++ b/net/mac80211/driver-ops.c @@ -284,9 +284,7 @@ int drv_switch_vif_chanctx(struct ieee80211_local *local, int drv_ampdu_action(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, - u16 *ssn, u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { int ret = -EOPNOTSUPP; @@ -296,12 +294,10 @@ int drv_ampdu_action(struct ieee80211_local *local, if (!check_sdata_in_driver(sdata)) return -EIO; - trace_drv_ampdu_action(local, sdata, action, sta, tid, - ssn, buf_size, amsdu); + trace_drv_ampdu_action(local, sdata, params); if (local->ops->ampdu_action) - ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action, - sta, tid, ssn, buf_size, amsdu); + ret = local->ops->ampdu_action(&local->hw, &sdata->vif, params); trace_drv_return_int(local, ret); diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 154ce4b13406..18b0d65baff0 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -585,9 +585,7 @@ static inline int drv_tx_last_beacon(struct ieee80211_local *local) int drv_ampdu_action(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, - u16 *ssn, u8 buf_size, bool amsdu); + struct ieee80211_ampdu_params *params); static inline int drv_get_survey(struct ieee80211_local *local, int idx, struct survey_info *survey) diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 56c6d6cfa5a1..913e959b03cf 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h @@ -80,7 +80,23 @@ #define KEY_PR_FMT " cipher:0x%x, flags=%#x, keyidx=%d, hw_key_idx=%d" #define KEY_PR_ARG __entry->cipher, __entry->flags, __entry->keyidx, __entry->hw_key_idx - +#define AMPDU_ACTION_ENTRY __field(enum ieee80211_ampdu_mlme_action, \ + ieee80211_ampdu_mlme_action) \ + STA_ENTRY \ + __field(u16, tid) \ + __field(u16, ssn) \ + __field(u8, buf_size) \ + __field(bool, amsdu) \ + __field(u16, timeout) +#define AMPDU_ACTION_ASSIGN STA_NAMED_ASSIGN(params->sta); \ + __entry->tid = params->tid; \ + __entry->ssn = params->ssn; \ + __entry->buf_size = params->buf_size; \ + __entry->amsdu = params->amsdu; \ + __entry->timeout = params->timeout; +#define AMPDU_ACTION_PR_FMT STA_PR_FMT " tid %d, ssn %d, buf_size %u, amsdu %d, timeout %d" +#define AMPDU_ACTION_PR_ARG STA_PR_ARG, __entry->tid, __entry->ssn, \ + __entry->buf_size, __entry->amsdu, __entry->timeout /* * Tracing for driver callbacks. @@ -970,38 +986,25 @@ DEFINE_EVENT(local_only_evt, drv_tx_last_beacon, TRACE_EVENT(drv_ampdu_action, TP_PROTO(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, - u16 *ssn, u8 buf_size, bool amsdu), + struct ieee80211_ampdu_params *params), - TP_ARGS(local, sdata, action, sta, tid, ssn, buf_size, amsdu), + TP_ARGS(local, sdata, params), TP_STRUCT__entry( LOCAL_ENTRY - STA_ENTRY - __field(u32, action) - __field(u16, tid) - __field(u16, ssn) - __field(u8, buf_size) - __field(bool, amsdu) VIF_ENTRY + AMPDU_ACTION_ENTRY ), TP_fast_assign( LOCAL_ASSIGN; VIF_ASSIGN; - STA_ASSIGN; - __entry->action = action; - __entry->tid = tid; - __entry->ssn = ssn ? *ssn : 0; - __entry->buf_size = buf_size; - __entry->amsdu = amsdu; + AMPDU_ACTION_ASSIGN; ), TP_printk( - LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d buf:%d amsdu:%d", - LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, - __entry->tid, __entry->buf_size, __entry->amsdu + LOCAL_PR_FMT VIF_PR_FMT AMPDU_ACTION_PR_FMT, + LOCAL_PR_ARG, VIF_PR_ARG, AMPDU_ACTION_PR_ARG ) ); diff --git a/security/pfe/pfk_kc.c b/security/pfe/pfk_kc.c index 0869a862f521..cd3f08b3959d 100644 --- a/security/pfe/pfk_kc.c +++ b/security/pfe/pfk_kc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -100,6 +100,9 @@ struct kc_entry { struct task_struct *thread_pending; enum pfk_kc_entry_state state; + + /* ref count for the number of requests in the HW queue for this key */ + int loaded_ref_cnt; int scm_error; }; @@ -520,6 +523,10 @@ int pfk_kc_load_key_start(const unsigned char *key, size_t key_size, if (entry_exists) { kc_update_timestamp(entry); entry->state = ACTIVE_ICE_LOADED; + + if (async) + entry->loaded_ref_cnt++; + break; } case (FREE): @@ -529,8 +536,17 @@ int pfk_kc_load_key_start(const unsigned char *key, size_t key_size, entry->scm_error = ret; pr_err("%s: key load error (%d)\n", __func__, ret); } else { - entry->state = ACTIVE_ICE_LOADED; kc_update_timestamp(entry); + entry->state = ACTIVE_ICE_LOADED; + + /* + * only increase ref cnt for async calls, + * sync calls from within work thread do not pass + * requests further to HW + */ + if (async) + entry->loaded_ref_cnt++; + } break; case (ACTIVE_ICE_PRELOAD): @@ -539,6 +555,10 @@ int pfk_kc_load_key_start(const unsigned char *key, size_t key_size, break; case (ACTIVE_ICE_LOADED): kc_update_timestamp(entry); + + if (async) + entry->loaded_ref_cnt++; + break; case(SCM_ERROR): ret = entry->scm_error; @@ -572,6 +592,8 @@ void pfk_kc_load_key_end(const unsigned char *key, size_t key_size, const unsigned char *salt, size_t salt_size) { struct kc_entry *entry = NULL; + struct task_struct *tmp_pending = NULL; + int ref_cnt = 0; if (!kc_is_ready()) return; @@ -591,14 +613,28 @@ void pfk_kc_load_key_end(const unsigned char *key, size_t key_size, if (!entry) { kc_spin_unlock(); pr_err("internal error, there should an entry to unlock\n"); + return; } - entry->state = INACTIVE; + ref_cnt = --entry->loaded_ref_cnt; + + if (ref_cnt < 0) + pr_err("internal error, ref count should never be negative\n"); - /* wake-up invalidation if it's waiting for the entry to be released */ - if (entry->thread_pending) { - wake_up_process(entry->thread_pending); - entry->thread_pending = NULL; + if (!ref_cnt) { + entry->state = INACTIVE; + /* + * wake-up invalidation if it's waiting + * for the entry to be released + */ + if (entry->thread_pending) { + tmp_pending = entry->thread_pending; + entry->thread_pending = NULL; + + kc_spin_unlock(); + wake_up_process(tmp_pending); + return; + } } kc_spin_unlock(); |
