Message ID | 20200921115424.4105-1-cezary.rojewski@intel.com |
---|---|
Headers | show |
Series | ASoC: Intel: Catpt - Lynx and Wildcat point | expand |
On Mon, Sep 21, 2020 at 05:20:12PM +0300, Andy Shevchenko wrote: > On Mon, Sep 21, 2020 at 03:58:33PM +0200, Amadeusz Sławiński wrote: > > On 9/21/2020 2:59 PM, Andy Shevchenko wrote: > > > > +struct catpt_set_volume_input { > > > > + u32 channel; > > > > + u32 target_volume; > > > > + u64 curve_duration; > > > > + enum catpt_audio_curve_type curve_type __aligned(4); > > > > +} __packed; > > > How this __packed changes anything? In general __packed doesn't make sense for > > > in-kernel data structures. Otherwise you have to use proper (POD) types for > > > data. Ditto for all similar cases. > > > > All of __packed use in code is done on structures used to communicate with > > FW, which is binary interface, so it is not kernel only structure, as it is > > also FW one. While we can expect compiler to do the right thing, I consider > > it is better to be explicit about what kind of data we are handling, so > > there aren't any surprises. > > Size of enum is compiler defined. It may not be used in the ABIs. I have to elaborate that I'm talking in ABIs which implies different compilers and even may be run on different CPU architectures. > __uXX vs. uXX I dunno. And here I'm talking about FW <--> OS interface. It's not user visible ABI, but still some Ext <--> Int protocol. I saw uXX types in data structures of FW communication protocols.
On 2020-09-21 2:59 PM, Andy Shevchenko wrote: > On Mon, Sep 21, 2020 at 01:54:13PM +0200, Cezary Rojewski wrote: >> Declare global and stream IPC message handlers for all known message >> types. ... >> +int catpt_coredump(struct catpt_dev *cdev) >> +{ >> + struct catpt_dump_section_hdr *hdr; >> + size_t dump_size, regs_size; >> + u8 *dump, *pos; >> + int i, j; >> + >> + regs_size = CATPT_SHIM_REGS_SIZE; >> + regs_size += CATPT_DMA_COUNT * CATPT_DMA_REGS_SIZE; >> + regs_size += CATPT_SSP_COUNT * CATPT_SSP_REGS_SIZE; >> + dump_size = resource_size(&cdev->dram); >> + dump_size += resource_size(&cdev->iram); >> + dump_size += regs_size; > >> + dump_size += 4 * sizeof(*hdr) + 20; /* hdrs and fw hash */ > > Function is full of hard coded 20s. Can you provide descriptive macro? > Will declare CATPT_DUMP_HASH_SIZE instead of hardcodes, sure. >> + dump = vzalloc(dump_size); >> + if (!dump) >> + return -ENOMEM; >> + >> + pos = dump; >> + >> + hdr = (struct catpt_dump_section_hdr *)pos; >> + hdr->magic = CATPT_DUMP_MAGIC; >> + hdr->core_id = cdev->spec->core_id; >> + hdr->section_id = CATPT_DUMP_SECTION_ID_FILE; >> + hdr->size = dump_size - sizeof(*hdr); >> + pos += sizeof(*hdr); >> + >> + for (i = j = 0; i < FW_INFO_SIZE_MAX; i++) >> + if (cdev->ipc.config.fw_info[i] == ' ') >> + if (++j == 4) >> + break; > >> + for (j = ++i; j < FW_INFO_SIZE_MAX && j - i < 20; j++) { > > This should have static_assert() at the place where you define both constants > (2nd is mentioned above 20). > >> + if (cdev->ipc.config.fw_info[j] == ' ') >> + break; >> + *(pos + j - i) = cdev->ipc.config.fw_info[j]; >> + } >> + pos += 20; > > These two for-loops should have some comment to explain what's going on. > Actually, after poking my FW friends again I realized that it's just dumping 20chars from "hash" segment of fw_info (struct catpt_fw_ready, field: fw_info[]). So, this could be replaced by: /* navigate to fifth info segment (fw hash) */ for (i = j = 0; i < FW_INFO_SIZE_MAX; i++) /* info segments are separated by space each */ if (cdev->ipc.config.fw_info[i] == ' ') if (++j == 4) break; memcpy(pos, &cdev->ipc.config.fw_info[++i], CATPT_DUMP_HASH_SIZE); pos += CATPT_DUMP_HASH_SIZE; Existing for-loops were based on internal solution. Half of the code isn't needed afterall.. Czarek
On 2020-09-21 8:41 PM, Andy Shevchenko wrote:> On Mon, Sep 21, 2020 at 06:13:59PM +0000, Rojewski, Cezary wrote: >> On 2020-09-21 2:59 PM, Andy Shevchenko wrote: >>> On Mon, Sep 21, 2020 at 01:54:13PM +0200, Cezary Rojewski wrote: ... >>>> + for (i = j = 0; i < FW_INFO_SIZE_MAX; i++) >>>> + if (cdev->ipc.config.fw_info[i] == ' ') >>>> + if (++j == 4) >>>> + break; >>> >>>> + for (j = ++i; j < FW_INFO_SIZE_MAX && j - i < 20; j++) { >>> >>> This should have static_assert() at the place where you define both constants >>> (2nd is mentioned above 20). >>> >>>> + if (cdev->ipc.config.fw_info[j] == ' ') >>>> + break; >>>> + *(pos + j - i) = cdev->ipc.config.fw_info[j]; >>>> + } >>>> + pos += 20; >>> >>> These two for-loops should have some comment to explain what's going on. >>> >> >> Actually, after poking my FW friends again I realized that it's just >> dumping 20chars from "hash" segment of fw_info (struct catpt_fw_ready, >> field: fw_info[]). >> >> So, this could be replaced by: >> > >> /* navigate to fifth info segment (fw hash) */ >> for (i = j = 0; i < FW_INFO_SIZE_MAX; i++) >> /* info segments are separated by space each */ >> if (cdev->ipc.config.fw_info[i] == ' ') >> if (++j == 4) >> break; > > ...and this is repeating strnchr() / strnchrnul(). > Indeed, will incorporate into above. > With the questions "what if...": > - nul in the middle of this? > - less than 4 spaces found? > While this should never happen (means user is somehow not making use of officially released firmware binary), coredumps are useful only if you have access to debug tools. In cases you'd mentioned, invalid hash would have been dumped to coredump and crash reader simply wouldn't have been able to navigate to actual build for it. The rest of the coredump is still vital though. memcpy() could be gated behind an 'if' for safety if needed: info = cdev->ipc.config.fw_info; eof = info + FW_INFO_SIZE_MAX; /* navigate to fifth info segment (fw hash) */ for (i = 0; i < 4 && info < eof; i++, info++) /* info segments are separated by space each */ if ((info = strnchr(info, eof - info, ' ')) == NULL) break; if (i == 4 && info < eof) memcpy(pos, info, min(eof - info, CATPT_DUMP_HASH_SIZE)); Didn't compile this, some typecheck fixes might be in order and so on. >> memcpy(pos, &cdev->ipc.config.fw_info[++i], CATPT_DUMP_HASH_SIZE); >> pos += CATPT_DUMP_HASH_SIZE; >> >> >> Existing for-loops were based on internal solution. Half of the code >> isn't needed afterall.. >
On 2020-09-22 11:04 AM, Andy Shevchenko wrote: > On Mon, Sep 21, 2020 at 08:48:12PM +0000, Rojewski, Cezary wrote: >> On 2020-09-21 8:41 PM, Andy Shevchenko wrote: ... >> While this should never happen (means user is somehow not making use of >> officially released firmware binary), coredumps are useful only if you >> have access to debug tools. In cases you'd mentioned, invalid hash would >> have been dumped to coredump and crash reader simply wouldn't have been >> able to navigate to actual build for it. The rest of the coredump is still >> vital though. >> >> memcpy() could be gated behind an 'if' for safety if needed: >> >> info = cdev->ipc.config.fw_info; >> eof = info + FW_INFO_SIZE_MAX; >> /* navigate to fifth info segment (fw hash) */ >> for (i = 0; i < 4 && info < eof; i++, info++) >> /* info segments are separated by space each */ >> if ((info = strnchr(info, eof - info, ' ')) == NULL) >> break; > >> if (i == 4 && info < eof) >> memcpy(pos, info, min(eof - info, CATPT_DUMP_HASH_SIZE)); > > And here basically enough check is info against NULL, right? > Just try to look at different possibilities how to make code simpler and neater. > >> Didn't compile this, some typecheck fixes might be in order and so on. > What you meant is: if (i == 4 && !info) // instead of 'info < eof' right? If 4th space is last char in this string then info would end up being non-NULL and equal to 'eof' and thus memcpy() would get invoked with size=eof-info=0. catpt_coredump() is here to gather debug info for Intel folks to analyze in case of critical error. In ideal world, it should not be required at all as when we get here, there are bigger problems on our head. Above solution is simpler than what is prevent in v7 while also maintaining good readability - variable names - plus comments which you suggested. Czarek
On Tue, Sep 22, 2020 at 02:29:10PM +0300, Andy Shevchenko wrote: > On Tue, Sep 22, 2020 at 11:04:31AM +0000, Rojewski, Cezary wrote: > > On 2020-09-22 11:04 AM, Andy Shevchenko wrote: > > > On Mon, Sep 21, 2020 at 08:48:12PM +0000, Rojewski, Cezary wrote: ... > > > And here basically enough check is info against NULL, right? > > > Just try to look at different possibilities how to make code simpler and neater. > > > > > >> Didn't compile this, some typecheck fixes might be in order and so on. > > > > > > > What you meant is: > > if (i == 4 && !info) // instead of 'info < eof' > > > > right? > > Simply if (!info)... if (info) memcpy(); of course, otherwise it will crash. > > If 4th space is last char in this string then info would end up being > > non-NULL and equal to 'eof' and thus memcpy() would get invoked with > > size=eof-info=0. > > ...which is not a problem.