Hi Cristian, On 26.04.23 14:19, Cristian Marussi wrote: > On Tue, Apr 25, 2023 at 07:51:34PM +0000, Oleksii Moisieiev wrote: >> Hi Cristian, >> >> On 13.04.23 01:04, Cristian Marussi wrote: >> >> On Fri, Apr 07, 2023 at 10:18:27AM +0000, Oleksii Moisieiev wrote: >> >> Implementation of the SCMI client driver, which implements >> PINCTRL_PROTOCOL. This protocol has ID 19 and is described >> in the latest DEN0056 document. >> >> Hi, >> > > Hi Oleksii, > > please do NOT post mail with html on the mailing list, it is very hard to > read and comment while useing text-only mail-reader (and not so much > appreciated :D) ; even readers with an UI can be setup to properly avoid > html stuff and properly format for Kernel upstream work: > > https://urldefense.com/v3/__https://www.kernel.org/doc/html/v4.10/process/email-clients.html__;!!GF_29dbcQIUBPA!w2wEJQrXQbVSfn4q6_Sot9NQhyl_GTC4UNjmHUcubxpIHDt5dPU6emDEkfOvtSSvjjzZR2J-VQDTOovNXDto8RP_FSJatQ$ [kernel[.]org] > > Indeed your original message now cannot even be found on lore, probably > discarded for the same reason ? (not sure). > > My comments inline. > I'm sorry for that. Somehow Thunderbird managed to switch to HTML after update. I've sent v2. >> >> This protocol is part of the feature that was designed to >> separate the pinctrl subsystem from the SCP firmware. >> The idea is to separate communication of the pin control >> subsystem with the hardware to SCP firmware >> (or a similar system, such as ATF), which provides an interface >> to give the OS ability to control the hardware through SCMI protocol. >> This is a generic driver that implements SCMI protocol, >> independent of the platform type. >> >> DEN0056 document: >> [1]https://urldefense.com/v3/__https://developer.arm.com/documentation/den0056/l >> atest__;!!GF_29dbcQIUBPA!wnEVmBR_V-0llnzQFsQfeZq5Ov7xJ87H364gqo1_UvsilzKNfJoy81u >> 5GR1f0EBIyXOGyesjURGdxT_U5tzLvqT5lgjNpw$ [developer[.]arm[.]com] >> >> >> No need to specify all of this in the commit message, just a note that >> you are adding a new SCMIv3.2 Pincontrol protocol, highlighting anything >> that has been left out in this patch (if any) will be enough. >> You can look at the very first commit logs of existing protos as an >> example like: drivers/firmware/arm_scmi/powercap.c >> >> Some more comments down below, I'll mostly skip anything related to the >> SCMI API change I mentioned before... >> >> I'll also wont comment on more trivial stuff related to style, BUT there >> are lots of them: you should run >> >> ./scripts/checkpatch.pl --strict <your-git-format-patch-file> >> >> for each patch in the series. (and fix accordingly..spacing, brackets...etc) >> >> Done. >> >> +static int scmi_pinctrl_list_associations(const struct scmi_handle *handle, > > [snip] > >> + u32 selector, >> + enum scmi_pinctrl_selector_type type, >> + uint16_t size, unsigned int *array) >> +{ >> >> This is the other functionalities you could implement straight away using >> ph->hops helpers (iterators) but just leave it this way, and I'll port it later >> (once we retested all of this as working with the new API but without any >> ph->hops usage..I think it is safer to change one bit at time... :P) >> >> Rewritten using iterators and checked with the unittests. > > Good, thanks. > > [snip] > >> +static int scmi_pinctrl_get_group_info(const struct scmi_handle *handle, >> + u32 selector, >> + struct scmi_group_info *group) >> +{ >> + int ret = 0; >> + struct scmi_pinctrl_info *pi; >> + >> + if (!handle || !handle->pinctrl_priv || !group) >> + return -EINVAL; >> + >> + pi = handle->pinctrl_priv; >> + >> + ret = scmi_pinctrl_attributes(handle, GROUP_TYPE, selector, >> + &group->name, >> + &group->nr_pins); >> + if (ret) >> + return ret; >> + >> + if (!group->nr_pins) { >> + dev_err(handle->dev, "Group %d has 0 elements", selector); >> + return -ENODATA; >> + } >> + >> + group->group_pins = devm_kmalloc_array(handle->dev, group->nr_pins, >> + sizeof(*group->group_pins), >> + GFP_KERNEL); >> >> I think you can just use for the array allocation >> >> devm_kcalloc(dev, n, size, flags) >> >> and it will add also __GFP_ZERO internally to clear it. >> (indeed it calls in turn devm_kmalloc_array) >> >> ...BUT I think there is a further tricky issue here related to memory allocation >> ... >> >> You call this and others function of this kind from some scmi_pinctrl_ops, >> like in scmi_pinctrl_get_group_pins (scmi_pinctrl_ops->get_group_pins), >> and then this is in turn called by the SCMI Pinctrl driver via >> pinctrl_ops->get_group_pins AND you set a present flag so that you issue a >> PINCTRL_LIST_ASSOCIATIONS and allocate here a new group_pins array just >> the first time: but these are never released anywhere, since, even though >> lazily dynamically allocated when asked for, these are static data that >> you pass to the caller/user of this protocol and so you cannot release >> them anytime soon, indeed. >> >> The core SCMI stack usually takes care to track and release all the devm_ >> resources allocated by the protocol ONLY if they were allocated with devres >> while inside scmi_pinctrl_protocol_init() function. >> (see drivers/firmware/arm-scmi/driver.c:scmi_alloc_init_protocol_instance() >> and scmi_protocol_release) >> >> BUT you do not allocate these arrays inside the protocol-init function, >> you allocate them the first time these ops are called at runtime. >> >> If you unbind/unload all the drivers using this protocol and then reload >> them, all the devm_ allocations in protocol_init will be freed and >> reallocated BUT these arrays will never be freed (they are boudn to handle->dev) >> and instead they will be reallocated multiple times (present flag will be cleare >> d >> on unload), remained unused and freed finally only when the whole SCMI stack is >> unbind/unloaded. >> >> You use a present flag to avoid reissuing the same query and >> reallocating all the arrays each time a driver calls these >> protocol_ops one, but really all these data is available early on at >> protocol init time and they are not supposed to change at runtime, dont they ? >> >> Even in a virtualized environment, you boot an agent and the SCMI >> platform server provides to the agent the list of associations when >> queried but then this does not change until the next reboot right ? >> (indeed you do not query more than once...) >> >> The agent can only change the PIN status with CONFIG_SET or >> FUNCTION_SELECT or REQUEST the exclusive use of a pin/group, but it is >> not that the platform can change the pin/groups associaion for the same >> agent at run time, this are static data for the whole life of the agent. >> >> Am I right ? >> >> IOW I think there is some potential memory leak on unbind/bind and it would >> be better to query and allocate all of these resources at init time and keep >> them ready to be retrieved by subsequent operations, since the lifetime >> of these resources is pretty long and they are basically representing >> static data that does not change after the init/probe phases. >> >> Indeed, all the other protocols usually allocate all the needed >> resources and query all the available SCMI resources once for all during >> the protocol_init, storing all the retrieved info in some struct *_info >> exposed in scmi_protocol.h and then provide some related protocol_ops to >> get the number of resources and to retrieve specific domain info descriptors. >> (voltage.c is an example and more on this down below...) >> >> This way, any dynamic allocation is done during protocol_init, so >> it can be automatically freed by the SCMI core once there are no more >> users of that protocol, and all of this static info data is queried >> and retrieved once for all at protocol initialization time, avoiding >> unneeded message exchanges to retrieve always the same data. >> (which you avoid anyway with the present flag) >> >> If you have a good reason to instead perform this sort of lazy >> allocation/query performed only at the last minute when someone ask for >> that specific resource, you will have to provide also a .instance_deinit >> function to clean anything you allocated out of the .instance_init >> routine; but this would seem strange to me since any resource that is >> discovered at init will be eventually immediately queried by a driver >> which uses this protocol...am I missing something ? >> >> >> This is a good point. But there is some reason why I've made such lazy >> allocations: >> >> I agree that we have all data on the early stage, but we probably do >> not want to request all associations. >> >> Let's assume we have partial pinctrl configuration with 2-3 groups, 2 >> functions and 10-15 pins involved. >> >> We don't want to request all 250 groups and 32 functions info during >> init because this will impact boottime and memory consumption. > > Yes I supposed this was the reason, and it could be reasonable to just > query the associations last minute when you need them for the stuff you > need which was put in the DT...I want to think a bit more about this, > being the only protocol that needs this behaviour. Good for now. > >> >> Pinctrl subsystem will request all needed data during device-tree node >> parsing. >> >> I have an idea to implement .instance_deinit callback from >> scmi_protocol, which will cleanup all allocated data. >> >> What do you think about that? If it is ok for you - I'll push v2. >> > > I'd say do the cleanup with the available .instance_deinit as proposed > in the meantime, so we can see how all the changes and the update to > mainline kernel pans out...then we can discuss this further down the > line, maybe finding a better way to serve you lazy allocation from the > SCMI core (or not) and also see what Sudeep thinks abou these lazy > allocations. > > [snip] > >> + * struct scmi_pinctrl_ops - represents the various operations provided >> + * by SCMI Pinctrl Protocol >> + * >> + * @get_groups_count: returns count of the registered groups >> + * @get_group_name: returns group name by index >> + * @get_group_pins: returns the set of pins, assigned to the specified group >> + * @get_functions_count: returns count of the registered fucntions >> + * @get_function_name: returns function name by indes >> + * @get_function_groups: returns the set of groups, assigned to the specified >> + * function >> + * @set_mux: set muxing function for groups of pins >> + * @get_pins: returns the set of pins, registered in driver >> + * @get_config: returns configuration parameter for pin >> + * @set_config: sets the configuration parameter for pin >> + * @get_config_group: returns the configuration parameter for a group of pins >> + * @set_config_group: sets the configuration parameter for a groups of pins >> + * @request_pin: aquire pin before selecting mux setting >> + * @free_pin: frees pin, acquired by request_pin call >> + */ >> +struct scmi_pinctrl_ops { >> + int (*get_groups_count)(const struct scmi_handle *handle); >> + int (*get_group_name)(const struct scmi_handle *handles, u32 selector, >> + const char **name); >> + int (*get_group_pins)(const struct scmi_handle *handle, u32 selector, >> + const unsigned int **pins, unsigned int *nr_pins); >> + int (*get_functions_count)(const struct scmi_handle *handle); >> + int (*get_function_name)(const struct scmi_handle *handle, u32 selector, >> + const char **name); >> + int (*get_function_groups)(const struct scmi_handle *handle, >> + u32 selector, unsigned int *nr_groups, >> + const unsigned int **groups); >> + int (*set_mux)(const struct scmi_handle *handle, u32 selector, >> + u32 group); >> + int (*get_pin_name)(const struct scmi_handle *handle, u32 selector, >> + const char **name); >> + int (*get_pins_count)(const struct scmi_handle *handle); >> + int (*get_config)(const struct scmi_handle *handle, u32 pin, >> + u32 *config); >> + int (*set_config)(const struct scmi_handle *handle, u32 pin, >> + u32 config); >> + int (*get_config_group)(const struct scmi_handle *handle, u32 pin, >> + u32 *config); >> + int (*set_config_group)(const struct scmi_handle *handle, u32 pin, >> + u32 config); >> + int (*request_pin)(const struct scmi_handle *handle, u32 pin); >> + int (*free_pin)(const struct scmi_handle *handle, u32 pin); >> +}; >> + >> >> As mentioned above, here you could drop a lot of this get_X_count/name/pins >> and instead expose a few of the internal proocol struct scmi__X_info and then >> provide just a mean to query how many resource are there and then get the info >> descriptor you want for the specific domain_id, i.e.: >> >> int (*num_domains_get)(ph, type) >> void *(*info_get)(ph, type, domain_id); >> >> Thanks, >> Cristian >> >> Updated. Exposed selector_type to scmi_protocol, which helped me to >> reduce number of call. >> >> Looking forward for your thoughts about .instance_deinit callback >> implementation I've mentioned above and I will be ready to push v2. >> > > As said, let'see V2 with cleanups in .instance_deinit and lazy > allocations as they are now and move on from there. > > Thanks, > Cristian