Skip to content

Commit 49add4e

Browse files
committed
dpll: core: add device-id-get and pin-id-get commands
Allow user to get id of a device or a pin with dpll netlink interface. It requires to provide arguments which result in a single match, otherwise the -EINVAL is returned. Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
1 parent 55223b7 commit 49add4e

1 file changed

Lines changed: 228 additions & 18 deletions

File tree

drivers/dpll/dpll_netlink.c

Lines changed: 228 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -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

643752
int 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+
702882
static int
703883
dpll_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

736933
int 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+
761965
int 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-
8751085
static int
8761086
dpll_device_event_send(enum dpll_cmd event, struct dpll_device *dpll)
8771087
{

0 commit comments

Comments
 (0)