@@ -633,11 +633,120 @@ dpll_pin_set_from_nlattr(struct dpll_pin *pin, struct genl_info *info)
633633 return 0 ;
634634}
635635
636- int dpll_nl_pin_set_doit (struct sk_buff * skb , struct genl_info * info )
636+ static struct dpll_pin *
637+ dpll_pin_find (u64 clock_id , struct nlattr * mod_name_attr ,
638+ enum dpll_pin_type type , struct nlattr * board_label ,
639+ struct nlattr * panel_label , struct nlattr * package_label )
637640{
638- struct dpll_pin * pin = info -> user_ptr [0 ];
641+ bool board_match , panel_match , package_match ;
642+ struct dpll_pin * pin_match = NULL , * pin ;
643+ bool cid_match , mod_match , type_match ;
644+ unsigned long i ;
639645
640- return dpll_pin_set_from_nlattr (pin , info );
646+ xa_for_each (& dpll_pin_xa , i , pin ) {
647+ if (xa_empty (& pin -> dpll_refs ))
648+ continue ;
649+ cid_match = clock_id ? pin -> clock_id == clock_id : true;
650+ mod_match = mod_name_attr ?
651+ !nla_strcmp (mod_name_attr , pin -> module -> name ) : true;
652+ type_match = type ? pin -> prop .type == type : true;
653+ board_match = board_label && pin -> prop .board_label ?
654+ !nla_strcmp (board_label , pin -> prop .board_label ) : true;
655+ panel_match = panel_label && pin -> prop .panel_label ?
656+ !nla_strcmp (panel_label , pin -> prop .panel_label ) : true;
657+ package_match = package_label && pin -> prop .package_label ?
658+ !nla_strcmp (package_label ,
659+ pin -> prop .package_label ) : true;
660+ if (cid_match && mod_match && type_match && board_match &&
661+ panel_match && package_match ) {
662+ if (pin_match )
663+ return NULL ;
664+ pin_match = pin ;
665+ };
666+ }
667+
668+ return pin_match ;
669+ }
670+
671+ static int
672+ dpll_pin_find_from_nlattr (struct genl_info * info , struct sk_buff * skb )
673+ {
674+ struct nlattr * attr , * mod_name_attr = NULL , * board_label_attr = NULL ,
675+ * panel_label_attr = NULL , * package_label_attr = NULL ;
676+ struct dpll_pin * pin = NULL ;
677+ enum dpll_pin_type type = 0 ;
678+ u64 clock_id = 0 ;
679+ int rem = 0 ;
680+
681+ nla_for_each_attr (attr , genlmsg_data (info -> genlhdr ),
682+ genlmsg_len (info -> genlhdr ), rem ) {
683+ switch (nla_type (attr )) {
684+ case DPLL_A_CLOCK_ID :
685+ if (clock_id )
686+ return - EINVAL ;
687+ clock_id = nla_get_u64 (attr );
688+ break ;
689+ case DPLL_A_MODULE_NAME :
690+ if (mod_name_attr )
691+ return - EINVAL ;
692+ mod_name_attr = attr ;
693+ break ;
694+ case DPLL_A_PIN_TYPE :
695+ if (type )
696+ return - EINVAL ;
697+ type = nla_get_u8 (attr );
698+ break ;
699+ case DPLL_A_PIN_BOARD_LABEL :
700+ if (board_label_attr )
701+ return - EINVAL ;
702+ board_label_attr = attr ;
703+ break ;
704+ case DPLL_A_PIN_PANEL_LABEL :
705+ if (panel_label_attr )
706+ return - EINVAL ;
707+ panel_label_attr = attr ;
708+ break ;
709+ case DPLL_A_PIN_PACKAGE_LABEL :
710+ if (package_label_attr )
711+ return - EINVAL ;
712+ package_label_attr = attr ;
713+ break ;
714+ default :
715+ break ;
716+ }
717+ }
718+ if (!(clock_id || mod_name_attr || board_label_attr ||
719+ panel_label_attr || package_label_attr ))
720+ return - EINVAL ;
721+ pin = dpll_pin_find (clock_id , mod_name_attr , type , board_label_attr ,
722+ panel_label_attr , package_label_attr );
723+ if (!pin )
724+ return - EINVAL ;
725+ return dpll_msg_add_pin_handle (skb , pin );
726+ }
727+
728+ int dpll_nl_pin_id_get_doit (struct sk_buff * skb , struct genl_info * info )
729+ {
730+ struct sk_buff * msg ;
731+ struct nlattr * hdr ;
732+ int ret ;
733+
734+ msg = genlmsg_new (NLMSG_GOODSIZE , GFP_KERNEL );
735+ if (!msg )
736+ return - ENOMEM ;
737+ hdr = genlmsg_put_reply (msg , info , & dpll_nl_family , 0 ,
738+ DPLL_CMD_PIN_ID_GET );
739+ if (!hdr )
740+ return - EMSGSIZE ;
741+
742+ ret = dpll_pin_find_from_nlattr (info , msg );
743+ if (ret ) {
744+ nlmsg_free (msg );
745+ return ret ;
746+ }
747+ genlmsg_end (msg , hdr );
748+
749+ return genlmsg_reply (msg , info );
641750}
642751
643752int dpll_nl_pin_get_doit (struct sk_buff * skb , struct genl_info * info )
@@ -699,6 +808,77 @@ int dpll_nl_pin_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
699808 return ret ;
700809}
701810
811+ int dpll_nl_pin_set_doit (struct sk_buff * skb , struct genl_info * info )
812+ {
813+ struct dpll_pin * pin = info -> user_ptr [0 ];
814+
815+ return dpll_pin_set_from_nlattr (pin , info );
816+ }
817+
818+ static struct dpll_device *
819+ dpll_device_find (u64 clock_id , struct nlattr * mod_name_attr ,
820+ enum dpll_type type )
821+ {
822+ struct dpll_device * dpll_match = NULL , * dpll ;
823+ bool cid_match , mod_match , type_match ;
824+ unsigned long i ;
825+
826+ xa_for_each_marked (& dpll_device_xa , i , dpll , DPLL_REGISTERED ) {
827+ cid_match = clock_id ? dpll -> clock_id == clock_id : true;
828+ mod_match = mod_name_attr ?
829+ !nla_strcmp (mod_name_attr , dpll -> module -> name ) : true;
830+ type_match = type ? dpll -> type == type : true;
831+ if (cid_match && mod_match && type_match ) {
832+ if (dpll_match )
833+ return NULL ;
834+ dpll_match = dpll ;
835+ }
836+ }
837+
838+ return dpll_match ;
839+ }
840+
841+ static int
842+ dpll_device_find_from_nlattr (struct genl_info * info , struct sk_buff * skb )
843+ {
844+ struct nlattr * attr , * mod_name_attr = NULL ;
845+ struct dpll_device * dpll = NULL ;
846+ enum dpll_type type = 0 ;
847+ u64 clock_id = 0 ;
848+ int rem = 0 ;
849+
850+ nla_for_each_attr (attr , genlmsg_data (info -> genlhdr ),
851+ genlmsg_len (info -> genlhdr ), rem ) {
852+ switch (nla_type (attr )) {
853+ case DPLL_A_CLOCK_ID :
854+ if (clock_id )
855+ return - EINVAL ;
856+ clock_id = nla_get_u64 (attr );
857+ break ;
858+ case DPLL_A_MODULE_NAME :
859+ if (mod_name_attr )
860+ return - EINVAL ;
861+ mod_name_attr = attr ;
862+ break ;
863+ case DPLL_A_TYPE :
864+ if (type )
865+ return - EINVAL ;
866+ type = nla_get_u8 (attr );
867+ break ;
868+ default :
869+ break ;
870+ }
871+ }
872+
873+ if (!clock_id && !mod_name_attr && !type )
874+ return - EINVAL ;
875+ dpll = dpll_device_find (clock_id , mod_name_attr , type );
876+ if (!dpll )
877+ return - EINVAL ;
878+
879+ return dpll_msg_add_dev_handle (skb , dpll );
880+ }
881+
702882static int
703883dpll_set_from_nlattr (struct dpll_device * dpll , struct genl_info * info )
704884{
@@ -726,11 +906,28 @@ dpll_set_from_nlattr(struct dpll_device *dpll, struct genl_info *info)
726906 return ret ;
727907}
728908
729- int dpll_nl_device_set_doit (struct sk_buff * skb , struct genl_info * info )
909+ int dpll_nl_device_id_get_doit (struct sk_buff * skb , struct genl_info * info )
730910{
731- struct dpll_device * dpll = info -> user_ptr [0 ];
911+ struct sk_buff * msg ;
912+ struct nlattr * hdr ;
913+ int ret ;
732914
733- return dpll_set_from_nlattr (dpll , info );
915+ msg = genlmsg_new (NLMSG_GOODSIZE , GFP_KERNEL );
916+ if (!msg )
917+ return - ENOMEM ;
918+ hdr = genlmsg_put_reply (msg , info , & dpll_nl_family , 0 ,
919+ DPLL_CMD_DEVICE_ID_GET );
920+ if (!hdr )
921+ return - EMSGSIZE ;
922+
923+ ret = dpll_device_find_from_nlattr (info , msg );
924+ if (ret ) {
925+ nlmsg_free (msg );
926+ return ret ;
927+ }
928+ genlmsg_end (msg , hdr );
929+
930+ return genlmsg_reply (msg , info );
734931}
735932
736933int dpll_nl_device_get_doit (struct sk_buff * skb , struct genl_info * info )
@@ -758,6 +955,13 @@ int dpll_nl_device_get_doit(struct sk_buff *skb, struct genl_info *info)
758955 return genlmsg_reply (msg , info );
759956}
760957
958+ int dpll_nl_device_set_doit (struct sk_buff * skb , struct genl_info * info )
959+ {
960+ struct dpll_device * dpll = info -> user_ptr [0 ];
961+
962+ return dpll_set_from_nlattr (dpll , info );
963+ }
964+
761965int dpll_nl_device_get_dumpit (struct sk_buff * skb , struct netlink_callback * cb )
762966{
763967 struct dpll_dump_ctx * ctx = dpll_dump_context (cb );
@@ -818,14 +1022,30 @@ void dpll_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
8181022 mutex_unlock (& dpll_xa_lock );
8191023}
8201024
821- int dpll_pre_dumpit (struct netlink_callback * cb )
1025+ int
1026+ dpll_lock_doit (const struct genl_split_ops * ops , struct sk_buff * skb ,
1027+ struct genl_info * info )
8221028{
8231029 mutex_lock (& dpll_xa_lock );
8241030
8251031 return 0 ;
8261032}
8271033
828- int dpll_post_dumpit (struct netlink_callback * cb )
1034+ void
1035+ dpll_unlock_doit (const struct genl_split_ops * ops , struct sk_buff * skb ,
1036+ struct genl_info * info )
1037+ {
1038+ mutex_unlock (& dpll_xa_lock );
1039+ }
1040+
1041+ int dpll_lock_dumpit (struct netlink_callback * cb )
1042+ {
1043+ mutex_lock (& dpll_xa_lock );
1044+
1045+ return 0 ;
1046+ }
1047+
1048+ int dpll_unlock_dumpit (struct netlink_callback * cb )
8291049{
8301050 mutex_unlock (& dpll_xa_lock );
8311051
@@ -862,16 +1082,6 @@ void dpll_pin_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
8621082 mutex_unlock (& dpll_xa_lock );
8631083}
8641084
865- int dpll_pin_pre_dumpit (struct netlink_callback * cb )
866- {
867- return dpll_pre_dumpit (cb );
868- }
869-
870- int dpll_pin_post_dumpit (struct netlink_callback * cb )
871- {
872- return dpll_post_dumpit (cb );
873- }
874-
8751085static int
8761086dpll_device_event_send (enum dpll_cmd event , struct dpll_device * dpll )
8771087{
0 commit comments