mirror of
https://github.com/torvalds/linux.git
synced 2026-03-13 23:46:14 +01:00
wifi: plfxlc: Fix error handling in usb driver probe
If probe fails before ieee80211_register_hw() is successfully done,
ieee80211_unregister_hw() will be called anyway. This may lead to various
bugs as the implementation of ieee80211_unregister_hw() assumes that
ieee80211_register_hw() has been called.
Divide error handling section into relevant subsections, so that
ieee80211_unregister_hw() is called only when it is appropriate. Correct
the order of the calls: ieee80211_unregister_hw() should go before
plfxlc_mac_release(). Also move ieee80211_free_hw() to plfxlc_mac_release()
as it supposed to be the opposite to plfxlc_mac_alloc_hw() that calls
ieee80211_alloc_hw().
Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
Fixes: 68d57a07bf ("wireless: add plfxlc driver for pureLiFi X, XL, XC devices")
Signed-off-by: Murad Masimov <m.masimov@mt-integration.ru>
Link: https://patch.msgid.link/20250321185226.71-3-m.masimov@mt-integration.ru
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
f8bf97ad19
commit
3fe79a25c3
3 changed files with 21 additions and 21 deletions
|
|
@ -99,11 +99,6 @@ int plfxlc_mac_init_hw(struct ieee80211_hw *hw)
|
|||
return r;
|
||||
}
|
||||
|
||||
void plfxlc_mac_release(struct plfxlc_mac *mac)
|
||||
{
|
||||
plfxlc_chip_release(&mac->chip);
|
||||
}
|
||||
|
||||
int plfxlc_op_start(struct ieee80211_hw *hw)
|
||||
{
|
||||
plfxlc_hw_mac(hw)->chip.usb.initialized = 1;
|
||||
|
|
@ -756,3 +751,9 @@ struct ieee80211_hw *plfxlc_mac_alloc_hw(struct usb_interface *intf)
|
|||
SET_IEEE80211_DEV(hw, &intf->dev);
|
||||
return hw;
|
||||
}
|
||||
|
||||
void plfxlc_mac_release_hw(struct ieee80211_hw *hw)
|
||||
{
|
||||
plfxlc_chip_release(&plfxlc_hw_mac(hw)->chip);
|
||||
ieee80211_free_hw(hw);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ static inline u8 *plfxlc_mac_get_perm_addr(struct plfxlc_mac *mac)
|
|||
}
|
||||
|
||||
struct ieee80211_hw *plfxlc_mac_alloc_hw(struct usb_interface *intf);
|
||||
void plfxlc_mac_release(struct plfxlc_mac *mac);
|
||||
void plfxlc_mac_release_hw(struct ieee80211_hw *hw);
|
||||
|
||||
int plfxlc_mac_preinit_hw(struct ieee80211_hw *hw, const u8 *hw_address);
|
||||
int plfxlc_mac_init_hw(struct ieee80211_hw *hw);
|
||||
|
|
|
|||
|
|
@ -604,7 +604,7 @@ static int probe(struct usb_interface *intf,
|
|||
r = plfxlc_upload_mac_and_serial(intf, hw_address, serial_number);
|
||||
if (r) {
|
||||
dev_err(&intf->dev, "MAC and Serial upload failed (%d)\n", r);
|
||||
goto error;
|
||||
goto error_free_hw;
|
||||
}
|
||||
|
||||
chip->unit_type = STA;
|
||||
|
|
@ -613,13 +613,13 @@ static int probe(struct usb_interface *intf,
|
|||
r = plfxlc_mac_preinit_hw(hw, hw_address);
|
||||
if (r) {
|
||||
dev_err(&intf->dev, "Init mac failed (%d)\n", r);
|
||||
goto error;
|
||||
goto error_free_hw;
|
||||
}
|
||||
|
||||
r = ieee80211_register_hw(hw);
|
||||
if (r) {
|
||||
dev_err(&intf->dev, "Register device failed (%d)\n", r);
|
||||
goto error;
|
||||
goto error_free_hw;
|
||||
}
|
||||
|
||||
if ((le16_to_cpu(interface_to_usbdev(intf)->descriptor.idVendor) ==
|
||||
|
|
@ -632,7 +632,7 @@ static int probe(struct usb_interface *intf,
|
|||
}
|
||||
if (r != 0) {
|
||||
dev_err(&intf->dev, "FPGA download failed (%d)\n", r);
|
||||
goto error;
|
||||
goto error_unreg_hw;
|
||||
}
|
||||
|
||||
tx->mac_fifo_full = 0;
|
||||
|
|
@ -642,21 +642,21 @@ static int probe(struct usb_interface *intf,
|
|||
r = plfxlc_usb_init_hw(usb);
|
||||
if (r < 0) {
|
||||
dev_err(&intf->dev, "usb_init_hw failed (%d)\n", r);
|
||||
goto error;
|
||||
goto error_unreg_hw;
|
||||
}
|
||||
|
||||
msleep(PLF_MSLEEP_TIME);
|
||||
r = plfxlc_chip_switch_radio(chip, PLFXLC_RADIO_ON);
|
||||
if (r < 0) {
|
||||
dev_dbg(&intf->dev, "chip_switch_radio_on failed (%d)\n", r);
|
||||
goto error;
|
||||
goto error_unreg_hw;
|
||||
}
|
||||
|
||||
msleep(PLF_MSLEEP_TIME);
|
||||
r = plfxlc_chip_set_rate(chip, 8);
|
||||
if (r < 0) {
|
||||
dev_dbg(&intf->dev, "chip_set_rate failed (%d)\n", r);
|
||||
goto error;
|
||||
goto error_unreg_hw;
|
||||
}
|
||||
|
||||
msleep(PLF_MSLEEP_TIME);
|
||||
|
|
@ -664,7 +664,7 @@ static int probe(struct usb_interface *intf,
|
|||
hw_address, ETH_ALEN, USB_REQ_MAC_WR);
|
||||
if (r < 0) {
|
||||
dev_dbg(&intf->dev, "MAC_WR failure (%d)\n", r);
|
||||
goto error;
|
||||
goto error_unreg_hw;
|
||||
}
|
||||
|
||||
plfxlc_chip_enable_rxtx(chip);
|
||||
|
|
@ -691,12 +691,12 @@ static int probe(struct usb_interface *intf,
|
|||
plfxlc_mac_init_hw(hw);
|
||||
usb->initialized = true;
|
||||
return 0;
|
||||
|
||||
error_unreg_hw:
|
||||
ieee80211_unregister_hw(hw);
|
||||
error_free_hw:
|
||||
plfxlc_mac_release_hw(hw);
|
||||
error:
|
||||
if (hw) {
|
||||
plfxlc_mac_release(plfxlc_hw_mac(hw));
|
||||
ieee80211_unregister_hw(hw);
|
||||
ieee80211_free_hw(hw);
|
||||
}
|
||||
dev_err(&intf->dev, "pureLifi:Device error");
|
||||
return r;
|
||||
}
|
||||
|
|
@ -730,8 +730,7 @@ static void disconnect(struct usb_interface *intf)
|
|||
*/
|
||||
usb_reset_device(interface_to_usbdev(intf));
|
||||
|
||||
plfxlc_mac_release(mac);
|
||||
ieee80211_free_hw(hw);
|
||||
plfxlc_mac_release_hw(hw);
|
||||
}
|
||||
|
||||
static void plfxlc_usb_resume(struct plfxlc_usb *usb)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue