@@ -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;
@@ -755,3 +750,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);
@@ -602,7 +602,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;
@@ -611,13 +611,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) ==
@@ -630,7 +630,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;
@@ -640,21 +640,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);
@@ -662,7 +662,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);
@@ -689,12 +689,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;
}
@@ -728,8 +728,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)
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: 68d57a07bfe5 ("wireless: add plfxlc driver for pureLiFi X, XL, XC devices") Signed-off-by: Murad Masimov <m.masimov@mt-integration.ru> --- drivers/net/wireless/purelifi/plfxlc/mac.c | 11 ++++---- drivers/net/wireless/purelifi/plfxlc/mac.h | 2 +- drivers/net/wireless/purelifi/plfxlc/usb.c | 29 +++++++++++----------- 3 files changed, 21 insertions(+), 21 deletions(-) -- 2.39.2