1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735 |
- From 09fd75cb06607500ed50ecf9a7044d78d065e34c Mon Sep 17 00:00:00 2001
- From: Maximilian Luz <luzmaximilian@gmail.com>
- Date: Fri, 27 May 2022 04:34:36 +0200
- Subject: [PATCH] platform/surface: aggregator: Allow is_ssam_device() to be
- used when CONFIG_SURFACE_AGGREGATOR_BUS is disabled
- In SSAM subsystem drivers that handle both ACPI and SSAM-native client
- devices, we may want to check whether we have a SSAM (native) client
- device. Further, we may want to do this even when instantiation thereof
- cannot happen due to CONFIG_SURFACE_AGGREGATOR_BUS=n. Currently, doing
- so causes an error due to an undefined reference error due to
- ssam_device_type being placed in the bus source unit.
- Therefore, if CONFIG_SURFACE_AGGREGATOR_BUS is not defined, simply let
- is_ssam_device() return false to prevent this error.
- Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
- Link: https://lore.kernel.org/r/20220527023447.2460025-2-luzmaximilian@gmail.com
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
- Signed-off-by: Hans de Goede <hdegoede@redhat.com>
- Patchset: surface-sam
- ---
- include/linux/surface_aggregator/device.h | 11 +++++++++++
- 1 file changed, 11 insertions(+)
- diff --git a/include/linux/surface_aggregator/device.h b/include/linux/surface_aggregator/device.h
- index cc257097eb05..62b38b4487eb 100644
- --- a/include/linux/surface_aggregator/device.h
- +++ b/include/linux/surface_aggregator/device.h
- @@ -177,6 +177,8 @@ struct ssam_device_driver {
- void (*remove)(struct ssam_device *sdev);
- };
-
- +#ifdef CONFIG_SURFACE_AGGREGATOR_BUS
- +
- extern struct bus_type ssam_bus_type;
- extern const struct device_type ssam_device_type;
-
- @@ -193,6 +195,15 @@ static inline bool is_ssam_device(struct device *d)
- return d->type == &ssam_device_type;
- }
-
- +#else /* CONFIG_SURFACE_AGGREGATOR_BUS */
- +
- +static inline bool is_ssam_device(struct device *d)
- +{
- + return false;
- +}
- +
- +#endif /* CONFIG_SURFACE_AGGREGATOR_BUS */
- +
- /**
- * to_ssam_device() - Casts the given device to a SSAM client device.
- * @d: The device to cast.
- --
- 2.37.3
- From 5576bf27906bef2436e2a50359a4a6df63a1c7ac Mon Sep 17 00:00:00 2001
- From: Maximilian Luz <luzmaximilian@gmail.com>
- Date: Fri, 27 May 2022 04:34:37 +0200
- Subject: [PATCH] platform/surface: aggregator: Allow devices to be marked as
- hot-removed
- Some SSAM devices, notably the keyboard cover (keyboard and touchpad) on
- the Surface Pro 8, can be hot-removed. When this occurs, communication
- with the device may fail and time out. This timeout can unnecessarily
- block and slow down device removal and even cause issues when the
- devices are detached and re-attached quickly. Thus, communication should
- generally be avoided once hot-removal is detected.
- While we already remove a device as soon as we detect its (hot-)removal,
- the corresponding device driver may still attempt to communicate with
- the device during teardown. This is especially critical as communication
- failure may also extend to disabling of events, which is typically done
- at that stage.
- Add a flag to allow marking devices as hot-removed. This can then be
- used during client driver teardown to check if any communication
- attempts should be avoided.
- Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
- Link: https://lore.kernel.org/r/20220527023447.2460025-3-luzmaximilian@gmail.com
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
- Signed-off-by: Hans de Goede <hdegoede@redhat.com>
- Patchset: surface-sam
- ---
- include/linux/surface_aggregator/device.h | 48 +++++++++++++++++++++--
- 1 file changed, 45 insertions(+), 3 deletions(-)
- diff --git a/include/linux/surface_aggregator/device.h b/include/linux/surface_aggregator/device.h
- index 62b38b4487eb..6df7c8d4e50e 100644
- --- a/include/linux/surface_aggregator/device.h
- +++ b/include/linux/surface_aggregator/device.h
- @@ -148,17 +148,30 @@ struct ssam_device_uid {
- #define SSAM_SDEV(cat, tid, iid, fun) \
- SSAM_DEVICE(SSAM_DOMAIN_SERIALHUB, SSAM_SSH_TC_##cat, tid, iid, fun)
-
- +/*
- + * enum ssam_device_flags - Flags for SSAM client devices.
- + * @SSAM_DEVICE_HOT_REMOVED_BIT:
- + * The device has been hot-removed. Further communication with it may time
- + * out and should be avoided.
- + */
- +enum ssam_device_flags {
- + SSAM_DEVICE_HOT_REMOVED_BIT = 0,
- +};
- +
- /**
- * struct ssam_device - SSAM client device.
- - * @dev: Driver model representation of the device.
- - * @ctrl: SSAM controller managing this device.
- - * @uid: UID identifying the device.
- + * @dev: Driver model representation of the device.
- + * @ctrl: SSAM controller managing this device.
- + * @uid: UID identifying the device.
- + * @flags: Device state flags, see &enum ssam_device_flags.
- */
- struct ssam_device {
- struct device dev;
- struct ssam_controller *ctrl;
-
- struct ssam_device_uid uid;
- +
- + unsigned long flags;
- };
-
- /**
- @@ -251,6 +264,35 @@ struct ssam_device *ssam_device_alloc(struct ssam_controller *ctrl,
- int ssam_device_add(struct ssam_device *sdev);
- void ssam_device_remove(struct ssam_device *sdev);
-
- +/**
- + * ssam_device_mark_hot_removed() - Mark the given device as hot-removed.
- + * @sdev: The device to mark as hot-removed.
- + *
- + * Mark the device as having been hot-removed. This signals drivers using the
- + * device that communication with the device should be avoided and may lead to
- + * timeouts.
- + */
- +static inline void ssam_device_mark_hot_removed(struct ssam_device *sdev)
- +{
- + dev_dbg(&sdev->dev, "marking device as hot-removed\n");
- + set_bit(SSAM_DEVICE_HOT_REMOVED_BIT, &sdev->flags);
- +}
- +
- +/**
- + * ssam_device_is_hot_removed() - Check if the given device has been
- + * hot-removed.
- + * @sdev: The device to check.
- + *
- + * Checks if the given device has been marked as hot-removed. See
- + * ssam_device_mark_hot_removed() for more details.
- + *
- + * Return: Returns ``true`` if the device has been marked as hot-removed.
- + */
- +static inline bool ssam_device_is_hot_removed(struct ssam_device *sdev)
- +{
- + return test_bit(SSAM_DEVICE_HOT_REMOVED_BIT, &sdev->flags);
- +}
- +
- /**
- * ssam_device_get() - Increment reference count of SSAM client device.
- * @sdev: The device to increment the reference count of.
- --
- 2.37.3
- From 47ff8404defeb7ee9f8d0d793f316cd7b172a317 Mon Sep 17 00:00:00 2001
- From: Maximilian Luz <luzmaximilian@gmail.com>
- Date: Fri, 27 May 2022 04:34:38 +0200
- Subject: [PATCH] platform/surface: aggregator: Allow notifiers to avoid
- communication on unregistering
- When SSAM client devices have been (physically) hot-removed,
- communication attempts with those devices may fail and time out. This
- can even extend to event notifiers, due to which timeouts may occur
- during device removal, slowing down that process.
- Add a parameter to the notifier unregister function that allows skipping
- communication with the EC to prevent this. Furthermore, add wrappers for
- registering and unregistering notifiers belonging to SSAM client devices
- that automatically check if the device has been marked as hot-removed
- and communication should be avoided.
- Note that non-SSAM client devices can generally not be hot-removed, so
- also add a convenience wrapper for those, defaulting to allow
- communication.
- Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
- Link: https://lore.kernel.org/r/20220527023447.2460025-4-luzmaximilian@gmail.com
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
- Signed-off-by: Hans de Goede <hdegoede@redhat.com>
- Patchset: surface-sam
- ---
- .../driver-api/surface_aggregator/client.rst | 6 +-
- .../platform/surface/aggregator/controller.c | 53 ++++++++++-----
- include/linux/surface_aggregator/controller.h | 24 ++++++-
- include/linux/surface_aggregator/device.h | 66 +++++++++++++++++++
- 4 files changed, 128 insertions(+), 21 deletions(-)
- diff --git a/Documentation/driver-api/surface_aggregator/client.rst b/Documentation/driver-api/surface_aggregator/client.rst
- index e519d374c378..27f95abdbe99 100644
- --- a/Documentation/driver-api/surface_aggregator/client.rst
- +++ b/Documentation/driver-api/surface_aggregator/client.rst
- @@ -17,6 +17,8 @@
- .. |SSAM_DEVICE| replace:: :c:func:`SSAM_DEVICE`
- .. |ssam_notifier_register| replace:: :c:func:`ssam_notifier_register`
- .. |ssam_notifier_unregister| replace:: :c:func:`ssam_notifier_unregister`
- +.. |ssam_device_notifier_register| replace:: :c:func:`ssam_device_notifier_register`
- +.. |ssam_device_notifier_unregister| replace:: :c:func:`ssam_device_notifier_unregister`
- .. |ssam_request_sync| replace:: :c:func:`ssam_request_sync`
- .. |ssam_event_mask| replace:: :c:type:`enum ssam_event_mask <ssam_event_mask>`
-
- @@ -312,7 +314,9 @@ Handling Events
- To receive events from the SAM EC, an event notifier must be registered for
- the desired event via |ssam_notifier_register|. The notifier must be
- unregistered via |ssam_notifier_unregister| once it is not required any
- -more.
- +more. For |ssam_device| type clients, the |ssam_device_notifier_register| and
- +|ssam_device_notifier_unregister| wrappers should be preferred as they properly
- +handle hot-removal of client devices.
-
- Event notifiers are registered by providing (at minimum) a callback to call
- in case an event has been received, the registry specifying how the event
- diff --git a/drivers/platform/surface/aggregator/controller.c b/drivers/platform/surface/aggregator/controller.c
- index b8c377b3f932..6de834b52b63 100644
- --- a/drivers/platform/surface/aggregator/controller.c
- +++ b/drivers/platform/surface/aggregator/controller.c
- @@ -2199,16 +2199,26 @@ static int ssam_nf_refcount_enable(struct ssam_controller *ctrl,
- }
-
- /**
- - * ssam_nf_refcount_disable_free() - Disable event for reference count entry if it is
- - * no longer in use and free the corresponding entry.
- + * ssam_nf_refcount_disable_free() - Disable event for reference count entry if
- + * it is no longer in use and free the corresponding entry.
- * @ctrl: The controller to disable the event on.
- * @entry: The reference count entry for the event to be disabled.
- * @flags: The flags used for enabling the event on the EC.
- + * @ec: Flag specifying if the event should actually be disabled on the EC.
- *
- - * If the reference count equals zero, i.e. the event is no longer requested by
- - * any client, the event will be disabled and the corresponding reference count
- - * entry freed. The reference count entry must not be used any more after a
- - * call to this function.
- + * If ``ec`` equals ``true`` and the reference count equals zero (i.e. the
- + * event is no longer requested by any client), the specified event will be
- + * disabled on the EC via the corresponding request.
- + *
- + * If ``ec`` equals ``false``, no request will be sent to the EC and the event
- + * can be considered in a detached state (i.e. no longer used but still
- + * enabled). Disabling an event via this method may be required for
- + * hot-removable devices, where event disable requests may time out after the
- + * device has been physically removed.
- + *
- + * In both cases, if the reference count equals zero, the corresponding
- + * reference count entry will be freed. The reference count entry must not be
- + * used any more after a call to this function.
- *
- * Also checks if the flags used for disabling the event match the flags used
- * for enabling the event and warns if they do not (regardless of reference
- @@ -2223,7 +2233,7 @@ static int ssam_nf_refcount_enable(struct ssam_controller *ctrl,
- * returns the status of the event-enable EC command.
- */
- static int ssam_nf_refcount_disable_free(struct ssam_controller *ctrl,
- - struct ssam_nf_refcount_entry *entry, u8 flags)
- + struct ssam_nf_refcount_entry *entry, u8 flags, bool ec)
- {
- const struct ssam_event_registry reg = entry->key.reg;
- const struct ssam_event_id id = entry->key.id;
- @@ -2232,8 +2242,9 @@ static int ssam_nf_refcount_disable_free(struct ssam_controller *ctrl,
-
- lockdep_assert_held(&nf->lock);
-
- - ssam_dbg(ctrl, "disabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n",
- - reg.target_category, id.target_category, id.instance, entry->refcount);
- + ssam_dbg(ctrl, "%s event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n",
- + ec ? "disabling" : "detaching", reg.target_category, id.target_category,
- + id.instance, entry->refcount);
-
- if (entry->flags != flags) {
- ssam_warn(ctrl,
- @@ -2242,7 +2253,7 @@ static int ssam_nf_refcount_disable_free(struct ssam_controller *ctrl,
- id.instance);
- }
-
- - if (entry->refcount == 0) {
- + if (ec && entry->refcount == 0) {
- status = ssam_ssh_event_disable(ctrl, reg, id, flags);
- kfree(entry);
- }
- @@ -2322,20 +2333,26 @@ int ssam_notifier_register(struct ssam_controller *ctrl, struct ssam_event_notif
- EXPORT_SYMBOL_GPL(ssam_notifier_register);
-
- /**
- - * ssam_notifier_unregister() - Unregister an event notifier.
- - * @ctrl: The controller the notifier has been registered on.
- - * @n: The event notifier to unregister.
- + * __ssam_notifier_unregister() - Unregister an event notifier.
- + * @ctrl: The controller the notifier has been registered on.
- + * @n: The event notifier to unregister.
- + * @disable: Whether to disable the corresponding event on the EC.
- *
- * Unregister an event notifier. Decrement the usage counter of the associated
- * SAM event if the notifier is not marked as an observer. If the usage counter
- - * reaches zero, the event will be disabled.
- + * reaches zero and ``disable`` equals ``true``, the event will be disabled.
- + *
- + * Useful for hot-removable devices, where communication may fail once the
- + * device has been physically removed. In that case, specifying ``disable`` as
- + * ``false`` avoids communication with the EC.
- *
- * Return: Returns zero on success, %-ENOENT if the given notifier block has
- * not been registered on the controller. If the given notifier block was the
- * last one associated with its specific event, returns the status of the
- * event-disable EC-command.
- */
- -int ssam_notifier_unregister(struct ssam_controller *ctrl, struct ssam_event_notifier *n)
- +int __ssam_notifier_unregister(struct ssam_controller *ctrl, struct ssam_event_notifier *n,
- + bool disable)
- {
- u16 rqid = ssh_tc_to_rqid(n->event.id.target_category);
- struct ssam_nf_refcount_entry *entry;
- @@ -2373,7 +2390,7 @@ int ssam_notifier_unregister(struct ssam_controller *ctrl, struct ssam_event_not
- goto remove;
- }
-
- - status = ssam_nf_refcount_disable_free(ctrl, entry, n->event.flags);
- + status = ssam_nf_refcount_disable_free(ctrl, entry, n->event.flags, disable);
- }
-
- remove:
- @@ -2383,7 +2400,7 @@ int ssam_notifier_unregister(struct ssam_controller *ctrl, struct ssam_event_not
-
- return status;
- }
- -EXPORT_SYMBOL_GPL(ssam_notifier_unregister);
- +EXPORT_SYMBOL_GPL(__ssam_notifier_unregister);
-
- /**
- * ssam_controller_event_enable() - Enable the specified event.
- @@ -2477,7 +2494,7 @@ int ssam_controller_event_disable(struct ssam_controller *ctrl,
- return -ENOENT;
- }
-
- - status = ssam_nf_refcount_disable_free(ctrl, entry, flags);
- + status = ssam_nf_refcount_disable_free(ctrl, entry, flags, true);
-
- mutex_unlock(&nf->lock);
- return status;
- diff --git a/include/linux/surface_aggregator/controller.h b/include/linux/surface_aggregator/controller.h
- index 74bfdffaf7b0..50a2b4926c06 100644
- --- a/include/linux/surface_aggregator/controller.h
- +++ b/include/linux/surface_aggregator/controller.h
- @@ -835,8 +835,28 @@ struct ssam_event_notifier {
- int ssam_notifier_register(struct ssam_controller *ctrl,
- struct ssam_event_notifier *n);
-
- -int ssam_notifier_unregister(struct ssam_controller *ctrl,
- - struct ssam_event_notifier *n);
- +int __ssam_notifier_unregister(struct ssam_controller *ctrl,
- + struct ssam_event_notifier *n, bool disable);
- +
- +/**
- + * ssam_notifier_unregister() - Unregister an event notifier.
- + * @ctrl: The controller the notifier has been registered on.
- + * @n: The event notifier to unregister.
- + *
- + * Unregister an event notifier. Decrement the usage counter of the associated
- + * SAM event if the notifier is not marked as an observer. If the usage counter
- + * reaches zero, the event will be disabled.
- + *
- + * Return: Returns zero on success, %-ENOENT if the given notifier block has
- + * not been registered on the controller. If the given notifier block was the
- + * last one associated with its specific event, returns the status of the
- + * event-disable EC-command.
- + */
- +static inline int ssam_notifier_unregister(struct ssam_controller *ctrl,
- + struct ssam_event_notifier *n)
- +{
- + return __ssam_notifier_unregister(ctrl, n, true);
- +}
-
- int ssam_controller_event_enable(struct ssam_controller *ctrl,
- struct ssam_event_registry reg,
- diff --git a/include/linux/surface_aggregator/device.h b/include/linux/surface_aggregator/device.h
- index 6df7c8d4e50e..c418f7f2732d 100644
- --- a/include/linux/surface_aggregator/device.h
- +++ b/include/linux/surface_aggregator/device.h
- @@ -483,4 +483,70 @@ static inline void ssam_remove_clients(struct device *dev) {}
- sdev->uid.instance, ret); \
- }
-
- +
- +/* -- Helpers for client-device notifiers. ---------------------------------- */
- +
- +/**
- + * ssam_device_notifier_register() - Register an event notifier for the
- + * specified client device.
- + * @sdev: The device the notifier should be registered on.
- + * @n: The event notifier to register.
- + *
- + * Register an event notifier. Increment the usage counter of the associated
- + * SAM event if the notifier is not marked as an observer. If the event is not
- + * marked as an observer and is currently not enabled, it will be enabled
- + * during this call. If the notifier is marked as an observer, no attempt will
- + * be made at enabling any event and no reference count will be modified.
- + *
- + * Notifiers marked as observers do not need to be associated with one specific
- + * event, i.e. as long as no event matching is performed, only the event target
- + * category needs to be set.
- + *
- + * Return: Returns zero on success, %-ENOSPC if there have already been
- + * %INT_MAX notifiers for the event ID/type associated with the notifier block
- + * registered, %-ENOMEM if the corresponding event entry could not be
- + * allocated, %-ENODEV if the device is marked as hot-removed. If this is the
- + * first time that a notifier block is registered for the specific associated
- + * event, returns the status of the event-enable EC-command.
- + */
- +static inline int ssam_device_notifier_register(struct ssam_device *sdev,
- + struct ssam_event_notifier *n)
- +{
- + /*
- + * Note that this check does not provide any guarantees whatsoever as
- + * hot-removal could happen at any point and we can't protect against
- + * it. Nevertheless, if we can detect hot-removal, bail early to avoid
- + * communication timeouts.
- + */
- + if (ssam_device_is_hot_removed(sdev))
- + return -ENODEV;
- +
- + return ssam_notifier_register(sdev->ctrl, n);
- +}
- +
- +/**
- + * ssam_device_notifier_unregister() - Unregister an event notifier for the
- + * specified client device.
- + * @sdev: The device the notifier has been registered on.
- + * @n: The event notifier to unregister.
- + *
- + * Unregister an event notifier. Decrement the usage counter of the associated
- + * SAM event if the notifier is not marked as an observer. If the usage counter
- + * reaches zero, the event will be disabled.
- + *
- + * In case the device has been marked as hot-removed, the event will not be
- + * disabled on the EC, as in those cases any attempt at doing so may time out.
- + *
- + * Return: Returns zero on success, %-ENOENT if the given notifier block has
- + * not been registered on the controller. If the given notifier block was the
- + * last one associated with its specific event, returns the status of the
- + * event-disable EC-command.
- + */
- +static inline int ssam_device_notifier_unregister(struct ssam_device *sdev,
- + struct ssam_event_notifier *n)
- +{
- + return __ssam_notifier_unregister(sdev->ctrl, n,
- + !ssam_device_is_hot_removed(sdev));
- +}
- +
- #endif /* _LINUX_SURFACE_AGGREGATOR_DEVICE_H */
- --
- 2.37.3
- From b7aa427fceed2784a444774f0dc50b5a6f9dc99b Mon Sep 17 00:00:00 2001
- From: Maximilian Luz <luzmaximilian@gmail.com>
- Date: Fri, 27 May 2022 04:34:39 +0200
- Subject: [PATCH] platform/surface: aggregator_registry: Use client device
- wrappers for notifier registration
- Use newly introduced client device wrapper functions for notifier
- registration and unregistration.
- Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
- Link: https://lore.kernel.org/r/20220527023447.2460025-5-luzmaximilian@gmail.com
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
- Signed-off-by: Hans de Goede <hdegoede@redhat.com>
- Patchset: surface-sam
- ---
- drivers/platform/surface/surface_aggregator_registry.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
- diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
- index ce2bd88feeaa..9f630e890ff7 100644
- --- a/drivers/platform/surface/surface_aggregator_registry.c
- +++ b/drivers/platform/surface/surface_aggregator_registry.c
- @@ -468,7 +468,7 @@ static int ssam_base_hub_probe(struct ssam_device *sdev)
-
- ssam_device_set_drvdata(sdev, hub);
-
- - status = ssam_notifier_register(sdev->ctrl, &hub->notif);
- + status = ssam_device_notifier_register(sdev, &hub->notif);
- if (status)
- return status;
-
- @@ -480,7 +480,7 @@ static int ssam_base_hub_probe(struct ssam_device *sdev)
- return 0;
-
- err:
- - ssam_notifier_unregister(sdev->ctrl, &hub->notif);
- + ssam_device_notifier_unregister(sdev, &hub->notif);
- cancel_delayed_work_sync(&hub->update_work);
- ssam_remove_clients(&sdev->dev);
- return status;
- @@ -492,7 +492,7 @@ static void ssam_base_hub_remove(struct ssam_device *sdev)
-
- sysfs_remove_group(&sdev->dev.kobj, &ssam_base_hub_group);
-
- - ssam_notifier_unregister(sdev->ctrl, &hub->notif);
- + ssam_device_notifier_unregister(sdev, &hub->notif);
- cancel_delayed_work_sync(&hub->update_work);
- ssam_remove_clients(&sdev->dev);
- }
- --
- 2.37.3
- From 1263a498c0a0127b23802200a68f574832dd1b5f Mon Sep 17 00:00:00 2001
- From: Maximilian Luz <luzmaximilian@gmail.com>
- Date: Fri, 27 May 2022 04:34:40 +0200
- Subject: [PATCH] power/supply: surface_charger: Use client device wrappers for
- notifier registration
- Use newly introduced client device wrapper functions for notifier
- registration and unregistration.
- Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
- Acked-by: Sebastian Reichel <sebastian.reichel@collabora.com>
- Link: https://lore.kernel.org/r/20220527023447.2460025-6-luzmaximilian@gmail.com
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
- Signed-off-by: Hans de Goede <hdegoede@redhat.com>
- Patchset: surface-sam
- ---
- drivers/power/supply/surface_charger.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
- diff --git a/drivers/power/supply/surface_charger.c b/drivers/power/supply/surface_charger.c
- index a060c36c7766..59182d55742d 100644
- --- a/drivers/power/supply/surface_charger.c
- +++ b/drivers/power/supply/surface_charger.c
- @@ -216,7 +216,7 @@ static int spwr_ac_register(struct spwr_ac_device *ac)
- if (IS_ERR(ac->psy))
- return PTR_ERR(ac->psy);
-
- - return ssam_notifier_register(ac->sdev->ctrl, &ac->notif);
- + return ssam_device_notifier_register(ac->sdev, &ac->notif);
- }
-
-
- @@ -251,7 +251,7 @@ static void surface_ac_remove(struct ssam_device *sdev)
- {
- struct spwr_ac_device *ac = ssam_device_get_drvdata(sdev);
-
- - ssam_notifier_unregister(sdev->ctrl, &ac->notif);
- + ssam_device_notifier_unregister(sdev, &ac->notif);
- }
-
- static const struct spwr_psy_properties spwr_psy_props_adp1 = {
- --
- 2.37.3
- From 89200c93bb064801fd7eb253f857c67294916aab Mon Sep 17 00:00:00 2001
- From: Maximilian Luz <luzmaximilian@gmail.com>
- Date: Fri, 27 May 2022 04:34:41 +0200
- Subject: [PATCH] power/supply: surface_battery: Use client device wrappers for
- notifier registration
- Use newly introduced client device wrapper functions for notifier
- registration and unregistration.
- Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
- Acked-by: Sebastian Reichel <sebastian.reichel@collabora.com>
- Link: https://lore.kernel.org/r/20220527023447.2460025-7-luzmaximilian@gmail.com
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
- Signed-off-by: Hans de Goede <hdegoede@redhat.com>
- Patchset: surface-sam
- ---
- drivers/power/supply/surface_battery.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
- diff --git a/drivers/power/supply/surface_battery.c b/drivers/power/supply/surface_battery.c
- index 5ec2e6bb2465..540707882bb0 100644
- --- a/drivers/power/supply/surface_battery.c
- +++ b/drivers/power/supply/surface_battery.c
- @@ -802,7 +802,7 @@ static int spwr_battery_register(struct spwr_battery_device *bat)
- if (IS_ERR(bat->psy))
- return PTR_ERR(bat->psy);
-
- - return ssam_notifier_register(bat->sdev->ctrl, &bat->notif);
- + return ssam_device_notifier_register(bat->sdev, &bat->notif);
- }
-
-
- @@ -837,7 +837,7 @@ static void surface_battery_remove(struct ssam_device *sdev)
- {
- struct spwr_battery_device *bat = ssam_device_get_drvdata(sdev);
-
- - ssam_notifier_unregister(sdev->ctrl, &bat->notif);
- + ssam_device_notifier_unregister(sdev, &bat->notif);
- cancel_delayed_work_sync(&bat->update_work);
- }
-
- --
- 2.37.3
- From 6f87bc8c02b89e0763ab5959424d0a7b27e0541a Mon Sep 17 00:00:00 2001
- From: Maximilian Luz <luzmaximilian@gmail.com>
- Date: Fri, 27 May 2022 04:34:42 +0200
- Subject: [PATCH] HID: surface-hid: Add support for hot-removal
- Add support for hot-removal of SSAM HID client devices.
- Once a device has been hot-removed, further communication with it should
- be avoided as it may fail and time out. While the device will be removed
- as soon as we detect hot-removal, communication may still occur during
- teardown, especially when unregistering notifiers.
- While hot-removal is a surprise event that can happen at any time, try
- to avoid communication as much as possible once it has been detected to
- prevent timeouts that can slow down device removal and cause issues,
- e.g. when quickly re-attaching the device.
- Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
- Link: https://lore.kernel.org/r/20220527023447.2460025-8-luzmaximilian@gmail.com
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
- Signed-off-by: Hans de Goede <hdegoede@redhat.com>
- Patchset: surface-sam
- ---
- drivers/hid/surface-hid/surface_hid_core.c | 38 +++++++++++++++++++++-
- 1 file changed, 37 insertions(+), 1 deletion(-)
- diff --git a/drivers/hid/surface-hid/surface_hid_core.c b/drivers/hid/surface-hid/surface_hid_core.c
- index e46330b2e561..87637f813de2 100644
- --- a/drivers/hid/surface-hid/surface_hid_core.c
- +++ b/drivers/hid/surface-hid/surface_hid_core.c
- @@ -19,12 +19,30 @@
- #include "surface_hid_core.h"
-
-
- +/* -- Utility functions. ---------------------------------------------------- */
- +
- +static bool surface_hid_is_hot_removed(struct surface_hid_device *shid)
- +{
- + /*
- + * Non-ssam client devices, i.e. platform client devices, cannot be
- + * hot-removed.
- + */
- + if (!is_ssam_device(shid->dev))
- + return false;
- +
- + return ssam_device_is_hot_removed(to_ssam_device(shid->dev));
- +}
- +
- +
- /* -- Device descriptor access. --------------------------------------------- */
-
- static int surface_hid_load_hid_descriptor(struct surface_hid_device *shid)
- {
- int status;
-
- + if (surface_hid_is_hot_removed(shid))
- + return -ENODEV;
- +
- status = shid->ops.get_descriptor(shid, SURFACE_HID_DESC_HID,
- (u8 *)&shid->hid_desc, sizeof(shid->hid_desc));
- if (status)
- @@ -61,6 +79,9 @@ static int surface_hid_load_device_attributes(struct surface_hid_device *shid)
- {
- int status;
-
- + if (surface_hid_is_hot_removed(shid))
- + return -ENODEV;
- +
- status = shid->ops.get_descriptor(shid, SURFACE_HID_DESC_ATTRS,
- (u8 *)&shid->attrs, sizeof(shid->attrs));
- if (status)
- @@ -88,9 +109,18 @@ static int surface_hid_start(struct hid_device *hid)
- static void surface_hid_stop(struct hid_device *hid)
- {
- struct surface_hid_device *shid = hid->driver_data;
- + bool hot_removed;
- +
- + /*
- + * Communication may fail for devices that have been hot-removed. This
- + * also includes unregistration of HID events, so we need to check this
- + * here. Only if the device has not been marked as hot-removed, we can
- + * safely disable events.
- + */
- + hot_removed = surface_hid_is_hot_removed(shid);
-
- /* Note: This call will log errors for us, so ignore them here. */
- - ssam_notifier_unregister(shid->ctrl, &shid->notif);
- + __ssam_notifier_unregister(shid->ctrl, &shid->notif, !hot_removed);
- }
-
- static int surface_hid_open(struct hid_device *hid)
- @@ -109,6 +139,9 @@ static int surface_hid_parse(struct hid_device *hid)
- u8 *buf;
- int status;
-
- + if (surface_hid_is_hot_removed(shid))
- + return -ENODEV;
- +
- buf = kzalloc(len, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
- @@ -126,6 +159,9 @@ static int surface_hid_raw_request(struct hid_device *hid, unsigned char reportn
- {
- struct surface_hid_device *shid = hid->driver_data;
-
- + if (surface_hid_is_hot_removed(shid))
- + return -ENODEV;
- +
- if (rtype == HID_OUTPUT_REPORT && reqtype == HID_REQ_SET_REPORT)
- return shid->ops.output_report(shid, reportnum, buf, len);
-
- --
- 2.37.3
- From 5bdfd97d1fe05edb5c9a051978640e2c72c08b6d Mon Sep 17 00:00:00 2001
- From: Maximilian Luz <luzmaximilian@gmail.com>
- Date: Fri, 27 May 2022 04:34:43 +0200
- Subject: [PATCH] platform/surface: aggregator: Add comment for KIP subsystem
- category
- The KIP subsystem (full name unknown, abbreviation has been obtained
- through reverse engineering) handles detachable peripherals such as the
- keyboard cover on the Surface Pro X and Surface Pro 8.
- It is currently not entirely clear what this subsystem entails, but at
- the very least it provides event notifications for when the keyboard
- cover on the Surface Pro X and Surface Pro 8 have been detached or
- re-attached, as well as the state that the keyboard cover is currently
- in (e.g. folded-back, folded laptop-like, closed, etc.).
- Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
- Link: https://lore.kernel.org/r/20220527023447.2460025-9-luzmaximilian@gmail.com
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
- Signed-off-by: Hans de Goede <hdegoede@redhat.com>
- Patchset: surface-sam
- ---
- include/linux/surface_aggregator/serial_hub.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
- diff --git a/include/linux/surface_aggregator/serial_hub.h b/include/linux/surface_aggregator/serial_hub.h
- index c3de43edcffa..26b95ec12733 100644
- --- a/include/linux/surface_aggregator/serial_hub.h
- +++ b/include/linux/surface_aggregator/serial_hub.h
- @@ -306,7 +306,7 @@ enum ssam_ssh_tc {
- SSAM_SSH_TC_LPC = 0x0b,
- SSAM_SSH_TC_TCL = 0x0c,
- SSAM_SSH_TC_SFL = 0x0d,
- - SSAM_SSH_TC_KIP = 0x0e,
- + SSAM_SSH_TC_KIP = 0x0e, /* Manages detachable peripherals (Pro X/8 keyboard cover) */
- SSAM_SSH_TC_EXT = 0x0f,
- SSAM_SSH_TC_BLD = 0x10,
- SSAM_SSH_TC_BAS = 0x11, /* Detachment system (Surface Book 2/3). */
- --
- 2.37.3
- From 6f5b3ec6a7e2c0282553ec25f786b32fde01898a Mon Sep 17 00:00:00 2001
- From: Maximilian Luz <luzmaximilian@gmail.com>
- Date: Fri, 27 May 2022 04:34:44 +0200
- Subject: [PATCH] platform/surface: aggregator_registry: Generify subsystem hub
- functionality
- The Surface System Aggregator Module (SSAM) has multiple subsystems that
- can manage detachable devices. At the moment, we only support the "base"
- (BAS/0x11) subsystem, which is used on the Surface Book 3 to manage
- devices (including keyboard, touchpad, and secondary battery) connected
- to the base of the device.
- The Surface Pro 8 has a new type-cover with keyboard and touchpad, which
- is managed via the KIP/0x0e subsystem. The general procedure is the
- same, but with slightly different events and setup. To make
- implementation of the KIP hub easier and prevent duplication, generify
- the parts of the base hub that we can use for the KIP hub (or any
- potential future subsystem hubs).
- This also switches over to use the newly introduced "hot-remove"
- functionality, which should prevent communication issues when devices
- have been detached.
- Lastly, also drop the undocumented and unused sysfs "state" attribute of
- the base hub. It has at best been useful for debugging.
- Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
- Link: https://lore.kernel.org/r/20220527023447.2460025-10-luzmaximilian@gmail.com
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
- Signed-off-by: Hans de Goede <hdegoede@redhat.com>
- Patchset: surface-sam
- ---
- .../surface/surface_aggregator_registry.c | 269 ++++++++++--------
- 1 file changed, 153 insertions(+), 116 deletions(-)
- diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
- index 9f630e890ff7..09cbeee2428b 100644
- --- a/drivers/platform/surface/surface_aggregator_registry.c
- +++ b/drivers/platform/surface/surface_aggregator_registry.c
- @@ -308,30 +308,159 @@ static int ssam_hub_register_clients(struct device *parent, struct ssam_controll
- }
-
-
- -/* -- SSAM base-hub driver. ------------------------------------------------- */
- +/* -- SSAM generic subsystem hub driver framework. -------------------------- */
-
- -/*
- - * Some devices (especially battery) may need a bit of time to be fully usable
- - * after being (re-)connected. This delay has been determined via
- - * experimentation.
- - */
- -#define SSAM_BASE_UPDATE_CONNECT_DELAY msecs_to_jiffies(2500)
- +enum ssam_hub_state {
- + SSAM_HUB_UNINITIALIZED, /* Only set during initialization. */
- + SSAM_HUB_CONNECTED,
- + SSAM_HUB_DISCONNECTED,
- +};
-
- -enum ssam_base_hub_state {
- - SSAM_BASE_HUB_UNINITIALIZED,
- - SSAM_BASE_HUB_CONNECTED,
- - SSAM_BASE_HUB_DISCONNECTED,
- +enum ssam_hub_flags {
- + SSAM_HUB_HOT_REMOVED,
- };
-
- -struct ssam_base_hub {
- +struct ssam_hub {
- struct ssam_device *sdev;
-
- - enum ssam_base_hub_state state;
- + enum ssam_hub_state state;
- + unsigned long flags;
- +
- struct delayed_work update_work;
- + unsigned long connect_delay;
-
- struct ssam_event_notifier notif;
- +
- + int (*get_state)(struct ssam_hub *hub, enum ssam_hub_state *state);
- };
-
- +static void ssam_hub_update_workfn(struct work_struct *work)
- +{
- + struct ssam_hub *hub = container_of(work, struct ssam_hub, update_work.work);
- + struct fwnode_handle *node = dev_fwnode(&hub->sdev->dev);
- + enum ssam_hub_state state;
- + int status = 0;
- +
- + status = hub->get_state(hub, &state);
- + if (status)
- + return;
- +
- + /*
- + * There is a small possibility that hub devices were hot-removed and
- + * re-added before we were able to remove them here. In that case, both
- + * the state returned by get_state() and the state of the hub will
- + * equal SSAM_HUB_CONNECTED and we would bail early below, which would
- + * leave child devices without proper (re-)initialization and the
- + * hot-remove flag set.
- + *
- + * Therefore, we check whether devices have been hot-removed via an
- + * additional flag on the hub and, in this case, override the returned
- + * hub state. In case of a missed disconnect (i.e. get_state returned
- + * "connected"), we further need to re-schedule this work (with the
- + * appropriate delay) as the actual connect work submission might have
- + * been merged with this one.
- + *
- + * This then leads to one of two cases: Either we submit an unnecessary
- + * work item (which will get ignored via either the queue or the state
- + * checks) or, in the unlikely case that the work is actually required,
- + * double the normal connect delay.
- + */
- + if (test_and_clear_bit(SSAM_HUB_HOT_REMOVED, &hub->flags)) {
- + if (state == SSAM_HUB_CONNECTED)
- + schedule_delayed_work(&hub->update_work, hub->connect_delay);
- +
- + state = SSAM_HUB_DISCONNECTED;
- + }
- +
- + if (hub->state == state)
- + return;
- + hub->state = state;
- +
- + if (hub->state == SSAM_HUB_CONNECTED)
- + status = ssam_hub_register_clients(&hub->sdev->dev, hub->sdev->ctrl, node);
- + else
- + ssam_remove_clients(&hub->sdev->dev);
- +
- + if (status)
- + dev_err(&hub->sdev->dev, "failed to update hub child devices: %d\n", status);
- +}
- +
- +static int ssam_hub_mark_hot_removed(struct device *dev, void *_data)
- +{
- + struct ssam_device *sdev = to_ssam_device(dev);
- +
- + if (is_ssam_device(dev))
- + ssam_device_mark_hot_removed(sdev);
- +
- + return 0;
- +}
- +
- +static void ssam_hub_update(struct ssam_hub *hub, bool connected)
- +{
- + unsigned long delay;
- +
- + /* Mark devices as hot-removed before we remove any. */
- + if (!connected) {
- + set_bit(SSAM_HUB_HOT_REMOVED, &hub->flags);
- + device_for_each_child_reverse(&hub->sdev->dev, NULL, ssam_hub_mark_hot_removed);
- + }
- +
- + /*
- + * Delay update when the base/keyboard cover is being connected to give
- + * devices/EC some time to set up.
- + */
- + delay = connected ? hub->connect_delay : 0;
- +
- + schedule_delayed_work(&hub->update_work, delay);
- +}
- +
- +static int __maybe_unused ssam_hub_resume(struct device *dev)
- +{
- + struct ssam_hub *hub = dev_get_drvdata(dev);
- +
- + schedule_delayed_work(&hub->update_work, 0);
- + return 0;
- +}
- +static SIMPLE_DEV_PM_OPS(ssam_hub_pm_ops, NULL, ssam_hub_resume);
- +
- +static int ssam_hub_setup(struct ssam_device *sdev, struct ssam_hub *hub)
- +{
- + int status;
- +
- + hub->sdev = sdev;
- + hub->state = SSAM_HUB_UNINITIALIZED;
- +
- + INIT_DELAYED_WORK(&hub->update_work, ssam_hub_update_workfn);
- +
- + ssam_device_set_drvdata(sdev, hub);
- +
- + status = ssam_device_notifier_register(sdev, &hub->notif);
- + if (status)
- + return status;
- +
- + schedule_delayed_work(&hub->update_work, 0);
- + return 0;
- +}
- +
- +static void ssam_hub_remove(struct ssam_device *sdev)
- +{
- + struct ssam_hub *hub = ssam_device_get_drvdata(sdev);
- +
- + ssam_device_notifier_unregister(sdev, &hub->notif);
- + cancel_delayed_work_sync(&hub->update_work);
- + ssam_remove_clients(&sdev->dev);
- +}
- +
- +
- +/* -- SSAM base-hub driver. ------------------------------------------------- */
- +
- +/*
- + * Some devices (especially battery) may need a bit of time to be fully usable
- + * after being (re-)connected. This delay has been determined via
- + * experimentation.
- + */
- +#define SSAM_BASE_UPDATE_CONNECT_DELAY msecs_to_jiffies(2500)
- +
- SSAM_DEFINE_SYNC_REQUEST_R(ssam_bas_query_opmode, u8, {
- .target_category = SSAM_SSH_TC_BAS,
- .target_id = 0x01,
- @@ -342,7 +471,7 @@ SSAM_DEFINE_SYNC_REQUEST_R(ssam_bas_query_opmode, u8, {
- #define SSAM_BAS_OPMODE_TABLET 0x00
- #define SSAM_EVENT_BAS_CID_CONNECTION 0x0c
-
- -static int ssam_base_hub_query_state(struct ssam_base_hub *hub, enum ssam_base_hub_state *state)
- +static int ssam_base_hub_query_state(struct ssam_hub *hub, enum ssam_hub_state *state)
- {
- u8 opmode;
- int status;
- @@ -354,62 +483,16 @@ static int ssam_base_hub_query_state(struct ssam_base_hub *hub, enum ssam_base_h
- }
-
- if (opmode != SSAM_BAS_OPMODE_TABLET)
- - *state = SSAM_BASE_HUB_CONNECTED;
- + *state = SSAM_HUB_CONNECTED;
- else
- - *state = SSAM_BASE_HUB_DISCONNECTED;
- + *state = SSAM_HUB_DISCONNECTED;
-
- return 0;
- }
-
- -static ssize_t ssam_base_hub_state_show(struct device *dev, struct device_attribute *attr,
- - char *buf)
- -{
- - struct ssam_base_hub *hub = dev_get_drvdata(dev);
- - bool connected = hub->state == SSAM_BASE_HUB_CONNECTED;
- -
- - return sysfs_emit(buf, "%d\n", connected);
- -}
- -
- -static struct device_attribute ssam_base_hub_attr_state =
- - __ATTR(state, 0444, ssam_base_hub_state_show, NULL);
- -
- -static struct attribute *ssam_base_hub_attrs[] = {
- - &ssam_base_hub_attr_state.attr,
- - NULL,
- -};
- -
- -static const struct attribute_group ssam_base_hub_group = {
- - .attrs = ssam_base_hub_attrs,
- -};
- -
- -static void ssam_base_hub_update_workfn(struct work_struct *work)
- -{
- - struct ssam_base_hub *hub = container_of(work, struct ssam_base_hub, update_work.work);
- - struct fwnode_handle *node = dev_fwnode(&hub->sdev->dev);
- - enum ssam_base_hub_state state;
- - int status = 0;
- -
- - status = ssam_base_hub_query_state(hub, &state);
- - if (status)
- - return;
- -
- - if (hub->state == state)
- - return;
- - hub->state = state;
- -
- - if (hub->state == SSAM_BASE_HUB_CONNECTED)
- - status = ssam_hub_register_clients(&hub->sdev->dev, hub->sdev->ctrl, node);
- - else
- - ssam_remove_clients(&hub->sdev->dev);
- -
- - if (status)
- - dev_err(&hub->sdev->dev, "failed to update base-hub devices: %d\n", status);
- -}
- -
- static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
- {
- - struct ssam_base_hub *hub = container_of(nf, struct ssam_base_hub, notif);
- - unsigned long delay;
- + struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
-
- if (event->command_id != SSAM_EVENT_BAS_CID_CONNECTION)
- return 0;
- @@ -419,13 +502,7 @@ static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam
- return 0;
- }
-
- - /*
- - * Delay update when the base is being connected to give devices/EC
- - * some time to set up.
- - */
- - delay = event->data[0] ? SSAM_BASE_UPDATE_CONNECT_DELAY : 0;
- -
- - schedule_delayed_work(&hub->update_work, delay);
- + ssam_hub_update(hub, event->data[0]);
-
- /*
- * Do not return SSAM_NOTIF_HANDLED: The event should be picked up and
- @@ -435,27 +512,14 @@ static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam
- return 0;
- }
-
- -static int __maybe_unused ssam_base_hub_resume(struct device *dev)
- -{
- - struct ssam_base_hub *hub = dev_get_drvdata(dev);
- -
- - schedule_delayed_work(&hub->update_work, 0);
- - return 0;
- -}
- -static SIMPLE_DEV_PM_OPS(ssam_base_hub_pm_ops, NULL, ssam_base_hub_resume);
- -
- static int ssam_base_hub_probe(struct ssam_device *sdev)
- {
- - struct ssam_base_hub *hub;
- - int status;
- + struct ssam_hub *hub;
-
- hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL);
- if (!hub)
- return -ENOMEM;
-
- - hub->sdev = sdev;
- - hub->state = SSAM_BASE_HUB_UNINITIALIZED;
- -
- hub->notif.base.priority = INT_MAX; /* This notifier should run first. */
- hub->notif.base.fn = ssam_base_hub_notif;
- hub->notif.event.reg = SSAM_EVENT_REGISTRY_SAM;
- @@ -464,37 +528,10 @@ static int ssam_base_hub_probe(struct ssam_device *sdev)
- hub->notif.event.mask = SSAM_EVENT_MASK_NONE;
- hub->notif.event.flags = SSAM_EVENT_SEQUENCED;
-
- - INIT_DELAYED_WORK(&hub->update_work, ssam_base_hub_update_workfn);
- -
- - ssam_device_set_drvdata(sdev, hub);
- -
- - status = ssam_device_notifier_register(sdev, &hub->notif);
- - if (status)
- - return status;
- -
- - status = sysfs_create_group(&sdev->dev.kobj, &ssam_base_hub_group);
- - if (status)
- - goto err;
- -
- - schedule_delayed_work(&hub->update_work, 0);
- - return 0;
- + hub->connect_delay = SSAM_BASE_UPDATE_CONNECT_DELAY;
- + hub->get_state = ssam_base_hub_query_state;
-
- -err:
- - ssam_device_notifier_unregister(sdev, &hub->notif);
- - cancel_delayed_work_sync(&hub->update_work);
- - ssam_remove_clients(&sdev->dev);
- - return status;
- -}
- -
- -static void ssam_base_hub_remove(struct ssam_device *sdev)
- -{
- - struct ssam_base_hub *hub = ssam_device_get_drvdata(sdev);
- -
- - sysfs_remove_group(&sdev->dev.kobj, &ssam_base_hub_group);
- -
- - ssam_device_notifier_unregister(sdev, &hub->notif);
- - cancel_delayed_work_sync(&hub->update_work);
- - ssam_remove_clients(&sdev->dev);
- + return ssam_hub_setup(sdev, hub);
- }
-
- static const struct ssam_device_id ssam_base_hub_match[] = {
- @@ -504,12 +541,12 @@ static const struct ssam_device_id ssam_base_hub_match[] = {
-
- static struct ssam_device_driver ssam_base_hub_driver = {
- .probe = ssam_base_hub_probe,
- - .remove = ssam_base_hub_remove,
- + .remove = ssam_hub_remove,
- .match_table = ssam_base_hub_match,
- .driver = {
- .name = "surface_aggregator_base_hub",
- .probe_type = PROBE_PREFER_ASYNCHRONOUS,
- - .pm = &ssam_base_hub_pm_ops,
- + .pm = &ssam_hub_pm_ops,
- },
- };
-
- --
- 2.37.3
- From 4e269b4e4f4c7273c32c5672740297890d537103 Mon Sep 17 00:00:00 2001
- From: Maximilian Luz <luzmaximilian@gmail.com>
- Date: Fri, 27 May 2022 04:34:45 +0200
- Subject: [PATCH] platform/surface: aggregator_registry: Change device ID for
- base hub
- Use the target category of the (base) hub as instance id in the
- (virtual) hub device UID. This makes association of the hub with the
- respective subsystem easier.
- Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
- Link: https://lore.kernel.org/r/20220527023447.2460025-11-luzmaximilian@gmail.com
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
- Signed-off-by: Hans de Goede <hdegoede@redhat.com>
- Patchset: surface-sam
- ---
- drivers/platform/surface/surface_aggregator_registry.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
- diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
- index 09cbeee2428b..b11ce87c7184 100644
- --- a/drivers/platform/surface/surface_aggregator_registry.c
- +++ b/drivers/platform/surface/surface_aggregator_registry.c
- @@ -43,7 +43,7 @@ static const struct software_node ssam_node_root = {
-
- /* Base device hub (devices attached to Surface Book 3 base). */
- static const struct software_node ssam_node_hub_base = {
- - .name = "ssam:00:00:02:00:00",
- + .name = "ssam:00:00:02:11:00",
- .parent = &ssam_node_root,
- };
-
- @@ -535,7 +535,7 @@ static int ssam_base_hub_probe(struct ssam_device *sdev)
- }
-
- static const struct ssam_device_id ssam_base_hub_match[] = {
- - { SSAM_VDEV(HUB, 0x02, SSAM_ANY_IID, 0x00) },
- + { SSAM_VDEV(HUB, 0x02, SSAM_SSH_TC_BAS, 0x00) },
- { },
- };
-
- --
- 2.37.3
- From ec7be5a60a78b0c39c6ea34ff97b14fcb3eca94e Mon Sep 17 00:00:00 2001
- From: Maximilian Luz <luzmaximilian@gmail.com>
- Date: Fri, 27 May 2022 04:34:46 +0200
- Subject: [PATCH] platform/surface: aggregator_registry: Add KIP device hub
- Add a Surface System Aggregator Module (SSAM) client device hub for
- hot-removable devices managed via the KIP subsystem.
- The KIP subsystem (full name unknown, abbreviation has been obtained
- through reverse engineering) is a subsystem that manages hot-removable
- SSAM client devices. Specifically, it manages HID input devices
- contained in the detachable keyboard cover of the Surface Pro 8 and
- Surface Pro X.
- The KIP subsystem handles a single group of devices (e.g. all devices
- contained in the keyboard cover) and cannot handle devices individually.
- Thus we model it as a client device hub, which (hot-)removes all devices
- contained under it once removal of the hub (e.g. keyboard cover) has
- been detected and (re-)adds all devices once the physical hub device has
- been (re-)attached. To do this, use the previously generified SSAM
- subsystem hub framework.
- Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
- Link: https://lore.kernel.org/r/20220527023447.2460025-12-luzmaximilian@gmail.com
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
- Signed-off-by: Hans de Goede <hdegoede@redhat.com>
- Patchset: surface-sam
- ---
- .../surface/surface_aggregator_registry.c | 103 +++++++++++++++++-
- 1 file changed, 101 insertions(+), 2 deletions(-)
- diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
- index b11ce87c7184..f15cef60630f 100644
- --- a/drivers/platform/surface/surface_aggregator_registry.c
- +++ b/drivers/platform/surface/surface_aggregator_registry.c
- @@ -551,6 +551,93 @@ static struct ssam_device_driver ssam_base_hub_driver = {
- };
-
-
- +/* -- SSAM KIP-subsystem hub driver. ---------------------------------------- */
- +
- +/*
- + * Some devices may need a bit of time to be fully usable after being
- + * (re-)connected. This delay has been determined via experimentation.
- + */
- +#define SSAM_KIP_UPDATE_CONNECT_DELAY msecs_to_jiffies(250)
- +
- +#define SSAM_EVENT_KIP_CID_CONNECTION 0x2c
- +
- +SSAM_DEFINE_SYNC_REQUEST_R(__ssam_kip_get_connection_state, u8, {
- + .target_category = SSAM_SSH_TC_KIP,
- + .target_id = 0x01,
- + .command_id = 0x2c,
- + .instance_id = 0x00,
- +});
- +
- +static int ssam_kip_get_connection_state(struct ssam_hub *hub, enum ssam_hub_state *state)
- +{
- + int status;
- + u8 connected;
- +
- + status = ssam_retry(__ssam_kip_get_connection_state, hub->sdev->ctrl, &connected);
- + if (status < 0) {
- + dev_err(&hub->sdev->dev, "failed to query KIP connection state: %d\n", status);
- + return status;
- + }
- +
- + *state = connected ? SSAM_HUB_CONNECTED : SSAM_HUB_DISCONNECTED;
- + return 0;
- +}
- +
- +static u32 ssam_kip_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
- +{
- + struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
- +
- + if (event->command_id != SSAM_EVENT_KIP_CID_CONNECTION)
- + return 0; /* Return "unhandled". */
- +
- + if (event->length < 1) {
- + dev_err(&hub->sdev->dev, "unexpected payload size: %u\n", event->length);
- + return 0;
- + }
- +
- + ssam_hub_update(hub, event->data[0]);
- + return SSAM_NOTIF_HANDLED;
- +}
- +
- +static int ssam_kip_hub_probe(struct ssam_device *sdev)
- +{
- + struct ssam_hub *hub;
- +
- + hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL);
- + if (!hub)
- + return -ENOMEM;
- +
- + hub->notif.base.priority = INT_MAX; /* This notifier should run first. */
- + hub->notif.base.fn = ssam_kip_hub_notif;
- + hub->notif.event.reg = SSAM_EVENT_REGISTRY_SAM;
- + hub->notif.event.id.target_category = SSAM_SSH_TC_KIP,
- + hub->notif.event.id.instance = 0,
- + hub->notif.event.mask = SSAM_EVENT_MASK_TARGET;
- + hub->notif.event.flags = SSAM_EVENT_SEQUENCED;
- +
- + hub->connect_delay = SSAM_KIP_UPDATE_CONNECT_DELAY;
- + hub->get_state = ssam_kip_get_connection_state;
- +
- + return ssam_hub_setup(sdev, hub);
- +}
- +
- +static const struct ssam_device_id ssam_kip_hub_match[] = {
- + { SSAM_VDEV(HUB, 0x01, SSAM_SSH_TC_KIP, 0x00) },
- + { },
- +};
- +
- +static struct ssam_device_driver ssam_kip_hub_driver = {
- + .probe = ssam_kip_hub_probe,
- + .remove = ssam_hub_remove,
- + .match_table = ssam_kip_hub_match,
- + .driver = {
- + .name = "surface_kip_hub",
- + .probe_type = PROBE_PREFER_ASYNCHRONOUS,
- + .pm = &ssam_hub_pm_ops,
- + },
- +};
- +
- +
- /* -- SSAM platform/meta-hub driver. ---------------------------------------- */
-
- static const struct acpi_device_id ssam_platform_hub_match[] = {
- @@ -673,18 +760,30 @@ static int __init ssam_device_hub_init(void)
-
- status = platform_driver_register(&ssam_platform_hub_driver);
- if (status)
- - return status;
- + goto err_platform;
-
- status = ssam_device_driver_register(&ssam_base_hub_driver);
- if (status)
- - platform_driver_unregister(&ssam_platform_hub_driver);
- + goto err_base;
- +
- + status = ssam_device_driver_register(&ssam_kip_hub_driver);
- + if (status)
- + goto err_kip;
-
- + return 0;
- +
- +err_kip:
- + ssam_device_driver_unregister(&ssam_base_hub_driver);
- +err_base:
- + platform_driver_unregister(&ssam_platform_hub_driver);
- +err_platform:
- return status;
- }
- module_init(ssam_device_hub_init);
-
- static void __exit ssam_device_hub_exit(void)
- {
- + ssam_device_driver_unregister(&ssam_kip_hub_driver);
- ssam_device_driver_unregister(&ssam_base_hub_driver);
- platform_driver_unregister(&ssam_platform_hub_driver);
- }
- --
- 2.37.3
- From 7eaf55002e05ef7da458fdd815d4805a8605da7a Mon Sep 17 00:00:00 2001
- From: Maximilian Luz <luzmaximilian@gmail.com>
- Date: Fri, 27 May 2022 04:34:47 +0200
- Subject: [PATCH] platform/surface: aggregator_registry: Add support for
- keyboard cover on Surface Pro 8
- Add support for the detachable keyboard cover on the Surface Pro 8.
- The keyboard cover on the Surface Pro 8 is, unlike the keyboard covers
- of earlier Surface Pro generations, handled via the Surface System
- Aggregator Module (SSAM). The keyboard and touchpad (as well as other
- HID input devices) of this cover are standard SSAM HID client devices
- (just like keyboard and touchpad on e.g. the Surface Laptop 3 and 4),
- however, some care needs to be taken as they can be physically detached
- (similarly to the Surface Book 3). Specifically, the respective SSAM
- client devices need to be removed when the keyboard cover has been
- detached and (re-)initialized when the keyboard cover has been
- (re-)attached.
- On the Surface Pro 8, detachment of the keyboard cover (and by extension
- its devices) is managed via the KIP subsystem. Therefore, said devices
- need to be registered under the KIP device hub, which in turn will
- remove and re-create/re-initialize those devices as needed.
- Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
- Link: https://lore.kernel.org/r/20220527023447.2460025-13-luzmaximilian@gmail.com
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
- Signed-off-by: Hans de Goede <hdegoede@redhat.com>
- Patchset: surface-sam
- ---
- .../surface/surface_aggregator_registry.c | 37 ++++++++++++++++++-
- 1 file changed, 36 insertions(+), 1 deletion(-)
- diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
- index f15cef60630f..bf3303f1aa71 100644
- --- a/drivers/platform/surface/surface_aggregator_registry.c
- +++ b/drivers/platform/surface/surface_aggregator_registry.c
- @@ -41,6 +41,12 @@ static const struct software_node ssam_node_root = {
- .name = "ssam_platform_hub",
- };
-
- +/* KIP device hub (connects keyboard cover devices on Surface Pro 8). */
- +static const struct software_node ssam_node_hub_kip = {
- + .name = "ssam:00:00:01:0e:00",
- + .parent = &ssam_node_root,
- +};
- +
- /* Base device hub (devices attached to Surface Book 3 base). */
- static const struct software_node ssam_node_hub_base = {
- .name = "ssam:00:00:02:11:00",
- @@ -155,6 +161,30 @@ static const struct software_node ssam_node_hid_base_iid6 = {
- .parent = &ssam_node_hub_base,
- };
-
- +/* HID keyboard (KIP hub). */
- +static const struct software_node ssam_node_hid_kip_keyboard = {
- + .name = "ssam:01:15:02:01:00",
- + .parent = &ssam_node_hub_kip,
- +};
- +
- +/* HID pen stash (KIP hub; pen taken / stashed away evens). */
- +static const struct software_node ssam_node_hid_kip_penstash = {
- + .name = "ssam:01:15:02:02:00",
- + .parent = &ssam_node_hub_kip,
- +};
- +
- +/* HID touchpad (KIP hub). */
- +static const struct software_node ssam_node_hid_kip_touchpad = {
- + .name = "ssam:01:15:02:03:00",
- + .parent = &ssam_node_hub_kip,
- +};
- +
- +/* HID device instance 5 (KIP hub, unknown HID device). */
- +static const struct software_node ssam_node_hid_kip_iid5 = {
- + .name = "ssam:01:15:02:05:00",
- + .parent = &ssam_node_hub_kip,
- +};
- +
- /*
- * Devices for 5th- and 6th-generations models:
- * - Surface Book 2,
- @@ -230,10 +260,15 @@ static const struct software_node *ssam_node_group_sp7[] = {
-
- static const struct software_node *ssam_node_group_sp8[] = {
- &ssam_node_root,
- + &ssam_node_hub_kip,
- &ssam_node_bat_ac,
- &ssam_node_bat_main,
- &ssam_node_tmp_pprof,
- - /* TODO: Add support for keyboard cover. */
- + &ssam_node_hid_kip_keyboard,
- + &ssam_node_hid_kip_penstash,
- + &ssam_node_hid_kip_touchpad,
- + &ssam_node_hid_kip_iid5,
- + /* TODO: Add support for tablet mode switch. */
- NULL,
- };
-
- --
- 2.37.3
- From 8a5e0a8677fdc380ee0396fc9028169ddcb41319 Mon Sep 17 00:00:00 2001
- From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
- Date: Fri, 10 Jun 2022 14:41:58 +0900
- Subject: [PATCH] platform/surface: avoid flush_scheduled_work() usage
- Use local wq in order to avoid flush_scheduled_work() usage.
- Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
- Reviewed-by: Maximilian Luz <luzmaximilian@gmail.com>
- Tested-by: Maximilian Luz <luzmaximilian@gmail.com>
- Link: https://lore.kernel.org/r/63ec2d45-c67c-1134-f6d3-490c8ba67a01@I-love.SAKURA.ne.jp
- Signed-off-by: Hans de Goede <hdegoede@redhat.com>
- Patchset: surface-sam
- ---
- .../platform/surface/surface_acpi_notify.c | 27 ++++++++++++++++---
- 1 file changed, 24 insertions(+), 3 deletions(-)
- diff --git a/drivers/platform/surface/surface_acpi_notify.c b/drivers/platform/surface/surface_acpi_notify.c
- index 7b758f8cc137..c0e12f0b9b79 100644
- --- a/drivers/platform/surface/surface_acpi_notify.c
- +++ b/drivers/platform/surface/surface_acpi_notify.c
- @@ -37,6 +37,7 @@ struct san_data {
- #define to_san_data(ptr, member) \
- container_of(ptr, struct san_data, member)
-
- +static struct workqueue_struct *san_wq;
-
- /* -- dGPU notifier interface. ---------------------------------------------- */
-
- @@ -356,7 +357,7 @@ static u32 san_evt_bat_nf(struct ssam_event_notifier *nf,
-
- memcpy(&work->event, event, sizeof(struct ssam_event) + event->length);
-
- - schedule_delayed_work(&work->work, delay);
- + queue_delayed_work(san_wq, &work->work, delay);
- return SSAM_NOTIF_HANDLED;
- }
-
- @@ -861,7 +862,7 @@ static int san_remove(struct platform_device *pdev)
- * We have unregistered our event sources. Now we need to ensure that
- * all delayed works they may have spawned are run to completion.
- */
- - flush_scheduled_work();
- + flush_workqueue(san_wq);
-
- return 0;
- }
- @@ -881,7 +882,27 @@ static struct platform_driver surface_acpi_notify = {
- .probe_type = PROBE_PREFER_ASYNCHRONOUS,
- },
- };
- -module_platform_driver(surface_acpi_notify);
- +
- +static int __init san_init(void)
- +{
- + int ret;
- +
- + san_wq = alloc_workqueue("san_wq", 0, 0);
- + if (!san_wq)
- + return -ENOMEM;
- + ret = platform_driver_register(&surface_acpi_notify);
- + if (ret)
- + destroy_workqueue(san_wq);
- + return ret;
- +}
- +module_init(san_init);
- +
- +static void __exit san_exit(void)
- +{
- + platform_driver_unregister(&surface_acpi_notify);
- + destroy_workqueue(san_wq);
- +}
- +module_exit(san_exit);
-
- MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
- MODULE_DESCRIPTION("Surface ACPI Notify driver for Surface System Aggregator Module");
- --
- 2.37.3
- From 1c87e70a44365ab940602ef2411089085b4da6dc Mon Sep 17 00:00:00 2001
- From: Maximilian Luz <luzmaximilian@gmail.com>
- Date: Tue, 14 Jun 2022 21:41:17 +0200
- Subject: [PATCH] platform/surface: aggregator: Reserve more event- and
- target-categories
- With the introduction of the Surface Laptop Studio, more event- and
- target categories have been added. Therefore, increase the number of
- reserved events and extend the enum of know target categories to
- accommodate this.
- Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
- Link: https://lore.kernel.org/r/20220614194117.4118897-1-luzmaximilian@gmail.com
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
- Signed-off-by: Hans de Goede <hdegoede@redhat.com>
- Patchset: surface-sam
- ---
- drivers/platform/surface/aggregator/trace.h | 80 +++++++++++--------
- include/linux/surface_aggregator/serial_hub.h | 75 +++++++++--------
- 2 files changed, 85 insertions(+), 70 deletions(-)
- diff --git a/drivers/platform/surface/aggregator/trace.h b/drivers/platform/surface/aggregator/trace.h
- index de64cf169060..cc9e73fbc18e 100644
- --- a/drivers/platform/surface/aggregator/trace.h
- +++ b/drivers/platform/surface/aggregator/trace.h
- @@ -76,7 +76,7 @@ TRACE_DEFINE_ENUM(SSAM_SSH_TC_HID);
- TRACE_DEFINE_ENUM(SSAM_SSH_TC_TCH);
- TRACE_DEFINE_ENUM(SSAM_SSH_TC_BKL);
- TRACE_DEFINE_ENUM(SSAM_SSH_TC_TAM);
- -TRACE_DEFINE_ENUM(SSAM_SSH_TC_ACC);
- +TRACE_DEFINE_ENUM(SSAM_SSH_TC_ACC0);
- TRACE_DEFINE_ENUM(SSAM_SSH_TC_UFI);
- TRACE_DEFINE_ENUM(SSAM_SSH_TC_USC);
- TRACE_DEFINE_ENUM(SSAM_SSH_TC_PEN);
- @@ -85,6 +85,11 @@ TRACE_DEFINE_ENUM(SSAM_SSH_TC_AUD);
- TRACE_DEFINE_ENUM(SSAM_SSH_TC_SMC);
- TRACE_DEFINE_ENUM(SSAM_SSH_TC_KPD);
- TRACE_DEFINE_ENUM(SSAM_SSH_TC_REG);
- +TRACE_DEFINE_ENUM(SSAM_SSH_TC_SPT);
- +TRACE_DEFINE_ENUM(SSAM_SSH_TC_SYS);
- +TRACE_DEFINE_ENUM(SSAM_SSH_TC_ACC1);
- +TRACE_DEFINE_ENUM(SSAM_SSH_TC_SHB);
- +TRACE_DEFINE_ENUM(SSAM_SSH_TC_POS);
-
- #define SSAM_PTR_UID_LEN 9
- #define SSAM_U8_FIELD_NOT_APPLICABLE ((u16)-1)
- @@ -229,40 +234,45 @@ static inline u32 ssam_trace_get_request_tc(const struct ssh_packet *p)
-
- #define ssam_show_ssh_tc(rqid) \
- __print_symbolic(rqid, \
- - { SSAM_SSH_TC_NOT_APPLICABLE, "N/A" }, \
- - { SSAM_SSH_TC_SAM, "SAM" }, \
- - { SSAM_SSH_TC_BAT, "BAT" }, \
- - { SSAM_SSH_TC_TMP, "TMP" }, \
- - { SSAM_SSH_TC_PMC, "PMC" }, \
- - { SSAM_SSH_TC_FAN, "FAN" }, \
- - { SSAM_SSH_TC_PoM, "PoM" }, \
- - { SSAM_SSH_TC_DBG, "DBG" }, \
- - { SSAM_SSH_TC_KBD, "KBD" }, \
- - { SSAM_SSH_TC_FWU, "FWU" }, \
- - { SSAM_SSH_TC_UNI, "UNI" }, \
- - { SSAM_SSH_TC_LPC, "LPC" }, \
- - { SSAM_SSH_TC_TCL, "TCL" }, \
- - { SSAM_SSH_TC_SFL, "SFL" }, \
- - { SSAM_SSH_TC_KIP, "KIP" }, \
- - { SSAM_SSH_TC_EXT, "EXT" }, \
- - { SSAM_SSH_TC_BLD, "BLD" }, \
- - { SSAM_SSH_TC_BAS, "BAS" }, \
- - { SSAM_SSH_TC_SEN, "SEN" }, \
- - { SSAM_SSH_TC_SRQ, "SRQ" }, \
- - { SSAM_SSH_TC_MCU, "MCU" }, \
- - { SSAM_SSH_TC_HID, "HID" }, \
- - { SSAM_SSH_TC_TCH, "TCH" }, \
- - { SSAM_SSH_TC_BKL, "BKL" }, \
- - { SSAM_SSH_TC_TAM, "TAM" }, \
- - { SSAM_SSH_TC_ACC, "ACC" }, \
- - { SSAM_SSH_TC_UFI, "UFI" }, \
- - { SSAM_SSH_TC_USC, "USC" }, \
- - { SSAM_SSH_TC_PEN, "PEN" }, \
- - { SSAM_SSH_TC_VID, "VID" }, \
- - { SSAM_SSH_TC_AUD, "AUD" }, \
- - { SSAM_SSH_TC_SMC, "SMC" }, \
- - { SSAM_SSH_TC_KPD, "KPD" }, \
- - { SSAM_SSH_TC_REG, "REG" } \
- + { SSAM_SSH_TC_NOT_APPLICABLE, "N/A" }, \
- + { SSAM_SSH_TC_SAM, "SAM" }, \
- + { SSAM_SSH_TC_BAT, "BAT" }, \
- + { SSAM_SSH_TC_TMP, "TMP" }, \
- + { SSAM_SSH_TC_PMC, "PMC" }, \
- + { SSAM_SSH_TC_FAN, "FAN" }, \
- + { SSAM_SSH_TC_PoM, "PoM" }, \
- + { SSAM_SSH_TC_DBG, "DBG" }, \
- + { SSAM_SSH_TC_KBD, "KBD" }, \
- + { SSAM_SSH_TC_FWU, "FWU" }, \
- + { SSAM_SSH_TC_UNI, "UNI" }, \
- + { SSAM_SSH_TC_LPC, "LPC" }, \
- + { SSAM_SSH_TC_TCL, "TCL" }, \
- + { SSAM_SSH_TC_SFL, "SFL" }, \
- + { SSAM_SSH_TC_KIP, "KIP" }, \
- + { SSAM_SSH_TC_EXT, "EXT" }, \
- + { SSAM_SSH_TC_BLD, "BLD" }, \
- + { SSAM_SSH_TC_BAS, "BAS" }, \
- + { SSAM_SSH_TC_SEN, "SEN" }, \
- + { SSAM_SSH_TC_SRQ, "SRQ" }, \
- + { SSAM_SSH_TC_MCU, "MCU" }, \
- + { SSAM_SSH_TC_HID, "HID" }, \
- + { SSAM_SSH_TC_TCH, "TCH" }, \
- + { SSAM_SSH_TC_BKL, "BKL" }, \
- + { SSAM_SSH_TC_TAM, "TAM" }, \
- + { SSAM_SSH_TC_ACC0, "ACC0" }, \
- + { SSAM_SSH_TC_UFI, "UFI" }, \
- + { SSAM_SSH_TC_USC, "USC" }, \
- + { SSAM_SSH_TC_PEN, "PEN" }, \
- + { SSAM_SSH_TC_VID, "VID" }, \
- + { SSAM_SSH_TC_AUD, "AUD" }, \
- + { SSAM_SSH_TC_SMC, "SMC" }, \
- + { SSAM_SSH_TC_KPD, "KPD" }, \
- + { SSAM_SSH_TC_REG, "REG" }, \
- + { SSAM_SSH_TC_SPT, "SPT" }, \
- + { SSAM_SSH_TC_SYS, "SYS" }, \
- + { SSAM_SSH_TC_ACC1, "ACC1" }, \
- + { SSAM_SSH_TC_SHB, "SMB" }, \
- + { SSAM_SSH_TC_POS, "POS" } \
- )
-
- DECLARE_EVENT_CLASS(ssam_frame_class,
- diff --git a/include/linux/surface_aggregator/serial_hub.h b/include/linux/surface_aggregator/serial_hub.h
- index 26b95ec12733..45501b6e54e8 100644
- --- a/include/linux/surface_aggregator/serial_hub.h
- +++ b/include/linux/surface_aggregator/serial_hub.h
- @@ -201,7 +201,7 @@ static inline u16 ssh_crc(const u8 *buf, size_t len)
- * exception of zero, which is not an event ID. Thus, this is also the
- * absolute maximum number of event handlers that can be registered.
- */
- -#define SSH_NUM_EVENTS 34
- +#define SSH_NUM_EVENTS 38
-
- /*
- * SSH_NUM_TARGETS - The number of communication targets used in the protocol.
- @@ -292,40 +292,45 @@ struct ssam_span {
- * Windows driver.
- */
- enum ssam_ssh_tc {
- - /* Category 0x00 is invalid for EC use. */
- - SSAM_SSH_TC_SAM = 0x01, /* Generic system functionality, real-time clock. */
- - SSAM_SSH_TC_BAT = 0x02, /* Battery/power subsystem. */
- - SSAM_SSH_TC_TMP = 0x03, /* Thermal subsystem. */
- - SSAM_SSH_TC_PMC = 0x04,
- - SSAM_SSH_TC_FAN = 0x05,
- - SSAM_SSH_TC_PoM = 0x06,
- - SSAM_SSH_TC_DBG = 0x07,
- - SSAM_SSH_TC_KBD = 0x08, /* Legacy keyboard (Laptop 1/2). */
- - SSAM_SSH_TC_FWU = 0x09,
- - SSAM_SSH_TC_UNI = 0x0a,
- - SSAM_SSH_TC_LPC = 0x0b,
- - SSAM_SSH_TC_TCL = 0x0c,
- - SSAM_SSH_TC_SFL = 0x0d,
- - SSAM_SSH_TC_KIP = 0x0e, /* Manages detachable peripherals (Pro X/8 keyboard cover) */
- - SSAM_SSH_TC_EXT = 0x0f,
- - SSAM_SSH_TC_BLD = 0x10,
- - SSAM_SSH_TC_BAS = 0x11, /* Detachment system (Surface Book 2/3). */
- - SSAM_SSH_TC_SEN = 0x12,
- - SSAM_SSH_TC_SRQ = 0x13,
- - SSAM_SSH_TC_MCU = 0x14,
- - SSAM_SSH_TC_HID = 0x15, /* Generic HID input subsystem. */
- - SSAM_SSH_TC_TCH = 0x16,
- - SSAM_SSH_TC_BKL = 0x17,
- - SSAM_SSH_TC_TAM = 0x18,
- - SSAM_SSH_TC_ACC = 0x19,
- - SSAM_SSH_TC_UFI = 0x1a,
- - SSAM_SSH_TC_USC = 0x1b,
- - SSAM_SSH_TC_PEN = 0x1c,
- - SSAM_SSH_TC_VID = 0x1d,
- - SSAM_SSH_TC_AUD = 0x1e,
- - SSAM_SSH_TC_SMC = 0x1f,
- - SSAM_SSH_TC_KPD = 0x20,
- - SSAM_SSH_TC_REG = 0x21, /* Extended event registry. */
- + /* Category 0x00 is invalid for EC use. */
- + SSAM_SSH_TC_SAM = 0x01, /* Generic system functionality, real-time clock. */
- + SSAM_SSH_TC_BAT = 0x02, /* Battery/power subsystem. */
- + SSAM_SSH_TC_TMP = 0x03, /* Thermal subsystem. */
- + SSAM_SSH_TC_PMC = 0x04,
- + SSAM_SSH_TC_FAN = 0x05,
- + SSAM_SSH_TC_PoM = 0x06,
- + SSAM_SSH_TC_DBG = 0x07,
- + SSAM_SSH_TC_KBD = 0x08, /* Legacy keyboard (Laptop 1/2). */
- + SSAM_SSH_TC_FWU = 0x09,
- + SSAM_SSH_TC_UNI = 0x0a,
- + SSAM_SSH_TC_LPC = 0x0b,
- + SSAM_SSH_TC_TCL = 0x0c,
- + SSAM_SSH_TC_SFL = 0x0d,
- + SSAM_SSH_TC_KIP = 0x0e, /* Manages detachable peripherals (Pro X/8 keyboard cover) */
- + SSAM_SSH_TC_EXT = 0x0f,
- + SSAM_SSH_TC_BLD = 0x10,
- + SSAM_SSH_TC_BAS = 0x11, /* Detachment system (Surface Book 2/3). */
- + SSAM_SSH_TC_SEN = 0x12,
- + SSAM_SSH_TC_SRQ = 0x13,
- + SSAM_SSH_TC_MCU = 0x14,
- + SSAM_SSH_TC_HID = 0x15, /* Generic HID input subsystem. */
- + SSAM_SSH_TC_TCH = 0x16,
- + SSAM_SSH_TC_BKL = 0x17,
- + SSAM_SSH_TC_TAM = 0x18,
- + SSAM_SSH_TC_ACC0 = 0x19,
- + SSAM_SSH_TC_UFI = 0x1a,
- + SSAM_SSH_TC_USC = 0x1b,
- + SSAM_SSH_TC_PEN = 0x1c,
- + SSAM_SSH_TC_VID = 0x1d,
- + SSAM_SSH_TC_AUD = 0x1e,
- + SSAM_SSH_TC_SMC = 0x1f,
- + SSAM_SSH_TC_KPD = 0x20,
- + SSAM_SSH_TC_REG = 0x21, /* Extended event registry. */
- + SSAM_SSH_TC_SPT = 0x22,
- + SSAM_SSH_TC_SYS = 0x23,
- + SSAM_SSH_TC_ACC1 = 0x24,
- + SSAM_SSH_TC_SHB = 0x25,
- + SSAM_SSH_TC_POS = 0x26, /* For obtaining Laptop Studio screen position. */
- };
-
-
- --
- 2.37.3
- From 9605088bc0d4b65631727218b293465e50d51258 Mon Sep 17 00:00:00 2001
- From: Maximilian Luz <luzmaximilian@gmail.com>
- Date: Fri, 24 Jun 2022 20:36:39 +0200
- Subject: [PATCH] platform/surface: aggregator: Add helper macros for requests
- with argument and return value
- Add helper macros for synchronous stack-allocated Surface Aggregator
- request with both argument and return value, similar to the current
- argument-only and return-value-only ones.
- Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
- Link: https://lore.kernel.org/r/20220624183642.910893-2-luzmaximilian@gmail.com
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
- Signed-off-by: Hans de Goede <hdegoede@redhat.com>
- Patchset: surface-sam
- ---
- include/linux/surface_aggregator/controller.h | 125 ++++++++++++++++++
- include/linux/surface_aggregator/device.h | 36 +++++
- 2 files changed, 161 insertions(+)
- diff --git a/include/linux/surface_aggregator/controller.h b/include/linux/surface_aggregator/controller.h
- index 50a2b4926c06..d11a1c6e3186 100644
- --- a/include/linux/surface_aggregator/controller.h
- +++ b/include/linux/surface_aggregator/controller.h
- @@ -469,6 +469,67 @@ struct ssam_request_spec_md {
- return 0; \
- }
-
- +/**
- + * SSAM_DEFINE_SYNC_REQUEST_WR() - Define synchronous SAM request function with
- + * both argument and return value.
- + * @name: Name of the generated function.
- + * @atype: Type of the request's argument.
- + * @rtype: Type of the request's return value.
- + * @spec: Specification (&struct ssam_request_spec) defining the request.
- + *
- + * Defines a function executing the synchronous SAM request specified by @spec,
- + * with the request taking an argument of type @atype and having a return value
- + * of type @rtype. The generated function takes care of setting up the request
- + * and response structs, buffer allocation, as well as execution of the request
- + * itself, returning once the request has been fully completed. The required
- + * transport buffer will be allocated on the stack.
- + *
- + * The generated function is defined as ``static int name(struct
- + * ssam_controller *ctrl, const atype *arg, rtype *ret)``, returning the status
- + * of the request, which is zero on success and negative on failure. The
- + * ``ctrl`` parameter is the controller via which the request is sent. The
- + * request argument is specified via the ``arg`` pointer. The request's return
- + * value is written to the memory pointed to by the ``ret`` parameter.
- + *
- + * Refer to ssam_request_sync_onstack() for more details on the behavior of
- + * the generated function.
- + */
- +#define SSAM_DEFINE_SYNC_REQUEST_WR(name, atype, rtype, spec...) \
- + static int name(struct ssam_controller *ctrl, const atype *arg, rtype *ret) \
- + { \
- + struct ssam_request_spec s = (struct ssam_request_spec)spec; \
- + struct ssam_request rqst; \
- + struct ssam_response rsp; \
- + int status; \
- + \
- + rqst.target_category = s.target_category; \
- + rqst.target_id = s.target_id; \
- + rqst.command_id = s.command_id; \
- + rqst.instance_id = s.instance_id; \
- + rqst.flags = s.flags | SSAM_REQUEST_HAS_RESPONSE; \
- + rqst.length = sizeof(atype); \
- + rqst.payload = (u8 *)arg; \
- + \
- + rsp.capacity = sizeof(rtype); \
- + rsp.length = 0; \
- + rsp.pointer = (u8 *)ret; \
- + \
- + status = ssam_request_sync_onstack(ctrl, &rqst, &rsp, sizeof(atype)); \
- + if (status) \
- + return status; \
- + \
- + if (rsp.length != sizeof(rtype)) { \
- + struct device *dev = ssam_controller_device(ctrl); \
- + dev_err(dev, \
- + "rqst: invalid response length, expected %zu, got %zu (tc: %#04x, cid: %#04x)", \
- + sizeof(rtype), rsp.length, rqst.target_category,\
- + rqst.command_id); \
- + return -EIO; \
- + } \
- + \
- + return 0; \
- + }
- +
- /**
- * SSAM_DEFINE_SYNC_REQUEST_MD_N() - Define synchronous multi-device SAM
- * request function with neither argument nor return value.
- @@ -613,6 +674,70 @@ struct ssam_request_spec_md {
- return 0; \
- }
-
- +/**
- + * SSAM_DEFINE_SYNC_REQUEST_MD_WR() - Define synchronous multi-device SAM
- + * request function with both argument and return value.
- + * @name: Name of the generated function.
- + * @atype: Type of the request's argument.
- + * @rtype: Type of the request's return value.
- + * @spec: Specification (&struct ssam_request_spec_md) defining the request.
- + *
- + * Defines a function executing the synchronous SAM request specified by @spec,
- + * with the request taking an argument of type @atype and having a return value
- + * of type @rtype. Device specifying parameters are not hard-coded, but instead
- + * must be provided to the function. The generated function takes care of
- + * setting up the request and response structs, buffer allocation, as well as
- + * execution of the request itself, returning once the request has been fully
- + * completed. The required transport buffer will be allocated on the stack.
- + *
- + * The generated function is defined as ``static int name(struct
- + * ssam_controller *ctrl, u8 tid, u8 iid, const atype *arg, rtype *ret)``,
- + * returning the status of the request, which is zero on success and negative
- + * on failure. The ``ctrl`` parameter is the controller via which the request
- + * is sent, ``tid`` the target ID for the request, and ``iid`` the instance ID.
- + * The request argument is specified via the ``arg`` pointer. The request's
- + * return value is written to the memory pointed to by the ``ret`` parameter.
- + *
- + * Refer to ssam_request_sync_onstack() for more details on the behavior of
- + * the generated function.
- + */
- +#define SSAM_DEFINE_SYNC_REQUEST_MD_WR(name, atype, rtype, spec...) \
- + static int name(struct ssam_controller *ctrl, u8 tid, u8 iid, \
- + const atype *arg, rtype *ret) \
- + { \
- + struct ssam_request_spec_md s = (struct ssam_request_spec_md)spec; \
- + struct ssam_request rqst; \
- + struct ssam_response rsp; \
- + int status; \
- + \
- + rqst.target_category = s.target_category; \
- + rqst.target_id = tid; \
- + rqst.command_id = s.command_id; \
- + rqst.instance_id = iid; \
- + rqst.flags = s.flags | SSAM_REQUEST_HAS_RESPONSE; \
- + rqst.length = sizeof(atype); \
- + rqst.payload = (u8 *)arg; \
- + \
- + rsp.capacity = sizeof(rtype); \
- + rsp.length = 0; \
- + rsp.pointer = (u8 *)ret; \
- + \
- + status = ssam_request_sync_onstack(ctrl, &rqst, &rsp, sizeof(atype)); \
- + if (status) \
- + return status; \
- + \
- + if (rsp.length != sizeof(rtype)) { \
- + struct device *dev = ssam_controller_device(ctrl); \
- + dev_err(dev, \
- + "rqst: invalid response length, expected %zu, got %zu (tc: %#04x, cid: %#04x)", \
- + sizeof(rtype), rsp.length, rqst.target_category,\
- + rqst.command_id); \
- + return -EIO; \
- + } \
- + \
- + return 0; \
- + }
- +
-
- /* -- Event notifier/callbacks. --------------------------------------------- */
-
- diff --git a/include/linux/surface_aggregator/device.h b/include/linux/surface_aggregator/device.h
- index c418f7f2732d..6cf7e80312d5 100644
- --- a/include/linux/surface_aggregator/device.h
- +++ b/include/linux/surface_aggregator/device.h
- @@ -483,6 +483,42 @@ static inline void ssam_remove_clients(struct device *dev) {}
- sdev->uid.instance, ret); \
- }
-
- +/**
- + * SSAM_DEFINE_SYNC_REQUEST_CL_WR() - Define synchronous client-device SAM
- + * request function with argument and return value.
- + * @name: Name of the generated function.
- + * @atype: Type of the request's argument.
- + * @rtype: Type of the request's return value.
- + * @spec: Specification (&struct ssam_request_spec_md) defining the request.
- + *
- + * Defines a function executing the synchronous SAM request specified by @spec,
- + * with the request taking an argument of type @atype and having a return value
- + * of type @rtype. Device specifying parameters are not hard-coded, but instead
- + * are provided via the client device, specifically its UID, supplied when
- + * calling this function. The generated function takes care of setting up the
- + * request struct, buffer allocation, as well as execution of the request
- + * itself, returning once the request has been fully completed. The required
- + * transport buffer will be allocated on the stack.
- + *
- + * The generated function is defined as ``static int name(struct ssam_device
- + * *sdev, const atype *arg, rtype *ret)``, returning the status of the request,
- + * which is zero on success and negative on failure. The ``sdev`` parameter
- + * specifies both the target device of the request and by association the
- + * controller via which the request is sent. The request's argument is
- + * specified via the ``arg`` pointer. The request's return value is written to
- + * the memory pointed to by the ``ret`` parameter.
- + *
- + * Refer to ssam_request_sync_onstack() for more details on the behavior of
- + * the generated function.
- + */
- +#define SSAM_DEFINE_SYNC_REQUEST_CL_WR(name, atype, rtype, spec...) \
- + SSAM_DEFINE_SYNC_REQUEST_MD_WR(__raw_##name, atype, rtype, spec) \
- + static int name(struct ssam_device *sdev, const atype *arg, rtype *ret) \
- + { \
- + return __raw_##name(sdev->ctrl, sdev->uid.target, \
- + sdev->uid.instance, arg, ret); \
- + }
- +
-
- /* -- Helpers for client-device notifiers. ---------------------------------- */
-
- --
- 2.37.3
- From 80cc5deee33592e920aa7a43a613ddd79ab82dd7 Mon Sep 17 00:00:00 2001
- From: Maximilian Luz <luzmaximilian@gmail.com>
- Date: Fri, 24 Jun 2022 20:36:40 +0200
- Subject: [PATCH] platform/surface: Add KIP/POS tablet-mode switch driver
- MIME-Version: 1.0
- Content-Type: text/plain; charset=UTF-8
- Content-Transfer-Encoding: 8bit
- Add a driver providing a tablet-mode switch input device for Microsoft
- Surface devices using the Surface Aggregator KIP subsystem (to manage
- detachable peripherals) or POS subsystem (to obtain device posture
- information).
- The KIP (full name unknown, abbreviation found through reverse
- engineering) subsystem is used on the Surface Pro 8 and Surface Pro X to
- manage the keyboard cover. Among other things, it provides information
- on the positioning (posture) of the cover (closed, laptop-style,
- detached, folded-back, ...), which can be used to implement an input
- device providing the SW_TABLET_MODE event. Similarly, the POS (posture
- information) subsystem provides such information on the Surface Laptop
- Studio, with the difference being that the keyboard is not detachable.
- As implementing the tablet-mode switch for both subsystems is largely
- similar, the driver proposed in this commit, in large, acts as a generic
- tablet mode switch driver framework for the Surface Aggregator Module.
- Specific implementations using this framework are provided for the KIP
- and POS subsystems, adding tablet-mode switch support to the
- aforementioned devices.
- A few more notes on the Surface Laptop Studio:
- A peculiarity of the Surface Laptop Studio is its "slate/tent" mode
- (symbolized: user> _/\). In this mode, the screen covers the keyboard
- but leaves the touchpad exposed. This is essentially a mode in-between
- tablet and laptop, and it is debatable whether tablet-mode should be
- enabled in this mode. We therefore let the user decide this via a module
- parameter.
- In particular, tablet-mode may bring up the on-screen touch keyboard
- more easily, which would be desirable in this mode. However, some
- user-space software currently also decides to disable keyboard and, more
- importantly, touchpad input, while the touchpad is still accessible in
- the "slate/tent" mode. Furthermore, this mode shares its identifier with
- "slate/flipped" mode where the screen is flipped 180° and the keyboard
- points away from the user (symbolized: user> /_). In this mode we would
- like to enable auto-rotation, something that user-space software may
- only do when tablet-mode is enabled. We therefore default to the
- slate-mode enabling the tablet-mode switch.
- Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
- Link: https://lore.kernel.org/r/20220624183642.910893-3-luzmaximilian@gmail.com
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
- Signed-off-by: Hans de Goede <hdegoede@redhat.com>
- Patchset: surface-sam
- ---
- .../sysfs-bus-surface_aggregator-tabletsw | 57 ++
- MAINTAINERS | 6 +
- drivers/platform/surface/Kconfig | 23 +
- drivers/platform/surface/Makefile | 1 +
- .../surface/surface_aggregator_tabletsw.c | 533 ++++++++++++++++++
- 5 files changed, 620 insertions(+)
- create mode 100644 Documentation/ABI/testing/sysfs-bus-surface_aggregator-tabletsw
- create mode 100644 drivers/platform/surface/surface_aggregator_tabletsw.c
- diff --git a/Documentation/ABI/testing/sysfs-bus-surface_aggregator-tabletsw b/Documentation/ABI/testing/sysfs-bus-surface_aggregator-tabletsw
- new file mode 100644
- index 000000000000..74cd9d754e60
- --- /dev/null
- +++ b/Documentation/ABI/testing/sysfs-bus-surface_aggregator-tabletsw
- @@ -0,0 +1,57 @@
- +What: /sys/bus/surface_aggregator/devices/01:0e:01:00:01/state
- +Date: July 2022
- +KernelVersion: 5.20
- +Contact: Maximilian Luz <luzmaximilian@gmail.com>
- +Description:
- + This attribute returns a string with the current type-cover
- + or device posture, as indicated by the embedded controller.
- + Currently returned posture states are:
- +
- + - "disconnected": The type-cover has been disconnected.
- +
- + - "closed": The type-cover has been folded closed and lies on
- + top of the display.
- +
- + - "laptop": The type-cover is open and in laptop-mode, i.e.,
- + ready for normal use.
- +
- + - "folded-canvas": The type-cover has been folded back
- + part-ways, but does not lie flush with the back side of the
- + device. In general, this means that the kick-stand is used
- + and extended atop of the cover.
- +
- + - "folded-back": The type cover has been fully folded back and
- + lies flush with the back side of the device.
- +
- + - "<unknown>": The current state is unknown to the driver, for
- + example due to newer as-of-yet unsupported hardware.
- +
- + New states may be introduced with new hardware. Users therefore
- + must not rely on this list of states being exhaustive and
- + gracefully handle unknown states.
- +
- +What: /sys/bus/surface_aggregator/devices/01:26:01:00:01/state
- +Date: July 2022
- +KernelVersion: 5.20
- +Contact: Maximilian Luz <luzmaximilian@gmail.com>
- +Description:
- + This attribute returns a string with the current device posture, as indicated by the embedded controller. Currently
- + returned posture states are:
- +
- + - "closed": The lid of the device is closed.
- +
- + - "laptop": The lid of the device is opened and the device
- + operates as a normal laptop.
- +
- + - "slate": The screen covers the keyboard or has been flipped
- + back and the device operates mainly based on touch input.
- +
- + - "tablet": The device operates as tablet and exclusively
- + relies on touch input (or external peripherals).
- +
- + - "<unknown>": The current state is unknown to the driver, for
- + example due to newer as-of-yet unsupported hardware.
- +
- + New states may be introduced with new hardware. Users therefore
- + must not rely on this list of states being exhaustive and
- + gracefully handle unknown states.
- diff --git a/MAINTAINERS b/MAINTAINERS
- index 08620b9a44fc..773eb8387f4a 100644
- --- a/MAINTAINERS
- +++ b/MAINTAINERS
- @@ -13299,6 +13299,12 @@ F: drivers/scsi/smartpqi/smartpqi*.[ch]
- F: include/linux/cciss*.h
- F: include/uapi/linux/cciss*.h
-
- +MICROSOFT SURFACE AGGREGATOR TABLET-MODE SWITCH
- +M: Maximilian Luz <luzmaximilian@gmail.com>
- +L: platform-driver-x86@vger.kernel.org
- +S: Maintained
- +F: drivers/platform/surface/surface_aggregator_tablet_switch.c
- +
- MICROSOFT SURFACE BATTERY AND AC DRIVERS
- M: Maximilian Luz <luzmaximilian@gmail.com>
- L: linux-pm@vger.kernel.org
- diff --git a/drivers/platform/surface/Kconfig b/drivers/platform/surface/Kconfig
- index eb79fbed8059..b152e930cc84 100644
- --- a/drivers/platform/surface/Kconfig
- +++ b/drivers/platform/surface/Kconfig
- @@ -99,6 +99,29 @@ config SURFACE_AGGREGATOR_REGISTRY
- the respective client devices. Drivers for these devices still need to
- be selected via the other options.
-
- +config SURFACE_AGGREGATOR_TABLET_SWITCH
- + tristate "Surface Aggregator Generic Tablet-Mode Switch Driver"
- + depends on SURFACE_AGGREGATOR
- + depends on SURFACE_AGGREGATOR_BUS
- + depends on INPUT
- + help
- + Provides a tablet-mode switch input device on Microsoft Surface models
- + using the KIP subsystem for detachable keyboards (e.g. keyboard covers)
- + or the POS subsystem for device/screen posture changes.
- +
- + The KIP subsystem is used on newer Surface generations to handle
- + detachable input peripherals, specifically the keyboard cover (containing
- + keyboard and touchpad) on the Surface Pro 8 and Surface Pro X. The POS
- + subsystem is used for device posture change notifications on the Surface
- + Laptop Studio. This module provides a driver to let user-space know when
- + the device should be considered in tablet-mode due to the keyboard cover
- + being detached or folded back (essentially signaling when the keyboard is
- + not available for input). It does so by creating a tablet-mode switch
- + input device, sending the standard SW_TABLET_MODE event on mode change.
- +
- + Select M or Y here, if you want to provide tablet-mode switch input
- + events on the Surface Pro 8, Surface Pro X, and Surface Laptop Studio.
- +
- config SURFACE_DTX
- tristate "Surface DTX (Detachment System) Driver"
- depends on SURFACE_AGGREGATOR
- diff --git a/drivers/platform/surface/Makefile b/drivers/platform/surface/Makefile
- index 0fc9cd3e4dd9..18b27898543e 100644
- --- a/drivers/platform/surface/Makefile
- +++ b/drivers/platform/surface/Makefile
- @@ -10,6 +10,7 @@ obj-$(CONFIG_SURFACE_ACPI_NOTIFY) += surface_acpi_notify.o
- obj-$(CONFIG_SURFACE_AGGREGATOR) += aggregator/
- obj-$(CONFIG_SURFACE_AGGREGATOR_CDEV) += surface_aggregator_cdev.o
- obj-$(CONFIG_SURFACE_AGGREGATOR_REGISTRY) += surface_aggregator_registry.o
- +obj-$(CONFIG_SURFACE_AGGREGATOR_TABLET_SWITCH) += surface_aggregator_tabletsw.o
- obj-$(CONFIG_SURFACE_DTX) += surface_dtx.o
- obj-$(CONFIG_SURFACE_GPE) += surface_gpe.o
- obj-$(CONFIG_SURFACE_HOTPLUG) += surface_hotplug.o
- diff --git a/drivers/platform/surface/surface_aggregator_tabletsw.c b/drivers/platform/surface/surface_aggregator_tabletsw.c
- new file mode 100644
- index 000000000000..596ca6c80681
- --- /dev/null
- +++ b/drivers/platform/surface/surface_aggregator_tabletsw.c
- @@ -0,0 +1,533 @@
- +// SPDX-License-Identifier: GPL-2.0+
- +/*
- + * Surface System Aggregator Module (SSAM) tablet mode switch driver.
- + *
- + * Copyright (C) 2022 Maximilian Luz <luzmaximilian@gmail.com>
- + */
- +
- +#include <asm/unaligned.h>
- +#include <linux/input.h>
- +#include <linux/kernel.h>
- +#include <linux/module.h>
- +#include <linux/types.h>
- +#include <linux/workqueue.h>
- +
- +#include <linux/surface_aggregator/controller.h>
- +#include <linux/surface_aggregator/device.h>
- +
- +
- +/* -- SSAM generic tablet switch driver framework. -------------------------- */
- +
- +struct ssam_tablet_sw;
- +
- +struct ssam_tablet_sw_ops {
- + int (*get_state)(struct ssam_tablet_sw *sw, u32 *state);
- + const char *(*state_name)(struct ssam_tablet_sw *sw, u32 state);
- + bool (*state_is_tablet_mode)(struct ssam_tablet_sw *sw, u32 state);
- +};
- +
- +struct ssam_tablet_sw {
- + struct ssam_device *sdev;
- +
- + u32 state;
- + struct work_struct update_work;
- + struct input_dev *mode_switch;
- +
- + struct ssam_tablet_sw_ops ops;
- + struct ssam_event_notifier notif;
- +};
- +
- +struct ssam_tablet_sw_desc {
- + struct {
- + const char *name;
- + const char *phys;
- + } dev;
- +
- + struct {
- + u32 (*notify)(struct ssam_event_notifier *nf, const struct ssam_event *event);
- + int (*get_state)(struct ssam_tablet_sw *sw, u32 *state);
- + const char *(*state_name)(struct ssam_tablet_sw *sw, u32 state);
- + bool (*state_is_tablet_mode)(struct ssam_tablet_sw *sw, u32 state);
- + } ops;
- +
- + struct {
- + struct ssam_event_registry reg;
- + struct ssam_event_id id;
- + enum ssam_event_mask mask;
- + u8 flags;
- + } event;
- +};
- +
- +static ssize_t state_show(struct device *dev, struct device_attribute *attr, char *buf)
- +{
- + struct ssam_tablet_sw *sw = dev_get_drvdata(dev);
- + const char *state = sw->ops.state_name(sw, sw->state);
- +
- + return sysfs_emit(buf, "%s\n", state);
- +}
- +static DEVICE_ATTR_RO(state);
- +
- +static struct attribute *ssam_tablet_sw_attrs[] = {
- + &dev_attr_state.attr,
- + NULL,
- +};
- +
- +static const struct attribute_group ssam_tablet_sw_group = {
- + .attrs = ssam_tablet_sw_attrs,
- +};
- +
- +static void ssam_tablet_sw_update_workfn(struct work_struct *work)
- +{
- + struct ssam_tablet_sw *sw = container_of(work, struct ssam_tablet_sw, update_work);
- + int tablet, status;
- + u32 state;
- +
- + status = sw->ops.get_state(sw, &state);
- + if (status)
- + return;
- +
- + if (sw->state == state)
- + return;
- + sw->state = state;
- +
- + /* Send SW_TABLET_MODE event. */
- + tablet = sw->ops.state_is_tablet_mode(sw, state);
- + input_report_switch(sw->mode_switch, SW_TABLET_MODE, tablet);
- + input_sync(sw->mode_switch);
- +}
- +
- +static int __maybe_unused ssam_tablet_sw_resume(struct device *dev)
- +{
- + struct ssam_tablet_sw *sw = dev_get_drvdata(dev);
- +
- + schedule_work(&sw->update_work);
- + return 0;
- +}
- +static SIMPLE_DEV_PM_OPS(ssam_tablet_sw_pm_ops, NULL, ssam_tablet_sw_resume);
- +
- +static int ssam_tablet_sw_probe(struct ssam_device *sdev)
- +{
- + const struct ssam_tablet_sw_desc *desc;
- + struct ssam_tablet_sw *sw;
- + int tablet, status;
- +
- + desc = ssam_device_get_match_data(sdev);
- + if (!desc) {
- + WARN(1, "no driver match data specified");
- + return -EINVAL;
- + }
- +
- + sw = devm_kzalloc(&sdev->dev, sizeof(*sw), GFP_KERNEL);
- + if (!sw)
- + return -ENOMEM;
- +
- + sw->sdev = sdev;
- +
- + sw->ops.get_state = desc->ops.get_state;
- + sw->ops.state_name = desc->ops.state_name;
- + sw->ops.state_is_tablet_mode = desc->ops.state_is_tablet_mode;
- +
- + INIT_WORK(&sw->update_work, ssam_tablet_sw_update_workfn);
- +
- + ssam_device_set_drvdata(sdev, sw);
- +
- + /* Get initial state. */
- + status = sw->ops.get_state(sw, &sw->state);
- + if (status)
- + return status;
- +
- + /* Set up tablet mode switch. */
- + sw->mode_switch = devm_input_allocate_device(&sdev->dev);
- + if (!sw->mode_switch)
- + return -ENOMEM;
- +
- + sw->mode_switch->name = desc->dev.name;
- + sw->mode_switch->phys = desc->dev.phys;
- + sw->mode_switch->id.bustype = BUS_HOST;
- + sw->mode_switch->dev.parent = &sdev->dev;
- +
- + tablet = sw->ops.state_is_tablet_mode(sw, sw->state);
- + input_set_capability(sw->mode_switch, EV_SW, SW_TABLET_MODE);
- + input_report_switch(sw->mode_switch, SW_TABLET_MODE, tablet);
- +
- + status = input_register_device(sw->mode_switch);
- + if (status)
- + return status;
- +
- + /* Set up notifier. */
- + sw->notif.base.priority = 0;
- + sw->notif.base.fn = desc->ops.notify;
- + sw->notif.event.reg = desc->event.reg;
- + sw->notif.event.id = desc->event.id;
- + sw->notif.event.mask = desc->event.mask;
- + sw->notif.event.flags = SSAM_EVENT_SEQUENCED;
- +
- + status = ssam_device_notifier_register(sdev, &sw->notif);
- + if (status)
- + return status;
- +
- + status = sysfs_create_group(&sdev->dev.kobj, &ssam_tablet_sw_group);
- + if (status)
- + goto err;
- +
- + /* We might have missed events during setup, so check again. */
- + schedule_work(&sw->update_work);
- + return 0;
- +
- +err:
- + ssam_device_notifier_unregister(sdev, &sw->notif);
- + cancel_work_sync(&sw->update_work);
- + return status;
- +}
- +
- +static void ssam_tablet_sw_remove(struct ssam_device *sdev)
- +{
- + struct ssam_tablet_sw *sw = ssam_device_get_drvdata(sdev);
- +
- + sysfs_remove_group(&sdev->dev.kobj, &ssam_tablet_sw_group);
- +
- + ssam_device_notifier_unregister(sdev, &sw->notif);
- + cancel_work_sync(&sw->update_work);
- +}
- +
- +
- +/* -- SSAM KIP tablet switch implementation. -------------------------------- */
- +
- +#define SSAM_EVENT_KIP_CID_COVER_STATE_CHANGED 0x1d
- +
- +enum ssam_kip_cover_state {
- + SSAM_KIP_COVER_STATE_DISCONNECTED = 0x01,
- + SSAM_KIP_COVER_STATE_CLOSED = 0x02,
- + SSAM_KIP_COVER_STATE_LAPTOP = 0x03,
- + SSAM_KIP_COVER_STATE_FOLDED_CANVAS = 0x04,
- + SSAM_KIP_COVER_STATE_FOLDED_BACK = 0x05,
- +};
- +
- +static const char *ssam_kip_cover_state_name(struct ssam_tablet_sw *sw, u32 state)
- +{
- + switch (state) {
- + case SSAM_KIP_COVER_STATE_DISCONNECTED:
- + return "disconnected";
- +
- + case SSAM_KIP_COVER_STATE_CLOSED:
- + return "closed";
- +
- + case SSAM_KIP_COVER_STATE_LAPTOP:
- + return "laptop";
- +
- + case SSAM_KIP_COVER_STATE_FOLDED_CANVAS:
- + return "folded-canvas";
- +
- + case SSAM_KIP_COVER_STATE_FOLDED_BACK:
- + return "folded-back";
- +
- + default:
- + dev_warn(&sw->sdev->dev, "unknown KIP cover state: %u\n", state);
- + return "<unknown>";
- + }
- +}
- +
- +static bool ssam_kip_cover_state_is_tablet_mode(struct ssam_tablet_sw *sw, u32 state)
- +{
- + switch (state) {
- + case SSAM_KIP_COVER_STATE_DISCONNECTED:
- + case SSAM_KIP_COVER_STATE_FOLDED_CANVAS:
- + case SSAM_KIP_COVER_STATE_FOLDED_BACK:
- + return true;
- +
- + case SSAM_KIP_COVER_STATE_CLOSED:
- + case SSAM_KIP_COVER_STATE_LAPTOP:
- + return false;
- +
- + default:
- + dev_warn(&sw->sdev->dev, "unknown KIP cover state: %d\n", sw->state);
- + return true;
- + }
- +}
- +
- +SSAM_DEFINE_SYNC_REQUEST_R(__ssam_kip_get_cover_state, u8, {
- + .target_category = SSAM_SSH_TC_KIP,
- + .target_id = 0x01,
- + .command_id = 0x1d,
- + .instance_id = 0x00,
- +});
- +
- +static int ssam_kip_get_cover_state(struct ssam_tablet_sw *sw, u32 *state)
- +{
- + int status;
- + u8 raw;
- +
- + status = ssam_retry(__ssam_kip_get_cover_state, sw->sdev->ctrl, &raw);
- + if (status < 0) {
- + dev_err(&sw->sdev->dev, "failed to query KIP lid state: %d\n", status);
- + return status;
- + }
- +
- + *state = raw;
- + return 0;
- +}
- +
- +static u32 ssam_kip_sw_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
- +{
- + struct ssam_tablet_sw *sw = container_of(nf, struct ssam_tablet_sw, notif);
- +
- + if (event->command_id != SSAM_EVENT_KIP_CID_COVER_STATE_CHANGED)
- + return 0; /* Return "unhandled". */
- +
- + if (event->length < 1)
- + dev_warn(&sw->sdev->dev, "unexpected payload size: %u\n", event->length);
- +
- + schedule_work(&sw->update_work);
- + return SSAM_NOTIF_HANDLED;
- +}
- +
- +static const struct ssam_tablet_sw_desc ssam_kip_sw_desc = {
- + .dev = {
- + .name = "Microsoft Surface KIP Tablet Mode Switch",
- + .phys = "ssam/01:0e:01:00:01/input0",
- + },
- + .ops = {
- + .notify = ssam_kip_sw_notif,
- + .get_state = ssam_kip_get_cover_state,
- + .state_name = ssam_kip_cover_state_name,
- + .state_is_tablet_mode = ssam_kip_cover_state_is_tablet_mode,
- + },
- + .event = {
- + .reg = SSAM_EVENT_REGISTRY_SAM,
- + .id = {
- + .target_category = SSAM_SSH_TC_KIP,
- + .instance = 0,
- + },
- + .mask = SSAM_EVENT_MASK_TARGET,
- + },
- +};
- +
- +
- +/* -- SSAM POS tablet switch implementation. -------------------------------- */
- +
- +static bool tablet_mode_in_slate_state = true;
- +module_param(tablet_mode_in_slate_state, bool, 0644);
- +MODULE_PARM_DESC(tablet_mode_in_slate_state, "Enable tablet mode in slate device posture, default is 'true'");
- +
- +#define SSAM_EVENT_POS_CID_POSTURE_CHANGED 0x03
- +#define SSAM_POS_MAX_SOURCES 4
- +
- +enum ssam_pos_state {
- + SSAM_POS_POSTURE_LID_CLOSED = 0x00,
- + SSAM_POS_POSTURE_LAPTOP = 0x01,
- + SSAM_POS_POSTURE_SLATE = 0x02,
- + SSAM_POS_POSTURE_TABLET = 0x03,
- +};
- +
- +struct ssam_sources_list {
- + __le32 count;
- + __le32 id[SSAM_POS_MAX_SOURCES];
- +} __packed;
- +
- +static const char *ssam_pos_state_name(struct ssam_tablet_sw *sw, u32 state)
- +{
- + switch (state) {
- + case SSAM_POS_POSTURE_LID_CLOSED:
- + return "closed";
- +
- + case SSAM_POS_POSTURE_LAPTOP:
- + return "laptop";
- +
- + case SSAM_POS_POSTURE_SLATE:
- + return "slate";
- +
- + case SSAM_POS_POSTURE_TABLET:
- + return "tablet";
- +
- + default:
- + dev_warn(&sw->sdev->dev, "unknown device posture: %u\n", state);
- + return "<unknown>";
- + }
- +}
- +
- +static bool ssam_pos_state_is_tablet_mode(struct ssam_tablet_sw *sw, u32 state)
- +{
- + switch (state) {
- + case SSAM_POS_POSTURE_LAPTOP:
- + case SSAM_POS_POSTURE_LID_CLOSED:
- + return false;
- +
- + case SSAM_POS_POSTURE_SLATE:
- + return tablet_mode_in_slate_state;
- +
- + case SSAM_POS_POSTURE_TABLET:
- + return true;
- +
- + default:
- + dev_warn(&sw->sdev->dev, "unknown device posture: %u\n", state);
- + return true;
- + }
- +}
- +
- +static int ssam_pos_get_sources_list(struct ssam_tablet_sw *sw, struct ssam_sources_list *sources)
- +{
- + struct ssam_request rqst;
- + struct ssam_response rsp;
- + int status;
- +
- + rqst.target_category = SSAM_SSH_TC_POS;
- + rqst.target_id = 0x01;
- + rqst.command_id = 0x01;
- + rqst.instance_id = 0x00;
- + rqst.flags = SSAM_REQUEST_HAS_RESPONSE;
- + rqst.length = 0;
- + rqst.payload = NULL;
- +
- + rsp.capacity = sizeof(*sources);
- + rsp.length = 0;
- + rsp.pointer = (u8 *)sources;
- +
- + status = ssam_retry(ssam_request_sync_onstack, sw->sdev->ctrl, &rqst, &rsp, 0);
- + if (status)
- + return status;
- +
- + /* We need at least the 'sources->count' field. */
- + if (rsp.length < sizeof(__le32)) {
- + dev_err(&sw->sdev->dev, "received source list response is too small\n");
- + return -EPROTO;
- + }
- +
- + /* Make sure 'sources->count' matches with the response length. */
- + if (get_unaligned_le32(&sources->count) * sizeof(__le32) + sizeof(__le32) != rsp.length) {
- + dev_err(&sw->sdev->dev, "mismatch between number of sources and response size\n");
- + return -EPROTO;
- + }
- +
- + return 0;
- +}
- +
- +static int ssam_pos_get_source(struct ssam_tablet_sw *sw, u32 *source_id)
- +{
- + struct ssam_sources_list sources = {};
- + int status;
- +
- + status = ssam_pos_get_sources_list(sw, &sources);
- + if (status)
- + return status;
- +
- + if (sources.count == 0) {
- + dev_err(&sw->sdev->dev, "no posture sources found\n");
- + return -ENODEV;
- + }
- +
- + /*
- + * We currently don't know what to do with more than one posture
- + * source. At the moment, only one source seems to be used/provided.
- + * The WARN_ON() here should hopefully let us know quickly once there
- + * is a device that provides multiple sources, at which point we can
- + * then try to figure out how to handle them.
- + */
- + WARN_ON(sources.count > 1);
- +
- + *source_id = get_unaligned_le32(&sources.id[0]);
- + return 0;
- +}
- +
- +SSAM_DEFINE_SYNC_REQUEST_WR(__ssam_pos_get_posture_for_source, __le32, __le32, {
- + .target_category = SSAM_SSH_TC_POS,
- + .target_id = 0x01,
- + .command_id = 0x02,
- + .instance_id = 0x00,
- +});
- +
- +static int ssam_pos_get_posture_for_source(struct ssam_tablet_sw *sw, u32 source_id, u32 *posture)
- +{
- + __le32 source_le = cpu_to_le32(source_id);
- + __le32 rspval_le = 0;
- + int status;
- +
- + status = ssam_retry(__ssam_pos_get_posture_for_source, sw->sdev->ctrl,
- + &source_le, &rspval_le);
- + if (status)
- + return status;
- +
- + *posture = le32_to_cpu(rspval_le);
- + return 0;
- +}
- +
- +static int ssam_pos_get_posture(struct ssam_tablet_sw *sw, u32 *state)
- +{
- + u32 source_id;
- + int status;
- +
- + status = ssam_pos_get_source(sw, &source_id);
- + if (status) {
- + dev_err(&sw->sdev->dev, "failed to get posture source ID: %d\n", status);
- + return status;
- + }
- +
- + status = ssam_pos_get_posture_for_source(sw, source_id, state);
- + if (status) {
- + dev_err(&sw->sdev->dev, "failed to get posture value for source %u: %d\n",
- + source_id, status);
- + return status;
- + }
- +
- + return 0;
- +}
- +
- +static u32 ssam_pos_sw_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
- +{
- + struct ssam_tablet_sw *sw = container_of(nf, struct ssam_tablet_sw, notif);
- +
- + if (event->command_id != SSAM_EVENT_POS_CID_POSTURE_CHANGED)
- + return 0; /* Return "unhandled". */
- +
- + if (event->length != sizeof(__le32) * 3)
- + dev_warn(&sw->sdev->dev, "unexpected payload size: %u\n", event->length);
- +
- + schedule_work(&sw->update_work);
- + return SSAM_NOTIF_HANDLED;
- +}
- +
- +static const struct ssam_tablet_sw_desc ssam_pos_sw_desc = {
- + .dev = {
- + .name = "Microsoft Surface POS Tablet Mode Switch",
- + .phys = "ssam/01:26:01:00:01/input0",
- + },
- + .ops = {
- + .notify = ssam_pos_sw_notif,
- + .get_state = ssam_pos_get_posture,
- + .state_name = ssam_pos_state_name,
- + .state_is_tablet_mode = ssam_pos_state_is_tablet_mode,
- + },
- + .event = {
- + .reg = SSAM_EVENT_REGISTRY_SAM,
- + .id = {
- + .target_category = SSAM_SSH_TC_POS,
- + .instance = 0,
- + },
- + .mask = SSAM_EVENT_MASK_TARGET,
- + },
- +};
- +
- +
- +/* -- Driver registration. -------------------------------------------------- */
- +
- +static const struct ssam_device_id ssam_tablet_sw_match[] = {
- + { SSAM_SDEV(KIP, 0x01, 0x00, 0x01), (unsigned long)&ssam_kip_sw_desc },
- + { SSAM_SDEV(POS, 0x01, 0x00, 0x01), (unsigned long)&ssam_pos_sw_desc },
- + { },
- +};
- +MODULE_DEVICE_TABLE(ssam, ssam_tablet_sw_match);
- +
- +static struct ssam_device_driver ssam_tablet_sw_driver = {
- + .probe = ssam_tablet_sw_probe,
- + .remove = ssam_tablet_sw_remove,
- + .match_table = ssam_tablet_sw_match,
- + .driver = {
- + .name = "surface_aggregator_tablet_mode_switch",
- + .probe_type = PROBE_PREFER_ASYNCHRONOUS,
- + .pm = &ssam_tablet_sw_pm_ops,
- + },
- +};
- +module_ssam_device_driver(ssam_tablet_sw_driver);
- +
- +MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
- +MODULE_DESCRIPTION("Tablet mode switch driver for Surface devices using the Surface Aggregator Module");
- +MODULE_LICENSE("GPL");
- --
- 2.37.3
- From aeff964ca43cb0f7041de4aa6c75d3d1aca851f8 Mon Sep 17 00:00:00 2001
- From: Maximilian Luz <luzmaximilian@gmail.com>
- Date: Fri, 24 Jun 2022 20:36:41 +0200
- Subject: [PATCH] platform/surface: aggregator_registry: Add support for tablet
- mode switch on Surface Pro 8
- Add a KIP subsystem tablet-mode switch device for the Surface Pro 8.
- The respective driver for this device provides SW_TABLET_MODE input
- events for user-space based on the state of the keyboard cover (e.g.
- detached, folded-back, normal/laptop mode).
- Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
- Link: https://lore.kernel.org/r/20220624183642.910893-4-luzmaximilian@gmail.com
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
- Signed-off-by: Hans de Goede <hdegoede@redhat.com>
- Patchset: surface-sam
- ---
- drivers/platform/surface/surface_aggregator_registry.c | 8 +++++++-
- 1 file changed, 7 insertions(+), 1 deletion(-)
- diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
- index bf3303f1aa71..8f249df673a4 100644
- --- a/drivers/platform/surface/surface_aggregator_registry.c
- +++ b/drivers/platform/surface/surface_aggregator_registry.c
- @@ -77,6 +77,12 @@ static const struct software_node ssam_node_tmp_pprof = {
- .parent = &ssam_node_root,
- };
-
- +/* Tablet-mode switch via KIP subsystem. */
- +static const struct software_node ssam_node_kip_tablet_switch = {
- + .name = "ssam:01:0e:01:00:01",
- + .parent = &ssam_node_root,
- +};
- +
- /* DTX / detachment-system device (Surface Book 3). */
- static const struct software_node ssam_node_bas_dtx = {
- .name = "ssam:01:11:01:00:00",
- @@ -264,11 +270,11 @@ static const struct software_node *ssam_node_group_sp8[] = {
- &ssam_node_bat_ac,
- &ssam_node_bat_main,
- &ssam_node_tmp_pprof,
- + &ssam_node_kip_tablet_switch,
- &ssam_node_hid_kip_keyboard,
- &ssam_node_hid_kip_penstash,
- &ssam_node_hid_kip_touchpad,
- &ssam_node_hid_kip_iid5,
- - /* TODO: Add support for tablet mode switch. */
- NULL,
- };
-
- --
- 2.37.3
- From d343a4324b7d8b064f8f8c91acfd08c869bfaf22 Mon Sep 17 00:00:00 2001
- From: Maximilian Luz <luzmaximilian@gmail.com>
- Date: Fri, 24 Jun 2022 20:36:42 +0200
- Subject: [PATCH] platform/surface: aggregator_registry: Add support for tablet
- mode switch on Surface Laptop Studio
- Add a POS subsystem tablet-mode switch device for the Surface Laptop
- Studio. The respective driver for this device provides SW_TABLET_MODE
- input events for user-space based on the posture of the screen.
- Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
- Link: https://lore.kernel.org/r/20220624183642.910893-5-luzmaximilian@gmail.com
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
- Signed-off-by: Hans de Goede <hdegoede@redhat.com>
- Patchset: surface-sam
- ---
- drivers/platform/surface/surface_aggregator_registry.c | 7 +++++++
- 1 file changed, 7 insertions(+)
- diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
- index 8f249df673a4..f1c5905f1c16 100644
- --- a/drivers/platform/surface/surface_aggregator_registry.c
- +++ b/drivers/platform/surface/surface_aggregator_registry.c
- @@ -191,6 +191,12 @@ static const struct software_node ssam_node_hid_kip_iid5 = {
- .parent = &ssam_node_hub_kip,
- };
-
- +/* Tablet-mode switch via POS subsystem. */
- +static const struct software_node ssam_node_pos_tablet_switch = {
- + .name = "ssam:01:26:01:00:01",
- + .parent = &ssam_node_root,
- +};
- +
- /*
- * Devices for 5th- and 6th-generations models:
- * - Surface Book 2,
- @@ -237,6 +243,7 @@ static const struct software_node *ssam_node_group_sls[] = {
- &ssam_node_bat_ac,
- &ssam_node_bat_main,
- &ssam_node_tmp_pprof,
- + &ssam_node_pos_tablet_switch,
- &ssam_node_hid_tid1_keyboard,
- &ssam_node_hid_tid1_penstash,
- &ssam_node_hid_tid1_touchpad,
- --
- 2.37.3
- From 1dcd80182218cda418c2d8f08b9ec2e78f53675c Mon Sep 17 00:00:00 2001
- From: Maximilian Luz <luzmaximilian@gmail.com>
- Date: Fri, 24 Jun 2022 22:57:58 +0200
- Subject: [PATCH] platform/surface: aggregator: Move device registry helper
- functions to core module
- Move helper functions for client device registration to the core module.
- This simplifies addition of future DT/OF support and also allows us to
- split out the device hub drivers into their own module.
- At the same time, also improve device node validation a bit by not
- silently skipping devices with invalid device UID specifiers. Further,
- ensure proper lifetime management for the firmware/software nodes
- associated with the added devices.
- Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
- Link: https://lore.kernel.org/r/20220624205800.1355621-2-luzmaximilian@gmail.com
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
- Signed-off-by: Hans de Goede <hdegoede@redhat.com>
- Patchset: surface-sam
- ---
- drivers/platform/surface/aggregator/bus.c | 149 ++++++++++++++++--
- .../surface/surface_aggregator_registry.c | 75 +--------
- include/linux/surface_aggregator/device.h | 52 ++++++
- 3 files changed, 187 insertions(+), 89 deletions(-)
- diff --git a/drivers/platform/surface/aggregator/bus.c b/drivers/platform/surface/aggregator/bus.c
- index abbbb5b08b07..e0b0381a2834 100644
- --- a/drivers/platform/surface/aggregator/bus.c
- +++ b/drivers/platform/surface/aggregator/bus.c
- @@ -6,6 +6,7 @@
- */
-
- #include <linux/device.h>
- +#include <linux/property.h>
- #include <linux/slab.h>
-
- #include <linux/surface_aggregator/controller.h>
- @@ -14,6 +15,9 @@
- #include "bus.h"
- #include "controller.h"
-
- +
- +/* -- Device and bus functions. --------------------------------------------- */
- +
- static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
- char *buf)
- {
- @@ -46,6 +50,7 @@ static void ssam_device_release(struct device *dev)
- struct ssam_device *sdev = to_ssam_device(dev);
-
- ssam_controller_put(sdev->ctrl);
- + fwnode_handle_put(sdev->dev.fwnode);
- kfree(sdev);
- }
-
- @@ -363,6 +368,134 @@ void ssam_device_driver_unregister(struct ssam_device_driver *sdrv)
- }
- EXPORT_SYMBOL_GPL(ssam_device_driver_unregister);
-
- +
- +/* -- Bus registration. ----------------------------------------------------- */
- +
- +/**
- + * ssam_bus_register() - Register and set-up the SSAM client device bus.
- + */
- +int ssam_bus_register(void)
- +{
- + return bus_register(&ssam_bus_type);
- +}
- +
- +/**
- + * ssam_bus_unregister() - Unregister the SSAM client device bus.
- + */
- +void ssam_bus_unregister(void)
- +{
- + return bus_unregister(&ssam_bus_type);
- +}
- +
- +
- +/* -- Helpers for controller and hub devices. ------------------------------- */
- +
- +static int ssam_device_uid_from_string(const char *str, struct ssam_device_uid *uid)
- +{
- + u8 d, tc, tid, iid, fn;
- + int n;
- +
- + n = sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx", &d, &tc, &tid, &iid, &fn);
- + if (n != 5)
- + return -EINVAL;
- +
- + uid->domain = d;
- + uid->category = tc;
- + uid->target = tid;
- + uid->instance = iid;
- + uid->function = fn;
- +
- + return 0;
- +}
- +
- +static int ssam_get_uid_for_node(struct fwnode_handle *node, struct ssam_device_uid *uid)
- +{
- + const char *str = fwnode_get_name(node);
- +
- + /*
- + * To simplify definitions of firmware nodes, we set the device name
- + * based on the UID of the device, prefixed with "ssam:".
- + */
- + if (strncmp(str, "ssam:", strlen("ssam:")) != 0)
- + return -ENODEV;
- +
- + str += strlen("ssam:");
- + return ssam_device_uid_from_string(str, uid);
- +}
- +
- +static int ssam_add_client_device(struct device *parent, struct ssam_controller *ctrl,
- + struct fwnode_handle *node)
- +{
- + struct ssam_device_uid uid;
- + struct ssam_device *sdev;
- + int status;
- +
- + status = ssam_get_uid_for_node(node, &uid);
- + if (status)
- + return status;
- +
- + sdev = ssam_device_alloc(ctrl, uid);
- + if (!sdev)
- + return -ENOMEM;
- +
- + sdev->dev.parent = parent;
- + sdev->dev.fwnode = fwnode_handle_get(node);
- +
- + status = ssam_device_add(sdev);
- + if (status)
- + ssam_device_put(sdev);
- +
- + return status;
- +}
- +
- +/**
- + * __ssam_register_clients() - Register client devices defined under the
- + * given firmware node as children of the given device.
- + * @parent: The parent device under which clients should be registered.
- + * @ctrl: The controller with which client should be registered.
- + * @node: The firmware node holding definitions of the devices to be added.
- + *
- + * Register all clients that have been defined as children of the given root
- + * firmware node as children of the given parent device. The respective child
- + * firmware nodes will be associated with the correspondingly created child
- + * devices.
- + *
- + * The given controller will be used to instantiate the new devices. See
- + * ssam_device_add() for details.
- + *
- + * Note that, generally, the use of either ssam_device_register_clients() or
- + * ssam_register_clients() should be preferred as they directly use the
- + * firmware node and/or controller associated with the given device. This
- + * function is only intended for use when different device specifications (e.g.
- + * ACPI and firmware nodes) need to be combined (as is done in the platform hub
- + * of the device registry).
- + *
- + * Return: Returns zero on success, nonzero on failure.
- + */
- +int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl,
- + struct fwnode_handle *node)
- +{
- + struct fwnode_handle *child;
- + int status;
- +
- + fwnode_for_each_child_node(node, child) {
- + /*
- + * Try to add the device specified in the firmware node. If
- + * this fails with -ENODEV, the node does not specify any SSAM
- + * device, so ignore it and continue with the next one.
- + */
- + status = ssam_add_client_device(parent, ctrl, child);
- + if (status && status != -ENODEV)
- + goto err;
- + }
- +
- + return 0;
- +err:
- + ssam_remove_clients(parent);
- + return status;
- +}
- +EXPORT_SYMBOL_GPL(__ssam_register_clients);
- +
- static int ssam_remove_device(struct device *dev, void *_data)
- {
- struct ssam_device *sdev = to_ssam_device(dev);
- @@ -387,19 +520,3 @@ void ssam_remove_clients(struct device *dev)
- device_for_each_child_reverse(dev, NULL, ssam_remove_device);
- }
- EXPORT_SYMBOL_GPL(ssam_remove_clients);
- -
- -/**
- - * ssam_bus_register() - Register and set-up the SSAM client device bus.
- - */
- -int ssam_bus_register(void)
- -{
- - return bus_register(&ssam_bus_type);
- -}
- -
- -/**
- - * ssam_bus_unregister() - Unregister the SSAM client device bus.
- - */
- -void ssam_bus_unregister(void)
- -{
- - return bus_unregister(&ssam_bus_type);
- -}
- diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
- index f1c5905f1c16..c680792a037e 100644
- --- a/drivers/platform/surface/surface_aggregator_registry.c
- +++ b/drivers/platform/surface/surface_aggregator_registry.c
- @@ -286,76 +286,6 @@ static const struct software_node *ssam_node_group_sp8[] = {
- };
-
-
- -/* -- Device registry helper functions. ------------------------------------- */
- -
- -static int ssam_uid_from_string(const char *str, struct ssam_device_uid *uid)
- -{
- - u8 d, tc, tid, iid, fn;
- - int n;
- -
- - n = sscanf(str, "ssam:%hhx:%hhx:%hhx:%hhx:%hhx", &d, &tc, &tid, &iid, &fn);
- - if (n != 5)
- - return -EINVAL;
- -
- - uid->domain = d;
- - uid->category = tc;
- - uid->target = tid;
- - uid->instance = iid;
- - uid->function = fn;
- -
- - return 0;
- -}
- -
- -static int ssam_hub_add_device(struct device *parent, struct ssam_controller *ctrl,
- - struct fwnode_handle *node)
- -{
- - struct ssam_device_uid uid;
- - struct ssam_device *sdev;
- - int status;
- -
- - status = ssam_uid_from_string(fwnode_get_name(node), &uid);
- - if (status)
- - return status;
- -
- - sdev = ssam_device_alloc(ctrl, uid);
- - if (!sdev)
- - return -ENOMEM;
- -
- - sdev->dev.parent = parent;
- - sdev->dev.fwnode = node;
- -
- - status = ssam_device_add(sdev);
- - if (status)
- - ssam_device_put(sdev);
- -
- - return status;
- -}
- -
- -static int ssam_hub_register_clients(struct device *parent, struct ssam_controller *ctrl,
- - struct fwnode_handle *node)
- -{
- - struct fwnode_handle *child;
- - int status;
- -
- - fwnode_for_each_child_node(node, child) {
- - /*
- - * Try to add the device specified in the firmware node. If
- - * this fails with -EINVAL, the node does not specify any SSAM
- - * device, so ignore it and continue with the next one.
- - */
- -
- - status = ssam_hub_add_device(parent, ctrl, child);
- - if (status && status != -EINVAL)
- - goto err;
- - }
- -
- - return 0;
- -err:
- - ssam_remove_clients(parent);
- - return status;
- -}
- -
- -
- /* -- SSAM generic subsystem hub driver framework. -------------------------- */
-
- enum ssam_hub_state {
- @@ -385,7 +315,6 @@ struct ssam_hub {
- static void ssam_hub_update_workfn(struct work_struct *work)
- {
- struct ssam_hub *hub = container_of(work, struct ssam_hub, update_work.work);
- - struct fwnode_handle *node = dev_fwnode(&hub->sdev->dev);
- enum ssam_hub_state state;
- int status = 0;
-
- @@ -425,7 +354,7 @@ static void ssam_hub_update_workfn(struct work_struct *work)
- hub->state = state;
-
- if (hub->state == SSAM_HUB_CONNECTED)
- - status = ssam_hub_register_clients(&hub->sdev->dev, hub->sdev->ctrl, node);
- + status = ssam_device_register_clients(hub->sdev);
- else
- ssam_remove_clients(&hub->sdev->dev);
-
- @@ -769,7 +698,7 @@ static int ssam_platform_hub_probe(struct platform_device *pdev)
-
- set_secondary_fwnode(&pdev->dev, root);
-
- - status = ssam_hub_register_clients(&pdev->dev, ctrl, root);
- + status = __ssam_register_clients(&pdev->dev, ctrl, root);
- if (status) {
- set_secondary_fwnode(&pdev->dev, NULL);
- software_node_unregister_node_group(nodes);
- diff --git a/include/linux/surface_aggregator/device.h b/include/linux/surface_aggregator/device.h
- index 6cf7e80312d5..46c45d1b6368 100644
- --- a/include/linux/surface_aggregator/device.h
- +++ b/include/linux/surface_aggregator/device.h
- @@ -15,6 +15,7 @@
-
- #include <linux/device.h>
- #include <linux/mod_devicetable.h>
- +#include <linux/property.h>
- #include <linux/types.h>
-
- #include <linux/surface_aggregator/controller.h>
- @@ -375,11 +376,62 @@ void ssam_device_driver_unregister(struct ssam_device_driver *d);
- /* -- Helpers for controller and hub devices. ------------------------------- */
-
- #ifdef CONFIG_SURFACE_AGGREGATOR_BUS
- +
- +int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl,
- + struct fwnode_handle *node);
- void ssam_remove_clients(struct device *dev);
- +
- #else /* CONFIG_SURFACE_AGGREGATOR_BUS */
- +
- +static inline int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl,
- + struct fwnode_handle *node)
- +{
- + return 0;
- +}
- +
- static inline void ssam_remove_clients(struct device *dev) {}
- +
- #endif /* CONFIG_SURFACE_AGGREGATOR_BUS */
-
- +/**
- + * ssam_register_clients() - Register all client devices defined under the
- + * given parent device.
- + * @dev: The parent device under which clients should be registered.
- + * @ctrl: The controller with which client should be registered.
- + *
- + * Register all clients that have via firmware nodes been defined as children
- + * of the given (parent) device. The respective child firmware nodes will be
- + * associated with the correspondingly created child devices.
- + *
- + * The given controller will be used to instantiate the new devices. See
- + * ssam_device_add() for details.
- + *
- + * Return: Returns zero on success, nonzero on failure.
- + */
- +static inline int ssam_register_clients(struct device *dev, struct ssam_controller *ctrl)
- +{
- + return __ssam_register_clients(dev, ctrl, dev_fwnode(dev));
- +}
- +
- +/**
- + * ssam_device_register_clients() - Register all client devices defined under
- + * the given SSAM parent device.
- + * @sdev: The parent device under which clients should be registered.
- + *
- + * Register all clients that have via firmware nodes been defined as children
- + * of the given (parent) device. The respective child firmware nodes will be
- + * associated with the correspondingly created child devices.
- + *
- + * The controller used by the parent device will be used to instantiate the new
- + * devices. See ssam_device_add() for details.
- + *
- + * Return: Returns zero on success, nonzero on failure.
- + */
- +static inline int ssam_device_register_clients(struct ssam_device *sdev)
- +{
- + return ssam_register_clients(&sdev->dev, sdev->ctrl);
- +}
- +
-
- /* -- Helpers for client-device requests. ----------------------------------- */
-
- --
- 2.37.3
- From 1ef45f74d7f5660d198a79835d6ad321ffc13cb2 Mon Sep 17 00:00:00 2001
- From: Maximilian Luz <luzmaximilian@gmail.com>
- Date: Fri, 24 Jun 2022 22:57:59 +0200
- Subject: [PATCH] platform/surface: aggregator: Move subsystem hub drivers to
- their own module
- Split out subsystem device hub drivers into their own module. This
- allows us to load the hub drivers separately from the registry, which
- will help future DT/OF support.
- While doing so, also remove a small bit of code duplication.
- Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
- Link: https://lore.kernel.org/r/20220624205800.1355621-3-luzmaximilian@gmail.com
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
- Signed-off-by: Hans de Goede <hdegoede@redhat.com>
- Patchset: surface-sam
- ---
- MAINTAINERS | 6 +
- drivers/platform/surface/Kconfig | 35 +-
- drivers/platform/surface/Makefile | 1 +
- .../platform/surface/surface_aggregator_hub.c | 371 ++++++++++++++++++
- .../surface/surface_aggregator_registry.c | 371 +-----------------
- 5 files changed, 410 insertions(+), 374 deletions(-)
- create mode 100644 drivers/platform/surface/surface_aggregator_hub.c
- diff --git a/MAINTAINERS b/MAINTAINERS
- index 773eb8387f4a..55e80354a097 100644
- --- a/MAINTAINERS
- +++ b/MAINTAINERS
- @@ -13376,6 +13376,12 @@ F: include/linux/surface_acpi_notify.h
- F: include/linux/surface_aggregator/
- F: include/uapi/linux/surface_aggregator/
-
- +MICROSOFT SURFACE SYSTEM AGGREGATOR HUB DRIVER
- +M: Maximilian Luz <luzmaximilian@gmail.com>
- +L: platform-driver-x86@vger.kernel.org
- +S: Maintained
- +F: drivers/platform/surface/surface_aggregator_hub.c
- +
- MICROTEK X6 SCANNER
- M: Oliver Neukum <oliver@neukum.org>
- S: Maintained
- diff --git a/drivers/platform/surface/Kconfig b/drivers/platform/surface/Kconfig
- index b152e930cc84..b629e82af97c 100644
- --- a/drivers/platform/surface/Kconfig
- +++ b/drivers/platform/surface/Kconfig
- @@ -72,18 +72,45 @@ config SURFACE_AGGREGATOR_CDEV
- The provided interface is intended for debugging and development only,
- and should not be used otherwise.
-
- +config SURFACE_AGGREGATOR_HUB
- + tristate "Surface System Aggregator Module Subsystem Device Hubs"
- + depends on SURFACE_AGGREGATOR
- + depends on SURFACE_AGGREGATOR_BUS
- + help
- + Device-hub drivers for Surface System Aggregator Module (SSAM) subsystem
- + devices.
- +
- + Provides subsystem hub drivers which manage client devices on various
- + SSAM subsystems. In some subsystems, notably the BAS subsystem managing
- + devices contained in the base of the Surface Book 3 and the KIP subsystem
- + managing type-cover devices in the Surface Pro 8 and Surface Pro X,
- + devices can be (hot-)removed. Hub devices and drivers are required to
- + manage these subdevices.
- +
- + Devices managed via these hubs are:
- + - Battery/AC devices (Surface Book 3).
- + - HID input devices (7th-generation and later models with detachable
- + input devices).
- +
- + Select M (recommended) or Y here if you want support for the above
- + mentioned devices on the corresponding Surface models. Without this
- + module, the respective devices mentioned above will not be instantiated
- + and thus any functionality provided by them will be missing, even when
- + drivers for these devices are present. This module only provides the
- + respective subsystem hubs. Both drivers and device specification (e.g.
- + via the Surface Aggregator Registry) for these devices still need to be
- + selected via other options.
- +
- config SURFACE_AGGREGATOR_REGISTRY
- tristate "Surface System Aggregator Module Device Registry"
- depends on SURFACE_AGGREGATOR
- depends on SURFACE_AGGREGATOR_BUS
- help
- - Device-registry and device-hubs for Surface System Aggregator Module
- - (SSAM) devices.
- + Device-registry for Surface System Aggregator Module (SSAM) devices.
-
- Provides a module and driver which act as a device-registry for SSAM
- client devices that cannot be detected automatically, e.g. via ACPI.
- - Such devices are instead provided via this registry and attached via
- - device hubs, also provided in this module.
- + Such devices are instead provided and managed via this registry.
-
- Devices provided via this registry are:
- - Platform profile (performance-/cooling-mode) device (5th- and later
- diff --git a/drivers/platform/surface/Makefile b/drivers/platform/surface/Makefile
- index 18b27898543e..53344330939b 100644
- --- a/drivers/platform/surface/Makefile
- +++ b/drivers/platform/surface/Makefile
- @@ -9,6 +9,7 @@ obj-$(CONFIG_SURFACE_3_POWER_OPREGION) += surface3_power.o
- obj-$(CONFIG_SURFACE_ACPI_NOTIFY) += surface_acpi_notify.o
- obj-$(CONFIG_SURFACE_AGGREGATOR) += aggregator/
- obj-$(CONFIG_SURFACE_AGGREGATOR_CDEV) += surface_aggregator_cdev.o
- +obj-$(CONFIG_SURFACE_AGGREGATOR_HUB) += surface_aggregator_hub.o
- obj-$(CONFIG_SURFACE_AGGREGATOR_REGISTRY) += surface_aggregator_registry.o
- obj-$(CONFIG_SURFACE_AGGREGATOR_TABLET_SWITCH) += surface_aggregator_tabletsw.o
- obj-$(CONFIG_SURFACE_DTX) += surface_dtx.o
- diff --git a/drivers/platform/surface/surface_aggregator_hub.c b/drivers/platform/surface/surface_aggregator_hub.c
- new file mode 100644
- index 000000000000..43061514be38
- --- /dev/null
- +++ b/drivers/platform/surface/surface_aggregator_hub.c
- @@ -0,0 +1,371 @@
- +// SPDX-License-Identifier: GPL-2.0+
- +/*
- + * Driver for Surface System Aggregator Module (SSAM) subsystem device hubs.
- + *
- + * Provides a driver for SSAM subsystems device hubs. This driver performs
- + * instantiation of the devices managed by said hubs and takes care of
- + * (hot-)removal.
- + *
- + * Copyright (C) 2020-2022 Maximilian Luz <luzmaximilian@gmail.com>
- + */
- +
- +#include <linux/kernel.h>
- +#include <linux/limits.h>
- +#include <linux/module.h>
- +#include <linux/types.h>
- +#include <linux/workqueue.h>
- +
- +#include <linux/surface_aggregator/device.h>
- +
- +
- +/* -- SSAM generic subsystem hub driver framework. -------------------------- */
- +
- +enum ssam_hub_state {
- + SSAM_HUB_UNINITIALIZED, /* Only set during initialization. */
- + SSAM_HUB_CONNECTED,
- + SSAM_HUB_DISCONNECTED,
- +};
- +
- +enum ssam_hub_flags {
- + SSAM_HUB_HOT_REMOVED,
- +};
- +
- +struct ssam_hub;
- +
- +struct ssam_hub_ops {
- + int (*get_state)(struct ssam_hub *hub, enum ssam_hub_state *state);
- +};
- +
- +struct ssam_hub {
- + struct ssam_device *sdev;
- +
- + enum ssam_hub_state state;
- + unsigned long flags;
- +
- + struct delayed_work update_work;
- + unsigned long connect_delay;
- +
- + struct ssam_event_notifier notif;
- + struct ssam_hub_ops ops;
- +};
- +
- +struct ssam_hub_desc {
- + struct {
- + struct ssam_event_registry reg;
- + struct ssam_event_id id;
- + enum ssam_event_mask mask;
- + } event;
- +
- + struct {
- + u32 (*notify)(struct ssam_event_notifier *nf, const struct ssam_event *event);
- + int (*get_state)(struct ssam_hub *hub, enum ssam_hub_state *state);
- + } ops;
- +
- + unsigned long connect_delay_ms;
- +};
- +
- +static void ssam_hub_update_workfn(struct work_struct *work)
- +{
- + struct ssam_hub *hub = container_of(work, struct ssam_hub, update_work.work);
- + enum ssam_hub_state state;
- + int status = 0;
- +
- + status = hub->ops.get_state(hub, &state);
- + if (status)
- + return;
- +
- + /*
- + * There is a small possibility that hub devices were hot-removed and
- + * re-added before we were able to remove them here. In that case, both
- + * the state returned by get_state() and the state of the hub will
- + * equal SSAM_HUB_CONNECTED and we would bail early below, which would
- + * leave child devices without proper (re-)initialization and the
- + * hot-remove flag set.
- + *
- + * Therefore, we check whether devices have been hot-removed via an
- + * additional flag on the hub and, in this case, override the returned
- + * hub state. In case of a missed disconnect (i.e. get_state returned
- + * "connected"), we further need to re-schedule this work (with the
- + * appropriate delay) as the actual connect work submission might have
- + * been merged with this one.
- + *
- + * This then leads to one of two cases: Either we submit an unnecessary
- + * work item (which will get ignored via either the queue or the state
- + * checks) or, in the unlikely case that the work is actually required,
- + * double the normal connect delay.
- + */
- + if (test_and_clear_bit(SSAM_HUB_HOT_REMOVED, &hub->flags)) {
- + if (state == SSAM_HUB_CONNECTED)
- + schedule_delayed_work(&hub->update_work, hub->connect_delay);
- +
- + state = SSAM_HUB_DISCONNECTED;
- + }
- +
- + if (hub->state == state)
- + return;
- + hub->state = state;
- +
- + if (hub->state == SSAM_HUB_CONNECTED)
- + status = ssam_device_register_clients(hub->sdev);
- + else
- + ssam_remove_clients(&hub->sdev->dev);
- +
- + if (status)
- + dev_err(&hub->sdev->dev, "failed to update hub child devices: %d\n", status);
- +}
- +
- +static int ssam_hub_mark_hot_removed(struct device *dev, void *_data)
- +{
- + struct ssam_device *sdev = to_ssam_device(dev);
- +
- + if (is_ssam_device(dev))
- + ssam_device_mark_hot_removed(sdev);
- +
- + return 0;
- +}
- +
- +static void ssam_hub_update(struct ssam_hub *hub, bool connected)
- +{
- + unsigned long delay;
- +
- + /* Mark devices as hot-removed before we remove any. */
- + if (!connected) {
- + set_bit(SSAM_HUB_HOT_REMOVED, &hub->flags);
- + device_for_each_child_reverse(&hub->sdev->dev, NULL, ssam_hub_mark_hot_removed);
- + }
- +
- + /*
- + * Delay update when the base/keyboard cover is being connected to give
- + * devices/EC some time to set up.
- + */
- + delay = connected ? hub->connect_delay : 0;
- +
- + schedule_delayed_work(&hub->update_work, delay);
- +}
- +
- +static int __maybe_unused ssam_hub_resume(struct device *dev)
- +{
- + struct ssam_hub *hub = dev_get_drvdata(dev);
- +
- + schedule_delayed_work(&hub->update_work, 0);
- + return 0;
- +}
- +static SIMPLE_DEV_PM_OPS(ssam_hub_pm_ops, NULL, ssam_hub_resume);
- +
- +static int ssam_hub_probe(struct ssam_device *sdev)
- +{
- + const struct ssam_hub_desc *desc;
- + struct ssam_hub *hub;
- + int status;
- +
- + desc = ssam_device_get_match_data(sdev);
- + if (!desc) {
- + WARN(1, "no driver match data specified");
- + return -EINVAL;
- + }
- +
- + hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL);
- + if (!hub)
- + return -ENOMEM;
- +
- + hub->sdev = sdev;
- + hub->state = SSAM_HUB_UNINITIALIZED;
- +
- + hub->notif.base.priority = INT_MAX; /* This notifier should run first. */
- + hub->notif.base.fn = desc->ops.notify;
- + hub->notif.event.reg = desc->event.reg;
- + hub->notif.event.id = desc->event.id;
- + hub->notif.event.mask = desc->event.mask;
- + hub->notif.event.flags = SSAM_EVENT_SEQUENCED;
- +
- + hub->connect_delay = msecs_to_jiffies(desc->connect_delay_ms);
- + hub->ops.get_state = desc->ops.get_state;
- +
- + INIT_DELAYED_WORK(&hub->update_work, ssam_hub_update_workfn);
- +
- + ssam_device_set_drvdata(sdev, hub);
- +
- + status = ssam_device_notifier_register(sdev, &hub->notif);
- + if (status)
- + return status;
- +
- + schedule_delayed_work(&hub->update_work, 0);
- + return 0;
- +}
- +
- +static void ssam_hub_remove(struct ssam_device *sdev)
- +{
- + struct ssam_hub *hub = ssam_device_get_drvdata(sdev);
- +
- + ssam_device_notifier_unregister(sdev, &hub->notif);
- + cancel_delayed_work_sync(&hub->update_work);
- + ssam_remove_clients(&sdev->dev);
- +}
- +
- +
- +/* -- SSAM base-subsystem hub driver. --------------------------------------- */
- +
- +/*
- + * Some devices (especially battery) may need a bit of time to be fully usable
- + * after being (re-)connected. This delay has been determined via
- + * experimentation.
- + */
- +#define SSAM_BASE_UPDATE_CONNECT_DELAY 2500
- +
- +SSAM_DEFINE_SYNC_REQUEST_R(ssam_bas_query_opmode, u8, {
- + .target_category = SSAM_SSH_TC_BAS,
- + .target_id = 0x01,
- + .command_id = 0x0d,
- + .instance_id = 0x00,
- +});
- +
- +#define SSAM_BAS_OPMODE_TABLET 0x00
- +#define SSAM_EVENT_BAS_CID_CONNECTION 0x0c
- +
- +static int ssam_base_hub_query_state(struct ssam_hub *hub, enum ssam_hub_state *state)
- +{
- + u8 opmode;
- + int status;
- +
- + status = ssam_retry(ssam_bas_query_opmode, hub->sdev->ctrl, &opmode);
- + if (status < 0) {
- + dev_err(&hub->sdev->dev, "failed to query base state: %d\n", status);
- + return status;
- + }
- +
- + if (opmode != SSAM_BAS_OPMODE_TABLET)
- + *state = SSAM_HUB_CONNECTED;
- + else
- + *state = SSAM_HUB_DISCONNECTED;
- +
- + return 0;
- +}
- +
- +static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
- +{
- + struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
- +
- + if (event->command_id != SSAM_EVENT_BAS_CID_CONNECTION)
- + return 0;
- +
- + if (event->length < 1) {
- + dev_err(&hub->sdev->dev, "unexpected payload size: %u\n", event->length);
- + return 0;
- + }
- +
- + ssam_hub_update(hub, event->data[0]);
- +
- + /*
- + * Do not return SSAM_NOTIF_HANDLED: The event should be picked up and
- + * consumed by the detachment system driver. We're just a (more or less)
- + * silent observer.
- + */
- + return 0;
- +}
- +
- +static const struct ssam_hub_desc base_hub = {
- + .event = {
- + .reg = SSAM_EVENT_REGISTRY_SAM,
- + .id = {
- + .target_category = SSAM_SSH_TC_BAS,
- + .instance = 0,
- + },
- + .mask = SSAM_EVENT_MASK_NONE,
- + },
- + .ops = {
- + .notify = ssam_base_hub_notif,
- + .get_state = ssam_base_hub_query_state,
- + },
- + .connect_delay_ms = SSAM_BASE_UPDATE_CONNECT_DELAY,
- +};
- +
- +
- +/* -- SSAM KIP-subsystem hub driver. ---------------------------------------- */
- +
- +/*
- + * Some devices may need a bit of time to be fully usable after being
- + * (re-)connected. This delay has been determined via experimentation.
- + */
- +#define SSAM_KIP_UPDATE_CONNECT_DELAY 250
- +
- +#define SSAM_EVENT_KIP_CID_CONNECTION 0x2c
- +
- +SSAM_DEFINE_SYNC_REQUEST_R(__ssam_kip_query_state, u8, {
- + .target_category = SSAM_SSH_TC_KIP,
- + .target_id = 0x01,
- + .command_id = 0x2c,
- + .instance_id = 0x00,
- +});
- +
- +static int ssam_kip_hub_query_state(struct ssam_hub *hub, enum ssam_hub_state *state)
- +{
- + int status;
- + u8 connected;
- +
- + status = ssam_retry(__ssam_kip_query_state, hub->sdev->ctrl, &connected);
- + if (status < 0) {
- + dev_err(&hub->sdev->dev, "failed to query KIP connection state: %d\n", status);
- + return status;
- + }
- +
- + *state = connected ? SSAM_HUB_CONNECTED : SSAM_HUB_DISCONNECTED;
- + return 0;
- +}
- +
- +static u32 ssam_kip_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
- +{
- + struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
- +
- + if (event->command_id != SSAM_EVENT_KIP_CID_CONNECTION)
- + return 0; /* Return "unhandled". */
- +
- + if (event->length < 1) {
- + dev_err(&hub->sdev->dev, "unexpected payload size: %u\n", event->length);
- + return 0;
- + }
- +
- + ssam_hub_update(hub, event->data[0]);
- + return SSAM_NOTIF_HANDLED;
- +}
- +
- +static const struct ssam_hub_desc kip_hub = {
- + .event = {
- + .reg = SSAM_EVENT_REGISTRY_SAM,
- + .id = {
- + .target_category = SSAM_SSH_TC_KIP,
- + .instance = 0,
- + },
- + .mask = SSAM_EVENT_MASK_TARGET,
- + },
- + .ops = {
- + .notify = ssam_kip_hub_notif,
- + .get_state = ssam_kip_hub_query_state,
- + },
- + .connect_delay_ms = SSAM_KIP_UPDATE_CONNECT_DELAY,
- +};
- +
- +
- +/* -- Driver registration. -------------------------------------------------- */
- +
- +static const struct ssam_device_id ssam_hub_match[] = {
- + { SSAM_VDEV(HUB, 0x01, SSAM_SSH_TC_KIP, 0x00), (unsigned long)&kip_hub },
- + { SSAM_VDEV(HUB, 0x02, SSAM_SSH_TC_BAS, 0x00), (unsigned long)&base_hub },
- + { }
- +};
- +MODULE_DEVICE_TABLE(ssam, ssam_hub_match);
- +
- +static struct ssam_device_driver ssam_subsystem_hub_driver = {
- + .probe = ssam_hub_probe,
- + .remove = ssam_hub_remove,
- + .match_table = ssam_hub_match,
- + .driver = {
- + .name = "surface_aggregator_subsystem_hub",
- + .probe_type = PROBE_PREFER_ASYNCHRONOUS,
- + .pm = &ssam_hub_pm_ops,
- + },
- +};
- +module_ssam_device_driver(ssam_subsystem_hub_driver);
- +
- +MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
- +MODULE_DESCRIPTION("Subsystem device hub driver for Surface System Aggregator Module");
- +MODULE_LICENSE("GPL");
- diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
- index c680792a037e..0cbb7f3a6b2d 100644
- --- a/drivers/platform/surface/surface_aggregator_registry.c
- +++ b/drivers/platform/surface/surface_aggregator_registry.c
- @@ -11,14 +11,11 @@
-
- #include <linux/acpi.h>
- #include <linux/kernel.h>
- -#include <linux/limits.h>
- #include <linux/module.h>
- #include <linux/platform_device.h>
- #include <linux/property.h>
- #include <linux/types.h>
- -#include <linux/workqueue.h>
-
- -#include <linux/surface_aggregator/controller.h>
- #include <linux/surface_aggregator/device.h>
-
-
- @@ -286,335 +283,6 @@ static const struct software_node *ssam_node_group_sp8[] = {
- };
-
-
- -/* -- SSAM generic subsystem hub driver framework. -------------------------- */
- -
- -enum ssam_hub_state {
- - SSAM_HUB_UNINITIALIZED, /* Only set during initialization. */
- - SSAM_HUB_CONNECTED,
- - SSAM_HUB_DISCONNECTED,
- -};
- -
- -enum ssam_hub_flags {
- - SSAM_HUB_HOT_REMOVED,
- -};
- -
- -struct ssam_hub {
- - struct ssam_device *sdev;
- -
- - enum ssam_hub_state state;
- - unsigned long flags;
- -
- - struct delayed_work update_work;
- - unsigned long connect_delay;
- -
- - struct ssam_event_notifier notif;
- -
- - int (*get_state)(struct ssam_hub *hub, enum ssam_hub_state *state);
- -};
- -
- -static void ssam_hub_update_workfn(struct work_struct *work)
- -{
- - struct ssam_hub *hub = container_of(work, struct ssam_hub, update_work.work);
- - enum ssam_hub_state state;
- - int status = 0;
- -
- - status = hub->get_state(hub, &state);
- - if (status)
- - return;
- -
- - /*
- - * There is a small possibility that hub devices were hot-removed and
- - * re-added before we were able to remove them here. In that case, both
- - * the state returned by get_state() and the state of the hub will
- - * equal SSAM_HUB_CONNECTED and we would bail early below, which would
- - * leave child devices without proper (re-)initialization and the
- - * hot-remove flag set.
- - *
- - * Therefore, we check whether devices have been hot-removed via an
- - * additional flag on the hub and, in this case, override the returned
- - * hub state. In case of a missed disconnect (i.e. get_state returned
- - * "connected"), we further need to re-schedule this work (with the
- - * appropriate delay) as the actual connect work submission might have
- - * been merged with this one.
- - *
- - * This then leads to one of two cases: Either we submit an unnecessary
- - * work item (which will get ignored via either the queue or the state
- - * checks) or, in the unlikely case that the work is actually required,
- - * double the normal connect delay.
- - */
- - if (test_and_clear_bit(SSAM_HUB_HOT_REMOVED, &hub->flags)) {
- - if (state == SSAM_HUB_CONNECTED)
- - schedule_delayed_work(&hub->update_work, hub->connect_delay);
- -
- - state = SSAM_HUB_DISCONNECTED;
- - }
- -
- - if (hub->state == state)
- - return;
- - hub->state = state;
- -
- - if (hub->state == SSAM_HUB_CONNECTED)
- - status = ssam_device_register_clients(hub->sdev);
- - else
- - ssam_remove_clients(&hub->sdev->dev);
- -
- - if (status)
- - dev_err(&hub->sdev->dev, "failed to update hub child devices: %d\n", status);
- -}
- -
- -static int ssam_hub_mark_hot_removed(struct device *dev, void *_data)
- -{
- - struct ssam_device *sdev = to_ssam_device(dev);
- -
- - if (is_ssam_device(dev))
- - ssam_device_mark_hot_removed(sdev);
- -
- - return 0;
- -}
- -
- -static void ssam_hub_update(struct ssam_hub *hub, bool connected)
- -{
- - unsigned long delay;
- -
- - /* Mark devices as hot-removed before we remove any. */
- - if (!connected) {
- - set_bit(SSAM_HUB_HOT_REMOVED, &hub->flags);
- - device_for_each_child_reverse(&hub->sdev->dev, NULL, ssam_hub_mark_hot_removed);
- - }
- -
- - /*
- - * Delay update when the base/keyboard cover is being connected to give
- - * devices/EC some time to set up.
- - */
- - delay = connected ? hub->connect_delay : 0;
- -
- - schedule_delayed_work(&hub->update_work, delay);
- -}
- -
- -static int __maybe_unused ssam_hub_resume(struct device *dev)
- -{
- - struct ssam_hub *hub = dev_get_drvdata(dev);
- -
- - schedule_delayed_work(&hub->update_work, 0);
- - return 0;
- -}
- -static SIMPLE_DEV_PM_OPS(ssam_hub_pm_ops, NULL, ssam_hub_resume);
- -
- -static int ssam_hub_setup(struct ssam_device *sdev, struct ssam_hub *hub)
- -{
- - int status;
- -
- - hub->sdev = sdev;
- - hub->state = SSAM_HUB_UNINITIALIZED;
- -
- - INIT_DELAYED_WORK(&hub->update_work, ssam_hub_update_workfn);
- -
- - ssam_device_set_drvdata(sdev, hub);
- -
- - status = ssam_device_notifier_register(sdev, &hub->notif);
- - if (status)
- - return status;
- -
- - schedule_delayed_work(&hub->update_work, 0);
- - return 0;
- -}
- -
- -static void ssam_hub_remove(struct ssam_device *sdev)
- -{
- - struct ssam_hub *hub = ssam_device_get_drvdata(sdev);
- -
- - ssam_device_notifier_unregister(sdev, &hub->notif);
- - cancel_delayed_work_sync(&hub->update_work);
- - ssam_remove_clients(&sdev->dev);
- -}
- -
- -
- -/* -- SSAM base-hub driver. ------------------------------------------------- */
- -
- -/*
- - * Some devices (especially battery) may need a bit of time to be fully usable
- - * after being (re-)connected. This delay has been determined via
- - * experimentation.
- - */
- -#define SSAM_BASE_UPDATE_CONNECT_DELAY msecs_to_jiffies(2500)
- -
- -SSAM_DEFINE_SYNC_REQUEST_R(ssam_bas_query_opmode, u8, {
- - .target_category = SSAM_SSH_TC_BAS,
- - .target_id = 0x01,
- - .command_id = 0x0d,
- - .instance_id = 0x00,
- -});
- -
- -#define SSAM_BAS_OPMODE_TABLET 0x00
- -#define SSAM_EVENT_BAS_CID_CONNECTION 0x0c
- -
- -static int ssam_base_hub_query_state(struct ssam_hub *hub, enum ssam_hub_state *state)
- -{
- - u8 opmode;
- - int status;
- -
- - status = ssam_retry(ssam_bas_query_opmode, hub->sdev->ctrl, &opmode);
- - if (status < 0) {
- - dev_err(&hub->sdev->dev, "failed to query base state: %d\n", status);
- - return status;
- - }
- -
- - if (opmode != SSAM_BAS_OPMODE_TABLET)
- - *state = SSAM_HUB_CONNECTED;
- - else
- - *state = SSAM_HUB_DISCONNECTED;
- -
- - return 0;
- -}
- -
- -static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
- -{
- - struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
- -
- - if (event->command_id != SSAM_EVENT_BAS_CID_CONNECTION)
- - return 0;
- -
- - if (event->length < 1) {
- - dev_err(&hub->sdev->dev, "unexpected payload size: %u\n", event->length);
- - return 0;
- - }
- -
- - ssam_hub_update(hub, event->data[0]);
- -
- - /*
- - * Do not return SSAM_NOTIF_HANDLED: The event should be picked up and
- - * consumed by the detachment system driver. We're just a (more or less)
- - * silent observer.
- - */
- - return 0;
- -}
- -
- -static int ssam_base_hub_probe(struct ssam_device *sdev)
- -{
- - struct ssam_hub *hub;
- -
- - hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL);
- - if (!hub)
- - return -ENOMEM;
- -
- - hub->notif.base.priority = INT_MAX; /* This notifier should run first. */
- - hub->notif.base.fn = ssam_base_hub_notif;
- - hub->notif.event.reg = SSAM_EVENT_REGISTRY_SAM;
- - hub->notif.event.id.target_category = SSAM_SSH_TC_BAS,
- - hub->notif.event.id.instance = 0,
- - hub->notif.event.mask = SSAM_EVENT_MASK_NONE;
- - hub->notif.event.flags = SSAM_EVENT_SEQUENCED;
- -
- - hub->connect_delay = SSAM_BASE_UPDATE_CONNECT_DELAY;
- - hub->get_state = ssam_base_hub_query_state;
- -
- - return ssam_hub_setup(sdev, hub);
- -}
- -
- -static const struct ssam_device_id ssam_base_hub_match[] = {
- - { SSAM_VDEV(HUB, 0x02, SSAM_SSH_TC_BAS, 0x00) },
- - { },
- -};
- -
- -static struct ssam_device_driver ssam_base_hub_driver = {
- - .probe = ssam_base_hub_probe,
- - .remove = ssam_hub_remove,
- - .match_table = ssam_base_hub_match,
- - .driver = {
- - .name = "surface_aggregator_base_hub",
- - .probe_type = PROBE_PREFER_ASYNCHRONOUS,
- - .pm = &ssam_hub_pm_ops,
- - },
- -};
- -
- -
- -/* -- SSAM KIP-subsystem hub driver. ---------------------------------------- */
- -
- -/*
- - * Some devices may need a bit of time to be fully usable after being
- - * (re-)connected. This delay has been determined via experimentation.
- - */
- -#define SSAM_KIP_UPDATE_CONNECT_DELAY msecs_to_jiffies(250)
- -
- -#define SSAM_EVENT_KIP_CID_CONNECTION 0x2c
- -
- -SSAM_DEFINE_SYNC_REQUEST_R(__ssam_kip_get_connection_state, u8, {
- - .target_category = SSAM_SSH_TC_KIP,
- - .target_id = 0x01,
- - .command_id = 0x2c,
- - .instance_id = 0x00,
- -});
- -
- -static int ssam_kip_get_connection_state(struct ssam_hub *hub, enum ssam_hub_state *state)
- -{
- - int status;
- - u8 connected;
- -
- - status = ssam_retry(__ssam_kip_get_connection_state, hub->sdev->ctrl, &connected);
- - if (status < 0) {
- - dev_err(&hub->sdev->dev, "failed to query KIP connection state: %d\n", status);
- - return status;
- - }
- -
- - *state = connected ? SSAM_HUB_CONNECTED : SSAM_HUB_DISCONNECTED;
- - return 0;
- -}
- -
- -static u32 ssam_kip_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
- -{
- - struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
- -
- - if (event->command_id != SSAM_EVENT_KIP_CID_CONNECTION)
- - return 0; /* Return "unhandled". */
- -
- - if (event->length < 1) {
- - dev_err(&hub->sdev->dev, "unexpected payload size: %u\n", event->length);
- - return 0;
- - }
- -
- - ssam_hub_update(hub, event->data[0]);
- - return SSAM_NOTIF_HANDLED;
- -}
- -
- -static int ssam_kip_hub_probe(struct ssam_device *sdev)
- -{
- - struct ssam_hub *hub;
- -
- - hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL);
- - if (!hub)
- - return -ENOMEM;
- -
- - hub->notif.base.priority = INT_MAX; /* This notifier should run first. */
- - hub->notif.base.fn = ssam_kip_hub_notif;
- - hub->notif.event.reg = SSAM_EVENT_REGISTRY_SAM;
- - hub->notif.event.id.target_category = SSAM_SSH_TC_KIP,
- - hub->notif.event.id.instance = 0,
- - hub->notif.event.mask = SSAM_EVENT_MASK_TARGET;
- - hub->notif.event.flags = SSAM_EVENT_SEQUENCED;
- -
- - hub->connect_delay = SSAM_KIP_UPDATE_CONNECT_DELAY;
- - hub->get_state = ssam_kip_get_connection_state;
- -
- - return ssam_hub_setup(sdev, hub);
- -}
- -
- -static const struct ssam_device_id ssam_kip_hub_match[] = {
- - { SSAM_VDEV(HUB, 0x01, SSAM_SSH_TC_KIP, 0x00) },
- - { },
- -};
- -
- -static struct ssam_device_driver ssam_kip_hub_driver = {
- - .probe = ssam_kip_hub_probe,
- - .remove = ssam_hub_remove,
- - .match_table = ssam_kip_hub_match,
- - .driver = {
- - .name = "surface_kip_hub",
- - .probe_type = PROBE_PREFER_ASYNCHRONOUS,
- - .pm = &ssam_hub_pm_ops,
- - },
- -};
- -
- -
- /* -- SSAM platform/meta-hub driver. ---------------------------------------- */
-
- static const struct acpi_device_id ssam_platform_hub_match[] = {
- @@ -727,44 +395,7 @@ static struct platform_driver ssam_platform_hub_driver = {
- .probe_type = PROBE_PREFER_ASYNCHRONOUS,
- },
- };
- -
- -
- -/* -- Module initialization. ------------------------------------------------ */
- -
- -static int __init ssam_device_hub_init(void)
- -{
- - int status;
- -
- - status = platform_driver_register(&ssam_platform_hub_driver);
- - if (status)
- - goto err_platform;
- -
- - status = ssam_device_driver_register(&ssam_base_hub_driver);
- - if (status)
- - goto err_base;
- -
- - status = ssam_device_driver_register(&ssam_kip_hub_driver);
- - if (status)
- - goto err_kip;
- -
- - return 0;
- -
- -err_kip:
- - ssam_device_driver_unregister(&ssam_base_hub_driver);
- -err_base:
- - platform_driver_unregister(&ssam_platform_hub_driver);
- -err_platform:
- - return status;
- -}
- -module_init(ssam_device_hub_init);
- -
- -static void __exit ssam_device_hub_exit(void)
- -{
- - ssam_device_driver_unregister(&ssam_kip_hub_driver);
- - ssam_device_driver_unregister(&ssam_base_hub_driver);
- - platform_driver_unregister(&ssam_platform_hub_driver);
- -}
- -module_exit(ssam_device_hub_exit);
- +module_platform_driver(ssam_platform_hub_driver);
-
- MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
- MODULE_DESCRIPTION("Device-registry for Surface System Aggregator Module");
- --
- 2.37.3
- From d55decce43e8eecfdcf95a8830a741c59e5196e5 Mon Sep 17 00:00:00 2001
- From: Maximilian Luz <luzmaximilian@gmail.com>
- Date: Fri, 24 Jun 2022 22:58:00 +0200
- Subject: [PATCH] platform/surface: Update copyright year of various drivers
- Update the copyright of various Surface drivers to the current year.
- Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
- Link: https://lore.kernel.org/r/20220624205800.1355621-4-luzmaximilian@gmail.com
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
- Signed-off-by: Hans de Goede <hdegoede@redhat.com>
- Patchset: surface-sam
- ---
- drivers/platform/surface/aggregator/Kconfig | 2 +-
- drivers/platform/surface/aggregator/Makefile | 2 +-
- drivers/platform/surface/aggregator/bus.c | 2 +-
- drivers/platform/surface/aggregator/bus.h | 2 +-
- drivers/platform/surface/aggregator/controller.c | 2 +-
- drivers/platform/surface/aggregator/controller.h | 2 +-
- drivers/platform/surface/aggregator/core.c | 2 +-
- drivers/platform/surface/aggregator/ssh_msgb.h | 2 +-
- drivers/platform/surface/aggregator/ssh_packet_layer.c | 2 +-
- drivers/platform/surface/aggregator/ssh_packet_layer.h | 2 +-
- drivers/platform/surface/aggregator/ssh_parser.c | 2 +-
- drivers/platform/surface/aggregator/ssh_parser.h | 2 +-
- drivers/platform/surface/aggregator/ssh_request_layer.c | 2 +-
- drivers/platform/surface/aggregator/ssh_request_layer.h | 2 +-
- drivers/platform/surface/aggregator/trace.h | 2 +-
- drivers/platform/surface/surface_acpi_notify.c | 2 +-
- drivers/platform/surface/surface_aggregator_cdev.c | 2 +-
- drivers/platform/surface/surface_aggregator_registry.c | 2 +-
- drivers/platform/surface/surface_dtx.c | 2 +-
- drivers/platform/surface/surface_gpe.c | 2 +-
- drivers/platform/surface/surface_hotplug.c | 2 +-
- drivers/platform/surface/surface_platform_profile.c | 2 +-
- 22 files changed, 22 insertions(+), 22 deletions(-)
- diff --git a/drivers/platform/surface/aggregator/Kconfig b/drivers/platform/surface/aggregator/Kconfig
- index cab020324256..c114f9dd5fe1 100644
- --- a/drivers/platform/surface/aggregator/Kconfig
- +++ b/drivers/platform/surface/aggregator/Kconfig
- @@ -1,5 +1,5 @@
- # SPDX-License-Identifier: GPL-2.0+
- -# Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
- +# Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
-
- menuconfig SURFACE_AGGREGATOR
- tristate "Microsoft Surface System Aggregator Module Subsystem and Drivers"
- diff --git a/drivers/platform/surface/aggregator/Makefile b/drivers/platform/surface/aggregator/Makefile
- index c0d550eda5cd..fdf664a217f9 100644
- --- a/drivers/platform/surface/aggregator/Makefile
- +++ b/drivers/platform/surface/aggregator/Makefile
- @@ -1,5 +1,5 @@
- # SPDX-License-Identifier: GPL-2.0+
- -# Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
- +# Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
-
- # For include/trace/define_trace.h to include trace.h
- CFLAGS_core.o = -I$(src)
- diff --git a/drivers/platform/surface/aggregator/bus.c b/drivers/platform/surface/aggregator/bus.c
- index e0b0381a2834..de539938896e 100644
- --- a/drivers/platform/surface/aggregator/bus.c
- +++ b/drivers/platform/surface/aggregator/bus.c
- @@ -2,7 +2,7 @@
- /*
- * Surface System Aggregator Module bus and device integration.
- *
- - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
- + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
- */
-
- #include <linux/device.h>
- diff --git a/drivers/platform/surface/aggregator/bus.h b/drivers/platform/surface/aggregator/bus.h
- index 6964ee84e79c..5b4dbf21906c 100644
- --- a/drivers/platform/surface/aggregator/bus.h
- +++ b/drivers/platform/surface/aggregator/bus.h
- @@ -2,7 +2,7 @@
- /*
- * Surface System Aggregator Module bus and device integration.
- *
- - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
- + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
- */
-
- #ifndef _SURFACE_AGGREGATOR_BUS_H
- diff --git a/drivers/platform/surface/aggregator/controller.c b/drivers/platform/surface/aggregator/controller.c
- index 6de834b52b63..43e765199137 100644
- --- a/drivers/platform/surface/aggregator/controller.c
- +++ b/drivers/platform/surface/aggregator/controller.c
- @@ -2,7 +2,7 @@
- /*
- * Main SSAM/SSH controller structure and functionality.
- *
- - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
- + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
- */
-
- #include <linux/acpi.h>
- diff --git a/drivers/platform/surface/aggregator/controller.h b/drivers/platform/surface/aggregator/controller.h
- index a0963c3562ff..f0d987abc51e 100644
- --- a/drivers/platform/surface/aggregator/controller.h
- +++ b/drivers/platform/surface/aggregator/controller.h
- @@ -2,7 +2,7 @@
- /*
- * Main SSAM/SSH controller structure and functionality.
- *
- - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
- + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
- */
-
- #ifndef _SURFACE_AGGREGATOR_CONTROLLER_H
- diff --git a/drivers/platform/surface/aggregator/core.c b/drivers/platform/surface/aggregator/core.c
- index a62c5dfe42d6..1a6373dea109 100644
- --- a/drivers/platform/surface/aggregator/core.c
- +++ b/drivers/platform/surface/aggregator/core.c
- @@ -7,7 +7,7 @@
- * Handles communication via requests as well as enabling, disabling, and
- * relaying of events.
- *
- - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
- + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
- */
-
- #include <linux/acpi.h>
- diff --git a/drivers/platform/surface/aggregator/ssh_msgb.h b/drivers/platform/surface/aggregator/ssh_msgb.h
- index e562958ffdf0..f3ecad92eefd 100644
- --- a/drivers/platform/surface/aggregator/ssh_msgb.h
- +++ b/drivers/platform/surface/aggregator/ssh_msgb.h
- @@ -2,7 +2,7 @@
- /*
- * SSH message builder functions.
- *
- - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
- + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
- */
-
- #ifndef _SURFACE_AGGREGATOR_SSH_MSGB_H
- diff --git a/drivers/platform/surface/aggregator/ssh_packet_layer.c b/drivers/platform/surface/aggregator/ssh_packet_layer.c
- index 8a4451c1ffe5..6748fe4ac5d5 100644
- --- a/drivers/platform/surface/aggregator/ssh_packet_layer.c
- +++ b/drivers/platform/surface/aggregator/ssh_packet_layer.c
- @@ -2,7 +2,7 @@
- /*
- * SSH packet transport layer.
- *
- - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
- + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
- */
-
- #include <asm/unaligned.h>
- diff --git a/drivers/platform/surface/aggregator/ssh_packet_layer.h b/drivers/platform/surface/aggregator/ssh_packet_layer.h
- index 2eb329f0b91a..64633522f971 100644
- --- a/drivers/platform/surface/aggregator/ssh_packet_layer.h
- +++ b/drivers/platform/surface/aggregator/ssh_packet_layer.h
- @@ -2,7 +2,7 @@
- /*
- * SSH packet transport layer.
- *
- - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
- + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
- */
-
- #ifndef _SURFACE_AGGREGATOR_SSH_PACKET_LAYER_H
- diff --git a/drivers/platform/surface/aggregator/ssh_parser.c b/drivers/platform/surface/aggregator/ssh_parser.c
- index b77912f8f13b..a6f668694365 100644
- --- a/drivers/platform/surface/aggregator/ssh_parser.c
- +++ b/drivers/platform/surface/aggregator/ssh_parser.c
- @@ -2,7 +2,7 @@
- /*
- * SSH message parser.
- *
- - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
- + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
- */
-
- #include <asm/unaligned.h>
- diff --git a/drivers/platform/surface/aggregator/ssh_parser.h b/drivers/platform/surface/aggregator/ssh_parser.h
- index 3bd6e180fd16..801d8fa69fb5 100644
- --- a/drivers/platform/surface/aggregator/ssh_parser.h
- +++ b/drivers/platform/surface/aggregator/ssh_parser.h
- @@ -2,7 +2,7 @@
- /*
- * SSH message parser.
- *
- - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
- + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
- */
-
- #ifndef _SURFACE_AGGREGATOR_SSH_PARSER_H
- diff --git a/drivers/platform/surface/aggregator/ssh_request_layer.c b/drivers/platform/surface/aggregator/ssh_request_layer.c
- index 790f7f0eee98..f5565570f16c 100644
- --- a/drivers/platform/surface/aggregator/ssh_request_layer.c
- +++ b/drivers/platform/surface/aggregator/ssh_request_layer.c
- @@ -2,7 +2,7 @@
- /*
- * SSH request transport layer.
- *
- - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
- + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
- */
-
- #include <asm/unaligned.h>
- diff --git a/drivers/platform/surface/aggregator/ssh_request_layer.h b/drivers/platform/surface/aggregator/ssh_request_layer.h
- index 9c3cbae2d4bd..4e387a031351 100644
- --- a/drivers/platform/surface/aggregator/ssh_request_layer.h
- +++ b/drivers/platform/surface/aggregator/ssh_request_layer.h
- @@ -2,7 +2,7 @@
- /*
- * SSH request transport layer.
- *
- - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
- + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
- */
-
- #ifndef _SURFACE_AGGREGATOR_SSH_REQUEST_LAYER_H
- diff --git a/drivers/platform/surface/aggregator/trace.h b/drivers/platform/surface/aggregator/trace.h
- index cc9e73fbc18e..2a2c17771d01 100644
- --- a/drivers/platform/surface/aggregator/trace.h
- +++ b/drivers/platform/surface/aggregator/trace.h
- @@ -2,7 +2,7 @@
- /*
- * Trace points for SSAM/SSH.
- *
- - * Copyright (C) 2020-2021 Maximilian Luz <luzmaximilian@gmail.com>
- + * Copyright (C) 2020-2022 Maximilian Luz <luzmaximilian@gmail.com>
- */
-
- #undef TRACE_SYSTEM
- diff --git a/drivers/platform/surface/surface_acpi_notify.c b/drivers/platform/surface/surface_acpi_notify.c
- index c0e12f0b9b79..44e317970557 100644
- --- a/drivers/platform/surface/surface_acpi_notify.c
- +++ b/drivers/platform/surface/surface_acpi_notify.c
- @@ -8,7 +8,7 @@
- * notifications sent from ACPI via the SAN interface by providing them to any
- * registered external driver.
- *
- - * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
- + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
- */
-
- #include <asm/unaligned.h>
- diff --git a/drivers/platform/surface/surface_aggregator_cdev.c b/drivers/platform/surface/surface_aggregator_cdev.c
- index 30fb50fde450..492c82e69182 100644
- --- a/drivers/platform/surface/surface_aggregator_cdev.c
- +++ b/drivers/platform/surface/surface_aggregator_cdev.c
- @@ -3,7 +3,7 @@
- * Provides user-space access to the SSAM EC via the /dev/surface/aggregator
- * misc device. Intended for debugging and development.
- *
- - * Copyright (C) 2020-2021 Maximilian Luz <luzmaximilian@gmail.com>
- + * Copyright (C) 2020-2022 Maximilian Luz <luzmaximilian@gmail.com>
- */
-
- #include <linux/fs.h>
- diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
- index 0cbb7f3a6b2d..d5655f6a4a41 100644
- --- a/drivers/platform/surface/surface_aggregator_registry.c
- +++ b/drivers/platform/surface/surface_aggregator_registry.c
- @@ -6,7 +6,7 @@
- * cannot be auto-detected. Provides device-hubs and performs instantiation
- * for these devices.
- *
- - * Copyright (C) 2020-2021 Maximilian Luz <luzmaximilian@gmail.com>
- + * Copyright (C) 2020-2022 Maximilian Luz <luzmaximilian@gmail.com>
- */
-
- #include <linux/acpi.h>
- diff --git a/drivers/platform/surface/surface_dtx.c b/drivers/platform/surface/surface_dtx.c
- index 1203b9a82993..ed36944467f9 100644
- --- a/drivers/platform/surface/surface_dtx.c
- +++ b/drivers/platform/surface/surface_dtx.c
- @@ -8,7 +8,7 @@
- * acknowledge (to speed things up), abort (e.g. in case the dGPU is still in
- * use), or request detachment via user-space.
- *
- - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
- + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
- */
-
- #include <linux/fs.h>
- diff --git a/drivers/platform/surface/surface_gpe.c b/drivers/platform/surface/surface_gpe.c
- index ec66fde28e75..27365cbe1ee9 100644
- --- a/drivers/platform/surface/surface_gpe.c
- +++ b/drivers/platform/surface/surface_gpe.c
- @@ -4,7 +4,7 @@
- * properly configuring the respective GPEs. Required for wakeup via lid on
- * newer Intel-based Microsoft Surface devices.
- *
- - * Copyright (C) 2020 Maximilian Luz <luzmaximilian@gmail.com>
- + * Copyright (C) 2020-2022 Maximilian Luz <luzmaximilian@gmail.com>
- */
-
- #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
- diff --git a/drivers/platform/surface/surface_hotplug.c b/drivers/platform/surface/surface_hotplug.c
- index cfcc15cfbacb..f004a2495201 100644
- --- a/drivers/platform/surface/surface_hotplug.c
- +++ b/drivers/platform/surface/surface_hotplug.c
- @@ -10,7 +10,7 @@
- * Event signaling is handled via ACPI, which will generate the appropriate
- * device-check notifications to be picked up by the PCIe hot-plug driver.
- *
- - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
- + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
- */
-
- #include <linux/acpi.h>
- diff --git a/drivers/platform/surface/surface_platform_profile.c b/drivers/platform/surface/surface_platform_profile.c
- index 6373d3b5eb7f..fbf2e11fd6ce 100644
- --- a/drivers/platform/surface/surface_platform_profile.c
- +++ b/drivers/platform/surface/surface_platform_profile.c
- @@ -3,7 +3,7 @@
- * Surface Platform Profile / Performance Mode driver for Surface System
- * Aggregator Module (thermal subsystem).
- *
- - * Copyright (C) 2021 Maximilian Luz <luzmaximilian@gmail.com>
- + * Copyright (C) 2021-2022 Maximilian Luz <luzmaximilian@gmail.com>
- */
-
- #include <asm/unaligned.h>
- --
- 2.37.3
- From 686174233840652bc5404c84c5fb7d596f640ddf Mon Sep 17 00:00:00 2001
- From: Lukas Bulwahn <lukas.bulwahn@gmail.com>
- Date: Wed, 13 Jul 2022 06:09:16 +0200
- Subject: [PATCH] MAINTAINERS: repair file entry in MICROSOFT SURFACE
- AGGREGATOR TABLET-MODE SWITCH
- Commit 9f794056db5b ("platform/surface: Add KIP/POS tablet-mode switch
- driver") adds the section MICROSOFT SURFACE AGGREGATOR TABLET-MODE SWITCH
- with a file entry, but the file that is added with this commit is actually
- named slightly differently.
- file entry name: drivers/platform/surface/surface_aggregator_tablet_switch.c
- added file name: drivers/platform/surface/surface_aggregator_tabletsw.c
- Hence, ./scripts/get_maintainer.pl --self-test=patterns complains about a
- broken reference.
- Repair this file entry to the actual file name added with the commit above.
- Fixes: 9f794056db5b ("platform/surface: Add KIP/POS tablet-mode switch driver")
- Signed-off-by: Lukas Bulwahn <lukas.bulwahn@gmail.com>
- Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
- Reviewed-by: Maximilian Luz <luzmaximilian@gmail.com>
- Link: https://lore.kernel.org/r/20220713040916.1767-1-lukas.bulwahn@gmail.com
- Signed-off-by: Hans de Goede <hdegoede@redhat.com>
- Patchset: surface-sam
- ---
- MAINTAINERS | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
- diff --git a/MAINTAINERS b/MAINTAINERS
- index 55e80354a097..6772c9d0eccc 100644
- --- a/MAINTAINERS
- +++ b/MAINTAINERS
- @@ -13303,7 +13303,7 @@ MICROSOFT SURFACE AGGREGATOR TABLET-MODE SWITCH
- M: Maximilian Luz <luzmaximilian@gmail.com>
- L: platform-driver-x86@vger.kernel.org
- S: Maintained
- -F: drivers/platform/surface/surface_aggregator_tablet_switch.c
- +F: drivers/platform/surface/surface_aggregator_tabletsw.c
-
- MICROSOFT SURFACE BATTERY AND AC DRIVERS
- M: Maximilian Luz <luzmaximilian@gmail.com>
- --
- 2.37.3
- From 53978e1cf5a26a0482ecc4f6520051e56f8523ae Mon Sep 17 00:00:00 2001
- From: Maximilian Luz <luzmaximilian@gmail.com>
- Date: Sun, 17 Jul 2022 14:07:35 +0200
- Subject: [PATCH] platform/surface: tabletsw: Fix __le32 integer access
- The sources.count field is a __le32 inside a packed struct. So use the
- proper functions to access it.
- Reported-by: kernel test robot <lkp@intel.com>
- Fixes: 9f794056db5b ("platform/surface: Add KIP/POS tablet-mode switch driver")
- Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
- Link: https://lore.kernel.org/r/20220717120735.2052160-1-luzmaximilian@gmail.com
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
- Signed-off-by: Hans de Goede <hdegoede@redhat.com>
- Patchset: surface-sam
- ---
- drivers/platform/surface/surface_aggregator_tabletsw.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
- diff --git a/drivers/platform/surface/surface_aggregator_tabletsw.c b/drivers/platform/surface/surface_aggregator_tabletsw.c
- index 596ca6c80681..27d95a6a7851 100644
- --- a/drivers/platform/surface/surface_aggregator_tabletsw.c
- +++ b/drivers/platform/surface/surface_aggregator_tabletsw.c
- @@ -410,7 +410,7 @@ static int ssam_pos_get_source(struct ssam_tablet_sw *sw, u32 *source_id)
- if (status)
- return status;
-
- - if (sources.count == 0) {
- + if (get_unaligned_le32(&sources.count) == 0) {
- dev_err(&sw->sdev->dev, "no posture sources found\n");
- return -ENODEV;
- }
- @@ -422,7 +422,7 @@ static int ssam_pos_get_source(struct ssam_tablet_sw *sw, u32 *source_id)
- * is a device that provides multiple sources, at which point we can
- * then try to figure out how to handle them.
- */
- - WARN_ON(sources.count > 1);
- + WARN_ON(get_unaligned_le32(&sources.count) > 1);
-
- *source_id = get_unaligned_le32(&sources.id[0]);
- return 0;
- --
- 2.37.3
- From 275b1eaec4c63b3a3ca011127cde06ce260be865 Mon Sep 17 00:00:00 2001
- From: Maximilian Luz <luzmaximilian@gmail.com>
- Date: Fri, 8 Jul 2022 03:34:44 +0200
- Subject: [PATCH] platform/surface: aggregator_registry: Add support for
- Surface Laptop Go 2
- The Surface Laptop Go 2 seems to have the same SAM client devices as the
- Surface Laptop Go 1, so re-use its node group.
- Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
- Patchset: surface-sam
- ---
- drivers/platform/surface/surface_aggregator_registry.c | 3 +++
- 1 file changed, 3 insertions(+)
- diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
- index d5655f6a4a41..93ab62eb393d 100644
- --- a/drivers/platform/surface/surface_aggregator_registry.c
- +++ b/drivers/platform/surface/surface_aggregator_registry.c
- @@ -325,6 +325,9 @@ static const struct acpi_device_id ssam_platform_hub_match[] = {
- /* Surface Laptop Go 1 */
- { "MSHW0118", (unsigned long)ssam_node_group_slg1 },
-
- + /* Surface Laptop Go 2 */
- + { "MSHW0290", (unsigned long)ssam_node_group_slg1 },
- +
- /* Surface Laptop Studio */
- { "MSHW0123", (unsigned long)ssam_node_group_sls },
-
- --
- 2.37.3
- From 9556175a48aefe4c379d7263250d8e83c1f4083a Mon Sep 17 00:00:00 2001
- From: Maximilian Luz <luzmaximilian@gmail.com>
- Date: Sat, 25 Jun 2022 20:42:00 +0200
- Subject: [PATCH] platform/surface: aggregator_registry: Rename HID device
- nodes based on their function
- Rename HID device nodes based on their function. In particular, these
- are nodes for firmware updates via the CFU mechanism (component firmware
- update), HID based sensors, and a USB-C UCSI client.
- Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
- Patchset: surface-sam
- ---
- .../surface/surface_aggregator_registry.c | 18 +++++++++---------
- 1 file changed, 9 insertions(+), 9 deletions(-)
- diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
- index 93ab62eb393d..7d82398f55b1 100644
- --- a/drivers/platform/surface/surface_aggregator_registry.c
- +++ b/drivers/platform/surface/surface_aggregator_registry.c
- @@ -104,14 +104,14 @@ static const struct software_node ssam_node_hid_tid1_touchpad = {
- .parent = &ssam_node_root,
- };
-
- -/* HID device instance 6 (TID1, unknown HID device). */
- -static const struct software_node ssam_node_hid_tid1_iid6 = {
- +/* HID device instance 6 (TID1, HID sensor collection). */
- +static const struct software_node ssam_node_hid_tid1_sensors = {
- .name = "ssam:01:15:01:06:00",
- .parent = &ssam_node_root,
- };
-
- -/* HID device instance 7 (TID1, unknown HID device). */
- -static const struct software_node ssam_node_hid_tid1_iid7 = {
- +/* HID device instance 7 (TID1, UCM UCSI HID client). */
- +static const struct software_node ssam_node_hid_tid1_ucm_ucsi = {
- .name = "ssam:01:15:01:07:00",
- .parent = &ssam_node_root,
- };
- @@ -182,8 +182,8 @@ static const struct software_node ssam_node_hid_kip_touchpad = {
- .parent = &ssam_node_hub_kip,
- };
-
- -/* HID device instance 5 (KIP hub, unknown HID device). */
- -static const struct software_node ssam_node_hid_kip_iid5 = {
- +/* HID device instance 5 (KIP hub, type-cover firmware update). */
- +static const struct software_node ssam_node_hid_kip_fwupd = {
- .name = "ssam:01:15:02:05:00",
- .parent = &ssam_node_hub_kip,
- };
- @@ -244,8 +244,8 @@ static const struct software_node *ssam_node_group_sls[] = {
- &ssam_node_hid_tid1_keyboard,
- &ssam_node_hid_tid1_penstash,
- &ssam_node_hid_tid1_touchpad,
- - &ssam_node_hid_tid1_iid6,
- - &ssam_node_hid_tid1_iid7,
- + &ssam_node_hid_tid1_sensors,
- + &ssam_node_hid_tid1_ucm_ucsi,
- &ssam_node_hid_tid1_sysctrl,
- NULL,
- };
- @@ -278,7 +278,7 @@ static const struct software_node *ssam_node_group_sp8[] = {
- &ssam_node_hid_kip_keyboard,
- &ssam_node_hid_kip_penstash,
- &ssam_node_hid_kip_touchpad,
- - &ssam_node_hid_kip_iid5,
- + &ssam_node_hid_kip_fwupd,
- NULL,
- };
-
- --
- 2.37.3
- From d4657223326239c2d5f6fe1be0c4ce0425420904 Mon Sep 17 00:00:00 2001
- From: Maximilian Luz <luzmaximilian@gmail.com>
- Date: Sat, 25 Jun 2022 20:52:47 +0200
- Subject: [PATCH] platform/surface: aggregator_registry: Rename HID device
- nodes based on new findings
- On Windows, the HID devices with target ID 1 are grouped as "Surface Hot
- Plug - SAM". Rename their device nodes in the registry to reflect that
- and update the comments accordingly.
- Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
- Patchset: surface-sam
- ---
- .../surface/surface_aggregator_registry.c | 36 +++++++++----------
- 1 file changed, 18 insertions(+), 18 deletions(-)
- diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
- index 7d82398f55b1..9970f89b1411 100644
- --- a/drivers/platform/surface/surface_aggregator_registry.c
- +++ b/drivers/platform/surface/surface_aggregator_registry.c
- @@ -86,38 +86,38 @@ static const struct software_node ssam_node_bas_dtx = {
- .parent = &ssam_node_root,
- };
-
- -/* HID keyboard (TID1). */
- -static const struct software_node ssam_node_hid_tid1_keyboard = {
- +/* HID keyboard (SAM, TID=1). */
- +static const struct software_node ssam_node_hid_sam_keyboard = {
- .name = "ssam:01:15:01:01:00",
- .parent = &ssam_node_root,
- };
-
- -/* HID pen stash (TID1; pen taken / stashed away evens). */
- -static const struct software_node ssam_node_hid_tid1_penstash = {
- +/* HID pen stash (SAM, TID=1; pen taken / stashed away evens). */
- +static const struct software_node ssam_node_hid_sam_penstash = {
- .name = "ssam:01:15:01:02:00",
- .parent = &ssam_node_root,
- };
-
- -/* HID touchpad (TID1). */
- -static const struct software_node ssam_node_hid_tid1_touchpad = {
- +/* HID touchpad (SAM, TID=1). */
- +static const struct software_node ssam_node_hid_sam_touchpad = {
- .name = "ssam:01:15:01:03:00",
- .parent = &ssam_node_root,
- };
-
- -/* HID device instance 6 (TID1, HID sensor collection). */
- -static const struct software_node ssam_node_hid_tid1_sensors = {
- +/* HID device instance 6 (SAM, TID=1, HID sensor collection). */
- +static const struct software_node ssam_node_hid_sam_sensors = {
- .name = "ssam:01:15:01:06:00",
- .parent = &ssam_node_root,
- };
-
- -/* HID device instance 7 (TID1, UCM UCSI HID client). */
- -static const struct software_node ssam_node_hid_tid1_ucm_ucsi = {
- +/* HID device instance 7 (SAM, TID=1, UCM UCSI HID client). */
- +static const struct software_node ssam_node_hid_sam_ucm_ucsi = {
- .name = "ssam:01:15:01:07:00",
- .parent = &ssam_node_root,
- };
-
- -/* HID system controls (TID1). */
- -static const struct software_node ssam_node_hid_tid1_sysctrl = {
- +/* HID system controls (SAM, TID=1). */
- +static const struct software_node ssam_node_hid_sam_sysctrl = {
- .name = "ssam:01:15:01:08:00",
- .parent = &ssam_node_root,
- };
- @@ -241,12 +241,12 @@ static const struct software_node *ssam_node_group_sls[] = {
- &ssam_node_bat_main,
- &ssam_node_tmp_pprof,
- &ssam_node_pos_tablet_switch,
- - &ssam_node_hid_tid1_keyboard,
- - &ssam_node_hid_tid1_penstash,
- - &ssam_node_hid_tid1_touchpad,
- - &ssam_node_hid_tid1_sensors,
- - &ssam_node_hid_tid1_ucm_ucsi,
- - &ssam_node_hid_tid1_sysctrl,
- + &ssam_node_hid_sam_keyboard,
- + &ssam_node_hid_sam_penstash,
- + &ssam_node_hid_sam_touchpad,
- + &ssam_node_hid_sam_sensors,
- + &ssam_node_hid_sam_ucm_ucsi,
- + &ssam_node_hid_sam_sysctrl,
- NULL,
- };
-
- --
- 2.37.3
- From 0d68c4c4dfc57ce02438d26fd9240ced2ea1fcd0 Mon Sep 17 00:00:00 2001
- From: Maximilian Luz <luzmaximilian@gmail.com>
- Date: Sat, 25 Jun 2022 20:54:59 +0200
- Subject: [PATCH] platform/surface: aggregator_registry: Add HID devices for
- sensors and UCSI client to SP8
- Add software nodes for the HID sensor collection and the UCM UCSI HID
- client to the Surface Pro 8. In contrast to the type-cover devices,
- these devices are directly attached to the SAM controller, without any
- hub.
- This enables support for HID-based sensors, including the ones used for
- automatic screen rotation, on the Surface Pro 8.
- Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
- Patchset: surface-sam
- ---
- drivers/platform/surface/surface_aggregator_registry.c | 2 ++
- 1 file changed, 2 insertions(+)
- diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
- index 9970f89b1411..585911020cea 100644
- --- a/drivers/platform/surface/surface_aggregator_registry.c
- +++ b/drivers/platform/surface/surface_aggregator_registry.c
- @@ -279,6 +279,8 @@ static const struct software_node *ssam_node_group_sp8[] = {
- &ssam_node_hid_kip_penstash,
- &ssam_node_hid_kip_touchpad,
- &ssam_node_hid_kip_fwupd,
- + &ssam_node_hid_sam_sensors,
- + &ssam_node_hid_sam_ucm_ucsi,
- NULL,
- };
-
- --
- 2.37.3
|