diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h index d00c728..9d89ca7 100644 --- a/drivers/net/wireless/libertas/defs.h +++ b/drivers/net/wireless/libertas/defs.h @@ -235,6 +235,8 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in #define MRVL_FW_V4 (0x04) /** FW definition from Marvell v5 */ #define MRVL_FW_V5 (0x05) +/** FW definition from Marvell v9 */ +#define MRVL_FW_V9 (0x09) /** FW definition from Marvell v10 */ #define MRVL_FW_V10 (0x0a) /** FW major revision definition */ diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index b4de0ca..063eff9 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -276,6 +276,12 @@ out: return ret; } +struct sdio_extended_event { + __le32 event; + __le16 reason_code; + u8 peer_addr[ETH_ALEN]; +} __packed; + static int if_sdio_handle_event(struct if_sdio_card *card, u8 *buffer, unsigned size) { @@ -290,21 +296,30 @@ static int if_sdio_handle_event(struct if_sdio_card *card, goto out; /* right shift 3 bits to get the event id */ - event >>= 3; + event = (event >> 3) & 0xFF; } else { + struct sdio_extended_event *ext_event = (void *) buffer; + if (size < 4) { lbs_deb_sdio("event packet too small (%d bytes)\n", (int)size); ret = -EINVAL; goto out; } - event = buffer[3] << 24; - event |= buffer[2] << 16; - event |= buffer[1] << 8; - event |= buffer[0] << 0; + event = le32_to_cpu(ext_event->event) & 0xFF; + + /* Firmware v9+ have an extended event format */ + if ((MRVL_FW_MAJOR_REV(card->priv->fwrelease) >= MRVL_FW_V9) && + (size >= sizeof(struct sdio_extended_event)) && + (event == MACREG_INT_CODE_DISASSOCIATED || + event == MACREG_INT_CODE_DEAUTHENTICATED)) { + lbs_deb_sdio("deauth/disassoc from %pM reason %d", + ext_event->peer_addr, + le16_to_cpu(ext_event->reason_code)); + } } - lbs_queue_event(card->priv, event & 0xFF); + lbs_queue_event(card->priv, event); ret = 0; out: