iwlwifi: fix hang on unloading driver
f808c43ad9 introduced a FreeBSD specific
behaviour to wait for firmware load completion before returning from
loading the driver. This does no longer allow iwl_drv_stop to detect
that startup has completed and it will wait indefinitely for a
completion event that will not happen.
We could change the complete() call to a complete_all() but to avoid
confusion, future side effects, and for simplicity daisy-chain two
complete events in FreeBSD.
PR: 267869
Reported by: Peter Much (pmc citylink.dinoex.sub.org)
Tested by: Peter Much (pmc citylink.dinoex.sub.org)
Sponsored by: The FreeBSD Foundation
MFC after: 3 days
This commit is contained in:
@@ -77,6 +77,9 @@ struct iwl_drv {
|
|||||||
char firmware_name[64]; /* name of firmware file to load */
|
char firmware_name[64]; /* name of firmware file to load */
|
||||||
|
|
||||||
struct completion request_firmware_complete;
|
struct completion request_firmware_complete;
|
||||||
|
#if defined(__FreeBSD__)
|
||||||
|
struct completion drv_start_complete;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||||
struct dentry *dbgfs_drv;
|
struct dentry *dbgfs_drv;
|
||||||
@@ -1736,6 +1739,9 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans)
|
|||||||
drv->dev = trans->dev;
|
drv->dev = trans->dev;
|
||||||
|
|
||||||
init_completion(&drv->request_firmware_complete);
|
init_completion(&drv->request_firmware_complete);
|
||||||
|
#if defined(__FreeBSD__)
|
||||||
|
init_completion(&drv->drv_start_complete);
|
||||||
|
#endif
|
||||||
INIT_LIST_HEAD(&drv->list);
|
INIT_LIST_HEAD(&drv->list);
|
||||||
|
|
||||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||||
@@ -1763,6 +1769,7 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans)
|
|||||||
* returned before it was all done that is what could happen.
|
* returned before it was all done that is what could happen.
|
||||||
*/
|
*/
|
||||||
wait_for_completion(&drv->request_firmware_complete);
|
wait_for_completion(&drv->request_firmware_complete);
|
||||||
|
complete(&drv->drv_start_complete);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return drv;
|
return drv;
|
||||||
@@ -1779,7 +1786,11 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans)
|
|||||||
|
|
||||||
void iwl_drv_stop(struct iwl_drv *drv)
|
void iwl_drv_stop(struct iwl_drv *drv)
|
||||||
{
|
{
|
||||||
|
#if defined(__linux__)
|
||||||
wait_for_completion(&drv->request_firmware_complete);
|
wait_for_completion(&drv->request_firmware_complete);
|
||||||
|
#elif defined(__FreeBSD__)
|
||||||
|
wait_for_completion(&drv->drv_start_complete);
|
||||||
|
#endif
|
||||||
|
|
||||||
_iwl_op_mode_stop(drv);
|
_iwl_op_mode_stop(drv);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user