MT7621 has three assigned interrupts for the pcie. This
interrupts should properly being mapped taking into account
which devices are finally connected in which bus according
to link status. So the irq mappings should be as follows
according to link status (three bits indicating which devices
are link up):
* For PCIe Bus 1 slot 0:
- status = 0x2 || status = 0x6 => IRQ = pcie1_irq (24).
- status = 0x4 => IRQ = pcie2_irq (25).
- default => IRQ = pcie0_irq (23).
* For PCIe Bus 2 slot 0:
- status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25).
- default => IRQ = pcie1_irq (24).
* For PCIe Bus 2 slot 1:
- status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25).
- default => IRQ = pcie1_irq (24).
* For PCIe Bus 3 any slot:
- default => IRQ = pcie2_irq (25).
Because of this, the function 'of_irq_parse_and_map_pci' cannot
be used and we need to change device tree information from using
the 'interrupt-map' and 'interrupt-map-mask' properties into an
'interrupts' property to be able to get irq information from the
ports using the 'platform_get_irq' and storing an 'irq-map' into
the pcie driver data node to properly map correct irq using a
new 'mt7621_map_irq' function where this map will be read and the
correct irq returned.
Fixes: 46d093124d ("staging: mt7621-pci: improve interrupt mapping")
Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com>
Link: https://lore.kernel.org/r/20200413055942.2714-1-sergio.paracuellos@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Pcie phy for pcie0 and pcie1 is shared using a dual ported
one. Current code was assuming that if nothing is connected
in pcie0 it won't be also nothing connected in pcie1. This
assumtion is wrong for some devices such us 'Mikrotik rbm33g'
and 'ZyXEL LTE3301-PLUS' where only connecting a card to the
second bus on the phy is possible. For such devices kernel
hangs in the same point because of the wrong poweroff of the
phy getting the following trace:
mt7621-pci-phy 1e149000.pcie-phy: PHY for 0xbe149000 (dual port = 1)
mt7621-pci-phy 1e14a000.pcie-phy: PHY for 0xbe14a000 (dual port = 0)
mt7621-pci-phy 1e149000.pcie-phy: Xtal is 40MHz
mt7621-pci-phy 1e14a000.pcie-phy: Xtal is 40MHz
mt7621-pci 1e140000.pcie: pcie0 no card, disable it (RST & CLK)
[hangs]
The wrong assumption is located in the 'mt7621_pcie_init_ports'
function where we are just making a power off of the phy for
slots 0 and 2 if nothing is connected in them. Hence, only
poweroff the phy if nothing is connected in both slot 0 and
slot 1 avoiding the kernel to hang.
Fixes: 5737cfe87a ("staging: mt7621-pci: avoid to poweroff the phy for slot one")
Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com>
Link: https://lore.kernel.org/r/20200409111652.30964-1-sergio.paracuellos@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
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>