0005-surface-sam.patch 162 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703
  1. From 10cd88124de652804f308111320a863b55da23a0 Mon Sep 17 00:00:00 2001
  2. From: Maximilian Luz <luzmaximilian@gmail.com>
  3. Date: Fri, 27 May 2022 04:34:36 +0200
  4. Subject: [PATCH] platform/surface: aggregator: Allow is_ssam_device() to be
  5. used when CONFIG_SURFACE_AGGREGATOR_BUS is disabled
  6. In SSAM subsystem drivers that handle both ACPI and SSAM-native client
  7. devices, we may want to check whether we have a SSAM (native) client
  8. device. Further, we may want to do this even when instantiation thereof
  9. cannot happen due to CONFIG_SURFACE_AGGREGATOR_BUS=n. Currently, doing
  10. so causes an error due to an undefined reference error due to
  11. ssam_device_type being placed in the bus source unit.
  12. Therefore, if CONFIG_SURFACE_AGGREGATOR_BUS is not defined, simply let
  13. is_ssam_device() return false to prevent this error.
  14. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  15. Link: https://lore.kernel.org/r/20220527023447.2460025-2-luzmaximilian@gmail.com
  16. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  17. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  18. Patchset: surface-sam
  19. ---
  20. include/linux/surface_aggregator/device.h | 11 +++++++++++
  21. 1 file changed, 11 insertions(+)
  22. diff --git a/include/linux/surface_aggregator/device.h b/include/linux/surface_aggregator/device.h
  23. index cc257097eb05..62b38b4487eb 100644
  24. --- a/include/linux/surface_aggregator/device.h
  25. +++ b/include/linux/surface_aggregator/device.h
  26. @@ -177,6 +177,8 @@ struct ssam_device_driver {
  27. void (*remove)(struct ssam_device *sdev);
  28. };
  29. +#ifdef CONFIG_SURFACE_AGGREGATOR_BUS
  30. +
  31. extern struct bus_type ssam_bus_type;
  32. extern const struct device_type ssam_device_type;
  33. @@ -193,6 +195,15 @@ static inline bool is_ssam_device(struct device *d)
  34. return d->type == &ssam_device_type;
  35. }
  36. +#else /* CONFIG_SURFACE_AGGREGATOR_BUS */
  37. +
  38. +static inline bool is_ssam_device(struct device *d)
  39. +{
  40. + return false;
  41. +}
  42. +
  43. +#endif /* CONFIG_SURFACE_AGGREGATOR_BUS */
  44. +
  45. /**
  46. * to_ssam_device() - Casts the given device to a SSAM client device.
  47. * @d: The device to cast.
  48. --
  49. 2.38.0
  50. From 491afd847e8b97631743293a1e88d1019038a710 Mon Sep 17 00:00:00 2001
  51. From: Maximilian Luz <luzmaximilian@gmail.com>
  52. Date: Fri, 27 May 2022 04:34:37 +0200
  53. Subject: [PATCH] platform/surface: aggregator: Allow devices to be marked as
  54. hot-removed
  55. Some SSAM devices, notably the keyboard cover (keyboard and touchpad) on
  56. the Surface Pro 8, can be hot-removed. When this occurs, communication
  57. with the device may fail and time out. This timeout can unnecessarily
  58. block and slow down device removal and even cause issues when the
  59. devices are detached and re-attached quickly. Thus, communication should
  60. generally be avoided once hot-removal is detected.
  61. While we already remove a device as soon as we detect its (hot-)removal,
  62. the corresponding device driver may still attempt to communicate with
  63. the device during teardown. This is especially critical as communication
  64. failure may also extend to disabling of events, which is typically done
  65. at that stage.
  66. Add a flag to allow marking devices as hot-removed. This can then be
  67. used during client driver teardown to check if any communication
  68. attempts should be avoided.
  69. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  70. Link: https://lore.kernel.org/r/20220527023447.2460025-3-luzmaximilian@gmail.com
  71. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  72. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  73. Patchset: surface-sam
  74. ---
  75. include/linux/surface_aggregator/device.h | 48 +++++++++++++++++++++--
  76. 1 file changed, 45 insertions(+), 3 deletions(-)
  77. diff --git a/include/linux/surface_aggregator/device.h b/include/linux/surface_aggregator/device.h
  78. index 62b38b4487eb..6df7c8d4e50e 100644
  79. --- a/include/linux/surface_aggregator/device.h
  80. +++ b/include/linux/surface_aggregator/device.h
  81. @@ -148,17 +148,30 @@ struct ssam_device_uid {
  82. #define SSAM_SDEV(cat, tid, iid, fun) \
  83. SSAM_DEVICE(SSAM_DOMAIN_SERIALHUB, SSAM_SSH_TC_##cat, tid, iid, fun)
  84. +/*
  85. + * enum ssam_device_flags - Flags for SSAM client devices.
  86. + * @SSAM_DEVICE_HOT_REMOVED_BIT:
  87. + * The device has been hot-removed. Further communication with it may time
  88. + * out and should be avoided.
  89. + */
  90. +enum ssam_device_flags {
  91. + SSAM_DEVICE_HOT_REMOVED_BIT = 0,
  92. +};
  93. +
  94. /**
  95. * struct ssam_device - SSAM client device.
  96. - * @dev: Driver model representation of the device.
  97. - * @ctrl: SSAM controller managing this device.
  98. - * @uid: UID identifying the device.
  99. + * @dev: Driver model representation of the device.
  100. + * @ctrl: SSAM controller managing this device.
  101. + * @uid: UID identifying the device.
  102. + * @flags: Device state flags, see &enum ssam_device_flags.
  103. */
  104. struct ssam_device {
  105. struct device dev;
  106. struct ssam_controller *ctrl;
  107. struct ssam_device_uid uid;
  108. +
  109. + unsigned long flags;
  110. };
  111. /**
  112. @@ -251,6 +264,35 @@ struct ssam_device *ssam_device_alloc(struct ssam_controller *ctrl,
  113. int ssam_device_add(struct ssam_device *sdev);
  114. void ssam_device_remove(struct ssam_device *sdev);
  115. +/**
  116. + * ssam_device_mark_hot_removed() - Mark the given device as hot-removed.
  117. + * @sdev: The device to mark as hot-removed.
  118. + *
  119. + * Mark the device as having been hot-removed. This signals drivers using the
  120. + * device that communication with the device should be avoided and may lead to
  121. + * timeouts.
  122. + */
  123. +static inline void ssam_device_mark_hot_removed(struct ssam_device *sdev)
  124. +{
  125. + dev_dbg(&sdev->dev, "marking device as hot-removed\n");
  126. + set_bit(SSAM_DEVICE_HOT_REMOVED_BIT, &sdev->flags);
  127. +}
  128. +
  129. +/**
  130. + * ssam_device_is_hot_removed() - Check if the given device has been
  131. + * hot-removed.
  132. + * @sdev: The device to check.
  133. + *
  134. + * Checks if the given device has been marked as hot-removed. See
  135. + * ssam_device_mark_hot_removed() for more details.
  136. + *
  137. + * Return: Returns ``true`` if the device has been marked as hot-removed.
  138. + */
  139. +static inline bool ssam_device_is_hot_removed(struct ssam_device *sdev)
  140. +{
  141. + return test_bit(SSAM_DEVICE_HOT_REMOVED_BIT, &sdev->flags);
  142. +}
  143. +
  144. /**
  145. * ssam_device_get() - Increment reference count of SSAM client device.
  146. * @sdev: The device to increment the reference count of.
  147. --
  148. 2.38.0
  149. From bebd8ac867acf177167fd156f5e7bcfd36869c52 Mon Sep 17 00:00:00 2001
  150. From: Maximilian Luz <luzmaximilian@gmail.com>
  151. Date: Fri, 27 May 2022 04:34:38 +0200
  152. Subject: [PATCH] platform/surface: aggregator: Allow notifiers to avoid
  153. communication on unregistering
  154. When SSAM client devices have been (physically) hot-removed,
  155. communication attempts with those devices may fail and time out. This
  156. can even extend to event notifiers, due to which timeouts may occur
  157. during device removal, slowing down that process.
  158. Add a parameter to the notifier unregister function that allows skipping
  159. communication with the EC to prevent this. Furthermore, add wrappers for
  160. registering and unregistering notifiers belonging to SSAM client devices
  161. that automatically check if the device has been marked as hot-removed
  162. and communication should be avoided.
  163. Note that non-SSAM client devices can generally not be hot-removed, so
  164. also add a convenience wrapper for those, defaulting to allow
  165. communication.
  166. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  167. Link: https://lore.kernel.org/r/20220527023447.2460025-4-luzmaximilian@gmail.com
  168. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  169. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  170. Patchset: surface-sam
  171. ---
  172. .../driver-api/surface_aggregator/client.rst | 6 +-
  173. .../platform/surface/aggregator/controller.c | 53 ++++++++++-----
  174. include/linux/surface_aggregator/controller.h | 24 ++++++-
  175. include/linux/surface_aggregator/device.h | 66 +++++++++++++++++++
  176. 4 files changed, 128 insertions(+), 21 deletions(-)
  177. diff --git a/Documentation/driver-api/surface_aggregator/client.rst b/Documentation/driver-api/surface_aggregator/client.rst
  178. index e519d374c378..27f95abdbe99 100644
  179. --- a/Documentation/driver-api/surface_aggregator/client.rst
  180. +++ b/Documentation/driver-api/surface_aggregator/client.rst
  181. @@ -17,6 +17,8 @@
  182. .. |SSAM_DEVICE| replace:: :c:func:`SSAM_DEVICE`
  183. .. |ssam_notifier_register| replace:: :c:func:`ssam_notifier_register`
  184. .. |ssam_notifier_unregister| replace:: :c:func:`ssam_notifier_unregister`
  185. +.. |ssam_device_notifier_register| replace:: :c:func:`ssam_device_notifier_register`
  186. +.. |ssam_device_notifier_unregister| replace:: :c:func:`ssam_device_notifier_unregister`
  187. .. |ssam_request_sync| replace:: :c:func:`ssam_request_sync`
  188. .. |ssam_event_mask| replace:: :c:type:`enum ssam_event_mask <ssam_event_mask>`
  189. @@ -312,7 +314,9 @@ Handling Events
  190. To receive events from the SAM EC, an event notifier must be registered for
  191. the desired event via |ssam_notifier_register|. The notifier must be
  192. unregistered via |ssam_notifier_unregister| once it is not required any
  193. -more.
  194. +more. For |ssam_device| type clients, the |ssam_device_notifier_register| and
  195. +|ssam_device_notifier_unregister| wrappers should be preferred as they properly
  196. +handle hot-removal of client devices.
  197. Event notifiers are registered by providing (at minimum) a callback to call
  198. in case an event has been received, the registry specifying how the event
  199. diff --git a/drivers/platform/surface/aggregator/controller.c b/drivers/platform/surface/aggregator/controller.c
  200. index b8c377b3f932..6de834b52b63 100644
  201. --- a/drivers/platform/surface/aggregator/controller.c
  202. +++ b/drivers/platform/surface/aggregator/controller.c
  203. @@ -2199,16 +2199,26 @@ static int ssam_nf_refcount_enable(struct ssam_controller *ctrl,
  204. }
  205. /**
  206. - * ssam_nf_refcount_disable_free() - Disable event for reference count entry if it is
  207. - * no longer in use and free the corresponding entry.
  208. + * ssam_nf_refcount_disable_free() - Disable event for reference count entry if
  209. + * it is no longer in use and free the corresponding entry.
  210. * @ctrl: The controller to disable the event on.
  211. * @entry: The reference count entry for the event to be disabled.
  212. * @flags: The flags used for enabling the event on the EC.
  213. + * @ec: Flag specifying if the event should actually be disabled on the EC.
  214. *
  215. - * If the reference count equals zero, i.e. the event is no longer requested by
  216. - * any client, the event will be disabled and the corresponding reference count
  217. - * entry freed. The reference count entry must not be used any more after a
  218. - * call to this function.
  219. + * If ``ec`` equals ``true`` and the reference count equals zero (i.e. the
  220. + * event is no longer requested by any client), the specified event will be
  221. + * disabled on the EC via the corresponding request.
  222. + *
  223. + * If ``ec`` equals ``false``, no request will be sent to the EC and the event
  224. + * can be considered in a detached state (i.e. no longer used but still
  225. + * enabled). Disabling an event via this method may be required for
  226. + * hot-removable devices, where event disable requests may time out after the
  227. + * device has been physically removed.
  228. + *
  229. + * In both cases, if the reference count equals zero, the corresponding
  230. + * reference count entry will be freed. The reference count entry must not be
  231. + * used any more after a call to this function.
  232. *
  233. * Also checks if the flags used for disabling the event match the flags used
  234. * for enabling the event and warns if they do not (regardless of reference
  235. @@ -2223,7 +2233,7 @@ static int ssam_nf_refcount_enable(struct ssam_controller *ctrl,
  236. * returns the status of the event-enable EC command.
  237. */
  238. static int ssam_nf_refcount_disable_free(struct ssam_controller *ctrl,
  239. - struct ssam_nf_refcount_entry *entry, u8 flags)
  240. + struct ssam_nf_refcount_entry *entry, u8 flags, bool ec)
  241. {
  242. const struct ssam_event_registry reg = entry->key.reg;
  243. const struct ssam_event_id id = entry->key.id;
  244. @@ -2232,8 +2242,9 @@ static int ssam_nf_refcount_disable_free(struct ssam_controller *ctrl,
  245. lockdep_assert_held(&nf->lock);
  246. - ssam_dbg(ctrl, "disabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n",
  247. - reg.target_category, id.target_category, id.instance, entry->refcount);
  248. + ssam_dbg(ctrl, "%s event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n",
  249. + ec ? "disabling" : "detaching", reg.target_category, id.target_category,
  250. + id.instance, entry->refcount);
  251. if (entry->flags != flags) {
  252. ssam_warn(ctrl,
  253. @@ -2242,7 +2253,7 @@ static int ssam_nf_refcount_disable_free(struct ssam_controller *ctrl,
  254. id.instance);
  255. }
  256. - if (entry->refcount == 0) {
  257. + if (ec && entry->refcount == 0) {
  258. status = ssam_ssh_event_disable(ctrl, reg, id, flags);
  259. kfree(entry);
  260. }
  261. @@ -2322,20 +2333,26 @@ int ssam_notifier_register(struct ssam_controller *ctrl, struct ssam_event_notif
  262. EXPORT_SYMBOL_GPL(ssam_notifier_register);
  263. /**
  264. - * ssam_notifier_unregister() - Unregister an event notifier.
  265. - * @ctrl: The controller the notifier has been registered on.
  266. - * @n: The event notifier to unregister.
  267. + * __ssam_notifier_unregister() - Unregister an event notifier.
  268. + * @ctrl: The controller the notifier has been registered on.
  269. + * @n: The event notifier to unregister.
  270. + * @disable: Whether to disable the corresponding event on the EC.
  271. *
  272. * Unregister an event notifier. Decrement the usage counter of the associated
  273. * SAM event if the notifier is not marked as an observer. If the usage counter
  274. - * reaches zero, the event will be disabled.
  275. + * reaches zero and ``disable`` equals ``true``, the event will be disabled.
  276. + *
  277. + * Useful for hot-removable devices, where communication may fail once the
  278. + * device has been physically removed. In that case, specifying ``disable`` as
  279. + * ``false`` avoids communication with the EC.
  280. *
  281. * Return: Returns zero on success, %-ENOENT if the given notifier block has
  282. * not been registered on the controller. If the given notifier block was the
  283. * last one associated with its specific event, returns the status of the
  284. * event-disable EC-command.
  285. */
  286. -int ssam_notifier_unregister(struct ssam_controller *ctrl, struct ssam_event_notifier *n)
  287. +int __ssam_notifier_unregister(struct ssam_controller *ctrl, struct ssam_event_notifier *n,
  288. + bool disable)
  289. {
  290. u16 rqid = ssh_tc_to_rqid(n->event.id.target_category);
  291. struct ssam_nf_refcount_entry *entry;
  292. @@ -2373,7 +2390,7 @@ int ssam_notifier_unregister(struct ssam_controller *ctrl, struct ssam_event_not
  293. goto remove;
  294. }
  295. - status = ssam_nf_refcount_disable_free(ctrl, entry, n->event.flags);
  296. + status = ssam_nf_refcount_disable_free(ctrl, entry, n->event.flags, disable);
  297. }
  298. remove:
  299. @@ -2383,7 +2400,7 @@ int ssam_notifier_unregister(struct ssam_controller *ctrl, struct ssam_event_not
  300. return status;
  301. }
  302. -EXPORT_SYMBOL_GPL(ssam_notifier_unregister);
  303. +EXPORT_SYMBOL_GPL(__ssam_notifier_unregister);
  304. /**
  305. * ssam_controller_event_enable() - Enable the specified event.
  306. @@ -2477,7 +2494,7 @@ int ssam_controller_event_disable(struct ssam_controller *ctrl,
  307. return -ENOENT;
  308. }
  309. - status = ssam_nf_refcount_disable_free(ctrl, entry, flags);
  310. + status = ssam_nf_refcount_disable_free(ctrl, entry, flags, true);
  311. mutex_unlock(&nf->lock);
  312. return status;
  313. diff --git a/include/linux/surface_aggregator/controller.h b/include/linux/surface_aggregator/controller.h
  314. index 74bfdffaf7b0..50a2b4926c06 100644
  315. --- a/include/linux/surface_aggregator/controller.h
  316. +++ b/include/linux/surface_aggregator/controller.h
  317. @@ -835,8 +835,28 @@ struct ssam_event_notifier {
  318. int ssam_notifier_register(struct ssam_controller *ctrl,
  319. struct ssam_event_notifier *n);
  320. -int ssam_notifier_unregister(struct ssam_controller *ctrl,
  321. - struct ssam_event_notifier *n);
  322. +int __ssam_notifier_unregister(struct ssam_controller *ctrl,
  323. + struct ssam_event_notifier *n, bool disable);
  324. +
  325. +/**
  326. + * ssam_notifier_unregister() - Unregister an event notifier.
  327. + * @ctrl: The controller the notifier has been registered on.
  328. + * @n: The event notifier to unregister.
  329. + *
  330. + * Unregister an event notifier. Decrement the usage counter of the associated
  331. + * SAM event if the notifier is not marked as an observer. If the usage counter
  332. + * reaches zero, the event will be disabled.
  333. + *
  334. + * Return: Returns zero on success, %-ENOENT if the given notifier block has
  335. + * not been registered on the controller. If the given notifier block was the
  336. + * last one associated with its specific event, returns the status of the
  337. + * event-disable EC-command.
  338. + */
  339. +static inline int ssam_notifier_unregister(struct ssam_controller *ctrl,
  340. + struct ssam_event_notifier *n)
  341. +{
  342. + return __ssam_notifier_unregister(ctrl, n, true);
  343. +}
  344. int ssam_controller_event_enable(struct ssam_controller *ctrl,
  345. struct ssam_event_registry reg,
  346. diff --git a/include/linux/surface_aggregator/device.h b/include/linux/surface_aggregator/device.h
  347. index 6df7c8d4e50e..c418f7f2732d 100644
  348. --- a/include/linux/surface_aggregator/device.h
  349. +++ b/include/linux/surface_aggregator/device.h
  350. @@ -483,4 +483,70 @@ static inline void ssam_remove_clients(struct device *dev) {}
  351. sdev->uid.instance, ret); \
  352. }
  353. +
  354. +/* -- Helpers for client-device notifiers. ---------------------------------- */
  355. +
  356. +/**
  357. + * ssam_device_notifier_register() - Register an event notifier for the
  358. + * specified client device.
  359. + * @sdev: The device the notifier should be registered on.
  360. + * @n: The event notifier to register.
  361. + *
  362. + * Register an event notifier. Increment the usage counter of the associated
  363. + * SAM event if the notifier is not marked as an observer. If the event is not
  364. + * marked as an observer and is currently not enabled, it will be enabled
  365. + * during this call. If the notifier is marked as an observer, no attempt will
  366. + * be made at enabling any event and no reference count will be modified.
  367. + *
  368. + * Notifiers marked as observers do not need to be associated with one specific
  369. + * event, i.e. as long as no event matching is performed, only the event target
  370. + * category needs to be set.
  371. + *
  372. + * Return: Returns zero on success, %-ENOSPC if there have already been
  373. + * %INT_MAX notifiers for the event ID/type associated with the notifier block
  374. + * registered, %-ENOMEM if the corresponding event entry could not be
  375. + * allocated, %-ENODEV if the device is marked as hot-removed. If this is the
  376. + * first time that a notifier block is registered for the specific associated
  377. + * event, returns the status of the event-enable EC-command.
  378. + */
  379. +static inline int ssam_device_notifier_register(struct ssam_device *sdev,
  380. + struct ssam_event_notifier *n)
  381. +{
  382. + /*
  383. + * Note that this check does not provide any guarantees whatsoever as
  384. + * hot-removal could happen at any point and we can't protect against
  385. + * it. Nevertheless, if we can detect hot-removal, bail early to avoid
  386. + * communication timeouts.
  387. + */
  388. + if (ssam_device_is_hot_removed(sdev))
  389. + return -ENODEV;
  390. +
  391. + return ssam_notifier_register(sdev->ctrl, n);
  392. +}
  393. +
  394. +/**
  395. + * ssam_device_notifier_unregister() - Unregister an event notifier for the
  396. + * specified client device.
  397. + * @sdev: The device the notifier has been registered on.
  398. + * @n: The event notifier to unregister.
  399. + *
  400. + * Unregister an event notifier. Decrement the usage counter of the associated
  401. + * SAM event if the notifier is not marked as an observer. If the usage counter
  402. + * reaches zero, the event will be disabled.
  403. + *
  404. + * In case the device has been marked as hot-removed, the event will not be
  405. + * disabled on the EC, as in those cases any attempt at doing so may time out.
  406. + *
  407. + * Return: Returns zero on success, %-ENOENT if the given notifier block has
  408. + * not been registered on the controller. If the given notifier block was the
  409. + * last one associated with its specific event, returns the status of the
  410. + * event-disable EC-command.
  411. + */
  412. +static inline int ssam_device_notifier_unregister(struct ssam_device *sdev,
  413. + struct ssam_event_notifier *n)
  414. +{
  415. + return __ssam_notifier_unregister(sdev->ctrl, n,
  416. + !ssam_device_is_hot_removed(sdev));
  417. +}
  418. +
  419. #endif /* _LINUX_SURFACE_AGGREGATOR_DEVICE_H */
  420. --
  421. 2.38.0
  422. From 0fd3d44ee0d9f061a61a909a0cc3fea3c61d40f0 Mon Sep 17 00:00:00 2001
  423. From: Maximilian Luz <luzmaximilian@gmail.com>
  424. Date: Fri, 27 May 2022 04:34:39 +0200
  425. Subject: [PATCH] platform/surface: aggregator_registry: Use client device
  426. wrappers for notifier registration
  427. Use newly introduced client device wrapper functions for notifier
  428. registration and unregistration.
  429. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  430. Link: https://lore.kernel.org/r/20220527023447.2460025-5-luzmaximilian@gmail.com
  431. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  432. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  433. Patchset: surface-sam
  434. ---
  435. drivers/platform/surface/surface_aggregator_registry.c | 6 +++---
  436. 1 file changed, 3 insertions(+), 3 deletions(-)
  437. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  438. index 08019c6ccc9c..71fe014d3ebb 100644
  439. --- a/drivers/platform/surface/surface_aggregator_registry.c
  440. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  441. @@ -468,7 +468,7 @@ static int ssam_base_hub_probe(struct ssam_device *sdev)
  442. ssam_device_set_drvdata(sdev, hub);
  443. - status = ssam_notifier_register(sdev->ctrl, &hub->notif);
  444. + status = ssam_device_notifier_register(sdev, &hub->notif);
  445. if (status)
  446. return status;
  447. @@ -480,7 +480,7 @@ static int ssam_base_hub_probe(struct ssam_device *sdev)
  448. return 0;
  449. err:
  450. - ssam_notifier_unregister(sdev->ctrl, &hub->notif);
  451. + ssam_device_notifier_unregister(sdev, &hub->notif);
  452. cancel_delayed_work_sync(&hub->update_work);
  453. ssam_remove_clients(&sdev->dev);
  454. return status;
  455. @@ -492,7 +492,7 @@ static void ssam_base_hub_remove(struct ssam_device *sdev)
  456. sysfs_remove_group(&sdev->dev.kobj, &ssam_base_hub_group);
  457. - ssam_notifier_unregister(sdev->ctrl, &hub->notif);
  458. + ssam_device_notifier_unregister(sdev, &hub->notif);
  459. cancel_delayed_work_sync(&hub->update_work);
  460. ssam_remove_clients(&sdev->dev);
  461. }
  462. --
  463. 2.38.0
  464. From cf13eafc909feea8e97fbd414e0b699c5a42dca5 Mon Sep 17 00:00:00 2001
  465. From: Maximilian Luz <luzmaximilian@gmail.com>
  466. Date: Fri, 27 May 2022 04:34:40 +0200
  467. Subject: [PATCH] power/supply: surface_charger: Use client device wrappers for
  468. notifier registration
  469. Use newly introduced client device wrapper functions for notifier
  470. registration and unregistration.
  471. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  472. Acked-by: Sebastian Reichel <sebastian.reichel@collabora.com>
  473. Link: https://lore.kernel.org/r/20220527023447.2460025-6-luzmaximilian@gmail.com
  474. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  475. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  476. Patchset: surface-sam
  477. ---
  478. drivers/power/supply/surface_charger.c | 4 ++--
  479. 1 file changed, 2 insertions(+), 2 deletions(-)
  480. diff --git a/drivers/power/supply/surface_charger.c b/drivers/power/supply/surface_charger.c
  481. index a060c36c7766..59182d55742d 100644
  482. --- a/drivers/power/supply/surface_charger.c
  483. +++ b/drivers/power/supply/surface_charger.c
  484. @@ -216,7 +216,7 @@ static int spwr_ac_register(struct spwr_ac_device *ac)
  485. if (IS_ERR(ac->psy))
  486. return PTR_ERR(ac->psy);
  487. - return ssam_notifier_register(ac->sdev->ctrl, &ac->notif);
  488. + return ssam_device_notifier_register(ac->sdev, &ac->notif);
  489. }
  490. @@ -251,7 +251,7 @@ static void surface_ac_remove(struct ssam_device *sdev)
  491. {
  492. struct spwr_ac_device *ac = ssam_device_get_drvdata(sdev);
  493. - ssam_notifier_unregister(sdev->ctrl, &ac->notif);
  494. + ssam_device_notifier_unregister(sdev, &ac->notif);
  495. }
  496. static const struct spwr_psy_properties spwr_psy_props_adp1 = {
  497. --
  498. 2.38.0
  499. From dc06c3418aa297013312a182d4c34da6609ce6de Mon Sep 17 00:00:00 2001
  500. From: Maximilian Luz <luzmaximilian@gmail.com>
  501. Date: Fri, 27 May 2022 04:34:41 +0200
  502. Subject: [PATCH] power/supply: surface_battery: Use client device wrappers for
  503. notifier registration
  504. Use newly introduced client device wrapper functions for notifier
  505. registration and unregistration.
  506. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  507. Acked-by: Sebastian Reichel <sebastian.reichel@collabora.com>
  508. Link: https://lore.kernel.org/r/20220527023447.2460025-7-luzmaximilian@gmail.com
  509. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  510. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  511. Patchset: surface-sam
  512. ---
  513. drivers/power/supply/surface_battery.c | 4 ++--
  514. 1 file changed, 2 insertions(+), 2 deletions(-)
  515. diff --git a/drivers/power/supply/surface_battery.c b/drivers/power/supply/surface_battery.c
  516. index 5ec2e6bb2465..540707882bb0 100644
  517. --- a/drivers/power/supply/surface_battery.c
  518. +++ b/drivers/power/supply/surface_battery.c
  519. @@ -802,7 +802,7 @@ static int spwr_battery_register(struct spwr_battery_device *bat)
  520. if (IS_ERR(bat->psy))
  521. return PTR_ERR(bat->psy);
  522. - return ssam_notifier_register(bat->sdev->ctrl, &bat->notif);
  523. + return ssam_device_notifier_register(bat->sdev, &bat->notif);
  524. }
  525. @@ -837,7 +837,7 @@ static void surface_battery_remove(struct ssam_device *sdev)
  526. {
  527. struct spwr_battery_device *bat = ssam_device_get_drvdata(sdev);
  528. - ssam_notifier_unregister(sdev->ctrl, &bat->notif);
  529. + ssam_device_notifier_unregister(sdev, &bat->notif);
  530. cancel_delayed_work_sync(&bat->update_work);
  531. }
  532. --
  533. 2.38.0
  534. From 900fd067b67e27666f43785ef0268e2c1b131eea Mon Sep 17 00:00:00 2001
  535. From: Maximilian Luz <luzmaximilian@gmail.com>
  536. Date: Fri, 27 May 2022 04:34:42 +0200
  537. Subject: [PATCH] HID: surface-hid: Add support for hot-removal
  538. Add support for hot-removal of SSAM HID client devices.
  539. Once a device has been hot-removed, further communication with it should
  540. be avoided as it may fail and time out. While the device will be removed
  541. as soon as we detect hot-removal, communication may still occur during
  542. teardown, especially when unregistering notifiers.
  543. While hot-removal is a surprise event that can happen at any time, try
  544. to avoid communication as much as possible once it has been detected to
  545. prevent timeouts that can slow down device removal and cause issues,
  546. e.g. when quickly re-attaching the device.
  547. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  548. Link: https://lore.kernel.org/r/20220527023447.2460025-8-luzmaximilian@gmail.com
  549. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  550. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  551. Patchset: surface-sam
  552. ---
  553. drivers/hid/surface-hid/surface_hid_core.c | 38 +++++++++++++++++++++-
  554. 1 file changed, 37 insertions(+), 1 deletion(-)
  555. diff --git a/drivers/hid/surface-hid/surface_hid_core.c b/drivers/hid/surface-hid/surface_hid_core.c
  556. index e46330b2e561..87637f813de2 100644
  557. --- a/drivers/hid/surface-hid/surface_hid_core.c
  558. +++ b/drivers/hid/surface-hid/surface_hid_core.c
  559. @@ -19,12 +19,30 @@
  560. #include "surface_hid_core.h"
  561. +/* -- Utility functions. ---------------------------------------------------- */
  562. +
  563. +static bool surface_hid_is_hot_removed(struct surface_hid_device *shid)
  564. +{
  565. + /*
  566. + * Non-ssam client devices, i.e. platform client devices, cannot be
  567. + * hot-removed.
  568. + */
  569. + if (!is_ssam_device(shid->dev))
  570. + return false;
  571. +
  572. + return ssam_device_is_hot_removed(to_ssam_device(shid->dev));
  573. +}
  574. +
  575. +
  576. /* -- Device descriptor access. --------------------------------------------- */
  577. static int surface_hid_load_hid_descriptor(struct surface_hid_device *shid)
  578. {
  579. int status;
  580. + if (surface_hid_is_hot_removed(shid))
  581. + return -ENODEV;
  582. +
  583. status = shid->ops.get_descriptor(shid, SURFACE_HID_DESC_HID,
  584. (u8 *)&shid->hid_desc, sizeof(shid->hid_desc));
  585. if (status)
  586. @@ -61,6 +79,9 @@ static int surface_hid_load_device_attributes(struct surface_hid_device *shid)
  587. {
  588. int status;
  589. + if (surface_hid_is_hot_removed(shid))
  590. + return -ENODEV;
  591. +
  592. status = shid->ops.get_descriptor(shid, SURFACE_HID_DESC_ATTRS,
  593. (u8 *)&shid->attrs, sizeof(shid->attrs));
  594. if (status)
  595. @@ -88,9 +109,18 @@ static int surface_hid_start(struct hid_device *hid)
  596. static void surface_hid_stop(struct hid_device *hid)
  597. {
  598. struct surface_hid_device *shid = hid->driver_data;
  599. + bool hot_removed;
  600. +
  601. + /*
  602. + * Communication may fail for devices that have been hot-removed. This
  603. + * also includes unregistration of HID events, so we need to check this
  604. + * here. Only if the device has not been marked as hot-removed, we can
  605. + * safely disable events.
  606. + */
  607. + hot_removed = surface_hid_is_hot_removed(shid);
  608. /* Note: This call will log errors for us, so ignore them here. */
  609. - ssam_notifier_unregister(shid->ctrl, &shid->notif);
  610. + __ssam_notifier_unregister(shid->ctrl, &shid->notif, !hot_removed);
  611. }
  612. static int surface_hid_open(struct hid_device *hid)
  613. @@ -109,6 +139,9 @@ static int surface_hid_parse(struct hid_device *hid)
  614. u8 *buf;
  615. int status;
  616. + if (surface_hid_is_hot_removed(shid))
  617. + return -ENODEV;
  618. +
  619. buf = kzalloc(len, GFP_KERNEL);
  620. if (!buf)
  621. return -ENOMEM;
  622. @@ -126,6 +159,9 @@ static int surface_hid_raw_request(struct hid_device *hid, unsigned char reportn
  623. {
  624. struct surface_hid_device *shid = hid->driver_data;
  625. + if (surface_hid_is_hot_removed(shid))
  626. + return -ENODEV;
  627. +
  628. if (rtype == HID_OUTPUT_REPORT && reqtype == HID_REQ_SET_REPORT)
  629. return shid->ops.output_report(shid, reportnum, buf, len);
  630. --
  631. 2.38.0
  632. From 6b145011e2842f8c0bfd947283ac2183f113604c Mon Sep 17 00:00:00 2001
  633. From: Maximilian Luz <luzmaximilian@gmail.com>
  634. Date: Fri, 27 May 2022 04:34:43 +0200
  635. Subject: [PATCH] platform/surface: aggregator: Add comment for KIP subsystem
  636. category
  637. The KIP subsystem (full name unknown, abbreviation has been obtained
  638. through reverse engineering) handles detachable peripherals such as the
  639. keyboard cover on the Surface Pro X and Surface Pro 8.
  640. It is currently not entirely clear what this subsystem entails, but at
  641. the very least it provides event notifications for when the keyboard
  642. cover on the Surface Pro X and Surface Pro 8 have been detached or
  643. re-attached, as well as the state that the keyboard cover is currently
  644. in (e.g. folded-back, folded laptop-like, closed, etc.).
  645. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  646. Link: https://lore.kernel.org/r/20220527023447.2460025-9-luzmaximilian@gmail.com
  647. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  648. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  649. Patchset: surface-sam
  650. ---
  651. include/linux/surface_aggregator/serial_hub.h | 2 +-
  652. 1 file changed, 1 insertion(+), 1 deletion(-)
  653. diff --git a/include/linux/surface_aggregator/serial_hub.h b/include/linux/surface_aggregator/serial_hub.h
  654. index c3de43edcffa..26b95ec12733 100644
  655. --- a/include/linux/surface_aggregator/serial_hub.h
  656. +++ b/include/linux/surface_aggregator/serial_hub.h
  657. @@ -306,7 +306,7 @@ enum ssam_ssh_tc {
  658. SSAM_SSH_TC_LPC = 0x0b,
  659. SSAM_SSH_TC_TCL = 0x0c,
  660. SSAM_SSH_TC_SFL = 0x0d,
  661. - SSAM_SSH_TC_KIP = 0x0e,
  662. + SSAM_SSH_TC_KIP = 0x0e, /* Manages detachable peripherals (Pro X/8 keyboard cover) */
  663. SSAM_SSH_TC_EXT = 0x0f,
  664. SSAM_SSH_TC_BLD = 0x10,
  665. SSAM_SSH_TC_BAS = 0x11, /* Detachment system (Surface Book 2/3). */
  666. --
  667. 2.38.0
  668. From 9767e9af49e71d638777210bdbbb1a6ec83c00bf Mon Sep 17 00:00:00 2001
  669. From: Maximilian Luz <luzmaximilian@gmail.com>
  670. Date: Fri, 27 May 2022 04:34:44 +0200
  671. Subject: [PATCH] platform/surface: aggregator_registry: Generify subsystem hub
  672. functionality
  673. The Surface System Aggregator Module (SSAM) has multiple subsystems that
  674. can manage detachable devices. At the moment, we only support the "base"
  675. (BAS/0x11) subsystem, which is used on the Surface Book 3 to manage
  676. devices (including keyboard, touchpad, and secondary battery) connected
  677. to the base of the device.
  678. The Surface Pro 8 has a new type-cover with keyboard and touchpad, which
  679. is managed via the KIP/0x0e subsystem. The general procedure is the
  680. same, but with slightly different events and setup. To make
  681. implementation of the KIP hub easier and prevent duplication, generify
  682. the parts of the base hub that we can use for the KIP hub (or any
  683. potential future subsystem hubs).
  684. This also switches over to use the newly introduced "hot-remove"
  685. functionality, which should prevent communication issues when devices
  686. have been detached.
  687. Lastly, also drop the undocumented and unused sysfs "state" attribute of
  688. the base hub. It has at best been useful for debugging.
  689. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  690. Link: https://lore.kernel.org/r/20220527023447.2460025-10-luzmaximilian@gmail.com
  691. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  692. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  693. Patchset: surface-sam
  694. ---
  695. .../surface/surface_aggregator_registry.c | 269 ++++++++++--------
  696. 1 file changed, 153 insertions(+), 116 deletions(-)
  697. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  698. index 71fe014d3ebb..0b1ca1155770 100644
  699. --- a/drivers/platform/surface/surface_aggregator_registry.c
  700. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  701. @@ -308,30 +308,159 @@ static int ssam_hub_register_clients(struct device *parent, struct ssam_controll
  702. }
  703. -/* -- SSAM base-hub driver. ------------------------------------------------- */
  704. +/* -- SSAM generic subsystem hub driver framework. -------------------------- */
  705. -/*
  706. - * Some devices (especially battery) may need a bit of time to be fully usable
  707. - * after being (re-)connected. This delay has been determined via
  708. - * experimentation.
  709. - */
  710. -#define SSAM_BASE_UPDATE_CONNECT_DELAY msecs_to_jiffies(2500)
  711. +enum ssam_hub_state {
  712. + SSAM_HUB_UNINITIALIZED, /* Only set during initialization. */
  713. + SSAM_HUB_CONNECTED,
  714. + SSAM_HUB_DISCONNECTED,
  715. +};
  716. -enum ssam_base_hub_state {
  717. - SSAM_BASE_HUB_UNINITIALIZED,
  718. - SSAM_BASE_HUB_CONNECTED,
  719. - SSAM_BASE_HUB_DISCONNECTED,
  720. +enum ssam_hub_flags {
  721. + SSAM_HUB_HOT_REMOVED,
  722. };
  723. -struct ssam_base_hub {
  724. +struct ssam_hub {
  725. struct ssam_device *sdev;
  726. - enum ssam_base_hub_state state;
  727. + enum ssam_hub_state state;
  728. + unsigned long flags;
  729. +
  730. struct delayed_work update_work;
  731. + unsigned long connect_delay;
  732. struct ssam_event_notifier notif;
  733. +
  734. + int (*get_state)(struct ssam_hub *hub, enum ssam_hub_state *state);
  735. };
  736. +static void ssam_hub_update_workfn(struct work_struct *work)
  737. +{
  738. + struct ssam_hub *hub = container_of(work, struct ssam_hub, update_work.work);
  739. + struct fwnode_handle *node = dev_fwnode(&hub->sdev->dev);
  740. + enum ssam_hub_state state;
  741. + int status = 0;
  742. +
  743. + status = hub->get_state(hub, &state);
  744. + if (status)
  745. + return;
  746. +
  747. + /*
  748. + * There is a small possibility that hub devices were hot-removed and
  749. + * re-added before we were able to remove them here. In that case, both
  750. + * the state returned by get_state() and the state of the hub will
  751. + * equal SSAM_HUB_CONNECTED and we would bail early below, which would
  752. + * leave child devices without proper (re-)initialization and the
  753. + * hot-remove flag set.
  754. + *
  755. + * Therefore, we check whether devices have been hot-removed via an
  756. + * additional flag on the hub and, in this case, override the returned
  757. + * hub state. In case of a missed disconnect (i.e. get_state returned
  758. + * "connected"), we further need to re-schedule this work (with the
  759. + * appropriate delay) as the actual connect work submission might have
  760. + * been merged with this one.
  761. + *
  762. + * This then leads to one of two cases: Either we submit an unnecessary
  763. + * work item (which will get ignored via either the queue or the state
  764. + * checks) or, in the unlikely case that the work is actually required,
  765. + * double the normal connect delay.
  766. + */
  767. + if (test_and_clear_bit(SSAM_HUB_HOT_REMOVED, &hub->flags)) {
  768. + if (state == SSAM_HUB_CONNECTED)
  769. + schedule_delayed_work(&hub->update_work, hub->connect_delay);
  770. +
  771. + state = SSAM_HUB_DISCONNECTED;
  772. + }
  773. +
  774. + if (hub->state == state)
  775. + return;
  776. + hub->state = state;
  777. +
  778. + if (hub->state == SSAM_HUB_CONNECTED)
  779. + status = ssam_hub_register_clients(&hub->sdev->dev, hub->sdev->ctrl, node);
  780. + else
  781. + ssam_remove_clients(&hub->sdev->dev);
  782. +
  783. + if (status)
  784. + dev_err(&hub->sdev->dev, "failed to update hub child devices: %d\n", status);
  785. +}
  786. +
  787. +static int ssam_hub_mark_hot_removed(struct device *dev, void *_data)
  788. +{
  789. + struct ssam_device *sdev = to_ssam_device(dev);
  790. +
  791. + if (is_ssam_device(dev))
  792. + ssam_device_mark_hot_removed(sdev);
  793. +
  794. + return 0;
  795. +}
  796. +
  797. +static void ssam_hub_update(struct ssam_hub *hub, bool connected)
  798. +{
  799. + unsigned long delay;
  800. +
  801. + /* Mark devices as hot-removed before we remove any. */
  802. + if (!connected) {
  803. + set_bit(SSAM_HUB_HOT_REMOVED, &hub->flags);
  804. + device_for_each_child_reverse(&hub->sdev->dev, NULL, ssam_hub_mark_hot_removed);
  805. + }
  806. +
  807. + /*
  808. + * Delay update when the base/keyboard cover is being connected to give
  809. + * devices/EC some time to set up.
  810. + */
  811. + delay = connected ? hub->connect_delay : 0;
  812. +
  813. + schedule_delayed_work(&hub->update_work, delay);
  814. +}
  815. +
  816. +static int __maybe_unused ssam_hub_resume(struct device *dev)
  817. +{
  818. + struct ssam_hub *hub = dev_get_drvdata(dev);
  819. +
  820. + schedule_delayed_work(&hub->update_work, 0);
  821. + return 0;
  822. +}
  823. +static SIMPLE_DEV_PM_OPS(ssam_hub_pm_ops, NULL, ssam_hub_resume);
  824. +
  825. +static int ssam_hub_setup(struct ssam_device *sdev, struct ssam_hub *hub)
  826. +{
  827. + int status;
  828. +
  829. + hub->sdev = sdev;
  830. + hub->state = SSAM_HUB_UNINITIALIZED;
  831. +
  832. + INIT_DELAYED_WORK(&hub->update_work, ssam_hub_update_workfn);
  833. +
  834. + ssam_device_set_drvdata(sdev, hub);
  835. +
  836. + status = ssam_device_notifier_register(sdev, &hub->notif);
  837. + if (status)
  838. + return status;
  839. +
  840. + schedule_delayed_work(&hub->update_work, 0);
  841. + return 0;
  842. +}
  843. +
  844. +static void ssam_hub_remove(struct ssam_device *sdev)
  845. +{
  846. + struct ssam_hub *hub = ssam_device_get_drvdata(sdev);
  847. +
  848. + ssam_device_notifier_unregister(sdev, &hub->notif);
  849. + cancel_delayed_work_sync(&hub->update_work);
  850. + ssam_remove_clients(&sdev->dev);
  851. +}
  852. +
  853. +
  854. +/* -- SSAM base-hub driver. ------------------------------------------------- */
  855. +
  856. +/*
  857. + * Some devices (especially battery) may need a bit of time to be fully usable
  858. + * after being (re-)connected. This delay has been determined via
  859. + * experimentation.
  860. + */
  861. +#define SSAM_BASE_UPDATE_CONNECT_DELAY msecs_to_jiffies(2500)
  862. +
  863. SSAM_DEFINE_SYNC_REQUEST_R(ssam_bas_query_opmode, u8, {
  864. .target_category = SSAM_SSH_TC_BAS,
  865. .target_id = 0x01,
  866. @@ -342,7 +471,7 @@ SSAM_DEFINE_SYNC_REQUEST_R(ssam_bas_query_opmode, u8, {
  867. #define SSAM_BAS_OPMODE_TABLET 0x00
  868. #define SSAM_EVENT_BAS_CID_CONNECTION 0x0c
  869. -static int ssam_base_hub_query_state(struct ssam_base_hub *hub, enum ssam_base_hub_state *state)
  870. +static int ssam_base_hub_query_state(struct ssam_hub *hub, enum ssam_hub_state *state)
  871. {
  872. u8 opmode;
  873. int status;
  874. @@ -354,62 +483,16 @@ static int ssam_base_hub_query_state(struct ssam_base_hub *hub, enum ssam_base_h
  875. }
  876. if (opmode != SSAM_BAS_OPMODE_TABLET)
  877. - *state = SSAM_BASE_HUB_CONNECTED;
  878. + *state = SSAM_HUB_CONNECTED;
  879. else
  880. - *state = SSAM_BASE_HUB_DISCONNECTED;
  881. + *state = SSAM_HUB_DISCONNECTED;
  882. return 0;
  883. }
  884. -static ssize_t ssam_base_hub_state_show(struct device *dev, struct device_attribute *attr,
  885. - char *buf)
  886. -{
  887. - struct ssam_base_hub *hub = dev_get_drvdata(dev);
  888. - bool connected = hub->state == SSAM_BASE_HUB_CONNECTED;
  889. -
  890. - return sysfs_emit(buf, "%d\n", connected);
  891. -}
  892. -
  893. -static struct device_attribute ssam_base_hub_attr_state =
  894. - __ATTR(state, 0444, ssam_base_hub_state_show, NULL);
  895. -
  896. -static struct attribute *ssam_base_hub_attrs[] = {
  897. - &ssam_base_hub_attr_state.attr,
  898. - NULL,
  899. -};
  900. -
  901. -static const struct attribute_group ssam_base_hub_group = {
  902. - .attrs = ssam_base_hub_attrs,
  903. -};
  904. -
  905. -static void ssam_base_hub_update_workfn(struct work_struct *work)
  906. -{
  907. - struct ssam_base_hub *hub = container_of(work, struct ssam_base_hub, update_work.work);
  908. - struct fwnode_handle *node = dev_fwnode(&hub->sdev->dev);
  909. - enum ssam_base_hub_state state;
  910. - int status = 0;
  911. -
  912. - status = ssam_base_hub_query_state(hub, &state);
  913. - if (status)
  914. - return;
  915. -
  916. - if (hub->state == state)
  917. - return;
  918. - hub->state = state;
  919. -
  920. - if (hub->state == SSAM_BASE_HUB_CONNECTED)
  921. - status = ssam_hub_register_clients(&hub->sdev->dev, hub->sdev->ctrl, node);
  922. - else
  923. - ssam_remove_clients(&hub->sdev->dev);
  924. -
  925. - if (status)
  926. - dev_err(&hub->sdev->dev, "failed to update base-hub devices: %d\n", status);
  927. -}
  928. -
  929. static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
  930. {
  931. - struct ssam_base_hub *hub = container_of(nf, struct ssam_base_hub, notif);
  932. - unsigned long delay;
  933. + struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
  934. if (event->command_id != SSAM_EVENT_BAS_CID_CONNECTION)
  935. return 0;
  936. @@ -419,13 +502,7 @@ static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam
  937. return 0;
  938. }
  939. - /*
  940. - * Delay update when the base is being connected to give devices/EC
  941. - * some time to set up.
  942. - */
  943. - delay = event->data[0] ? SSAM_BASE_UPDATE_CONNECT_DELAY : 0;
  944. -
  945. - schedule_delayed_work(&hub->update_work, delay);
  946. + ssam_hub_update(hub, event->data[0]);
  947. /*
  948. * Do not return SSAM_NOTIF_HANDLED: The event should be picked up and
  949. @@ -435,27 +512,14 @@ static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam
  950. return 0;
  951. }
  952. -static int __maybe_unused ssam_base_hub_resume(struct device *dev)
  953. -{
  954. - struct ssam_base_hub *hub = dev_get_drvdata(dev);
  955. -
  956. - schedule_delayed_work(&hub->update_work, 0);
  957. - return 0;
  958. -}
  959. -static SIMPLE_DEV_PM_OPS(ssam_base_hub_pm_ops, NULL, ssam_base_hub_resume);
  960. -
  961. static int ssam_base_hub_probe(struct ssam_device *sdev)
  962. {
  963. - struct ssam_base_hub *hub;
  964. - int status;
  965. + struct ssam_hub *hub;
  966. hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL);
  967. if (!hub)
  968. return -ENOMEM;
  969. - hub->sdev = sdev;
  970. - hub->state = SSAM_BASE_HUB_UNINITIALIZED;
  971. -
  972. hub->notif.base.priority = INT_MAX; /* This notifier should run first. */
  973. hub->notif.base.fn = ssam_base_hub_notif;
  974. hub->notif.event.reg = SSAM_EVENT_REGISTRY_SAM;
  975. @@ -464,37 +528,10 @@ static int ssam_base_hub_probe(struct ssam_device *sdev)
  976. hub->notif.event.mask = SSAM_EVENT_MASK_NONE;
  977. hub->notif.event.flags = SSAM_EVENT_SEQUENCED;
  978. - INIT_DELAYED_WORK(&hub->update_work, ssam_base_hub_update_workfn);
  979. -
  980. - ssam_device_set_drvdata(sdev, hub);
  981. -
  982. - status = ssam_device_notifier_register(sdev, &hub->notif);
  983. - if (status)
  984. - return status;
  985. -
  986. - status = sysfs_create_group(&sdev->dev.kobj, &ssam_base_hub_group);
  987. - if (status)
  988. - goto err;
  989. -
  990. - schedule_delayed_work(&hub->update_work, 0);
  991. - return 0;
  992. + hub->connect_delay = SSAM_BASE_UPDATE_CONNECT_DELAY;
  993. + hub->get_state = ssam_base_hub_query_state;
  994. -err:
  995. - ssam_device_notifier_unregister(sdev, &hub->notif);
  996. - cancel_delayed_work_sync(&hub->update_work);
  997. - ssam_remove_clients(&sdev->dev);
  998. - return status;
  999. -}
  1000. -
  1001. -static void ssam_base_hub_remove(struct ssam_device *sdev)
  1002. -{
  1003. - struct ssam_base_hub *hub = ssam_device_get_drvdata(sdev);
  1004. -
  1005. - sysfs_remove_group(&sdev->dev.kobj, &ssam_base_hub_group);
  1006. -
  1007. - ssam_device_notifier_unregister(sdev, &hub->notif);
  1008. - cancel_delayed_work_sync(&hub->update_work);
  1009. - ssam_remove_clients(&sdev->dev);
  1010. + return ssam_hub_setup(sdev, hub);
  1011. }
  1012. static const struct ssam_device_id ssam_base_hub_match[] = {
  1013. @@ -504,12 +541,12 @@ static const struct ssam_device_id ssam_base_hub_match[] = {
  1014. static struct ssam_device_driver ssam_base_hub_driver = {
  1015. .probe = ssam_base_hub_probe,
  1016. - .remove = ssam_base_hub_remove,
  1017. + .remove = ssam_hub_remove,
  1018. .match_table = ssam_base_hub_match,
  1019. .driver = {
  1020. .name = "surface_aggregator_base_hub",
  1021. .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  1022. - .pm = &ssam_base_hub_pm_ops,
  1023. + .pm = &ssam_hub_pm_ops,
  1024. },
  1025. };
  1026. --
  1027. 2.38.0
  1028. From e668d006ec6ad044f993c0857afee7f3f0303709 Mon Sep 17 00:00:00 2001
  1029. From: Maximilian Luz <luzmaximilian@gmail.com>
  1030. Date: Fri, 27 May 2022 04:34:45 +0200
  1031. Subject: [PATCH] platform/surface: aggregator_registry: Change device ID for
  1032. base hub
  1033. Use the target category of the (base) hub as instance id in the
  1034. (virtual) hub device UID. This makes association of the hub with the
  1035. respective subsystem easier.
  1036. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  1037. Link: https://lore.kernel.org/r/20220527023447.2460025-11-luzmaximilian@gmail.com
  1038. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  1039. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  1040. Patchset: surface-sam
  1041. ---
  1042. drivers/platform/surface/surface_aggregator_registry.c | 4 ++--
  1043. 1 file changed, 2 insertions(+), 2 deletions(-)
  1044. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  1045. index 0b1ca1155770..d0e9e287c7e5 100644
  1046. --- a/drivers/platform/surface/surface_aggregator_registry.c
  1047. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  1048. @@ -43,7 +43,7 @@ static const struct software_node ssam_node_root = {
  1049. /* Base device hub (devices attached to Surface Book 3 base). */
  1050. static const struct software_node ssam_node_hub_base = {
  1051. - .name = "ssam:00:00:02:00:00",
  1052. + .name = "ssam:00:00:02:11:00",
  1053. .parent = &ssam_node_root,
  1054. };
  1055. @@ -535,7 +535,7 @@ static int ssam_base_hub_probe(struct ssam_device *sdev)
  1056. }
  1057. static const struct ssam_device_id ssam_base_hub_match[] = {
  1058. - { SSAM_VDEV(HUB, 0x02, SSAM_ANY_IID, 0x00) },
  1059. + { SSAM_VDEV(HUB, 0x02, SSAM_SSH_TC_BAS, 0x00) },
  1060. { },
  1061. };
  1062. --
  1063. 2.38.0
  1064. From 607f5c3e825c05bf0a5b9fa2e9570bc01cef2770 Mon Sep 17 00:00:00 2001
  1065. From: Maximilian Luz <luzmaximilian@gmail.com>
  1066. Date: Fri, 27 May 2022 04:34:46 +0200
  1067. Subject: [PATCH] platform/surface: aggregator_registry: Add KIP device hub
  1068. Add a Surface System Aggregator Module (SSAM) client device hub for
  1069. hot-removable devices managed via the KIP subsystem.
  1070. The KIP subsystem (full name unknown, abbreviation has been obtained
  1071. through reverse engineering) is a subsystem that manages hot-removable
  1072. SSAM client devices. Specifically, it manages HID input devices
  1073. contained in the detachable keyboard cover of the Surface Pro 8 and
  1074. Surface Pro X.
  1075. The KIP subsystem handles a single group of devices (e.g. all devices
  1076. contained in the keyboard cover) and cannot handle devices individually.
  1077. Thus we model it as a client device hub, which (hot-)removes all devices
  1078. contained under it once removal of the hub (e.g. keyboard cover) has
  1079. been detected and (re-)adds all devices once the physical hub device has
  1080. been (re-)attached. To do this, use the previously generified SSAM
  1081. subsystem hub framework.
  1082. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  1083. Link: https://lore.kernel.org/r/20220527023447.2460025-12-luzmaximilian@gmail.com
  1084. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  1085. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  1086. Patchset: surface-sam
  1087. ---
  1088. .../surface/surface_aggregator_registry.c | 103 +++++++++++++++++-
  1089. 1 file changed, 101 insertions(+), 2 deletions(-)
  1090. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  1091. index d0e9e287c7e5..0b4aeba4ad93 100644
  1092. --- a/drivers/platform/surface/surface_aggregator_registry.c
  1093. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  1094. @@ -551,6 +551,93 @@ static struct ssam_device_driver ssam_base_hub_driver = {
  1095. };
  1096. +/* -- SSAM KIP-subsystem hub driver. ---------------------------------------- */
  1097. +
  1098. +/*
  1099. + * Some devices may need a bit of time to be fully usable after being
  1100. + * (re-)connected. This delay has been determined via experimentation.
  1101. + */
  1102. +#define SSAM_KIP_UPDATE_CONNECT_DELAY msecs_to_jiffies(250)
  1103. +
  1104. +#define SSAM_EVENT_KIP_CID_CONNECTION 0x2c
  1105. +
  1106. +SSAM_DEFINE_SYNC_REQUEST_R(__ssam_kip_get_connection_state, u8, {
  1107. + .target_category = SSAM_SSH_TC_KIP,
  1108. + .target_id = 0x01,
  1109. + .command_id = 0x2c,
  1110. + .instance_id = 0x00,
  1111. +});
  1112. +
  1113. +static int ssam_kip_get_connection_state(struct ssam_hub *hub, enum ssam_hub_state *state)
  1114. +{
  1115. + int status;
  1116. + u8 connected;
  1117. +
  1118. + status = ssam_retry(__ssam_kip_get_connection_state, hub->sdev->ctrl, &connected);
  1119. + if (status < 0) {
  1120. + dev_err(&hub->sdev->dev, "failed to query KIP connection state: %d\n", status);
  1121. + return status;
  1122. + }
  1123. +
  1124. + *state = connected ? SSAM_HUB_CONNECTED : SSAM_HUB_DISCONNECTED;
  1125. + return 0;
  1126. +}
  1127. +
  1128. +static u32 ssam_kip_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
  1129. +{
  1130. + struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
  1131. +
  1132. + if (event->command_id != SSAM_EVENT_KIP_CID_CONNECTION)
  1133. + return 0; /* Return "unhandled". */
  1134. +
  1135. + if (event->length < 1) {
  1136. + dev_err(&hub->sdev->dev, "unexpected payload size: %u\n", event->length);
  1137. + return 0;
  1138. + }
  1139. +
  1140. + ssam_hub_update(hub, event->data[0]);
  1141. + return SSAM_NOTIF_HANDLED;
  1142. +}
  1143. +
  1144. +static int ssam_kip_hub_probe(struct ssam_device *sdev)
  1145. +{
  1146. + struct ssam_hub *hub;
  1147. +
  1148. + hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL);
  1149. + if (!hub)
  1150. + return -ENOMEM;
  1151. +
  1152. + hub->notif.base.priority = INT_MAX; /* This notifier should run first. */
  1153. + hub->notif.base.fn = ssam_kip_hub_notif;
  1154. + hub->notif.event.reg = SSAM_EVENT_REGISTRY_SAM;
  1155. + hub->notif.event.id.target_category = SSAM_SSH_TC_KIP,
  1156. + hub->notif.event.id.instance = 0,
  1157. + hub->notif.event.mask = SSAM_EVENT_MASK_TARGET;
  1158. + hub->notif.event.flags = SSAM_EVENT_SEQUENCED;
  1159. +
  1160. + hub->connect_delay = SSAM_KIP_UPDATE_CONNECT_DELAY;
  1161. + hub->get_state = ssam_kip_get_connection_state;
  1162. +
  1163. + return ssam_hub_setup(sdev, hub);
  1164. +}
  1165. +
  1166. +static const struct ssam_device_id ssam_kip_hub_match[] = {
  1167. + { SSAM_VDEV(HUB, 0x01, SSAM_SSH_TC_KIP, 0x00) },
  1168. + { },
  1169. +};
  1170. +
  1171. +static struct ssam_device_driver ssam_kip_hub_driver = {
  1172. + .probe = ssam_kip_hub_probe,
  1173. + .remove = ssam_hub_remove,
  1174. + .match_table = ssam_kip_hub_match,
  1175. + .driver = {
  1176. + .name = "surface_kip_hub",
  1177. + .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  1178. + .pm = &ssam_hub_pm_ops,
  1179. + },
  1180. +};
  1181. +
  1182. +
  1183. /* -- SSAM platform/meta-hub driver. ---------------------------------------- */
  1184. static const struct acpi_device_id ssam_platform_hub_match[] = {
  1185. @@ -676,18 +763,30 @@ static int __init ssam_device_hub_init(void)
  1186. status = platform_driver_register(&ssam_platform_hub_driver);
  1187. if (status)
  1188. - return status;
  1189. + goto err_platform;
  1190. status = ssam_device_driver_register(&ssam_base_hub_driver);
  1191. if (status)
  1192. - platform_driver_unregister(&ssam_platform_hub_driver);
  1193. + goto err_base;
  1194. +
  1195. + status = ssam_device_driver_register(&ssam_kip_hub_driver);
  1196. + if (status)
  1197. + goto err_kip;
  1198. + return 0;
  1199. +
  1200. +err_kip:
  1201. + ssam_device_driver_unregister(&ssam_base_hub_driver);
  1202. +err_base:
  1203. + platform_driver_unregister(&ssam_platform_hub_driver);
  1204. +err_platform:
  1205. return status;
  1206. }
  1207. module_init(ssam_device_hub_init);
  1208. static void __exit ssam_device_hub_exit(void)
  1209. {
  1210. + ssam_device_driver_unregister(&ssam_kip_hub_driver);
  1211. ssam_device_driver_unregister(&ssam_base_hub_driver);
  1212. platform_driver_unregister(&ssam_platform_hub_driver);
  1213. }
  1214. --
  1215. 2.38.0
  1216. From 336477e2e2926a4adea68881da5b10a4445c702b Mon Sep 17 00:00:00 2001
  1217. From: Maximilian Luz <luzmaximilian@gmail.com>
  1218. Date: Fri, 27 May 2022 04:34:47 +0200
  1219. Subject: [PATCH] platform/surface: aggregator_registry: Add support for
  1220. keyboard cover on Surface Pro 8
  1221. Add support for the detachable keyboard cover on the Surface Pro 8.
  1222. The keyboard cover on the Surface Pro 8 is, unlike the keyboard covers
  1223. of earlier Surface Pro generations, handled via the Surface System
  1224. Aggregator Module (SSAM). The keyboard and touchpad (as well as other
  1225. HID input devices) of this cover are standard SSAM HID client devices
  1226. (just like keyboard and touchpad on e.g. the Surface Laptop 3 and 4),
  1227. however, some care needs to be taken as they can be physically detached
  1228. (similarly to the Surface Book 3). Specifically, the respective SSAM
  1229. client devices need to be removed when the keyboard cover has been
  1230. detached and (re-)initialized when the keyboard cover has been
  1231. (re-)attached.
  1232. On the Surface Pro 8, detachment of the keyboard cover (and by extension
  1233. its devices) is managed via the KIP subsystem. Therefore, said devices
  1234. need to be registered under the KIP device hub, which in turn will
  1235. remove and re-create/re-initialize those devices as needed.
  1236. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  1237. Link: https://lore.kernel.org/r/20220527023447.2460025-13-luzmaximilian@gmail.com
  1238. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  1239. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  1240. Patchset: surface-sam
  1241. ---
  1242. .../surface/surface_aggregator_registry.c | 37 ++++++++++++++++++-
  1243. 1 file changed, 36 insertions(+), 1 deletion(-)
  1244. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  1245. index 0b4aeba4ad93..3b1310d61a24 100644
  1246. --- a/drivers/platform/surface/surface_aggregator_registry.c
  1247. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  1248. @@ -41,6 +41,12 @@ static const struct software_node ssam_node_root = {
  1249. .name = "ssam_platform_hub",
  1250. };
  1251. +/* KIP device hub (connects keyboard cover devices on Surface Pro 8). */
  1252. +static const struct software_node ssam_node_hub_kip = {
  1253. + .name = "ssam:00:00:01:0e:00",
  1254. + .parent = &ssam_node_root,
  1255. +};
  1256. +
  1257. /* Base device hub (devices attached to Surface Book 3 base). */
  1258. static const struct software_node ssam_node_hub_base = {
  1259. .name = "ssam:00:00:02:11:00",
  1260. @@ -155,6 +161,30 @@ static const struct software_node ssam_node_hid_base_iid6 = {
  1261. .parent = &ssam_node_hub_base,
  1262. };
  1263. +/* HID keyboard (KIP hub). */
  1264. +static const struct software_node ssam_node_hid_kip_keyboard = {
  1265. + .name = "ssam:01:15:02:01:00",
  1266. + .parent = &ssam_node_hub_kip,
  1267. +};
  1268. +
  1269. +/* HID pen stash (KIP hub; pen taken / stashed away evens). */
  1270. +static const struct software_node ssam_node_hid_kip_penstash = {
  1271. + .name = "ssam:01:15:02:02:00",
  1272. + .parent = &ssam_node_hub_kip,
  1273. +};
  1274. +
  1275. +/* HID touchpad (KIP hub). */
  1276. +static const struct software_node ssam_node_hid_kip_touchpad = {
  1277. + .name = "ssam:01:15:02:03:00",
  1278. + .parent = &ssam_node_hub_kip,
  1279. +};
  1280. +
  1281. +/* HID device instance 5 (KIP hub, unknown HID device). */
  1282. +static const struct software_node ssam_node_hid_kip_iid5 = {
  1283. + .name = "ssam:01:15:02:05:00",
  1284. + .parent = &ssam_node_hub_kip,
  1285. +};
  1286. +
  1287. /*
  1288. * Devices for 5th- and 6th-generations models:
  1289. * - Surface Book 2,
  1290. @@ -230,10 +260,15 @@ static const struct software_node *ssam_node_group_sp7[] = {
  1291. static const struct software_node *ssam_node_group_sp8[] = {
  1292. &ssam_node_root,
  1293. + &ssam_node_hub_kip,
  1294. &ssam_node_bat_ac,
  1295. &ssam_node_bat_main,
  1296. &ssam_node_tmp_pprof,
  1297. - /* TODO: Add support for keyboard cover. */
  1298. + &ssam_node_hid_kip_keyboard,
  1299. + &ssam_node_hid_kip_penstash,
  1300. + &ssam_node_hid_kip_touchpad,
  1301. + &ssam_node_hid_kip_iid5,
  1302. + /* TODO: Add support for tablet mode switch. */
  1303. NULL,
  1304. };
  1305. --
  1306. 2.38.0
  1307. From 6451a24698c042a26385615af15bc5bb97188d99 Mon Sep 17 00:00:00 2001
  1308. From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
  1309. Date: Fri, 10 Jun 2022 14:41:58 +0900
  1310. Subject: [PATCH] platform/surface: avoid flush_scheduled_work() usage
  1311. Use local wq in order to avoid flush_scheduled_work() usage.
  1312. Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
  1313. Reviewed-by: Maximilian Luz <luzmaximilian@gmail.com>
  1314. Tested-by: Maximilian Luz <luzmaximilian@gmail.com>
  1315. Link: https://lore.kernel.org/r/63ec2d45-c67c-1134-f6d3-490c8ba67a01@I-love.SAKURA.ne.jp
  1316. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  1317. Patchset: surface-sam
  1318. ---
  1319. .../platform/surface/surface_acpi_notify.c | 27 ++++++++++++++++---
  1320. 1 file changed, 24 insertions(+), 3 deletions(-)
  1321. diff --git a/drivers/platform/surface/surface_acpi_notify.c b/drivers/platform/surface/surface_acpi_notify.c
  1322. index 7b758f8cc137..c0e12f0b9b79 100644
  1323. --- a/drivers/platform/surface/surface_acpi_notify.c
  1324. +++ b/drivers/platform/surface/surface_acpi_notify.c
  1325. @@ -37,6 +37,7 @@ struct san_data {
  1326. #define to_san_data(ptr, member) \
  1327. container_of(ptr, struct san_data, member)
  1328. +static struct workqueue_struct *san_wq;
  1329. /* -- dGPU notifier interface. ---------------------------------------------- */
  1330. @@ -356,7 +357,7 @@ static u32 san_evt_bat_nf(struct ssam_event_notifier *nf,
  1331. memcpy(&work->event, event, sizeof(struct ssam_event) + event->length);
  1332. - schedule_delayed_work(&work->work, delay);
  1333. + queue_delayed_work(san_wq, &work->work, delay);
  1334. return SSAM_NOTIF_HANDLED;
  1335. }
  1336. @@ -861,7 +862,7 @@ static int san_remove(struct platform_device *pdev)
  1337. * We have unregistered our event sources. Now we need to ensure that
  1338. * all delayed works they may have spawned are run to completion.
  1339. */
  1340. - flush_scheduled_work();
  1341. + flush_workqueue(san_wq);
  1342. return 0;
  1343. }
  1344. @@ -881,7 +882,27 @@ static struct platform_driver surface_acpi_notify = {
  1345. .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  1346. },
  1347. };
  1348. -module_platform_driver(surface_acpi_notify);
  1349. +
  1350. +static int __init san_init(void)
  1351. +{
  1352. + int ret;
  1353. +
  1354. + san_wq = alloc_workqueue("san_wq", 0, 0);
  1355. + if (!san_wq)
  1356. + return -ENOMEM;
  1357. + ret = platform_driver_register(&surface_acpi_notify);
  1358. + if (ret)
  1359. + destroy_workqueue(san_wq);
  1360. + return ret;
  1361. +}
  1362. +module_init(san_init);
  1363. +
  1364. +static void __exit san_exit(void)
  1365. +{
  1366. + platform_driver_unregister(&surface_acpi_notify);
  1367. + destroy_workqueue(san_wq);
  1368. +}
  1369. +module_exit(san_exit);
  1370. MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
  1371. MODULE_DESCRIPTION("Surface ACPI Notify driver for Surface System Aggregator Module");
  1372. --
  1373. 2.38.0
  1374. From d08092adbfe7e12c8fd688e2262ce7dad8f7baf4 Mon Sep 17 00:00:00 2001
  1375. From: Maximilian Luz <luzmaximilian@gmail.com>
  1376. Date: Tue, 14 Jun 2022 21:41:17 +0200
  1377. Subject: [PATCH] platform/surface: aggregator: Reserve more event- and
  1378. target-categories
  1379. With the introduction of the Surface Laptop Studio, more event- and
  1380. target categories have been added. Therefore, increase the number of
  1381. reserved events and extend the enum of know target categories to
  1382. accommodate this.
  1383. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  1384. Link: https://lore.kernel.org/r/20220614194117.4118897-1-luzmaximilian@gmail.com
  1385. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  1386. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  1387. Patchset: surface-sam
  1388. ---
  1389. drivers/platform/surface/aggregator/trace.h | 80 +++++++++++--------
  1390. include/linux/surface_aggregator/serial_hub.h | 75 +++++++++--------
  1391. 2 files changed, 85 insertions(+), 70 deletions(-)
  1392. diff --git a/drivers/platform/surface/aggregator/trace.h b/drivers/platform/surface/aggregator/trace.h
  1393. index de64cf169060..cc9e73fbc18e 100644
  1394. --- a/drivers/platform/surface/aggregator/trace.h
  1395. +++ b/drivers/platform/surface/aggregator/trace.h
  1396. @@ -76,7 +76,7 @@ TRACE_DEFINE_ENUM(SSAM_SSH_TC_HID);
  1397. TRACE_DEFINE_ENUM(SSAM_SSH_TC_TCH);
  1398. TRACE_DEFINE_ENUM(SSAM_SSH_TC_BKL);
  1399. TRACE_DEFINE_ENUM(SSAM_SSH_TC_TAM);
  1400. -TRACE_DEFINE_ENUM(SSAM_SSH_TC_ACC);
  1401. +TRACE_DEFINE_ENUM(SSAM_SSH_TC_ACC0);
  1402. TRACE_DEFINE_ENUM(SSAM_SSH_TC_UFI);
  1403. TRACE_DEFINE_ENUM(SSAM_SSH_TC_USC);
  1404. TRACE_DEFINE_ENUM(SSAM_SSH_TC_PEN);
  1405. @@ -85,6 +85,11 @@ TRACE_DEFINE_ENUM(SSAM_SSH_TC_AUD);
  1406. TRACE_DEFINE_ENUM(SSAM_SSH_TC_SMC);
  1407. TRACE_DEFINE_ENUM(SSAM_SSH_TC_KPD);
  1408. TRACE_DEFINE_ENUM(SSAM_SSH_TC_REG);
  1409. +TRACE_DEFINE_ENUM(SSAM_SSH_TC_SPT);
  1410. +TRACE_DEFINE_ENUM(SSAM_SSH_TC_SYS);
  1411. +TRACE_DEFINE_ENUM(SSAM_SSH_TC_ACC1);
  1412. +TRACE_DEFINE_ENUM(SSAM_SSH_TC_SHB);
  1413. +TRACE_DEFINE_ENUM(SSAM_SSH_TC_POS);
  1414. #define SSAM_PTR_UID_LEN 9
  1415. #define SSAM_U8_FIELD_NOT_APPLICABLE ((u16)-1)
  1416. @@ -229,40 +234,45 @@ static inline u32 ssam_trace_get_request_tc(const struct ssh_packet *p)
  1417. #define ssam_show_ssh_tc(rqid) \
  1418. __print_symbolic(rqid, \
  1419. - { SSAM_SSH_TC_NOT_APPLICABLE, "N/A" }, \
  1420. - { SSAM_SSH_TC_SAM, "SAM" }, \
  1421. - { SSAM_SSH_TC_BAT, "BAT" }, \
  1422. - { SSAM_SSH_TC_TMP, "TMP" }, \
  1423. - { SSAM_SSH_TC_PMC, "PMC" }, \
  1424. - { SSAM_SSH_TC_FAN, "FAN" }, \
  1425. - { SSAM_SSH_TC_PoM, "PoM" }, \
  1426. - { SSAM_SSH_TC_DBG, "DBG" }, \
  1427. - { SSAM_SSH_TC_KBD, "KBD" }, \
  1428. - { SSAM_SSH_TC_FWU, "FWU" }, \
  1429. - { SSAM_SSH_TC_UNI, "UNI" }, \
  1430. - { SSAM_SSH_TC_LPC, "LPC" }, \
  1431. - { SSAM_SSH_TC_TCL, "TCL" }, \
  1432. - { SSAM_SSH_TC_SFL, "SFL" }, \
  1433. - { SSAM_SSH_TC_KIP, "KIP" }, \
  1434. - { SSAM_SSH_TC_EXT, "EXT" }, \
  1435. - { SSAM_SSH_TC_BLD, "BLD" }, \
  1436. - { SSAM_SSH_TC_BAS, "BAS" }, \
  1437. - { SSAM_SSH_TC_SEN, "SEN" }, \
  1438. - { SSAM_SSH_TC_SRQ, "SRQ" }, \
  1439. - { SSAM_SSH_TC_MCU, "MCU" }, \
  1440. - { SSAM_SSH_TC_HID, "HID" }, \
  1441. - { SSAM_SSH_TC_TCH, "TCH" }, \
  1442. - { SSAM_SSH_TC_BKL, "BKL" }, \
  1443. - { SSAM_SSH_TC_TAM, "TAM" }, \
  1444. - { SSAM_SSH_TC_ACC, "ACC" }, \
  1445. - { SSAM_SSH_TC_UFI, "UFI" }, \
  1446. - { SSAM_SSH_TC_USC, "USC" }, \
  1447. - { SSAM_SSH_TC_PEN, "PEN" }, \
  1448. - { SSAM_SSH_TC_VID, "VID" }, \
  1449. - { SSAM_SSH_TC_AUD, "AUD" }, \
  1450. - { SSAM_SSH_TC_SMC, "SMC" }, \
  1451. - { SSAM_SSH_TC_KPD, "KPD" }, \
  1452. - { SSAM_SSH_TC_REG, "REG" } \
  1453. + { SSAM_SSH_TC_NOT_APPLICABLE, "N/A" }, \
  1454. + { SSAM_SSH_TC_SAM, "SAM" }, \
  1455. + { SSAM_SSH_TC_BAT, "BAT" }, \
  1456. + { SSAM_SSH_TC_TMP, "TMP" }, \
  1457. + { SSAM_SSH_TC_PMC, "PMC" }, \
  1458. + { SSAM_SSH_TC_FAN, "FAN" }, \
  1459. + { SSAM_SSH_TC_PoM, "PoM" }, \
  1460. + { SSAM_SSH_TC_DBG, "DBG" }, \
  1461. + { SSAM_SSH_TC_KBD, "KBD" }, \
  1462. + { SSAM_SSH_TC_FWU, "FWU" }, \
  1463. + { SSAM_SSH_TC_UNI, "UNI" }, \
  1464. + { SSAM_SSH_TC_LPC, "LPC" }, \
  1465. + { SSAM_SSH_TC_TCL, "TCL" }, \
  1466. + { SSAM_SSH_TC_SFL, "SFL" }, \
  1467. + { SSAM_SSH_TC_KIP, "KIP" }, \
  1468. + { SSAM_SSH_TC_EXT, "EXT" }, \
  1469. + { SSAM_SSH_TC_BLD, "BLD" }, \
  1470. + { SSAM_SSH_TC_BAS, "BAS" }, \
  1471. + { SSAM_SSH_TC_SEN, "SEN" }, \
  1472. + { SSAM_SSH_TC_SRQ, "SRQ" }, \
  1473. + { SSAM_SSH_TC_MCU, "MCU" }, \
  1474. + { SSAM_SSH_TC_HID, "HID" }, \
  1475. + { SSAM_SSH_TC_TCH, "TCH" }, \
  1476. + { SSAM_SSH_TC_BKL, "BKL" }, \
  1477. + { SSAM_SSH_TC_TAM, "TAM" }, \
  1478. + { SSAM_SSH_TC_ACC0, "ACC0" }, \
  1479. + { SSAM_SSH_TC_UFI, "UFI" }, \
  1480. + { SSAM_SSH_TC_USC, "USC" }, \
  1481. + { SSAM_SSH_TC_PEN, "PEN" }, \
  1482. + { SSAM_SSH_TC_VID, "VID" }, \
  1483. + { SSAM_SSH_TC_AUD, "AUD" }, \
  1484. + { SSAM_SSH_TC_SMC, "SMC" }, \
  1485. + { SSAM_SSH_TC_KPD, "KPD" }, \
  1486. + { SSAM_SSH_TC_REG, "REG" }, \
  1487. + { SSAM_SSH_TC_SPT, "SPT" }, \
  1488. + { SSAM_SSH_TC_SYS, "SYS" }, \
  1489. + { SSAM_SSH_TC_ACC1, "ACC1" }, \
  1490. + { SSAM_SSH_TC_SHB, "SMB" }, \
  1491. + { SSAM_SSH_TC_POS, "POS" } \
  1492. )
  1493. DECLARE_EVENT_CLASS(ssam_frame_class,
  1494. diff --git a/include/linux/surface_aggregator/serial_hub.h b/include/linux/surface_aggregator/serial_hub.h
  1495. index 26b95ec12733..45501b6e54e8 100644
  1496. --- a/include/linux/surface_aggregator/serial_hub.h
  1497. +++ b/include/linux/surface_aggregator/serial_hub.h
  1498. @@ -201,7 +201,7 @@ static inline u16 ssh_crc(const u8 *buf, size_t len)
  1499. * exception of zero, which is not an event ID. Thus, this is also the
  1500. * absolute maximum number of event handlers that can be registered.
  1501. */
  1502. -#define SSH_NUM_EVENTS 34
  1503. +#define SSH_NUM_EVENTS 38
  1504. /*
  1505. * SSH_NUM_TARGETS - The number of communication targets used in the protocol.
  1506. @@ -292,40 +292,45 @@ struct ssam_span {
  1507. * Windows driver.
  1508. */
  1509. enum ssam_ssh_tc {
  1510. - /* Category 0x00 is invalid for EC use. */
  1511. - SSAM_SSH_TC_SAM = 0x01, /* Generic system functionality, real-time clock. */
  1512. - SSAM_SSH_TC_BAT = 0x02, /* Battery/power subsystem. */
  1513. - SSAM_SSH_TC_TMP = 0x03, /* Thermal subsystem. */
  1514. - SSAM_SSH_TC_PMC = 0x04,
  1515. - SSAM_SSH_TC_FAN = 0x05,
  1516. - SSAM_SSH_TC_PoM = 0x06,
  1517. - SSAM_SSH_TC_DBG = 0x07,
  1518. - SSAM_SSH_TC_KBD = 0x08, /* Legacy keyboard (Laptop 1/2). */
  1519. - SSAM_SSH_TC_FWU = 0x09,
  1520. - SSAM_SSH_TC_UNI = 0x0a,
  1521. - SSAM_SSH_TC_LPC = 0x0b,
  1522. - SSAM_SSH_TC_TCL = 0x0c,
  1523. - SSAM_SSH_TC_SFL = 0x0d,
  1524. - SSAM_SSH_TC_KIP = 0x0e, /* Manages detachable peripherals (Pro X/8 keyboard cover) */
  1525. - SSAM_SSH_TC_EXT = 0x0f,
  1526. - SSAM_SSH_TC_BLD = 0x10,
  1527. - SSAM_SSH_TC_BAS = 0x11, /* Detachment system (Surface Book 2/3). */
  1528. - SSAM_SSH_TC_SEN = 0x12,
  1529. - SSAM_SSH_TC_SRQ = 0x13,
  1530. - SSAM_SSH_TC_MCU = 0x14,
  1531. - SSAM_SSH_TC_HID = 0x15, /* Generic HID input subsystem. */
  1532. - SSAM_SSH_TC_TCH = 0x16,
  1533. - SSAM_SSH_TC_BKL = 0x17,
  1534. - SSAM_SSH_TC_TAM = 0x18,
  1535. - SSAM_SSH_TC_ACC = 0x19,
  1536. - SSAM_SSH_TC_UFI = 0x1a,
  1537. - SSAM_SSH_TC_USC = 0x1b,
  1538. - SSAM_SSH_TC_PEN = 0x1c,
  1539. - SSAM_SSH_TC_VID = 0x1d,
  1540. - SSAM_SSH_TC_AUD = 0x1e,
  1541. - SSAM_SSH_TC_SMC = 0x1f,
  1542. - SSAM_SSH_TC_KPD = 0x20,
  1543. - SSAM_SSH_TC_REG = 0x21, /* Extended event registry. */
  1544. + /* Category 0x00 is invalid for EC use. */
  1545. + SSAM_SSH_TC_SAM = 0x01, /* Generic system functionality, real-time clock. */
  1546. + SSAM_SSH_TC_BAT = 0x02, /* Battery/power subsystem. */
  1547. + SSAM_SSH_TC_TMP = 0x03, /* Thermal subsystem. */
  1548. + SSAM_SSH_TC_PMC = 0x04,
  1549. + SSAM_SSH_TC_FAN = 0x05,
  1550. + SSAM_SSH_TC_PoM = 0x06,
  1551. + SSAM_SSH_TC_DBG = 0x07,
  1552. + SSAM_SSH_TC_KBD = 0x08, /* Legacy keyboard (Laptop 1/2). */
  1553. + SSAM_SSH_TC_FWU = 0x09,
  1554. + SSAM_SSH_TC_UNI = 0x0a,
  1555. + SSAM_SSH_TC_LPC = 0x0b,
  1556. + SSAM_SSH_TC_TCL = 0x0c,
  1557. + SSAM_SSH_TC_SFL = 0x0d,
  1558. + SSAM_SSH_TC_KIP = 0x0e, /* Manages detachable peripherals (Pro X/8 keyboard cover) */
  1559. + SSAM_SSH_TC_EXT = 0x0f,
  1560. + SSAM_SSH_TC_BLD = 0x10,
  1561. + SSAM_SSH_TC_BAS = 0x11, /* Detachment system (Surface Book 2/3). */
  1562. + SSAM_SSH_TC_SEN = 0x12,
  1563. + SSAM_SSH_TC_SRQ = 0x13,
  1564. + SSAM_SSH_TC_MCU = 0x14,
  1565. + SSAM_SSH_TC_HID = 0x15, /* Generic HID input subsystem. */
  1566. + SSAM_SSH_TC_TCH = 0x16,
  1567. + SSAM_SSH_TC_BKL = 0x17,
  1568. + SSAM_SSH_TC_TAM = 0x18,
  1569. + SSAM_SSH_TC_ACC0 = 0x19,
  1570. + SSAM_SSH_TC_UFI = 0x1a,
  1571. + SSAM_SSH_TC_USC = 0x1b,
  1572. + SSAM_SSH_TC_PEN = 0x1c,
  1573. + SSAM_SSH_TC_VID = 0x1d,
  1574. + SSAM_SSH_TC_AUD = 0x1e,
  1575. + SSAM_SSH_TC_SMC = 0x1f,
  1576. + SSAM_SSH_TC_KPD = 0x20,
  1577. + SSAM_SSH_TC_REG = 0x21, /* Extended event registry. */
  1578. + SSAM_SSH_TC_SPT = 0x22,
  1579. + SSAM_SSH_TC_SYS = 0x23,
  1580. + SSAM_SSH_TC_ACC1 = 0x24,
  1581. + SSAM_SSH_TC_SHB = 0x25,
  1582. + SSAM_SSH_TC_POS = 0x26, /* For obtaining Laptop Studio screen position. */
  1583. };
  1584. --
  1585. 2.38.0
  1586. From bb44dfeb982ea5fdf9d18982512084eeca71ed7f Mon Sep 17 00:00:00 2001
  1587. From: Maximilian Luz <luzmaximilian@gmail.com>
  1588. Date: Fri, 24 Jun 2022 20:36:39 +0200
  1589. Subject: [PATCH] platform/surface: aggregator: Add helper macros for requests
  1590. with argument and return value
  1591. Add helper macros for synchronous stack-allocated Surface Aggregator
  1592. request with both argument and return value, similar to the current
  1593. argument-only and return-value-only ones.
  1594. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  1595. Link: https://lore.kernel.org/r/20220624183642.910893-2-luzmaximilian@gmail.com
  1596. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  1597. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  1598. Patchset: surface-sam
  1599. ---
  1600. include/linux/surface_aggregator/controller.h | 125 ++++++++++++++++++
  1601. include/linux/surface_aggregator/device.h | 36 +++++
  1602. 2 files changed, 161 insertions(+)
  1603. diff --git a/include/linux/surface_aggregator/controller.h b/include/linux/surface_aggregator/controller.h
  1604. index 50a2b4926c06..d11a1c6e3186 100644
  1605. --- a/include/linux/surface_aggregator/controller.h
  1606. +++ b/include/linux/surface_aggregator/controller.h
  1607. @@ -469,6 +469,67 @@ struct ssam_request_spec_md {
  1608. return 0; \
  1609. }
  1610. +/**
  1611. + * SSAM_DEFINE_SYNC_REQUEST_WR() - Define synchronous SAM request function with
  1612. + * both argument and return value.
  1613. + * @name: Name of the generated function.
  1614. + * @atype: Type of the request's argument.
  1615. + * @rtype: Type of the request's return value.
  1616. + * @spec: Specification (&struct ssam_request_spec) defining the request.
  1617. + *
  1618. + * Defines a function executing the synchronous SAM request specified by @spec,
  1619. + * with the request taking an argument of type @atype and having a return value
  1620. + * of type @rtype. The generated function takes care of setting up the request
  1621. + * and response structs, buffer allocation, as well as execution of the request
  1622. + * itself, returning once the request has been fully completed. The required
  1623. + * transport buffer will be allocated on the stack.
  1624. + *
  1625. + * The generated function is defined as ``static int name(struct
  1626. + * ssam_controller *ctrl, const atype *arg, rtype *ret)``, returning the status
  1627. + * of the request, which is zero on success and negative on failure. The
  1628. + * ``ctrl`` parameter is the controller via which the request is sent. The
  1629. + * request argument is specified via the ``arg`` pointer. The request's return
  1630. + * value is written to the memory pointed to by the ``ret`` parameter.
  1631. + *
  1632. + * Refer to ssam_request_sync_onstack() for more details on the behavior of
  1633. + * the generated function.
  1634. + */
  1635. +#define SSAM_DEFINE_SYNC_REQUEST_WR(name, atype, rtype, spec...) \
  1636. + static int name(struct ssam_controller *ctrl, const atype *arg, rtype *ret) \
  1637. + { \
  1638. + struct ssam_request_spec s = (struct ssam_request_spec)spec; \
  1639. + struct ssam_request rqst; \
  1640. + struct ssam_response rsp; \
  1641. + int status; \
  1642. + \
  1643. + rqst.target_category = s.target_category; \
  1644. + rqst.target_id = s.target_id; \
  1645. + rqst.command_id = s.command_id; \
  1646. + rqst.instance_id = s.instance_id; \
  1647. + rqst.flags = s.flags | SSAM_REQUEST_HAS_RESPONSE; \
  1648. + rqst.length = sizeof(atype); \
  1649. + rqst.payload = (u8 *)arg; \
  1650. + \
  1651. + rsp.capacity = sizeof(rtype); \
  1652. + rsp.length = 0; \
  1653. + rsp.pointer = (u8 *)ret; \
  1654. + \
  1655. + status = ssam_request_sync_onstack(ctrl, &rqst, &rsp, sizeof(atype)); \
  1656. + if (status) \
  1657. + return status; \
  1658. + \
  1659. + if (rsp.length != sizeof(rtype)) { \
  1660. + struct device *dev = ssam_controller_device(ctrl); \
  1661. + dev_err(dev, \
  1662. + "rqst: invalid response length, expected %zu, got %zu (tc: %#04x, cid: %#04x)", \
  1663. + sizeof(rtype), rsp.length, rqst.target_category,\
  1664. + rqst.command_id); \
  1665. + return -EIO; \
  1666. + } \
  1667. + \
  1668. + return 0; \
  1669. + }
  1670. +
  1671. /**
  1672. * SSAM_DEFINE_SYNC_REQUEST_MD_N() - Define synchronous multi-device SAM
  1673. * request function with neither argument nor return value.
  1674. @@ -613,6 +674,70 @@ struct ssam_request_spec_md {
  1675. return 0; \
  1676. }
  1677. +/**
  1678. + * SSAM_DEFINE_SYNC_REQUEST_MD_WR() - Define synchronous multi-device SAM
  1679. + * request function with both argument and return value.
  1680. + * @name: Name of the generated function.
  1681. + * @atype: Type of the request's argument.
  1682. + * @rtype: Type of the request's return value.
  1683. + * @spec: Specification (&struct ssam_request_spec_md) defining the request.
  1684. + *
  1685. + * Defines a function executing the synchronous SAM request specified by @spec,
  1686. + * with the request taking an argument of type @atype and having a return value
  1687. + * of type @rtype. Device specifying parameters are not hard-coded, but instead
  1688. + * must be provided to the function. The generated function takes care of
  1689. + * setting up the request and response structs, buffer allocation, as well as
  1690. + * execution of the request itself, returning once the request has been fully
  1691. + * completed. The required transport buffer will be allocated on the stack.
  1692. + *
  1693. + * The generated function is defined as ``static int name(struct
  1694. + * ssam_controller *ctrl, u8 tid, u8 iid, const atype *arg, rtype *ret)``,
  1695. + * returning the status of the request, which is zero on success and negative
  1696. + * on failure. The ``ctrl`` parameter is the controller via which the request
  1697. + * is sent, ``tid`` the target ID for the request, and ``iid`` the instance ID.
  1698. + * The request argument is specified via the ``arg`` pointer. The request's
  1699. + * return value is written to the memory pointed to by the ``ret`` parameter.
  1700. + *
  1701. + * Refer to ssam_request_sync_onstack() for more details on the behavior of
  1702. + * the generated function.
  1703. + */
  1704. +#define SSAM_DEFINE_SYNC_REQUEST_MD_WR(name, atype, rtype, spec...) \
  1705. + static int name(struct ssam_controller *ctrl, u8 tid, u8 iid, \
  1706. + const atype *arg, rtype *ret) \
  1707. + { \
  1708. + struct ssam_request_spec_md s = (struct ssam_request_spec_md)spec; \
  1709. + struct ssam_request rqst; \
  1710. + struct ssam_response rsp; \
  1711. + int status; \
  1712. + \
  1713. + rqst.target_category = s.target_category; \
  1714. + rqst.target_id = tid; \
  1715. + rqst.command_id = s.command_id; \
  1716. + rqst.instance_id = iid; \
  1717. + rqst.flags = s.flags | SSAM_REQUEST_HAS_RESPONSE; \
  1718. + rqst.length = sizeof(atype); \
  1719. + rqst.payload = (u8 *)arg; \
  1720. + \
  1721. + rsp.capacity = sizeof(rtype); \
  1722. + rsp.length = 0; \
  1723. + rsp.pointer = (u8 *)ret; \
  1724. + \
  1725. + status = ssam_request_sync_onstack(ctrl, &rqst, &rsp, sizeof(atype)); \
  1726. + if (status) \
  1727. + return status; \
  1728. + \
  1729. + if (rsp.length != sizeof(rtype)) { \
  1730. + struct device *dev = ssam_controller_device(ctrl); \
  1731. + dev_err(dev, \
  1732. + "rqst: invalid response length, expected %zu, got %zu (tc: %#04x, cid: %#04x)", \
  1733. + sizeof(rtype), rsp.length, rqst.target_category,\
  1734. + rqst.command_id); \
  1735. + return -EIO; \
  1736. + } \
  1737. + \
  1738. + return 0; \
  1739. + }
  1740. +
  1741. /* -- Event notifier/callbacks. --------------------------------------------- */
  1742. diff --git a/include/linux/surface_aggregator/device.h b/include/linux/surface_aggregator/device.h
  1743. index c418f7f2732d..6cf7e80312d5 100644
  1744. --- a/include/linux/surface_aggregator/device.h
  1745. +++ b/include/linux/surface_aggregator/device.h
  1746. @@ -483,6 +483,42 @@ static inline void ssam_remove_clients(struct device *dev) {}
  1747. sdev->uid.instance, ret); \
  1748. }
  1749. +/**
  1750. + * SSAM_DEFINE_SYNC_REQUEST_CL_WR() - Define synchronous client-device SAM
  1751. + * request function with argument and return value.
  1752. + * @name: Name of the generated function.
  1753. + * @atype: Type of the request's argument.
  1754. + * @rtype: Type of the request's return value.
  1755. + * @spec: Specification (&struct ssam_request_spec_md) defining the request.
  1756. + *
  1757. + * Defines a function executing the synchronous SAM request specified by @spec,
  1758. + * with the request taking an argument of type @atype and having a return value
  1759. + * of type @rtype. Device specifying parameters are not hard-coded, but instead
  1760. + * are provided via the client device, specifically its UID, supplied when
  1761. + * calling this function. The generated function takes care of setting up the
  1762. + * request struct, buffer allocation, as well as execution of the request
  1763. + * itself, returning once the request has been fully completed. The required
  1764. + * transport buffer will be allocated on the stack.
  1765. + *
  1766. + * The generated function is defined as ``static int name(struct ssam_device
  1767. + * *sdev, const atype *arg, rtype *ret)``, returning the status of the request,
  1768. + * which is zero on success and negative on failure. The ``sdev`` parameter
  1769. + * specifies both the target device of the request and by association the
  1770. + * controller via which the request is sent. The request's argument is
  1771. + * specified via the ``arg`` pointer. The request's return value is written to
  1772. + * the memory pointed to by the ``ret`` parameter.
  1773. + *
  1774. + * Refer to ssam_request_sync_onstack() for more details on the behavior of
  1775. + * the generated function.
  1776. + */
  1777. +#define SSAM_DEFINE_SYNC_REQUEST_CL_WR(name, atype, rtype, spec...) \
  1778. + SSAM_DEFINE_SYNC_REQUEST_MD_WR(__raw_##name, atype, rtype, spec) \
  1779. + static int name(struct ssam_device *sdev, const atype *arg, rtype *ret) \
  1780. + { \
  1781. + return __raw_##name(sdev->ctrl, sdev->uid.target, \
  1782. + sdev->uid.instance, arg, ret); \
  1783. + }
  1784. +
  1785. /* -- Helpers for client-device notifiers. ---------------------------------- */
  1786. --
  1787. 2.38.0
  1788. From b0e8cc2fefdf4e572e6ce71b0bf60b9e63022ed1 Mon Sep 17 00:00:00 2001
  1789. From: Maximilian Luz <luzmaximilian@gmail.com>
  1790. Date: Fri, 24 Jun 2022 20:36:40 +0200
  1791. Subject: [PATCH] platform/surface: Add KIP/POS tablet-mode switch driver
  1792. MIME-Version: 1.0
  1793. Content-Type: text/plain; charset=UTF-8
  1794. Content-Transfer-Encoding: 8bit
  1795. Add a driver providing a tablet-mode switch input device for Microsoft
  1796. Surface devices using the Surface Aggregator KIP subsystem (to manage
  1797. detachable peripherals) or POS subsystem (to obtain device posture
  1798. information).
  1799. The KIP (full name unknown, abbreviation found through reverse
  1800. engineering) subsystem is used on the Surface Pro 8 and Surface Pro X to
  1801. manage the keyboard cover. Among other things, it provides information
  1802. on the positioning (posture) of the cover (closed, laptop-style,
  1803. detached, folded-back, ...), which can be used to implement an input
  1804. device providing the SW_TABLET_MODE event. Similarly, the POS (posture
  1805. information) subsystem provides such information on the Surface Laptop
  1806. Studio, with the difference being that the keyboard is not detachable.
  1807. As implementing the tablet-mode switch for both subsystems is largely
  1808. similar, the driver proposed in this commit, in large, acts as a generic
  1809. tablet mode switch driver framework for the Surface Aggregator Module.
  1810. Specific implementations using this framework are provided for the KIP
  1811. and POS subsystems, adding tablet-mode switch support to the
  1812. aforementioned devices.
  1813. A few more notes on the Surface Laptop Studio:
  1814. A peculiarity of the Surface Laptop Studio is its "slate/tent" mode
  1815. (symbolized: user> _/\). In this mode, the screen covers the keyboard
  1816. but leaves the touchpad exposed. This is essentially a mode in-between
  1817. tablet and laptop, and it is debatable whether tablet-mode should be
  1818. enabled in this mode. We therefore let the user decide this via a module
  1819. parameter.
  1820. In particular, tablet-mode may bring up the on-screen touch keyboard
  1821. more easily, which would be desirable in this mode. However, some
  1822. user-space software currently also decides to disable keyboard and, more
  1823. importantly, touchpad input, while the touchpad is still accessible in
  1824. the "slate/tent" mode. Furthermore, this mode shares its identifier with
  1825. "slate/flipped" mode where the screen is flipped 180° and the keyboard
  1826. points away from the user (symbolized: user> /_). In this mode we would
  1827. like to enable auto-rotation, something that user-space software may
  1828. only do when tablet-mode is enabled. We therefore default to the
  1829. slate-mode enabling the tablet-mode switch.
  1830. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  1831. Link: https://lore.kernel.org/r/20220624183642.910893-3-luzmaximilian@gmail.com
  1832. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  1833. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  1834. Patchset: surface-sam
  1835. ---
  1836. .../sysfs-bus-surface_aggregator-tabletsw | 57 ++
  1837. MAINTAINERS | 6 +
  1838. drivers/platform/surface/Kconfig | 23 +
  1839. drivers/platform/surface/Makefile | 1 +
  1840. .../surface/surface_aggregator_tabletsw.c | 533 ++++++++++++++++++
  1841. 5 files changed, 620 insertions(+)
  1842. create mode 100644 Documentation/ABI/testing/sysfs-bus-surface_aggregator-tabletsw
  1843. create mode 100644 drivers/platform/surface/surface_aggregator_tabletsw.c
  1844. diff --git a/Documentation/ABI/testing/sysfs-bus-surface_aggregator-tabletsw b/Documentation/ABI/testing/sysfs-bus-surface_aggregator-tabletsw
  1845. new file mode 100644
  1846. index 000000000000..74cd9d754e60
  1847. --- /dev/null
  1848. +++ b/Documentation/ABI/testing/sysfs-bus-surface_aggregator-tabletsw
  1849. @@ -0,0 +1,57 @@
  1850. +What: /sys/bus/surface_aggregator/devices/01:0e:01:00:01/state
  1851. +Date: July 2022
  1852. +KernelVersion: 5.20
  1853. +Contact: Maximilian Luz <luzmaximilian@gmail.com>
  1854. +Description:
  1855. + This attribute returns a string with the current type-cover
  1856. + or device posture, as indicated by the embedded controller.
  1857. + Currently returned posture states are:
  1858. +
  1859. + - "disconnected": The type-cover has been disconnected.
  1860. +
  1861. + - "closed": The type-cover has been folded closed and lies on
  1862. + top of the display.
  1863. +
  1864. + - "laptop": The type-cover is open and in laptop-mode, i.e.,
  1865. + ready for normal use.
  1866. +
  1867. + - "folded-canvas": The type-cover has been folded back
  1868. + part-ways, but does not lie flush with the back side of the
  1869. + device. In general, this means that the kick-stand is used
  1870. + and extended atop of the cover.
  1871. +
  1872. + - "folded-back": The type cover has been fully folded back and
  1873. + lies flush with the back side of the device.
  1874. +
  1875. + - "<unknown>": The current state is unknown to the driver, for
  1876. + example due to newer as-of-yet unsupported hardware.
  1877. +
  1878. + New states may be introduced with new hardware. Users therefore
  1879. + must not rely on this list of states being exhaustive and
  1880. + gracefully handle unknown states.
  1881. +
  1882. +What: /sys/bus/surface_aggregator/devices/01:26:01:00:01/state
  1883. +Date: July 2022
  1884. +KernelVersion: 5.20
  1885. +Contact: Maximilian Luz <luzmaximilian@gmail.com>
  1886. +Description:
  1887. + This attribute returns a string with the current device posture, as indicated by the embedded controller. Currently
  1888. + returned posture states are:
  1889. +
  1890. + - "closed": The lid of the device is closed.
  1891. +
  1892. + - "laptop": The lid of the device is opened and the device
  1893. + operates as a normal laptop.
  1894. +
  1895. + - "slate": The screen covers the keyboard or has been flipped
  1896. + back and the device operates mainly based on touch input.
  1897. +
  1898. + - "tablet": The device operates as tablet and exclusively
  1899. + relies on touch input (or external peripherals).
  1900. +
  1901. + - "<unknown>": The current state is unknown to the driver, for
  1902. + example due to newer as-of-yet unsupported hardware.
  1903. +
  1904. + New states may be introduced with new hardware. Users therefore
  1905. + must not rely on this list of states being exhaustive and
  1906. + gracefully handle unknown states.
  1907. diff --git a/MAINTAINERS b/MAINTAINERS
  1908. index 08620b9a44fc..773eb8387f4a 100644
  1909. --- a/MAINTAINERS
  1910. +++ b/MAINTAINERS
  1911. @@ -13299,6 +13299,12 @@ F: drivers/scsi/smartpqi/smartpqi*.[ch]
  1912. F: include/linux/cciss*.h
  1913. F: include/uapi/linux/cciss*.h
  1914. +MICROSOFT SURFACE AGGREGATOR TABLET-MODE SWITCH
  1915. +M: Maximilian Luz <luzmaximilian@gmail.com>
  1916. +L: platform-driver-x86@vger.kernel.org
  1917. +S: Maintained
  1918. +F: drivers/platform/surface/surface_aggregator_tablet_switch.c
  1919. +
  1920. MICROSOFT SURFACE BATTERY AND AC DRIVERS
  1921. M: Maximilian Luz <luzmaximilian@gmail.com>
  1922. L: linux-pm@vger.kernel.org
  1923. diff --git a/drivers/platform/surface/Kconfig b/drivers/platform/surface/Kconfig
  1924. index eb79fbed8059..b152e930cc84 100644
  1925. --- a/drivers/platform/surface/Kconfig
  1926. +++ b/drivers/platform/surface/Kconfig
  1927. @@ -99,6 +99,29 @@ config SURFACE_AGGREGATOR_REGISTRY
  1928. the respective client devices. Drivers for these devices still need to
  1929. be selected via the other options.
  1930. +config SURFACE_AGGREGATOR_TABLET_SWITCH
  1931. + tristate "Surface Aggregator Generic Tablet-Mode Switch Driver"
  1932. + depends on SURFACE_AGGREGATOR
  1933. + depends on SURFACE_AGGREGATOR_BUS
  1934. + depends on INPUT
  1935. + help
  1936. + Provides a tablet-mode switch input device on Microsoft Surface models
  1937. + using the KIP subsystem for detachable keyboards (e.g. keyboard covers)
  1938. + or the POS subsystem for device/screen posture changes.
  1939. +
  1940. + The KIP subsystem is used on newer Surface generations to handle
  1941. + detachable input peripherals, specifically the keyboard cover (containing
  1942. + keyboard and touchpad) on the Surface Pro 8 and Surface Pro X. The POS
  1943. + subsystem is used for device posture change notifications on the Surface
  1944. + Laptop Studio. This module provides a driver to let user-space know when
  1945. + the device should be considered in tablet-mode due to the keyboard cover
  1946. + being detached or folded back (essentially signaling when the keyboard is
  1947. + not available for input). It does so by creating a tablet-mode switch
  1948. + input device, sending the standard SW_TABLET_MODE event on mode change.
  1949. +
  1950. + Select M or Y here, if you want to provide tablet-mode switch input
  1951. + events on the Surface Pro 8, Surface Pro X, and Surface Laptop Studio.
  1952. +
  1953. config SURFACE_DTX
  1954. tristate "Surface DTX (Detachment System) Driver"
  1955. depends on SURFACE_AGGREGATOR
  1956. diff --git a/drivers/platform/surface/Makefile b/drivers/platform/surface/Makefile
  1957. index 0fc9cd3e4dd9..18b27898543e 100644
  1958. --- a/drivers/platform/surface/Makefile
  1959. +++ b/drivers/platform/surface/Makefile
  1960. @@ -10,6 +10,7 @@ obj-$(CONFIG_SURFACE_ACPI_NOTIFY) += surface_acpi_notify.o
  1961. obj-$(CONFIG_SURFACE_AGGREGATOR) += aggregator/
  1962. obj-$(CONFIG_SURFACE_AGGREGATOR_CDEV) += surface_aggregator_cdev.o
  1963. obj-$(CONFIG_SURFACE_AGGREGATOR_REGISTRY) += surface_aggregator_registry.o
  1964. +obj-$(CONFIG_SURFACE_AGGREGATOR_TABLET_SWITCH) += surface_aggregator_tabletsw.o
  1965. obj-$(CONFIG_SURFACE_DTX) += surface_dtx.o
  1966. obj-$(CONFIG_SURFACE_GPE) += surface_gpe.o
  1967. obj-$(CONFIG_SURFACE_HOTPLUG) += surface_hotplug.o
  1968. diff --git a/drivers/platform/surface/surface_aggregator_tabletsw.c b/drivers/platform/surface/surface_aggregator_tabletsw.c
  1969. new file mode 100644
  1970. index 000000000000..596ca6c80681
  1971. --- /dev/null
  1972. +++ b/drivers/platform/surface/surface_aggregator_tabletsw.c
  1973. @@ -0,0 +1,533 @@
  1974. +// SPDX-License-Identifier: GPL-2.0+
  1975. +/*
  1976. + * Surface System Aggregator Module (SSAM) tablet mode switch driver.
  1977. + *
  1978. + * Copyright (C) 2022 Maximilian Luz <luzmaximilian@gmail.com>
  1979. + */
  1980. +
  1981. +#include <asm/unaligned.h>
  1982. +#include <linux/input.h>
  1983. +#include <linux/kernel.h>
  1984. +#include <linux/module.h>
  1985. +#include <linux/types.h>
  1986. +#include <linux/workqueue.h>
  1987. +
  1988. +#include <linux/surface_aggregator/controller.h>
  1989. +#include <linux/surface_aggregator/device.h>
  1990. +
  1991. +
  1992. +/* -- SSAM generic tablet switch driver framework. -------------------------- */
  1993. +
  1994. +struct ssam_tablet_sw;
  1995. +
  1996. +struct ssam_tablet_sw_ops {
  1997. + int (*get_state)(struct ssam_tablet_sw *sw, u32 *state);
  1998. + const char *(*state_name)(struct ssam_tablet_sw *sw, u32 state);
  1999. + bool (*state_is_tablet_mode)(struct ssam_tablet_sw *sw, u32 state);
  2000. +};
  2001. +
  2002. +struct ssam_tablet_sw {
  2003. + struct ssam_device *sdev;
  2004. +
  2005. + u32 state;
  2006. + struct work_struct update_work;
  2007. + struct input_dev *mode_switch;
  2008. +
  2009. + struct ssam_tablet_sw_ops ops;
  2010. + struct ssam_event_notifier notif;
  2011. +};
  2012. +
  2013. +struct ssam_tablet_sw_desc {
  2014. + struct {
  2015. + const char *name;
  2016. + const char *phys;
  2017. + } dev;
  2018. +
  2019. + struct {
  2020. + u32 (*notify)(struct ssam_event_notifier *nf, const struct ssam_event *event);
  2021. + int (*get_state)(struct ssam_tablet_sw *sw, u32 *state);
  2022. + const char *(*state_name)(struct ssam_tablet_sw *sw, u32 state);
  2023. + bool (*state_is_tablet_mode)(struct ssam_tablet_sw *sw, u32 state);
  2024. + } ops;
  2025. +
  2026. + struct {
  2027. + struct ssam_event_registry reg;
  2028. + struct ssam_event_id id;
  2029. + enum ssam_event_mask mask;
  2030. + u8 flags;
  2031. + } event;
  2032. +};
  2033. +
  2034. +static ssize_t state_show(struct device *dev, struct device_attribute *attr, char *buf)
  2035. +{
  2036. + struct ssam_tablet_sw *sw = dev_get_drvdata(dev);
  2037. + const char *state = sw->ops.state_name(sw, sw->state);
  2038. +
  2039. + return sysfs_emit(buf, "%s\n", state);
  2040. +}
  2041. +static DEVICE_ATTR_RO(state);
  2042. +
  2043. +static struct attribute *ssam_tablet_sw_attrs[] = {
  2044. + &dev_attr_state.attr,
  2045. + NULL,
  2046. +};
  2047. +
  2048. +static const struct attribute_group ssam_tablet_sw_group = {
  2049. + .attrs = ssam_tablet_sw_attrs,
  2050. +};
  2051. +
  2052. +static void ssam_tablet_sw_update_workfn(struct work_struct *work)
  2053. +{
  2054. + struct ssam_tablet_sw *sw = container_of(work, struct ssam_tablet_sw, update_work);
  2055. + int tablet, status;
  2056. + u32 state;
  2057. +
  2058. + status = sw->ops.get_state(sw, &state);
  2059. + if (status)
  2060. + return;
  2061. +
  2062. + if (sw->state == state)
  2063. + return;
  2064. + sw->state = state;
  2065. +
  2066. + /* Send SW_TABLET_MODE event. */
  2067. + tablet = sw->ops.state_is_tablet_mode(sw, state);
  2068. + input_report_switch(sw->mode_switch, SW_TABLET_MODE, tablet);
  2069. + input_sync(sw->mode_switch);
  2070. +}
  2071. +
  2072. +static int __maybe_unused ssam_tablet_sw_resume(struct device *dev)
  2073. +{
  2074. + struct ssam_tablet_sw *sw = dev_get_drvdata(dev);
  2075. +
  2076. + schedule_work(&sw->update_work);
  2077. + return 0;
  2078. +}
  2079. +static SIMPLE_DEV_PM_OPS(ssam_tablet_sw_pm_ops, NULL, ssam_tablet_sw_resume);
  2080. +
  2081. +static int ssam_tablet_sw_probe(struct ssam_device *sdev)
  2082. +{
  2083. + const struct ssam_tablet_sw_desc *desc;
  2084. + struct ssam_tablet_sw *sw;
  2085. + int tablet, status;
  2086. +
  2087. + desc = ssam_device_get_match_data(sdev);
  2088. + if (!desc) {
  2089. + WARN(1, "no driver match data specified");
  2090. + return -EINVAL;
  2091. + }
  2092. +
  2093. + sw = devm_kzalloc(&sdev->dev, sizeof(*sw), GFP_KERNEL);
  2094. + if (!sw)
  2095. + return -ENOMEM;
  2096. +
  2097. + sw->sdev = sdev;
  2098. +
  2099. + sw->ops.get_state = desc->ops.get_state;
  2100. + sw->ops.state_name = desc->ops.state_name;
  2101. + sw->ops.state_is_tablet_mode = desc->ops.state_is_tablet_mode;
  2102. +
  2103. + INIT_WORK(&sw->update_work, ssam_tablet_sw_update_workfn);
  2104. +
  2105. + ssam_device_set_drvdata(sdev, sw);
  2106. +
  2107. + /* Get initial state. */
  2108. + status = sw->ops.get_state(sw, &sw->state);
  2109. + if (status)
  2110. + return status;
  2111. +
  2112. + /* Set up tablet mode switch. */
  2113. + sw->mode_switch = devm_input_allocate_device(&sdev->dev);
  2114. + if (!sw->mode_switch)
  2115. + return -ENOMEM;
  2116. +
  2117. + sw->mode_switch->name = desc->dev.name;
  2118. + sw->mode_switch->phys = desc->dev.phys;
  2119. + sw->mode_switch->id.bustype = BUS_HOST;
  2120. + sw->mode_switch->dev.parent = &sdev->dev;
  2121. +
  2122. + tablet = sw->ops.state_is_tablet_mode(sw, sw->state);
  2123. + input_set_capability(sw->mode_switch, EV_SW, SW_TABLET_MODE);
  2124. + input_report_switch(sw->mode_switch, SW_TABLET_MODE, tablet);
  2125. +
  2126. + status = input_register_device(sw->mode_switch);
  2127. + if (status)
  2128. + return status;
  2129. +
  2130. + /* Set up notifier. */
  2131. + sw->notif.base.priority = 0;
  2132. + sw->notif.base.fn = desc->ops.notify;
  2133. + sw->notif.event.reg = desc->event.reg;
  2134. + sw->notif.event.id = desc->event.id;
  2135. + sw->notif.event.mask = desc->event.mask;
  2136. + sw->notif.event.flags = SSAM_EVENT_SEQUENCED;
  2137. +
  2138. + status = ssam_device_notifier_register(sdev, &sw->notif);
  2139. + if (status)
  2140. + return status;
  2141. +
  2142. + status = sysfs_create_group(&sdev->dev.kobj, &ssam_tablet_sw_group);
  2143. + if (status)
  2144. + goto err;
  2145. +
  2146. + /* We might have missed events during setup, so check again. */
  2147. + schedule_work(&sw->update_work);
  2148. + return 0;
  2149. +
  2150. +err:
  2151. + ssam_device_notifier_unregister(sdev, &sw->notif);
  2152. + cancel_work_sync(&sw->update_work);
  2153. + return status;
  2154. +}
  2155. +
  2156. +static void ssam_tablet_sw_remove(struct ssam_device *sdev)
  2157. +{
  2158. + struct ssam_tablet_sw *sw = ssam_device_get_drvdata(sdev);
  2159. +
  2160. + sysfs_remove_group(&sdev->dev.kobj, &ssam_tablet_sw_group);
  2161. +
  2162. + ssam_device_notifier_unregister(sdev, &sw->notif);
  2163. + cancel_work_sync(&sw->update_work);
  2164. +}
  2165. +
  2166. +
  2167. +/* -- SSAM KIP tablet switch implementation. -------------------------------- */
  2168. +
  2169. +#define SSAM_EVENT_KIP_CID_COVER_STATE_CHANGED 0x1d
  2170. +
  2171. +enum ssam_kip_cover_state {
  2172. + SSAM_KIP_COVER_STATE_DISCONNECTED = 0x01,
  2173. + SSAM_KIP_COVER_STATE_CLOSED = 0x02,
  2174. + SSAM_KIP_COVER_STATE_LAPTOP = 0x03,
  2175. + SSAM_KIP_COVER_STATE_FOLDED_CANVAS = 0x04,
  2176. + SSAM_KIP_COVER_STATE_FOLDED_BACK = 0x05,
  2177. +};
  2178. +
  2179. +static const char *ssam_kip_cover_state_name(struct ssam_tablet_sw *sw, u32 state)
  2180. +{
  2181. + switch (state) {
  2182. + case SSAM_KIP_COVER_STATE_DISCONNECTED:
  2183. + return "disconnected";
  2184. +
  2185. + case SSAM_KIP_COVER_STATE_CLOSED:
  2186. + return "closed";
  2187. +
  2188. + case SSAM_KIP_COVER_STATE_LAPTOP:
  2189. + return "laptop";
  2190. +
  2191. + case SSAM_KIP_COVER_STATE_FOLDED_CANVAS:
  2192. + return "folded-canvas";
  2193. +
  2194. + case SSAM_KIP_COVER_STATE_FOLDED_BACK:
  2195. + return "folded-back";
  2196. +
  2197. + default:
  2198. + dev_warn(&sw->sdev->dev, "unknown KIP cover state: %u\n", state);
  2199. + return "<unknown>";
  2200. + }
  2201. +}
  2202. +
  2203. +static bool ssam_kip_cover_state_is_tablet_mode(struct ssam_tablet_sw *sw, u32 state)
  2204. +{
  2205. + switch (state) {
  2206. + case SSAM_KIP_COVER_STATE_DISCONNECTED:
  2207. + case SSAM_KIP_COVER_STATE_FOLDED_CANVAS:
  2208. + case SSAM_KIP_COVER_STATE_FOLDED_BACK:
  2209. + return true;
  2210. +
  2211. + case SSAM_KIP_COVER_STATE_CLOSED:
  2212. + case SSAM_KIP_COVER_STATE_LAPTOP:
  2213. + return false;
  2214. +
  2215. + default:
  2216. + dev_warn(&sw->sdev->dev, "unknown KIP cover state: %d\n", sw->state);
  2217. + return true;
  2218. + }
  2219. +}
  2220. +
  2221. +SSAM_DEFINE_SYNC_REQUEST_R(__ssam_kip_get_cover_state, u8, {
  2222. + .target_category = SSAM_SSH_TC_KIP,
  2223. + .target_id = 0x01,
  2224. + .command_id = 0x1d,
  2225. + .instance_id = 0x00,
  2226. +});
  2227. +
  2228. +static int ssam_kip_get_cover_state(struct ssam_tablet_sw *sw, u32 *state)
  2229. +{
  2230. + int status;
  2231. + u8 raw;
  2232. +
  2233. + status = ssam_retry(__ssam_kip_get_cover_state, sw->sdev->ctrl, &raw);
  2234. + if (status < 0) {
  2235. + dev_err(&sw->sdev->dev, "failed to query KIP lid state: %d\n", status);
  2236. + return status;
  2237. + }
  2238. +
  2239. + *state = raw;
  2240. + return 0;
  2241. +}
  2242. +
  2243. +static u32 ssam_kip_sw_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
  2244. +{
  2245. + struct ssam_tablet_sw *sw = container_of(nf, struct ssam_tablet_sw, notif);
  2246. +
  2247. + if (event->command_id != SSAM_EVENT_KIP_CID_COVER_STATE_CHANGED)
  2248. + return 0; /* Return "unhandled". */
  2249. +
  2250. + if (event->length < 1)
  2251. + dev_warn(&sw->sdev->dev, "unexpected payload size: %u\n", event->length);
  2252. +
  2253. + schedule_work(&sw->update_work);
  2254. + return SSAM_NOTIF_HANDLED;
  2255. +}
  2256. +
  2257. +static const struct ssam_tablet_sw_desc ssam_kip_sw_desc = {
  2258. + .dev = {
  2259. + .name = "Microsoft Surface KIP Tablet Mode Switch",
  2260. + .phys = "ssam/01:0e:01:00:01/input0",
  2261. + },
  2262. + .ops = {
  2263. + .notify = ssam_kip_sw_notif,
  2264. + .get_state = ssam_kip_get_cover_state,
  2265. + .state_name = ssam_kip_cover_state_name,
  2266. + .state_is_tablet_mode = ssam_kip_cover_state_is_tablet_mode,
  2267. + },
  2268. + .event = {
  2269. + .reg = SSAM_EVENT_REGISTRY_SAM,
  2270. + .id = {
  2271. + .target_category = SSAM_SSH_TC_KIP,
  2272. + .instance = 0,
  2273. + },
  2274. + .mask = SSAM_EVENT_MASK_TARGET,
  2275. + },
  2276. +};
  2277. +
  2278. +
  2279. +/* -- SSAM POS tablet switch implementation. -------------------------------- */
  2280. +
  2281. +static bool tablet_mode_in_slate_state = true;
  2282. +module_param(tablet_mode_in_slate_state, bool, 0644);
  2283. +MODULE_PARM_DESC(tablet_mode_in_slate_state, "Enable tablet mode in slate device posture, default is 'true'");
  2284. +
  2285. +#define SSAM_EVENT_POS_CID_POSTURE_CHANGED 0x03
  2286. +#define SSAM_POS_MAX_SOURCES 4
  2287. +
  2288. +enum ssam_pos_state {
  2289. + SSAM_POS_POSTURE_LID_CLOSED = 0x00,
  2290. + SSAM_POS_POSTURE_LAPTOP = 0x01,
  2291. + SSAM_POS_POSTURE_SLATE = 0x02,
  2292. + SSAM_POS_POSTURE_TABLET = 0x03,
  2293. +};
  2294. +
  2295. +struct ssam_sources_list {
  2296. + __le32 count;
  2297. + __le32 id[SSAM_POS_MAX_SOURCES];
  2298. +} __packed;
  2299. +
  2300. +static const char *ssam_pos_state_name(struct ssam_tablet_sw *sw, u32 state)
  2301. +{
  2302. + switch (state) {
  2303. + case SSAM_POS_POSTURE_LID_CLOSED:
  2304. + return "closed";
  2305. +
  2306. + case SSAM_POS_POSTURE_LAPTOP:
  2307. + return "laptop";
  2308. +
  2309. + case SSAM_POS_POSTURE_SLATE:
  2310. + return "slate";
  2311. +
  2312. + case SSAM_POS_POSTURE_TABLET:
  2313. + return "tablet";
  2314. +
  2315. + default:
  2316. + dev_warn(&sw->sdev->dev, "unknown device posture: %u\n", state);
  2317. + return "<unknown>";
  2318. + }
  2319. +}
  2320. +
  2321. +static bool ssam_pos_state_is_tablet_mode(struct ssam_tablet_sw *sw, u32 state)
  2322. +{
  2323. + switch (state) {
  2324. + case SSAM_POS_POSTURE_LAPTOP:
  2325. + case SSAM_POS_POSTURE_LID_CLOSED:
  2326. + return false;
  2327. +
  2328. + case SSAM_POS_POSTURE_SLATE:
  2329. + return tablet_mode_in_slate_state;
  2330. +
  2331. + case SSAM_POS_POSTURE_TABLET:
  2332. + return true;
  2333. +
  2334. + default:
  2335. + dev_warn(&sw->sdev->dev, "unknown device posture: %u\n", state);
  2336. + return true;
  2337. + }
  2338. +}
  2339. +
  2340. +static int ssam_pos_get_sources_list(struct ssam_tablet_sw *sw, struct ssam_sources_list *sources)
  2341. +{
  2342. + struct ssam_request rqst;
  2343. + struct ssam_response rsp;
  2344. + int status;
  2345. +
  2346. + rqst.target_category = SSAM_SSH_TC_POS;
  2347. + rqst.target_id = 0x01;
  2348. + rqst.command_id = 0x01;
  2349. + rqst.instance_id = 0x00;
  2350. + rqst.flags = SSAM_REQUEST_HAS_RESPONSE;
  2351. + rqst.length = 0;
  2352. + rqst.payload = NULL;
  2353. +
  2354. + rsp.capacity = sizeof(*sources);
  2355. + rsp.length = 0;
  2356. + rsp.pointer = (u8 *)sources;
  2357. +
  2358. + status = ssam_retry(ssam_request_sync_onstack, sw->sdev->ctrl, &rqst, &rsp, 0);
  2359. + if (status)
  2360. + return status;
  2361. +
  2362. + /* We need at least the 'sources->count' field. */
  2363. + if (rsp.length < sizeof(__le32)) {
  2364. + dev_err(&sw->sdev->dev, "received source list response is too small\n");
  2365. + return -EPROTO;
  2366. + }
  2367. +
  2368. + /* Make sure 'sources->count' matches with the response length. */
  2369. + if (get_unaligned_le32(&sources->count) * sizeof(__le32) + sizeof(__le32) != rsp.length) {
  2370. + dev_err(&sw->sdev->dev, "mismatch between number of sources and response size\n");
  2371. + return -EPROTO;
  2372. + }
  2373. +
  2374. + return 0;
  2375. +}
  2376. +
  2377. +static int ssam_pos_get_source(struct ssam_tablet_sw *sw, u32 *source_id)
  2378. +{
  2379. + struct ssam_sources_list sources = {};
  2380. + int status;
  2381. +
  2382. + status = ssam_pos_get_sources_list(sw, &sources);
  2383. + if (status)
  2384. + return status;
  2385. +
  2386. + if (sources.count == 0) {
  2387. + dev_err(&sw->sdev->dev, "no posture sources found\n");
  2388. + return -ENODEV;
  2389. + }
  2390. +
  2391. + /*
  2392. + * We currently don't know what to do with more than one posture
  2393. + * source. At the moment, only one source seems to be used/provided.
  2394. + * The WARN_ON() here should hopefully let us know quickly once there
  2395. + * is a device that provides multiple sources, at which point we can
  2396. + * then try to figure out how to handle them.
  2397. + */
  2398. + WARN_ON(sources.count > 1);
  2399. +
  2400. + *source_id = get_unaligned_le32(&sources.id[0]);
  2401. + return 0;
  2402. +}
  2403. +
  2404. +SSAM_DEFINE_SYNC_REQUEST_WR(__ssam_pos_get_posture_for_source, __le32, __le32, {
  2405. + .target_category = SSAM_SSH_TC_POS,
  2406. + .target_id = 0x01,
  2407. + .command_id = 0x02,
  2408. + .instance_id = 0x00,
  2409. +});
  2410. +
  2411. +static int ssam_pos_get_posture_for_source(struct ssam_tablet_sw *sw, u32 source_id, u32 *posture)
  2412. +{
  2413. + __le32 source_le = cpu_to_le32(source_id);
  2414. + __le32 rspval_le = 0;
  2415. + int status;
  2416. +
  2417. + status = ssam_retry(__ssam_pos_get_posture_for_source, sw->sdev->ctrl,
  2418. + &source_le, &rspval_le);
  2419. + if (status)
  2420. + return status;
  2421. +
  2422. + *posture = le32_to_cpu(rspval_le);
  2423. + return 0;
  2424. +}
  2425. +
  2426. +static int ssam_pos_get_posture(struct ssam_tablet_sw *sw, u32 *state)
  2427. +{
  2428. + u32 source_id;
  2429. + int status;
  2430. +
  2431. + status = ssam_pos_get_source(sw, &source_id);
  2432. + if (status) {
  2433. + dev_err(&sw->sdev->dev, "failed to get posture source ID: %d\n", status);
  2434. + return status;
  2435. + }
  2436. +
  2437. + status = ssam_pos_get_posture_for_source(sw, source_id, state);
  2438. + if (status) {
  2439. + dev_err(&sw->sdev->dev, "failed to get posture value for source %u: %d\n",
  2440. + source_id, status);
  2441. + return status;
  2442. + }
  2443. +
  2444. + return 0;
  2445. +}
  2446. +
  2447. +static u32 ssam_pos_sw_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
  2448. +{
  2449. + struct ssam_tablet_sw *sw = container_of(nf, struct ssam_tablet_sw, notif);
  2450. +
  2451. + if (event->command_id != SSAM_EVENT_POS_CID_POSTURE_CHANGED)
  2452. + return 0; /* Return "unhandled". */
  2453. +
  2454. + if (event->length != sizeof(__le32) * 3)
  2455. + dev_warn(&sw->sdev->dev, "unexpected payload size: %u\n", event->length);
  2456. +
  2457. + schedule_work(&sw->update_work);
  2458. + return SSAM_NOTIF_HANDLED;
  2459. +}
  2460. +
  2461. +static const struct ssam_tablet_sw_desc ssam_pos_sw_desc = {
  2462. + .dev = {
  2463. + .name = "Microsoft Surface POS Tablet Mode Switch",
  2464. + .phys = "ssam/01:26:01:00:01/input0",
  2465. + },
  2466. + .ops = {
  2467. + .notify = ssam_pos_sw_notif,
  2468. + .get_state = ssam_pos_get_posture,
  2469. + .state_name = ssam_pos_state_name,
  2470. + .state_is_tablet_mode = ssam_pos_state_is_tablet_mode,
  2471. + },
  2472. + .event = {
  2473. + .reg = SSAM_EVENT_REGISTRY_SAM,
  2474. + .id = {
  2475. + .target_category = SSAM_SSH_TC_POS,
  2476. + .instance = 0,
  2477. + },
  2478. + .mask = SSAM_EVENT_MASK_TARGET,
  2479. + },
  2480. +};
  2481. +
  2482. +
  2483. +/* -- Driver registration. -------------------------------------------------- */
  2484. +
  2485. +static const struct ssam_device_id ssam_tablet_sw_match[] = {
  2486. + { SSAM_SDEV(KIP, 0x01, 0x00, 0x01), (unsigned long)&ssam_kip_sw_desc },
  2487. + { SSAM_SDEV(POS, 0x01, 0x00, 0x01), (unsigned long)&ssam_pos_sw_desc },
  2488. + { },
  2489. +};
  2490. +MODULE_DEVICE_TABLE(ssam, ssam_tablet_sw_match);
  2491. +
  2492. +static struct ssam_device_driver ssam_tablet_sw_driver = {
  2493. + .probe = ssam_tablet_sw_probe,
  2494. + .remove = ssam_tablet_sw_remove,
  2495. + .match_table = ssam_tablet_sw_match,
  2496. + .driver = {
  2497. + .name = "surface_aggregator_tablet_mode_switch",
  2498. + .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  2499. + .pm = &ssam_tablet_sw_pm_ops,
  2500. + },
  2501. +};
  2502. +module_ssam_device_driver(ssam_tablet_sw_driver);
  2503. +
  2504. +MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
  2505. +MODULE_DESCRIPTION("Tablet mode switch driver for Surface devices using the Surface Aggregator Module");
  2506. +MODULE_LICENSE("GPL");
  2507. --
  2508. 2.38.0
  2509. From f4cb665baca13f087ffa41e999f61031b44315da Mon Sep 17 00:00:00 2001
  2510. From: Maximilian Luz <luzmaximilian@gmail.com>
  2511. Date: Fri, 24 Jun 2022 20:36:41 +0200
  2512. Subject: [PATCH] platform/surface: aggregator_registry: Add support for tablet
  2513. mode switch on Surface Pro 8
  2514. Add a KIP subsystem tablet-mode switch device for the Surface Pro 8.
  2515. The respective driver for this device provides SW_TABLET_MODE input
  2516. events for user-space based on the state of the keyboard cover (e.g.
  2517. detached, folded-back, normal/laptop mode).
  2518. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  2519. Link: https://lore.kernel.org/r/20220624183642.910893-4-luzmaximilian@gmail.com
  2520. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  2521. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  2522. Patchset: surface-sam
  2523. ---
  2524. drivers/platform/surface/surface_aggregator_registry.c | 8 +++++++-
  2525. 1 file changed, 7 insertions(+), 1 deletion(-)
  2526. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  2527. index 3b1310d61a24..6994168ee898 100644
  2528. --- a/drivers/platform/surface/surface_aggregator_registry.c
  2529. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  2530. @@ -77,6 +77,12 @@ static const struct software_node ssam_node_tmp_pprof = {
  2531. .parent = &ssam_node_root,
  2532. };
  2533. +/* Tablet-mode switch via KIP subsystem. */
  2534. +static const struct software_node ssam_node_kip_tablet_switch = {
  2535. + .name = "ssam:01:0e:01:00:01",
  2536. + .parent = &ssam_node_root,
  2537. +};
  2538. +
  2539. /* DTX / detachment-system device (Surface Book 3). */
  2540. static const struct software_node ssam_node_bas_dtx = {
  2541. .name = "ssam:01:11:01:00:00",
  2542. @@ -264,11 +270,11 @@ static const struct software_node *ssam_node_group_sp8[] = {
  2543. &ssam_node_bat_ac,
  2544. &ssam_node_bat_main,
  2545. &ssam_node_tmp_pprof,
  2546. + &ssam_node_kip_tablet_switch,
  2547. &ssam_node_hid_kip_keyboard,
  2548. &ssam_node_hid_kip_penstash,
  2549. &ssam_node_hid_kip_touchpad,
  2550. &ssam_node_hid_kip_iid5,
  2551. - /* TODO: Add support for tablet mode switch. */
  2552. NULL,
  2553. };
  2554. --
  2555. 2.38.0
  2556. From f648e64b4ea98a52495f8e7382605d3c99ffbea0 Mon Sep 17 00:00:00 2001
  2557. From: Maximilian Luz <luzmaximilian@gmail.com>
  2558. Date: Fri, 24 Jun 2022 20:36:42 +0200
  2559. Subject: [PATCH] platform/surface: aggregator_registry: Add support for tablet
  2560. mode switch on Surface Laptop Studio
  2561. Add a POS subsystem tablet-mode switch device for the Surface Laptop
  2562. Studio. The respective driver for this device provides SW_TABLET_MODE
  2563. input events for user-space based on the posture of the screen.
  2564. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  2565. Link: https://lore.kernel.org/r/20220624183642.910893-5-luzmaximilian@gmail.com
  2566. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  2567. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  2568. Patchset: surface-sam
  2569. ---
  2570. drivers/platform/surface/surface_aggregator_registry.c | 7 +++++++
  2571. 1 file changed, 7 insertions(+)
  2572. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  2573. index 6994168ee898..6e14dd18c7a7 100644
  2574. --- a/drivers/platform/surface/surface_aggregator_registry.c
  2575. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  2576. @@ -191,6 +191,12 @@ static const struct software_node ssam_node_hid_kip_iid5 = {
  2577. .parent = &ssam_node_hub_kip,
  2578. };
  2579. +/* Tablet-mode switch via POS subsystem. */
  2580. +static const struct software_node ssam_node_pos_tablet_switch = {
  2581. + .name = "ssam:01:26:01:00:01",
  2582. + .parent = &ssam_node_root,
  2583. +};
  2584. +
  2585. /*
  2586. * Devices for 5th- and 6th-generations models:
  2587. * - Surface Book 2,
  2588. @@ -237,6 +243,7 @@ static const struct software_node *ssam_node_group_sls[] = {
  2589. &ssam_node_bat_ac,
  2590. &ssam_node_bat_main,
  2591. &ssam_node_tmp_pprof,
  2592. + &ssam_node_pos_tablet_switch,
  2593. &ssam_node_hid_tid1_keyboard,
  2594. &ssam_node_hid_tid1_penstash,
  2595. &ssam_node_hid_tid1_touchpad,
  2596. --
  2597. 2.38.0
  2598. From 246f11e41c786c82df2e816a3a94705784bc1b0f Mon Sep 17 00:00:00 2001
  2599. From: Maximilian Luz <luzmaximilian@gmail.com>
  2600. Date: Fri, 24 Jun 2022 22:57:58 +0200
  2601. Subject: [PATCH] platform/surface: aggregator: Move device registry helper
  2602. functions to core module
  2603. Move helper functions for client device registration to the core module.
  2604. This simplifies addition of future DT/OF support and also allows us to
  2605. split out the device hub drivers into their own module.
  2606. At the same time, also improve device node validation a bit by not
  2607. silently skipping devices with invalid device UID specifiers. Further,
  2608. ensure proper lifetime management for the firmware/software nodes
  2609. associated with the added devices.
  2610. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  2611. Link: https://lore.kernel.org/r/20220624205800.1355621-2-luzmaximilian@gmail.com
  2612. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  2613. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  2614. Patchset: surface-sam
  2615. ---
  2616. drivers/platform/surface/aggregator/bus.c | 149 ++++++++++++++++--
  2617. .../surface/surface_aggregator_registry.c | 75 +--------
  2618. include/linux/surface_aggregator/device.h | 52 ++++++
  2619. 3 files changed, 187 insertions(+), 89 deletions(-)
  2620. diff --git a/drivers/platform/surface/aggregator/bus.c b/drivers/platform/surface/aggregator/bus.c
  2621. index abbbb5b08b07..e0b0381a2834 100644
  2622. --- a/drivers/platform/surface/aggregator/bus.c
  2623. +++ b/drivers/platform/surface/aggregator/bus.c
  2624. @@ -6,6 +6,7 @@
  2625. */
  2626. #include <linux/device.h>
  2627. +#include <linux/property.h>
  2628. #include <linux/slab.h>
  2629. #include <linux/surface_aggregator/controller.h>
  2630. @@ -14,6 +15,9 @@
  2631. #include "bus.h"
  2632. #include "controller.h"
  2633. +
  2634. +/* -- Device and bus functions. --------------------------------------------- */
  2635. +
  2636. static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
  2637. char *buf)
  2638. {
  2639. @@ -46,6 +50,7 @@ static void ssam_device_release(struct device *dev)
  2640. struct ssam_device *sdev = to_ssam_device(dev);
  2641. ssam_controller_put(sdev->ctrl);
  2642. + fwnode_handle_put(sdev->dev.fwnode);
  2643. kfree(sdev);
  2644. }
  2645. @@ -363,6 +368,134 @@ void ssam_device_driver_unregister(struct ssam_device_driver *sdrv)
  2646. }
  2647. EXPORT_SYMBOL_GPL(ssam_device_driver_unregister);
  2648. +
  2649. +/* -- Bus registration. ----------------------------------------------------- */
  2650. +
  2651. +/**
  2652. + * ssam_bus_register() - Register and set-up the SSAM client device bus.
  2653. + */
  2654. +int ssam_bus_register(void)
  2655. +{
  2656. + return bus_register(&ssam_bus_type);
  2657. +}
  2658. +
  2659. +/**
  2660. + * ssam_bus_unregister() - Unregister the SSAM client device bus.
  2661. + */
  2662. +void ssam_bus_unregister(void)
  2663. +{
  2664. + return bus_unregister(&ssam_bus_type);
  2665. +}
  2666. +
  2667. +
  2668. +/* -- Helpers for controller and hub devices. ------------------------------- */
  2669. +
  2670. +static int ssam_device_uid_from_string(const char *str, struct ssam_device_uid *uid)
  2671. +{
  2672. + u8 d, tc, tid, iid, fn;
  2673. + int n;
  2674. +
  2675. + n = sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx", &d, &tc, &tid, &iid, &fn);
  2676. + if (n != 5)
  2677. + return -EINVAL;
  2678. +
  2679. + uid->domain = d;
  2680. + uid->category = tc;
  2681. + uid->target = tid;
  2682. + uid->instance = iid;
  2683. + uid->function = fn;
  2684. +
  2685. + return 0;
  2686. +}
  2687. +
  2688. +static int ssam_get_uid_for_node(struct fwnode_handle *node, struct ssam_device_uid *uid)
  2689. +{
  2690. + const char *str = fwnode_get_name(node);
  2691. +
  2692. + /*
  2693. + * To simplify definitions of firmware nodes, we set the device name
  2694. + * based on the UID of the device, prefixed with "ssam:".
  2695. + */
  2696. + if (strncmp(str, "ssam:", strlen("ssam:")) != 0)
  2697. + return -ENODEV;
  2698. +
  2699. + str += strlen("ssam:");
  2700. + return ssam_device_uid_from_string(str, uid);
  2701. +}
  2702. +
  2703. +static int ssam_add_client_device(struct device *parent, struct ssam_controller *ctrl,
  2704. + struct fwnode_handle *node)
  2705. +{
  2706. + struct ssam_device_uid uid;
  2707. + struct ssam_device *sdev;
  2708. + int status;
  2709. +
  2710. + status = ssam_get_uid_for_node(node, &uid);
  2711. + if (status)
  2712. + return status;
  2713. +
  2714. + sdev = ssam_device_alloc(ctrl, uid);
  2715. + if (!sdev)
  2716. + return -ENOMEM;
  2717. +
  2718. + sdev->dev.parent = parent;
  2719. + sdev->dev.fwnode = fwnode_handle_get(node);
  2720. +
  2721. + status = ssam_device_add(sdev);
  2722. + if (status)
  2723. + ssam_device_put(sdev);
  2724. +
  2725. + return status;
  2726. +}
  2727. +
  2728. +/**
  2729. + * __ssam_register_clients() - Register client devices defined under the
  2730. + * given firmware node as children of the given device.
  2731. + * @parent: The parent device under which clients should be registered.
  2732. + * @ctrl: The controller with which client should be registered.
  2733. + * @node: The firmware node holding definitions of the devices to be added.
  2734. + *
  2735. + * Register all clients that have been defined as children of the given root
  2736. + * firmware node as children of the given parent device. The respective child
  2737. + * firmware nodes will be associated with the correspondingly created child
  2738. + * devices.
  2739. + *
  2740. + * The given controller will be used to instantiate the new devices. See
  2741. + * ssam_device_add() for details.
  2742. + *
  2743. + * Note that, generally, the use of either ssam_device_register_clients() or
  2744. + * ssam_register_clients() should be preferred as they directly use the
  2745. + * firmware node and/or controller associated with the given device. This
  2746. + * function is only intended for use when different device specifications (e.g.
  2747. + * ACPI and firmware nodes) need to be combined (as is done in the platform hub
  2748. + * of the device registry).
  2749. + *
  2750. + * Return: Returns zero on success, nonzero on failure.
  2751. + */
  2752. +int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl,
  2753. + struct fwnode_handle *node)
  2754. +{
  2755. + struct fwnode_handle *child;
  2756. + int status;
  2757. +
  2758. + fwnode_for_each_child_node(node, child) {
  2759. + /*
  2760. + * Try to add the device specified in the firmware node. If
  2761. + * this fails with -ENODEV, the node does not specify any SSAM
  2762. + * device, so ignore it and continue with the next one.
  2763. + */
  2764. + status = ssam_add_client_device(parent, ctrl, child);
  2765. + if (status && status != -ENODEV)
  2766. + goto err;
  2767. + }
  2768. +
  2769. + return 0;
  2770. +err:
  2771. + ssam_remove_clients(parent);
  2772. + return status;
  2773. +}
  2774. +EXPORT_SYMBOL_GPL(__ssam_register_clients);
  2775. +
  2776. static int ssam_remove_device(struct device *dev, void *_data)
  2777. {
  2778. struct ssam_device *sdev = to_ssam_device(dev);
  2779. @@ -387,19 +520,3 @@ void ssam_remove_clients(struct device *dev)
  2780. device_for_each_child_reverse(dev, NULL, ssam_remove_device);
  2781. }
  2782. EXPORT_SYMBOL_GPL(ssam_remove_clients);
  2783. -
  2784. -/**
  2785. - * ssam_bus_register() - Register and set-up the SSAM client device bus.
  2786. - */
  2787. -int ssam_bus_register(void)
  2788. -{
  2789. - return bus_register(&ssam_bus_type);
  2790. -}
  2791. -
  2792. -/**
  2793. - * ssam_bus_unregister() - Unregister the SSAM client device bus.
  2794. - */
  2795. -void ssam_bus_unregister(void)
  2796. -{
  2797. - return bus_unregister(&ssam_bus_type);
  2798. -}
  2799. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  2800. index 6e14dd18c7a7..eb88021c208c 100644
  2801. --- a/drivers/platform/surface/surface_aggregator_registry.c
  2802. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  2803. @@ -286,76 +286,6 @@ static const struct software_node *ssam_node_group_sp8[] = {
  2804. };
  2805. -/* -- Device registry helper functions. ------------------------------------- */
  2806. -
  2807. -static int ssam_uid_from_string(const char *str, struct ssam_device_uid *uid)
  2808. -{
  2809. - u8 d, tc, tid, iid, fn;
  2810. - int n;
  2811. -
  2812. - n = sscanf(str, "ssam:%hhx:%hhx:%hhx:%hhx:%hhx", &d, &tc, &tid, &iid, &fn);
  2813. - if (n != 5)
  2814. - return -EINVAL;
  2815. -
  2816. - uid->domain = d;
  2817. - uid->category = tc;
  2818. - uid->target = tid;
  2819. - uid->instance = iid;
  2820. - uid->function = fn;
  2821. -
  2822. - return 0;
  2823. -}
  2824. -
  2825. -static int ssam_hub_add_device(struct device *parent, struct ssam_controller *ctrl,
  2826. - struct fwnode_handle *node)
  2827. -{
  2828. - struct ssam_device_uid uid;
  2829. - struct ssam_device *sdev;
  2830. - int status;
  2831. -
  2832. - status = ssam_uid_from_string(fwnode_get_name(node), &uid);
  2833. - if (status)
  2834. - return status;
  2835. -
  2836. - sdev = ssam_device_alloc(ctrl, uid);
  2837. - if (!sdev)
  2838. - return -ENOMEM;
  2839. -
  2840. - sdev->dev.parent = parent;
  2841. - sdev->dev.fwnode = node;
  2842. -
  2843. - status = ssam_device_add(sdev);
  2844. - if (status)
  2845. - ssam_device_put(sdev);
  2846. -
  2847. - return status;
  2848. -}
  2849. -
  2850. -static int ssam_hub_register_clients(struct device *parent, struct ssam_controller *ctrl,
  2851. - struct fwnode_handle *node)
  2852. -{
  2853. - struct fwnode_handle *child;
  2854. - int status;
  2855. -
  2856. - fwnode_for_each_child_node(node, child) {
  2857. - /*
  2858. - * Try to add the device specified in the firmware node. If
  2859. - * this fails with -EINVAL, the node does not specify any SSAM
  2860. - * device, so ignore it and continue with the next one.
  2861. - */
  2862. -
  2863. - status = ssam_hub_add_device(parent, ctrl, child);
  2864. - if (status && status != -EINVAL)
  2865. - goto err;
  2866. - }
  2867. -
  2868. - return 0;
  2869. -err:
  2870. - ssam_remove_clients(parent);
  2871. - return status;
  2872. -}
  2873. -
  2874. -
  2875. /* -- SSAM generic subsystem hub driver framework. -------------------------- */
  2876. enum ssam_hub_state {
  2877. @@ -385,7 +315,6 @@ struct ssam_hub {
  2878. static void ssam_hub_update_workfn(struct work_struct *work)
  2879. {
  2880. struct ssam_hub *hub = container_of(work, struct ssam_hub, update_work.work);
  2881. - struct fwnode_handle *node = dev_fwnode(&hub->sdev->dev);
  2882. enum ssam_hub_state state;
  2883. int status = 0;
  2884. @@ -425,7 +354,7 @@ static void ssam_hub_update_workfn(struct work_struct *work)
  2885. hub->state = state;
  2886. if (hub->state == SSAM_HUB_CONNECTED)
  2887. - status = ssam_hub_register_clients(&hub->sdev->dev, hub->sdev->ctrl, node);
  2888. + status = ssam_device_register_clients(hub->sdev);
  2889. else
  2890. ssam_remove_clients(&hub->sdev->dev);
  2891. @@ -772,7 +701,7 @@ static int ssam_platform_hub_probe(struct platform_device *pdev)
  2892. set_secondary_fwnode(&pdev->dev, root);
  2893. - status = ssam_hub_register_clients(&pdev->dev, ctrl, root);
  2894. + status = __ssam_register_clients(&pdev->dev, ctrl, root);
  2895. if (status) {
  2896. set_secondary_fwnode(&pdev->dev, NULL);
  2897. software_node_unregister_node_group(nodes);
  2898. diff --git a/include/linux/surface_aggregator/device.h b/include/linux/surface_aggregator/device.h
  2899. index 6cf7e80312d5..46c45d1b6368 100644
  2900. --- a/include/linux/surface_aggregator/device.h
  2901. +++ b/include/linux/surface_aggregator/device.h
  2902. @@ -15,6 +15,7 @@
  2903. #include <linux/device.h>
  2904. #include <linux/mod_devicetable.h>
  2905. +#include <linux/property.h>
  2906. #include <linux/types.h>
  2907. #include <linux/surface_aggregator/controller.h>
  2908. @@ -375,11 +376,62 @@ void ssam_device_driver_unregister(struct ssam_device_driver *d);
  2909. /* -- Helpers for controller and hub devices. ------------------------------- */
  2910. #ifdef CONFIG_SURFACE_AGGREGATOR_BUS
  2911. +
  2912. +int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl,
  2913. + struct fwnode_handle *node);
  2914. void ssam_remove_clients(struct device *dev);
  2915. +
  2916. #else /* CONFIG_SURFACE_AGGREGATOR_BUS */
  2917. +
  2918. +static inline int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl,
  2919. + struct fwnode_handle *node)
  2920. +{
  2921. + return 0;
  2922. +}
  2923. +
  2924. static inline void ssam_remove_clients(struct device *dev) {}
  2925. +
  2926. #endif /* CONFIG_SURFACE_AGGREGATOR_BUS */
  2927. +/**
  2928. + * ssam_register_clients() - Register all client devices defined under the
  2929. + * given parent device.
  2930. + * @dev: The parent device under which clients should be registered.
  2931. + * @ctrl: The controller with which client should be registered.
  2932. + *
  2933. + * Register all clients that have via firmware nodes been defined as children
  2934. + * of the given (parent) device. The respective child firmware nodes will be
  2935. + * associated with the correspondingly created child devices.
  2936. + *
  2937. + * The given controller will be used to instantiate the new devices. See
  2938. + * ssam_device_add() for details.
  2939. + *
  2940. + * Return: Returns zero on success, nonzero on failure.
  2941. + */
  2942. +static inline int ssam_register_clients(struct device *dev, struct ssam_controller *ctrl)
  2943. +{
  2944. + return __ssam_register_clients(dev, ctrl, dev_fwnode(dev));
  2945. +}
  2946. +
  2947. +/**
  2948. + * ssam_device_register_clients() - Register all client devices defined under
  2949. + * the given SSAM parent device.
  2950. + * @sdev: The parent device under which clients should be registered.
  2951. + *
  2952. + * Register all clients that have via firmware nodes been defined as children
  2953. + * of the given (parent) device. The respective child firmware nodes will be
  2954. + * associated with the correspondingly created child devices.
  2955. + *
  2956. + * The controller used by the parent device will be used to instantiate the new
  2957. + * devices. See ssam_device_add() for details.
  2958. + *
  2959. + * Return: Returns zero on success, nonzero on failure.
  2960. + */
  2961. +static inline int ssam_device_register_clients(struct ssam_device *sdev)
  2962. +{
  2963. + return ssam_register_clients(&sdev->dev, sdev->ctrl);
  2964. +}
  2965. +
  2966. /* -- Helpers for client-device requests. ----------------------------------- */
  2967. --
  2968. 2.38.0
  2969. From b864dfd5fa6a705d7ae5a13e79ac32ca67dec4a9 Mon Sep 17 00:00:00 2001
  2970. From: Maximilian Luz <luzmaximilian@gmail.com>
  2971. Date: Fri, 24 Jun 2022 22:57:59 +0200
  2972. Subject: [PATCH] platform/surface: aggregator: Move subsystem hub drivers to
  2973. their own module
  2974. Split out subsystem device hub drivers into their own module. This
  2975. allows us to load the hub drivers separately from the registry, which
  2976. will help future DT/OF support.
  2977. While doing so, also remove a small bit of code duplication.
  2978. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  2979. Link: https://lore.kernel.org/r/20220624205800.1355621-3-luzmaximilian@gmail.com
  2980. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  2981. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  2982. Patchset: surface-sam
  2983. ---
  2984. MAINTAINERS | 6 +
  2985. drivers/platform/surface/Kconfig | 35 +-
  2986. drivers/platform/surface/Makefile | 1 +
  2987. .../platform/surface/surface_aggregator_hub.c | 371 ++++++++++++++++++
  2988. .../surface/surface_aggregator_registry.c | 371 +-----------------
  2989. 5 files changed, 410 insertions(+), 374 deletions(-)
  2990. create mode 100644 drivers/platform/surface/surface_aggregator_hub.c
  2991. diff --git a/MAINTAINERS b/MAINTAINERS
  2992. index 773eb8387f4a..55e80354a097 100644
  2993. --- a/MAINTAINERS
  2994. +++ b/MAINTAINERS
  2995. @@ -13376,6 +13376,12 @@ F: include/linux/surface_acpi_notify.h
  2996. F: include/linux/surface_aggregator/
  2997. F: include/uapi/linux/surface_aggregator/
  2998. +MICROSOFT SURFACE SYSTEM AGGREGATOR HUB DRIVER
  2999. +M: Maximilian Luz <luzmaximilian@gmail.com>
  3000. +L: platform-driver-x86@vger.kernel.org
  3001. +S: Maintained
  3002. +F: drivers/platform/surface/surface_aggregator_hub.c
  3003. +
  3004. MICROTEK X6 SCANNER
  3005. M: Oliver Neukum <oliver@neukum.org>
  3006. S: Maintained
  3007. diff --git a/drivers/platform/surface/Kconfig b/drivers/platform/surface/Kconfig
  3008. index b152e930cc84..b629e82af97c 100644
  3009. --- a/drivers/platform/surface/Kconfig
  3010. +++ b/drivers/platform/surface/Kconfig
  3011. @@ -72,18 +72,45 @@ config SURFACE_AGGREGATOR_CDEV
  3012. The provided interface is intended for debugging and development only,
  3013. and should not be used otherwise.
  3014. +config SURFACE_AGGREGATOR_HUB
  3015. + tristate "Surface System Aggregator Module Subsystem Device Hubs"
  3016. + depends on SURFACE_AGGREGATOR
  3017. + depends on SURFACE_AGGREGATOR_BUS
  3018. + help
  3019. + Device-hub drivers for Surface System Aggregator Module (SSAM) subsystem
  3020. + devices.
  3021. +
  3022. + Provides subsystem hub drivers which manage client devices on various
  3023. + SSAM subsystems. In some subsystems, notably the BAS subsystem managing
  3024. + devices contained in the base of the Surface Book 3 and the KIP subsystem
  3025. + managing type-cover devices in the Surface Pro 8 and Surface Pro X,
  3026. + devices can be (hot-)removed. Hub devices and drivers are required to
  3027. + manage these subdevices.
  3028. +
  3029. + Devices managed via these hubs are:
  3030. + - Battery/AC devices (Surface Book 3).
  3031. + - HID input devices (7th-generation and later models with detachable
  3032. + input devices).
  3033. +
  3034. + Select M (recommended) or Y here if you want support for the above
  3035. + mentioned devices on the corresponding Surface models. Without this
  3036. + module, the respective devices mentioned above will not be instantiated
  3037. + and thus any functionality provided by them will be missing, even when
  3038. + drivers for these devices are present. This module only provides the
  3039. + respective subsystem hubs. Both drivers and device specification (e.g.
  3040. + via the Surface Aggregator Registry) for these devices still need to be
  3041. + selected via other options.
  3042. +
  3043. config SURFACE_AGGREGATOR_REGISTRY
  3044. tristate "Surface System Aggregator Module Device Registry"
  3045. depends on SURFACE_AGGREGATOR
  3046. depends on SURFACE_AGGREGATOR_BUS
  3047. help
  3048. - Device-registry and device-hubs for Surface System Aggregator Module
  3049. - (SSAM) devices.
  3050. + Device-registry for Surface System Aggregator Module (SSAM) devices.
  3051. Provides a module and driver which act as a device-registry for SSAM
  3052. client devices that cannot be detected automatically, e.g. via ACPI.
  3053. - Such devices are instead provided via this registry and attached via
  3054. - device hubs, also provided in this module.
  3055. + Such devices are instead provided and managed via this registry.
  3056. Devices provided via this registry are:
  3057. - Platform profile (performance-/cooling-mode) device (5th- and later
  3058. diff --git a/drivers/platform/surface/Makefile b/drivers/platform/surface/Makefile
  3059. index 18b27898543e..53344330939b 100644
  3060. --- a/drivers/platform/surface/Makefile
  3061. +++ b/drivers/platform/surface/Makefile
  3062. @@ -9,6 +9,7 @@ obj-$(CONFIG_SURFACE_3_POWER_OPREGION) += surface3_power.o
  3063. obj-$(CONFIG_SURFACE_ACPI_NOTIFY) += surface_acpi_notify.o
  3064. obj-$(CONFIG_SURFACE_AGGREGATOR) += aggregator/
  3065. obj-$(CONFIG_SURFACE_AGGREGATOR_CDEV) += surface_aggregator_cdev.o
  3066. +obj-$(CONFIG_SURFACE_AGGREGATOR_HUB) += surface_aggregator_hub.o
  3067. obj-$(CONFIG_SURFACE_AGGREGATOR_REGISTRY) += surface_aggregator_registry.o
  3068. obj-$(CONFIG_SURFACE_AGGREGATOR_TABLET_SWITCH) += surface_aggregator_tabletsw.o
  3069. obj-$(CONFIG_SURFACE_DTX) += surface_dtx.o
  3070. diff --git a/drivers/platform/surface/surface_aggregator_hub.c b/drivers/platform/surface/surface_aggregator_hub.c
  3071. new file mode 100644
  3072. index 000000000000..43061514be38
  3073. --- /dev/null
  3074. +++ b/drivers/platform/surface/surface_aggregator_hub.c
  3075. @@ -0,0 +1,371 @@
  3076. +// SPDX-License-Identifier: GPL-2.0+
  3077. +/*
  3078. + * Driver for Surface System Aggregator Module (SSAM) subsystem device hubs.
  3079. + *
  3080. + * Provides a driver for SSAM subsystems device hubs. This driver performs
  3081. + * instantiation of the devices managed by said hubs and takes care of
  3082. + * (hot-)removal.
  3083. + *
  3084. + * Copyright (C) 2020-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3085. + */
  3086. +
  3087. +#include <linux/kernel.h>
  3088. +#include <linux/limits.h>
  3089. +#include <linux/module.h>
  3090. +#include <linux/types.h>
  3091. +#include <linux/workqueue.h>
  3092. +
  3093. +#include <linux/surface_aggregator/device.h>
  3094. +
  3095. +
  3096. +/* -- SSAM generic subsystem hub driver framework. -------------------------- */
  3097. +
  3098. +enum ssam_hub_state {
  3099. + SSAM_HUB_UNINITIALIZED, /* Only set during initialization. */
  3100. + SSAM_HUB_CONNECTED,
  3101. + SSAM_HUB_DISCONNECTED,
  3102. +};
  3103. +
  3104. +enum ssam_hub_flags {
  3105. + SSAM_HUB_HOT_REMOVED,
  3106. +};
  3107. +
  3108. +struct ssam_hub;
  3109. +
  3110. +struct ssam_hub_ops {
  3111. + int (*get_state)(struct ssam_hub *hub, enum ssam_hub_state *state);
  3112. +};
  3113. +
  3114. +struct ssam_hub {
  3115. + struct ssam_device *sdev;
  3116. +
  3117. + enum ssam_hub_state state;
  3118. + unsigned long flags;
  3119. +
  3120. + struct delayed_work update_work;
  3121. + unsigned long connect_delay;
  3122. +
  3123. + struct ssam_event_notifier notif;
  3124. + struct ssam_hub_ops ops;
  3125. +};
  3126. +
  3127. +struct ssam_hub_desc {
  3128. + struct {
  3129. + struct ssam_event_registry reg;
  3130. + struct ssam_event_id id;
  3131. + enum ssam_event_mask mask;
  3132. + } event;
  3133. +
  3134. + struct {
  3135. + u32 (*notify)(struct ssam_event_notifier *nf, const struct ssam_event *event);
  3136. + int (*get_state)(struct ssam_hub *hub, enum ssam_hub_state *state);
  3137. + } ops;
  3138. +
  3139. + unsigned long connect_delay_ms;
  3140. +};
  3141. +
  3142. +static void ssam_hub_update_workfn(struct work_struct *work)
  3143. +{
  3144. + struct ssam_hub *hub = container_of(work, struct ssam_hub, update_work.work);
  3145. + enum ssam_hub_state state;
  3146. + int status = 0;
  3147. +
  3148. + status = hub->ops.get_state(hub, &state);
  3149. + if (status)
  3150. + return;
  3151. +
  3152. + /*
  3153. + * There is a small possibility that hub devices were hot-removed and
  3154. + * re-added before we were able to remove them here. In that case, both
  3155. + * the state returned by get_state() and the state of the hub will
  3156. + * equal SSAM_HUB_CONNECTED and we would bail early below, which would
  3157. + * leave child devices without proper (re-)initialization and the
  3158. + * hot-remove flag set.
  3159. + *
  3160. + * Therefore, we check whether devices have been hot-removed via an
  3161. + * additional flag on the hub and, in this case, override the returned
  3162. + * hub state. In case of a missed disconnect (i.e. get_state returned
  3163. + * "connected"), we further need to re-schedule this work (with the
  3164. + * appropriate delay) as the actual connect work submission might have
  3165. + * been merged with this one.
  3166. + *
  3167. + * This then leads to one of two cases: Either we submit an unnecessary
  3168. + * work item (which will get ignored via either the queue or the state
  3169. + * checks) or, in the unlikely case that the work is actually required,
  3170. + * double the normal connect delay.
  3171. + */
  3172. + if (test_and_clear_bit(SSAM_HUB_HOT_REMOVED, &hub->flags)) {
  3173. + if (state == SSAM_HUB_CONNECTED)
  3174. + schedule_delayed_work(&hub->update_work, hub->connect_delay);
  3175. +
  3176. + state = SSAM_HUB_DISCONNECTED;
  3177. + }
  3178. +
  3179. + if (hub->state == state)
  3180. + return;
  3181. + hub->state = state;
  3182. +
  3183. + if (hub->state == SSAM_HUB_CONNECTED)
  3184. + status = ssam_device_register_clients(hub->sdev);
  3185. + else
  3186. + ssam_remove_clients(&hub->sdev->dev);
  3187. +
  3188. + if (status)
  3189. + dev_err(&hub->sdev->dev, "failed to update hub child devices: %d\n", status);
  3190. +}
  3191. +
  3192. +static int ssam_hub_mark_hot_removed(struct device *dev, void *_data)
  3193. +{
  3194. + struct ssam_device *sdev = to_ssam_device(dev);
  3195. +
  3196. + if (is_ssam_device(dev))
  3197. + ssam_device_mark_hot_removed(sdev);
  3198. +
  3199. + return 0;
  3200. +}
  3201. +
  3202. +static void ssam_hub_update(struct ssam_hub *hub, bool connected)
  3203. +{
  3204. + unsigned long delay;
  3205. +
  3206. + /* Mark devices as hot-removed before we remove any. */
  3207. + if (!connected) {
  3208. + set_bit(SSAM_HUB_HOT_REMOVED, &hub->flags);
  3209. + device_for_each_child_reverse(&hub->sdev->dev, NULL, ssam_hub_mark_hot_removed);
  3210. + }
  3211. +
  3212. + /*
  3213. + * Delay update when the base/keyboard cover is being connected to give
  3214. + * devices/EC some time to set up.
  3215. + */
  3216. + delay = connected ? hub->connect_delay : 0;
  3217. +
  3218. + schedule_delayed_work(&hub->update_work, delay);
  3219. +}
  3220. +
  3221. +static int __maybe_unused ssam_hub_resume(struct device *dev)
  3222. +{
  3223. + struct ssam_hub *hub = dev_get_drvdata(dev);
  3224. +
  3225. + schedule_delayed_work(&hub->update_work, 0);
  3226. + return 0;
  3227. +}
  3228. +static SIMPLE_DEV_PM_OPS(ssam_hub_pm_ops, NULL, ssam_hub_resume);
  3229. +
  3230. +static int ssam_hub_probe(struct ssam_device *sdev)
  3231. +{
  3232. + const struct ssam_hub_desc *desc;
  3233. + struct ssam_hub *hub;
  3234. + int status;
  3235. +
  3236. + desc = ssam_device_get_match_data(sdev);
  3237. + if (!desc) {
  3238. + WARN(1, "no driver match data specified");
  3239. + return -EINVAL;
  3240. + }
  3241. +
  3242. + hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL);
  3243. + if (!hub)
  3244. + return -ENOMEM;
  3245. +
  3246. + hub->sdev = sdev;
  3247. + hub->state = SSAM_HUB_UNINITIALIZED;
  3248. +
  3249. + hub->notif.base.priority = INT_MAX; /* This notifier should run first. */
  3250. + hub->notif.base.fn = desc->ops.notify;
  3251. + hub->notif.event.reg = desc->event.reg;
  3252. + hub->notif.event.id = desc->event.id;
  3253. + hub->notif.event.mask = desc->event.mask;
  3254. + hub->notif.event.flags = SSAM_EVENT_SEQUENCED;
  3255. +
  3256. + hub->connect_delay = msecs_to_jiffies(desc->connect_delay_ms);
  3257. + hub->ops.get_state = desc->ops.get_state;
  3258. +
  3259. + INIT_DELAYED_WORK(&hub->update_work, ssam_hub_update_workfn);
  3260. +
  3261. + ssam_device_set_drvdata(sdev, hub);
  3262. +
  3263. + status = ssam_device_notifier_register(sdev, &hub->notif);
  3264. + if (status)
  3265. + return status;
  3266. +
  3267. + schedule_delayed_work(&hub->update_work, 0);
  3268. + return 0;
  3269. +}
  3270. +
  3271. +static void ssam_hub_remove(struct ssam_device *sdev)
  3272. +{
  3273. + struct ssam_hub *hub = ssam_device_get_drvdata(sdev);
  3274. +
  3275. + ssam_device_notifier_unregister(sdev, &hub->notif);
  3276. + cancel_delayed_work_sync(&hub->update_work);
  3277. + ssam_remove_clients(&sdev->dev);
  3278. +}
  3279. +
  3280. +
  3281. +/* -- SSAM base-subsystem hub driver. --------------------------------------- */
  3282. +
  3283. +/*
  3284. + * Some devices (especially battery) may need a bit of time to be fully usable
  3285. + * after being (re-)connected. This delay has been determined via
  3286. + * experimentation.
  3287. + */
  3288. +#define SSAM_BASE_UPDATE_CONNECT_DELAY 2500
  3289. +
  3290. +SSAM_DEFINE_SYNC_REQUEST_R(ssam_bas_query_opmode, u8, {
  3291. + .target_category = SSAM_SSH_TC_BAS,
  3292. + .target_id = 0x01,
  3293. + .command_id = 0x0d,
  3294. + .instance_id = 0x00,
  3295. +});
  3296. +
  3297. +#define SSAM_BAS_OPMODE_TABLET 0x00
  3298. +#define SSAM_EVENT_BAS_CID_CONNECTION 0x0c
  3299. +
  3300. +static int ssam_base_hub_query_state(struct ssam_hub *hub, enum ssam_hub_state *state)
  3301. +{
  3302. + u8 opmode;
  3303. + int status;
  3304. +
  3305. + status = ssam_retry(ssam_bas_query_opmode, hub->sdev->ctrl, &opmode);
  3306. + if (status < 0) {
  3307. + dev_err(&hub->sdev->dev, "failed to query base state: %d\n", status);
  3308. + return status;
  3309. + }
  3310. +
  3311. + if (opmode != SSAM_BAS_OPMODE_TABLET)
  3312. + *state = SSAM_HUB_CONNECTED;
  3313. + else
  3314. + *state = SSAM_HUB_DISCONNECTED;
  3315. +
  3316. + return 0;
  3317. +}
  3318. +
  3319. +static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
  3320. +{
  3321. + struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
  3322. +
  3323. + if (event->command_id != SSAM_EVENT_BAS_CID_CONNECTION)
  3324. + return 0;
  3325. +
  3326. + if (event->length < 1) {
  3327. + dev_err(&hub->sdev->dev, "unexpected payload size: %u\n", event->length);
  3328. + return 0;
  3329. + }
  3330. +
  3331. + ssam_hub_update(hub, event->data[0]);
  3332. +
  3333. + /*
  3334. + * Do not return SSAM_NOTIF_HANDLED: The event should be picked up and
  3335. + * consumed by the detachment system driver. We're just a (more or less)
  3336. + * silent observer.
  3337. + */
  3338. + return 0;
  3339. +}
  3340. +
  3341. +static const struct ssam_hub_desc base_hub = {
  3342. + .event = {
  3343. + .reg = SSAM_EVENT_REGISTRY_SAM,
  3344. + .id = {
  3345. + .target_category = SSAM_SSH_TC_BAS,
  3346. + .instance = 0,
  3347. + },
  3348. + .mask = SSAM_EVENT_MASK_NONE,
  3349. + },
  3350. + .ops = {
  3351. + .notify = ssam_base_hub_notif,
  3352. + .get_state = ssam_base_hub_query_state,
  3353. + },
  3354. + .connect_delay_ms = SSAM_BASE_UPDATE_CONNECT_DELAY,
  3355. +};
  3356. +
  3357. +
  3358. +/* -- SSAM KIP-subsystem hub driver. ---------------------------------------- */
  3359. +
  3360. +/*
  3361. + * Some devices may need a bit of time to be fully usable after being
  3362. + * (re-)connected. This delay has been determined via experimentation.
  3363. + */
  3364. +#define SSAM_KIP_UPDATE_CONNECT_DELAY 250
  3365. +
  3366. +#define SSAM_EVENT_KIP_CID_CONNECTION 0x2c
  3367. +
  3368. +SSAM_DEFINE_SYNC_REQUEST_R(__ssam_kip_query_state, u8, {
  3369. + .target_category = SSAM_SSH_TC_KIP,
  3370. + .target_id = 0x01,
  3371. + .command_id = 0x2c,
  3372. + .instance_id = 0x00,
  3373. +});
  3374. +
  3375. +static int ssam_kip_hub_query_state(struct ssam_hub *hub, enum ssam_hub_state *state)
  3376. +{
  3377. + int status;
  3378. + u8 connected;
  3379. +
  3380. + status = ssam_retry(__ssam_kip_query_state, hub->sdev->ctrl, &connected);
  3381. + if (status < 0) {
  3382. + dev_err(&hub->sdev->dev, "failed to query KIP connection state: %d\n", status);
  3383. + return status;
  3384. + }
  3385. +
  3386. + *state = connected ? SSAM_HUB_CONNECTED : SSAM_HUB_DISCONNECTED;
  3387. + return 0;
  3388. +}
  3389. +
  3390. +static u32 ssam_kip_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
  3391. +{
  3392. + struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
  3393. +
  3394. + if (event->command_id != SSAM_EVENT_KIP_CID_CONNECTION)
  3395. + return 0; /* Return "unhandled". */
  3396. +
  3397. + if (event->length < 1) {
  3398. + dev_err(&hub->sdev->dev, "unexpected payload size: %u\n", event->length);
  3399. + return 0;
  3400. + }
  3401. +
  3402. + ssam_hub_update(hub, event->data[0]);
  3403. + return SSAM_NOTIF_HANDLED;
  3404. +}
  3405. +
  3406. +static const struct ssam_hub_desc kip_hub = {
  3407. + .event = {
  3408. + .reg = SSAM_EVENT_REGISTRY_SAM,
  3409. + .id = {
  3410. + .target_category = SSAM_SSH_TC_KIP,
  3411. + .instance = 0,
  3412. + },
  3413. + .mask = SSAM_EVENT_MASK_TARGET,
  3414. + },
  3415. + .ops = {
  3416. + .notify = ssam_kip_hub_notif,
  3417. + .get_state = ssam_kip_hub_query_state,
  3418. + },
  3419. + .connect_delay_ms = SSAM_KIP_UPDATE_CONNECT_DELAY,
  3420. +};
  3421. +
  3422. +
  3423. +/* -- Driver registration. -------------------------------------------------- */
  3424. +
  3425. +static const struct ssam_device_id ssam_hub_match[] = {
  3426. + { SSAM_VDEV(HUB, 0x01, SSAM_SSH_TC_KIP, 0x00), (unsigned long)&kip_hub },
  3427. + { SSAM_VDEV(HUB, 0x02, SSAM_SSH_TC_BAS, 0x00), (unsigned long)&base_hub },
  3428. + { }
  3429. +};
  3430. +MODULE_DEVICE_TABLE(ssam, ssam_hub_match);
  3431. +
  3432. +static struct ssam_device_driver ssam_subsystem_hub_driver = {
  3433. + .probe = ssam_hub_probe,
  3434. + .remove = ssam_hub_remove,
  3435. + .match_table = ssam_hub_match,
  3436. + .driver = {
  3437. + .name = "surface_aggregator_subsystem_hub",
  3438. + .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  3439. + .pm = &ssam_hub_pm_ops,
  3440. + },
  3441. +};
  3442. +module_ssam_device_driver(ssam_subsystem_hub_driver);
  3443. +
  3444. +MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
  3445. +MODULE_DESCRIPTION("Subsystem device hub driver for Surface System Aggregator Module");
  3446. +MODULE_LICENSE("GPL");
  3447. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  3448. index eb88021c208c..76dc9c4f108e 100644
  3449. --- a/drivers/platform/surface/surface_aggregator_registry.c
  3450. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  3451. @@ -11,14 +11,11 @@
  3452. #include <linux/acpi.h>
  3453. #include <linux/kernel.h>
  3454. -#include <linux/limits.h>
  3455. #include <linux/module.h>
  3456. #include <linux/platform_device.h>
  3457. #include <linux/property.h>
  3458. #include <linux/types.h>
  3459. -#include <linux/workqueue.h>
  3460. -#include <linux/surface_aggregator/controller.h>
  3461. #include <linux/surface_aggregator/device.h>
  3462. @@ -286,335 +283,6 @@ static const struct software_node *ssam_node_group_sp8[] = {
  3463. };
  3464. -/* -- SSAM generic subsystem hub driver framework. -------------------------- */
  3465. -
  3466. -enum ssam_hub_state {
  3467. - SSAM_HUB_UNINITIALIZED, /* Only set during initialization. */
  3468. - SSAM_HUB_CONNECTED,
  3469. - SSAM_HUB_DISCONNECTED,
  3470. -};
  3471. -
  3472. -enum ssam_hub_flags {
  3473. - SSAM_HUB_HOT_REMOVED,
  3474. -};
  3475. -
  3476. -struct ssam_hub {
  3477. - struct ssam_device *sdev;
  3478. -
  3479. - enum ssam_hub_state state;
  3480. - unsigned long flags;
  3481. -
  3482. - struct delayed_work update_work;
  3483. - unsigned long connect_delay;
  3484. -
  3485. - struct ssam_event_notifier notif;
  3486. -
  3487. - int (*get_state)(struct ssam_hub *hub, enum ssam_hub_state *state);
  3488. -};
  3489. -
  3490. -static void ssam_hub_update_workfn(struct work_struct *work)
  3491. -{
  3492. - struct ssam_hub *hub = container_of(work, struct ssam_hub, update_work.work);
  3493. - enum ssam_hub_state state;
  3494. - int status = 0;
  3495. -
  3496. - status = hub->get_state(hub, &state);
  3497. - if (status)
  3498. - return;
  3499. -
  3500. - /*
  3501. - * There is a small possibility that hub devices were hot-removed and
  3502. - * re-added before we were able to remove them here. In that case, both
  3503. - * the state returned by get_state() and the state of the hub will
  3504. - * equal SSAM_HUB_CONNECTED and we would bail early below, which would
  3505. - * leave child devices without proper (re-)initialization and the
  3506. - * hot-remove flag set.
  3507. - *
  3508. - * Therefore, we check whether devices have been hot-removed via an
  3509. - * additional flag on the hub and, in this case, override the returned
  3510. - * hub state. In case of a missed disconnect (i.e. get_state returned
  3511. - * "connected"), we further need to re-schedule this work (with the
  3512. - * appropriate delay) as the actual connect work submission might have
  3513. - * been merged with this one.
  3514. - *
  3515. - * This then leads to one of two cases: Either we submit an unnecessary
  3516. - * work item (which will get ignored via either the queue or the state
  3517. - * checks) or, in the unlikely case that the work is actually required,
  3518. - * double the normal connect delay.
  3519. - */
  3520. - if (test_and_clear_bit(SSAM_HUB_HOT_REMOVED, &hub->flags)) {
  3521. - if (state == SSAM_HUB_CONNECTED)
  3522. - schedule_delayed_work(&hub->update_work, hub->connect_delay);
  3523. -
  3524. - state = SSAM_HUB_DISCONNECTED;
  3525. - }
  3526. -
  3527. - if (hub->state == state)
  3528. - return;
  3529. - hub->state = state;
  3530. -
  3531. - if (hub->state == SSAM_HUB_CONNECTED)
  3532. - status = ssam_device_register_clients(hub->sdev);
  3533. - else
  3534. - ssam_remove_clients(&hub->sdev->dev);
  3535. -
  3536. - if (status)
  3537. - dev_err(&hub->sdev->dev, "failed to update hub child devices: %d\n", status);
  3538. -}
  3539. -
  3540. -static int ssam_hub_mark_hot_removed(struct device *dev, void *_data)
  3541. -{
  3542. - struct ssam_device *sdev = to_ssam_device(dev);
  3543. -
  3544. - if (is_ssam_device(dev))
  3545. - ssam_device_mark_hot_removed(sdev);
  3546. -
  3547. - return 0;
  3548. -}
  3549. -
  3550. -static void ssam_hub_update(struct ssam_hub *hub, bool connected)
  3551. -{
  3552. - unsigned long delay;
  3553. -
  3554. - /* Mark devices as hot-removed before we remove any. */
  3555. - if (!connected) {
  3556. - set_bit(SSAM_HUB_HOT_REMOVED, &hub->flags);
  3557. - device_for_each_child_reverse(&hub->sdev->dev, NULL, ssam_hub_mark_hot_removed);
  3558. - }
  3559. -
  3560. - /*
  3561. - * Delay update when the base/keyboard cover is being connected to give
  3562. - * devices/EC some time to set up.
  3563. - */
  3564. - delay = connected ? hub->connect_delay : 0;
  3565. -
  3566. - schedule_delayed_work(&hub->update_work, delay);
  3567. -}
  3568. -
  3569. -static int __maybe_unused ssam_hub_resume(struct device *dev)
  3570. -{
  3571. - struct ssam_hub *hub = dev_get_drvdata(dev);
  3572. -
  3573. - schedule_delayed_work(&hub->update_work, 0);
  3574. - return 0;
  3575. -}
  3576. -static SIMPLE_DEV_PM_OPS(ssam_hub_pm_ops, NULL, ssam_hub_resume);
  3577. -
  3578. -static int ssam_hub_setup(struct ssam_device *sdev, struct ssam_hub *hub)
  3579. -{
  3580. - int status;
  3581. -
  3582. - hub->sdev = sdev;
  3583. - hub->state = SSAM_HUB_UNINITIALIZED;
  3584. -
  3585. - INIT_DELAYED_WORK(&hub->update_work, ssam_hub_update_workfn);
  3586. -
  3587. - ssam_device_set_drvdata(sdev, hub);
  3588. -
  3589. - status = ssam_device_notifier_register(sdev, &hub->notif);
  3590. - if (status)
  3591. - return status;
  3592. -
  3593. - schedule_delayed_work(&hub->update_work, 0);
  3594. - return 0;
  3595. -}
  3596. -
  3597. -static void ssam_hub_remove(struct ssam_device *sdev)
  3598. -{
  3599. - struct ssam_hub *hub = ssam_device_get_drvdata(sdev);
  3600. -
  3601. - ssam_device_notifier_unregister(sdev, &hub->notif);
  3602. - cancel_delayed_work_sync(&hub->update_work);
  3603. - ssam_remove_clients(&sdev->dev);
  3604. -}
  3605. -
  3606. -
  3607. -/* -- SSAM base-hub driver. ------------------------------------------------- */
  3608. -
  3609. -/*
  3610. - * Some devices (especially battery) may need a bit of time to be fully usable
  3611. - * after being (re-)connected. This delay has been determined via
  3612. - * experimentation.
  3613. - */
  3614. -#define SSAM_BASE_UPDATE_CONNECT_DELAY msecs_to_jiffies(2500)
  3615. -
  3616. -SSAM_DEFINE_SYNC_REQUEST_R(ssam_bas_query_opmode, u8, {
  3617. - .target_category = SSAM_SSH_TC_BAS,
  3618. - .target_id = 0x01,
  3619. - .command_id = 0x0d,
  3620. - .instance_id = 0x00,
  3621. -});
  3622. -
  3623. -#define SSAM_BAS_OPMODE_TABLET 0x00
  3624. -#define SSAM_EVENT_BAS_CID_CONNECTION 0x0c
  3625. -
  3626. -static int ssam_base_hub_query_state(struct ssam_hub *hub, enum ssam_hub_state *state)
  3627. -{
  3628. - u8 opmode;
  3629. - int status;
  3630. -
  3631. - status = ssam_retry(ssam_bas_query_opmode, hub->sdev->ctrl, &opmode);
  3632. - if (status < 0) {
  3633. - dev_err(&hub->sdev->dev, "failed to query base state: %d\n", status);
  3634. - return status;
  3635. - }
  3636. -
  3637. - if (opmode != SSAM_BAS_OPMODE_TABLET)
  3638. - *state = SSAM_HUB_CONNECTED;
  3639. - else
  3640. - *state = SSAM_HUB_DISCONNECTED;
  3641. -
  3642. - return 0;
  3643. -}
  3644. -
  3645. -static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
  3646. -{
  3647. - struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
  3648. -
  3649. - if (event->command_id != SSAM_EVENT_BAS_CID_CONNECTION)
  3650. - return 0;
  3651. -
  3652. - if (event->length < 1) {
  3653. - dev_err(&hub->sdev->dev, "unexpected payload size: %u\n", event->length);
  3654. - return 0;
  3655. - }
  3656. -
  3657. - ssam_hub_update(hub, event->data[0]);
  3658. -
  3659. - /*
  3660. - * Do not return SSAM_NOTIF_HANDLED: The event should be picked up and
  3661. - * consumed by the detachment system driver. We're just a (more or less)
  3662. - * silent observer.
  3663. - */
  3664. - return 0;
  3665. -}
  3666. -
  3667. -static int ssam_base_hub_probe(struct ssam_device *sdev)
  3668. -{
  3669. - struct ssam_hub *hub;
  3670. -
  3671. - hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL);
  3672. - if (!hub)
  3673. - return -ENOMEM;
  3674. -
  3675. - hub->notif.base.priority = INT_MAX; /* This notifier should run first. */
  3676. - hub->notif.base.fn = ssam_base_hub_notif;
  3677. - hub->notif.event.reg = SSAM_EVENT_REGISTRY_SAM;
  3678. - hub->notif.event.id.target_category = SSAM_SSH_TC_BAS,
  3679. - hub->notif.event.id.instance = 0,
  3680. - hub->notif.event.mask = SSAM_EVENT_MASK_NONE;
  3681. - hub->notif.event.flags = SSAM_EVENT_SEQUENCED;
  3682. -
  3683. - hub->connect_delay = SSAM_BASE_UPDATE_CONNECT_DELAY;
  3684. - hub->get_state = ssam_base_hub_query_state;
  3685. -
  3686. - return ssam_hub_setup(sdev, hub);
  3687. -}
  3688. -
  3689. -static const struct ssam_device_id ssam_base_hub_match[] = {
  3690. - { SSAM_VDEV(HUB, 0x02, SSAM_SSH_TC_BAS, 0x00) },
  3691. - { },
  3692. -};
  3693. -
  3694. -static struct ssam_device_driver ssam_base_hub_driver = {
  3695. - .probe = ssam_base_hub_probe,
  3696. - .remove = ssam_hub_remove,
  3697. - .match_table = ssam_base_hub_match,
  3698. - .driver = {
  3699. - .name = "surface_aggregator_base_hub",
  3700. - .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  3701. - .pm = &ssam_hub_pm_ops,
  3702. - },
  3703. -};
  3704. -
  3705. -
  3706. -/* -- SSAM KIP-subsystem hub driver. ---------------------------------------- */
  3707. -
  3708. -/*
  3709. - * Some devices may need a bit of time to be fully usable after being
  3710. - * (re-)connected. This delay has been determined via experimentation.
  3711. - */
  3712. -#define SSAM_KIP_UPDATE_CONNECT_DELAY msecs_to_jiffies(250)
  3713. -
  3714. -#define SSAM_EVENT_KIP_CID_CONNECTION 0x2c
  3715. -
  3716. -SSAM_DEFINE_SYNC_REQUEST_R(__ssam_kip_get_connection_state, u8, {
  3717. - .target_category = SSAM_SSH_TC_KIP,
  3718. - .target_id = 0x01,
  3719. - .command_id = 0x2c,
  3720. - .instance_id = 0x00,
  3721. -});
  3722. -
  3723. -static int ssam_kip_get_connection_state(struct ssam_hub *hub, enum ssam_hub_state *state)
  3724. -{
  3725. - int status;
  3726. - u8 connected;
  3727. -
  3728. - status = ssam_retry(__ssam_kip_get_connection_state, hub->sdev->ctrl, &connected);
  3729. - if (status < 0) {
  3730. - dev_err(&hub->sdev->dev, "failed to query KIP connection state: %d\n", status);
  3731. - return status;
  3732. - }
  3733. -
  3734. - *state = connected ? SSAM_HUB_CONNECTED : SSAM_HUB_DISCONNECTED;
  3735. - return 0;
  3736. -}
  3737. -
  3738. -static u32 ssam_kip_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
  3739. -{
  3740. - struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
  3741. -
  3742. - if (event->command_id != SSAM_EVENT_KIP_CID_CONNECTION)
  3743. - return 0; /* Return "unhandled". */
  3744. -
  3745. - if (event->length < 1) {
  3746. - dev_err(&hub->sdev->dev, "unexpected payload size: %u\n", event->length);
  3747. - return 0;
  3748. - }
  3749. -
  3750. - ssam_hub_update(hub, event->data[0]);
  3751. - return SSAM_NOTIF_HANDLED;
  3752. -}
  3753. -
  3754. -static int ssam_kip_hub_probe(struct ssam_device *sdev)
  3755. -{
  3756. - struct ssam_hub *hub;
  3757. -
  3758. - hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL);
  3759. - if (!hub)
  3760. - return -ENOMEM;
  3761. -
  3762. - hub->notif.base.priority = INT_MAX; /* This notifier should run first. */
  3763. - hub->notif.base.fn = ssam_kip_hub_notif;
  3764. - hub->notif.event.reg = SSAM_EVENT_REGISTRY_SAM;
  3765. - hub->notif.event.id.target_category = SSAM_SSH_TC_KIP,
  3766. - hub->notif.event.id.instance = 0,
  3767. - hub->notif.event.mask = SSAM_EVENT_MASK_TARGET;
  3768. - hub->notif.event.flags = SSAM_EVENT_SEQUENCED;
  3769. -
  3770. - hub->connect_delay = SSAM_KIP_UPDATE_CONNECT_DELAY;
  3771. - hub->get_state = ssam_kip_get_connection_state;
  3772. -
  3773. - return ssam_hub_setup(sdev, hub);
  3774. -}
  3775. -
  3776. -static const struct ssam_device_id ssam_kip_hub_match[] = {
  3777. - { SSAM_VDEV(HUB, 0x01, SSAM_SSH_TC_KIP, 0x00) },
  3778. - { },
  3779. -};
  3780. -
  3781. -static struct ssam_device_driver ssam_kip_hub_driver = {
  3782. - .probe = ssam_kip_hub_probe,
  3783. - .remove = ssam_hub_remove,
  3784. - .match_table = ssam_kip_hub_match,
  3785. - .driver = {
  3786. - .name = "surface_kip_hub",
  3787. - .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  3788. - .pm = &ssam_hub_pm_ops,
  3789. - },
  3790. -};
  3791. -
  3792. -
  3793. /* -- SSAM platform/meta-hub driver. ---------------------------------------- */
  3794. static const struct acpi_device_id ssam_platform_hub_match[] = {
  3795. @@ -730,44 +398,7 @@ static struct platform_driver ssam_platform_hub_driver = {
  3796. .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  3797. },
  3798. };
  3799. -
  3800. -
  3801. -/* -- Module initialization. ------------------------------------------------ */
  3802. -
  3803. -static int __init ssam_device_hub_init(void)
  3804. -{
  3805. - int status;
  3806. -
  3807. - status = platform_driver_register(&ssam_platform_hub_driver);
  3808. - if (status)
  3809. - goto err_platform;
  3810. -
  3811. - status = ssam_device_driver_register(&ssam_base_hub_driver);
  3812. - if (status)
  3813. - goto err_base;
  3814. -
  3815. - status = ssam_device_driver_register(&ssam_kip_hub_driver);
  3816. - if (status)
  3817. - goto err_kip;
  3818. -
  3819. - return 0;
  3820. -
  3821. -err_kip:
  3822. - ssam_device_driver_unregister(&ssam_base_hub_driver);
  3823. -err_base:
  3824. - platform_driver_unregister(&ssam_platform_hub_driver);
  3825. -err_platform:
  3826. - return status;
  3827. -}
  3828. -module_init(ssam_device_hub_init);
  3829. -
  3830. -static void __exit ssam_device_hub_exit(void)
  3831. -{
  3832. - ssam_device_driver_unregister(&ssam_kip_hub_driver);
  3833. - ssam_device_driver_unregister(&ssam_base_hub_driver);
  3834. - platform_driver_unregister(&ssam_platform_hub_driver);
  3835. -}
  3836. -module_exit(ssam_device_hub_exit);
  3837. +module_platform_driver(ssam_platform_hub_driver);
  3838. MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
  3839. MODULE_DESCRIPTION("Device-registry for Surface System Aggregator Module");
  3840. --
  3841. 2.38.0
  3842. From 7724d8aff10451320a984da1e036e6287d31d885 Mon Sep 17 00:00:00 2001
  3843. From: Maximilian Luz <luzmaximilian@gmail.com>
  3844. Date: Fri, 24 Jun 2022 22:58:00 +0200
  3845. Subject: [PATCH] platform/surface: Update copyright year of various drivers
  3846. Update the copyright of various Surface drivers to the current year.
  3847. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  3848. Link: https://lore.kernel.org/r/20220624205800.1355621-4-luzmaximilian@gmail.com
  3849. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  3850. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  3851. Patchset: surface-sam
  3852. ---
  3853. drivers/platform/surface/aggregator/Kconfig | 2 +-
  3854. drivers/platform/surface/aggregator/Makefile | 2 +-
  3855. drivers/platform/surface/aggregator/bus.c | 2 +-
  3856. drivers/platform/surface/aggregator/bus.h | 2 +-
  3857. drivers/platform/surface/aggregator/controller.c | 2 +-
  3858. drivers/platform/surface/aggregator/controller.h | 2 +-
  3859. drivers/platform/surface/aggregator/core.c | 2 +-
  3860. drivers/platform/surface/aggregator/ssh_msgb.h | 2 +-
  3861. drivers/platform/surface/aggregator/ssh_packet_layer.c | 2 +-
  3862. drivers/platform/surface/aggregator/ssh_packet_layer.h | 2 +-
  3863. drivers/platform/surface/aggregator/ssh_parser.c | 2 +-
  3864. drivers/platform/surface/aggregator/ssh_parser.h | 2 +-
  3865. drivers/platform/surface/aggregator/ssh_request_layer.c | 2 +-
  3866. drivers/platform/surface/aggregator/ssh_request_layer.h | 2 +-
  3867. drivers/platform/surface/aggregator/trace.h | 2 +-
  3868. drivers/platform/surface/surface_acpi_notify.c | 2 +-
  3869. drivers/platform/surface/surface_aggregator_cdev.c | 2 +-
  3870. drivers/platform/surface/surface_aggregator_registry.c | 2 +-
  3871. drivers/platform/surface/surface_dtx.c | 2 +-
  3872. drivers/platform/surface/surface_gpe.c | 2 +-
  3873. drivers/platform/surface/surface_hotplug.c | 2 +-
  3874. drivers/platform/surface/surface_platform_profile.c | 2 +-
  3875. 22 files changed, 22 insertions(+), 22 deletions(-)
  3876. diff --git a/drivers/platform/surface/aggregator/Kconfig b/drivers/platform/surface/aggregator/Kconfig
  3877. index cab020324256..c114f9dd5fe1 100644
  3878. --- a/drivers/platform/surface/aggregator/Kconfig
  3879. +++ b/drivers/platform/surface/aggregator/Kconfig
  3880. @@ -1,5 +1,5 @@
  3881. # SPDX-License-Identifier: GPL-2.0+
  3882. -# Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3883. +# Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3884. menuconfig SURFACE_AGGREGATOR
  3885. tristate "Microsoft Surface System Aggregator Module Subsystem and Drivers"
  3886. diff --git a/drivers/platform/surface/aggregator/Makefile b/drivers/platform/surface/aggregator/Makefile
  3887. index c0d550eda5cd..fdf664a217f9 100644
  3888. --- a/drivers/platform/surface/aggregator/Makefile
  3889. +++ b/drivers/platform/surface/aggregator/Makefile
  3890. @@ -1,5 +1,5 @@
  3891. # SPDX-License-Identifier: GPL-2.0+
  3892. -# Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3893. +# Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3894. # For include/trace/define_trace.h to include trace.h
  3895. CFLAGS_core.o = -I$(src)
  3896. diff --git a/drivers/platform/surface/aggregator/bus.c b/drivers/platform/surface/aggregator/bus.c
  3897. index e0b0381a2834..de539938896e 100644
  3898. --- a/drivers/platform/surface/aggregator/bus.c
  3899. +++ b/drivers/platform/surface/aggregator/bus.c
  3900. @@ -2,7 +2,7 @@
  3901. /*
  3902. * Surface System Aggregator Module bus and device integration.
  3903. *
  3904. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3905. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3906. */
  3907. #include <linux/device.h>
  3908. diff --git a/drivers/platform/surface/aggregator/bus.h b/drivers/platform/surface/aggregator/bus.h
  3909. index 6964ee84e79c..5b4dbf21906c 100644
  3910. --- a/drivers/platform/surface/aggregator/bus.h
  3911. +++ b/drivers/platform/surface/aggregator/bus.h
  3912. @@ -2,7 +2,7 @@
  3913. /*
  3914. * Surface System Aggregator Module bus and device integration.
  3915. *
  3916. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3917. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3918. */
  3919. #ifndef _SURFACE_AGGREGATOR_BUS_H
  3920. diff --git a/drivers/platform/surface/aggregator/controller.c b/drivers/platform/surface/aggregator/controller.c
  3921. index 6de834b52b63..43e765199137 100644
  3922. --- a/drivers/platform/surface/aggregator/controller.c
  3923. +++ b/drivers/platform/surface/aggregator/controller.c
  3924. @@ -2,7 +2,7 @@
  3925. /*
  3926. * Main SSAM/SSH controller structure and functionality.
  3927. *
  3928. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3929. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3930. */
  3931. #include <linux/acpi.h>
  3932. diff --git a/drivers/platform/surface/aggregator/controller.h b/drivers/platform/surface/aggregator/controller.h
  3933. index a0963c3562ff..f0d987abc51e 100644
  3934. --- a/drivers/platform/surface/aggregator/controller.h
  3935. +++ b/drivers/platform/surface/aggregator/controller.h
  3936. @@ -2,7 +2,7 @@
  3937. /*
  3938. * Main SSAM/SSH controller structure and functionality.
  3939. *
  3940. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3941. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3942. */
  3943. #ifndef _SURFACE_AGGREGATOR_CONTROLLER_H
  3944. diff --git a/drivers/platform/surface/aggregator/core.c b/drivers/platform/surface/aggregator/core.c
  3945. index a62c5dfe42d6..1a6373dea109 100644
  3946. --- a/drivers/platform/surface/aggregator/core.c
  3947. +++ b/drivers/platform/surface/aggregator/core.c
  3948. @@ -7,7 +7,7 @@
  3949. * Handles communication via requests as well as enabling, disabling, and
  3950. * relaying of events.
  3951. *
  3952. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3953. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3954. */
  3955. #include <linux/acpi.h>
  3956. diff --git a/drivers/platform/surface/aggregator/ssh_msgb.h b/drivers/platform/surface/aggregator/ssh_msgb.h
  3957. index e562958ffdf0..f3ecad92eefd 100644
  3958. --- a/drivers/platform/surface/aggregator/ssh_msgb.h
  3959. +++ b/drivers/platform/surface/aggregator/ssh_msgb.h
  3960. @@ -2,7 +2,7 @@
  3961. /*
  3962. * SSH message builder functions.
  3963. *
  3964. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3965. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3966. */
  3967. #ifndef _SURFACE_AGGREGATOR_SSH_MSGB_H
  3968. diff --git a/drivers/platform/surface/aggregator/ssh_packet_layer.c b/drivers/platform/surface/aggregator/ssh_packet_layer.c
  3969. index 8a4451c1ffe5..6748fe4ac5d5 100644
  3970. --- a/drivers/platform/surface/aggregator/ssh_packet_layer.c
  3971. +++ b/drivers/platform/surface/aggregator/ssh_packet_layer.c
  3972. @@ -2,7 +2,7 @@
  3973. /*
  3974. * SSH packet transport layer.
  3975. *
  3976. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3977. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3978. */
  3979. #include <asm/unaligned.h>
  3980. diff --git a/drivers/platform/surface/aggregator/ssh_packet_layer.h b/drivers/platform/surface/aggregator/ssh_packet_layer.h
  3981. index 2eb329f0b91a..64633522f971 100644
  3982. --- a/drivers/platform/surface/aggregator/ssh_packet_layer.h
  3983. +++ b/drivers/platform/surface/aggregator/ssh_packet_layer.h
  3984. @@ -2,7 +2,7 @@
  3985. /*
  3986. * SSH packet transport layer.
  3987. *
  3988. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3989. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3990. */
  3991. #ifndef _SURFACE_AGGREGATOR_SSH_PACKET_LAYER_H
  3992. diff --git a/drivers/platform/surface/aggregator/ssh_parser.c b/drivers/platform/surface/aggregator/ssh_parser.c
  3993. index b77912f8f13b..a6f668694365 100644
  3994. --- a/drivers/platform/surface/aggregator/ssh_parser.c
  3995. +++ b/drivers/platform/surface/aggregator/ssh_parser.c
  3996. @@ -2,7 +2,7 @@
  3997. /*
  3998. * SSH message parser.
  3999. *
  4000. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  4001. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  4002. */
  4003. #include <asm/unaligned.h>
  4004. diff --git a/drivers/platform/surface/aggregator/ssh_parser.h b/drivers/platform/surface/aggregator/ssh_parser.h
  4005. index 3bd6e180fd16..801d8fa69fb5 100644
  4006. --- a/drivers/platform/surface/aggregator/ssh_parser.h
  4007. +++ b/drivers/platform/surface/aggregator/ssh_parser.h
  4008. @@ -2,7 +2,7 @@
  4009. /*
  4010. * SSH message parser.
  4011. *
  4012. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  4013. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  4014. */
  4015. #ifndef _SURFACE_AGGREGATOR_SSH_PARSER_H
  4016. diff --git a/drivers/platform/surface/aggregator/ssh_request_layer.c b/drivers/platform/surface/aggregator/ssh_request_layer.c
  4017. index 790f7f0eee98..f5565570f16c 100644
  4018. --- a/drivers/platform/surface/aggregator/ssh_request_layer.c
  4019. +++ b/drivers/platform/surface/aggregator/ssh_request_layer.c
  4020. @@ -2,7 +2,7 @@
  4021. /*
  4022. * SSH request transport layer.
  4023. *
  4024. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  4025. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  4026. */
  4027. #include <asm/unaligned.h>
  4028. diff --git a/drivers/platform/surface/aggregator/ssh_request_layer.h b/drivers/platform/surface/aggregator/ssh_request_layer.h
  4029. index 9c3cbae2d4bd..4e387a031351 100644
  4030. --- a/drivers/platform/surface/aggregator/ssh_request_layer.h
  4031. +++ b/drivers/platform/surface/aggregator/ssh_request_layer.h
  4032. @@ -2,7 +2,7 @@
  4033. /*
  4034. * SSH request transport layer.
  4035. *
  4036. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  4037. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  4038. */
  4039. #ifndef _SURFACE_AGGREGATOR_SSH_REQUEST_LAYER_H
  4040. diff --git a/drivers/platform/surface/aggregator/trace.h b/drivers/platform/surface/aggregator/trace.h
  4041. index cc9e73fbc18e..2a2c17771d01 100644
  4042. --- a/drivers/platform/surface/aggregator/trace.h
  4043. +++ b/drivers/platform/surface/aggregator/trace.h
  4044. @@ -2,7 +2,7 @@
  4045. /*
  4046. * Trace points for SSAM/SSH.
  4047. *
  4048. - * Copyright (C) 2020-2021 Maximilian Luz <luzmaximilian@gmail.com>
  4049. + * Copyright (C) 2020-2022 Maximilian Luz <luzmaximilian@gmail.com>
  4050. */
  4051. #undef TRACE_SYSTEM
  4052. diff --git a/drivers/platform/surface/surface_acpi_notify.c b/drivers/platform/surface/surface_acpi_notify.c
  4053. index c0e12f0b9b79..44e317970557 100644
  4054. --- a/drivers/platform/surface/surface_acpi_notify.c
  4055. +++ b/drivers/platform/surface/surface_acpi_notify.c
  4056. @@ -8,7 +8,7 @@
  4057. * notifications sent from ACPI via the SAN interface by providing them to any
  4058. * registered external driver.
  4059. *
  4060. - * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
  4061. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  4062. */
  4063. #include <asm/unaligned.h>
  4064. diff --git a/drivers/platform/surface/surface_aggregator_cdev.c b/drivers/platform/surface/surface_aggregator_cdev.c
  4065. index 30fb50fde450..492c82e69182 100644
  4066. --- a/drivers/platform/surface/surface_aggregator_cdev.c
  4067. +++ b/drivers/platform/surface/surface_aggregator_cdev.c
  4068. @@ -3,7 +3,7 @@
  4069. * Provides user-space access to the SSAM EC via the /dev/surface/aggregator
  4070. * misc device. Intended for debugging and development.
  4071. *
  4072. - * Copyright (C) 2020-2021 Maximilian Luz <luzmaximilian@gmail.com>
  4073. + * Copyright (C) 2020-2022 Maximilian Luz <luzmaximilian@gmail.com>
  4074. */
  4075. #include <linux/fs.h>
  4076. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  4077. index 76dc9c4f108e..93ab62eb393d 100644
  4078. --- a/drivers/platform/surface/surface_aggregator_registry.c
  4079. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  4080. @@ -6,7 +6,7 @@
  4081. * cannot be auto-detected. Provides device-hubs and performs instantiation
  4082. * for these devices.
  4083. *
  4084. - * Copyright (C) 2020-2021 Maximilian Luz <luzmaximilian@gmail.com>
  4085. + * Copyright (C) 2020-2022 Maximilian Luz <luzmaximilian@gmail.com>
  4086. */
  4087. #include <linux/acpi.h>
  4088. diff --git a/drivers/platform/surface/surface_dtx.c b/drivers/platform/surface/surface_dtx.c
  4089. index 1203b9a82993..ed36944467f9 100644
  4090. --- a/drivers/platform/surface/surface_dtx.c
  4091. +++ b/drivers/platform/surface/surface_dtx.c
  4092. @@ -8,7 +8,7 @@
  4093. * acknowledge (to speed things up), abort (e.g. in case the dGPU is still in
  4094. * use), or request detachment via user-space.
  4095. *
  4096. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  4097. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  4098. */
  4099. #include <linux/fs.h>
  4100. diff --git a/drivers/platform/surface/surface_gpe.c b/drivers/platform/surface/surface_gpe.c
  4101. index ec66fde28e75..27365cbe1ee9 100644
  4102. --- a/drivers/platform/surface/surface_gpe.c
  4103. +++ b/drivers/platform/surface/surface_gpe.c
  4104. @@ -4,7 +4,7 @@
  4105. * properly configuring the respective GPEs. Required for wakeup via lid on
  4106. * newer Intel-based Microsoft Surface devices.
  4107. *
  4108. - * Copyright (C) 2020 Maximilian Luz <luzmaximilian@gmail.com>
  4109. + * Copyright (C) 2020-2022 Maximilian Luz <luzmaximilian@gmail.com>
  4110. */
  4111. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  4112. diff --git a/drivers/platform/surface/surface_hotplug.c b/drivers/platform/surface/surface_hotplug.c
  4113. index cfcc15cfbacb..f004a2495201 100644
  4114. --- a/drivers/platform/surface/surface_hotplug.c
  4115. +++ b/drivers/platform/surface/surface_hotplug.c
  4116. @@ -10,7 +10,7 @@
  4117. * Event signaling is handled via ACPI, which will generate the appropriate
  4118. * device-check notifications to be picked up by the PCIe hot-plug driver.
  4119. *
  4120. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  4121. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  4122. */
  4123. #include <linux/acpi.h>
  4124. diff --git a/drivers/platform/surface/surface_platform_profile.c b/drivers/platform/surface/surface_platform_profile.c
  4125. index 6373d3b5eb7f..fbf2e11fd6ce 100644
  4126. --- a/drivers/platform/surface/surface_platform_profile.c
  4127. +++ b/drivers/platform/surface/surface_platform_profile.c
  4128. @@ -3,7 +3,7 @@
  4129. * Surface Platform Profile / Performance Mode driver for Surface System
  4130. * Aggregator Module (thermal subsystem).
  4131. *
  4132. - * Copyright (C) 2021 Maximilian Luz <luzmaximilian@gmail.com>
  4133. + * Copyright (C) 2021-2022 Maximilian Luz <luzmaximilian@gmail.com>
  4134. */
  4135. #include <asm/unaligned.h>
  4136. --
  4137. 2.38.0
  4138. From c438c4623613abea111de98c2b31e5485ad3ebfa Mon Sep 17 00:00:00 2001
  4139. From: Lukas Bulwahn <lukas.bulwahn@gmail.com>
  4140. Date: Wed, 13 Jul 2022 06:09:16 +0200
  4141. Subject: [PATCH] MAINTAINERS: repair file entry in MICROSOFT SURFACE
  4142. AGGREGATOR TABLET-MODE SWITCH
  4143. Commit 9f794056db5b ("platform/surface: Add KIP/POS tablet-mode switch
  4144. driver") adds the section MICROSOFT SURFACE AGGREGATOR TABLET-MODE SWITCH
  4145. with a file entry, but the file that is added with this commit is actually
  4146. named slightly differently.
  4147. file entry name: drivers/platform/surface/surface_aggregator_tablet_switch.c
  4148. added file name: drivers/platform/surface/surface_aggregator_tabletsw.c
  4149. Hence, ./scripts/get_maintainer.pl --self-test=patterns complains about a
  4150. broken reference.
  4151. Repair this file entry to the actual file name added with the commit above.
  4152. Fixes: 9f794056db5b ("platform/surface: Add KIP/POS tablet-mode switch driver")
  4153. Signed-off-by: Lukas Bulwahn <lukas.bulwahn@gmail.com>
  4154. Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
  4155. Reviewed-by: Maximilian Luz <luzmaximilian@gmail.com>
  4156. Link: https://lore.kernel.org/r/20220713040916.1767-1-lukas.bulwahn@gmail.com
  4157. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  4158. Patchset: surface-sam
  4159. ---
  4160. MAINTAINERS | 2 +-
  4161. 1 file changed, 1 insertion(+), 1 deletion(-)
  4162. diff --git a/MAINTAINERS b/MAINTAINERS
  4163. index 55e80354a097..6772c9d0eccc 100644
  4164. --- a/MAINTAINERS
  4165. +++ b/MAINTAINERS
  4166. @@ -13303,7 +13303,7 @@ MICROSOFT SURFACE AGGREGATOR TABLET-MODE SWITCH
  4167. M: Maximilian Luz <luzmaximilian@gmail.com>
  4168. L: platform-driver-x86@vger.kernel.org
  4169. S: Maintained
  4170. -F: drivers/platform/surface/surface_aggregator_tablet_switch.c
  4171. +F: drivers/platform/surface/surface_aggregator_tabletsw.c
  4172. MICROSOFT SURFACE BATTERY AND AC DRIVERS
  4173. M: Maximilian Luz <luzmaximilian@gmail.com>
  4174. --
  4175. 2.38.0
  4176. From 5186ef74d3d66701d614de93666a74ca282b7f63 Mon Sep 17 00:00:00 2001
  4177. From: Maximilian Luz <luzmaximilian@gmail.com>
  4178. Date: Sun, 17 Jul 2022 14:07:35 +0200
  4179. Subject: [PATCH] platform/surface: tabletsw: Fix __le32 integer access
  4180. The sources.count field is a __le32 inside a packed struct. So use the
  4181. proper functions to access it.
  4182. Reported-by: kernel test robot <lkp@intel.com>
  4183. Fixes: 9f794056db5b ("platform/surface: Add KIP/POS tablet-mode switch driver")
  4184. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  4185. Link: https://lore.kernel.org/r/20220717120735.2052160-1-luzmaximilian@gmail.com
  4186. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  4187. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  4188. Patchset: surface-sam
  4189. ---
  4190. drivers/platform/surface/surface_aggregator_tabletsw.c | 4 ++--
  4191. 1 file changed, 2 insertions(+), 2 deletions(-)
  4192. diff --git a/drivers/platform/surface/surface_aggregator_tabletsw.c b/drivers/platform/surface/surface_aggregator_tabletsw.c
  4193. index 596ca6c80681..27d95a6a7851 100644
  4194. --- a/drivers/platform/surface/surface_aggregator_tabletsw.c
  4195. +++ b/drivers/platform/surface/surface_aggregator_tabletsw.c
  4196. @@ -410,7 +410,7 @@ static int ssam_pos_get_source(struct ssam_tablet_sw *sw, u32 *source_id)
  4197. if (status)
  4198. return status;
  4199. - if (sources.count == 0) {
  4200. + if (get_unaligned_le32(&sources.count) == 0) {
  4201. dev_err(&sw->sdev->dev, "no posture sources found\n");
  4202. return -ENODEV;
  4203. }
  4204. @@ -422,7 +422,7 @@ static int ssam_pos_get_source(struct ssam_tablet_sw *sw, u32 *source_id)
  4205. * is a device that provides multiple sources, at which point we can
  4206. * then try to figure out how to handle them.
  4207. */
  4208. - WARN_ON(sources.count > 1);
  4209. + WARN_ON(get_unaligned_le32(&sources.count) > 1);
  4210. *source_id = get_unaligned_le32(&sources.id[0]);
  4211. return 0;
  4212. --
  4213. 2.38.0
  4214. From 8d9c314269418930276f16add5c811760cb5bceb Mon Sep 17 00:00:00 2001
  4215. From: Maximilian Luz <luzmaximilian@gmail.com>
  4216. Date: Sat, 25 Jun 2022 20:42:00 +0200
  4217. Subject: [PATCH] platform/surface: aggregator_registry: Rename HID device
  4218. nodes based on their function
  4219. Rename HID device nodes based on their function. In particular, these
  4220. are nodes for firmware updates via the CFU mechanism (component firmware
  4221. update), HID based sensors, and a USB-C UCSI client.
  4222. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  4223. Patchset: surface-sam
  4224. ---
  4225. .../surface/surface_aggregator_registry.c | 18 +++++++++---------
  4226. 1 file changed, 9 insertions(+), 9 deletions(-)
  4227. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  4228. index 93ab62eb393d..7d82398f55b1 100644
  4229. --- a/drivers/platform/surface/surface_aggregator_registry.c
  4230. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  4231. @@ -104,14 +104,14 @@ static const struct software_node ssam_node_hid_tid1_touchpad = {
  4232. .parent = &ssam_node_root,
  4233. };
  4234. -/* HID device instance 6 (TID1, unknown HID device). */
  4235. -static const struct software_node ssam_node_hid_tid1_iid6 = {
  4236. +/* HID device instance 6 (TID1, HID sensor collection). */
  4237. +static const struct software_node ssam_node_hid_tid1_sensors = {
  4238. .name = "ssam:01:15:01:06:00",
  4239. .parent = &ssam_node_root,
  4240. };
  4241. -/* HID device instance 7 (TID1, unknown HID device). */
  4242. -static const struct software_node ssam_node_hid_tid1_iid7 = {
  4243. +/* HID device instance 7 (TID1, UCM UCSI HID client). */
  4244. +static const struct software_node ssam_node_hid_tid1_ucm_ucsi = {
  4245. .name = "ssam:01:15:01:07:00",
  4246. .parent = &ssam_node_root,
  4247. };
  4248. @@ -182,8 +182,8 @@ static const struct software_node ssam_node_hid_kip_touchpad = {
  4249. .parent = &ssam_node_hub_kip,
  4250. };
  4251. -/* HID device instance 5 (KIP hub, unknown HID device). */
  4252. -static const struct software_node ssam_node_hid_kip_iid5 = {
  4253. +/* HID device instance 5 (KIP hub, type-cover firmware update). */
  4254. +static const struct software_node ssam_node_hid_kip_fwupd = {
  4255. .name = "ssam:01:15:02:05:00",
  4256. .parent = &ssam_node_hub_kip,
  4257. };
  4258. @@ -244,8 +244,8 @@ static const struct software_node *ssam_node_group_sls[] = {
  4259. &ssam_node_hid_tid1_keyboard,
  4260. &ssam_node_hid_tid1_penstash,
  4261. &ssam_node_hid_tid1_touchpad,
  4262. - &ssam_node_hid_tid1_iid6,
  4263. - &ssam_node_hid_tid1_iid7,
  4264. + &ssam_node_hid_tid1_sensors,
  4265. + &ssam_node_hid_tid1_ucm_ucsi,
  4266. &ssam_node_hid_tid1_sysctrl,
  4267. NULL,
  4268. };
  4269. @@ -278,7 +278,7 @@ static const struct software_node *ssam_node_group_sp8[] = {
  4270. &ssam_node_hid_kip_keyboard,
  4271. &ssam_node_hid_kip_penstash,
  4272. &ssam_node_hid_kip_touchpad,
  4273. - &ssam_node_hid_kip_iid5,
  4274. + &ssam_node_hid_kip_fwupd,
  4275. NULL,
  4276. };
  4277. --
  4278. 2.38.0
  4279. From 60c2cdb4214c855aa92b1e23f15856eefbaef80f Mon Sep 17 00:00:00 2001
  4280. From: Maximilian Luz <luzmaximilian@gmail.com>
  4281. Date: Sat, 25 Jun 2022 20:52:47 +0200
  4282. Subject: [PATCH] platform/surface: aggregator_registry: Rename HID device
  4283. nodes based on new findings
  4284. On Windows, the HID devices with target ID 1 are grouped as "Surface Hot
  4285. Plug - SAM". Rename their device nodes in the registry to reflect that
  4286. and update the comments accordingly.
  4287. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  4288. Patchset: surface-sam
  4289. ---
  4290. .../surface/surface_aggregator_registry.c | 36 +++++++++----------
  4291. 1 file changed, 18 insertions(+), 18 deletions(-)
  4292. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  4293. index 7d82398f55b1..9970f89b1411 100644
  4294. --- a/drivers/platform/surface/surface_aggregator_registry.c
  4295. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  4296. @@ -86,38 +86,38 @@ static const struct software_node ssam_node_bas_dtx = {
  4297. .parent = &ssam_node_root,
  4298. };
  4299. -/* HID keyboard (TID1). */
  4300. -static const struct software_node ssam_node_hid_tid1_keyboard = {
  4301. +/* HID keyboard (SAM, TID=1). */
  4302. +static const struct software_node ssam_node_hid_sam_keyboard = {
  4303. .name = "ssam:01:15:01:01:00",
  4304. .parent = &ssam_node_root,
  4305. };
  4306. -/* HID pen stash (TID1; pen taken / stashed away evens). */
  4307. -static const struct software_node ssam_node_hid_tid1_penstash = {
  4308. +/* HID pen stash (SAM, TID=1; pen taken / stashed away evens). */
  4309. +static const struct software_node ssam_node_hid_sam_penstash = {
  4310. .name = "ssam:01:15:01:02:00",
  4311. .parent = &ssam_node_root,
  4312. };
  4313. -/* HID touchpad (TID1). */
  4314. -static const struct software_node ssam_node_hid_tid1_touchpad = {
  4315. +/* HID touchpad (SAM, TID=1). */
  4316. +static const struct software_node ssam_node_hid_sam_touchpad = {
  4317. .name = "ssam:01:15:01:03:00",
  4318. .parent = &ssam_node_root,
  4319. };
  4320. -/* HID device instance 6 (TID1, HID sensor collection). */
  4321. -static const struct software_node ssam_node_hid_tid1_sensors = {
  4322. +/* HID device instance 6 (SAM, TID=1, HID sensor collection). */
  4323. +static const struct software_node ssam_node_hid_sam_sensors = {
  4324. .name = "ssam:01:15:01:06:00",
  4325. .parent = &ssam_node_root,
  4326. };
  4327. -/* HID device instance 7 (TID1, UCM UCSI HID client). */
  4328. -static const struct software_node ssam_node_hid_tid1_ucm_ucsi = {
  4329. +/* HID device instance 7 (SAM, TID=1, UCM UCSI HID client). */
  4330. +static const struct software_node ssam_node_hid_sam_ucm_ucsi = {
  4331. .name = "ssam:01:15:01:07:00",
  4332. .parent = &ssam_node_root,
  4333. };
  4334. -/* HID system controls (TID1). */
  4335. -static const struct software_node ssam_node_hid_tid1_sysctrl = {
  4336. +/* HID system controls (SAM, TID=1). */
  4337. +static const struct software_node ssam_node_hid_sam_sysctrl = {
  4338. .name = "ssam:01:15:01:08:00",
  4339. .parent = &ssam_node_root,
  4340. };
  4341. @@ -241,12 +241,12 @@ static const struct software_node *ssam_node_group_sls[] = {
  4342. &ssam_node_bat_main,
  4343. &ssam_node_tmp_pprof,
  4344. &ssam_node_pos_tablet_switch,
  4345. - &ssam_node_hid_tid1_keyboard,
  4346. - &ssam_node_hid_tid1_penstash,
  4347. - &ssam_node_hid_tid1_touchpad,
  4348. - &ssam_node_hid_tid1_sensors,
  4349. - &ssam_node_hid_tid1_ucm_ucsi,
  4350. - &ssam_node_hid_tid1_sysctrl,
  4351. + &ssam_node_hid_sam_keyboard,
  4352. + &ssam_node_hid_sam_penstash,
  4353. + &ssam_node_hid_sam_touchpad,
  4354. + &ssam_node_hid_sam_sensors,
  4355. + &ssam_node_hid_sam_ucm_ucsi,
  4356. + &ssam_node_hid_sam_sysctrl,
  4357. NULL,
  4358. };
  4359. --
  4360. 2.38.0
  4361. From dbd435c49913b4e6f186647301f311fb1ab1e61c Mon Sep 17 00:00:00 2001
  4362. From: Maximilian Luz <luzmaximilian@gmail.com>
  4363. Date: Sat, 25 Jun 2022 20:54:59 +0200
  4364. Subject: [PATCH] platform/surface: aggregator_registry: Add HID devices for
  4365. sensors and UCSI client to SP8
  4366. Add software nodes for the HID sensor collection and the UCM UCSI HID
  4367. client to the Surface Pro 8. In contrast to the type-cover devices,
  4368. these devices are directly attached to the SAM controller, without any
  4369. hub.
  4370. This enables support for HID-based sensors, including the ones used for
  4371. automatic screen rotation, on the Surface Pro 8.
  4372. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  4373. Patchset: surface-sam
  4374. ---
  4375. drivers/platform/surface/surface_aggregator_registry.c | 2 ++
  4376. 1 file changed, 2 insertions(+)
  4377. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  4378. index 9970f89b1411..585911020cea 100644
  4379. --- a/drivers/platform/surface/surface_aggregator_registry.c
  4380. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  4381. @@ -279,6 +279,8 @@ static const struct software_node *ssam_node_group_sp8[] = {
  4382. &ssam_node_hid_kip_penstash,
  4383. &ssam_node_hid_kip_touchpad,
  4384. &ssam_node_hid_kip_fwupd,
  4385. + &ssam_node_hid_sam_sensors,
  4386. + &ssam_node_hid_sam_ucm_ucsi,
  4387. NULL,
  4388. };
  4389. --
  4390. 2.38.0