Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752541AbdFOKeY (ORCPT ); Thu, 15 Jun 2017 06:34:24 -0400 Received: from mail-bn3nam01on0087.outbound.protection.outlook.com ([104.47.33.87]:62272 "EHLO NAM01-BN3-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752088AbdFOKeV (ORCPT ); Thu, 15 Jun 2017 06:34:21 -0400 Authentication-Results: arm.com; dkim=none (message not signed) header.d=none;arm.com; dmarc=none action=none header.from=caviumnetworks.com; Date: Thu, 15 Jun 2017 12:34:06 +0200 From: Jan Glauber To: Mark Rutland Cc: Will Deacon , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Borislav Petkov Subject: Re: [PATCH v5 2/3] perf: cavium: Support memory controller PMU counters Message-ID: <20170615103406.GA13427@hc> References: <20170517083122.5050-1-jglauber@cavium.com> <20170517083122.5050-3-jglauber@cavium.com> <20170602163337.GM28299@leverpostej> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20170602163337.GM28299@leverpostej> User-Agent: Mutt/1.5.21 (2010-09-15) X-Originating-IP: [88.67.130.225] X-ClientProxiedBy: VI1PR0501CA0017.eurprd05.prod.outlook.com (10.172.9.155) To CO2PR07MB2582.namprd07.prod.outlook.com (10.166.201.21) X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CO2PR07MB2582: X-MS-Office365-Filtering-Correlation-Id: 121787c6-90b9-4643-69fc-08d4b3da1409 X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(22001)(201703131423075)(201703031133081);SRVR:CO2PR07MB2582; X-Microsoft-Exchange-Diagnostics: 1;CO2PR07MB2582;3:2f7W+Vsj3DOwLCImWlOrPn9cZ01ngEvf5oHSoGTt6pQFztL3bTM385z0o7LcYv4untc2Yw1IkMxeODmh5OMk3gxY3vOIZELWeDVqjyeV/vrkdAtc03/HgIh1obvH8JLhgfzMFFt1PpUu2JoWzvjtY4LJ4Y76ouFuGHZUugX3YTBpeG8Qu3Yt+jRvS6uw9OZRH91MoyhVpDhdTYsvf2W77dO3fdP73Enk0ECpFXDC7aCJ8df+Ntf69P3Ij0/4b0bFpIchlqffHqo3xtqD+X3MsQRq/7+vW1/dot4tIJMHydt4vd0Z/0wR0FuAqV9/0hsX8r68tREKMyKelFGbzx/K2Q==;25:/UcONJxIcpz5H2OQUxwKNR6wKFYmkjR5VBnP5dciJ7YMQxp98yoHO+OWF1J5diWbcT2lozWoq5Fcl3Deg2laIgtRcbE+dGhnQzDdnOrqpSfuz9TjbD99zp4zBJNh6UUXd5S0KVz9BlTiAZY5vissvy9ZbDDUBEXUYEFejlKWVZoVqsvXCMoYsaYbmBvKtRNhdYucrMnxXCHXibgBRfs5h0pTZakH/wofQo6z8WOsB/0Aj2UkCb6hjKqRuifv4tSJHBbnMb7FvF+3bPiA7RTd16mzm/0HoSccjnA49/wxBXvUVsbqBl5WMjdOYPoFoAHV7KhpTSbZaEvxc6yfcQcsXBIrBAcBbL3h63MjxF/A3fQ+mCFXAtYeYosOkCr5mRSwoycbsn8NUrSpi2t1gyb+kPyE0F37Crmh6Y65tGnaZLvolZ8SfP3Av2oFBZ6YVvj8xidHqVq7Ff9oPzF3FVCEuB1Lz/r+WOo/yu8VBLeuWik= X-Microsoft-Exchange-Diagnostics: 1;CO2PR07MB2582;31:Tej+BXFFBh4BFUPDEf3ekc21weAL9c89YEl8UaJs3wxWFYpmIxsY9XJ3br4vkukgqkbWJL0OTwuYJsAggtTBuyITbeBHFJY3B3bpZ001L/+9wNu7LIp72EyJRZ24fEiYBVS0nkihQhRZN0KBKdWroBrNtnwOZXxWDUttOsgSkpX/R1kKqAnNL47amozb6Cl7MDsnfDC/v4ckx565Srp00uM7Z97juibRiw3RVlPrKp6/qP2gkNFtLrqFMkdnopTBhOsKLh/vcaJtPOrt7W+ykg==;20:rLKxn+ll2yRX2Io2yGGCkxcAp1LKdQ+Da/4nXDHgP2Cy4fibAcWdBy5GceK7+CaKkmhbDOqSudDJK1Tb512MfNg09dv1m2eFz3uSkBurlPZ2s85hy/0xMHFh57PiN+OkpB485YUTf+ez6hIwv6Q4ZuKdfWHSv0eGHxmcq4VIlHU1z3UNFchagYLmZGpGTjmqeVIP6+rhSkVV1tUUhYYuklrkuZbtoIgKSLlGl9NrRKWt9kUY9YDDOWemQaMHAWG/K0KocBZxzKFJMo6p7UnoRoPBPtYE4Ykptq1HWeZHTWD+bkySCRCFqSP2ChxECIIFH3LCckp7SnSBmr1y0P2HdUSBYZdS0iGEda1ufGuHrlb2VHer5a91W4bfjJq0UvL45aG7zMeI6DkUwHODzDISbvO7FMSsqwD9cBjzryItGH/E9RBQjUQIVM3p/dR9EPM6FQP9QoQeILooKwIVDTB6Zio0QQCW2Uv3LKQrPvGcSUl3M+YcFW17WoqmL+PxeZS7DpV6frgw/+DPYrrhZvBnaDtgrGDJHdyiq+rMzUczMNjRGzGqPQkA9vnyKHm5EDMz7kYA9fHZ/f6WwaioZI1Ucl+ChccZoqnpiYHnGyG9NEE= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(100000700101)(100105000095)(100000701101)(100105300095)(100000702101)(100105100095)(6040450)(601004)(2401047)(5005006)(8121501046)(100000703101)(100105400095)(3002001)(10201501046)(93006095)(6041248)(20161123560025)(20161123564025)(20161123562025)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123558100)(20161123555025)(6072148)(100000704101)(100105200095)(100000705101)(100105500095);SRVR:CO2PR07MB2582;BCL:0;PCL:0;RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(100000804101)(100110200095)(100000805101)(100110500095);SRVR:CO2PR07MB2582; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;CO2PR07MB2582;4:3b4zH2fKE4FC9rrFWYHMBq3a4XLwTXfxaXcIwvljsq?= =?us-ascii?Q?GlRv6e+oJMHBoQ/ENnzFa21MQgFrcFpPwav5CluLFFLwTxe3Oi5zU8NvqWjG?= =?us-ascii?Q?R2E/g9jy22EA0EBVab8o+19K5PnOhglVpna5EYBlxuj04NF2Qk+LBdewZfSa?= =?us-ascii?Q?GVMHVvLDZXgy/+DFytoHOLlEaL9hyUh8iuBdOiV49ozOljWjgdqj9hf5WBAQ?= =?us-ascii?Q?1V8X1Gxzouvc/V2zrB1LJY79HrIN7XWuCjWqc7um1scfIyl6ncbZtHm3YQQ4?= =?us-ascii?Q?YYeCaT2/Xuj/DpqQnJjTIUwK5XecWP/DcUeB7KvnBYYb7QlCklWQUM7jLE8L?= =?us-ascii?Q?8xWXpFvZHckAwCntvlPZi453yLPeD2VMEREzHnHgmq7fEaIxhk9iqof4peTz?= =?us-ascii?Q?c2JPwZ70iQvFl876HmLvURJzAXosnljgtULriFzKq8XtyEex+QIss+yfuVq6?= =?us-ascii?Q?ctJhunkzVJbZDp0Xx+0KXnNfrwnsYXFKoJArLJfyU7ZjP4mSBOxOkQG7Gob0?= =?us-ascii?Q?GAxdpv89ftty4Croi19PtePrqt1nK7kNERjlSrmI36DrsUP418XdUwfi0pMy?= =?us-ascii?Q?sqOdj1/8EHQDF0ojnhbEgU5qPOVuvm/BWMaKvxcXEVB3sQa2NKKyDE4qPFAu?= =?us-ascii?Q?JKb05q7sQjw7Wq+07wVQPw7wreEE2+JuK2BZzcJHnVTWKJxfcFMtRkc5zSWH?= =?us-ascii?Q?5Q8Nfh/3HrzaONMW3ioCl2JIhnDLm1o5mercz1PgD50nbpVW6HSesu3MOpnt?= =?us-ascii?Q?dbegn+t+8sS0/p2cjm2yP6nG/Z3knoCBF150tcMXNvMwOHCeZYhqNtUgvSix?= =?us-ascii?Q?1NDWVL7NZJHFufQKWm2gm9+w2ZfZHKnYyidZSsl0YkEA2d1RnmytQhvTtEFv?= =?us-ascii?Q?Ppw3WXOZa+dx5YzM4FRUmHHs5t1nprLcg+yk2Wd/ZI71GJ4MtqBTnZPFbeTr?= =?us-ascii?Q?R8T2916yDiskbe7B+cH6q8wu4iXBLySz5oX5SYsl6Nm/RqWDtTW5rqCJ6o7h?= =?us-ascii?Q?9uZbcbXAYRSQx8vxpbw8nTlPDRY/bCEjr7xiww6BHFxesnnBQsPiQzzU1fyP?= =?us-ascii?Q?hMVLLF1a79n8Ioa9pfFGO+sScN8yWo3p2sgdsQizpcH65cwN0RzH4WyS+c1W?= =?us-ascii?Q?CLBvuQtHA=3D?= X-Forefront-PRVS: 0339F89554 X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10009020)(4630300001)(6009001)(39840400002)(39450400003)(39850400002)(39400400002)(39410400002)(24454002)(51914003)(54906002)(72206003)(55016002)(229853002)(25786009)(42186005)(81166006)(8676002)(33656002)(4326008)(6666003)(42882006)(50466002)(5660300001)(2950100002)(2906002)(305945005)(6916009)(66066001)(47776003)(3846002)(6116002)(7736002)(23726003)(1076002)(4001350100001)(54356999)(189998001)(6496005)(478600001)(50986999)(53936002)(9686003)(33716001)(83506001)(110136004)(38730400002)(6246003)(76176999)(18370500001);DIR:OUT;SFP:1101;SCL:1;SRVR:CO2PR07MB2582;H:hc;FPR:;SPF:None;MLV:sfv;LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;CO2PR07MB2582;23:SVYu2l5RXvTaHiWR6FFrLfqCg/khJrpeapG31Drrh?= =?us-ascii?Q?WgQKwms+Zt+q6snotWkty7w0YRXM4KNfDzE59UQVo7E+ix6ujMmXKnE80wQ9?= =?us-ascii?Q?rLieXpU0yggBZNL1F3ExmgV21J9YQ+gumC9uZqWppVXRl4bwhghQQTqtXjD7?= =?us-ascii?Q?yLO+neTOh9j7oY1sS9W2LOxRe9C7UUllwNHVzfE+C7CP2JtaeO+IkFDDucFp?= =?us-ascii?Q?ElUDJjhoo93YPqeHFxa/3SZIiUSC5lF1iHLXQiI8YUgY2G43ClzWjCx3s20M?= =?us-ascii?Q?q0bdPWSQXANNCZ/OcSFGzrOFcWTcny/IRC4xT0e4txyhBDB2m+0AO08N4x8z?= =?us-ascii?Q?3aIfdvjcqD1UMTtsjfGimZdCWdJpMjURvJ48GrCcYSxtVa5LYOZ6jxqN2CcQ?= =?us-ascii?Q?HaKF5oncafzEWFpr9di6OQL5/ppgoeEHa5e6zV7CePbGcKS3VJuc/121qJ3h?= =?us-ascii?Q?X9mRJgTY20E9mODH142gsNLjyyH1aP/3nClf0nz4zdG+hJ4+OFeYCYy8u3Ef?= =?us-ascii?Q?tyFpE6t9X4Tel7B1+Im6CCeLyXxsQb9f4ePbYBG3yq7RA8qIGVgWjBg7owDK?= =?us-ascii?Q?0H7iOgKqumLkbx9C3U46rlTX8FgLOXFjMq/cJeDj3EwEKRyvSryQYaSiYbPR?= =?us-ascii?Q?3eg49uo2Rqtn/f4cUyNF+DGKZurrsOXnv5XWwk/7mWa5wQE0Mkty7G3OkeCI?= =?us-ascii?Q?4ao/I3z+v3TJuJGplqXuTLAbwupjKVqtTIdSeYD5VoQ5ITHOcFPDsIp69j1f?= =?us-ascii?Q?12G+CCYXtVhHpq7ixvDdwAmZOdwcKM25Bo1ijbKVSZuly/EOe5BZgagqMw+C?= =?us-ascii?Q?Hg1wJVU+bOwMZc8OR9+GnoIOxjeGXbo35vEMa7vRvQNw2NwCXXSB3lggJOkK?= =?us-ascii?Q?bscJ4otd0WtD7YK7XfgETSuL92MaUrEIBaVuukzqXRvPdZ6iUMWwg6OIJXpn?= =?us-ascii?Q?s8iDtRcF7oZiZdCbjRtSLtnVgY3uwXlyoznG6ow0Vdq659rPzGWvmi+zLy98?= =?us-ascii?Q?BfXzRNOdQhiq5QtYdHT/XWk/rTZTCzKBbrvQGWZKFDEc21GgCTmF45nsnPuj?= =?us-ascii?Q?NdTqz6cmHufyG5Ksv8THd2EBKu5+YdVH1HzO5j7UknD21qauMwb2wg2Qq+A4?= =?us-ascii?Q?B6cD/19LTU0myBeRhTo3H2F1BfB+Z3upENbuzfFzkszhxhBtwxpSkmUZdhbV?= =?us-ascii?Q?s7mScFi7PSJXHIc2tRVQtWCogZSz5IDbGOH4HsR0JGFB0B9kM6TGSlzpw=3D?= =?us-ascii?Q?=3D?= X-Microsoft-Exchange-Diagnostics: 1;CO2PR07MB2582;6:Cgqdd6c0h/BTu/5QIEdR8rr+Jigkusy1LO8/rj0qqjpoKCiLW7mej0LXdQq1DsZ+kxV40swL5p2LTb5hSyIR5x4GKA/hOrZSErxZt1BnI40aotG9UZe8vDp4xy26XE+60IR0xzoaQXm55COGg9J2XxOfniuknSUnXLmUQLkzpR/XcSaBrN5OmW4MKTskNEd9g2rEi/UGo+OecW3JkEeIqSHN26+x9RwiO3qh2be0bpwLnBYUeKvESuY1n65nylEDs9qUNEyX0crFRc64ozUFnNhHlMt2KJ3VqECzR6pO2oVe89f4B2b6LSjNSr607suWP9RenYmH2MZWPaZNgU7pMN0Vysqcvkki4xczT79w947+1756SB7Yd0/hTZS+LpWljjTGbv/pml02Nx51LrC/+pXEE9tzstfg8Blrp+xrTNiE/r+waNSP7d5YJmxqPKGbXSGqQgin99aBb7iFlB5VmYxehWyYhqijp/+yDkW8jC60Z6uPqDwsPqAjxg62tfTuPrlxv5+qA5RbpIRqeZuYqA== X-Microsoft-Exchange-Diagnostics: 1;CO2PR07MB2582;5:NO7hHiGHJ7XM4CNTXAdnwkx2lNnTyArZJy6w42GYfzgaTsO0UllhOaxu31ju9kMpn25Ue1oKurVmtx0a8ux94GRbI+kIWkx7Gs7Vf+v0EDMpqhDA/Dk0/+bLm0d5FU/0RRr6DqXIDH737kALmWfpwJKIXJp02Wzdn09jQ/+p2gMKk/CwXwaLEXqNOOobexOLGdJA8sPoBJwOj47YP0I7t2e3rDudOKGk/I9PDAK096KjMQLJOtZfJ0Zld14T6JISZvY76VMBiP2E6YWyZTuQEK8uzlorhusDn+9qkmk0qPCHHLLaFtS/honHiWxEji/dR7mZH+cbQReV91UwmA1kbc/Li++7uR7ZGZbIAJUSkG9WtjpWrauAsflPb+kwlrlCrlerGtcH49gOb41MtKYy1a6IGuF8NRdvI6c6qGy8WFZMiIdqL5BTjEkzGJHBPSbAUsiNKSrsiiwFzMNidXVB12xI87njntATkzUZugiZ5i7tQCc2vllKezoT3fUCxmva;24:9HsBiteGYMzSJo8eRit8itD68DTrT14UbBbCxiV0PF2PNyNylmu7YsnMNPv0g0PW7S97qZRA4Ya5gPMJCOaIeAIMYX60rKTselwaEJXuqeA= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;CO2PR07MB2582;7:z1LABXq94DtZ0+xDWnTIEhmg/Eyi9265/pSrTQyohM6edR8qnuIw9CeLP43piEe1DYY1oN6qEtklm4wasPmR3ocnkf6owrnby5ZFYWm+j500f+OUirtpjMc/CbAiU94oys2M6ctCXNffpzjRnIwPAb4anOQI8y008bfxEODyVE8QE4vhqD6aHUKSEoUbfjpmjmKLGN3TFfedTNlAc8nu8ojqFyszwUyrRMMVo29Wu/7I1Hy1vF39A4zSstlI6t8T5RCrwrR8QY5oGBVEX0Ahct63a0AyGP2V8hJwlQOEzlp4oLczuRNPqkqPraMdHdz9DIyHZ46PNBoEom7r4K/BdA== X-OriginatorOrg: caviumnetworks.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Jun 2017 10:34:17.0079 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: CO2PR07MB2582 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 8829 Lines: 302 On Fri, Jun 02, 2017 at 05:33:38PM +0100, Mark Rutland wrote: > Hi, > > On Wed, May 17, 2017 at 10:31:21AM +0200, Jan Glauber wrote: > > Add support for the PMU counters on Cavium SOC memory controllers. > > > > This patch also adds generic functions to allow supporting more > > devices with PMU counters. > > Please add a short description of the PMU. e.g. whether counters are > programmable, how they relate to components in the system. There is a short description in the comments for each PMU type, I can add that to the commit message. I'm also brewing up something for Documentation/perf. > > @@ -810,6 +812,9 @@ static int thunderx_lmc_probe(struct pci_dev *pdev, > > } > > } > > > > + if (IS_ENABLED(CONFIG_CAVIUM_PMU)) > > + lmc->pmu_data = cvm_pmu_probe(pdev, lmc->regs, CVM_PMU_LMC); > > I don't think this makes sense given CAVIUM_PMU is a tristate. This > can't work if that's a module. Right, the combination of EDAC_THUNDERX=y and CAVIUM_PMU=m does not work. Both as module or builtin works. The config option can be moved to the header file. Is the approach of hooking into the driver that owns the device (edac) good or should I merge the pmu code into the edac driver? > > @@ -824,6 +829,9 @@ static void thunderx_lmc_remove(struct pci_dev *pdev) > > struct mem_ctl_info *mci = pci_get_drvdata(pdev); > > struct thunderx_lmc *lmc = mci->pvt_info; > > > > + if (IS_ENABLED(CONFIG_CAVIUM_PMU)) > > + cvm_pmu_remove(pdev, lmc->pmu_data, CVM_PMU_LMC); > > Likewise. > > [...] > > > +#define to_pmu_dev(x) container_of((x), struct cvm_pmu_dev, pmu) > > + > > +static int cvm_pmu_event_init(struct perf_event *event) > > +{ > > + struct hw_perf_event *hwc = &event->hw; > > + struct cvm_pmu_dev *pmu_dev; > > + > > + if (event->attr.type != event->pmu->type) > > + return -ENOENT; > > + > > + /* we do not support sampling */ > > + if (is_sampling_event(event)) > > + return -EINVAL; > > + > > + /* PMU counters do not support any these bits */ > > + if (event->attr.exclude_user || > > + event->attr.exclude_kernel || > > + event->attr.exclude_host || > > + event->attr.exclude_guest || > > + event->attr.exclude_hv || > > + event->attr.exclude_idle) > > + return -EINVAL; > > + > > + pmu_dev = to_pmu_dev(event->pmu); > > + if (!pmu_dev) > > + return -ENODEV; > > This cannot happen given to_pmu_dev() is just a container_of(). OK. > > + if (!pmu_dev->event_valid(event->attr.config)) > > + return -EINVAL; > > Is group validation expected to take place in this callback? No, that callback is needed to prevent access to other registers of the device. The PMU counters are embedded all over the place and allowing access to a non-PMU counter could be fatal. > AFAICT, nothing does so (including cvm_pmu_lmc_event_valid()). OK, I completely missed the group validation thing. I'll add it in the next revision. > > + > > + hwc->config = event->attr.config; > > + hwc->idx = -1; > > + return 0; > > +} > > + > > +static void cvm_pmu_read(struct perf_event *event) > > +{ > > + struct cvm_pmu_dev *pmu_dev = to_pmu_dev(event->pmu); > > + struct hw_perf_event *hwc = &event->hw; > > + u64 prev, delta, new; > > + > > + new = readq(hwc->event_base + pmu_dev->map); > > + > > + prev = local64_read(&hwc->prev_count); > > + local64_set(&hwc->prev_count, new); > > + delta = new - prev; > > + local64_add(delta, &event->count); > > +} > > Typically we need a local64_cmpxchg loop to update prev_count. > > Why is that not the case here? OK, will fix this. > > +static void cvm_pmu_start(struct perf_event *event, int flags) > > +{ > > + struct cvm_pmu_dev *pmu_dev = to_pmu_dev(event->pmu); > > + struct hw_perf_event *hwc = &event->hw; > > + u64 new; > > + > > + if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED))) > > + return; > > + > > + WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE)); > > + hwc->state = 0; > > + > > + /* update prev_count always in order support unstoppable counters */ > > All of the counters are free-running and unstoppable? No, unfortunately every device containing PMU counters implemements them in a different way. The TLK counters are stoppable, the LMC counters are not. > Please mention that in the commit message. OK. > > + new = readq(hwc->event_base + pmu_dev->map); > > + local64_set(&hwc->prev_count, new); > > + > > + perf_event_update_userpage(event); > > +} > > + > > +static void cvm_pmu_stop(struct perf_event *event, int flags) > > +{ > > + struct hw_perf_event *hwc = &event->hw; > > + > > + WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED); > > + hwc->state |= PERF_HES_STOPPED; > > + > > + if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) { > > + cvm_pmu_read(event); > > + hwc->state |= PERF_HES_UPTODATE; > > + } > > +} > > + > > +static int cvm_pmu_add(struct perf_event *event, int flags, u64 config_base, > > + u64 event_base) > > +{ > > + struct cvm_pmu_dev *pmu_dev = to_pmu_dev(event->pmu); > > + struct hw_perf_event *hwc = &event->hw; > > + > > + if (!cmpxchg(&pmu_dev->events[hwc->config], NULL, event)) > > + hwc->idx = hwc->config; > > So all of the counters are fixed-purpose? Again no, I'm trying to come up with a common part that can handle all the different PMU implementations. In this patches all counters are fixed-purpose. As I said in the commit message I plan to also support the L2 cache counters in the future, which are not fixed purpose. > Please mention that in the commit message > > > + > > + if (hwc->idx == -1) > > + return -EBUSY; > > + > > + hwc->config_base = config_base; > > + hwc->event_base = event_base; > > + hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED; > > + > > + if (flags & PERF_EF_START) > > + pmu_dev->pmu.start(event, PERF_EF_RELOAD); > > + > > + return 0; > > +} > > + > > +static void cvm_pmu_del(struct perf_event *event, int flags) > > +{ > > + struct cvm_pmu_dev *pmu_dev = to_pmu_dev(event->pmu); > > + struct hw_perf_event *hwc = &event->hw; > > + int i; > > + > > + event->pmu->stop(event, PERF_EF_UPDATE); > > + > > + /* > > + * For programmable counters we need to check where we installed it. > > AFAICT cvm_pmu_{start,add} don't handle programmable counters at all. > What's going on? Not sure what you mean. The previous revisions had support for the programmable L2 cache counters and the cvm_pmu_{start,add} code was nearly identical for these. > > + * To keep this function generic always test the more complicated > > + * case (free running counters won't need the loop). > > + */ > > + for (i = 0; i < pmu_dev->num_counters; i++) > > + if (cmpxchg(&pmu_dev->events[i], event, NULL) == event) > > + break; > > + > > + perf_event_update_userpage(event); > > + hwc->idx = -1; > > +} > > > +static bool cvm_pmu_lmc_event_valid(u64 config) > > +{ > > + if (config < ARRAY_SIZE(lmc_events)) > > + return true; > > + return false; > > +} > > return (config < ARRAY_SIZE(lmc_events)); OK. > > +static void *cvm_pmu_lmc_probe(struct pci_dev *pdev, void __iomem *regs) > > +{ > > + struct cvm_pmu_dev *next, *lmc; > > + int nr = 0, ret = -ENOMEM; > > + char name[8]; > > + > > + lmc = kzalloc(sizeof(*lmc), GFP_KERNEL); > > + if (!lmc) > > + goto fail_nomem; > > + > > + list_for_each_entry(next, &cvm_pmu_lmcs, entry) > > + nr++; > > + memset(name, 0, 8); > > + snprintf(name, 8, "lmc%d", nr); > > + > > + list_add(&lmc->entry, &cvm_pmu_lmcs); > > Please add the new element to the list after we've exhausted the error > cases below... Argh... missed that. Will fix. > > + > > + lmc->pdev = pdev; > > + lmc->map = regs; > > + lmc->num_counters = ARRAY_SIZE(lmc_events); > > + lmc->pmu = (struct pmu) { > > + .name = name, > > + .task_ctx_nr = perf_invalid_context, > > + .event_init = cvm_pmu_event_init, > > + .add = cvm_pmu_lmc_add, > > + .del = cvm_pmu_del, > > + .start = cvm_pmu_start, > > + .stop = cvm_pmu_stop, > > + .read = cvm_pmu_read, > > + .attr_groups = cvm_pmu_lmc_attr_groups, > > + }; > > + > > + cpuhp_state_add_instance_nocalls(CPUHP_AP_PERF_ARM_CVM_ONLINE, > > + &lmc->cpuhp_node); > > + > > + /* > > + * perf PMU is CPU dependent so pick a random CPU and migrate away > > + * if it goes offline. > > + */ > > + cpumask_set_cpu(smp_processor_id(), &lmc->active_mask); > > + > > + ret = perf_pmu_register(&lmc->pmu, lmc->pmu.name, -1); > > + if (ret) > > + goto fail_hp; > > + > > + lmc->event_valid = cvm_pmu_lmc_event_valid; > > + dev_info(&pdev->dev, "Enabled %s PMU with %d counters\n", > > + lmc->pmu.name, lmc->num_counters); > > + return lmc; > > + > > +fail_hp: > > + cpuhp_state_remove_instance(CPUHP_AP_PERF_ARM_CVM_ONLINE, > > + &lmc->cpuhp_node); > > + kfree(lmc); > > ... so that we don't free it without removing it. > > > +fail_nomem: > > + return ERR_PTR(ret); > > +} > > Thanks, > Mark. thanks for the review, Jan