-
Notifications
You must be signed in to change notification settings - Fork 140
Leave SoundWire IRQs enabled during device removal #5264
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,6 +28,15 @@ static void intel_link_dev_release(struct device *dev) | |
| kfree(ldev); | ||
| } | ||
|
|
||
| static void intel_link_list_del(void *data) | ||
| { | ||
| struct sdw_intel_link_res *link = data; | ||
|
|
||
| mutex_lock(link->link_lock); | ||
| list_del(&link->list); | ||
| mutex_unlock(link->link_lock); | ||
| } | ||
|
|
||
| /* alloc, init and add link devices */ | ||
| static struct sdw_intel_link_dev *intel_link_dev_register(struct sdw_intel_res *res, | ||
| struct sdw_intel_ctx *ctx, | ||
|
|
@@ -78,6 +87,7 @@ static struct sdw_intel_link_dev *intel_link_dev_register(struct sdw_intel_res * | |
| link->shim_vs = res->mmio_base + SDW_SHIM2_VS_BASE(link_id); | ||
| link->shim_lock = res->eml_lock; | ||
| } | ||
| link->link_lock = &ctx->link_lock; | ||
|
|
||
| link->ops = res->ops; | ||
| link->dev = res->dev; | ||
|
|
@@ -144,8 +154,10 @@ irqreturn_t sdw_intel_thread(int irq, void *dev_id) | |
| struct sdw_intel_ctx *ctx = dev_id; | ||
| struct sdw_intel_link_res *link; | ||
|
|
||
| mutex_lock(&ctx->link_lock); | ||
| list_for_each_entry(link, &ctx->link_list, list) | ||
| sdw_cdns_irq(irq, link->cdns); | ||
| mutex_unlock(&ctx->link_lock); | ||
|
|
||
| return IRQ_HANDLED; | ||
| } | ||
|
|
@@ -209,6 +221,7 @@ static struct sdw_intel_ctx | |
| ctx->link_mask = res->link_mask; | ||
| ctx->handle = res->handle; | ||
| mutex_init(&ctx->shim_lock); | ||
| mutex_init(&ctx->link_lock); | ||
|
|
||
| link_mask = ctx->link_mask; | ||
|
|
||
|
|
@@ -245,7 +258,10 @@ static struct sdw_intel_ctx | |
| i++; | ||
| goto err; | ||
| } | ||
| mutex_lock(&ctx->link_lock); | ||
| list_add_tail(&link->list, &ctx->link_list); | ||
| mutex_unlock(&ctx->link_lock); | ||
| devm_add_action_or_reset(&ldev->auxdev.dev, intel_link_list_del, link); | ||
| bus = &link->cdns->bus; | ||
|
Comment on lines
+261
to
265
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lot of locking here to manage the in flight IRQs as we iterate the list. Have you tried to safely iterate/remove the list elems ?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't believe one can safely traverse a list that will be accessed from multiple threads without locking. There are _safe versions of the list macros, but they are only safe against accesses from within your own thread, say if the loop over the list might also modify the list. That said the actual contention on this lock should be close to zero, since the list is only modified during probe and remove. The rest of the time the only thing accessing the list is the IRQ handler.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, I wondered if you able to safely remove the device from the list before device->remove() and device->irq(), but it seems not in this case.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Trouble is the IRQ is part of communicating with the device, and one generally wants to communicate with the device whilst doing a remove to park the device in a sensible state. The simplest way of avoid a clash on the list is to mask the IRQ before the remove, which is infact what the code used to do. But this causes us problems as we can't communicate with the device anymore. |
||
| /* Calculate number of slaves */ | ||
| list_for_each(node, &bus->slaves) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1108,8 +1108,12 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) | |
| return ret; | ||
| } | ||
|
|
||
| /* One per DAI link, worst case is a DAI link for every endpoint */ | ||
| sof_dais = kcalloc(num_ends, sizeof(*sof_dais), GFP_KERNEL); | ||
| /* | ||
| * One per DAI link, worst case is a DAI link for every endpoint, also | ||
| * add one additional to act as a terminator such that code can iterate | ||
| * until it hits an uninitialised DAI. | ||
| */ | ||
| sof_dais = kcalloc(num_ends + 1, sizeof(*sof_dais), GFP_KERNEL); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we not fix this at source i.e. where its being dereferenced ?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The initial intention was to reduce the number of parameters getting passed around, I guess the alternative fix would be something like: Happy to go with that if we prefer, although personally I slightly prefer the approach of just having a spare sof_dais entry.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I prefer this version with a comment to explain why we need the additional sof_dai
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, best to fix at source with a comment otherwise new clients could make the same mistake. |
||
| if (!sof_dais) | ||
| return -ENOMEM; | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.