Firmware does not support Block Acks when multiple vif are running.
Thus, wfx_add_interface() and wfx_remove_interface() enable and disable
Block Acks as necessary.
Block Ack policy is also reset after hif_reset(). Driver have to
re-enable it after each call to hif_reset().
This patch reflects this behavior.
Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com>
Link: https://lore.kernel.org/r/20200410133239.438347-17-Jerome.Pouiller@silabs.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
In former code, wfx_upload_ap_templates() was called in more cases
than necessary. Therefore, it tried to not update the frame templates
if it was not necessary.
Now, wfx_upload_ap_templates() is called only if mac80211 asked to
update the templates. In add, it does not hurt to upload template if
they are not used. So, remove unnecessary conditions at beginning of
wfx_upload_ap_templates()
Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com>
Link: https://lore.kernel.org/r/20200410133239.438347-11-Jerome.Pouiller@silabs.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Chip firmware is able to send periodic null frames to keep the
association with the AP.
The driver arbitrary set this period to 30sec. We prefer to rely on
BSS_CHANGED_KEEP_ALIVE that provide a true value.
Note that if BSS_CHANGED_KEEP_ALIVE is not received, we just disable
keep_alive feature. It is not very disturbing since AP will probably
ping the station before to disconnect it.
Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com>
Link: https://lore.kernel.org/r/20200410133239.438347-9-Jerome.Pouiller@silabs.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Chipset need two steps to associate with an AP:
1. it start receiving beacon from the AP (done with wfx_do_join())
2. it sent the association request (done with wfx_join_finalize())
The join request (see hif_join()) contains basic rates, beacon interval
and bssid to connect, so we trig on these events for the first step.
The second step is obviously associated to the event BSS_CHANGED_ASSOC.
Note that conf_mutex is now easier to manage. It is held by
wfx_bss_info_changed() and inner functions does not need to lock it.
Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com>
Link: https://lore.kernel.org/r/20200410133239.438347-7-Jerome.Pouiller@silabs.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Currently, wfx_bss_info_changed() check interface status changes and
guess when the pattern match with an AP start and AP stop (through
wfx_update_beaconing()). It is far easier to rely on start_ap and
stop_ap callbacks provided by mac80211.
wfx_bss_info_changed() keeps only the responsibility of updating the
frame templates.
Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com>
Link: https://lore.kernel.org/r/20200410133239.438347-5-Jerome.Pouiller@silabs.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Currently, wfx_do_unjoin() are called by the mean of work queues.
However, the contexts from where they are called are not atomic. So
there is no reason to not call it synchronously.
This change will simplify the code. Notice two main changes:
- There no more reason to lock tx queue before to run
wfx_do_unjoin(). We can lock the tx queue directly from
wfx_do_unjoin().
- Most of the time, wfx_do_unjoin_work() was called with conf_mutex
held. This patch remove lock of conf_mutex in wfx_do_unjoin_work()
and ensure that conf_mutex is always held whatever the context.
Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com>
Link: https://lore.kernel.org/r/20200410133239.438347-4-Jerome.Pouiller@silabs.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
wfx_remove_interface() and wfx_configure_filter() can be run
concurrently. Therefore, this patch protect access to the list of
interfaces from wfx_configure_filter().
Notice that wfx_configure_filter() now lock "conf_lock" and "scan_lock".
Beside that, wfx_hw_scan_work() also access to the same locks. So we
have to lock them in same order to avoid any deadlock.
Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com>
Link: https://lore.kernel.org/r/20200410133239.438347-2-Jerome.Pouiller@silabs.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
wfx_tx_flush() wait there are no more frame in device buffer. However,
this event may never happens since wfx_tx_flush() don't forbid to
enqueue new frames.
Note that wfx_tx_flush() should only ensure that all frames currently in
hardware queues are sent. So the current code is more restrictive that
it should.
Note that wfx_tx_flush() release the lock before to return while
wfx_tx_lock_flush() keep the lock.
Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com>
Link: https://lore.kernel.org/r/20200401110405.80282-31-Jerome.Pouiller@silabs.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Until now, wfx_flush() flushed queue for while device instead of only
the queue of the intended vif. It sometime failed with a timeout, but
this error was not reported.
Moreover, if the device was frozen, wfx_flush didn't do anything and it
results a potential warning (and maybe a resource leak) when the frozen
device was unregistered.
We can also notice that wfx_tx_queues_wait_empty_vif() did only exist to
work around the broken feature of wfx_flush().
This patch repair wfx_flush() and therefore drop
wfx_tx_queues_wait_empty_vif().
Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com>
Link: https://lore.kernel.org/r/20200401110405.80282-29-Jerome.Pouiller@silabs.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Currently, wfx_pending_remove() (from queue.c) call wfx_skb_dtor()
(from data_tx.c) that forward the tx status to mac80211.
Moreover, there no purpose to retrieve a frame from the pending queue
without dequeuing it. So, the main purpose of wfx_pending_remove() is to
forward the tx status to mac80211.
Let's make the architecture cleaner:
- merge wfx_pending_remove() into wfx_pending_get()
- call wfx_skb_dtor() from data_tx.c
Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com>
Link: https://lore.kernel.org/r/20200401110405.80282-27-Jerome.Pouiller@silabs.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
The current code computes itself the QoS policy to choose which frame
should be sent. However, firmware already do that job. Firmware would
prefer to have packets in every queues and be able to choose itself
which queue to use.
So, this patch sort the queues from the emptiest to the fulliest (thanks
to the pending frames counter introduced a few commits earlier). It send
frame to the least full queue.
However, we continue to be careful with frames that have to be sent
after a dtim ("cab": Content After (DTIM) Beacon).
So, this patch splits AC queues in two skb_queues: one for normal frames
and another for cab frames. It cares to send frames from CAB skb_queue
if appropriate.
Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com>
Link: https://lore.kernel.org/r/20200401110405.80282-23-Jerome.Pouiller@silabs.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>