0006-surface-sam.patch 83 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324
  1. From 529419e047ed78101c90bfe75b9aef900c71a47e Mon Sep 17 00:00:00 2001
  2. From: Maximilian Luz <luzmaximilian@gmail.com>
  3. Date: Sun, 23 May 2021 14:09:42 +0200
  4. Subject: [PATCH] platform/surface: aggregator_registry: Consolidate node
  5. groups for 5th- and 6th-gen devices
  6. 5th- and 6th-generation Surface devices have all SAM clients defined in
  7. ACPI, except for the platform profile/performance mode which his handled
  8. via the WSID (Windows Surface Integration Device). Thus, the node groups
  9. for those devices are the same and we can just use a single one instead
  10. of re-defining the same one over and over again.
  11. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  12. Patchset: surface-sam
  13. ---
  14. .../surface/surface_aggregator_registry.c | 47 +++++--------------
  15. 1 file changed, 12 insertions(+), 35 deletions(-)
  16. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  17. index ef83461fa536..4428c4330229 100644
  18. --- a/drivers/platform/surface/surface_aggregator_registry.c
  19. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  20. @@ -119,8 +119,13 @@ static const struct software_node ssam_node_hid_base_iid6 = {
  21. .parent = &ssam_node_hub_base,
  22. };
  23. -/* Devices for Surface Book 2. */
  24. -static const struct software_node *ssam_node_group_sb2[] = {
  25. +/*
  26. + * Devices for 5th- and 6th-generations models:
  27. + * - Surface Book 2,
  28. + * - Surface Laptop 1 and 2,
  29. + * - Surface Pro 5 and 6.
  30. + */
  31. +static const struct software_node *ssam_node_group_gen5[] = {
  32. &ssam_node_root,
  33. &ssam_node_tmp_pprof,
  34. NULL,
  35. @@ -142,20 +147,6 @@ static const struct software_node *ssam_node_group_sb3[] = {
  36. NULL,
  37. };
  38. -/* Devices for Surface Laptop 1. */
  39. -static const struct software_node *ssam_node_group_sl1[] = {
  40. - &ssam_node_root,
  41. - &ssam_node_tmp_pprof,
  42. - NULL,
  43. -};
  44. -
  45. -/* Devices for Surface Laptop 2. */
  46. -static const struct software_node *ssam_node_group_sl2[] = {
  47. - &ssam_node_root,
  48. - &ssam_node_tmp_pprof,
  49. - NULL,
  50. -};
  51. -
  52. /* Devices for Surface Laptop 3 and 4. */
  53. static const struct software_node *ssam_node_group_sl3[] = {
  54. &ssam_node_root,
  55. @@ -177,20 +168,6 @@ static const struct software_node *ssam_node_group_slg1[] = {
  56. NULL,
  57. };
  58. -/* Devices for Surface Pro 5. */
  59. -static const struct software_node *ssam_node_group_sp5[] = {
  60. - &ssam_node_root,
  61. - &ssam_node_tmp_pprof,
  62. - NULL,
  63. -};
  64. -
  65. -/* Devices for Surface Pro 6. */
  66. -static const struct software_node *ssam_node_group_sp6[] = {
  67. - &ssam_node_root,
  68. - &ssam_node_tmp_pprof,
  69. - NULL,
  70. -};
  71. -
  72. /* Devices for Surface Pro 7 and Surface Pro 7+. */
  73. static const struct software_node *ssam_node_group_sp7[] = {
  74. &ssam_node_root,
  75. @@ -495,10 +472,10 @@ static struct ssam_device_driver ssam_base_hub_driver = {
  76. static const struct acpi_device_id ssam_platform_hub_match[] = {
  77. /* Surface Pro 4, 5, and 6 (OMBR < 0x10) */
  78. - { "MSHW0081", (unsigned long)ssam_node_group_sp5 },
  79. + { "MSHW0081", (unsigned long)ssam_node_group_gen5 },
  80. /* Surface Pro 6 (OMBR >= 0x10) */
  81. - { "MSHW0111", (unsigned long)ssam_node_group_sp6 },
  82. + { "MSHW0111", (unsigned long)ssam_node_group_gen5 },
  83. /* Surface Pro 7 */
  84. { "MSHW0116", (unsigned long)ssam_node_group_sp7 },
  85. @@ -507,16 +484,16 @@ static const struct acpi_device_id ssam_platform_hub_match[] = {
  86. { "MSHW0119", (unsigned long)ssam_node_group_sp7 },
  87. /* Surface Book 2 */
  88. - { "MSHW0107", (unsigned long)ssam_node_group_sb2 },
  89. + { "MSHW0107", (unsigned long)ssam_node_group_gen5 },
  90. /* Surface Book 3 */
  91. { "MSHW0117", (unsigned long)ssam_node_group_sb3 },
  92. /* Surface Laptop 1 */
  93. - { "MSHW0086", (unsigned long)ssam_node_group_sl1 },
  94. + { "MSHW0086", (unsigned long)ssam_node_group_gen5 },
  95. /* Surface Laptop 2 */
  96. - { "MSHW0112", (unsigned long)ssam_node_group_sl2 },
  97. + { "MSHW0112", (unsigned long)ssam_node_group_gen5 },
  98. /* Surface Laptop 3 (13", Intel) */
  99. { "MSHW0114", (unsigned long)ssam_node_group_sl3 },
  100. --
  101. 2.32.0
  102. From 7cfa1fee5d33055aac80df5c5fd98d923cf48bb6 Mon Sep 17 00:00:00 2001
  103. From: Maximilian Luz <luzmaximilian@gmail.com>
  104. Date: Fri, 4 Jun 2021 15:47:49 +0200
  105. Subject: [PATCH] platform/surface: aggregator: Allow registering notifiers
  106. without enabling events
  107. Currently, each SSAM event notifier is directly tied to one group of
  108. events. This makes sense as registering a notifier will automatically
  109. take care of enabling the corresponding event group and normally drivers
  110. only need notifications for a very limited number of events, associated
  111. with different callbacks for each group.
  112. However, there are rare cases, especially for debugging, when we want to
  113. get notifications for a whole event target category instead of just a
  114. single group of events in that category. Registering multiple notifiers,
  115. i.e. one per group, may be infeasible due to two issues: a) we might not
  116. know every event enable/disable specification as some events are
  117. auto-enabled by the EC and b) forwarding this to the same callback will
  118. lead to duplicate events as we might not know the full event
  119. specification to perform the appropriate filtering.
  120. This commit introduces observer-notifiers, which are notifiers that are
  121. not tied to a specific event group and do not attempt to manage any
  122. events. In other words, they can be registered without enabling any
  123. event group or incrementing the corresponding reference count and just
  124. act as silent observers, listening to all currently/previously enabled
  125. events based on their match-specification.
  126. Essentially, this allows us to register one single notifier for a full
  127. event target category, meaning that we can process all events of that
  128. target category in a single callback without duplication. Specifically,
  129. this will be used in the cdev debug interface to forward events to
  130. user-space via a device file from which the events can be read.
  131. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  132. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  133. Link: https://lore.kernel.org/r/20210604134755.535590-2-luzmaximilian@gmail.com
  134. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  135. Patchset: surface-sam
  136. ---
  137. .../platform/surface/aggregator/controller.c | 69 +++++++++++--------
  138. include/linux/surface_aggregator/controller.h | 17 +++++
  139. 2 files changed, 58 insertions(+), 28 deletions(-)
  140. diff --git a/drivers/platform/surface/aggregator/controller.c b/drivers/platform/surface/aggregator/controller.c
  141. index a06964aa96e7..cd3a6b77f48d 100644
  142. --- a/drivers/platform/surface/aggregator/controller.c
  143. +++ b/drivers/platform/surface/aggregator/controller.c
  144. @@ -2127,9 +2127,15 @@ int ssam_ctrl_notif_d0_entry(struct ssam_controller *ctrl)
  145. * @ctrl: The controller to register the notifier on.
  146. * @n: The event notifier to register.
  147. *
  148. - * Register an event notifier and increment the usage counter of the
  149. - * associated SAM event. If the event was previously not enabled, it will be
  150. - * enabled during this call.
  151. + * Register an event notifier. Increment the usage counter of the associated
  152. + * SAM event if the notifier is not marked as an observer. If the event is not
  153. + * marked as an observer and is currently not enabled, it will be enabled
  154. + * during this call. If the notifier is marked as an observer, no attempt will
  155. + * be made at enabling any event and no reference count will be modified.
  156. + *
  157. + * Notifiers marked as observers do not need to be associated with one specific
  158. + * event, i.e. as long as no event matching is performed, only the event target
  159. + * category needs to be set.
  160. *
  161. * Return: Returns zero on success, %-ENOSPC if there have already been
  162. * %INT_MAX notifiers for the event ID/type associated with the notifier block
  163. @@ -2138,11 +2144,10 @@ int ssam_ctrl_notif_d0_entry(struct ssam_controller *ctrl)
  164. * for the specific associated event, returns the status of the event-enable
  165. * EC-command.
  166. */
  167. -int ssam_notifier_register(struct ssam_controller *ctrl,
  168. - struct ssam_event_notifier *n)
  169. +int ssam_notifier_register(struct ssam_controller *ctrl, struct ssam_event_notifier *n)
  170. {
  171. u16 rqid = ssh_tc_to_rqid(n->event.id.target_category);
  172. - struct ssam_nf_refcount_entry *entry;
  173. + struct ssam_nf_refcount_entry *entry = NULL;
  174. struct ssam_nf_head *nf_head;
  175. struct ssam_nf *nf;
  176. int status;
  177. @@ -2155,29 +2160,32 @@ int ssam_notifier_register(struct ssam_controller *ctrl,
  178. mutex_lock(&nf->lock);
  179. - entry = ssam_nf_refcount_inc(nf, n->event.reg, n->event.id);
  180. - if (IS_ERR(entry)) {
  181. - mutex_unlock(&nf->lock);
  182. - return PTR_ERR(entry);
  183. - }
  184. + if (!(n->flags & SSAM_EVENT_NOTIFIER_OBSERVER)) {
  185. + entry = ssam_nf_refcount_inc(nf, n->event.reg, n->event.id);
  186. + if (IS_ERR(entry)) {
  187. + mutex_unlock(&nf->lock);
  188. + return PTR_ERR(entry);
  189. + }
  190. - ssam_dbg(ctrl, "enabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n",
  191. - n->event.reg.target_category, n->event.id.target_category,
  192. - n->event.id.instance, entry->refcount);
  193. + ssam_dbg(ctrl, "enabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n",
  194. + n->event.reg.target_category, n->event.id.target_category,
  195. + n->event.id.instance, entry->refcount);
  196. + }
  197. status = ssam_nfblk_insert(nf_head, &n->base);
  198. if (status) {
  199. - entry = ssam_nf_refcount_dec(nf, n->event.reg, n->event.id);
  200. - if (entry->refcount == 0)
  201. - kfree(entry);
  202. + if (entry) {
  203. + entry = ssam_nf_refcount_dec(nf, n->event.reg, n->event.id);
  204. + if (entry->refcount == 0)
  205. + kfree(entry);
  206. + }
  207. mutex_unlock(&nf->lock);
  208. return status;
  209. }
  210. - if (entry->refcount == 1) {
  211. - status = ssam_ssh_event_enable(ctrl, n->event.reg, n->event.id,
  212. - n->event.flags);
  213. + if (entry && entry->refcount == 1) {
  214. + status = ssam_ssh_event_enable(ctrl, n->event.reg, n->event.id, n->event.flags);
  215. if (status) {
  216. ssam_nfblk_remove(&n->base);
  217. kfree(ssam_nf_refcount_dec(nf, n->event.reg, n->event.id));
  218. @@ -2188,7 +2196,7 @@ int ssam_notifier_register(struct ssam_controller *ctrl,
  219. entry->flags = n->event.flags;
  220. - } else if (entry->flags != n->event.flags) {
  221. + } else if (entry && entry->flags != n->event.flags) {
  222. ssam_warn(ctrl,
  223. "inconsistent flags when enabling event: got %#04x, expected %#04x (reg: %#04x, tc: %#04x, iid: %#04x)\n",
  224. n->event.flags, entry->flags, n->event.reg.target_category,
  225. @@ -2205,17 +2213,16 @@ EXPORT_SYMBOL_GPL(ssam_notifier_register);
  226. * @ctrl: The controller the notifier has been registered on.
  227. * @n: The event notifier to unregister.
  228. *
  229. - * Unregister an event notifier and decrement the usage counter of the
  230. - * associated SAM event. If the usage counter reaches zero, the event will be
  231. - * disabled.
  232. + * Unregister an event notifier. Decrement the usage counter of the associated
  233. + * SAM event if the notifier is not marked as an observer. If the usage counter
  234. + * reaches zero, the event will be disabled.
  235. *
  236. * Return: Returns zero on success, %-ENOENT if the given notifier block has
  237. * not been registered on the controller. If the given notifier block was the
  238. * last one associated with its specific event, returns the status of the
  239. * event-disable EC-command.
  240. */
  241. -int ssam_notifier_unregister(struct ssam_controller *ctrl,
  242. - struct ssam_event_notifier *n)
  243. +int ssam_notifier_unregister(struct ssam_controller *ctrl, struct ssam_event_notifier *n)
  244. {
  245. u16 rqid = ssh_tc_to_rqid(n->event.id.target_category);
  246. struct ssam_nf_refcount_entry *entry;
  247. @@ -2236,6 +2243,13 @@ int ssam_notifier_unregister(struct ssam_controller *ctrl,
  248. return -ENOENT;
  249. }
  250. + /*
  251. + * If this is an observer notifier, do not attempt to disable the
  252. + * event, just remove it.
  253. + */
  254. + if (n->flags & SSAM_EVENT_NOTIFIER_OBSERVER)
  255. + goto remove;
  256. +
  257. entry = ssam_nf_refcount_dec(nf, n->event.reg, n->event.id);
  258. if (WARN_ON(!entry)) {
  259. /*
  260. @@ -2260,8 +2274,7 @@ int ssam_notifier_unregister(struct ssam_controller *ctrl,
  261. }
  262. if (entry->refcount == 0) {
  263. - status = ssam_ssh_event_disable(ctrl, n->event.reg, n->event.id,
  264. - n->event.flags);
  265. + status = ssam_ssh_event_disable(ctrl, n->event.reg, n->event.id, n->event.flags);
  266. kfree(entry);
  267. }
  268. diff --git a/include/linux/surface_aggregator/controller.h b/include/linux/surface_aggregator/controller.h
  269. index 0806796eabcb..cf4bb48a850e 100644
  270. --- a/include/linux/surface_aggregator/controller.h
  271. +++ b/include/linux/surface_aggregator/controller.h
  272. @@ -795,6 +795,20 @@ enum ssam_event_mask {
  273. #define SSAM_EVENT_REGISTRY_REG \
  274. SSAM_EVENT_REGISTRY(SSAM_SSH_TC_REG, 0x02, 0x01, 0x02)
  275. +/**
  276. + * enum ssam_event_notifier_flags - Flags for event notifiers.
  277. + * @SSAM_EVENT_NOTIFIER_OBSERVER:
  278. + * The corresponding notifier acts as observer. Registering a notifier
  279. + * with this flag set will not attempt to enable any event. Equally,
  280. + * unregistering will not attempt to disable any event. Note that a
  281. + * notifier with this flag may not even correspond to a certain event at
  282. + * all, only to a specific event target category. Event matching will not
  283. + * be influenced by this flag.
  284. + */
  285. +enum ssam_event_notifier_flags {
  286. + SSAM_EVENT_NOTIFIER_OBSERVER = BIT(0),
  287. +};
  288. +
  289. /**
  290. * struct ssam_event_notifier - Notifier block for SSAM events.
  291. * @base: The base notifier block with callback function and priority.
  292. @@ -803,6 +817,7 @@ enum ssam_event_mask {
  293. * @event.id: ID specifying the event.
  294. * @event.mask: Flags determining how events are matched to the notifier.
  295. * @event.flags: Flags used for enabling the event.
  296. + * @flags: Notifier flags (see &enum ssam_event_notifier_flags).
  297. */
  298. struct ssam_event_notifier {
  299. struct ssam_notifier_block base;
  300. @@ -813,6 +828,8 @@ struct ssam_event_notifier {
  301. enum ssam_event_mask mask;
  302. u8 flags;
  303. } event;
  304. +
  305. + unsigned long flags;
  306. };
  307. int ssam_notifier_register(struct ssam_controller *ctrl,
  308. --
  309. 2.32.0
  310. From ae51e1e0f612e8ce069a583e189dacdfbe7616a1 Mon Sep 17 00:00:00 2001
  311. From: Maximilian Luz <luzmaximilian@gmail.com>
  312. Date: Fri, 4 Jun 2021 15:47:50 +0200
  313. Subject: [PATCH] platform/surface: aggregator: Allow enabling of events
  314. without notifiers
  315. We can already enable and disable SAM events via one of two ways: either
  316. via a (non-observer) notifier tied to a specific event group, or a
  317. generic event enable/disable request. In some instances, however,
  318. neither method may be desirable.
  319. The first method will tie the event enable request to a specific
  320. notifier, however, when we want to receive notifications for multiple
  321. event groups of the same target category and forward this to the same
  322. notifier callback, we may receive duplicate events, i.e. one event per
  323. registered notifier. The second method will bypass the internal
  324. reference counting mechanism, meaning that a disable request will
  325. disable the event regardless of any other client driver using it, which
  326. may break the functionality of that driver.
  327. To address this problem, add new functions that allow enabling and
  328. disabling of events via the event reference counting mechanism built
  329. into the controller, without needing to register a notifier.
  330. This can then be used in combination with observer notifiers to process
  331. multiple events of the same target category without duplication in the
  332. same callback function.
  333. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  334. Link: https://lore.kernel.org/r/20210604134755.535590-3-luzmaximilian@gmail.com
  335. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  336. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  337. Patchset: surface-sam
  338. ---
  339. .../platform/surface/aggregator/controller.c | 293 +++++++++++++++---
  340. include/linux/surface_aggregator/controller.h | 8 +
  341. 2 files changed, 253 insertions(+), 48 deletions(-)
  342. diff --git a/drivers/platform/surface/aggregator/controller.c b/drivers/platform/surface/aggregator/controller.c
  343. index cd3a6b77f48d..cedd0f779f7a 100644
  344. --- a/drivers/platform/surface/aggregator/controller.c
  345. +++ b/drivers/platform/surface/aggregator/controller.c
  346. @@ -407,6 +407,31 @@ ssam_nf_refcount_dec(struct ssam_nf *nf, struct ssam_event_registry reg,
  347. return NULL;
  348. }
  349. +/**
  350. + * ssam_nf_refcount_dec_free() - Decrement reference-/activation-count of the
  351. + * given event and free its entry if the reference count reaches zero.
  352. + * @nf: The notifier system reference.
  353. + * @reg: The registry used to enable/disable the event.
  354. + * @id: The event ID.
  355. + *
  356. + * Decrements the reference-/activation-count of the specified event, freeing
  357. + * its entry if it reaches zero.
  358. + *
  359. + * Note: ``nf->lock`` must be held when calling this function.
  360. + */
  361. +static void ssam_nf_refcount_dec_free(struct ssam_nf *nf,
  362. + struct ssam_event_registry reg,
  363. + struct ssam_event_id id)
  364. +{
  365. + struct ssam_nf_refcount_entry *entry;
  366. +
  367. + lockdep_assert_held(&nf->lock);
  368. +
  369. + entry = ssam_nf_refcount_dec(nf, reg, id);
  370. + if (entry && entry->refcount == 0)
  371. + kfree(entry);
  372. +}
  373. +
  374. /**
  375. * ssam_nf_refcount_empty() - Test if the notification system has any
  376. * enabled/active events.
  377. @@ -2122,6 +2147,109 @@ int ssam_ctrl_notif_d0_entry(struct ssam_controller *ctrl)
  378. /* -- Top-level event registry interface. ----------------------------------- */
  379. +/**
  380. + * ssam_nf_refcount_enable() - Enable event for reference count entry if it has
  381. + * not already been enabled.
  382. + * @ctrl: The controller to enable the event on.
  383. + * @entry: The reference count entry for the event to be enabled.
  384. + * @flags: The flags used for enabling the event on the EC.
  385. + *
  386. + * Enable the event associated with the given reference count entry if the
  387. + * reference count equals one, i.e. the event has not previously been enabled.
  388. + * If the event has already been enabled (i.e. reference count not equal to
  389. + * one), check that the flags used for enabling match and warn about this if
  390. + * they do not.
  391. + *
  392. + * This does not modify the reference count itself, which is done with
  393. + * ssam_nf_refcount_inc() / ssam_nf_refcount_dec().
  394. + *
  395. + * Note: ``nf->lock`` must be held when calling this function.
  396. + *
  397. + * Return: Returns zero on success. If the event is enabled by this call,
  398. + * returns the status of the event-enable EC command.
  399. + */
  400. +static int ssam_nf_refcount_enable(struct ssam_controller *ctrl,
  401. + struct ssam_nf_refcount_entry *entry, u8 flags)
  402. +{
  403. + const struct ssam_event_registry reg = entry->key.reg;
  404. + const struct ssam_event_id id = entry->key.id;
  405. + struct ssam_nf *nf = &ctrl->cplt.event.notif;
  406. + int status;
  407. +
  408. + lockdep_assert_held(&nf->lock);
  409. +
  410. + ssam_dbg(ctrl, "enabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n",
  411. + reg.target_category, id.target_category, id.instance, entry->refcount);
  412. +
  413. + if (entry->refcount == 1) {
  414. + status = ssam_ssh_event_enable(ctrl, reg, id, flags);
  415. + if (status)
  416. + return status;
  417. +
  418. + entry->flags = flags;
  419. +
  420. + } else if (entry->flags != flags) {
  421. + ssam_warn(ctrl,
  422. + "inconsistent flags when enabling event: got %#04x, expected %#04x (reg: %#04x, tc: %#04x, iid: %#04x)\n",
  423. + flags, entry->flags, reg.target_category, id.target_category,
  424. + id.instance);
  425. + }
  426. +
  427. + return 0;
  428. +}
  429. +
  430. +/**
  431. + * ssam_nf_refcount_disable_free() - Disable event for reference count entry if it is
  432. + * no longer in use and free the corresponding entry.
  433. + * @ctrl: The controller to disable the event on.
  434. + * @entry: The reference count entry for the event to be disabled.
  435. + * @flags: The flags used for enabling the event on the EC.
  436. + *
  437. + * If the reference count equals zero, i.e. the event is no longer requested by
  438. + * any client, the event will be disabled and the corresponding reference count
  439. + * entry freed. The reference count entry must not be used any more after a
  440. + * call to this function.
  441. + *
  442. + * Also checks if the flags used for disabling the event match the flags used
  443. + * for enabling the event and warns if they do not (regardless of reference
  444. + * count).
  445. + *
  446. + * This does not modify the reference count itself, which is done with
  447. + * ssam_nf_refcount_inc() / ssam_nf_refcount_dec().
  448. + *
  449. + * Note: ``nf->lock`` must be held when calling this function.
  450. + *
  451. + * Return: Returns zero on success. If the event is disabled by this call,
  452. + * returns the status of the event-enable EC command.
  453. + */
  454. +static int ssam_nf_refcount_disable_free(struct ssam_controller *ctrl,
  455. + struct ssam_nf_refcount_entry *entry, u8 flags)
  456. +{
  457. + const struct ssam_event_registry reg = entry->key.reg;
  458. + const struct ssam_event_id id = entry->key.id;
  459. + struct ssam_nf *nf = &ctrl->cplt.event.notif;
  460. + int status;
  461. +
  462. + lockdep_assert_held(&nf->lock);
  463. +
  464. + ssam_dbg(ctrl, "disabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n",
  465. + reg.target_category, id.target_category, id.instance, entry->refcount);
  466. +
  467. + if (entry->flags != flags) {
  468. + ssam_warn(ctrl,
  469. + "inconsistent flags when disabling event: got %#04x, expected %#04x (reg: %#04x, tc: %#04x, iid: %#04x)\n",
  470. + flags, entry->flags, reg.target_category, id.target_category,
  471. + id.instance);
  472. + }
  473. +
  474. + if (entry->refcount == 0) {
  475. + status = ssam_ssh_event_disable(ctrl, reg, id, flags);
  476. + kfree(entry);
  477. + }
  478. +
  479. + return status;
  480. +}
  481. +
  482. /**
  483. * ssam_notifier_register() - Register an event notifier.
  484. * @ctrl: The controller to register the notifier on.
  485. @@ -2166,41 +2294,26 @@ int ssam_notifier_register(struct ssam_controller *ctrl, struct ssam_event_notif
  486. mutex_unlock(&nf->lock);
  487. return PTR_ERR(entry);
  488. }
  489. -
  490. - ssam_dbg(ctrl, "enabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n",
  491. - n->event.reg.target_category, n->event.id.target_category,
  492. - n->event.id.instance, entry->refcount);
  493. }
  494. status = ssam_nfblk_insert(nf_head, &n->base);
  495. if (status) {
  496. - if (entry) {
  497. - entry = ssam_nf_refcount_dec(nf, n->event.reg, n->event.id);
  498. - if (entry->refcount == 0)
  499. - kfree(entry);
  500. - }
  501. + if (entry)
  502. + ssam_nf_refcount_dec_free(nf, n->event.reg, n->event.id);
  503. mutex_unlock(&nf->lock);
  504. return status;
  505. }
  506. - if (entry && entry->refcount == 1) {
  507. - status = ssam_ssh_event_enable(ctrl, n->event.reg, n->event.id, n->event.flags);
  508. + if (entry) {
  509. + status = ssam_nf_refcount_enable(ctrl, entry, n->event.flags);
  510. if (status) {
  511. ssam_nfblk_remove(&n->base);
  512. - kfree(ssam_nf_refcount_dec(nf, n->event.reg, n->event.id));
  513. + ssam_nf_refcount_dec_free(nf, n->event.reg, n->event.id);
  514. mutex_unlock(&nf->lock);
  515. synchronize_srcu(&nf_head->srcu);
  516. return status;
  517. }
  518. -
  519. - entry->flags = n->event.flags;
  520. -
  521. - } else if (entry && entry->flags != n->event.flags) {
  522. - ssam_warn(ctrl,
  523. - "inconsistent flags when enabling event: got %#04x, expected %#04x (reg: %#04x, tc: %#04x, iid: %#04x)\n",
  524. - n->event.flags, entry->flags, n->event.reg.target_category,
  525. - n->event.id.target_category, n->event.id.instance);
  526. }
  527. mutex_unlock(&nf->lock);
  528. @@ -2247,35 +2360,20 @@ int ssam_notifier_unregister(struct ssam_controller *ctrl, struct ssam_event_not
  529. * If this is an observer notifier, do not attempt to disable the
  530. * event, just remove it.
  531. */
  532. - if (n->flags & SSAM_EVENT_NOTIFIER_OBSERVER)
  533. - goto remove;
  534. -
  535. - entry = ssam_nf_refcount_dec(nf, n->event.reg, n->event.id);
  536. - if (WARN_ON(!entry)) {
  537. - /*
  538. - * If this does not return an entry, there's a logic error
  539. - * somewhere: The notifier block is registered, but the event
  540. - * refcount entry is not there. Remove the notifier block
  541. - * anyways.
  542. - */
  543. - status = -ENOENT;
  544. - goto remove;
  545. - }
  546. -
  547. - ssam_dbg(ctrl, "disabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n",
  548. - n->event.reg.target_category, n->event.id.target_category,
  549. - n->event.id.instance, entry->refcount);
  550. -
  551. - if (entry->flags != n->event.flags) {
  552. - ssam_warn(ctrl,
  553. - "inconsistent flags when disabling event: got %#04x, expected %#04x (reg: %#04x, tc: %#04x, iid: %#04x)\n",
  554. - n->event.flags, entry->flags, n->event.reg.target_category,
  555. - n->event.id.target_category, n->event.id.instance);
  556. - }
  557. + if (!(n->flags & SSAM_EVENT_NOTIFIER_OBSERVER)) {
  558. + entry = ssam_nf_refcount_dec(nf, n->event.reg, n->event.id);
  559. + if (WARN_ON(!entry)) {
  560. + /*
  561. + * If this does not return an entry, there's a logic
  562. + * error somewhere: The notifier block is registered,
  563. + * but the event refcount entry is not there. Remove
  564. + * the notifier block anyways.
  565. + */
  566. + status = -ENOENT;
  567. + goto remove;
  568. + }
  569. - if (entry->refcount == 0) {
  570. - status = ssam_ssh_event_disable(ctrl, n->event.reg, n->event.id, n->event.flags);
  571. - kfree(entry);
  572. + status = ssam_nf_refcount_disable_free(ctrl, entry, n->event.flags);
  573. }
  574. remove:
  575. @@ -2287,6 +2385,105 @@ int ssam_notifier_unregister(struct ssam_controller *ctrl, struct ssam_event_not
  576. }
  577. EXPORT_SYMBOL_GPL(ssam_notifier_unregister);
  578. +/**
  579. + * ssam_controller_event_enable() - Enable the specified event.
  580. + * @ctrl: The controller to enable the event for.
  581. + * @reg: The event registry to use for enabling the event.
  582. + * @id: The event ID specifying the event to be enabled.
  583. + * @flags: The SAM event flags used for enabling the event.
  584. + *
  585. + * Increment the event reference count of the specified event. If the event has
  586. + * not been enabled previously, it will be enabled by this call.
  587. + *
  588. + * Note: In general, ssam_notifier_register() with a non-observer notifier
  589. + * should be preferred for enabling/disabling events, as this will guarantee
  590. + * proper ordering and event forwarding in case of errors during event
  591. + * enabling/disabling.
  592. + *
  593. + * Return: Returns zero on success, %-ENOSPC if the reference count for the
  594. + * specified event has reached its maximum, %-ENOMEM if the corresponding event
  595. + * entry could not be allocated. If this is the first time that this event has
  596. + * been enabled (i.e. the reference count was incremented from zero to one by
  597. + * this call), returns the status of the event-enable EC-command.
  598. + */
  599. +int ssam_controller_event_enable(struct ssam_controller *ctrl,
  600. + struct ssam_event_registry reg,
  601. + struct ssam_event_id id, u8 flags)
  602. +{
  603. + u16 rqid = ssh_tc_to_rqid(id.target_category);
  604. + struct ssam_nf *nf = &ctrl->cplt.event.notif;
  605. + struct ssam_nf_refcount_entry *entry;
  606. + int status;
  607. +
  608. + if (!ssh_rqid_is_event(rqid))
  609. + return -EINVAL;
  610. +
  611. + mutex_lock(&nf->lock);
  612. +
  613. + entry = ssam_nf_refcount_inc(nf, reg, id);
  614. + if (IS_ERR(entry)) {
  615. + mutex_unlock(&nf->lock);
  616. + return PTR_ERR(entry);
  617. + }
  618. +
  619. + status = ssam_nf_refcount_enable(ctrl, entry, flags);
  620. + if (status) {
  621. + ssam_nf_refcount_dec_free(nf, reg, id);
  622. + mutex_unlock(&nf->lock);
  623. + return status;
  624. + }
  625. +
  626. + mutex_unlock(&nf->lock);
  627. + return 0;
  628. +}
  629. +EXPORT_SYMBOL_GPL(ssam_controller_event_enable);
  630. +
  631. +/**
  632. + * ssam_controller_event_disable() - Disable the specified event.
  633. + * @ctrl: The controller to disable the event for.
  634. + * @reg: The event registry to use for disabling the event.
  635. + * @id: The event ID specifying the event to be disabled.
  636. + * @flags: The flags used when enabling the event.
  637. + *
  638. + * Decrement the reference count of the specified event. If the reference count
  639. + * reaches zero, the event will be disabled.
  640. + *
  641. + * Note: In general, ssam_notifier_register()/ssam_notifier_unregister() with a
  642. + * non-observer notifier should be preferred for enabling/disabling events, as
  643. + * this will guarantee proper ordering and event forwarding in case of errors
  644. + * during event enabling/disabling.
  645. + *
  646. + * Return: Returns zero on success, %-ENOENT if the given event has not been
  647. + * enabled on the controller. If the reference count of the event reaches zero
  648. + * during this call, returns the status of the event-disable EC-command.
  649. + */
  650. +int ssam_controller_event_disable(struct ssam_controller *ctrl,
  651. + struct ssam_event_registry reg,
  652. + struct ssam_event_id id, u8 flags)
  653. +{
  654. + u16 rqid = ssh_tc_to_rqid(id.target_category);
  655. + struct ssam_nf *nf = &ctrl->cplt.event.notif;
  656. + struct ssam_nf_refcount_entry *entry;
  657. + int status = 0;
  658. +
  659. + if (!ssh_rqid_is_event(rqid))
  660. + return -EINVAL;
  661. +
  662. + mutex_lock(&nf->lock);
  663. +
  664. + entry = ssam_nf_refcount_dec(nf, reg, id);
  665. + if (!entry) {
  666. + mutex_unlock(&nf->lock);
  667. + return -ENOENT;
  668. + }
  669. +
  670. + status = ssam_nf_refcount_disable_free(ctrl, entry, flags);
  671. +
  672. + mutex_unlock(&nf->lock);
  673. + return status;
  674. +}
  675. +EXPORT_SYMBOL_GPL(ssam_controller_event_disable);
  676. +
  677. /**
  678. * ssam_notifier_disable_registered() - Disable events for all registered
  679. * notifiers.
  680. diff --git a/include/linux/surface_aggregator/controller.h b/include/linux/surface_aggregator/controller.h
  681. index cf4bb48a850e..7965bdc669c5 100644
  682. --- a/include/linux/surface_aggregator/controller.h
  683. +++ b/include/linux/surface_aggregator/controller.h
  684. @@ -838,4 +838,12 @@ int ssam_notifier_register(struct ssam_controller *ctrl,
  685. int ssam_notifier_unregister(struct ssam_controller *ctrl,
  686. struct ssam_event_notifier *n);
  687. +int ssam_controller_event_enable(struct ssam_controller *ctrl,
  688. + struct ssam_event_registry reg,
  689. + struct ssam_event_id id, u8 flags);
  690. +
  691. +int ssam_controller_event_disable(struct ssam_controller *ctrl,
  692. + struct ssam_event_registry reg,
  693. + struct ssam_event_id id, u8 flags);
  694. +
  695. #endif /* _LINUX_SURFACE_AGGREGATOR_CONTROLLER_H */
  696. --
  697. 2.32.0
  698. From aee14cd170550e9c16fc106846056eb4d006b044 Mon Sep 17 00:00:00 2001
  699. From: Maximilian Luz <luzmaximilian@gmail.com>
  700. Date: Fri, 4 Jun 2021 15:47:51 +0200
  701. Subject: [PATCH] platform/surface: aggregator: Update copyright
  702. It's 2021, update the copyright accordingly.
  703. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  704. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  705. Link: https://lore.kernel.org/r/20210604134755.535590-4-luzmaximilian@gmail.com
  706. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  707. Patchset: surface-sam
  708. ---
  709. drivers/platform/surface/aggregator/Kconfig | 2 +-
  710. drivers/platform/surface/aggregator/Makefile | 2 +-
  711. drivers/platform/surface/aggregator/bus.c | 2 +-
  712. drivers/platform/surface/aggregator/bus.h | 2 +-
  713. drivers/platform/surface/aggregator/controller.c | 2 +-
  714. drivers/platform/surface/aggregator/controller.h | 2 +-
  715. drivers/platform/surface/aggregator/core.c | 2 +-
  716. drivers/platform/surface/aggregator/ssh_msgb.h | 2 +-
  717. drivers/platform/surface/aggregator/ssh_packet_layer.c | 2 +-
  718. drivers/platform/surface/aggregator/ssh_packet_layer.h | 2 +-
  719. drivers/platform/surface/aggregator/ssh_parser.c | 2 +-
  720. drivers/platform/surface/aggregator/ssh_parser.h | 2 +-
  721. drivers/platform/surface/aggregator/ssh_request_layer.c | 2 +-
  722. drivers/platform/surface/aggregator/ssh_request_layer.h | 2 +-
  723. drivers/platform/surface/aggregator/trace.h | 2 +-
  724. include/linux/surface_aggregator/controller.h | 2 +-
  725. include/linux/surface_aggregator/device.h | 2 +-
  726. include/linux/surface_aggregator/serial_hub.h | 2 +-
  727. 18 files changed, 18 insertions(+), 18 deletions(-)
  728. diff --git a/drivers/platform/surface/aggregator/Kconfig b/drivers/platform/surface/aggregator/Kconfig
  729. index 3aaeea9f0433..fd6dc452f3e8 100644
  730. --- a/drivers/platform/surface/aggregator/Kconfig
  731. +++ b/drivers/platform/surface/aggregator/Kconfig
  732. @@ -1,5 +1,5 @@
  733. # SPDX-License-Identifier: GPL-2.0+
  734. -# Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
  735. +# Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  736. menuconfig SURFACE_AGGREGATOR
  737. tristate "Microsoft Surface System Aggregator Module Subsystem and Drivers"
  738. diff --git a/drivers/platform/surface/aggregator/Makefile b/drivers/platform/surface/aggregator/Makefile
  739. index c112e2c7112b..c8498c41e758 100644
  740. --- a/drivers/platform/surface/aggregator/Makefile
  741. +++ b/drivers/platform/surface/aggregator/Makefile
  742. @@ -1,5 +1,5 @@
  743. # SPDX-License-Identifier: GPL-2.0+
  744. -# Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
  745. +# Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  746. # For include/trace/define_trace.h to include trace.h
  747. CFLAGS_core.o = -I$(src)
  748. diff --git a/drivers/platform/surface/aggregator/bus.c b/drivers/platform/surface/aggregator/bus.c
  749. index a9b660af0917..0169677c243e 100644
  750. --- a/drivers/platform/surface/aggregator/bus.c
  751. +++ b/drivers/platform/surface/aggregator/bus.c
  752. @@ -2,7 +2,7 @@
  753. /*
  754. * Surface System Aggregator Module bus and device integration.
  755. *
  756. - * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
  757. + * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  758. */
  759. #include <linux/device.h>
  760. diff --git a/drivers/platform/surface/aggregator/bus.h b/drivers/platform/surface/aggregator/bus.h
  761. index 7712baaed6a5..ed032c2cbdb2 100644
  762. --- a/drivers/platform/surface/aggregator/bus.h
  763. +++ b/drivers/platform/surface/aggregator/bus.h
  764. @@ -2,7 +2,7 @@
  765. /*
  766. * Surface System Aggregator Module bus and device integration.
  767. *
  768. - * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
  769. + * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  770. */
  771. #ifndef _SURFACE_AGGREGATOR_BUS_H
  772. diff --git a/drivers/platform/surface/aggregator/controller.c b/drivers/platform/surface/aggregator/controller.c
  773. index cedd0f779f7a..6646f4d6e10d 100644
  774. --- a/drivers/platform/surface/aggregator/controller.c
  775. +++ b/drivers/platform/surface/aggregator/controller.c
  776. @@ -2,7 +2,7 @@
  777. /*
  778. * Main SSAM/SSH controller structure and functionality.
  779. *
  780. - * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
  781. + * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  782. */
  783. #include <linux/acpi.h>
  784. diff --git a/drivers/platform/surface/aggregator/controller.h b/drivers/platform/surface/aggregator/controller.h
  785. index 8297d34e7489..a0963c3562ff 100644
  786. --- a/drivers/platform/surface/aggregator/controller.h
  787. +++ b/drivers/platform/surface/aggregator/controller.h
  788. @@ -2,7 +2,7 @@
  789. /*
  790. * Main SSAM/SSH controller structure and functionality.
  791. *
  792. - * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
  793. + * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  794. */
  795. #ifndef _SURFACE_AGGREGATOR_CONTROLLER_H
  796. diff --git a/drivers/platform/surface/aggregator/core.c b/drivers/platform/surface/aggregator/core.c
  797. index 8dc2c267bcd6..5d780e55f4a1 100644
  798. --- a/drivers/platform/surface/aggregator/core.c
  799. +++ b/drivers/platform/surface/aggregator/core.c
  800. @@ -7,7 +7,7 @@
  801. * Handles communication via requests as well as enabling, disabling, and
  802. * relaying of events.
  803. *
  804. - * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
  805. + * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  806. */
  807. #include <linux/acpi.h>
  808. diff --git a/drivers/platform/surface/aggregator/ssh_msgb.h b/drivers/platform/surface/aggregator/ssh_msgb.h
  809. index 1221f642dda1..e562958ffdf0 100644
  810. --- a/drivers/platform/surface/aggregator/ssh_msgb.h
  811. +++ b/drivers/platform/surface/aggregator/ssh_msgb.h
  812. @@ -2,7 +2,7 @@
  813. /*
  814. * SSH message builder functions.
  815. *
  816. - * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
  817. + * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  818. */
  819. #ifndef _SURFACE_AGGREGATOR_SSH_MSGB_H
  820. diff --git a/drivers/platform/surface/aggregator/ssh_packet_layer.c b/drivers/platform/surface/aggregator/ssh_packet_layer.c
  821. index 15d96eac6811..5e08049fc3ac 100644
  822. --- a/drivers/platform/surface/aggregator/ssh_packet_layer.c
  823. +++ b/drivers/platform/surface/aggregator/ssh_packet_layer.c
  824. @@ -2,7 +2,7 @@
  825. /*
  826. * SSH packet transport layer.
  827. *
  828. - * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
  829. + * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  830. */
  831. #include <asm/unaligned.h>
  832. diff --git a/drivers/platform/surface/aggregator/ssh_packet_layer.h b/drivers/platform/surface/aggregator/ssh_packet_layer.h
  833. index e8757d03f279..2eb329f0b91a 100644
  834. --- a/drivers/platform/surface/aggregator/ssh_packet_layer.h
  835. +++ b/drivers/platform/surface/aggregator/ssh_packet_layer.h
  836. @@ -2,7 +2,7 @@
  837. /*
  838. * SSH packet transport layer.
  839. *
  840. - * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
  841. + * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  842. */
  843. #ifndef _SURFACE_AGGREGATOR_SSH_PACKET_LAYER_H
  844. diff --git a/drivers/platform/surface/aggregator/ssh_parser.c b/drivers/platform/surface/aggregator/ssh_parser.c
  845. index e2dead8de94a..b77912f8f13b 100644
  846. --- a/drivers/platform/surface/aggregator/ssh_parser.c
  847. +++ b/drivers/platform/surface/aggregator/ssh_parser.c
  848. @@ -2,7 +2,7 @@
  849. /*
  850. * SSH message parser.
  851. *
  852. - * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
  853. + * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  854. */
  855. #include <asm/unaligned.h>
  856. diff --git a/drivers/platform/surface/aggregator/ssh_parser.h b/drivers/platform/surface/aggregator/ssh_parser.h
  857. index 63c38d350988..3bd6e180fd16 100644
  858. --- a/drivers/platform/surface/aggregator/ssh_parser.h
  859. +++ b/drivers/platform/surface/aggregator/ssh_parser.h
  860. @@ -2,7 +2,7 @@
  861. /*
  862. * SSH message parser.
  863. *
  864. - * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
  865. + * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  866. */
  867. #ifndef _SURFACE_AGGREGATOR_SSH_PARSER_H
  868. diff --git a/drivers/platform/surface/aggregator/ssh_request_layer.c b/drivers/platform/surface/aggregator/ssh_request_layer.c
  869. index 52a83a8fcf82..bfe1aaf38065 100644
  870. --- a/drivers/platform/surface/aggregator/ssh_request_layer.c
  871. +++ b/drivers/platform/surface/aggregator/ssh_request_layer.c
  872. @@ -2,7 +2,7 @@
  873. /*
  874. * SSH request transport layer.
  875. *
  876. - * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
  877. + * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  878. */
  879. #include <asm/unaligned.h>
  880. diff --git a/drivers/platform/surface/aggregator/ssh_request_layer.h b/drivers/platform/surface/aggregator/ssh_request_layer.h
  881. index cb35815858d1..9c3cbae2d4bd 100644
  882. --- a/drivers/platform/surface/aggregator/ssh_request_layer.h
  883. +++ b/drivers/platform/surface/aggregator/ssh_request_layer.h
  884. @@ -2,7 +2,7 @@
  885. /*
  886. * SSH request transport layer.
  887. *
  888. - * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
  889. + * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  890. */
  891. #ifndef _SURFACE_AGGREGATOR_SSH_REQUEST_LAYER_H
  892. diff --git a/drivers/platform/surface/aggregator/trace.h b/drivers/platform/surface/aggregator/trace.h
  893. index eb332bb53ae4..de64cf169060 100644
  894. --- a/drivers/platform/surface/aggregator/trace.h
  895. +++ b/drivers/platform/surface/aggregator/trace.h
  896. @@ -2,7 +2,7 @@
  897. /*
  898. * Trace points for SSAM/SSH.
  899. *
  900. - * Copyright (C) 2020 Maximilian Luz <luzmaximilian@gmail.com>
  901. + * Copyright (C) 2020-2021 Maximilian Luz <luzmaximilian@gmail.com>
  902. */
  903. #undef TRACE_SYSTEM
  904. diff --git a/include/linux/surface_aggregator/controller.h b/include/linux/surface_aggregator/controller.h
  905. index 7965bdc669c5..068e1982ad37 100644
  906. --- a/include/linux/surface_aggregator/controller.h
  907. +++ b/include/linux/surface_aggregator/controller.h
  908. @@ -6,7 +6,7 @@
  909. * managing access and communication to and from the SSAM EC, as well as main
  910. * communication structures and definitions.
  911. *
  912. - * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
  913. + * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  914. */
  915. #ifndef _LINUX_SURFACE_AGGREGATOR_CONTROLLER_H
  916. diff --git a/include/linux/surface_aggregator/device.h b/include/linux/surface_aggregator/device.h
  917. index 6ff9c58b3e17..f636c5310321 100644
  918. --- a/include/linux/surface_aggregator/device.h
  919. +++ b/include/linux/surface_aggregator/device.h
  920. @@ -7,7 +7,7 @@
  921. * Provides support for non-platform/non-ACPI SSAM clients via dedicated
  922. * subsystem.
  923. *
  924. - * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
  925. + * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  926. */
  927. #ifndef _LINUX_SURFACE_AGGREGATOR_DEVICE_H
  928. diff --git a/include/linux/surface_aggregator/serial_hub.h b/include/linux/surface_aggregator/serial_hub.h
  929. index 64276fbfa1d5..c3de43edcffa 100644
  930. --- a/include/linux/surface_aggregator/serial_hub.h
  931. +++ b/include/linux/surface_aggregator/serial_hub.h
  932. @@ -6,7 +6,7 @@
  933. * Surface System Aggregator Module (SSAM). Provides the interface for basic
  934. * packet- and request-based communication with the SSAM EC via SSH.
  935. *
  936. - * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
  937. + * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  938. */
  939. #ifndef _LINUX_SURFACE_AGGREGATOR_SERIAL_HUB_H
  940. --
  941. 2.32.0
  942. From 3ef2675ab9aea4ff11b29e0250165bd1cbcdda46 Mon Sep 17 00:00:00 2001
  943. From: Maximilian Luz <luzmaximilian@gmail.com>
  944. Date: Fri, 4 Jun 2021 15:47:52 +0200
  945. Subject: [PATCH] platform/surface: aggregator_cdev: Add support for forwarding
  946. events to user-space
  947. Currently, debugging unknown events requires writing a custom driver.
  948. This is somewhat difficult, slow to adapt, and not entirely
  949. user-friendly for quickly trying to figure out things on devices of some
  950. third-party user. We can do better. We already have a user-space
  951. interface intended for debugging SAM EC requests, so let's add support
  952. for receiving events to that.
  953. This commit provides support for receiving events by reading from the
  954. controller file. It additionally introduces two new IOCTLs to control
  955. which event categories will be forwarded. Specifically, a user-space
  956. client can specify which target categories it wants to receive events
  957. from by registering the corresponding notifier(s) via the IOCTLs and
  958. after that, read the received events by reading from the controller
  959. device.
  960. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  961. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  962. Link: https://lore.kernel.org/r/20210604134755.535590-5-luzmaximilian@gmail.com
  963. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  964. Patchset: surface-sam
  965. ---
  966. .../userspace-api/ioctl/ioctl-number.rst | 2 +-
  967. .../surface/surface_aggregator_cdev.c | 460 +++++++++++++++++-
  968. include/uapi/linux/surface_aggregator/cdev.h | 41 +-
  969. 3 files changed, 477 insertions(+), 26 deletions(-)
  970. diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst
  971. index 9bfc2b510c64..1409e40e6345 100644
  972. --- a/Documentation/userspace-api/ioctl/ioctl-number.rst
  973. +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst
  974. @@ -325,7 +325,7 @@ Code Seq# Include File Comments
  975. 0xA3 90-9F linux/dtlk.h
  976. 0xA4 00-1F uapi/linux/tee.h Generic TEE subsystem
  977. 0xA4 00-1F uapi/asm/sgx.h <mailto:linux-sgx@vger.kernel.org>
  978. -0xA5 01 linux/surface_aggregator/cdev.h Microsoft Surface Platform System Aggregator
  979. +0xA5 01-05 linux/surface_aggregator/cdev.h Microsoft Surface Platform System Aggregator
  980. <mailto:luzmaximilian@gmail.com>
  981. 0xA5 20-2F linux/surface_aggregator/dtx.h Microsoft Surface DTX driver
  982. <mailto:luzmaximilian@gmail.com>
  983. diff --git a/drivers/platform/surface/surface_aggregator_cdev.c b/drivers/platform/surface/surface_aggregator_cdev.c
  984. index 79e28fab7e40..dcda377896b7 100644
  985. --- a/drivers/platform/surface/surface_aggregator_cdev.c
  986. +++ b/drivers/platform/surface/surface_aggregator_cdev.c
  987. @@ -3,29 +3,69 @@
  988. * Provides user-space access to the SSAM EC via the /dev/surface/aggregator
  989. * misc device. Intended for debugging and development.
  990. *
  991. - * Copyright (C) 2020 Maximilian Luz <luzmaximilian@gmail.com>
  992. + * Copyright (C) 2020-2021 Maximilian Luz <luzmaximilian@gmail.com>
  993. */
  994. #include <linux/fs.h>
  995. +#include <linux/ioctl.h>
  996. #include <linux/kernel.h>
  997. +#include <linux/kfifo.h>
  998. #include <linux/kref.h>
  999. #include <linux/miscdevice.h>
  1000. #include <linux/module.h>
  1001. #include <linux/platform_device.h>
  1002. +#include <linux/poll.h>
  1003. #include <linux/rwsem.h>
  1004. #include <linux/slab.h>
  1005. #include <linux/uaccess.h>
  1006. +#include <linux/vmalloc.h>
  1007. #include <linux/surface_aggregator/cdev.h>
  1008. #include <linux/surface_aggregator/controller.h>
  1009. +#include <linux/surface_aggregator/serial_hub.h>
  1010. #define SSAM_CDEV_DEVICE_NAME "surface_aggregator_cdev"
  1011. +
  1012. +/* -- Main structures. ------------------------------------------------------ */
  1013. +
  1014. +enum ssam_cdev_device_state {
  1015. + SSAM_CDEV_DEVICE_SHUTDOWN_BIT = BIT(0),
  1016. +};
  1017. +
  1018. struct ssam_cdev {
  1019. struct kref kref;
  1020. struct rw_semaphore lock;
  1021. +
  1022. + struct device *dev;
  1023. struct ssam_controller *ctrl;
  1024. struct miscdevice mdev;
  1025. + unsigned long flags;
  1026. +
  1027. + struct rw_semaphore client_lock; /* Guards client list. */
  1028. + struct list_head client_list;
  1029. +};
  1030. +
  1031. +struct ssam_cdev_client;
  1032. +
  1033. +struct ssam_cdev_notifier {
  1034. + struct ssam_cdev_client *client;
  1035. + struct ssam_event_notifier nf;
  1036. +};
  1037. +
  1038. +struct ssam_cdev_client {
  1039. + struct ssam_cdev *cdev;
  1040. + struct list_head node;
  1041. +
  1042. + struct mutex notifier_lock; /* Guards notifier access for registration */
  1043. + struct ssam_cdev_notifier *notifier[SSH_NUM_EVENTS];
  1044. +
  1045. + struct mutex read_lock; /* Guards FIFO buffer read access */
  1046. + struct mutex write_lock; /* Guards FIFO buffer write access */
  1047. + DECLARE_KFIFO(buffer, u8, 4096);
  1048. +
  1049. + wait_queue_head_t waitq;
  1050. + struct fasync_struct *fasync;
  1051. };
  1052. static void __ssam_cdev_release(struct kref *kref)
  1053. @@ -47,24 +87,169 @@ static void ssam_cdev_put(struct ssam_cdev *cdev)
  1054. kref_put(&cdev->kref, __ssam_cdev_release);
  1055. }
  1056. -static int ssam_cdev_device_open(struct inode *inode, struct file *filp)
  1057. +
  1058. +/* -- Notifier handling. ---------------------------------------------------- */
  1059. +
  1060. +static u32 ssam_cdev_notifier(struct ssam_event_notifier *nf, const struct ssam_event *in)
  1061. {
  1062. - struct miscdevice *mdev = filp->private_data;
  1063. - struct ssam_cdev *cdev = container_of(mdev, struct ssam_cdev, mdev);
  1064. + struct ssam_cdev_notifier *cdev_nf = container_of(nf, struct ssam_cdev_notifier, nf);
  1065. + struct ssam_cdev_client *client = cdev_nf->client;
  1066. + struct ssam_cdev_event event;
  1067. + size_t n = struct_size(&event, data, in->length);
  1068. +
  1069. + /* Translate event. */
  1070. + event.target_category = in->target_category;
  1071. + event.target_id = in->target_id;
  1072. + event.command_id = in->command_id;
  1073. + event.instance_id = in->instance_id;
  1074. + event.length = in->length;
  1075. +
  1076. + mutex_lock(&client->write_lock);
  1077. +
  1078. + /* Make sure we have enough space. */
  1079. + if (kfifo_avail(&client->buffer) < n) {
  1080. + dev_warn(client->cdev->dev,
  1081. + "buffer full, dropping event (tc: %#04x, tid: %#04x, cid: %#04x, iid: %#04x)\n",
  1082. + in->target_category, in->target_id, in->command_id, in->instance_id);
  1083. + mutex_unlock(&client->write_lock);
  1084. + return 0;
  1085. + }
  1086. - filp->private_data = ssam_cdev_get(cdev);
  1087. - return stream_open(inode, filp);
  1088. + /* Copy event header and payload. */
  1089. + kfifo_in(&client->buffer, (const u8 *)&event, struct_size(&event, data, 0));
  1090. + kfifo_in(&client->buffer, &in->data[0], in->length);
  1091. +
  1092. + mutex_unlock(&client->write_lock);
  1093. +
  1094. + /* Notify waiting readers. */
  1095. + kill_fasync(&client->fasync, SIGIO, POLL_IN);
  1096. + wake_up_interruptible(&client->waitq);
  1097. +
  1098. + /*
  1099. + * Don't mark events as handled, this is the job of a proper driver and
  1100. + * not the debugging interface.
  1101. + */
  1102. + return 0;
  1103. }
  1104. -static int ssam_cdev_device_release(struct inode *inode, struct file *filp)
  1105. +static int ssam_cdev_notifier_register(struct ssam_cdev_client *client, u8 tc, int priority)
  1106. {
  1107. - ssam_cdev_put(filp->private_data);
  1108. - return 0;
  1109. + const u16 rqid = ssh_tc_to_rqid(tc);
  1110. + const u16 event = ssh_rqid_to_event(rqid);
  1111. + struct ssam_cdev_notifier *nf;
  1112. + int status;
  1113. +
  1114. + /* Validate notifier target category. */
  1115. + if (!ssh_rqid_is_event(rqid))
  1116. + return -EINVAL;
  1117. +
  1118. + mutex_lock(&client->notifier_lock);
  1119. +
  1120. + /* Check if the notifier has already been registered. */
  1121. + if (client->notifier[event]) {
  1122. + mutex_unlock(&client->notifier_lock);
  1123. + return -EEXIST;
  1124. + }
  1125. +
  1126. + /* Allocate new notifier. */
  1127. + nf = kzalloc(sizeof(*nf), GFP_KERNEL);
  1128. + if (!nf) {
  1129. + mutex_unlock(&client->notifier_lock);
  1130. + return -ENOMEM;
  1131. + }
  1132. +
  1133. + /*
  1134. + * Create a dummy notifier with the minimal required fields for
  1135. + * observer registration. Note that we can skip fully specifying event
  1136. + * and registry here as we do not need any matching and use silent
  1137. + * registration, which does not enable the corresponding event.
  1138. + */
  1139. + nf->client = client;
  1140. + nf->nf.base.fn = ssam_cdev_notifier;
  1141. + nf->nf.base.priority = priority;
  1142. + nf->nf.event.id.target_category = tc;
  1143. + nf->nf.event.mask = 0; /* Do not do any matching. */
  1144. + nf->nf.flags = SSAM_EVENT_NOTIFIER_OBSERVER;
  1145. +
  1146. + /* Register notifier. */
  1147. + status = ssam_notifier_register(client->cdev->ctrl, &nf->nf);
  1148. + if (status)
  1149. + kfree(nf);
  1150. + else
  1151. + client->notifier[event] = nf;
  1152. +
  1153. + mutex_unlock(&client->notifier_lock);
  1154. + return status;
  1155. }
  1156. -static long ssam_cdev_request(struct ssam_cdev *cdev, unsigned long arg)
  1157. +static int ssam_cdev_notifier_unregister(struct ssam_cdev_client *client, u8 tc)
  1158. +{
  1159. + const u16 rqid = ssh_tc_to_rqid(tc);
  1160. + const u16 event = ssh_rqid_to_event(rqid);
  1161. + int status;
  1162. +
  1163. + /* Validate notifier target category. */
  1164. + if (!ssh_rqid_is_event(rqid))
  1165. + return -EINVAL;
  1166. +
  1167. + mutex_lock(&client->notifier_lock);
  1168. +
  1169. + /* Check if the notifier is currently registered. */
  1170. + if (!client->notifier[event]) {
  1171. + mutex_unlock(&client->notifier_lock);
  1172. + return -ENOENT;
  1173. + }
  1174. +
  1175. + /* Unregister and free notifier. */
  1176. + status = ssam_notifier_unregister(client->cdev->ctrl, &client->notifier[event]->nf);
  1177. + kfree(client->notifier[event]);
  1178. + client->notifier[event] = NULL;
  1179. +
  1180. + mutex_unlock(&client->notifier_lock);
  1181. + return status;
  1182. +}
  1183. +
  1184. +static void ssam_cdev_notifier_unregister_all(struct ssam_cdev_client *client)
  1185. +{
  1186. + int i;
  1187. +
  1188. + down_read(&client->cdev->lock);
  1189. +
  1190. + /*
  1191. + * This function may be used during shutdown, thus we need to test for
  1192. + * cdev->ctrl instead of the SSAM_CDEV_DEVICE_SHUTDOWN_BIT bit.
  1193. + */
  1194. + if (client->cdev->ctrl) {
  1195. + for (i = 0; i < SSH_NUM_EVENTS; i++)
  1196. + ssam_cdev_notifier_unregister(client, i + 1);
  1197. +
  1198. + } else {
  1199. + int count = 0;
  1200. +
  1201. + /*
  1202. + * Device has been shut down. Any notifier remaining is a bug,
  1203. + * so warn about that as this would otherwise hardly be
  1204. + * noticeable. Nevertheless, free them as well.
  1205. + */
  1206. + mutex_lock(&client->notifier_lock);
  1207. + for (i = 0; i < SSH_NUM_EVENTS; i++) {
  1208. + count += !!(client->notifier[i]);
  1209. + kfree(client->notifier[i]);
  1210. + client->notifier[i] = NULL;
  1211. + }
  1212. + mutex_unlock(&client->notifier_lock);
  1213. +
  1214. + WARN_ON(count > 0);
  1215. + }
  1216. +
  1217. + up_read(&client->cdev->lock);
  1218. +}
  1219. +
  1220. +
  1221. +/* -- IOCTL functions. ------------------------------------------------------ */
  1222. +
  1223. +static long ssam_cdev_request(struct ssam_cdev_client *client, struct ssam_cdev_request __user *r)
  1224. {
  1225. - struct ssam_cdev_request __user *r;
  1226. struct ssam_cdev_request rqst;
  1227. struct ssam_request spec = {};
  1228. struct ssam_response rsp = {};
  1229. @@ -72,7 +257,6 @@ static long ssam_cdev_request(struct ssam_cdev *cdev, unsigned long arg)
  1230. void __user *rspdata;
  1231. int status = 0, ret = 0, tmp;
  1232. - r = (struct ssam_cdev_request __user *)arg;
  1233. ret = copy_struct_from_user(&rqst, sizeof(rqst), r, sizeof(*r));
  1234. if (ret)
  1235. goto out;
  1236. @@ -152,7 +336,7 @@ static long ssam_cdev_request(struct ssam_cdev *cdev, unsigned long arg)
  1237. }
  1238. /* Perform request. */
  1239. - status = ssam_request_sync(cdev->ctrl, &spec, &rsp);
  1240. + status = ssam_request_sync(client->cdev->ctrl, &spec, &rsp);
  1241. if (status)
  1242. goto out;
  1243. @@ -177,48 +361,247 @@ static long ssam_cdev_request(struct ssam_cdev *cdev, unsigned long arg)
  1244. return ret;
  1245. }
  1246. -static long __ssam_cdev_device_ioctl(struct ssam_cdev *cdev, unsigned int cmd,
  1247. +static long ssam_cdev_notif_register(struct ssam_cdev_client *client,
  1248. + const struct ssam_cdev_notifier_desc __user *d)
  1249. +{
  1250. + struct ssam_cdev_notifier_desc desc;
  1251. + long ret;
  1252. +
  1253. + ret = copy_struct_from_user(&desc, sizeof(desc), d, sizeof(*d));
  1254. + if (ret)
  1255. + return ret;
  1256. +
  1257. + return ssam_cdev_notifier_register(client, desc.target_category, desc.priority);
  1258. +}
  1259. +
  1260. +static long ssam_cdev_notif_unregister(struct ssam_cdev_client *client,
  1261. + const struct ssam_cdev_notifier_desc __user *d)
  1262. +{
  1263. + struct ssam_cdev_notifier_desc desc;
  1264. + long ret;
  1265. +
  1266. + ret = copy_struct_from_user(&desc, sizeof(desc), d, sizeof(*d));
  1267. + if (ret)
  1268. + return ret;
  1269. +
  1270. + return ssam_cdev_notifier_unregister(client, desc.target_category);
  1271. +}
  1272. +
  1273. +
  1274. +/* -- File operations. ------------------------------------------------------ */
  1275. +
  1276. +static int ssam_cdev_device_open(struct inode *inode, struct file *filp)
  1277. +{
  1278. + struct miscdevice *mdev = filp->private_data;
  1279. + struct ssam_cdev_client *client;
  1280. + struct ssam_cdev *cdev = container_of(mdev, struct ssam_cdev, mdev);
  1281. +
  1282. + /* Initialize client */
  1283. + client = vzalloc(sizeof(*client));
  1284. + if (!client)
  1285. + return -ENOMEM;
  1286. +
  1287. + client->cdev = ssam_cdev_get(cdev);
  1288. +
  1289. + INIT_LIST_HEAD(&client->node);
  1290. +
  1291. + mutex_init(&client->notifier_lock);
  1292. +
  1293. + mutex_init(&client->read_lock);
  1294. + mutex_init(&client->write_lock);
  1295. + INIT_KFIFO(client->buffer);
  1296. + init_waitqueue_head(&client->waitq);
  1297. +
  1298. + filp->private_data = client;
  1299. +
  1300. + /* Attach client. */
  1301. + down_write(&cdev->client_lock);
  1302. +
  1303. + if (test_bit(SSAM_CDEV_DEVICE_SHUTDOWN_BIT, &cdev->flags)) {
  1304. + up_write(&cdev->client_lock);
  1305. + mutex_destroy(&client->write_lock);
  1306. + mutex_destroy(&client->read_lock);
  1307. + mutex_destroy(&client->notifier_lock);
  1308. + ssam_cdev_put(client->cdev);
  1309. + vfree(client);
  1310. + return -ENODEV;
  1311. + }
  1312. + list_add_tail(&client->node, &cdev->client_list);
  1313. +
  1314. + up_write(&cdev->client_lock);
  1315. +
  1316. + stream_open(inode, filp);
  1317. + return 0;
  1318. +}
  1319. +
  1320. +static int ssam_cdev_device_release(struct inode *inode, struct file *filp)
  1321. +{
  1322. + struct ssam_cdev_client *client = filp->private_data;
  1323. +
  1324. + /* Force-unregister all remaining notifiers of this client. */
  1325. + ssam_cdev_notifier_unregister_all(client);
  1326. +
  1327. + /* Detach client. */
  1328. + down_write(&client->cdev->client_lock);
  1329. + list_del(&client->node);
  1330. + up_write(&client->cdev->client_lock);
  1331. +
  1332. + /* Free client. */
  1333. + mutex_destroy(&client->write_lock);
  1334. + mutex_destroy(&client->read_lock);
  1335. +
  1336. + mutex_destroy(&client->notifier_lock);
  1337. +
  1338. + ssam_cdev_put(client->cdev);
  1339. + vfree(client);
  1340. +
  1341. + return 0;
  1342. +}
  1343. +
  1344. +static long __ssam_cdev_device_ioctl(struct ssam_cdev_client *client, unsigned int cmd,
  1345. unsigned long arg)
  1346. {
  1347. switch (cmd) {
  1348. case SSAM_CDEV_REQUEST:
  1349. - return ssam_cdev_request(cdev, arg);
  1350. + return ssam_cdev_request(client, (struct ssam_cdev_request __user *)arg);
  1351. +
  1352. + case SSAM_CDEV_NOTIF_REGISTER:
  1353. + return ssam_cdev_notif_register(client,
  1354. + (struct ssam_cdev_notifier_desc __user *)arg);
  1355. +
  1356. + case SSAM_CDEV_NOTIF_UNREGISTER:
  1357. + return ssam_cdev_notif_unregister(client,
  1358. + (struct ssam_cdev_notifier_desc __user *)arg);
  1359. default:
  1360. return -ENOTTY;
  1361. }
  1362. }
  1363. -static long ssam_cdev_device_ioctl(struct file *file, unsigned int cmd,
  1364. - unsigned long arg)
  1365. +static long ssam_cdev_device_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  1366. {
  1367. - struct ssam_cdev *cdev = file->private_data;
  1368. + struct ssam_cdev_client *client = file->private_data;
  1369. long status;
  1370. /* Ensure that controller is valid for as long as we need it. */
  1371. + if (down_read_killable(&client->cdev->lock))
  1372. + return -ERESTARTSYS;
  1373. +
  1374. + if (test_bit(SSAM_CDEV_DEVICE_SHUTDOWN_BIT, &client->cdev->flags)) {
  1375. + up_read(&client->cdev->lock);
  1376. + return -ENODEV;
  1377. + }
  1378. +
  1379. + status = __ssam_cdev_device_ioctl(client, cmd, arg);
  1380. +
  1381. + up_read(&client->cdev->lock);
  1382. + return status;
  1383. +}
  1384. +
  1385. +static ssize_t ssam_cdev_read(struct file *file, char __user *buf, size_t count, loff_t *offs)
  1386. +{
  1387. + struct ssam_cdev_client *client = file->private_data;
  1388. + struct ssam_cdev *cdev = client->cdev;
  1389. + unsigned int copied;
  1390. + int status = 0;
  1391. +
  1392. if (down_read_killable(&cdev->lock))
  1393. return -ERESTARTSYS;
  1394. - if (!cdev->ctrl) {
  1395. + /* Make sure we're not shut down. */
  1396. + if (test_bit(SSAM_CDEV_DEVICE_SHUTDOWN_BIT, &cdev->flags)) {
  1397. up_read(&cdev->lock);
  1398. return -ENODEV;
  1399. }
  1400. - status = __ssam_cdev_device_ioctl(cdev, cmd, arg);
  1401. + do {
  1402. + /* Check availability, wait if necessary. */
  1403. + if (kfifo_is_empty(&client->buffer)) {
  1404. + up_read(&cdev->lock);
  1405. +
  1406. + if (file->f_flags & O_NONBLOCK)
  1407. + return -EAGAIN;
  1408. +
  1409. + status = wait_event_interruptible(client->waitq,
  1410. + !kfifo_is_empty(&client->buffer) ||
  1411. + test_bit(SSAM_CDEV_DEVICE_SHUTDOWN_BIT,
  1412. + &cdev->flags));
  1413. + if (status < 0)
  1414. + return status;
  1415. +
  1416. + if (down_read_killable(&cdev->lock))
  1417. + return -ERESTARTSYS;
  1418. +
  1419. + /* Need to check that we're not shut down again. */
  1420. + if (test_bit(SSAM_CDEV_DEVICE_SHUTDOWN_BIT, &cdev->flags)) {
  1421. + up_read(&cdev->lock);
  1422. + return -ENODEV;
  1423. + }
  1424. + }
  1425. +
  1426. + /* Try to read from FIFO. */
  1427. + if (mutex_lock_interruptible(&client->read_lock)) {
  1428. + up_read(&cdev->lock);
  1429. + return -ERESTARTSYS;
  1430. + }
  1431. +
  1432. + status = kfifo_to_user(&client->buffer, buf, count, &copied);
  1433. + mutex_unlock(&client->read_lock);
  1434. +
  1435. + if (status < 0) {
  1436. + up_read(&cdev->lock);
  1437. + return status;
  1438. + }
  1439. +
  1440. + /* We might not have gotten anything, check this here. */
  1441. + if (copied == 0 && (file->f_flags & O_NONBLOCK)) {
  1442. + up_read(&cdev->lock);
  1443. + return -EAGAIN;
  1444. + }
  1445. + } while (copied == 0);
  1446. up_read(&cdev->lock);
  1447. - return status;
  1448. + return copied;
  1449. +}
  1450. +
  1451. +static __poll_t ssam_cdev_poll(struct file *file, struct poll_table_struct *pt)
  1452. +{
  1453. + struct ssam_cdev_client *client = file->private_data;
  1454. + __poll_t events = 0;
  1455. +
  1456. + if (test_bit(SSAM_CDEV_DEVICE_SHUTDOWN_BIT, &client->cdev->flags))
  1457. + return EPOLLHUP | EPOLLERR;
  1458. +
  1459. + poll_wait(file, &client->waitq, pt);
  1460. +
  1461. + if (!kfifo_is_empty(&client->buffer))
  1462. + events |= EPOLLIN | EPOLLRDNORM;
  1463. +
  1464. + return events;
  1465. +}
  1466. +
  1467. +static int ssam_cdev_fasync(int fd, struct file *file, int on)
  1468. +{
  1469. + struct ssam_cdev_client *client = file->private_data;
  1470. +
  1471. + return fasync_helper(fd, file, on, &client->fasync);
  1472. }
  1473. static const struct file_operations ssam_controller_fops = {
  1474. .owner = THIS_MODULE,
  1475. .open = ssam_cdev_device_open,
  1476. .release = ssam_cdev_device_release,
  1477. + .read = ssam_cdev_read,
  1478. + .poll = ssam_cdev_poll,
  1479. + .fasync = ssam_cdev_fasync,
  1480. .unlocked_ioctl = ssam_cdev_device_ioctl,
  1481. .compat_ioctl = ssam_cdev_device_ioctl,
  1482. - .llseek = noop_llseek,
  1483. + .llseek = no_llseek,
  1484. };
  1485. +
  1486. +/* -- Device and driver setup ----------------------------------------------- */
  1487. +
  1488. static int ssam_dbg_device_probe(struct platform_device *pdev)
  1489. {
  1490. struct ssam_controller *ctrl;
  1491. @@ -236,6 +619,7 @@ static int ssam_dbg_device_probe(struct platform_device *pdev)
  1492. kref_init(&cdev->kref);
  1493. init_rwsem(&cdev->lock);
  1494. cdev->ctrl = ctrl;
  1495. + cdev->dev = &pdev->dev;
  1496. cdev->mdev.parent = &pdev->dev;
  1497. cdev->mdev.minor = MISC_DYNAMIC_MINOR;
  1498. @@ -243,6 +627,9 @@ static int ssam_dbg_device_probe(struct platform_device *pdev)
  1499. cdev->mdev.nodename = "surface/aggregator";
  1500. cdev->mdev.fops = &ssam_controller_fops;
  1501. + init_rwsem(&cdev->client_lock);
  1502. + INIT_LIST_HEAD(&cdev->client_list);
  1503. +
  1504. status = misc_register(&cdev->mdev);
  1505. if (status) {
  1506. kfree(cdev);
  1507. @@ -256,8 +643,32 @@ static int ssam_dbg_device_probe(struct platform_device *pdev)
  1508. static int ssam_dbg_device_remove(struct platform_device *pdev)
  1509. {
  1510. struct ssam_cdev *cdev = platform_get_drvdata(pdev);
  1511. + struct ssam_cdev_client *client;
  1512. - misc_deregister(&cdev->mdev);
  1513. + /*
  1514. + * Mark device as shut-down. Prevent new clients from being added and
  1515. + * new operations from being executed.
  1516. + */
  1517. + set_bit(SSAM_CDEV_DEVICE_SHUTDOWN_BIT, &cdev->flags);
  1518. +
  1519. + down_write(&cdev->client_lock);
  1520. +
  1521. + /* Remove all notifiers registered by us. */
  1522. + list_for_each_entry(client, &cdev->client_list, node) {
  1523. + ssam_cdev_notifier_unregister_all(client);
  1524. + }
  1525. +
  1526. + /* Wake up async clients. */
  1527. + list_for_each_entry(client, &cdev->client_list, node) {
  1528. + kill_fasync(&client->fasync, SIGIO, POLL_HUP);
  1529. + }
  1530. +
  1531. + /* Wake up blocking clients. */
  1532. + list_for_each_entry(client, &cdev->client_list, node) {
  1533. + wake_up_interruptible(&client->waitq);
  1534. + }
  1535. +
  1536. + up_write(&cdev->client_lock);
  1537. /*
  1538. * The controller is only guaranteed to be valid for as long as the
  1539. @@ -266,8 +677,11 @@ static int ssam_dbg_device_remove(struct platform_device *pdev)
  1540. */
  1541. down_write(&cdev->lock);
  1542. cdev->ctrl = NULL;
  1543. + cdev->dev = NULL;
  1544. up_write(&cdev->lock);
  1545. + misc_deregister(&cdev->mdev);
  1546. +
  1547. ssam_cdev_put(cdev);
  1548. return 0;
  1549. }
  1550. diff --git a/include/uapi/linux/surface_aggregator/cdev.h b/include/uapi/linux/surface_aggregator/cdev.h
  1551. index fbcce04abfe9..4f393fafc235 100644
  1552. --- a/include/uapi/linux/surface_aggregator/cdev.h
  1553. +++ b/include/uapi/linux/surface_aggregator/cdev.h
  1554. @@ -6,7 +6,7 @@
  1555. * device. This device provides direct user-space access to the SSAM EC.
  1556. * Intended for debugging and development.
  1557. *
  1558. - * Copyright (C) 2020 Maximilian Luz <luzmaximilian@gmail.com>
  1559. + * Copyright (C) 2020-2021 Maximilian Luz <luzmaximilian@gmail.com>
  1560. */
  1561. #ifndef _UAPI_LINUX_SURFACE_AGGREGATOR_CDEV_H
  1562. @@ -73,6 +73,43 @@ struct ssam_cdev_request {
  1563. } response;
  1564. } __attribute__((__packed__));
  1565. -#define SSAM_CDEV_REQUEST _IOWR(0xA5, 1, struct ssam_cdev_request)
  1566. +/**
  1567. + * struct ssam_cdev_notifier_desc - Notifier descriptor.
  1568. + * @priority: Priority value determining the order in which notifier
  1569. + * callbacks will be called. A higher value means higher
  1570. + * priority, i.e. the associated callback will be executed
  1571. + * earlier than other (lower priority) callbacks.
  1572. + * @target_category: The event target category for which this notifier should
  1573. + * receive events.
  1574. + *
  1575. + * Specifies the notifier that should be registered or unregistered,
  1576. + * specifically with which priority and for which target category of events.
  1577. + */
  1578. +struct ssam_cdev_notifier_desc {
  1579. + __s32 priority;
  1580. + __u8 target_category;
  1581. +} __attribute__((__packed__));
  1582. +
  1583. +/**
  1584. + * struct ssam_cdev_event - SSAM event sent by the EC.
  1585. + * @target_category: Target category of the event source. See &enum ssam_ssh_tc.
  1586. + * @target_id: Target ID of the event source.
  1587. + * @command_id: Command ID of the event.
  1588. + * @instance_id: Instance ID of the event source.
  1589. + * @length: Length of the event payload in bytes.
  1590. + * @data: Event payload data.
  1591. + */
  1592. +struct ssam_cdev_event {
  1593. + __u8 target_category;
  1594. + __u8 target_id;
  1595. + __u8 command_id;
  1596. + __u8 instance_id;
  1597. + __u16 length;
  1598. + __u8 data[];
  1599. +} __attribute__((__packed__));
  1600. +
  1601. +#define SSAM_CDEV_REQUEST _IOWR(0xA5, 1, struct ssam_cdev_request)
  1602. +#define SSAM_CDEV_NOTIF_REGISTER _IOW(0xA5, 2, struct ssam_cdev_notifier_desc)
  1603. +#define SSAM_CDEV_NOTIF_UNREGISTER _IOW(0xA5, 3, struct ssam_cdev_notifier_desc)
  1604. #endif /* _UAPI_LINUX_SURFACE_AGGREGATOR_CDEV_H */
  1605. --
  1606. 2.32.0
  1607. From 57beefc4a8f10cc0a26f6d9299fff0574a0c1c95 Mon Sep 17 00:00:00 2001
  1608. From: Maximilian Luz <luzmaximilian@gmail.com>
  1609. Date: Fri, 4 Jun 2021 15:47:53 +0200
  1610. Subject: [PATCH] platform/surface: aggregator_cdev: Allow enabling of events
  1611. from user-space
  1612. While events can already be enabled and disabled via the generic request
  1613. IOCTL, this bypasses the internal reference counting mechanism of the
  1614. controller. Due to that, disabling an event will turn it off regardless
  1615. of any other client having requested said event, which may break
  1616. functionality of that client.
  1617. To solve this, add IOCTLs wrapping the ssam_controller_event_enable()
  1618. and ssam_controller_event_disable() functions, which have been
  1619. previously introduced for this specific purpose.
  1620. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  1621. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  1622. Link: https://lore.kernel.org/r/20210604134755.535590-6-luzmaximilian@gmail.com
  1623. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  1624. Patchset: surface-sam
  1625. ---
  1626. .../surface/surface_aggregator_cdev.c | 58 +++++++++++++++++++
  1627. include/uapi/linux/surface_aggregator/cdev.h | 32 ++++++++++
  1628. 2 files changed, 90 insertions(+)
  1629. diff --git a/drivers/platform/surface/surface_aggregator_cdev.c b/drivers/platform/surface/surface_aggregator_cdev.c
  1630. index dcda377896b7..7b86b36eaaa0 100644
  1631. --- a/drivers/platform/surface/surface_aggregator_cdev.c
  1632. +++ b/drivers/platform/surface/surface_aggregator_cdev.c
  1633. @@ -387,6 +387,58 @@ static long ssam_cdev_notif_unregister(struct ssam_cdev_client *client,
  1634. return ssam_cdev_notifier_unregister(client, desc.target_category);
  1635. }
  1636. +static long ssam_cdev_event_enable(struct ssam_cdev_client *client,
  1637. + const struct ssam_cdev_event_desc __user *d)
  1638. +{
  1639. + struct ssam_cdev_event_desc desc;
  1640. + struct ssam_event_registry reg;
  1641. + struct ssam_event_id id;
  1642. + long ret;
  1643. +
  1644. + /* Read descriptor from user-space. */
  1645. + ret = copy_struct_from_user(&desc, sizeof(desc), d, sizeof(*d));
  1646. + if (ret)
  1647. + return ret;
  1648. +
  1649. + /* Translate descriptor. */
  1650. + reg.target_category = desc.reg.target_category;
  1651. + reg.target_id = desc.reg.target_id;
  1652. + reg.cid_enable = desc.reg.cid_enable;
  1653. + reg.cid_disable = desc.reg.cid_disable;
  1654. +
  1655. + id.target_category = desc.id.target_category;
  1656. + id.instance = desc.id.instance;
  1657. +
  1658. + /* Disable event. */
  1659. + return ssam_controller_event_enable(client->cdev->ctrl, reg, id, desc.flags);
  1660. +}
  1661. +
  1662. +static long ssam_cdev_event_disable(struct ssam_cdev_client *client,
  1663. + const struct ssam_cdev_event_desc __user *d)
  1664. +{
  1665. + struct ssam_cdev_event_desc desc;
  1666. + struct ssam_event_registry reg;
  1667. + struct ssam_event_id id;
  1668. + long ret;
  1669. +
  1670. + /* Read descriptor from user-space. */
  1671. + ret = copy_struct_from_user(&desc, sizeof(desc), d, sizeof(*d));
  1672. + if (ret)
  1673. + return ret;
  1674. +
  1675. + /* Translate descriptor. */
  1676. + reg.target_category = desc.reg.target_category;
  1677. + reg.target_id = desc.reg.target_id;
  1678. + reg.cid_enable = desc.reg.cid_enable;
  1679. + reg.cid_disable = desc.reg.cid_disable;
  1680. +
  1681. + id.target_category = desc.id.target_category;
  1682. + id.instance = desc.id.instance;
  1683. +
  1684. + /* Disable event. */
  1685. + return ssam_controller_event_disable(client->cdev->ctrl, reg, id, desc.flags);
  1686. +}
  1687. +
  1688. /* -- File operations. ------------------------------------------------------ */
  1689. @@ -473,6 +525,12 @@ static long __ssam_cdev_device_ioctl(struct ssam_cdev_client *client, unsigned i
  1690. return ssam_cdev_notif_unregister(client,
  1691. (struct ssam_cdev_notifier_desc __user *)arg);
  1692. + case SSAM_CDEV_EVENT_ENABLE:
  1693. + return ssam_cdev_event_enable(client, (struct ssam_cdev_event_desc __user *)arg);
  1694. +
  1695. + case SSAM_CDEV_EVENT_DISABLE:
  1696. + return ssam_cdev_event_disable(client, (struct ssam_cdev_event_desc __user *)arg);
  1697. +
  1698. default:
  1699. return -ENOTTY;
  1700. }
  1701. diff --git a/include/uapi/linux/surface_aggregator/cdev.h b/include/uapi/linux/surface_aggregator/cdev.h
  1702. index 4f393fafc235..08f46b60b151 100644
  1703. --- a/include/uapi/linux/surface_aggregator/cdev.h
  1704. +++ b/include/uapi/linux/surface_aggregator/cdev.h
  1705. @@ -90,6 +90,36 @@ struct ssam_cdev_notifier_desc {
  1706. __u8 target_category;
  1707. } __attribute__((__packed__));
  1708. +/**
  1709. + * struct ssam_cdev_event_desc - Event descriptor.
  1710. + * @reg: Registry via which the event will be enabled/disabled.
  1711. + * @reg.target_category: Target category for the event registry requests.
  1712. + * @reg.target_id: Target ID for the event registry requests.
  1713. + * @reg.cid_enable: Command ID for the event-enable request.
  1714. + * @reg.cid_disable: Command ID for the event-disable request.
  1715. + * @id: ID specifying the event.
  1716. + * @id.target_category: Target category of the event source.
  1717. + * @id.instance: Instance ID of the event source.
  1718. + * @flags: Flags used for enabling the event.
  1719. + *
  1720. + * Specifies which event should be enabled/disabled and how to do that.
  1721. + */
  1722. +struct ssam_cdev_event_desc {
  1723. + struct {
  1724. + __u8 target_category;
  1725. + __u8 target_id;
  1726. + __u8 cid_enable;
  1727. + __u8 cid_disable;
  1728. + } reg;
  1729. +
  1730. + struct {
  1731. + __u8 target_category;
  1732. + __u8 instance;
  1733. + } id;
  1734. +
  1735. + __u8 flags;
  1736. +} __attribute__((__packed__));
  1737. +
  1738. /**
  1739. * struct ssam_cdev_event - SSAM event sent by the EC.
  1740. * @target_category: Target category of the event source. See &enum ssam_ssh_tc.
  1741. @@ -111,5 +141,7 @@ struct ssam_cdev_event {
  1742. #define SSAM_CDEV_REQUEST _IOWR(0xA5, 1, struct ssam_cdev_request)
  1743. #define SSAM_CDEV_NOTIF_REGISTER _IOW(0xA5, 2, struct ssam_cdev_notifier_desc)
  1744. #define SSAM_CDEV_NOTIF_UNREGISTER _IOW(0xA5, 3, struct ssam_cdev_notifier_desc)
  1745. +#define SSAM_CDEV_EVENT_ENABLE _IOW(0xA5, 4, struct ssam_cdev_event_desc)
  1746. +#define SSAM_CDEV_EVENT_DISABLE _IOW(0xA5, 5, struct ssam_cdev_event_desc)
  1747. #endif /* _UAPI_LINUX_SURFACE_AGGREGATOR_CDEV_H */
  1748. --
  1749. 2.32.0
  1750. From b26eb043920cf30a9c6dad8b02ebd78adcf1fb2c Mon Sep 17 00:00:00 2001
  1751. From: Maximilian Luz <luzmaximilian@gmail.com>
  1752. Date: Fri, 4 Jun 2021 15:47:54 +0200
  1753. Subject: [PATCH] platform/surface: aggregator_cdev: Add lockdep support
  1754. Mark functions with locking requirements via the corresponding lockdep
  1755. calls for debugging and documentary purposes.
  1756. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  1757. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  1758. Link: https://lore.kernel.org/r/20210604134755.535590-7-luzmaximilian@gmail.com
  1759. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  1760. Patchset: surface-sam
  1761. ---
  1762. .../platform/surface/surface_aggregator_cdev.c | 16 ++++++++++++++++
  1763. 1 file changed, 16 insertions(+)
  1764. diff --git a/drivers/platform/surface/surface_aggregator_cdev.c b/drivers/platform/surface/surface_aggregator_cdev.c
  1765. index 7b86b36eaaa0..30fb50fde450 100644
  1766. --- a/drivers/platform/surface/surface_aggregator_cdev.c
  1767. +++ b/drivers/platform/surface/surface_aggregator_cdev.c
  1768. @@ -139,6 +139,8 @@ static int ssam_cdev_notifier_register(struct ssam_cdev_client *client, u8 tc, i
  1769. struct ssam_cdev_notifier *nf;
  1770. int status;
  1771. + lockdep_assert_held_read(&client->cdev->lock);
  1772. +
  1773. /* Validate notifier target category. */
  1774. if (!ssh_rqid_is_event(rqid))
  1775. return -EINVAL;
  1776. @@ -188,6 +190,8 @@ static int ssam_cdev_notifier_unregister(struct ssam_cdev_client *client, u8 tc)
  1777. const u16 event = ssh_rqid_to_event(rqid);
  1778. int status;
  1779. + lockdep_assert_held_read(&client->cdev->lock);
  1780. +
  1781. /* Validate notifier target category. */
  1782. if (!ssh_rqid_is_event(rqid))
  1783. return -EINVAL;
  1784. @@ -257,6 +261,8 @@ static long ssam_cdev_request(struct ssam_cdev_client *client, struct ssam_cdev_
  1785. void __user *rspdata;
  1786. int status = 0, ret = 0, tmp;
  1787. + lockdep_assert_held_read(&client->cdev->lock);
  1788. +
  1789. ret = copy_struct_from_user(&rqst, sizeof(rqst), r, sizeof(*r));
  1790. if (ret)
  1791. goto out;
  1792. @@ -367,6 +373,8 @@ static long ssam_cdev_notif_register(struct ssam_cdev_client *client,
  1793. struct ssam_cdev_notifier_desc desc;
  1794. long ret;
  1795. + lockdep_assert_held_read(&client->cdev->lock);
  1796. +
  1797. ret = copy_struct_from_user(&desc, sizeof(desc), d, sizeof(*d));
  1798. if (ret)
  1799. return ret;
  1800. @@ -380,6 +388,8 @@ static long ssam_cdev_notif_unregister(struct ssam_cdev_client *client,
  1801. struct ssam_cdev_notifier_desc desc;
  1802. long ret;
  1803. + lockdep_assert_held_read(&client->cdev->lock);
  1804. +
  1805. ret = copy_struct_from_user(&desc, sizeof(desc), d, sizeof(*d));
  1806. if (ret)
  1807. return ret;
  1808. @@ -395,6 +405,8 @@ static long ssam_cdev_event_enable(struct ssam_cdev_client *client,
  1809. struct ssam_event_id id;
  1810. long ret;
  1811. + lockdep_assert_held_read(&client->cdev->lock);
  1812. +
  1813. /* Read descriptor from user-space. */
  1814. ret = copy_struct_from_user(&desc, sizeof(desc), d, sizeof(*d));
  1815. if (ret)
  1816. @@ -421,6 +433,8 @@ static long ssam_cdev_event_disable(struct ssam_cdev_client *client,
  1817. struct ssam_event_id id;
  1818. long ret;
  1819. + lockdep_assert_held_read(&client->cdev->lock);
  1820. +
  1821. /* Read descriptor from user-space. */
  1822. ret = copy_struct_from_user(&desc, sizeof(desc), d, sizeof(*d));
  1823. if (ret)
  1824. @@ -513,6 +527,8 @@ static int ssam_cdev_device_release(struct inode *inode, struct file *filp)
  1825. static long __ssam_cdev_device_ioctl(struct ssam_cdev_client *client, unsigned int cmd,
  1826. unsigned long arg)
  1827. {
  1828. + lockdep_assert_held_read(&client->cdev->lock);
  1829. +
  1830. switch (cmd) {
  1831. case SSAM_CDEV_REQUEST:
  1832. return ssam_cdev_request(client, (struct ssam_cdev_request __user *)arg);
  1833. --
  1834. 2.32.0
  1835. From e41af53103f8422234d1ce3091b496a8a3d9b6e0 Mon Sep 17 00:00:00 2001
  1836. From: Maximilian Luz <luzmaximilian@gmail.com>
  1837. Date: Wed, 2 Jun 2021 20:07:47 +0200
  1838. Subject: [PATCH] docs: driver-api: Update Surface Aggregator user-space
  1839. interface documentation
  1840. Update the controller-device user-space interface (cdev) documentation
  1841. for the newly introduced IOCTLs and event interface.
  1842. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  1843. Patchset: surface-sam
  1844. ---
  1845. .../surface_aggregator/clients/cdev.rst | 127 +++++++++++++++++-
  1846. 1 file changed, 122 insertions(+), 5 deletions(-)
  1847. diff --git a/Documentation/driver-api/surface_aggregator/clients/cdev.rst b/Documentation/driver-api/surface_aggregator/clients/cdev.rst
  1848. index 248c1372d879..0134a841a079 100644
  1849. --- a/Documentation/driver-api/surface_aggregator/clients/cdev.rst
  1850. +++ b/Documentation/driver-api/surface_aggregator/clients/cdev.rst
  1851. @@ -1,9 +1,8 @@
  1852. .. SPDX-License-Identifier: GPL-2.0+
  1853. -.. |u8| replace:: :c:type:`u8 <u8>`
  1854. -.. |u16| replace:: :c:type:`u16 <u16>`
  1855. .. |ssam_cdev_request| replace:: :c:type:`struct ssam_cdev_request <ssam_cdev_request>`
  1856. .. |ssam_cdev_request_flags| replace:: :c:type:`enum ssam_cdev_request_flags <ssam_cdev_request_flags>`
  1857. +.. |ssam_cdev_event| replace:: :c:type:`struct ssam_cdev_event <ssam_cdev_event>`
  1858. ==============================
  1859. User-Space EC Interface (cdev)
  1860. @@ -23,6 +22,40 @@ These IOCTLs and their respective input/output parameter structs are defined in
  1861. A small python library and scripts for accessing this interface can be found
  1862. at https://github.com/linux-surface/surface-aggregator-module/tree/master/scripts/ssam.
  1863. +.. contents::
  1864. +
  1865. +
  1866. +Receiving Events
  1867. +================
  1868. +
  1869. +Events can be received by reading from the device-file. The are represented by
  1870. +the |ssam_cdev_event| datatype.
  1871. +
  1872. +Before events are available to be read, however, the desired notifiers must be
  1873. +registered via the ``SSAM_CDEV_NOTIF_REGISTER`` IOCTL. Notifiers are, in
  1874. +essence, callbacks, called when the EC sends an event. They are, in this
  1875. +interface, associated with a specific target category and device-file-instance.
  1876. +They forward any event of this category to the buffer of the corresponding
  1877. +instance, from which it can then be read.
  1878. +
  1879. +Notifiers themselves do not enable events on the EC. Thus, it may additionally
  1880. +be necessary to enable events via the ``SSAM_CDEV_EVENT_ENABLE`` IOCTL. While
  1881. +notifiers work per-client (i.e. per-device-file-instance), events are enabled
  1882. +globally, for the EC and all of its clients (regardless of userspace or
  1883. +non-userspace). The ``SSAM_CDEV_EVENT_ENABLE`` and ``SSAM_CDEV_EVENT_DISABLE``
  1884. +IOCTLs take care of reference counting the events, such that an event is
  1885. +enabled as long as there is a client that has requested it.
  1886. +
  1887. +Note that enabled events are not automatically disabled once the client
  1888. +instance is closed. Therefore any client process (or group of processes) should
  1889. +balance their event enable calls with the corresponding event disable calls. It
  1890. +is, however, perfectly valid to enable and disable events on different client
  1891. +instances. For example, it is valid to set up notifiers and read events on
  1892. +client instance ``A``, enable those events on instance ``B`` (note that these
  1893. +will also be received by A since events are enabled/disabled globally), and
  1894. +after no more events are desired, disable the previously enabled events via
  1895. +instance ``C``.
  1896. +
  1897. Controller IOCTLs
  1898. =================
  1899. @@ -45,9 +78,33 @@ The following IOCTLs are provided:
  1900. - ``REQUEST``
  1901. - Perform synchronous SAM request.
  1902. + * - ``0xA5``
  1903. + - ``2``
  1904. + - ``W``
  1905. + - ``NOTIF_REGISTER``
  1906. + - Register event notifier.
  1907. -``REQUEST``
  1908. ------------
  1909. + * - ``0xA5``
  1910. + - ``3``
  1911. + - ``W``
  1912. + - ``NOTIF_UNREGISTER``
  1913. + - Unregister event notifier.
  1914. +
  1915. + * - ``0xA5``
  1916. + - ``4``
  1917. + - ``W``
  1918. + - ``EVENT_ENABLE``
  1919. + - Enable event source.
  1920. +
  1921. + * - ``0xA5``
  1922. + - ``5``
  1923. + - ``W``
  1924. + - ``EVENT_DISABLE``
  1925. + - Disable event source.
  1926. +
  1927. +
  1928. +``SSAM_CDEV_REQUEST``
  1929. +---------------------
  1930. Defined as ``_IOWR(0xA5, 1, struct ssam_cdev_request)``.
  1931. @@ -82,6 +139,66 @@ submitted, and completed (i.e. handed back to user-space) successfully from
  1932. inside the IOCTL, but the request ``status`` member may still be negative in
  1933. case the actual execution of the request failed after it has been submitted.
  1934. -A full definition of the argument struct is provided below:
  1935. +A full definition of the argument struct is provided below.
  1936. +
  1937. +``SSAM_CDEV_NOTIF_REGISTER``
  1938. +----------------------------
  1939. +
  1940. +Defined as ``_IOW(0xA5, 2, struct ssam_cdev_notifier_desc)``.
  1941. +
  1942. +Register a notifier for the event target category specified in the given
  1943. +notifier description with the specified priority. Notifiers registration is
  1944. +required to receive events, but does not enable events themselves. After a
  1945. +notifier for a specific target category has been registered, all events of that
  1946. +category will be forwarded to the userspace client and can then be read from
  1947. +the device file instance. Note that events may have to be enabled, e.g. via the
  1948. +``SSAM_CDEV_EVENT_ENABLE`` IOCTL, before the EC will send them.
  1949. +
  1950. +Only one notifier can be registered per target category and client instance. If
  1951. +a notifier has already been registered, this IOCTL will fail with ``-EEXIST``.
  1952. +
  1953. +Notifiers will automatically be removed when the device file instance is
  1954. +closed.
  1955. +
  1956. +``SSAM_CDEV_NOTIF_UNREGISTER``
  1957. +------------------------------
  1958. +
  1959. +Defined as ``_IOW(0xA5, 3, struct ssam_cdev_notifier_desc)``.
  1960. +
  1961. +Unregisters the notifier associated with the specified target category. The
  1962. +priority field will be ignored by this IOCTL. If no notifier has been
  1963. +registered for this client instance and the given category, this IOCTL will
  1964. +fail with ``-ENOENT``.
  1965. +
  1966. +``SSAM_CDEV_EVENT_ENABLE``
  1967. +--------------------------
  1968. +
  1969. +Defined as ``_IOW(0xA5, 4, struct ssam_cdev_event_desc)``.
  1970. +
  1971. +Enable the event associated with the given event descriptor.
  1972. +
  1973. +Note that this call will not register a notifier itself, it will only enable
  1974. +events on the controller. If you want to receive events by reading from the
  1975. +device file, you will need to register the corresponding notifier(s) on that
  1976. +instance.
  1977. +
  1978. +Events are not automatically disabled when the device file is closed. This must
  1979. +be done manually, via a call to the ``SSAM_CDEV_EVENT_DISABLE`` IOCTL.
  1980. +
  1981. +``SSAM_CDEV_EVENT_DISABLE``
  1982. +---------------------------
  1983. +
  1984. +Defined as ``_IOW(0xA5, 5, struct ssam_cdev_event_desc)``.
  1985. +
  1986. +Disable the event associated with the given event descriptor.
  1987. +
  1988. +Note that this will not unregister any notifiers. Events may still be received
  1989. +and forwarded to user-space after this call. The only safe way of stopping
  1990. +events from being received is unregistering all previously registered
  1991. +notifiers.
  1992. +
  1993. +
  1994. +Structures and Enums
  1995. +====================
  1996. .. kernel-doc:: include/uapi/linux/surface_aggregator/cdev.h
  1997. --
  1998. 2.32.0
  1999. From 60ac33ea0f8194f891b9808d7d7215297de0c63c Mon Sep 17 00:00:00 2001
  2000. From: Maximilian Luz <luzmaximilian@gmail.com>
  2001. Date: Fri, 4 Jun 2021 23:09:06 +0200
  2002. Subject: [PATCH] platform/surface: aggregator: Do not return uninitialized
  2003. value
  2004. The status variable in ssam_nf_refcount_disable_free() is only set when
  2005. the reference count equals zero. Otherwise, it is returned
  2006. uninitialized. Fix this by always initializing status to zero.
  2007. Reported-by: kernel test robot <lkp@intel.com>
  2008. Fixes: 640ee17199e4 ("platform/surface: aggregator: Allow enabling of events without notifiers")
  2009. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  2010. Link: https://lore.kernel.org/r/20210604210907.25738-2-luzmaximilian@gmail.com
  2011. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  2012. Patchset: surface-sam
  2013. ---
  2014. drivers/platform/surface/aggregator/controller.c | 2 +-
  2015. 1 file changed, 1 insertion(+), 1 deletion(-)
  2016. diff --git a/drivers/platform/surface/aggregator/controller.c b/drivers/platform/surface/aggregator/controller.c
  2017. index 6646f4d6e10d..634399387d76 100644
  2018. --- a/drivers/platform/surface/aggregator/controller.c
  2019. +++ b/drivers/platform/surface/aggregator/controller.c
  2020. @@ -2228,7 +2228,7 @@ static int ssam_nf_refcount_disable_free(struct ssam_controller *ctrl,
  2021. const struct ssam_event_registry reg = entry->key.reg;
  2022. const struct ssam_event_id id = entry->key.id;
  2023. struct ssam_nf *nf = &ctrl->cplt.event.notif;
  2024. - int status;
  2025. + int status = 0;
  2026. lockdep_assert_held(&nf->lock);
  2027. --
  2028. 2.32.0
  2029. From 7640650e61d9f4fba894e321dfe7c9184b3b8a29 Mon Sep 17 00:00:00 2001
  2030. From: Maximilian Luz <luzmaximilian@gmail.com>
  2031. Date: Fri, 4 Jun 2021 23:09:07 +0200
  2032. Subject: [PATCH] platform/surface: aggregator: Drop unnecessary variable
  2033. initialization
  2034. The status variable in ssam_controller_event_disable() is always set, no
  2035. need to initialize it.
  2036. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  2037. Link: https://lore.kernel.org/r/20210604210907.25738-3-luzmaximilian@gmail.com
  2038. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  2039. Patchset: surface-sam
  2040. ---
  2041. drivers/platform/surface/aggregator/controller.c | 2 +-
  2042. 1 file changed, 1 insertion(+), 1 deletion(-)
  2043. diff --git a/drivers/platform/surface/aggregator/controller.c b/drivers/platform/surface/aggregator/controller.c
  2044. index 634399387d76..b8c377b3f932 100644
  2045. --- a/drivers/platform/surface/aggregator/controller.c
  2046. +++ b/drivers/platform/surface/aggregator/controller.c
  2047. @@ -2464,7 +2464,7 @@ int ssam_controller_event_disable(struct ssam_controller *ctrl,
  2048. u16 rqid = ssh_tc_to_rqid(id.target_category);
  2049. struct ssam_nf *nf = &ctrl->cplt.event.notif;
  2050. struct ssam_nf_refcount_entry *entry;
  2051. - int status = 0;
  2052. + int status;
  2053. if (!ssh_rqid_is_event(rqid))
  2054. return -EINVAL;
  2055. --
  2056. 2.32.0
  2057. From 4e9280059d06eca593d3da0ccc25250796676908 Mon Sep 17 00:00:00 2001
  2058. From: Baokun Li <libaokun1@huawei.com>
  2059. Date: Wed, 9 Jun 2021 15:26:38 +0800
  2060. Subject: [PATCH] platform/surface: aggregator: Use list_move_tail instead of
  2061. list_del/list_add_tail in ssh_request_layer.c
  2062. Using list_move_tail() instead of list_del() + list_add_tail() in ssh_request_layer.c.
  2063. Reported-by: Hulk Robot <hulkci@huawei.com>
  2064. Signed-off-by: Baokun Li <libaokun1@huawei.com>
  2065. Reviewed-by: Maximilian Luz <luzmaximilian@gmail.com>
  2066. Link: https://lore.kernel.org/r/20210609072638.1358174-1-libaokun1@huawei.com
  2067. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  2068. Patchset: surface-sam
  2069. ---
  2070. .../platform/surface/aggregator/ssh_request_layer.c | 10 +++-------
  2071. 1 file changed, 3 insertions(+), 7 deletions(-)
  2072. diff --git a/drivers/platform/surface/aggregator/ssh_request_layer.c b/drivers/platform/surface/aggregator/ssh_request_layer.c
  2073. index bfe1aaf38065..790f7f0eee98 100644
  2074. --- a/drivers/platform/surface/aggregator/ssh_request_layer.c
  2075. +++ b/drivers/platform/surface/aggregator/ssh_request_layer.c
  2076. @@ -863,9 +863,7 @@ static void ssh_rtl_timeout_reap(struct work_struct *work)
  2077. clear_bit(SSH_REQUEST_SF_PENDING_BIT, &r->state);
  2078. atomic_dec(&rtl->pending.count);
  2079. - list_del(&r->node);
  2080. -
  2081. - list_add_tail(&r->node, &claimed);
  2082. + list_move_tail(&r->node, &claimed);
  2083. }
  2084. spin_unlock(&rtl->pending.lock);
  2085. @@ -1204,8 +1202,7 @@ void ssh_rtl_shutdown(struct ssh_rtl *rtl)
  2086. smp_mb__before_atomic();
  2087. clear_bit(SSH_REQUEST_SF_QUEUED_BIT, &r->state);
  2088. - list_del(&r->node);
  2089. - list_add_tail(&r->node, &claimed);
  2090. + list_move_tail(&r->node, &claimed);
  2091. }
  2092. spin_unlock(&rtl->queue.lock);
  2093. @@ -1238,8 +1235,7 @@ void ssh_rtl_shutdown(struct ssh_rtl *rtl)
  2094. smp_mb__before_atomic();
  2095. clear_bit(SSH_REQUEST_SF_PENDING_BIT, &r->state);
  2096. - list_del(&r->node);
  2097. - list_add_tail(&r->node, &claimed);
  2098. + list_move_tail(&r->node, &claimed);
  2099. }
  2100. spin_unlock(&rtl->pending.lock);
  2101. }
  2102. --
  2103. 2.32.0
  2104. From d73fd93fdf881de16ce199225ce97f3c4ce602c5 Mon Sep 17 00:00:00 2001
  2105. From: Baokun Li <libaokun1@huawei.com>
  2106. Date: Wed, 9 Jun 2021 15:24:48 +0800
  2107. Subject: [PATCH] platform/surface: aggregator: Use list_move_tail instead of
  2108. list_del/list_add_tail in ssh_packet_layer.c
  2109. Using list_move_tail() instead of list_del() + list_add_tail() in ssh_packet_layer.c.
  2110. Reported-by: Hulk Robot <hulkci@huawei.com>
  2111. Signed-off-by: Baokun Li <libaokun1@huawei.com>
  2112. Reviewed-by: Maximilian Luz <luzmaximilian@gmail.com>
  2113. Link: https://lore.kernel.org/r/20210609072448.1357524-1-libaokun1@huawei.com
  2114. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  2115. Patchset: surface-sam
  2116. ---
  2117. drivers/platform/surface/aggregator/ssh_packet_layer.c | 10 +++-------
  2118. 1 file changed, 3 insertions(+), 7 deletions(-)
  2119. diff --git a/drivers/platform/surface/aggregator/ssh_packet_layer.c b/drivers/platform/surface/aggregator/ssh_packet_layer.c
  2120. index 5e08049fc3ac..8a4451c1ffe5 100644
  2121. --- a/drivers/platform/surface/aggregator/ssh_packet_layer.c
  2122. +++ b/drivers/platform/surface/aggregator/ssh_packet_layer.c
  2123. @@ -1567,9 +1567,7 @@ static void ssh_ptl_timeout_reap(struct work_struct *work)
  2124. clear_bit(SSH_PACKET_SF_PENDING_BIT, &p->state);
  2125. atomic_dec(&ptl->pending.count);
  2126. - list_del(&p->pending_node);
  2127. -
  2128. - list_add_tail(&p->pending_node, &claimed);
  2129. + list_move_tail(&p->pending_node, &claimed);
  2130. }
  2131. spin_unlock(&ptl->pending.lock);
  2132. @@ -1957,8 +1955,7 @@ void ssh_ptl_shutdown(struct ssh_ptl *ptl)
  2133. smp_mb__before_atomic();
  2134. clear_bit(SSH_PACKET_SF_QUEUED_BIT, &p->state);
  2135. - list_del(&p->queue_node);
  2136. - list_add_tail(&p->queue_node, &complete_q);
  2137. + list_move_tail(&p->queue_node, &complete_q);
  2138. }
  2139. spin_unlock(&ptl->queue.lock);
  2140. @@ -1970,8 +1967,7 @@ void ssh_ptl_shutdown(struct ssh_ptl *ptl)
  2141. smp_mb__before_atomic();
  2142. clear_bit(SSH_PACKET_SF_PENDING_BIT, &p->state);
  2143. - list_del(&p->pending_node);
  2144. - list_add_tail(&p->pending_node, &complete_q);
  2145. + list_move_tail(&p->pending_node, &complete_q);
  2146. }
  2147. atomic_set(&ptl->pending.count, 0);
  2148. spin_unlock(&ptl->pending.lock);
  2149. --
  2150. 2.32.0