Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Conflicts: drivers/net/wireless/iwlwifi/pcie/tx.c
This commit is contained in:
commit
79d38f7d6c
|
@ -5157,6 +5157,7 @@ F: net/nfc/
|
|||
F: include/linux/nfc.h
|
||||
F: include/net/nfc/
|
||||
F: drivers/nfc/
|
||||
F: include/linux/platform_data/pn544.h
|
||||
|
||||
NFS, SUNRPC, AND LOCKD CLIENTS
|
||||
M: Trond Myklebust <Trond.Myklebust@netapp.com>
|
||||
|
|
|
@ -96,6 +96,7 @@ static struct usb_device_id btusb_table[] = {
|
|||
{ USB_DEVICE(0x0c10, 0x0000) },
|
||||
|
||||
/* Broadcom BCM20702A0 */
|
||||
{ USB_DEVICE(0x0b05, 0x17b5) },
|
||||
{ USB_DEVICE(0x04ca, 0x2003) },
|
||||
{ USB_DEVICE(0x0489, 0xe042) },
|
||||
{ USB_DEVICE(0x413c, 0x8197) },
|
||||
|
|
|
@ -379,7 +379,7 @@ static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size,
|
|||
manifest_sync_timeout);
|
||||
|
||||
if (!size) {
|
||||
dev_printk(KERN_ERR, &udev->dev, "FW buffer length invalid!\n");
|
||||
dev_err(&udev->dev, "FW buffer length invalid!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -391,8 +391,8 @@ static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size,
|
|||
if (need_dfu_state) {
|
||||
ret = at76_dfu_get_state(udev, &dfu_state);
|
||||
if (ret < 0) {
|
||||
dev_printk(KERN_ERR, &udev->dev,
|
||||
"cannot get DFU state: %d\n", ret);
|
||||
dev_err(&udev->dev,
|
||||
"cannot get DFU state: %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
need_dfu_state = 0;
|
||||
|
@ -407,9 +407,9 @@ static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size,
|
|||
dfu_timeout = at76_get_timeout(&dfu_stat_buf);
|
||||
need_dfu_state = 0;
|
||||
} else
|
||||
dev_printk(KERN_ERR, &udev->dev,
|
||||
"at76_dfu_get_status returned %d\n",
|
||||
ret);
|
||||
dev_err(&udev->dev,
|
||||
"at76_dfu_get_status returned %d\n",
|
||||
ret);
|
||||
break;
|
||||
|
||||
case STATE_DFU_DOWNLOAD_BUSY:
|
||||
|
@ -438,9 +438,9 @@ static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size,
|
|||
blockno++;
|
||||
|
||||
if (ret != bsize)
|
||||
dev_printk(KERN_ERR, &udev->dev,
|
||||
"at76_load_int_fw_block "
|
||||
"returned %d\n", ret);
|
||||
dev_err(&udev->dev,
|
||||
"at76_load_int_fw_block returned %d\n",
|
||||
ret);
|
||||
need_dfu_state = 1;
|
||||
break;
|
||||
|
||||
|
@ -1255,8 +1255,7 @@ static int at76_load_external_fw(struct usb_device *udev, struct fwentry *fwe)
|
|||
at76_dbg(DBG_DEVSTART, "opmode %d", op_mode);
|
||||
|
||||
if (op_mode != OPMODE_NORMAL_NIC_WITHOUT_FLASH) {
|
||||
dev_printk(KERN_ERR, &udev->dev, "unexpected opmode %d\n",
|
||||
op_mode);
|
||||
dev_err(&udev->dev, "unexpected opmode %d\n", op_mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1275,9 +1274,9 @@ static int at76_load_external_fw(struct usb_device *udev, struct fwentry *fwe)
|
|||
size, bsize, blockno);
|
||||
ret = at76_load_ext_fw_block(udev, blockno, block, bsize);
|
||||
if (ret != bsize) {
|
||||
dev_printk(KERN_ERR, &udev->dev,
|
||||
"loading %dth firmware block failed: %d\n",
|
||||
blockno, ret);
|
||||
dev_err(&udev->dev,
|
||||
"loading %dth firmware block failed: %d\n",
|
||||
blockno, ret);
|
||||
goto exit;
|
||||
}
|
||||
buf += bsize;
|
||||
|
@ -1293,8 +1292,8 @@ static int at76_load_external_fw(struct usb_device *udev, struct fwentry *fwe)
|
|||
exit:
|
||||
kfree(block);
|
||||
if (ret < 0)
|
||||
dev_printk(KERN_ERR, &udev->dev,
|
||||
"downloading external firmware failed: %d\n", ret);
|
||||
dev_err(&udev->dev,
|
||||
"downloading external firmware failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1308,8 +1307,8 @@ static int at76_load_internal_fw(struct usb_device *udev, struct fwentry *fwe)
|
|||
need_remap ? 0 : 2 * HZ);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_printk(KERN_ERR, &udev->dev,
|
||||
"downloading internal fw failed with %d\n", ret);
|
||||
dev_err(&udev->dev,
|
||||
"downloading internal fw failed with %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -1319,8 +1318,8 @@ static int at76_load_internal_fw(struct usb_device *udev, struct fwentry *fwe)
|
|||
if (need_remap) {
|
||||
ret = at76_remap(udev);
|
||||
if (ret < 0) {
|
||||
dev_printk(KERN_ERR, &udev->dev,
|
||||
"sending REMAP failed with %d\n", ret);
|
||||
dev_err(&udev->dev,
|
||||
"sending REMAP failed with %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
@ -1555,11 +1554,10 @@ static struct fwentry *at76_load_firmware(struct usb_device *udev,
|
|||
at76_dbg(DBG_FW, "downloading firmware %s", fwe->fwname);
|
||||
ret = request_firmware(&fwe->fw, fwe->fwname, &udev->dev);
|
||||
if (ret < 0) {
|
||||
dev_printk(KERN_ERR, &udev->dev, "firmware %s not found!\n",
|
||||
fwe->fwname);
|
||||
dev_printk(KERN_ERR, &udev->dev,
|
||||
"you may need to download the firmware from "
|
||||
"http://developer.berlios.de/projects/at76c503a/\n");
|
||||
dev_err(&udev->dev, "firmware %s not found!\n",
|
||||
fwe->fwname);
|
||||
dev_err(&udev->dev,
|
||||
"you may need to download the firmware from http://developer.berlios.de/projects/at76c503a/\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -1567,17 +1565,17 @@ static struct fwentry *at76_load_firmware(struct usb_device *udev,
|
|||
fwh = (struct at76_fw_header *)(fwe->fw->data);
|
||||
|
||||
if (fwe->fw->size <= sizeof(*fwh)) {
|
||||
dev_printk(KERN_ERR, &udev->dev,
|
||||
"firmware is too short (0x%zx)\n", fwe->fw->size);
|
||||
dev_err(&udev->dev,
|
||||
"firmware is too short (0x%zx)\n", fwe->fw->size);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* CRC currently not checked */
|
||||
fwe->board_type = le32_to_cpu(fwh->board_type);
|
||||
if (fwe->board_type != board_type) {
|
||||
dev_printk(KERN_ERR, &udev->dev,
|
||||
"board type mismatch, requested %u, got %u\n",
|
||||
board_type, fwe->board_type);
|
||||
dev_err(&udev->dev,
|
||||
"board type mismatch, requested %u, got %u\n",
|
||||
board_type, fwe->board_type);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -2150,8 +2148,7 @@ static int at76_alloc_urbs(struct at76_priv *priv,
|
|||
}
|
||||
|
||||
if (!ep_in || !ep_out) {
|
||||
dev_printk(KERN_ERR, &interface->dev,
|
||||
"bulk endpoints missing\n");
|
||||
dev_err(&interface->dev, "bulk endpoints missing\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
|
@ -2161,15 +2158,14 @@ static int at76_alloc_urbs(struct at76_priv *priv,
|
|||
priv->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
priv->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!priv->rx_urb || !priv->tx_urb) {
|
||||
dev_printk(KERN_ERR, &interface->dev, "cannot allocate URB\n");
|
||||
dev_err(&interface->dev, "cannot allocate URB\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
buffer_size = sizeof(struct at76_tx_buffer) + MAX_PADDING_SIZE;
|
||||
priv->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
|
||||
if (!priv->bulk_out_buffer) {
|
||||
dev_printk(KERN_ERR, &interface->dev,
|
||||
"cannot allocate output buffer\n");
|
||||
dev_err(&interface->dev, "cannot allocate output buffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -2230,8 +2226,7 @@ static int at76_init_new_device(struct at76_priv *priv,
|
|||
/* MAC address */
|
||||
ret = at76_get_hw_config(priv);
|
||||
if (ret < 0) {
|
||||
dev_printk(KERN_ERR, &interface->dev,
|
||||
"cannot get MAC address\n");
|
||||
dev_err(&interface->dev, "cannot get MAC address\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -2358,8 +2353,8 @@ static int at76_probe(struct usb_interface *interface,
|
|||
we get 204 with 2.4.23, Fiberline FL-WL240u (505A+RFMD2958) ??? */
|
||||
|
||||
if (op_mode == OPMODE_HW_CONFIG_MODE) {
|
||||
dev_printk(KERN_ERR, &interface->dev,
|
||||
"cannot handle a device in HW_CONFIG_MODE\n");
|
||||
dev_err(&interface->dev,
|
||||
"cannot handle a device in HW_CONFIG_MODE\n");
|
||||
ret = -EBUSY;
|
||||
goto error;
|
||||
}
|
||||
|
@ -2371,9 +2366,9 @@ static int at76_probe(struct usb_interface *interface,
|
|||
"downloading internal firmware\n");
|
||||
ret = at76_load_internal_fw(udev, fwe);
|
||||
if (ret < 0) {
|
||||
dev_printk(KERN_ERR, &interface->dev,
|
||||
"error %d downloading internal firmware\n",
|
||||
ret);
|
||||
dev_err(&interface->dev,
|
||||
"error %d downloading internal firmware\n",
|
||||
ret);
|
||||
goto error;
|
||||
}
|
||||
usb_put_dev(udev);
|
||||
|
@ -2408,8 +2403,8 @@ static int at76_probe(struct usb_interface *interface,
|
|||
/* Re-check firmware version */
|
||||
ret = at76_get_mib(udev, MIB_FW_VERSION, &fwv, sizeof(fwv));
|
||||
if (ret < 0) {
|
||||
dev_printk(KERN_ERR, &interface->dev,
|
||||
"error %d getting firmware version\n", ret);
|
||||
dev_err(&interface->dev,
|
||||
"error %d getting firmware version\n", ret);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
@ -2449,7 +2444,7 @@ static void at76_disconnect(struct usb_interface *interface)
|
|||
|
||||
wiphy_info(priv->hw->wiphy, "disconnecting\n");
|
||||
at76_delete_device(priv);
|
||||
dev_printk(KERN_INFO, &interface->dev, "disconnected\n");
|
||||
dev_info(&interface->dev, "disconnected\n");
|
||||
}
|
||||
|
||||
/* Structure for registering this driver with the USB subsystem */
|
||||
|
|
|
@ -50,18 +50,19 @@ static void ar5523_read_reply(struct ar5523 *ar, struct ar5523_cmd_hdr *hdr,
|
|||
struct ar5523_tx_cmd *cmd)
|
||||
{
|
||||
int dlen, olen;
|
||||
u32 *rp;
|
||||
__be32 *rp;
|
||||
|
||||
dlen = hdr->len - sizeof(*hdr);
|
||||
dlen = be32_to_cpu(hdr->len) - sizeof(*hdr);
|
||||
|
||||
if (dlen < 0) {
|
||||
WARN_ON(1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ar5523_dbg(ar, "Code = %d len = %d\n", hdr->code & 0xff, dlen);
|
||||
ar5523_dbg(ar, "Code = %d len = %d\n", be32_to_cpu(hdr->code) & 0xff,
|
||||
dlen);
|
||||
|
||||
rp = (u32 *)(hdr + 1);
|
||||
rp = (__be32 *)(hdr + 1);
|
||||
if (dlen >= sizeof(u32)) {
|
||||
olen = be32_to_cpu(rp[0]);
|
||||
dlen -= sizeof(u32);
|
||||
|
@ -95,6 +96,7 @@ static void ar5523_cmd_rx_cb(struct urb *urb)
|
|||
struct ar5523_tx_cmd *cmd = &ar->tx_cmd;
|
||||
struct ar5523_cmd_hdr *hdr = ar->rx_cmd_buf;
|
||||
int dlen;
|
||||
u32 code, hdrlen;
|
||||
|
||||
if (urb->status) {
|
||||
if (urb->status != -ESHUTDOWN)
|
||||
|
@ -110,15 +112,15 @@ static void ar5523_cmd_rx_cb(struct urb *urb)
|
|||
ar5523_dbg(ar, "%s code %02x priv %d\n", __func__,
|
||||
be32_to_cpu(hdr->code) & 0xff, hdr->priv);
|
||||
|
||||
hdr->code = be32_to_cpu(hdr->code);
|
||||
hdr->len = be32_to_cpu(hdr->len);
|
||||
code = be32_to_cpu(hdr->code);
|
||||
hdrlen = be32_to_cpu(hdr->len);
|
||||
|
||||
switch (hdr->code & 0xff) {
|
||||
switch (code & 0xff) {
|
||||
default:
|
||||
/* reply to a read command */
|
||||
if (hdr->priv != AR5523_CMD_ID) {
|
||||
ar5523_err(ar, "Unexpected command id: %02x\n",
|
||||
hdr->code & 0xff);
|
||||
code & 0xff);
|
||||
goto skip;
|
||||
}
|
||||
ar5523_read_reply(ar, hdr, cmd);
|
||||
|
@ -147,7 +149,7 @@ static void ar5523_cmd_rx_cb(struct urb *urb)
|
|||
case WDCMSG_TARGET_START:
|
||||
/* This command returns a bogus id so it needs special
|
||||
handling */
|
||||
dlen = hdr->len - sizeof(*hdr);
|
||||
dlen = hdrlen - sizeof(*hdr);
|
||||
if (dlen != (int)sizeof(u32)) {
|
||||
ar5523_err(ar, "Invalid reply to WDCMSG_TARGET_START");
|
||||
return;
|
||||
|
@ -303,7 +305,7 @@ static int ar5523_config(struct ar5523 *ar, u32 reg, u32 val)
|
|||
|
||||
write.reg = cpu_to_be32(reg);
|
||||
write.len = cpu_to_be32(0); /* 0 = single write */
|
||||
*(u32 *)write.data = cpu_to_be32(val);
|
||||
*(__be32 *)write.data = cpu_to_be32(val);
|
||||
|
||||
error = ar5523_cmd_write(ar, WDCMSG_TARGET_SET_CONFIG, &write,
|
||||
3 * sizeof(u32), 0);
|
||||
|
@ -335,29 +337,30 @@ static int ar5523_get_status(struct ar5523 *ar, u32 which, void *odata,
|
|||
int olen)
|
||||
{
|
||||
int error;
|
||||
__be32 which_be;
|
||||
|
||||
which = cpu_to_be32(which);
|
||||
which_be = cpu_to_be32(which);
|
||||
error = ar5523_cmd_read(ar, WDCMSG_TARGET_GET_STATUS,
|
||||
&which, sizeof(which), odata, olen, AR5523_CMD_FLAG_MAGIC);
|
||||
&which_be, sizeof(which_be), odata, olen, AR5523_CMD_FLAG_MAGIC);
|
||||
if (error != 0)
|
||||
ar5523_err(ar, "could not read EEPROM offset 0x%02x\n",
|
||||
be32_to_cpu(which));
|
||||
ar5523_err(ar, "could not read EEPROM offset 0x%02x\n", which);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int ar5523_get_capability(struct ar5523 *ar, u32 cap, u32 *val)
|
||||
{
|
||||
int error;
|
||||
__be32 cap_be, val_be;
|
||||
|
||||
cap = cpu_to_be32(cap);
|
||||
error = ar5523_cmd_read(ar, WDCMSG_TARGET_GET_CAPABILITY,
|
||||
&cap, sizeof(cap), val, sizeof(u32), AR5523_CMD_FLAG_MAGIC);
|
||||
cap_be = cpu_to_be32(cap);
|
||||
error = ar5523_cmd_read(ar, WDCMSG_TARGET_GET_CAPABILITY, &cap_be,
|
||||
sizeof(cap_be), &val_be, sizeof(__be32),
|
||||
AR5523_CMD_FLAG_MAGIC);
|
||||
if (error != 0) {
|
||||
ar5523_err(ar, "could not read capability %u\n",
|
||||
be32_to_cpu(cap));
|
||||
ar5523_err(ar, "could not read capability %u\n", cap);
|
||||
return error;
|
||||
}
|
||||
*val = be32_to_cpu(*val);
|
||||
*val = be32_to_cpu(val_be);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -1193,8 +1196,8 @@ static void ar5523_create_rateset(struct ar5523 *ar,
|
|||
if (!sta) {
|
||||
ar5523_info(ar, "STA not found. Cannot set rates\n");
|
||||
sta_rate_set = bss_conf->basic_rates;
|
||||
}
|
||||
sta_rate_set = sta->supp_rates[ar->hw->conf.channel->band];
|
||||
} else
|
||||
sta_rate_set = sta->supp_rates[ar->hw->conf.channel->band];
|
||||
|
||||
ar5523_dbg(ar, "sta rate_set = %08x\n", sta_rate_set);
|
||||
|
||||
|
@ -1789,18 +1792,7 @@ static struct usb_driver ar5523_driver = {
|
|||
.disconnect = ar5523_disconnect,
|
||||
};
|
||||
|
||||
static int __init ar5523_init(void)
|
||||
{
|
||||
return usb_register(&ar5523_driver);
|
||||
}
|
||||
|
||||
static void __exit ar5523_exit(void)
|
||||
{
|
||||
usb_deregister(&ar5523_driver);
|
||||
}
|
||||
module_usb_driver(ar5523_driver);
|
||||
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_FIRMWARE(AR5523_FIRMWARE_FILE);
|
||||
|
||||
module_init(ar5523_init);
|
||||
module_exit(ar5523_exit);
|
||||
|
|
|
@ -161,7 +161,7 @@ struct ar5523_rx_desc {
|
|||
|
||||
struct ar5523_tx_desc {
|
||||
__be32 msglen;
|
||||
__be32 msgid; /* msg id (supplied by host) */
|
||||
u32 msgid; /* msg id (supplied by host) */
|
||||
__be32 type; /* opcode: WDMSG_SEND or WDCMSG_FLUSH */
|
||||
__be32 txqid; /* tx queue id and flags */
|
||||
#define UATH_TXQID_MASK 0x0f
|
||||
|
|
|
@ -236,17 +236,4 @@ static struct platform_driver ath_ahb_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init
|
||||
ath5k_ahb_init(void)
|
||||
{
|
||||
return platform_driver_register(&ath_ahb_driver);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
ath5k_ahb_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&ath_ahb_driver);
|
||||
}
|
||||
|
||||
module_init(ath5k_ahb_init);
|
||||
module_exit(ath5k_ahb_exit);
|
||||
module_platform_driver(ath_ahb_driver);
|
||||
|
|
|
@ -511,8 +511,9 @@ ath5k_update_bssid_mask_and_opmode(struct ath5k_hw *ah,
|
|||
ath5k_vif_iter(&iter_data, vif->addr, vif);
|
||||
|
||||
/* Get list of all active MAC addresses */
|
||||
ieee80211_iterate_active_interfaces_atomic(ah->hw, ath5k_vif_iter,
|
||||
&iter_data);
|
||||
ieee80211_iterate_active_interfaces_atomic(
|
||||
ah->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
ath5k_vif_iter, &iter_data);
|
||||
memcpy(ah->bssidmask, iter_data.mask, ETH_ALEN);
|
||||
|
||||
ah->opmode = iter_data.opmode;
|
||||
|
@ -1348,7 +1349,7 @@ ath5k_receive_frame(struct ath5k_hw *ah, struct sk_buff *skb,
|
|||
* right now, so it's not too bad...
|
||||
*/
|
||||
rxs->mactime = ath5k_extend_tsf(ah, rs->rs_tstamp);
|
||||
rxs->flag |= RX_FLAG_MACTIME_MPDU;
|
||||
rxs->flag |= RX_FLAG_MACTIME_START;
|
||||
|
||||
rxs->freq = ah->curchan->center_freq;
|
||||
rxs->band = ah->curchan->band;
|
||||
|
@ -3045,8 +3046,9 @@ ath5k_any_vif_assoc(struct ath5k_hw *ah)
|
|||
iter_data.need_set_hw_addr = false;
|
||||
iter_data.found_active = true;
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(ah->hw, ath5k_vif_iter,
|
||||
&iter_data);
|
||||
ieee80211_iterate_active_interfaces_atomic(
|
||||
ah->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
ath5k_vif_iter, &iter_data);
|
||||
return iter_data.any_assoc;
|
||||
}
|
||||
|
||||
|
|
|
@ -452,8 +452,9 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
|
|||
iter_data.hw_macaddr = NULL;
|
||||
iter_data.n_stas = 0;
|
||||
iter_data.need_set_hw_addr = false;
|
||||
ieee80211_iterate_active_interfaces_atomic(ah->hw, ath5k_vif_iter,
|
||||
&iter_data);
|
||||
ieee80211_iterate_active_interfaces_atomic(
|
||||
ah->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
ath5k_vif_iter, &iter_data);
|
||||
|
||||
/* Set up RX Filter */
|
||||
if (iter_data.n_stas > 1) {
|
||||
|
|
|
@ -789,9 +789,9 @@ ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel)
|
|||
* (I don't think it supports 44MHz) */
|
||||
/* On 2425 initvals TURBO_SHORT is not present */
|
||||
if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) {
|
||||
turbo = AR5K_PHY_TURBO_MODE |
|
||||
(ah->ah_radio == AR5K_RF2425) ? 0 :
|
||||
AR5K_PHY_TURBO_SHORT;
|
||||
turbo = AR5K_PHY_TURBO_MODE;
|
||||
if (ah->ah_radio != AR5K_RF2425)
|
||||
turbo |= AR5K_PHY_TURBO_SHORT;
|
||||
} else if (ah->ah_bwmode != AR5K_BWMODE_DEFAULT) {
|
||||
if (ah->ah_radio == AR5K_RF5413) {
|
||||
mode |= (ah->ah_bwmode == AR5K_BWMODE_10MHZ) ?
|
||||
|
|
|
@ -30,3 +30,12 @@ config ATH6KL_DEBUG
|
|||
depends on ATH6KL
|
||||
---help---
|
||||
Enables debug support
|
||||
|
||||
config ATH6KL_REGDOMAIN
|
||||
bool "Atheros ath6kl regdomain support"
|
||||
depends on ATH6KL
|
||||
depends on CFG80211_CERTIFICATION_ONUS
|
||||
---help---
|
||||
Enabling this makes it possible to change the regdomain in
|
||||
the firmware. This can be only enabled if regulatory requirements
|
||||
are taken into account.
|
||||
|
|
|
@ -34,6 +34,7 @@ ath6kl_core-y += main.o
|
|||
ath6kl_core-y += txrx.o
|
||||
ath6kl_core-y += wmi.o
|
||||
ath6kl_core-y += core.o
|
||||
ath6kl_core-y += recovery.o
|
||||
ath6kl_core-$(CONFIG_NL80211_TESTMODE) += testmode.o
|
||||
|
||||
obj-$(CONFIG_ATH6KL_SDIO) += ath6kl_sdio.o
|
||||
|
|
|
@ -147,15 +147,15 @@ static bool __ath6kl_cfg80211_sscan_stop(struct ath6kl_vif *vif)
|
|||
{
|
||||
struct ath6kl *ar = vif->ar;
|
||||
|
||||
if (ar->state != ATH6KL_STATE_SCHED_SCAN)
|
||||
if (!test_and_clear_bit(SCHED_SCANNING, &vif->flags))
|
||||
return false;
|
||||
|
||||
del_timer_sync(&vif->sched_scan_timer);
|
||||
|
||||
ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
ATH6KL_HOST_MODE_AWAKE);
|
||||
if (ar->state == ATH6KL_STATE_RECOVERY)
|
||||
return true;
|
||||
|
||||
ar->state = ATH6KL_STATE_ON;
|
||||
ath6kl_wmi_enable_sched_scan_cmd(ar->wmi, vif->fw_vif_idx, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -369,17 +369,13 @@ static int ath6kl_nliftype_to_drv_iftype(enum nl80211_iftype type, u8 *nw_type)
|
|||
{
|
||||
switch (type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
*nw_type = INFRA_NETWORK;
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
*nw_type = ADHOC_NETWORK;
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
*nw_type = AP_NETWORK;
|
||||
break;
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
*nw_type = INFRA_NETWORK;
|
||||
break;
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
*nw_type = AP_NETWORK;
|
||||
break;
|
||||
|
@ -1031,30 +1027,15 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy,
|
|||
|
||||
vif->scan_req = request;
|
||||
|
||||
if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX,
|
||||
ar->fw_capabilities)) {
|
||||
/*
|
||||
* If capable of doing P2P mgmt operations using
|
||||
* station interface, send additional information like
|
||||
* supported rates to advertise and xmit rates for
|
||||
* probe requests
|
||||
*/
|
||||
ret = ath6kl_wmi_beginscan_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
WMI_LONG_SCAN, force_fg_scan,
|
||||
false, 0,
|
||||
ATH6KL_FG_SCAN_INTERVAL,
|
||||
n_channels, channels,
|
||||
request->no_cck,
|
||||
request->rates);
|
||||
} else {
|
||||
ret = ath6kl_wmi_startscan_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
WMI_LONG_SCAN, force_fg_scan,
|
||||
false, 0,
|
||||
ATH6KL_FG_SCAN_INTERVAL,
|
||||
n_channels, channels);
|
||||
}
|
||||
ret = ath6kl_wmi_beginscan_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
WMI_LONG_SCAN, force_fg_scan,
|
||||
false, 0,
|
||||
ATH6KL_FG_SCAN_INTERVAL,
|
||||
n_channels, channels,
|
||||
request->no_cck,
|
||||
request->rates);
|
||||
if (ret) {
|
||||
ath6kl_err("wmi_startscan_cmd failed\n");
|
||||
ath6kl_err("failed to start scan: %d\n", ret);
|
||||
vif->scan_req = NULL;
|
||||
}
|
||||
|
||||
|
@ -1093,15 +1074,18 @@ out:
|
|||
void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq,
|
||||
enum wmi_phy_mode mode)
|
||||
{
|
||||
enum nl80211_channel_type type;
|
||||
struct cfg80211_chan_def chandef;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
|
||||
"channel switch notify nw_type %d freq %d mode %d\n",
|
||||
vif->nw_type, freq, mode);
|
||||
|
||||
type = (mode == WMI_11G_HT20) ? NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT;
|
||||
cfg80211_chandef_create(&chandef,
|
||||
ieee80211_get_channel(vif->ar->wiphy, freq),
|
||||
(mode == WMI_11G_HT20) ?
|
||||
NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT);
|
||||
|
||||
cfg80211_ch_switch_notify(vif->ndev, freq, type);
|
||||
cfg80211_ch_switch_notify(vif->ndev, &chandef);
|
||||
}
|
||||
|
||||
static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
|
||||
|
@ -1384,11 +1368,8 @@ static int ath6kl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The type nl80211_tx_power_setting replaces the following
|
||||
* data type from 2.6.36 onwards
|
||||
*/
|
||||
static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev,
|
||||
enum nl80211_tx_power_setting type,
|
||||
int mbm)
|
||||
{
|
||||
|
@ -1423,7 +1404,9 @@ static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ath6kl_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
|
||||
static int ath6kl_cfg80211_get_txpower(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev,
|
||||
int *dbm)
|
||||
{
|
||||
struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
|
||||
struct ath6kl_vif *vif;
|
||||
|
@ -1614,8 +1597,8 @@ static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy,
|
|||
vif->ssid_len = ibss_param->ssid_len;
|
||||
memcpy(vif->ssid, ibss_param->ssid, vif->ssid_len);
|
||||
|
||||
if (ibss_param->channel)
|
||||
vif->ch_hint = ibss_param->channel->center_freq;
|
||||
if (ibss_param->chandef.chan)
|
||||
vif->ch_hint = ibss_param->chandef.chan->center_freq;
|
||||
|
||||
if (ibss_param->channel_fixed) {
|
||||
/*
|
||||
|
@ -1889,7 +1872,7 @@ static int ath6kl_wow_usr(struct ath6kl *ar, struct ath6kl_vif *vif,
|
|||
struct cfg80211_wowlan *wow, u32 *filter)
|
||||
{
|
||||
int ret, pos;
|
||||
u8 mask[WOW_MASK_SIZE];
|
||||
u8 mask[WOW_PATTERN_SIZE];
|
||||
u16 i;
|
||||
|
||||
/* Configure the patterns that we received from the user. */
|
||||
|
@ -2107,33 +2090,16 @@ static int ath6kl_cfg80211_host_sleep(struct ath6kl *ar, struct ath6kl_vif *vif)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
|
||||
static int ath6kl_wow_suspend_vif(struct ath6kl_vif *vif,
|
||||
struct cfg80211_wowlan *wow, u32 *filter)
|
||||
{
|
||||
struct ath6kl *ar = vif->ar;
|
||||
struct in_device *in_dev;
|
||||
struct in_ifaddr *ifa;
|
||||
struct ath6kl_vif *vif;
|
||||
int ret;
|
||||
u32 filter = 0;
|
||||
u16 i, bmiss_time;
|
||||
u8 index = 0;
|
||||
__be32 ips[MAX_IP_ADDRS];
|
||||
|
||||
/* The FW currently can't support multi-vif WoW properly. */
|
||||
if (ar->num_vif > 1)
|
||||
return -EIO;
|
||||
|
||||
vif = ath6kl_vif_first(ar);
|
||||
if (!vif)
|
||||
return -EIO;
|
||||
|
||||
if (!ath6kl_cfg80211_ready(vif))
|
||||
return -EIO;
|
||||
|
||||
if (!test_bit(CONNECTED, &vif->flags))
|
||||
return -ENOTCONN;
|
||||
|
||||
if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST))
|
||||
return -EINVAL;
|
||||
u8 index = 0;
|
||||
|
||||
if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags) &&
|
||||
test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
|
||||
|
@ -2155,7 +2121,7 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
|
|||
* the user.
|
||||
*/
|
||||
if (wow)
|
||||
ret = ath6kl_wow_usr(ar, vif, wow, &filter);
|
||||
ret = ath6kl_wow_usr(ar, vif, wow, filter);
|
||||
else if (vif->nw_type == AP_NETWORK)
|
||||
ret = ath6kl_wow_ap(ar, vif);
|
||||
else
|
||||
|
@ -2190,12 +2156,10 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ar->state = ATH6KL_STATE_SUSPENDING;
|
||||
|
||||
/* Setup own IP addr for ARP agent. */
|
||||
in_dev = __in_dev_get_rtnl(vif->ndev);
|
||||
if (!in_dev)
|
||||
goto skip_arp;
|
||||
return 0;
|
||||
|
||||
ifa = in_dev->ifa_list;
|
||||
memset(&ips, 0, sizeof(ips));
|
||||
|
@ -2218,41 +2182,61 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
|
|||
return ret;
|
||||
}
|
||||
|
||||
skip_arp:
|
||||
ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
|
||||
{
|
||||
struct ath6kl_vif *first_vif, *vif;
|
||||
int ret = 0;
|
||||
u32 filter = 0;
|
||||
bool connected = false;
|
||||
|
||||
/* enter / leave wow suspend on first vif always */
|
||||
first_vif = ath6kl_vif_first(ar);
|
||||
if (WARN_ON(unlikely(!first_vif)) ||
|
||||
!ath6kl_cfg80211_ready(first_vif))
|
||||
return -EIO;
|
||||
|
||||
if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST))
|
||||
return -EINVAL;
|
||||
|
||||
/* install filters for each connected vif */
|
||||
spin_lock_bh(&ar->list_lock);
|
||||
list_for_each_entry(vif, &ar->vif_list, list) {
|
||||
if (!test_bit(CONNECTED, &vif->flags) ||
|
||||
!ath6kl_cfg80211_ready(vif))
|
||||
continue;
|
||||
connected = true;
|
||||
|
||||
ret = ath6kl_wow_suspend_vif(vif, wow, &filter);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
spin_unlock_bh(&ar->list_lock);
|
||||
|
||||
if (!connected)
|
||||
return -ENOTCONN;
|
||||
else if (ret)
|
||||
return ret;
|
||||
|
||||
ar->state = ATH6KL_STATE_SUSPENDING;
|
||||
|
||||
ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, first_vif->fw_vif_idx,
|
||||
ATH6KL_WOW_MODE_ENABLE,
|
||||
filter,
|
||||
WOW_HOST_REQ_DELAY);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ath6kl_cfg80211_host_sleep(ar, vif);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
return ath6kl_cfg80211_host_sleep(ar, first_vif);
|
||||
}
|
||||
|
||||
static int ath6kl_wow_resume(struct ath6kl *ar)
|
||||
static int ath6kl_wow_resume_vif(struct ath6kl_vif *vif)
|
||||
{
|
||||
struct ath6kl_vif *vif;
|
||||
struct ath6kl *ar = vif->ar;
|
||||
int ret;
|
||||
|
||||
vif = ath6kl_vif_first(ar);
|
||||
if (!vif)
|
||||
return -EIO;
|
||||
|
||||
ar->state = ATH6KL_STATE_RESUMING;
|
||||
|
||||
ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
ATH6KL_HOST_MODE_AWAKE);
|
||||
if (ret) {
|
||||
ath6kl_warn("Failed to configure host sleep mode for wow resume: %d\n",
|
||||
ret);
|
||||
ar->state = ATH6KL_STATE_WOW;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (vif->nw_type != AP_NETWORK) {
|
||||
ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
0, 0, 0, 0, 0, 0, 3, 0, 0, 0);
|
||||
|
@ -2270,13 +2254,11 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ar->state = ATH6KL_STATE_ON;
|
||||
|
||||
if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags) &&
|
||||
test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
|
||||
ar->fw_capabilities)) {
|
||||
ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi,
|
||||
vif->fw_vif_idx, true);
|
||||
vif->fw_vif_idx, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
@ -2286,6 +2268,48 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ath6kl_wow_resume(struct ath6kl *ar)
|
||||
{
|
||||
struct ath6kl_vif *vif;
|
||||
int ret;
|
||||
|
||||
vif = ath6kl_vif_first(ar);
|
||||
if (WARN_ON(unlikely(!vif)) ||
|
||||
!ath6kl_cfg80211_ready(vif))
|
||||
return -EIO;
|
||||
|
||||
ar->state = ATH6KL_STATE_RESUMING;
|
||||
|
||||
ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
ATH6KL_HOST_MODE_AWAKE);
|
||||
if (ret) {
|
||||
ath6kl_warn("Failed to configure host sleep mode for wow resume: %d\n",
|
||||
ret);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
spin_lock_bh(&ar->list_lock);
|
||||
list_for_each_entry(vif, &ar->vif_list, list) {
|
||||
if (!test_bit(CONNECTED, &vif->flags) ||
|
||||
!ath6kl_cfg80211_ready(vif))
|
||||
continue;
|
||||
ret = ath6kl_wow_resume_vif(vif);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
spin_unlock_bh(&ar->list_lock);
|
||||
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
|
||||
ar->state = ATH6KL_STATE_ON;
|
||||
return 0;
|
||||
|
||||
cleanup:
|
||||
ar->state = ATH6KL_STATE_WOW;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath6kl_cfg80211_deepsleep_suspend(struct ath6kl *ar)
|
||||
{
|
||||
struct ath6kl_vif *vif;
|
||||
|
@ -2422,13 +2446,6 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar,
|
|||
|
||||
break;
|
||||
|
||||
case ATH6KL_CFG_SUSPEND_SCHED_SCAN:
|
||||
/*
|
||||
* Nothing needed for schedule scan, firmware is already in
|
||||
* wow mode and sleeping most of the time.
|
||||
*/
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -2476,9 +2493,6 @@ int ath6kl_cfg80211_resume(struct ath6kl *ar)
|
|||
}
|
||||
break;
|
||||
|
||||
case ATH6KL_STATE_SCHED_SCAN:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -2495,14 +2509,23 @@ static int __ath6kl_cfg80211_suspend(struct wiphy *wiphy,
|
|||
{
|
||||
struct ath6kl *ar = wiphy_priv(wiphy);
|
||||
|
||||
ath6kl_recovery_suspend(ar);
|
||||
|
||||
return ath6kl_hif_suspend(ar, wow);
|
||||
}
|
||||
|
||||
static int __ath6kl_cfg80211_resume(struct wiphy *wiphy)
|
||||
{
|
||||
struct ath6kl *ar = wiphy_priv(wiphy);
|
||||
int err;
|
||||
|
||||
return ath6kl_hif_resume(ar);
|
||||
err = ath6kl_hif_resume(ar);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ath6kl_recovery_resume(ar);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2739,6 +2762,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
|||
int res;
|
||||
int i, ret;
|
||||
u16 rsn_capab = 0;
|
||||
int inactivity_timeout = 0;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s:\n", __func__);
|
||||
|
||||
|
@ -2857,7 +2881,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
|||
p.ssid_len = vif->ssid_len;
|
||||
memcpy(p.ssid, vif->ssid, vif->ssid_len);
|
||||
p.dot11_auth_mode = vif->dot11_auth_mode;
|
||||
p.ch = cpu_to_le16(info->channel->center_freq);
|
||||
p.ch = cpu_to_le16(info->chandef.chan->center_freq);
|
||||
|
||||
/* Enable uAPSD support by default */
|
||||
res = ath6kl_wmi_ap_set_apsd(ar->wmi, vif->fw_vif_idx, true);
|
||||
|
@ -2875,14 +2899,22 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
|||
}
|
||||
|
||||
if (info->inactivity_timeout) {
|
||||
|
||||
inactivity_timeout = info->inactivity_timeout;
|
||||
|
||||
if (ar->hw.flags & ATH6KL_HW_AP_INACTIVITY_MINS)
|
||||
inactivity_timeout = DIV_ROUND_UP(inactivity_timeout,
|
||||
60);
|
||||
|
||||
res = ath6kl_wmi_set_inact_period(ar->wmi, vif->fw_vif_idx,
|
||||
info->inactivity_timeout);
|
||||
inactivity_timeout);
|
||||
if (res < 0)
|
||||
return res;
|
||||
}
|
||||
|
||||
if (ath6kl_set_htcap(vif, info->channel->band,
|
||||
info->channel_type != NL80211_CHAN_NO_HT))
|
||||
if (ath6kl_set_htcap(vif, info->chandef.chan->band,
|
||||
cfg80211_get_chandef_type(&info->chandef)
|
||||
!= NL80211_CHAN_NO_HT))
|
||||
return -EIO;
|
||||
|
||||
/*
|
||||
|
@ -2898,6 +2930,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
|||
WLAN_EID_RSN, WMI_RSN_IE_CAPB,
|
||||
(const u8 *) &rsn_capab,
|
||||
sizeof(rsn_capab));
|
||||
vif->rsn_capab = rsn_capab;
|
||||
if (res < 0)
|
||||
return res;
|
||||
}
|
||||
|
@ -2977,7 +3010,6 @@ static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev,
|
|||
static int ath6kl_remain_on_channel(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type,
|
||||
unsigned int duration,
|
||||
u64 *cookie)
|
||||
{
|
||||
|
@ -3136,10 +3168,8 @@ static bool ath6kl_is_p2p_go_ssid(const u8 *buf, size_t len)
|
|||
|
||||
static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
struct ieee80211_channel *chan, bool offchan,
|
||||
enum nl80211_channel_type channel_type,
|
||||
bool channel_type_valid, unsigned int wait,
|
||||
const u8 *buf, size_t len, bool no_cck,
|
||||
bool dont_wait_for_ack, u64 *cookie)
|
||||
unsigned int wait, const u8 *buf, size_t len,
|
||||
bool no_cck, bool dont_wait_for_ack, u64 *cookie)
|
||||
{
|
||||
struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
|
||||
struct ath6kl *ar = ath6kl_priv(vif->ndev);
|
||||
|
@ -3211,7 +3241,7 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
|
|||
struct ath6kl *ar = ath6kl_priv(dev);
|
||||
struct ath6kl_vif *vif = netdev_priv(dev);
|
||||
u16 interval;
|
||||
int ret;
|
||||
int ret, rssi_thold;
|
||||
|
||||
if (ar->state != ATH6KL_STATE_ON)
|
||||
return -EIO;
|
||||
|
@ -3219,10 +3249,6 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
|
|||
if (vif->sme_state != SME_DISCONNECTED)
|
||||
return -EBUSY;
|
||||
|
||||
/* The FW currently can't support multi-vif WoW properly. */
|
||||
if (ar->num_vif > 1)
|
||||
return -EIO;
|
||||
|
||||
ath6kl_cfg80211_scan_complete_event(vif, true);
|
||||
|
||||
ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
|
||||
|
@ -3244,6 +3270,23 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (test_bit(ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD,
|
||||
ar->fw_capabilities)) {
|
||||
if (request->rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF)
|
||||
rssi_thold = 0;
|
||||
else if (request->rssi_thold < -127)
|
||||
rssi_thold = -127;
|
||||
else
|
||||
rssi_thold = request->rssi_thold;
|
||||
|
||||
ret = ath6kl_wmi_set_rssi_filter_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
rssi_thold);
|
||||
if (ret) {
|
||||
ath6kl_err("failed to set RSSI threshold for scan\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* fw uses seconds, also make sure that it's >0 */
|
||||
interval = max_t(u16, 1, request->interval / 1000);
|
||||
|
||||
|
@ -3251,15 +3294,6 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
|
|||
interval, interval,
|
||||
vif->bg_scan_period, 0, 0, 0, 3, 0, 0, 0);
|
||||
|
||||
ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
ATH6KL_WOW_MODE_ENABLE,
|
||||
WOW_FILTER_SSID,
|
||||
WOW_HOST_REQ_DELAY);
|
||||
if (ret) {
|
||||
ath6kl_warn("Failed to enable wow with ssid filter: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* this also clears IE in fw if it's not set */
|
||||
ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
WMI_FRAME_PROBE_REQ,
|
||||
|
@ -3270,17 +3304,13 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
ATH6KL_HOST_MODE_ASLEEP);
|
||||
if (ret) {
|
||||
ath6kl_warn("Failed to enable host sleep mode for sched scan: %d\n",
|
||||
ret);
|
||||
ret = ath6kl_wmi_enable_sched_scan_cmd(ar->wmi, vif->fw_vif_idx, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ar->state = ATH6KL_STATE_SCHED_SCAN;
|
||||
set_bit(SCHED_SCANNING, &vif->flags);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath6kl_cfg80211_sscan_stop(struct wiphy *wiphy,
|
||||
|
@ -3309,6 +3339,27 @@ static int ath6kl_cfg80211_set_bitrate(struct wiphy *wiphy,
|
|||
mask);
|
||||
}
|
||||
|
||||
static int ath6kl_cfg80211_set_txe_config(struct wiphy *wiphy,
|
||||
struct net_device *dev,
|
||||
u32 rate, u32 pkts, u32 intvl)
|
||||
{
|
||||
struct ath6kl *ar = ath6kl_priv(dev);
|
||||
struct ath6kl_vif *vif = netdev_priv(dev);
|
||||
|
||||
if (vif->nw_type != INFRA_NETWORK ||
|
||||
!test_bit(ATH6KL_FW_CAPABILITY_TX_ERR_NOTIFY, ar->fw_capabilities))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (vif->sme_state != SME_CONNECTED)
|
||||
return -ENOTCONN;
|
||||
|
||||
/* save this since the firmware won't report the interval */
|
||||
vif->txe_intvl = intvl;
|
||||
|
||||
return ath6kl_wmi_set_txe_notify(ar->wmi, vif->fw_vif_idx,
|
||||
rate, pkts, intvl);
|
||||
}
|
||||
|
||||
static const struct ieee80211_txrx_stypes
|
||||
ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = {
|
||||
[NL80211_IFTYPE_STATION] = {
|
||||
|
@ -3375,6 +3426,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = {
|
|||
.sched_scan_start = ath6kl_cfg80211_sscan_start,
|
||||
.sched_scan_stop = ath6kl_cfg80211_sscan_stop,
|
||||
.set_bitrate_mask = ath6kl_cfg80211_set_bitrate,
|
||||
.set_cqm_txe_config = ath6kl_cfg80211_set_txe_config,
|
||||
};
|
||||
|
||||
void ath6kl_cfg80211_stop(struct ath6kl_vif *vif)
|
||||
|
@ -3395,16 +3447,22 @@ void ath6kl_cfg80211_stop(struct ath6kl_vif *vif)
|
|||
break;
|
||||
}
|
||||
|
||||
if (test_bit(CONNECTED, &vif->flags) ||
|
||||
test_bit(CONNECT_PEND, &vif->flags))
|
||||
if (vif->ar->state != ATH6KL_STATE_RECOVERY &&
|
||||
(test_bit(CONNECTED, &vif->flags) ||
|
||||
test_bit(CONNECT_PEND, &vif->flags)))
|
||||
ath6kl_wmi_disconnect_cmd(vif->ar->wmi, vif->fw_vif_idx);
|
||||
|
||||
vif->sme_state = SME_DISCONNECTED;
|
||||
clear_bit(CONNECTED, &vif->flags);
|
||||
clear_bit(CONNECT_PEND, &vif->flags);
|
||||
|
||||
/* Stop netdev queues, needed during recovery */
|
||||
netif_stop_queue(vif->ndev);
|
||||
netif_carrier_off(vif->ndev);
|
||||
|
||||
/* disable scanning */
|
||||
if (ath6kl_wmi_scanparams_cmd(vif->ar->wmi, vif->fw_vif_idx, 0xFFFF,
|
||||
if (vif->ar->state != ATH6KL_STATE_RECOVERY &&
|
||||
ath6kl_wmi_scanparams_cmd(vif->ar->wmi, vif->fw_vif_idx, 0xFFFF,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0) != 0)
|
||||
ath6kl_warn("failed to disable scan during stop\n");
|
||||
|
||||
|
@ -3416,7 +3474,7 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar)
|
|||
struct ath6kl_vif *vif;
|
||||
|
||||
vif = ath6kl_vif_first(ar);
|
||||
if (!vif) {
|
||||
if (!vif && ar->state != ATH6KL_STATE_RECOVERY) {
|
||||
/* save the current power mode before enabling power save */
|
||||
ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
|
||||
|
||||
|
@ -3434,6 +3492,56 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar)
|
|||
ath6kl_cfg80211_stop(vif);
|
||||
}
|
||||
|
||||
static int ath6kl_cfg80211_reg_notify(struct wiphy *wiphy,
|
||||
struct regulatory_request *request)
|
||||
{
|
||||
struct ath6kl *ar = wiphy_priv(wiphy);
|
||||
u32 rates[IEEE80211_NUM_BANDS];
|
||||
int ret, i;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
|
||||
"cfg reg_notify %c%c%s%s initiator %d hint_type %d\n",
|
||||
request->alpha2[0], request->alpha2[1],
|
||||
request->intersect ? " intersect" : "",
|
||||
request->processed ? " processed" : "",
|
||||
request->initiator, request->user_reg_hint_type);
|
||||
|
||||
/*
|
||||
* As firmware is not able intersect regdoms, we can only listen to
|
||||
* cellular hints.
|
||||
*/
|
||||
if (request->user_reg_hint_type != NL80211_USER_REG_HINT_CELL_BASE)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ret = ath6kl_wmi_set_regdomain_cmd(ar->wmi, request->alpha2);
|
||||
if (ret) {
|
||||
ath6kl_err("failed to set regdomain: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Firmware will apply the regdomain change only after a scan is
|
||||
* issued and it will send a WMI_REGDOMAIN_EVENTID when it has been
|
||||
* changed.
|
||||
*/
|
||||
|
||||
for (i = 0; i < IEEE80211_NUM_BANDS; i++)
|
||||
if (wiphy->bands[i])
|
||||
rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1;
|
||||
|
||||
|
||||
ret = ath6kl_wmi_beginscan_cmd(ar->wmi, 0, WMI_LONG_SCAN, false,
|
||||
false, 0, ATH6KL_FG_SCAN_INTERVAL,
|
||||
0, NULL, false, rates);
|
||||
if (ret) {
|
||||
ath6kl_err("failed to start scan for a regdomain change: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath6kl_cfg80211_vif_init(struct ath6kl_vif *vif)
|
||||
{
|
||||
vif->aggr_cntxt = aggr_init(vif);
|
||||
|
@ -3506,9 +3614,13 @@ struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name,
|
|||
vif->htcap[IEEE80211_BAND_5GHZ].ht_enable = true;
|
||||
|
||||
memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
|
||||
if (fw_vif_idx != 0)
|
||||
if (fw_vif_idx != 0) {
|
||||
ndev->dev_addr[0] = (ndev->dev_addr[0] ^ (1 << fw_vif_idx)) |
|
||||
0x2;
|
||||
if (test_bit(ATH6KL_FW_CAPABILITY_CUSTOM_MAC_ADDR,
|
||||
ar->fw_capabilities))
|
||||
ndev->dev_addr[4] ^= 0x80;
|
||||
}
|
||||
|
||||
init_netdev(ndev);
|
||||
|
||||
|
@ -3562,6 +3674,12 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
|
|||
BIT(NL80211_IFTYPE_P2P_CLIENT);
|
||||
}
|
||||
|
||||
if (config_enabled(CONFIG_ATH6KL_REGDOMAIN) &&
|
||||
test_bit(ATH6KL_FW_CAPABILITY_REGDOMAIN, ar->fw_capabilities)) {
|
||||
wiphy->reg_notifier = ath6kl_cfg80211_reg_notify;
|
||||
ar->wiphy->features |= NL80211_FEATURE_CELL_BASE_REG_HINTS;
|
||||
}
|
||||
|
||||
/* max num of ssids that can be probed during scanning */
|
||||
wiphy->max_scan_ssids = MAX_PROBED_SSIDS;
|
||||
|
||||
|
@ -3607,7 +3725,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
|
|||
ath6kl_band_5ghz.ht_cap.ht_supported = false;
|
||||
}
|
||||
|
||||
if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES) {
|
||||
if (ar->hw.flags & ATH6KL_HW_64BIT_RATES) {
|
||||
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
|
||||
ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
|
||||
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff;
|
||||
|
@ -3646,7 +3764,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
|
|||
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
|
||||
WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
|
||||
|
||||
if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN, ar->fw_capabilities))
|
||||
if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2, ar->fw_capabilities))
|
||||
ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
|
||||
|
||||
if (test_bit(ATH6KL_FW_CAPABILITY_INACTIVITY_TIMEOUT,
|
||||
|
|
|
@ -22,7 +22,6 @@ enum ath6kl_cfg_suspend_mode {
|
|||
ATH6KL_CFG_SUSPEND_DEEPSLEEP,
|
||||
ATH6KL_CFG_SUSPEND_CUTPOWER,
|
||||
ATH6KL_CFG_SUSPEND_WOW,
|
||||
ATH6KL_CFG_SUSPEND_SCHED_SCAN,
|
||||
};
|
||||
|
||||
struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name,
|
||||
|
|
|
@ -33,6 +33,8 @@ static unsigned int wow_mode;
|
|||
static unsigned int uart_debug;
|
||||
static unsigned int ath6kl_p2p;
|
||||
static unsigned int testmode;
|
||||
static unsigned int recovery_enable;
|
||||
static unsigned int heart_beat_poll;
|
||||
|
||||
module_param(debug_mask, uint, 0644);
|
||||
module_param(suspend_mode, uint, 0644);
|
||||
|
@ -40,6 +42,12 @@ module_param(wow_mode, uint, 0644);
|
|||
module_param(uart_debug, uint, 0644);
|
||||
module_param(ath6kl_p2p, uint, 0644);
|
||||
module_param(testmode, uint, 0644);
|
||||
module_param(recovery_enable, uint, 0644);
|
||||
module_param(heart_beat_poll, uint, 0644);
|
||||
MODULE_PARM_DESC(recovery_enable, "Enable recovery from firmware error");
|
||||
MODULE_PARM_DESC(heart_beat_poll, "Enable fw error detection periodic" \
|
||||
"polling. This also specifies the polling interval in" \
|
||||
"msecs. Set reocvery_enable for this to be effective");
|
||||
|
||||
void ath6kl_core_tx_complete(struct ath6kl *ar, struct sk_buff *skb)
|
||||
{
|
||||
|
@ -202,6 +210,17 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type)
|
|||
ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n",
|
||||
__func__, wdev->netdev->name, wdev->netdev, ar);
|
||||
|
||||
ar->fw_recovery.enable = !!recovery_enable;
|
||||
if (!ar->fw_recovery.enable)
|
||||
return ret;
|
||||
|
||||
if (heart_beat_poll &&
|
||||
test_bit(ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL,
|
||||
ar->fw_capabilities))
|
||||
ar->fw_recovery.hb_poll = heart_beat_poll;
|
||||
|
||||
ath6kl_recovery_init(ar);
|
||||
|
||||
return ret;
|
||||
|
||||
err_rxbuf_cleanup:
|
||||
|
@ -291,6 +310,8 @@ void ath6kl_core_cleanup(struct ath6kl *ar)
|
|||
{
|
||||
ath6kl_hif_power_off(ar);
|
||||
|
||||
ath6kl_recovery_cleanup(ar);
|
||||
|
||||
destroy_workqueue(ar->ath6kl_wq);
|
||||
|
||||
if (ar->htc_target)
|
||||
|
|
|
@ -115,6 +115,27 @@ enum ath6kl_fw_capability {
|
|||
*/
|
||||
ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST,
|
||||
|
||||
/* Firmware supports filtering BSS results by RSSI */
|
||||
ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD,
|
||||
|
||||
/* FW sets mac_addr[4] ^= 0x80 for newly created interfaces */
|
||||
ATH6KL_FW_CAPABILITY_CUSTOM_MAC_ADDR,
|
||||
|
||||
/* Firmware supports TX error rate notification */
|
||||
ATH6KL_FW_CAPABILITY_TX_ERR_NOTIFY,
|
||||
|
||||
/* supports WMI_SET_REGDOMAIN_CMDID command */
|
||||
ATH6KL_FW_CAPABILITY_REGDOMAIN,
|
||||
|
||||
/* Firmware supports sched scan decoupled from host sleep */
|
||||
ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2,
|
||||
|
||||
/*
|
||||
* Firmware capability for hang detection through heart beat
|
||||
* challenge messages.
|
||||
*/
|
||||
ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL,
|
||||
|
||||
/* this needs to be last */
|
||||
ATH6KL_FW_CAPABILITY_MAX,
|
||||
};
|
||||
|
@ -128,11 +149,15 @@ struct ath6kl_fw_ie {
|
|||
};
|
||||
|
||||
enum ath6kl_hw_flags {
|
||||
ATH6KL_HW_FLAG_64BIT_RATES = BIT(0),
|
||||
ATH6KL_HW_64BIT_RATES = BIT(0),
|
||||
ATH6KL_HW_AP_INACTIVITY_MINS = BIT(1),
|
||||
ATH6KL_HW_MAP_LP_ENDPOINT = BIT(2),
|
||||
ATH6KL_HW_SDIO_CRC_ERROR_WAR = BIT(3),
|
||||
};
|
||||
|
||||
#define ATH6KL_FW_API2_FILE "fw-2.bin"
|
||||
#define ATH6KL_FW_API3_FILE "fw-3.bin"
|
||||
#define ATH6KL_FW_API4_FILE "fw-4.bin"
|
||||
|
||||
/* AR6003 1.0 definitions */
|
||||
#define AR6003_HW_1_0_VERSION 0x300002ba
|
||||
|
@ -186,6 +211,13 @@ enum ath6kl_hw_flags {
|
|||
#define AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE \
|
||||
AR6004_HW_1_2_FW_DIR "/bdata.bin"
|
||||
|
||||
/* AR6004 1.3 definitions */
|
||||
#define AR6004_HW_1_3_VERSION 0x31c8088a
|
||||
#define AR6004_HW_1_3_FW_DIR "ath6k/AR6004/hw1.3"
|
||||
#define AR6004_HW_1_3_FIRMWARE_FILE "fw.ram.bin"
|
||||
#define AR6004_HW_1_3_BOARD_DATA_FILE "ath6k/AR6004/hw1.3/bdata.bin"
|
||||
#define AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE "ath6k/AR6004/hw1.3/bdata.bin"
|
||||
|
||||
/* Per STA data, used in AP mode */
|
||||
#define STA_PS_AWAKE BIT(0)
|
||||
#define STA_PS_SLEEP BIT(1)
|
||||
|
@ -536,6 +568,7 @@ enum ath6kl_vif_state {
|
|||
HOST_SLEEP_MODE_CMD_PROCESSED,
|
||||
NETDEV_MCAST_ALL_ON,
|
||||
NETDEV_MCAST_ALL_OFF,
|
||||
SCHED_SCANNING,
|
||||
};
|
||||
|
||||
struct ath6kl_vif {
|
||||
|
@ -580,11 +613,13 @@ struct ath6kl_vif {
|
|||
u16 assoc_bss_beacon_int;
|
||||
u16 listen_intvl_t;
|
||||
u16 bmiss_time_t;
|
||||
u32 txe_intvl;
|
||||
u16 bg_scan_period;
|
||||
u8 assoc_bss_dtim_period;
|
||||
struct net_device_stats net_stats;
|
||||
struct target_stats target_stats;
|
||||
struct wmi_connect_cmd profile;
|
||||
u16 rsn_capab;
|
||||
|
||||
struct list_head mc_filter;
|
||||
};
|
||||
|
@ -609,6 +644,7 @@ enum ath6kl_dev_state {
|
|||
SKIP_SCAN,
|
||||
ROAM_TBL_PEND,
|
||||
FIRST_BOOT,
|
||||
RECOVERY_CLEANUP,
|
||||
};
|
||||
|
||||
enum ath6kl_state {
|
||||
|
@ -619,7 +655,16 @@ enum ath6kl_state {
|
|||
ATH6KL_STATE_DEEPSLEEP,
|
||||
ATH6KL_STATE_CUTPOWER,
|
||||
ATH6KL_STATE_WOW,
|
||||
ATH6KL_STATE_SCHED_SCAN,
|
||||
ATH6KL_STATE_RECOVERY,
|
||||
};
|
||||
|
||||
/* Fw error recovery */
|
||||
#define ATH6KL_HB_RESP_MISS_THRES 5
|
||||
|
||||
enum ath6kl_fw_err {
|
||||
ATH6KL_FW_ASSERT,
|
||||
ATH6KL_FW_HB_RESP_FAILURE,
|
||||
ATH6KL_FW_EP_FULL,
|
||||
};
|
||||
|
||||
struct ath6kl {
|
||||
|
@ -679,6 +724,7 @@ struct ath6kl {
|
|||
struct ath6kl_req_key ap_mode_bkey;
|
||||
struct sk_buff_head mcastpsq;
|
||||
u32 want_ch_switch;
|
||||
u16 last_ch;
|
||||
|
||||
/*
|
||||
* FIXME: protects access to mcastpsq but is actually useless as
|
||||
|
@ -764,6 +810,17 @@ struct ath6kl {
|
|||
|
||||
bool wiphy_registered;
|
||||
|
||||
struct ath6kl_fw_recovery {
|
||||
struct work_struct recovery_work;
|
||||
unsigned long err_reason;
|
||||
unsigned long hb_poll;
|
||||
struct timer_list hb_timer;
|
||||
u32 seq_num;
|
||||
bool hb_pending;
|
||||
u8 hb_misscnt;
|
||||
bool enable;
|
||||
} fw_recovery;
|
||||
|
||||
#ifdef CONFIG_ATH6KL_DEBUG
|
||||
struct {
|
||||
struct sk_buff_head fwlog_queue;
|
||||
|
@ -899,4 +956,12 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type);
|
|||
void ath6kl_core_cleanup(struct ath6kl *ar);
|
||||
void ath6kl_core_destroy(struct ath6kl *ar);
|
||||
|
||||
/* Fw error recovery */
|
||||
void ath6kl_init_hw_restart(struct ath6kl *ar);
|
||||
void ath6kl_recovery_err_notify(struct ath6kl *ar, enum ath6kl_fw_err reason);
|
||||
void ath6kl_recovery_hb_event(struct ath6kl *ar, u32 cookie);
|
||||
void ath6kl_recovery_init(struct ath6kl *ar);
|
||||
void ath6kl_recovery_cleanup(struct ath6kl *ar);
|
||||
void ath6kl_recovery_suspend(struct ath6kl *ar);
|
||||
void ath6kl_recovery_resume(struct ath6kl *ar);
|
||||
#endif /* CORE_H */
|
||||
|
|
|
@ -44,6 +44,7 @@ enum ATH6K_DEBUG_MASK {
|
|||
ATH6KL_DBG_SUSPEND = BIT(20),
|
||||
ATH6KL_DBG_USB = BIT(21),
|
||||
ATH6KL_DBG_USB_BULK = BIT(22),
|
||||
ATH6KL_DBG_RECOVERY = BIT(23),
|
||||
ATH6KL_DBG_ANY = 0xffffffff /* enable all logs */
|
||||
};
|
||||
|
||||
|
|
|
@ -136,6 +136,7 @@ static int ath6kl_hif_proc_dbg_intr(struct ath6kl_device *dev)
|
|||
|
||||
ath6kl_hif_dump_fw_crash(dev->ar);
|
||||
ath6kl_read_fwlogs(dev->ar);
|
||||
ath6kl_recovery_err_notify(dev->ar, ATH6KL_FW_ASSERT);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -338,8 +339,7 @@ static int ath6kl_hif_proc_err_intr(struct ath6kl_device *dev)
|
|||
status = hif_read_write_sync(dev->ar, ERROR_INT_STATUS_ADDRESS,
|
||||
reg_buf, 4, HIF_WR_SYNC_BYTE_FIX);
|
||||
|
||||
if (status)
|
||||
WARN_ON(1);
|
||||
WARN_ON(status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -383,8 +383,7 @@ static int ath6kl_hif_proc_cpu_intr(struct ath6kl_device *dev)
|
|||
status = hif_read_write_sync(dev->ar, CPU_INT_STATUS_ADDRESS,
|
||||
reg_buf, 4, HIF_WR_SYNC_BYTE_FIX);
|
||||
|
||||
if (status)
|
||||
WARN_ON(1);
|
||||
WARN_ON(status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -695,11 +694,6 @@ int ath6kl_hif_setup(struct ath6kl_device *dev)
|
|||
ath6kl_dbg(ATH6KL_DBG_HIF, "hif block size %d mbox addr 0x%x\n",
|
||||
dev->htc_cnxt->block_sz, dev->ar->mbox_info.htc_addr);
|
||||
|
||||
/* usb doesn't support enabling interrupts */
|
||||
/* FIXME: remove check once USB support is implemented */
|
||||
if (dev->ar->hif_type == ATH6KL_HIF_TYPE_USB)
|
||||
return 0;
|
||||
|
||||
status = ath6kl_hif_disable_intrs(dev);
|
||||
|
||||
fail_setup:
|
||||
|
|
|
@ -2492,7 +2492,8 @@ static int ath6kl_htc_mbox_conn_service(struct htc_target *target,
|
|||
max_msg_sz = le16_to_cpu(resp_msg->max_msg_sz);
|
||||
}
|
||||
|
||||
if (assigned_ep >= ENDPOINT_MAX || !max_msg_sz) {
|
||||
if (WARN_ON_ONCE(assigned_ep == ENDPOINT_UNUSED ||
|
||||
assigned_ep >= ENDPOINT_MAX || !max_msg_sz)) {
|
||||
status = -ENOMEM;
|
||||
goto fail_tx;
|
||||
}
|
||||
|
@ -2655,12 +2656,6 @@ static int ath6kl_htc_mbox_wait_target(struct htc_target *target)
|
|||
struct htc_service_connect_resp resp;
|
||||
int status;
|
||||
|
||||
/* FIXME: remove once USB support is implemented */
|
||||
if (target->dev->ar->hif_type == ATH6KL_HIF_TYPE_USB) {
|
||||
ath6kl_err("HTC doesn't support USB yet. Patience!\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* we should be getting 1 control message that the target is ready */
|
||||
packet = htc_wait_for_ctrl_msg(target);
|
||||
|
||||
|
@ -2890,9 +2885,7 @@ static void ath6kl_htc_mbox_cleanup(struct htc_target *target)
|
|||
{
|
||||
struct htc_packet *packet, *tmp_packet;
|
||||
|
||||
/* FIXME: remove check once USB support is implemented */
|
||||
if (target->dev->ar->hif_type != ATH6KL_HIF_TYPE_USB)
|
||||
ath6kl_hif_cleanup_scatter(target->dev->ar);
|
||||
ath6kl_hif_cleanup_scatter(target->dev->ar);
|
||||
|
||||
list_for_each_entry_safe(packet, tmp_packet,
|
||||
&target->free_ctrl_txbuf, list) {
|
||||
|
|
|
@ -374,9 +374,8 @@ static enum htc_send_queue_result htc_try_send(struct htc_target *target,
|
|||
packet = list_first_entry(txq,
|
||||
struct htc_packet,
|
||||
list);
|
||||
list_del(&packet->list);
|
||||
/* insert into local queue */
|
||||
list_add_tail(&packet->list, &send_queue);
|
||||
/* move to local queue */
|
||||
list_move_tail(&packet->list, &send_queue);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -399,11 +398,10 @@ static enum htc_send_queue_result htc_try_send(struct htc_target *target,
|
|||
* for cleanup */
|
||||
} else {
|
||||
/* callback wants to keep this packet,
|
||||
* remove from caller's queue */
|
||||
list_del(&packet->list);
|
||||
/* put it in the send queue */
|
||||
list_add_tail(&packet->list,
|
||||
&send_queue);
|
||||
* move from caller's queue to the send
|
||||
* queue */
|
||||
list_move_tail(&packet->list,
|
||||
&send_queue);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ static const struct ath6kl_hw hw_list[] = {
|
|||
.reserved_ram_size = 6912,
|
||||
.refclk_hz = 26000000,
|
||||
.uarttx_pin = 8,
|
||||
.flags = 0,
|
||||
.flags = ATH6KL_HW_SDIO_CRC_ERROR_WAR,
|
||||
|
||||
/* hw2.0 needs override address hardcoded */
|
||||
.app_start_override_addr = 0x944C00,
|
||||
|
@ -68,7 +68,7 @@ static const struct ath6kl_hw hw_list[] = {
|
|||
.refclk_hz = 26000000,
|
||||
.uarttx_pin = 8,
|
||||
.testscript_addr = 0x57ef74,
|
||||
.flags = 0,
|
||||
.flags = ATH6KL_HW_SDIO_CRC_ERROR_WAR,
|
||||
|
||||
.fw = {
|
||||
.dir = AR6003_HW_2_1_1_FW_DIR,
|
||||
|
@ -93,7 +93,8 @@ static const struct ath6kl_hw hw_list[] = {
|
|||
.board_addr = 0x433900,
|
||||
.refclk_hz = 26000000,
|
||||
.uarttx_pin = 11,
|
||||
.flags = ATH6KL_HW_FLAG_64BIT_RATES,
|
||||
.flags = ATH6KL_HW_64BIT_RATES |
|
||||
ATH6KL_HW_AP_INACTIVITY_MINS,
|
||||
|
||||
.fw = {
|
||||
.dir = AR6004_HW_1_0_FW_DIR,
|
||||
|
@ -113,8 +114,8 @@ static const struct ath6kl_hw hw_list[] = {
|
|||
.board_addr = 0x43d400,
|
||||
.refclk_hz = 40000000,
|
||||
.uarttx_pin = 11,
|
||||
.flags = ATH6KL_HW_FLAG_64BIT_RATES,
|
||||
|
||||
.flags = ATH6KL_HW_64BIT_RATES |
|
||||
ATH6KL_HW_AP_INACTIVITY_MINS,
|
||||
.fw = {
|
||||
.dir = AR6004_HW_1_1_FW_DIR,
|
||||
.fw = AR6004_HW_1_1_FIRMWARE_FILE,
|
||||
|
@ -133,7 +134,8 @@ static const struct ath6kl_hw hw_list[] = {
|
|||
.board_addr = 0x435c00,
|
||||
.refclk_hz = 40000000,
|
||||
.uarttx_pin = 11,
|
||||
.flags = ATH6KL_HW_FLAG_64BIT_RATES,
|
||||
.flags = ATH6KL_HW_64BIT_RATES |
|
||||
ATH6KL_HW_AP_INACTIVITY_MINS,
|
||||
|
||||
.fw = {
|
||||
.dir = AR6004_HW_1_2_FW_DIR,
|
||||
|
@ -142,6 +144,28 @@ static const struct ath6kl_hw hw_list[] = {
|
|||
.fw_board = AR6004_HW_1_2_BOARD_DATA_FILE,
|
||||
.fw_default_board = AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE,
|
||||
},
|
||||
{
|
||||
.id = AR6004_HW_1_3_VERSION,
|
||||
.name = "ar6004 hw 1.3",
|
||||
.dataset_patch_addr = 0x437860,
|
||||
.app_load_addr = 0x1234,
|
||||
.board_ext_data_addr = 0x437000,
|
||||
.reserved_ram_size = 7168,
|
||||
.board_addr = 0x436400,
|
||||
.refclk_hz = 40000000,
|
||||
.uarttx_pin = 11,
|
||||
.flags = ATH6KL_HW_64BIT_RATES |
|
||||
ATH6KL_HW_AP_INACTIVITY_MINS |
|
||||
ATH6KL_HW_MAP_LP_ENDPOINT,
|
||||
|
||||
.fw = {
|
||||
.dir = AR6004_HW_1_3_FW_DIR,
|
||||
.fw = AR6004_HW_1_3_FIRMWARE_FILE,
|
||||
},
|
||||
|
||||
.fw_board = AR6004_HW_1_3_BOARD_DATA_FILE,
|
||||
.fw_default_board = AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -337,7 +361,7 @@ static int ath6kl_init_service_ep(struct ath6kl *ar)
|
|||
if (ath6kl_connectservice(ar, &connect, "WMI DATA BK"))
|
||||
return -EIO;
|
||||
|
||||
/* connect to Video service, map this to to HI PRI */
|
||||
/* connect to Video service, map this to HI PRI */
|
||||
connect.svc_id = WMI_DATA_VI_SVC;
|
||||
if (ath6kl_connectservice(ar, &connect, "WMI DATA VI"))
|
||||
return -EIO;
|
||||
|
@ -1088,6 +1112,12 @@ int ath6kl_init_fetch_firmwares(struct ath6kl *ar)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API4_FILE);
|
||||
if (ret == 0) {
|
||||
ar->fw_api = 4;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API3_FILE);
|
||||
if (ret == 0) {
|
||||
ar->fw_api = 3;
|
||||
|
@ -1401,8 +1431,7 @@ static int ath6kl_init_upload(struct ath6kl *ar)
|
|||
return status;
|
||||
|
||||
/* WAR to avoid SDIO CRC err */
|
||||
if (ar->version.target_ver == AR6003_HW_2_0_VERSION ||
|
||||
ar->version.target_ver == AR6003_HW_2_1_1_VERSION) {
|
||||
if (ar->hw.flags & ATH6KL_HW_SDIO_CRC_ERROR_WAR) {
|
||||
ath6kl_err("temporary war to avoid sdio crc error\n");
|
||||
|
||||
param = 0x28;
|
||||
|
@ -1520,7 +1549,7 @@ static const char *ath6kl_init_get_hif_name(enum ath6kl_hif_type type)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int ath6kl_init_hw_start(struct ath6kl *ar)
|
||||
static int __ath6kl_init_hw_start(struct ath6kl *ar)
|
||||
{
|
||||
long timeleft;
|
||||
int ret, i;
|
||||
|
@ -1616,8 +1645,6 @@ int ath6kl_init_hw_start(struct ath6kl *ar)
|
|||
goto err_htc_stop;
|
||||
}
|
||||
|
||||
ar->state = ATH6KL_STATE_ON;
|
||||
|
||||
return 0;
|
||||
|
||||
err_htc_stop:
|
||||
|
@ -1630,7 +1657,18 @@ err_power_off:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int ath6kl_init_hw_stop(struct ath6kl *ar)
|
||||
int ath6kl_init_hw_start(struct ath6kl *ar)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = __ath6kl_init_hw_start(ar);
|
||||
if (err)
|
||||
return err;
|
||||
ar->state = ATH6KL_STATE_ON;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __ath6kl_init_hw_stop(struct ath6kl *ar)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -1646,11 +1684,37 @@ int ath6kl_init_hw_stop(struct ath6kl *ar)
|
|||
if (ret)
|
||||
ath6kl_warn("failed to power off hif: %d\n", ret);
|
||||
|
||||
ar->state = ATH6KL_STATE_OFF;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath6kl_init_hw_stop(struct ath6kl *ar)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = __ath6kl_init_hw_stop(ar);
|
||||
if (err)
|
||||
return err;
|
||||
ar->state = ATH6KL_STATE_OFF;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ath6kl_init_hw_restart(struct ath6kl *ar)
|
||||
{
|
||||
clear_bit(WMI_READY, &ar->flag);
|
||||
|
||||
ath6kl_cfg80211_stop_all(ar);
|
||||
|
||||
if (__ath6kl_init_hw_stop(ar)) {
|
||||
ath6kl_dbg(ATH6KL_DBG_RECOVERY, "Failed to stop during fw error recovery\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (__ath6kl_init_hw_start(ar)) {
|
||||
ath6kl_dbg(ATH6KL_DBG_RECOVERY, "Failed to restart during fw error recovery\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: move this to cfg80211.c and rename to ath6kl_cfg80211_vif_stop() */
|
||||
void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready)
|
||||
{
|
||||
|
|
|
@ -293,13 +293,17 @@ int ath6kl_read_fwlogs(struct ath6kl *ar)
|
|||
}
|
||||
|
||||
address = TARG_VTOP(ar->target_type, debug_hdr_addr);
|
||||
ath6kl_diag_read(ar, address, &debug_hdr, sizeof(debug_hdr));
|
||||
ret = ath6kl_diag_read(ar, address, &debug_hdr, sizeof(debug_hdr));
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
address = TARG_VTOP(ar->target_type,
|
||||
le32_to_cpu(debug_hdr.dbuf_addr));
|
||||
firstbuf = address;
|
||||
dropped = le32_to_cpu(debug_hdr.dropped);
|
||||
ath6kl_diag_read(ar, address, &debug_buf, sizeof(debug_buf));
|
||||
ret = ath6kl_diag_read(ar, address, &debug_buf, sizeof(debug_buf));
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
loop = 100;
|
||||
|
||||
|
@ -322,7 +326,8 @@ int ath6kl_read_fwlogs(struct ath6kl *ar)
|
|||
|
||||
address = TARG_VTOP(ar->target_type,
|
||||
le32_to_cpu(debug_buf.next));
|
||||
ath6kl_diag_read(ar, address, &debug_buf, sizeof(debug_buf));
|
||||
ret = ath6kl_diag_read(ar, address, &debug_buf,
|
||||
sizeof(debug_buf));
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
|
@ -436,12 +441,9 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel)
|
|||
break;
|
||||
}
|
||||
|
||||
if (ar->want_ch_switch & (1 << vif->fw_vif_idx)) {
|
||||
ar->want_ch_switch &= ~(1 << vif->fw_vif_idx);
|
||||
if (ar->last_ch != channel)
|
||||
/* we actually don't know the phymode, default to HT20 */
|
||||
ath6kl_cfg80211_ch_switch_notify(vif, channel,
|
||||
WMI_11G_HT20);
|
||||
}
|
||||
ath6kl_cfg80211_ch_switch_notify(vif, channel, WMI_11G_HT20);
|
||||
|
||||
ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, NONE_BSS_FILTER, 0);
|
||||
set_bit(CONNECTED, &vif->flags);
|
||||
|
@ -606,6 +608,18 @@ static int ath6kl_commit_ch_switch(struct ath6kl_vif *vif, u16 channel)
|
|||
|
||||
switch (vif->nw_type) {
|
||||
case AP_NETWORK:
|
||||
/*
|
||||
* reconfigure any saved RSN IE capabilites in the beacon /
|
||||
* probe response to stay in sync with the supplicant.
|
||||
*/
|
||||
if (vif->rsn_capab &&
|
||||
test_bit(ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE,
|
||||
ar->fw_capabilities))
|
||||
ath6kl_wmi_set_ie_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
WLAN_EID_RSN, WMI_RSN_IE_CAPB,
|
||||
(const u8 *) &vif->rsn_capab,
|
||||
sizeof(vif->rsn_capab));
|
||||
|
||||
return ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx,
|
||||
&vif->profile);
|
||||
default:
|
||||
|
@ -628,6 +642,9 @@ static void ath6kl_check_ch_switch(struct ath6kl *ar, u16 channel)
|
|||
if (ar->want_ch_switch & (1 << vif->fw_vif_idx))
|
||||
res = ath6kl_commit_ch_switch(vif, channel);
|
||||
|
||||
/* if channel switch failed, oh well we tried */
|
||||
ar->want_ch_switch &= ~(1 << vif->fw_vif_idx);
|
||||
|
||||
if (res)
|
||||
ath6kl_err("channel switch failed nw_type %d res %d\n",
|
||||
vif->nw_type, res);
|
||||
|
@ -981,8 +998,25 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid,
|
|||
if (vif->nw_type == AP_NETWORK) {
|
||||
/* disconnect due to other STA vif switching channels */
|
||||
if (reason == BSS_DISCONNECTED &&
|
||||
prot_reason_status == WMI_AP_REASON_STA_ROAM)
|
||||
prot_reason_status == WMI_AP_REASON_STA_ROAM) {
|
||||
ar->want_ch_switch |= 1 << vif->fw_vif_idx;
|
||||
/* bail back to this channel if STA vif fails connect */
|
||||
ar->last_ch = le16_to_cpu(vif->profile.ch);
|
||||
}
|
||||
|
||||
if (prot_reason_status == WMI_AP_REASON_MAX_STA) {
|
||||
/* send max client reached notification to user space */
|
||||
cfg80211_conn_failed(vif->ndev, bssid,
|
||||
NL80211_CONN_FAIL_MAX_CLIENTS,
|
||||
GFP_KERNEL);
|
||||
}
|
||||
|
||||
if (prot_reason_status == WMI_AP_REASON_ACL) {
|
||||
/* send blocked client notification to user space */
|
||||
cfg80211_conn_failed(vif->ndev, bssid,
|
||||
NL80211_CONN_FAIL_BLOCKED_CLIENT,
|
||||
GFP_KERNEL);
|
||||
}
|
||||
|
||||
if (!ath6kl_remove_sta(ar, bssid, prot_reason_status))
|
||||
return;
|
||||
|
@ -1041,6 +1075,9 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid,
|
|||
}
|
||||
}
|
||||
|
||||
/* restart disconnected concurrent vifs waiting for new channel */
|
||||
ath6kl_check_ch_switch(ar, ar->last_ch);
|
||||
|
||||
/* update connect & link status atomically */
|
||||
spin_lock_bh(&vif->if_lock);
|
||||
clear_bit(CONNECTED, &vif->flags);
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Qualcomm Atheros, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "cfg80211.h"
|
||||
#include "debug.h"
|
||||
|
||||
static void ath6kl_recovery_work(struct work_struct *work)
|
||||
{
|
||||
struct ath6kl *ar = container_of(work, struct ath6kl,
|
||||
fw_recovery.recovery_work);
|
||||
|
||||
ar->state = ATH6KL_STATE_RECOVERY;
|
||||
|
||||
del_timer_sync(&ar->fw_recovery.hb_timer);
|
||||
|
||||
ath6kl_init_hw_restart(ar);
|
||||
|
||||
ar->state = ATH6KL_STATE_ON;
|
||||
clear_bit(WMI_CTRL_EP_FULL, &ar->flag);
|
||||
|
||||
ar->fw_recovery.err_reason = 0;
|
||||
|
||||
if (ar->fw_recovery.hb_poll)
|
||||
mod_timer(&ar->fw_recovery.hb_timer, jiffies +
|
||||
msecs_to_jiffies(ar->fw_recovery.hb_poll));
|
||||
}
|
||||
|
||||
void ath6kl_recovery_err_notify(struct ath6kl *ar, enum ath6kl_fw_err reason)
|
||||
{
|
||||
if (!ar->fw_recovery.enable)
|
||||
return;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_RECOVERY, "Fw error detected, reason:%d\n",
|
||||
reason);
|
||||
|
||||
set_bit(reason, &ar->fw_recovery.err_reason);
|
||||
|
||||
if (!test_bit(RECOVERY_CLEANUP, &ar->flag) &&
|
||||
ar->state != ATH6KL_STATE_RECOVERY)
|
||||
queue_work(ar->ath6kl_wq, &ar->fw_recovery.recovery_work);
|
||||
}
|
||||
|
||||
void ath6kl_recovery_hb_event(struct ath6kl *ar, u32 cookie)
|
||||
{
|
||||
if (cookie == ar->fw_recovery.seq_num)
|
||||
ar->fw_recovery.hb_pending = false;
|
||||
}
|
||||
|
||||
static void ath6kl_recovery_hb_timer(unsigned long data)
|
||||
{
|
||||
struct ath6kl *ar = (struct ath6kl *) data;
|
||||
int err;
|
||||
|
||||
if (test_bit(RECOVERY_CLEANUP, &ar->flag) ||
|
||||
(ar->state == ATH6KL_STATE_RECOVERY))
|
||||
return;
|
||||
|
||||
if (ar->fw_recovery.hb_pending)
|
||||
ar->fw_recovery.hb_misscnt++;
|
||||
else
|
||||
ar->fw_recovery.hb_misscnt = 0;
|
||||
|
||||
if (ar->fw_recovery.hb_misscnt > ATH6KL_HB_RESP_MISS_THRES) {
|
||||
ar->fw_recovery.hb_misscnt = 0;
|
||||
ar->fw_recovery.seq_num = 0;
|
||||
ar->fw_recovery.hb_pending = false;
|
||||
ath6kl_recovery_err_notify(ar, ATH6KL_FW_HB_RESP_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
ar->fw_recovery.seq_num++;
|
||||
ar->fw_recovery.hb_pending = true;
|
||||
|
||||
err = ath6kl_wmi_get_challenge_resp_cmd(ar->wmi,
|
||||
ar->fw_recovery.seq_num, 0);
|
||||
if (err)
|
||||
ath6kl_warn("Failed to send hb challenge request, err:%d\n",
|
||||
err);
|
||||
|
||||
mod_timer(&ar->fw_recovery.hb_timer, jiffies +
|
||||
msecs_to_jiffies(ar->fw_recovery.hb_poll));
|
||||
}
|
||||
|
||||
void ath6kl_recovery_init(struct ath6kl *ar)
|
||||
{
|
||||
struct ath6kl_fw_recovery *recovery = &ar->fw_recovery;
|
||||
|
||||
clear_bit(RECOVERY_CLEANUP, &ar->flag);
|
||||
INIT_WORK(&recovery->recovery_work, ath6kl_recovery_work);
|
||||
recovery->seq_num = 0;
|
||||
recovery->hb_misscnt = 0;
|
||||
ar->fw_recovery.hb_pending = false;
|
||||
ar->fw_recovery.hb_timer.function = ath6kl_recovery_hb_timer;
|
||||
ar->fw_recovery.hb_timer.data = (unsigned long) ar;
|
||||
init_timer_deferrable(&ar->fw_recovery.hb_timer);
|
||||
|
||||
if (ar->fw_recovery.hb_poll)
|
||||
mod_timer(&ar->fw_recovery.hb_timer, jiffies +
|
||||
msecs_to_jiffies(ar->fw_recovery.hb_poll));
|
||||
}
|
||||
|
||||
void ath6kl_recovery_cleanup(struct ath6kl *ar)
|
||||
{
|
||||
if (!ar->fw_recovery.enable)
|
||||
return;
|
||||
|
||||
set_bit(RECOVERY_CLEANUP, &ar->flag);
|
||||
|
||||
del_timer_sync(&ar->fw_recovery.hb_timer);
|
||||
cancel_work_sync(&ar->fw_recovery.recovery_work);
|
||||
}
|
||||
|
||||
void ath6kl_recovery_suspend(struct ath6kl *ar)
|
||||
{
|
||||
if (!ar->fw_recovery.enable)
|
||||
return;
|
||||
|
||||
ath6kl_recovery_cleanup(ar);
|
||||
|
||||
if (!ar->fw_recovery.err_reason)
|
||||
return;
|
||||
|
||||
/* Process pending fw error detection */
|
||||
ar->fw_recovery.err_reason = 0;
|
||||
WARN_ON(ar->state != ATH6KL_STATE_ON);
|
||||
ar->state = ATH6KL_STATE_RECOVERY;
|
||||
ath6kl_init_hw_restart(ar);
|
||||
ar->state = ATH6KL_STATE_ON;
|
||||
}
|
||||
|
||||
void ath6kl_recovery_resume(struct ath6kl *ar)
|
||||
{
|
||||
if (!ar->fw_recovery.enable)
|
||||
return;
|
||||
|
||||
clear_bit(RECOVERY_CLEANUP, &ar->flag);
|
||||
|
||||
if (!ar->fw_recovery.hb_poll)
|
||||
return;
|
||||
|
||||
ar->fw_recovery.hb_pending = false;
|
||||
ar->fw_recovery.seq_num = 0;
|
||||
ar->fw_recovery.hb_misscnt = 0;
|
||||
mod_timer(&ar->fw_recovery.hb_timer,
|
||||
jiffies + msecs_to_jiffies(ar->fw_recovery.hb_poll));
|
||||
}
|
|
@ -709,7 +709,7 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar)
|
|||
{
|
||||
struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
|
||||
struct htc_target *target = ar->htc_target;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
bool virt_scat = false;
|
||||
|
||||
if (ar_sdio->scatter_enabled)
|
||||
|
@ -844,22 +844,6 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
|
|||
bool try_deepsleep = false;
|
||||
int ret;
|
||||
|
||||
if (ar->state == ATH6KL_STATE_SCHED_SCAN) {
|
||||
ath6kl_dbg(ATH6KL_DBG_SUSPEND, "sched scan is in progress\n");
|
||||
|
||||
ret = ath6kl_set_sdio_pm_caps(ar);
|
||||
if (ret)
|
||||
goto cut_pwr;
|
||||
|
||||
ret = ath6kl_cfg80211_suspend(ar,
|
||||
ATH6KL_CFG_SUSPEND_SCHED_SCAN,
|
||||
NULL);
|
||||
if (ret)
|
||||
goto cut_pwr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ar->suspend_mode == WLAN_POWER_STATE_WOW ||
|
||||
(!ar->suspend_mode && wow)) {
|
||||
|
||||
|
@ -942,14 +926,14 @@ static int ath6kl_sdio_resume(struct ath6kl *ar)
|
|||
case ATH6KL_STATE_WOW:
|
||||
break;
|
||||
|
||||
case ATH6KL_STATE_SCHED_SCAN:
|
||||
break;
|
||||
|
||||
case ATH6KL_STATE_SUSPENDING:
|
||||
break;
|
||||
|
||||
case ATH6KL_STATE_RESUMING:
|
||||
break;
|
||||
|
||||
case ATH6KL_STATE_RECOVERY:
|
||||
break;
|
||||
}
|
||||
|
||||
ath6kl_cfg80211_resume(ar);
|
||||
|
@ -1462,3 +1446,6 @@ MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE);
|
|||
MODULE_FIRMWARE(AR6004_HW_1_2_FW_DIR "/" AR6004_HW_1_2_FIRMWARE_FILE);
|
||||
MODULE_FIRMWARE(AR6004_HW_1_2_BOARD_DATA_FILE);
|
||||
MODULE_FIRMWARE(AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE);
|
||||
MODULE_FIRMWARE(AR6004_HW_1_3_FW_DIR "/" AR6004_HW_1_3_FIRMWARE_FILE);
|
||||
MODULE_FIRMWARE(AR6004_HW_1_3_BOARD_DATA_FILE);
|
||||
MODULE_FIRMWARE(AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE);
|
||||
|
|
|
@ -288,8 +288,16 @@ int ath6kl_control_tx(void *devt, struct sk_buff *skb,
|
|||
int status = 0;
|
||||
struct ath6kl_cookie *cookie = NULL;
|
||||
|
||||
if (WARN_ON_ONCE(ar->state == ATH6KL_STATE_WOW))
|
||||
if (WARN_ON_ONCE(ar->state == ATH6KL_STATE_WOW)) {
|
||||
dev_kfree_skb(skb);
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
if (WARN_ON_ONCE(eid == ENDPOINT_UNUSED ||
|
||||
eid >= ENDPOINT_MAX)) {
|
||||
status = -EINVAL;
|
||||
goto fail_ctrl_tx;
|
||||
}
|
||||
|
||||
spin_lock_bh(&ar->lock);
|
||||
|
||||
|
@ -591,6 +599,7 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
|
|||
*/
|
||||
set_bit(WMI_CTRL_EP_FULL, &ar->flag);
|
||||
ath6kl_err("wmi ctrl ep is full\n");
|
||||
ath6kl_recovery_err_notify(ar, ATH6KL_FW_EP_FULL);
|
||||
return action;
|
||||
}
|
||||
|
||||
|
@ -695,22 +704,31 @@ void ath6kl_tx_complete(struct htc_target *target,
|
|||
list);
|
||||
list_del(&packet->list);
|
||||
|
||||
if (WARN_ON_ONCE(packet->endpoint == ENDPOINT_UNUSED ||
|
||||
packet->endpoint >= ENDPOINT_MAX))
|
||||
continue;
|
||||
|
||||
ath6kl_cookie = (struct ath6kl_cookie *)packet->pkt_cntxt;
|
||||
if (!ath6kl_cookie)
|
||||
goto fatal;
|
||||
if (WARN_ON_ONCE(!ath6kl_cookie))
|
||||
continue;
|
||||
|
||||
status = packet->status;
|
||||
skb = ath6kl_cookie->skb;
|
||||
eid = packet->endpoint;
|
||||
map_no = ath6kl_cookie->map_no;
|
||||
|
||||
if (!skb || !skb->data)
|
||||
goto fatal;
|
||||
if (WARN_ON_ONCE(!skb || !skb->data)) {
|
||||
dev_kfree_skb(skb);
|
||||
ath6kl_free_cookie(ar, ath6kl_cookie);
|
||||
continue;
|
||||
}
|
||||
|
||||
__skb_queue_tail(&skb_queue, skb);
|
||||
|
||||
if (!status && (packet->act_len != skb->len))
|
||||
goto fatal;
|
||||
if (WARN_ON_ONCE(!status && (packet->act_len != skb->len))) {
|
||||
ath6kl_free_cookie(ar, ath6kl_cookie);
|
||||
continue;
|
||||
}
|
||||
|
||||
ar->tx_pending[eid]--;
|
||||
|
||||
|
@ -792,11 +810,6 @@ void ath6kl_tx_complete(struct htc_target *target,
|
|||
wake_up(&ar->event_wq);
|
||||
|
||||
return;
|
||||
|
||||
fatal:
|
||||
WARN_ON(1);
|
||||
spin_unlock_bh(&ar->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
void ath6kl_tx_data_cleanup(struct ath6kl *ar)
|
||||
|
@ -885,8 +898,11 @@ void ath6kl_rx_refill(struct htc_target *target, enum htc_endpoint_id endpoint)
|
|||
break;
|
||||
|
||||
packet = (struct htc_packet *) skb->head;
|
||||
if (!IS_ALIGNED((unsigned long) skb->data, 4))
|
||||
if (!IS_ALIGNED((unsigned long) skb->data, 4)) {
|
||||
size_t len = skb_headlen(skb);
|
||||
skb->data = PTR_ALIGN(skb->data - 4, 4);
|
||||
skb_set_tail_pointer(skb, len);
|
||||
}
|
||||
set_htc_rxpkt_info(packet, skb, skb->data,
|
||||
ATH6KL_BUFFER_SIZE, endpoint);
|
||||
packet->skb = skb;
|
||||
|
@ -908,8 +924,11 @@ void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count)
|
|||
return;
|
||||
|
||||
packet = (struct htc_packet *) skb->head;
|
||||
if (!IS_ALIGNED((unsigned long) skb->data, 4))
|
||||
if (!IS_ALIGNED((unsigned long) skb->data, 4)) {
|
||||
size_t len = skb_headlen(skb);
|
||||
skb->data = PTR_ALIGN(skb->data - 4, 4);
|
||||
skb_set_tail_pointer(skb, len);
|
||||
}
|
||||
set_htc_rxpkt_info(packet, skb, skb->data,
|
||||
ATH6KL_AMSDU_BUFFER_SIZE, 0);
|
||||
packet->skb = skb;
|
||||
|
|
|
@ -185,9 +185,10 @@ static int ath6kl_usb_alloc_pipe_resources(struct ath6kl_usb_pipe *pipe,
|
|||
for (i = 0; i < urb_cnt; i++) {
|
||||
urb_context = kzalloc(sizeof(struct ath6kl_urb_context),
|
||||
GFP_KERNEL);
|
||||
if (urb_context == NULL)
|
||||
/* FIXME: set status to -ENOMEM */
|
||||
break;
|
||||
if (urb_context == NULL) {
|
||||
status = -ENOMEM;
|
||||
goto fail_alloc_pipe_resources;
|
||||
}
|
||||
|
||||
urb_context->pipe = pipe;
|
||||
|
||||
|
@ -204,6 +205,7 @@ static int ath6kl_usb_alloc_pipe_resources(struct ath6kl_usb_pipe *pipe,
|
|||
pipe->logical_pipe_num, pipe->usb_pipe_handle,
|
||||
pipe->urb_alloc);
|
||||
|
||||
fail_alloc_pipe_resources:
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -803,7 +805,11 @@ static int ath6kl_usb_map_service_pipe(struct ath6kl *ar, u16 svc_id,
|
|||
*dl_pipe = ATH6KL_USB_PIPE_RX_DATA;
|
||||
break;
|
||||
case WMI_DATA_VI_SVC:
|
||||
*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP;
|
||||
|
||||
if (ar->hw.flags & ATH6KL_HW_MAP_LP_ENDPOINT)
|
||||
*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP;
|
||||
else
|
||||
*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP;
|
||||
/*
|
||||
* Disable rxdata2 directly, it will be enabled
|
||||
* if FW enable rxdata2
|
||||
|
@ -811,7 +817,11 @@ static int ath6kl_usb_map_service_pipe(struct ath6kl *ar, u16 svc_id,
|
|||
*dl_pipe = ATH6KL_USB_PIPE_RX_DATA;
|
||||
break;
|
||||
case WMI_DATA_VO_SVC:
|
||||
*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_HP;
|
||||
|
||||
if (ar->hw.flags & ATH6KL_HW_MAP_LP_ENDPOINT)
|
||||
*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP;
|
||||
else
|
||||
*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP;
|
||||
/*
|
||||
* Disable rxdata2 directly, it will be enabled
|
||||
* if FW enable rxdata2
|
||||
|
@ -1196,7 +1206,14 @@ static struct usb_driver ath6kl_usb_driver = {
|
|||
|
||||
static int ath6kl_usb_init(void)
|
||||
{
|
||||
usb_register(&ath6kl_usb_driver);
|
||||
int ret;
|
||||
|
||||
ret = usb_register(&ath6kl_usb_driver);
|
||||
if (ret) {
|
||||
ath6kl_err("usb registration failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1220,3 +1237,6 @@ MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE);
|
|||
MODULE_FIRMWARE(AR6004_HW_1_2_FIRMWARE_FILE);
|
||||
MODULE_FIRMWARE(AR6004_HW_1_2_BOARD_DATA_FILE);
|
||||
MODULE_FIRMWARE(AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE);
|
||||
MODULE_FIRMWARE(AR6004_HW_1_3_FW_DIR "/" AR6004_HW_1_3_FIRMWARE_FILE);
|
||||
MODULE_FIRMWARE(AR6004_HW_1_3_BOARD_DATA_FILE);
|
||||
MODULE_FIRMWARE(AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE);
|
||||
|
|
|
@ -474,7 +474,7 @@ static int ath6kl_wmi_remain_on_chnl_event_rx(struct wmi *wmi, u8 *datap,
|
|||
return -EINVAL;
|
||||
}
|
||||
id = vif->last_roc_id;
|
||||
cfg80211_ready_on_channel(&vif->wdev, id, chan, NL80211_CHAN_NO_HT,
|
||||
cfg80211_ready_on_channel(&vif->wdev, id, chan,
|
||||
dur, GFP_ATOMIC);
|
||||
|
||||
return 0;
|
||||
|
@ -513,8 +513,7 @@ static int ath6kl_wmi_cancel_remain_on_chnl_event_rx(struct wmi *wmi,
|
|||
else
|
||||
id = vif->last_roc_id; /* timeout on uncanceled r-o-c */
|
||||
vif->last_cancel_roc_id = 0;
|
||||
cfg80211_remain_on_channel_expired(&vif->wdev, id, chan,
|
||||
NL80211_CHAN_NO_HT, GFP_ATOMIC);
|
||||
cfg80211_remain_on_channel_expired(&vif->wdev, id, chan, GFP_ATOMIC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -936,8 +935,12 @@ static void ath6kl_wmi_regdomain_event(struct wmi *wmi, u8 *datap, int len)
|
|||
|
||||
regpair = ath6kl_get_regpair((u16) reg_code);
|
||||
country = ath6kl_regd_find_country_by_rd((u16) reg_code);
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "Regpair used: 0x%0x\n",
|
||||
regpair->regDmnEnum);
|
||||
if (regpair)
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "Regpair used: 0x%0x\n",
|
||||
regpair->regDmnEnum);
|
||||
else
|
||||
ath6kl_warn("Regpair not found reg_code 0x%0x\n",
|
||||
reg_code);
|
||||
}
|
||||
|
||||
if (country && wmi->parent_dev->wiphy_registered) {
|
||||
|
@ -1116,7 +1119,7 @@ static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len,
|
|||
* the timer would not ever fire if the scan interval is short
|
||||
* enough.
|
||||
*/
|
||||
if (ar->state == ATH6KL_STATE_SCHED_SCAN &&
|
||||
if (test_bit(SCHED_SCANNING, &vif->flags) &&
|
||||
!timer_pending(&vif->sched_scan_timer)) {
|
||||
mod_timer(&vif->sched_scan_timer, jiffies +
|
||||
msecs_to_jiffies(ATH6KL_SCHED_SCAN_RESULT_DELAY));
|
||||
|
@ -1170,6 +1173,9 @@ static int ath6kl_wmi_bitrate_reply_rx(struct wmi *wmi, u8 *datap, int len)
|
|||
rate = RATE_AUTO;
|
||||
} else {
|
||||
index = reply->rate_index & 0x7f;
|
||||
if (WARN_ON_ONCE(index > (RATE_MCS_7_40 + 1)))
|
||||
return -EINVAL;
|
||||
|
||||
sgi = (reply->rate_index & 0x80) ? 1 : 0;
|
||||
rate = wmi_rate_tbl[index][sgi];
|
||||
}
|
||||
|
@ -1531,6 +1537,68 @@ static int ath6kl_wmi_cac_event_rx(struct wmi *wmi, u8 *datap, int len,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ath6kl_wmi_txe_notify_event_rx(struct wmi *wmi, u8 *datap, int len,
|
||||
struct ath6kl_vif *vif)
|
||||
{
|
||||
struct wmi_txe_notify_event *ev;
|
||||
u32 rate, pkts;
|
||||
|
||||
if (len < sizeof(*ev))
|
||||
return -EINVAL;
|
||||
|
||||
if (vif->sme_state != SME_CONNECTED)
|
||||
return -ENOTCONN;
|
||||
|
||||
ev = (struct wmi_txe_notify_event *) datap;
|
||||
rate = le32_to_cpu(ev->rate);
|
||||
pkts = le32_to_cpu(ev->pkts);
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "TXE notify event: peer %pM rate %d% pkts %d intvl %ds\n",
|
||||
vif->bssid, rate, pkts, vif->txe_intvl);
|
||||
|
||||
cfg80211_cqm_txe_notify(vif->ndev, vif->bssid, pkts,
|
||||
rate, vif->txe_intvl, GFP_KERNEL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath6kl_wmi_set_txe_notify(struct wmi *wmi, u8 idx,
|
||||
u32 rate, u32 pkts, u32 intvl)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct wmi_txe_notify_cmd *cmd;
|
||||
|
||||
skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_txe_notify_cmd *) skb->data;
|
||||
cmd->rate = cpu_to_le32(rate);
|
||||
cmd->pkts = cpu_to_le32(pkts);
|
||||
cmd->intvl = cpu_to_le32(intvl);
|
||||
|
||||
return ath6kl_wmi_cmd_send(wmi, idx, skb, WMI_SET_TXE_NOTIFY_CMDID,
|
||||
NO_SYNC_WMIFLAG);
|
||||
}
|
||||
|
||||
int ath6kl_wmi_set_rssi_filter_cmd(struct wmi *wmi, u8 if_idx, s8 rssi)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct wmi_set_rssi_filter_cmd *cmd;
|
||||
int ret;
|
||||
|
||||
skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_set_rssi_filter_cmd *) skb->data;
|
||||
cmd->rssi = rssi;
|
||||
|
||||
ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_RSSI_FILTER_CMDID,
|
||||
NO_SYNC_WMIFLAG);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath6kl_wmi_send_snr_threshold_params(struct wmi *wmi,
|
||||
struct wmi_snr_threshold_params_cmd *snr_cmd)
|
||||
{
|
||||
|
@ -1677,8 +1745,11 @@ int ath6kl_wmi_cmd_send(struct wmi *wmi, u8 if_idx, struct sk_buff *skb,
|
|||
int ret;
|
||||
u16 info1;
|
||||
|
||||
if (WARN_ON(skb == NULL || (if_idx > (wmi->parent_dev->vif_max - 1))))
|
||||
if (WARN_ON(skb == NULL ||
|
||||
(if_idx > (wmi->parent_dev->vif_max - 1)))) {
|
||||
dev_kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "wmi tx id %d len %d flag %d\n",
|
||||
cmd_id, skb->len, sync_flag);
|
||||
|
@ -1833,6 +1904,59 @@ int ath6kl_wmi_disconnect_cmd(struct wmi *wmi, u8 if_idx)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* ath6kl_wmi_start_scan_cmd is to be deprecated. Use
|
||||
* ath6kl_wmi_begin_scan_cmd instead. The new function supports P2P
|
||||
* mgmt operations using station interface.
|
||||
*/
|
||||
static int ath6kl_wmi_startscan_cmd(struct wmi *wmi, u8 if_idx,
|
||||
enum wmi_scan_type scan_type,
|
||||
u32 force_fgscan, u32 is_legacy,
|
||||
u32 home_dwell_time,
|
||||
u32 force_scan_interval,
|
||||
s8 num_chan, u16 *ch_list)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct wmi_start_scan_cmd *sc;
|
||||
s8 size;
|
||||
int i, ret;
|
||||
|
||||
size = sizeof(struct wmi_start_scan_cmd);
|
||||
|
||||
if ((scan_type != WMI_LONG_SCAN) && (scan_type != WMI_SHORT_SCAN))
|
||||
return -EINVAL;
|
||||
|
||||
if (num_chan > WMI_MAX_CHANNELS)
|
||||
return -EINVAL;
|
||||
|
||||
if (num_chan)
|
||||
size += sizeof(u16) * (num_chan - 1);
|
||||
|
||||
skb = ath6kl_wmi_get_new_buf(size);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
sc = (struct wmi_start_scan_cmd *) skb->data;
|
||||
sc->scan_type = scan_type;
|
||||
sc->force_fg_scan = cpu_to_le32(force_fgscan);
|
||||
sc->is_legacy = cpu_to_le32(is_legacy);
|
||||
sc->home_dwell_time = cpu_to_le32(home_dwell_time);
|
||||
sc->force_scan_intvl = cpu_to_le32(force_scan_interval);
|
||||
sc->num_ch = num_chan;
|
||||
|
||||
for (i = 0; i < num_chan; i++)
|
||||
sc->ch_list[i] = cpu_to_le16(ch_list[i]);
|
||||
|
||||
ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_START_SCAN_CMDID,
|
||||
NO_SYNC_WMIFLAG);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* beginscan supports (compared to old startscan) P2P mgmt operations using
|
||||
* station interface, send additional information like supported rates to
|
||||
* advertise and xmit rates for probe requests
|
||||
*/
|
||||
int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
|
||||
enum wmi_scan_type scan_type,
|
||||
u32 force_fgscan, u32 is_legacy,
|
||||
|
@ -1848,6 +1972,15 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
|
|||
int num_rates;
|
||||
u32 ratemask;
|
||||
|
||||
if (!test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX,
|
||||
ar->fw_capabilities)) {
|
||||
return ath6kl_wmi_startscan_cmd(wmi, if_idx,
|
||||
scan_type, force_fgscan,
|
||||
is_legacy, home_dwell_time,
|
||||
force_scan_interval,
|
||||
num_chan, ch_list);
|
||||
}
|
||||
|
||||
size = sizeof(struct wmi_begin_scan_cmd);
|
||||
|
||||
if ((scan_type != WMI_LONG_SCAN) && (scan_type != WMI_SHORT_SCAN))
|
||||
|
@ -1900,50 +2033,24 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* ath6kl_wmi_start_scan_cmd is to be deprecated. Use
|
||||
* ath6kl_wmi_begin_scan_cmd instead. The new function supports P2P
|
||||
* mgmt operations using station interface.
|
||||
*/
|
||||
int ath6kl_wmi_startscan_cmd(struct wmi *wmi, u8 if_idx,
|
||||
enum wmi_scan_type scan_type,
|
||||
u32 force_fgscan, u32 is_legacy,
|
||||
u32 home_dwell_time, u32 force_scan_interval,
|
||||
s8 num_chan, u16 *ch_list)
|
||||
int ath6kl_wmi_enable_sched_scan_cmd(struct wmi *wmi, u8 if_idx, bool enable)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct wmi_start_scan_cmd *sc;
|
||||
s8 size;
|
||||
int i, ret;
|
||||
struct wmi_enable_sched_scan_cmd *sc;
|
||||
int ret;
|
||||
|
||||
size = sizeof(struct wmi_start_scan_cmd);
|
||||
|
||||
if ((scan_type != WMI_LONG_SCAN) && (scan_type != WMI_SHORT_SCAN))
|
||||
return -EINVAL;
|
||||
|
||||
if (num_chan > WMI_MAX_CHANNELS)
|
||||
return -EINVAL;
|
||||
|
||||
if (num_chan)
|
||||
size += sizeof(u16) * (num_chan - 1);
|
||||
|
||||
skb = ath6kl_wmi_get_new_buf(size);
|
||||
skb = ath6kl_wmi_get_new_buf(sizeof(*sc));
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
sc = (struct wmi_start_scan_cmd *) skb->data;
|
||||
sc->scan_type = scan_type;
|
||||
sc->force_fg_scan = cpu_to_le32(force_fgscan);
|
||||
sc->is_legacy = cpu_to_le32(is_legacy);
|
||||
sc->home_dwell_time = cpu_to_le32(home_dwell_time);
|
||||
sc->force_scan_intvl = cpu_to_le32(force_scan_interval);
|
||||
sc->num_ch = num_chan;
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "%s scheduled scan on vif %d\n",
|
||||
enable ? "enabling" : "disabling", if_idx);
|
||||
sc = (struct wmi_enable_sched_scan_cmd *) skb->data;
|
||||
sc->enable = enable ? 1 : 0;
|
||||
|
||||
for (i = 0; i < num_chan; i++)
|
||||
sc->ch_list[i] = cpu_to_le16(ch_list[i]);
|
||||
|
||||
ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_START_SCAN_CMDID,
|
||||
ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
|
||||
WMI_ENABLE_SCHED_SCAN_CMDID,
|
||||
NO_SYNC_WMIFLAG);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2275,8 +2382,10 @@ static int ath6kl_wmi_data_sync_send(struct wmi *wmi, struct sk_buff *skb,
|
|||
struct wmi_data_hdr *data_hdr;
|
||||
int ret;
|
||||
|
||||
if (WARN_ON(skb == NULL || ep_id == wmi->ep_id))
|
||||
if (WARN_ON(skb == NULL || ep_id == wmi->ep_id)) {
|
||||
dev_kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
skb_push(skb, sizeof(struct wmi_data_hdr));
|
||||
|
||||
|
@ -2313,10 +2422,8 @@ static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx)
|
|||
spin_unlock_bh(&wmi->lock);
|
||||
|
||||
skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
|
||||
if (!skb) {
|
||||
ret = -ENOMEM;
|
||||
goto free_skb;
|
||||
}
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_sync_cmd *) skb->data;
|
||||
|
||||
|
@ -2339,7 +2446,7 @@ static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx)
|
|||
* then do not send the Synchronize cmd on the control ep
|
||||
*/
|
||||
if (ret)
|
||||
goto free_skb;
|
||||
goto free_cmd_skb;
|
||||
|
||||
/*
|
||||
* Send sync cmd followed by sync data messages on all
|
||||
|
@ -2349,15 +2456,12 @@ static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx)
|
|||
NO_SYNC_WMIFLAG);
|
||||
|
||||
if (ret)
|
||||
goto free_skb;
|
||||
|
||||
/* cmd buffer sent, we no longer own it */
|
||||
skb = NULL;
|
||||
goto free_data_skb;
|
||||
|
||||
for (index = 0; index < num_pri_streams; index++) {
|
||||
|
||||
if (WARN_ON(!data_sync_bufs[index].skb))
|
||||
break;
|
||||
goto free_data_skb;
|
||||
|
||||
ep_id = ath6kl_ac2_endpoint_id(wmi->parent_dev,
|
||||
data_sync_bufs[index].
|
||||
|
@ -2366,17 +2470,20 @@ static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx)
|
|||
ath6kl_wmi_data_sync_send(wmi, data_sync_bufs[index].skb,
|
||||
ep_id, if_idx);
|
||||
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
data_sync_bufs[index].skb = NULL;
|
||||
|
||||
if (ret)
|
||||
goto free_data_skb;
|
||||
}
|
||||
|
||||
free_skb:
|
||||
return 0;
|
||||
|
||||
free_cmd_skb:
|
||||
/* free up any resources left over (possibly due to an error) */
|
||||
if (skb)
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
free_data_skb:
|
||||
for (index = 0; index < num_pri_streams; index++) {
|
||||
if (data_sync_bufs[index].skb != NULL) {
|
||||
dev_kfree_skb((struct sk_buff *)data_sync_bufs[index].
|
||||
|
@ -2618,11 +2725,13 @@ static int ath6kl_set_bitrate_mask64(struct wmi *wmi, u8 if_idx,
|
|||
{
|
||||
struct sk_buff *skb;
|
||||
int ret, mode, band;
|
||||
u64 mcsrate, ratemask[IEEE80211_NUM_BANDS];
|
||||
u64 mcsrate, ratemask[ATH6KL_NUM_BANDS];
|
||||
struct wmi_set_tx_select_rates64_cmd *cmd;
|
||||
|
||||
memset(&ratemask, 0, sizeof(ratemask));
|
||||
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
|
||||
|
||||
/* only check 2.4 and 5 GHz bands, skip the rest */
|
||||
for (band = 0; band <= IEEE80211_BAND_5GHZ; band++) {
|
||||
/* copy legacy rate mask */
|
||||
ratemask[band] = mask->control[band].legacy;
|
||||
if (band == IEEE80211_BAND_5GHZ)
|
||||
|
@ -2668,11 +2777,13 @@ static int ath6kl_set_bitrate_mask32(struct wmi *wmi, u8 if_idx,
|
|||
{
|
||||
struct sk_buff *skb;
|
||||
int ret, mode, band;
|
||||
u32 mcsrate, ratemask[IEEE80211_NUM_BANDS];
|
||||
u32 mcsrate, ratemask[ATH6KL_NUM_BANDS];
|
||||
struct wmi_set_tx_select_rates32_cmd *cmd;
|
||||
|
||||
memset(&ratemask, 0, sizeof(ratemask));
|
||||
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
|
||||
|
||||
/* only check 2.4 and 5 GHz bands, skip the rest */
|
||||
for (band = 0; band <= IEEE80211_BAND_5GHZ; band++) {
|
||||
/* copy legacy rate mask */
|
||||
ratemask[band] = mask->control[band].legacy;
|
||||
if (band == IEEE80211_BAND_5GHZ)
|
||||
|
@ -2716,7 +2827,7 @@ int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
|
|||
{
|
||||
struct ath6kl *ar = wmi->parent_dev;
|
||||
|
||||
if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES)
|
||||
if (ar->hw.flags & ATH6KL_HW_64BIT_RATES)
|
||||
return ath6kl_set_bitrate_mask64(wmi, if_idx, mask);
|
||||
else
|
||||
return ath6kl_set_bitrate_mask32(wmi, if_idx, mask);
|
||||
|
@ -3139,12 +3250,40 @@ int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enhance)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int ath6kl_wmi_set_regdomain_cmd(struct wmi *wmi, const char *alpha2)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct wmi_set_regdomain_cmd *cmd;
|
||||
|
||||
skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_set_regdomain_cmd *) skb->data;
|
||||
memcpy(cmd->iso_name, alpha2, 2);
|
||||
|
||||
return ath6kl_wmi_cmd_send(wmi, 0, skb,
|
||||
WMI_SET_REGDOMAIN_CMDID,
|
||||
NO_SYNC_WMIFLAG);
|
||||
}
|
||||
|
||||
s32 ath6kl_wmi_get_rate(s8 rate_index)
|
||||
{
|
||||
u8 sgi = 0;
|
||||
|
||||
if (rate_index == RATE_AUTO)
|
||||
return 0;
|
||||
|
||||
return wmi_rate_tbl[(u32) rate_index][0];
|
||||
/* SGI is stored as the MSB of the rate_index */
|
||||
if (rate_index & RATE_INDEX_MSB) {
|
||||
rate_index &= RATE_INDEX_WITHOUT_SGI_MASK;
|
||||
sgi = 1;
|
||||
}
|
||||
|
||||
if (WARN_ON(rate_index > RATE_MCS_7_40))
|
||||
rate_index = RATE_MCS_7_40;
|
||||
|
||||
return wmi_rate_tbl[(u32) rate_index][sgi];
|
||||
}
|
||||
|
||||
static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap,
|
||||
|
@ -3634,6 +3773,19 @@ int ath6kl_wmi_set_inact_period(struct wmi *wmi, u8 if_idx, int inact_timeout)
|
|||
NO_SYNC_WMIFLAG);
|
||||
}
|
||||
|
||||
static void ath6kl_wmi_hb_challenge_resp_event(struct wmi *wmi, u8 *datap,
|
||||
int len)
|
||||
{
|
||||
struct wmix_hb_challenge_resp_cmd *cmd;
|
||||
|
||||
if (len < sizeof(struct wmix_hb_challenge_resp_cmd))
|
||||
return;
|
||||
|
||||
cmd = (struct wmix_hb_challenge_resp_cmd *) datap;
|
||||
ath6kl_recovery_hb_event(wmi->parent_dev,
|
||||
le32_to_cpu(cmd->cookie));
|
||||
}
|
||||
|
||||
static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb)
|
||||
{
|
||||
struct wmix_cmd_hdr *cmd;
|
||||
|
@ -3658,6 +3810,7 @@ static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb)
|
|||
switch (id) {
|
||||
case WMIX_HB_CHALLENGE_RESP_EVENTID:
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "wmi event hb challenge resp\n");
|
||||
ath6kl_wmi_hb_challenge_resp_event(wmi, datap, len);
|
||||
break;
|
||||
case WMIX_DBGLOG_EVENTID:
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "wmi event dbglog len %d\n", len);
|
||||
|
@ -3750,6 +3903,9 @@ static int ath6kl_wmi_proc_events_vif(struct wmi *wmi, u16 if_idx, u16 cmd_id,
|
|||
case WMI_RX_ACTION_EVENTID:
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_ACTION_EVENTID\n");
|
||||
return ath6kl_wmi_rx_action_event_rx(wmi, datap, len, vif);
|
||||
case WMI_TXE_NOTIFY_EVENTID:
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TXE_NOTIFY_EVENTID\n");
|
||||
return ath6kl_wmi_txe_notify_event_rx(wmi, datap, len, vif);
|
||||
default:
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "unknown cmd id 0x%x\n", cmd_id);
|
||||
return -EINVAL;
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
|
||||
#define A_BAND_24GHZ 0
|
||||
#define A_BAND_5GHZ 1
|
||||
#define A_NUM_BANDS 2
|
||||
#define ATH6KL_NUM_BANDS 2
|
||||
|
||||
/* in ms */
|
||||
#define WMI_IMPLICIT_PSTREAM_INACTIVITY_INT 5000
|
||||
|
@ -628,6 +628,20 @@ enum wmi_cmd_id {
|
|||
WMI_SET_MCASTRATE,
|
||||
|
||||
WMI_STA_BMISS_ENHANCE_CMDID,
|
||||
|
||||
WMI_SET_REGDOMAIN_CMDID,
|
||||
|
||||
WMI_SET_RSSI_FILTER_CMDID,
|
||||
|
||||
WMI_SET_KEEP_ALIVE_EXT,
|
||||
|
||||
WMI_VOICE_DETECTION_ENABLE_CMDID,
|
||||
|
||||
WMI_SET_TXE_NOTIFY_CMDID,
|
||||
|
||||
WMI_SET_RECOVERY_TEST_PARAMETER_CMDID, /*0xf094*/
|
||||
|
||||
WMI_ENABLE_SCHED_SCAN_CMDID,
|
||||
};
|
||||
|
||||
enum wmi_mgmt_frame_type {
|
||||
|
@ -843,7 +857,7 @@ struct wmi_begin_scan_cmd {
|
|||
u8 scan_type;
|
||||
|
||||
/* Supported rates to advertise in the probe request frames */
|
||||
struct wmi_supp_rates supp_rates[IEEE80211_NUM_BANDS];
|
||||
struct wmi_supp_rates supp_rates[ATH6KL_NUM_BANDS];
|
||||
|
||||
/* how many channels follow */
|
||||
u8 num_ch;
|
||||
|
@ -941,6 +955,11 @@ struct wmi_scan_params_cmd {
|
|||
__le32 max_dfsch_act_time;
|
||||
} __packed;
|
||||
|
||||
/* WMI_ENABLE_SCHED_SCAN_CMDID */
|
||||
struct wmi_enable_sched_scan_cmd {
|
||||
u8 enable;
|
||||
} __packed;
|
||||
|
||||
/* WMI_SET_BSS_FILTER_CMDID */
|
||||
enum wmi_bss_filter {
|
||||
/* no beacons forwarded */
|
||||
|
@ -1032,6 +1051,11 @@ struct wmi_sta_bmiss_enhance_cmd {
|
|||
u8 enable;
|
||||
} __packed;
|
||||
|
||||
struct wmi_set_regdomain_cmd {
|
||||
u8 length;
|
||||
u8 iso_name[2];
|
||||
} __packed;
|
||||
|
||||
/* WMI_SET_POWER_MODE_CMDID */
|
||||
enum wmi_power_mode {
|
||||
REC_POWER = 0x01,
|
||||
|
@ -1276,6 +1300,11 @@ struct wmi_snr_threshold_params_cmd {
|
|||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* Don't report BSSs with signal (RSSI) below this threshold */
|
||||
struct wmi_set_rssi_filter_cmd {
|
||||
s8 rssi;
|
||||
} __packed;
|
||||
|
||||
enum wmi_preamble_policy {
|
||||
WMI_IGNORE_BARKER_IN_ERP = 0,
|
||||
WMI_FOLLOW_BARKER_IN_ERP,
|
||||
|
@ -1455,6 +1484,20 @@ enum wmi_event_id {
|
|||
WMI_P2P_CAPABILITIES_EVENTID,
|
||||
WMI_RX_ACTION_EVENTID,
|
||||
WMI_P2P_INFO_EVENTID,
|
||||
|
||||
/* WPS Events */
|
||||
WMI_WPS_GET_STATUS_EVENTID,
|
||||
WMI_WPS_PROFILE_EVENTID,
|
||||
|
||||
/* more P2P events */
|
||||
WMI_NOA_INFO_EVENTID,
|
||||
WMI_OPPPS_INFO_EVENTID,
|
||||
WMI_PORT_STATUS_EVENTID,
|
||||
|
||||
/* 802.11w */
|
||||
WMI_GET_RSN_CAP_EVENTID,
|
||||
|
||||
WMI_TXE_NOTIFY_EVENTID,
|
||||
};
|
||||
|
||||
struct wmi_ready_event_2 {
|
||||
|
@ -1749,6 +1792,9 @@ struct rx_stats {
|
|||
a_sle32 ucast_rate;
|
||||
} __packed;
|
||||
|
||||
#define RATE_INDEX_WITHOUT_SGI_MASK 0x7f
|
||||
#define RATE_INDEX_MSB 0x80
|
||||
|
||||
struct tkip_ccmp_stats {
|
||||
__le32 tkip_local_mic_fail;
|
||||
__le32 tkip_cnter_measures_invoked;
|
||||
|
@ -2019,7 +2065,6 @@ struct wmi_set_ie_cmd {
|
|||
|
||||
#define WOW_MAX_FILTERS_PER_LIST 4
|
||||
#define WOW_PATTERN_SIZE 64
|
||||
#define WOW_MASK_SIZE 64
|
||||
|
||||
#define MAC_MAX_FILTERS_PER_LIST 4
|
||||
|
||||
|
@ -2028,7 +2073,7 @@ struct wow_filter {
|
|||
u8 wow_filter_id;
|
||||
u8 wow_filter_size;
|
||||
u8 wow_filter_offset;
|
||||
u8 wow_filter_mask[WOW_MASK_SIZE];
|
||||
u8 wow_filter_mask[WOW_PATTERN_SIZE];
|
||||
u8 wow_filter_pattern[WOW_PATTERN_SIZE];
|
||||
} __packed;
|
||||
|
||||
|
@ -2087,6 +2132,19 @@ struct wmi_del_wow_pattern_cmd {
|
|||
__le16 filter_id;
|
||||
} __packed;
|
||||
|
||||
/* WMI_SET_TXE_NOTIFY_CMDID */
|
||||
struct wmi_txe_notify_cmd {
|
||||
__le32 rate;
|
||||
__le32 pkts;
|
||||
__le32 intvl;
|
||||
} __packed;
|
||||
|
||||
/* WMI_TXE_NOTIFY_EVENTID */
|
||||
struct wmi_txe_notify_event {
|
||||
__le32 rate;
|
||||
__le32 pkts;
|
||||
} __packed;
|
||||
|
||||
/* WMI_SET_AKMP_PARAMS_CMD */
|
||||
|
||||
struct wmi_pmkid {
|
||||
|
@ -2505,11 +2563,6 @@ int ath6kl_wmi_connect_cmd(struct wmi *wmi, u8 if_idx,
|
|||
int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 if_idx, u8 *bssid,
|
||||
u16 channel);
|
||||
int ath6kl_wmi_disconnect_cmd(struct wmi *wmi, u8 if_idx);
|
||||
int ath6kl_wmi_startscan_cmd(struct wmi *wmi, u8 if_idx,
|
||||
enum wmi_scan_type scan_type,
|
||||
u32 force_fgscan, u32 is_legacy,
|
||||
u32 home_dwell_time, u32 force_scan_interval,
|
||||
s8 num_chan, u16 *ch_list);
|
||||
|
||||
int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
|
||||
enum wmi_scan_type scan_type,
|
||||
|
@ -2517,6 +2570,7 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
|
|||
u32 home_dwell_time, u32 force_scan_interval,
|
||||
s8 num_chan, u16 *ch_list, u32 no_cck,
|
||||
u32 *rates);
|
||||
int ath6kl_wmi_enable_sched_scan_cmd(struct wmi *wmi, u8 if_idx, bool enable);
|
||||
|
||||
int ath6kl_wmi_scanparams_cmd(struct wmi *wmi, u8 if_idx, u16 fg_start_sec,
|
||||
u16 fg_end_sec, u16 bg_sec,
|
||||
|
@ -2592,6 +2646,7 @@ int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
|
|||
const u8 *mask);
|
||||
int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
|
||||
u16 list_id, u16 filter_id);
|
||||
int ath6kl_wmi_set_rssi_filter_cmd(struct wmi *wmi, u8 if_idx, s8 rssi);
|
||||
int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi);
|
||||
int ath6kl_wmi_ap_set_dtim_cmd(struct wmi *wmi, u8 if_idx, u32 dtim_period);
|
||||
int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid);
|
||||
|
@ -2600,6 +2655,9 @@ int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on);
|
|||
int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx,
|
||||
u8 *filter, bool add_filter);
|
||||
int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enable);
|
||||
int ath6kl_wmi_set_txe_notify(struct wmi *wmi, u8 idx,
|
||||
u32 rate, u32 pkts, u32 intvl);
|
||||
int ath6kl_wmi_set_regdomain_cmd(struct wmi *wmi, const char *alpha2);
|
||||
|
||||
/* AP mode uAPSD */
|
||||
int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable);
|
||||
|
@ -2658,6 +2716,8 @@ int ath6kl_wmi_set_inact_period(struct wmi *wmi, u8 if_idx, int inact_timeout);
|
|||
|
||||
void ath6kl_wmi_sscan_timer(unsigned long ptr);
|
||||
|
||||
int ath6kl_wmi_get_challenge_resp_cmd(struct wmi *wmi, u32 cookie, u32 source);
|
||||
|
||||
struct ath6kl_vif *ath6kl_get_vif_by_index(struct ath6kl *ar, u8 if_idx);
|
||||
void *ath6kl_wmi_init(struct ath6kl *devt);
|
||||
void ath6kl_wmi_shutdown(struct wmi *wmi);
|
||||
|
|
|
@ -891,6 +891,74 @@ static void ar9003_hw_tx_iq_cal_reload(struct ath_hw *ah)
|
|||
AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
|
||||
}
|
||||
|
||||
static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g)
|
||||
{
|
||||
int offset[8], total = 0, test;
|
||||
int agc_out, i;
|
||||
|
||||
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
|
||||
AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE, 0x1);
|
||||
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
|
||||
AR_PHY_65NM_RXRF_GAINSTAGES_LNAON_CALDC, 0x0);
|
||||
if (is_2g)
|
||||
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
|
||||
AR_PHY_65NM_RXRF_GAINSTAGES_LNA2G_GAIN_OVR, 0x0);
|
||||
else
|
||||
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
|
||||
AR_PHY_65NM_RXRF_GAINSTAGES_LNA5G_GAIN_OVR, 0x0);
|
||||
|
||||
REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain),
|
||||
AR_PHY_65NM_RXTX2_RXON_OVR, 0x1);
|
||||
REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain),
|
||||
AR_PHY_65NM_RXTX2_RXON, 0x0);
|
||||
|
||||
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
|
||||
AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE, 0x1);
|
||||
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
|
||||
AR_PHY_65NM_RXRF_AGC_AGC_ON_OVR, 0x1);
|
||||
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
|
||||
AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0x1);
|
||||
if (is_2g)
|
||||
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
|
||||
AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR, 0x0);
|
||||
else
|
||||
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
|
||||
AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR, 0x0);
|
||||
|
||||
for (i = 6; i > 0; i--) {
|
||||
offset[i] = BIT(i - 1);
|
||||
test = total + offset[i];
|
||||
|
||||
if (is_2g)
|
||||
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
|
||||
AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR,
|
||||
test);
|
||||
else
|
||||
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
|
||||
AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR,
|
||||
test);
|
||||
udelay(100);
|
||||
agc_out = REG_READ_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
|
||||
AR_PHY_65NM_RXRF_AGC_AGC_OUT);
|
||||
offset[i] = (agc_out) ? 0 : 1;
|
||||
total += (offset[i] << (i - 1));
|
||||
}
|
||||
|
||||
if (is_2g)
|
||||
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
|
||||
AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, total);
|
||||
else
|
||||
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
|
||||
AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR, total);
|
||||
|
||||
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
|
||||
AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE, 0);
|
||||
REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain),
|
||||
AR_PHY_65NM_RXTX2_RXON_OVR, 0);
|
||||
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
|
||||
AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0);
|
||||
}
|
||||
|
||||
static bool ar9003_hw_init_cal(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
|
@ -989,6 +1057,14 @@ skip_tx_iqcal:
|
|||
status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
|
||||
AR_PHY_AGC_CONTROL_CAL,
|
||||
0, AH_WAIT_TIMEOUT);
|
||||
if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
|
||||
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
|
||||
if (!(ah->rxchainmask & (1 << i)))
|
||||
continue;
|
||||
ar9003_hw_manual_peak_cal(ah, i,
|
||||
IS_CHAN_2GHZ(chan));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal)
|
||||
|
|
|
@ -35,12 +35,6 @@
|
|||
*/
|
||||
static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
|
||||
{
|
||||
#define AR9462_BB_CTX_COEFJ(x) \
|
||||
ar9462_##x##_baseband_core_txfir_coeff_japan_2484
|
||||
|
||||
#define AR9462_BBC_TXIFR_COEFFJ \
|
||||
ar9462_2p0_baseband_core_txfir_coeff_japan_2484
|
||||
|
||||
if (AR_SREV_9330_11(ah)) {
|
||||
/* mac */
|
||||
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
|
||||
|
@ -70,6 +64,10 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
|
|||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9331_modes_lowest_ob_db_tx_gain_1p1);
|
||||
|
||||
/* Japan 2484 Mhz CCK */
|
||||
INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
|
||||
ar9331_1p1_baseband_core_txfir_coeff_japan_2484);
|
||||
|
||||
/* additional clock settings */
|
||||
if (ah->is_clk_25mhz)
|
||||
INIT_INI_ARRAY(&ah->iniAdditional,
|
||||
|
@ -106,6 +104,10 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
|
|||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9331_modes_lowest_ob_db_tx_gain_1p2);
|
||||
|
||||
/* Japan 2484 Mhz CCK */
|
||||
INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
|
||||
ar9331_1p2_baseband_core_txfir_coeff_japan_2484);
|
||||
|
||||
/* additional clock settings */
|
||||
if (ah->is_clk_25mhz)
|
||||
INIT_INI_ARRAY(&ah->iniAdditional,
|
||||
|
@ -180,6 +182,10 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
|
|||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9485_modes_lowest_ob_db_tx_gain_1_1);
|
||||
|
||||
/* Japan 2484 Mhz CCK */
|
||||
INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
|
||||
ar9485_1_1_baseband_core_txfir_coeff_japan_2484);
|
||||
|
||||
/* Load PCIE SERDES settings from INI */
|
||||
|
||||
/* Awake Setting */
|
||||
|
@ -229,9 +235,7 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
|
|||
ar9462_modes_fast_clock_2p0);
|
||||
|
||||
INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
|
||||
AR9462_BB_CTX_COEFJ(2p0));
|
||||
|
||||
INIT_INI_ARRAY(&ah->ini_japan2484, AR9462_BBC_TXIFR_COEFFJ);
|
||||
ar9462_2p0_baseband_core_txfir_coeff_japan_2484);
|
||||
} else if (AR_SREV_9550(ah)) {
|
||||
/* mac */
|
||||
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
|
||||
|
|
|
@ -714,7 +714,6 @@ bool ar9003_mci_start_reset(struct ath_hw *ah, struct ath9k_channel *chan)
|
|||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(ar9003_mci_start_reset);
|
||||
|
||||
int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
struct ath9k_hw_cal_data *caldata)
|
||||
|
|
|
@ -784,7 +784,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
|
|||
REG_WRITE_ARRAY(&ah->iniAdditional, 1, regWrites);
|
||||
|
||||
if (chan->channel == 2484)
|
||||
ar9003_hw_prog_ini(ah, &ah->ini_japan2484, 1);
|
||||
ar9003_hw_prog_ini(ah, &ah->iniCckfirJapan2484, 1);
|
||||
|
||||
if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
|
||||
REG_WRITE(ah, AR_GLB_SWREG_DISCONT_MODE,
|
||||
|
|
|
@ -698,13 +698,6 @@
|
|||
#define AR_PHY_65NM_CH0_THERM_SAR_ADC_OUT 0x0000ff00
|
||||
#define AR_PHY_65NM_CH0_THERM_SAR_ADC_OUT_S 8
|
||||
|
||||
#define AR_PHY_65NM_CH0_RXTX1 0x16100
|
||||
#define AR_PHY_65NM_CH0_RXTX2 0x16104
|
||||
#define AR_PHY_65NM_CH1_RXTX1 0x16500
|
||||
#define AR_PHY_65NM_CH1_RXTX2 0x16504
|
||||
#define AR_PHY_65NM_CH2_RXTX1 0x16900
|
||||
#define AR_PHY_65NM_CH2_RXTX2 0x16904
|
||||
|
||||
#define AR_CH0_TOP2 (AR_SREV_9300(ah) ? 0x1628c : \
|
||||
(AR_SREV_9462(ah) ? 0x16290 : 0x16284))
|
||||
#define AR_CH0_TOP2_XPABIASLVL 0xf000
|
||||
|
@ -1286,4 +1279,43 @@
|
|||
#define AR_BTCOEX_WL_LNADIV_BT_INACTIVE_THRESHOLD 0xFC000000
|
||||
#define AR_BTCOEX_WL_LNADIV_BT_INACTIVE_THRESHOLD_S 26
|
||||
|
||||
/* Manual Peak detector calibration */
|
||||
#define AR_PHY_65NM_BASE 0x16000
|
||||
#define AR_PHY_65NM_RXRF_GAINSTAGES(i) (AR_PHY_65NM_BASE + \
|
||||
(i * 0x400) + 0x8)
|
||||
#define AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE 0x80000000
|
||||
#define AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE_S 31
|
||||
#define AR_PHY_65NM_RXRF_GAINSTAGES_LNAON_CALDC 0x00000002
|
||||
#define AR_PHY_65NM_RXRF_GAINSTAGES_LNAON_CALDC_S 1
|
||||
#define AR_PHY_65NM_RXRF_GAINSTAGES_LNA2G_GAIN_OVR 0x70000000
|
||||
#define AR_PHY_65NM_RXRF_GAINSTAGES_LNA2G_GAIN_OVR_S 28
|
||||
#define AR_PHY_65NM_RXRF_GAINSTAGES_LNA5G_GAIN_OVR 0x03800000
|
||||
#define AR_PHY_65NM_RXRF_GAINSTAGES_LNA5G_GAIN_OVR_S 23
|
||||
|
||||
#define AR_PHY_65NM_RXTX2(i) (AR_PHY_65NM_BASE + \
|
||||
(i * 0x400) + 0x104)
|
||||
#define AR_PHY_65NM_RXTX2_RXON_OVR 0x00001000
|
||||
#define AR_PHY_65NM_RXTX2_RXON_OVR_S 12
|
||||
#define AR_PHY_65NM_RXTX2_RXON 0x00000800
|
||||
#define AR_PHY_65NM_RXTX2_RXON_S 11
|
||||
|
||||
#define AR_PHY_65NM_RXRF_AGC(i) (AR_PHY_65NM_BASE + \
|
||||
(i * 0x400) + 0xc)
|
||||
#define AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE 0x80000000
|
||||
#define AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE_S 31
|
||||
#define AR_PHY_65NM_RXRF_AGC_AGC_ON_OVR 0x40000000
|
||||
#define AR_PHY_65NM_RXRF_AGC_AGC_ON_OVR_S 30
|
||||
#define AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR 0x20000000
|
||||
#define AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR_S 29
|
||||
#define AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR 0x1E000000
|
||||
#define AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR_S 25
|
||||
#define AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR 0x00078000
|
||||
#define AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR_S 15
|
||||
#define AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR 0x01F80000
|
||||
#define AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR_S 19
|
||||
#define AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR 0x00007e00
|
||||
#define AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR_S 9
|
||||
#define AR_PHY_65NM_RXRF_AGC_AGC_OUT 0x00000004
|
||||
#define AR_PHY_65NM_RXRF_AGC_AGC_OUT_S 2
|
||||
|
||||
#endif /* AR9003_PHY_H */
|
||||
|
|
|
@ -78,7 +78,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
|
|||
{0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
|
||||
{0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
|
||||
{0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
|
||||
{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
|
||||
{0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
|
||||
{0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982},
|
||||
{0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
|
||||
{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#ifndef INITVALS_9485_H
|
||||
#define INITVALS_9485_H
|
||||
|
||||
/* AR9485 1.0 */
|
||||
/* AR9485 1.1 */
|
||||
|
||||
#define ar9485_1_1_mac_postamble ar9300_2p2_mac_postamble
|
||||
|
||||
|
@ -31,6 +31,11 @@ static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1[][2] = {
|
|||
|
||||
static const u32 ar9485Common_wo_xlna_rx_gain_1_1[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x00009e00, 0x037216a0},
|
||||
{0x00009e04, 0x00182020},
|
||||
{0x00009e18, 0x00000000},
|
||||
{0x00009e2c, 0x00004121},
|
||||
{0x00009e44, 0x02282324},
|
||||
{0x0000a000, 0x00060005},
|
||||
{0x0000a004, 0x00810080},
|
||||
{0x0000a008, 0x00830082},
|
||||
|
@ -164,6 +169,11 @@ static const u32 ar9485Common_wo_xlna_rx_gain_1_1[][2] = {
|
|||
static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = {
|
||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||
{0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
|
||||
{0x0000a2d8, 0xf999a83a, 0xf999a83a, 0x7999a83a, 0x7999a83a},
|
||||
{0x0000a2dc, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
|
||||
{0x0000a2e0, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
|
||||
{0x0000a2e4, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
|
||||
{0x0000a2e8, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
|
||||
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
|
||||
{0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
|
||||
|
@ -198,6 +208,22 @@ static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = {
|
|||
{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a580, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a584, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a588, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a58c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a590, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a594, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a598, 0x00000000, 0x00000000, 0x01404501, 0x01404501},
|
||||
{0x0000a59c, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02},
|
||||
{0x0000a5a0, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02},
|
||||
{0x0000a5a4, 0x00000000, 0x00000000, 0x02808803, 0x02808803},
|
||||
{0x0000a5a8, 0x00000000, 0x00000000, 0x04c14b04, 0x04c14b04},
|
||||
{0x0000a5ac, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
|
||||
{0x0000a5b0, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
|
||||
{0x0000a5b4, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
|
||||
{0x0000a5b8, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
|
||||
{0x0000a5bc, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
|
||||
{0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
|
@ -234,9 +260,193 @@ static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = {
|
|||
{0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
|
||||
};
|
||||
|
||||
#define ar9485Modes_high_ob_db_tx_gain_1_1 ar9485Modes_high_power_tx_gain_1_1
|
||||
static const u32 ar9485Modes_high_ob_db_tx_gain_1_1[][5] = {
|
||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||
{0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
|
||||
{0x0000a2d8, 0xf999a83a, 0xf999a83a, 0x7999a83a, 0x7999a83a},
|
||||
{0x0000a2dc, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
|
||||
{0x0000a2e0, 0x00000000, 0x00000000, 0xffc63a84, 0xffc63a84},
|
||||
{0x0000a2e4, 0x00000000, 0x00000000, 0xfe0fc000, 0xfe0fc000},
|
||||
{0x0000a2e8, 0x00000000, 0x00000000, 0xfff00000, 0xfff00000},
|
||||
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
|
||||
{0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
|
||||
{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
|
||||
{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
|
||||
{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
|
||||
{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
|
||||
{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
|
||||
{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
|
||||
{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
|
||||
{0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603},
|
||||
{0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605},
|
||||
{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03},
|
||||
{0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04},
|
||||
{0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20},
|
||||
{0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21},
|
||||
{0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
|
||||
{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
|
||||
{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
|
||||
{0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
|
||||
{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
|
||||
{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
|
||||
{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
|
||||
{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
|
||||
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
|
||||
{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a580, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a584, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a588, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a58c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a590, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a594, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a598, 0x00000000, 0x00000000, 0x01404501, 0x01404501},
|
||||
{0x0000a59c, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02},
|
||||
{0x0000a5a0, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02},
|
||||
{0x0000a5a4, 0x00000000, 0x00000000, 0x02808803, 0x02808803},
|
||||
{0x0000a5a8, 0x00000000, 0x00000000, 0x04c14b04, 0x04c14b04},
|
||||
{0x0000a5ac, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
|
||||
{0x0000a5b0, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
|
||||
{0x0000a5b4, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
|
||||
{0x0000a5b8, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
|
||||
{0x0000a5bc, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
|
||||
{0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
|
||||
{0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
|
||||
};
|
||||
|
||||
#define ar9485Modes_low_ob_db_tx_gain_1_1 ar9485Modes_high_ob_db_tx_gain_1_1
|
||||
static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = {
|
||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||
{0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
|
||||
{0x0000a2d8, 0xf999a83a, 0xf999a83a, 0x7999a83a, 0x7999a83a},
|
||||
{0x0000a2dc, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
|
||||
{0x0000a2e0, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
|
||||
{0x0000a2e4, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
|
||||
{0x0000a2e8, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
|
||||
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
|
||||
{0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
|
||||
{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
|
||||
{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
|
||||
{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
|
||||
{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
|
||||
{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
|
||||
{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
|
||||
{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
|
||||
{0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603},
|
||||
{0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605},
|
||||
{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03},
|
||||
{0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04},
|
||||
{0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20},
|
||||
{0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21},
|
||||
{0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
|
||||
{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
|
||||
{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
|
||||
{0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
|
||||
{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
|
||||
{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
|
||||
{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
|
||||
{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
|
||||
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
|
||||
{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a580, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a584, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a588, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a58c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a590, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a594, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a598, 0x00000000, 0x00000000, 0x01404501, 0x01404501},
|
||||
{0x0000a59c, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02},
|
||||
{0x0000a5a0, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02},
|
||||
{0x0000a5a4, 0x00000000, 0x00000000, 0x02808803, 0x02808803},
|
||||
{0x0000a5a8, 0x00000000, 0x00000000, 0x04c14b04, 0x04c14b04},
|
||||
{0x0000a5ac, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
|
||||
{0x0000a5b0, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
|
||||
{0x0000a5b4, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
|
||||
{0x0000a5b8, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
|
||||
{0x0000a5bc, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
|
||||
{0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
|
||||
{0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
|
||||
};
|
||||
|
||||
#define ar9485_modes_lowest_ob_db_tx_gain_1_1 ar9485Modes_low_ob_db_tx_gain_1_1
|
||||
|
||||
|
@ -245,19 +455,19 @@ static const u32 ar9485_1_1[][2] = {
|
|||
{0x0000a580, 0x00000000},
|
||||
{0x0000a584, 0x00000000},
|
||||
{0x0000a588, 0x00000000},
|
||||
{0x0000a58c, 0x00000000},
|
||||
{0x0000a590, 0x00000000},
|
||||
{0x0000a594, 0x00000000},
|
||||
{0x0000a598, 0x00000000},
|
||||
{0x0000a59c, 0x00000000},
|
||||
{0x0000a5a0, 0x00000000},
|
||||
{0x0000a5a4, 0x00000000},
|
||||
{0x0000a5a8, 0x00000000},
|
||||
{0x0000a5ac, 0x00000000},
|
||||
{0x0000a5b0, 0x00000000},
|
||||
{0x0000a5b4, 0x00000000},
|
||||
{0x0000a5b8, 0x00000000},
|
||||
{0x0000a5bc, 0x00000000},
|
||||
{0x0000a58c, 0x01804000},
|
||||
{0x0000a590, 0x02808a02},
|
||||
{0x0000a594, 0x0340ca02},
|
||||
{0x0000a598, 0x0340cd03},
|
||||
{0x0000a59c, 0x0340cd03},
|
||||
{0x0000a5a0, 0x06415304},
|
||||
{0x0000a5a4, 0x04c11905},
|
||||
{0x0000a5a8, 0x06415905},
|
||||
{0x0000a5ac, 0x06415905},
|
||||
{0x0000a5b0, 0x06415905},
|
||||
{0x0000a5b4, 0x06415905},
|
||||
{0x0000a5b8, 0x06415905},
|
||||
{0x0000a5bc, 0x06415905},
|
||||
};
|
||||
|
||||
static const u32 ar9485_1_1_radio_core[][2] = {
|
||||
|
@ -340,7 +550,7 @@ static const u32 ar9485_1_1_baseband_core[][2] = {
|
|||
{0x00009880, 0x201fff00},
|
||||
{0x00009884, 0x00001042},
|
||||
{0x000098a4, 0x00200400},
|
||||
{0x000098b0, 0x52440bbe},
|
||||
{0x000098b0, 0x32840bbe},
|
||||
{0x000098d0, 0x004b6a8e},
|
||||
{0x000098d4, 0x00000820},
|
||||
{0x000098dc, 0x00000000},
|
||||
|
@ -362,7 +572,7 @@ static const u32 ar9485_1_1_baseband_core[][2] = {
|
|||
{0x00009d18, 0x00000000},
|
||||
{0x00009d1c, 0x00000000},
|
||||
{0x00009e08, 0x0038233c},
|
||||
{0x00009e24, 0x9927b515},
|
||||
{0x00009e24, 0x992bb515},
|
||||
{0x00009e28, 0x12ef0200},
|
||||
{0x00009e30, 0x06336f77},
|
||||
{0x00009e34, 0x6af6532f},
|
||||
|
@ -427,7 +637,7 @@ static const u32 ar9485_1_1_baseband_core[][2] = {
|
|||
{0x0000a408, 0x0e79e5c6},
|
||||
{0x0000a40c, 0x00820820},
|
||||
{0x0000a414, 0x1ce739cf},
|
||||
{0x0000a418, 0x2d0019ce},
|
||||
{0x0000a418, 0x2d0021ce},
|
||||
{0x0000a41c, 0x1ce739ce},
|
||||
{0x0000a420, 0x000001ce},
|
||||
{0x0000a424, 0x1ce739ce},
|
||||
|
@ -443,8 +653,8 @@ static const u32 ar9485_1_1_baseband_core[][2] = {
|
|||
{0x0000a44c, 0x00000001},
|
||||
{0x0000a450, 0x00010000},
|
||||
{0x0000a5c4, 0xbfad9d74},
|
||||
{0x0000a5c8, 0x0048060a},
|
||||
{0x0000a5cc, 0x00000637},
|
||||
{0x0000a5c8, 0x00480605},
|
||||
{0x0000a5cc, 0x00002e37},
|
||||
{0x0000a760, 0x03020100},
|
||||
{0x0000a764, 0x09080504},
|
||||
{0x0000a768, 0x0d0c0b0a},
|
||||
|
@ -464,17 +674,22 @@ static const u32 ar9485_1_1_baseband_core[][2] = {
|
|||
|
||||
static const u32 ar9485_common_rx_gain_1_1[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x0000a000, 0x00010000},
|
||||
{0x0000a004, 0x00030002},
|
||||
{0x0000a008, 0x00050004},
|
||||
{0x0000a00c, 0x00810080},
|
||||
{0x0000a010, 0x01800082},
|
||||
{0x0000a014, 0x01820181},
|
||||
{0x0000a018, 0x01840183},
|
||||
{0x0000a01c, 0x01880185},
|
||||
{0x0000a020, 0x018a0189},
|
||||
{0x0000a024, 0x02850284},
|
||||
{0x0000a028, 0x02890288},
|
||||
{0x00009e00, 0x03721b20},
|
||||
{0x00009e04, 0x00082020},
|
||||
{0x00009e18, 0x0300501e},
|
||||
{0x00009e2c, 0x00002e21},
|
||||
{0x00009e44, 0x02182324},
|
||||
{0x0000a000, 0x00060005},
|
||||
{0x0000a004, 0x00810080},
|
||||
{0x0000a008, 0x00830082},
|
||||
{0x0000a00c, 0x00850084},
|
||||
{0x0000a010, 0x01820181},
|
||||
{0x0000a014, 0x01840183},
|
||||
{0x0000a018, 0x01880185},
|
||||
{0x0000a01c, 0x018a0189},
|
||||
{0x0000a020, 0x02850284},
|
||||
{0x0000a024, 0x02890288},
|
||||
{0x0000a028, 0x028b028a},
|
||||
{0x0000a02c, 0x03850384},
|
||||
{0x0000a030, 0x03890388},
|
||||
{0x0000a034, 0x038b038a},
|
||||
|
@ -496,15 +711,15 @@ static const u32 ar9485_common_rx_gain_1_1[][2] = {
|
|||
{0x0000a074, 0x00000000},
|
||||
{0x0000a078, 0x00000000},
|
||||
{0x0000a07c, 0x00000000},
|
||||
{0x0000a080, 0x28282828},
|
||||
{0x0000a084, 0x28282828},
|
||||
{0x0000a088, 0x28282828},
|
||||
{0x0000a08c, 0x28282828},
|
||||
{0x0000a090, 0x28282828},
|
||||
{0x0000a094, 0x21212128},
|
||||
{0x0000a098, 0x171c1c1c},
|
||||
{0x0000a09c, 0x02020212},
|
||||
{0x0000a0a0, 0x00000202},
|
||||
{0x0000a080, 0x18181818},
|
||||
{0x0000a084, 0x18181818},
|
||||
{0x0000a088, 0x18181818},
|
||||
{0x0000a08c, 0x18181818},
|
||||
{0x0000a090, 0x18181818},
|
||||
{0x0000a094, 0x18181818},
|
||||
{0x0000a098, 0x17181818},
|
||||
{0x0000a09c, 0x02020b0b},
|
||||
{0x0000a0a0, 0x02020202},
|
||||
{0x0000a0a4, 0x00000000},
|
||||
{0x0000a0a8, 0x00000000},
|
||||
{0x0000a0ac, 0x00000000},
|
||||
|
@ -512,22 +727,22 @@ static const u32 ar9485_common_rx_gain_1_1[][2] = {
|
|||
{0x0000a0b4, 0x00000000},
|
||||
{0x0000a0b8, 0x00000000},
|
||||
{0x0000a0bc, 0x00000000},
|
||||
{0x0000a0c0, 0x001f0000},
|
||||
{0x0000a0c4, 0x111f1100},
|
||||
{0x0000a0c8, 0x111d111e},
|
||||
{0x0000a0cc, 0x111b111c},
|
||||
{0x0000a0d0, 0x22032204},
|
||||
{0x0000a0d4, 0x22012202},
|
||||
{0x0000a0d8, 0x221f2200},
|
||||
{0x0000a0dc, 0x221d221e},
|
||||
{0x0000a0e0, 0x33013302},
|
||||
{0x0000a0e4, 0x331f3300},
|
||||
{0x0000a0e8, 0x4402331e},
|
||||
{0x0000a0ec, 0x44004401},
|
||||
{0x0000a0f0, 0x441e441f},
|
||||
{0x0000a0f4, 0x55015502},
|
||||
{0x0000a0f8, 0x551f5500},
|
||||
{0x0000a0fc, 0x6602551e},
|
||||
{0x0000a0c0, 0x22072208},
|
||||
{0x0000a0c4, 0x22052206},
|
||||
{0x0000a0c8, 0x22032204},
|
||||
{0x0000a0cc, 0x22012202},
|
||||
{0x0000a0d0, 0x221f2200},
|
||||
{0x0000a0d4, 0x221d221e},
|
||||
{0x0000a0d8, 0x33023303},
|
||||
{0x0000a0dc, 0x33003301},
|
||||
{0x0000a0e0, 0x331e331f},
|
||||
{0x0000a0e4, 0x4402331d},
|
||||
{0x0000a0e8, 0x44004401},
|
||||
{0x0000a0ec, 0x441e441f},
|
||||
{0x0000a0f0, 0x55025503},
|
||||
{0x0000a0f4, 0x55005501},
|
||||
{0x0000a0f8, 0x551e551f},
|
||||
{0x0000a0fc, 0x6602551d},
|
||||
{0x0000a100, 0x66006601},
|
||||
{0x0000a104, 0x661e661f},
|
||||
{0x0000a108, 0x7703661d},
|
||||
|
@ -636,17 +851,12 @@ static const u32 ar9485_1_1_baseband_postamble[][5] = {
|
|||
{0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
|
||||
{0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
|
||||
{0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044},
|
||||
{0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
|
||||
{0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020},
|
||||
{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
|
||||
{0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec80d2e, 0x7ec80d2e},
|
||||
{0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
|
||||
{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x00009e14, 0x31395d53, 0x31396053, 0x312e6053, 0x312e5d53},
|
||||
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
|
||||
{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
|
||||
{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
|
||||
{0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222},
|
||||
{0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
|
||||
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
|
||||
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
|
||||
{0x0000a204, 0x01303fc0, 0x01303fc4, 0x01303fc4, 0x01303fc0},
|
||||
|
@ -850,4 +1060,6 @@ static const u32 ar9485_1_1_mac_core[][2] = {
|
|||
{0x000083d0, 0x000301ff},
|
||||
};
|
||||
|
||||
#define ar9485_1_1_baseband_core_txfir_coeff_japan_2484 ar9462_2p0_baseband_core_txfir_coeff_japan_2484
|
||||
|
||||
#endif /* INITVALS_9485_H */
|
||||
|
|
|
@ -129,10 +129,10 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
|
|||
#define ATH_TXMAXTRY 13
|
||||
|
||||
#define TID_TO_WME_AC(_tid) \
|
||||
((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \
|
||||
(((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \
|
||||
(((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \
|
||||
WME_AC_VO)
|
||||
((((_tid) == 0) || ((_tid) == 3)) ? IEEE80211_AC_BE : \
|
||||
(((_tid) == 1) || ((_tid) == 2)) ? IEEE80211_AC_BK : \
|
||||
(((_tid) == 4) || ((_tid) == 5)) ? IEEE80211_AC_VI : \
|
||||
IEEE80211_AC_VO)
|
||||
|
||||
#define ATH_AGGR_DELIM_SZ 4
|
||||
#define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */
|
||||
|
@ -259,13 +259,10 @@ struct ath_atx_tid {
|
|||
};
|
||||
|
||||
struct ath_node {
|
||||
#ifdef CONFIG_ATH9K_DEBUGFS
|
||||
struct list_head list; /* for sc->nodes */
|
||||
#endif
|
||||
struct ieee80211_sta *sta; /* station struct we're part of */
|
||||
struct ieee80211_vif *vif; /* interface with which we're associated */
|
||||
struct ath_atx_tid tid[WME_NUM_TID];
|
||||
struct ath_atx_ac ac[WME_NUM_AC];
|
||||
struct ath_atx_ac ac[IEEE80211_NUM_ACS];
|
||||
int ps_key;
|
||||
|
||||
u16 maxampdu;
|
||||
|
@ -299,9 +296,9 @@ struct ath_tx {
|
|||
struct list_head txbuf;
|
||||
struct ath_txq txq[ATH9K_NUM_TX_QUEUES];
|
||||
struct ath_descdma txdma;
|
||||
struct ath_txq *txq_map[WME_NUM_AC];
|
||||
u32 txq_max_pending[WME_NUM_AC];
|
||||
u16 max_aggr_framelen[WME_NUM_AC][4][32];
|
||||
struct ath_txq *txq_map[IEEE80211_NUM_ACS];
|
||||
u32 txq_max_pending[IEEE80211_NUM_ACS];
|
||||
u16 max_aggr_framelen[IEEE80211_NUM_ACS][4][32];
|
||||
};
|
||||
|
||||
struct ath_rx_edma {
|
||||
|
@ -461,6 +458,12 @@ void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type);
|
|||
/* BTCOEX */
|
||||
/**********/
|
||||
|
||||
#define ATH_DUMP_BTCOEX(_s, _val) \
|
||||
do { \
|
||||
len += snprintf(buf + len, size - len, \
|
||||
"%20s : %10d\n", _s, (_val)); \
|
||||
} while (0)
|
||||
|
||||
enum bt_op_flags {
|
||||
BT_OP_PRIORITY_DETECTED,
|
||||
BT_OP_SCAN,
|
||||
|
@ -482,6 +485,7 @@ struct ath_btcoex {
|
|||
int rssi_count;
|
||||
struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */
|
||||
struct ath_mci_profile mci;
|
||||
u8 stomp_audio;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
|
||||
|
@ -494,7 +498,7 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc);
|
|||
void ath9k_btcoex_handle_interrupt(struct ath_softc *sc, u32 status);
|
||||
u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen);
|
||||
void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc);
|
||||
int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 len, u32 size);
|
||||
int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 size);
|
||||
#else
|
||||
static inline int ath9k_init_btcoex(struct ath_softc *sc)
|
||||
{
|
||||
|
@ -521,8 +525,7 @@ static inline u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc,
|
|||
static inline void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)
|
||||
{
|
||||
}
|
||||
static inline int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf,
|
||||
u32 len, u32 size)
|
||||
static inline int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -717,9 +720,6 @@ struct ath_softc {
|
|||
|
||||
#ifdef CONFIG_ATH9K_DEBUGFS
|
||||
struct ath9k_debug debug;
|
||||
spinlock_t nodes_lock;
|
||||
struct list_head nodes; /* basically, stations */
|
||||
unsigned int tx_complete_poll_work_seen;
|
||||
#endif
|
||||
struct ath_beacon_config cur_beacon_conf;
|
||||
struct delayed_work tx_complete_work;
|
||||
|
|
|
@ -46,7 +46,7 @@ static void ath9k_beaconq_config(struct ath_softc *sc)
|
|||
qi.tqi_cwmax = 0;
|
||||
} else {
|
||||
/* Adhoc mode; important thing is to use 2x cwmin. */
|
||||
txq = sc->tx.txq_map[WME_AC_BE];
|
||||
txq = sc->tx.txq_map[IEEE80211_AC_BE];
|
||||
ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be);
|
||||
qi.tqi_aifs = qi_be.tqi_aifs;
|
||||
if (ah->slottime == ATH9K_SLOT_TIME_20)
|
||||
|
|
|
@ -49,6 +49,7 @@ static const u32 mci_wlan_weights[ATH_BTCOEX_STOMP_MAX]
|
|||
{ 0x01017d01, 0x3b3b3b01, 0x3b3b3b01, 0x3b3b3b3b }, /* STOMP_LOW */
|
||||
{ 0x01017d01, 0x01010101, 0x01010101, 0x01010101 }, /* STOMP_NONE */
|
||||
{ 0x01017d01, 0x013b0101, 0x3b3b0101, 0x3b3b013b }, /* STOMP_LOW_FTP */
|
||||
{ 0xffffff01, 0xffffffff, 0xffffff01, 0xffffffff }, /* STOMP_AUDIO */
|
||||
};
|
||||
|
||||
void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
|
||||
|
|
|
@ -50,6 +50,7 @@ enum ath_stomp_type {
|
|||
ATH_BTCOEX_STOMP_LOW,
|
||||
ATH_BTCOEX_STOMP_NONE,
|
||||
ATH_BTCOEX_STOMP_LOW_FTP,
|
||||
ATH_BTCOEX_STOMP_AUDIO,
|
||||
ATH_BTCOEX_STOMP_MAX
|
||||
};
|
||||
|
||||
|
|
|
@ -28,13 +28,6 @@
|
|||
#define WME_MAX_BA WME_BA_BMP_SIZE
|
||||
#define ATH_TID_MAX_BUFS (2 * WME_MAX_BA)
|
||||
|
||||
/* These must match mac80211 skb queue mapping numbers */
|
||||
#define WME_AC_VO 0
|
||||
#define WME_AC_VI 1
|
||||
#define WME_AC_BE 2
|
||||
#define WME_AC_BK 3
|
||||
#define WME_NUM_AC 4
|
||||
|
||||
#define ATH_RSSI_DUMMY_MARKER 0x127
|
||||
#define ATH_RSSI_LPF_LEN 10
|
||||
#define RSSI_LPF_THRESHOLD -20
|
||||
|
|
|
@ -512,62 +512,19 @@ static const struct file_operations fops_interrupt = {
|
|||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
#define PR_QNUM(_n) sc->tx.txq_map[_n]->axq_qnum
|
||||
#define PR(str, elem) \
|
||||
do { \
|
||||
len += snprintf(buf + len, size - len, \
|
||||
"%s%13u%11u%10u%10u\n", str, \
|
||||
sc->debug.stats.txstats[PR_QNUM(WME_AC_BE)].elem, \
|
||||
sc->debug.stats.txstats[PR_QNUM(WME_AC_BK)].elem, \
|
||||
sc->debug.stats.txstats[PR_QNUM(WME_AC_VI)].elem, \
|
||||
sc->debug.stats.txstats[PR_QNUM(WME_AC_VO)].elem); \
|
||||
if (len >= size) \
|
||||
goto done; \
|
||||
} while(0)
|
||||
|
||||
#define PRX(str, elem) \
|
||||
do { \
|
||||
len += snprintf(buf + len, size - len, \
|
||||
"%s%13u%11u%10u%10u\n", str, \
|
||||
(unsigned int)(sc->tx.txq_map[WME_AC_BE]->elem), \
|
||||
(unsigned int)(sc->tx.txq_map[WME_AC_BK]->elem), \
|
||||
(unsigned int)(sc->tx.txq_map[WME_AC_VI]->elem), \
|
||||
(unsigned int)(sc->tx.txq_map[WME_AC_VO]->elem)); \
|
||||
if (len >= size) \
|
||||
goto done; \
|
||||
} while(0)
|
||||
|
||||
#define PRQLE(str, elem) \
|
||||
do { \
|
||||
len += snprintf(buf + len, size - len, \
|
||||
"%s%13i%11i%10i%10i\n", str, \
|
||||
list_empty(&sc->tx.txq_map[WME_AC_BE]->elem), \
|
||||
list_empty(&sc->tx.txq_map[WME_AC_BK]->elem), \
|
||||
list_empty(&sc->tx.txq_map[WME_AC_VI]->elem), \
|
||||
list_empty(&sc->tx.txq_map[WME_AC_VO]->elem)); \
|
||||
if (len >= size) \
|
||||
goto done; \
|
||||
} while (0)
|
||||
|
||||
static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
char *buf;
|
||||
unsigned int len = 0, size = 8000;
|
||||
int i;
|
||||
unsigned int len = 0, size = 2048;
|
||||
ssize_t retval = 0;
|
||||
char tmp[32];
|
||||
|
||||
buf = kzalloc(size, GFP_KERNEL);
|
||||
if (buf == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
len += sprintf(buf, "Num-Tx-Queues: %i tx-queues-setup: 0x%x"
|
||||
" poll-work-seen: %u\n"
|
||||
"%30s %10s%10s%10s\n\n",
|
||||
ATH9K_NUM_TX_QUEUES, sc->tx.txqsetup,
|
||||
sc->tx_complete_poll_work_seen,
|
||||
len += sprintf(buf, "%30s %10s%10s%10s\n\n",
|
||||
"BE", "BK", "VI", "VO");
|
||||
|
||||
PR("MPDUs Queued: ", queued);
|
||||
|
@ -587,62 +544,11 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
|
|||
PR("DELIM Underrun: ", delim_underrun);
|
||||
PR("TX-Pkts-All: ", tx_pkts_all);
|
||||
PR("TX-Bytes-All: ", tx_bytes_all);
|
||||
PR("hw-put-tx-buf: ", puttxbuf);
|
||||
PR("hw-tx-start: ", txstart);
|
||||
PR("hw-tx-proc-desc: ", txprocdesc);
|
||||
PR("HW-put-tx-buf: ", puttxbuf);
|
||||
PR("HW-tx-start: ", txstart);
|
||||
PR("HW-tx-proc-desc: ", txprocdesc);
|
||||
PR("TX-Failed: ", txfailed);
|
||||
len += snprintf(buf + len, size - len,
|
||||
"%s%11p%11p%10p%10p\n", "txq-memory-address:",
|
||||
sc->tx.txq_map[WME_AC_BE],
|
||||
sc->tx.txq_map[WME_AC_BK],
|
||||
sc->tx.txq_map[WME_AC_VI],
|
||||
sc->tx.txq_map[WME_AC_VO]);
|
||||
if (len >= size)
|
||||
goto done;
|
||||
|
||||
PRX("axq-qnum: ", axq_qnum);
|
||||
PRX("axq-depth: ", axq_depth);
|
||||
PRX("axq-ampdu_depth: ", axq_ampdu_depth);
|
||||
PRX("axq-stopped ", stopped);
|
||||
PRX("tx-in-progress ", axq_tx_inprogress);
|
||||
PRX("pending-frames ", pending_frames);
|
||||
PRX("txq_headidx: ", txq_headidx);
|
||||
PRX("txq_tailidx: ", txq_headidx);
|
||||
|
||||
PRQLE("axq_q empty: ", axq_q);
|
||||
PRQLE("axq_acq empty: ", axq_acq);
|
||||
for (i = 0; i < ATH_TXFIFO_DEPTH; i++) {
|
||||
snprintf(tmp, sizeof(tmp) - 1, "txq_fifo[%i] empty: ", i);
|
||||
PRQLE(tmp, txq_fifo[i]);
|
||||
}
|
||||
|
||||
/* Print out more detailed queue-info */
|
||||
for (i = 0; i <= WME_AC_BK; i++) {
|
||||
struct ath_txq *txq = &(sc->tx.txq[i]);
|
||||
struct ath_atx_ac *ac;
|
||||
struct ath_atx_tid *tid;
|
||||
if (len >= size)
|
||||
goto done;
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
if (!list_empty(&txq->axq_acq)) {
|
||||
ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac,
|
||||
list);
|
||||
len += snprintf(buf + len, size - len,
|
||||
"txq[%i] first-ac: %p sched: %i\n",
|
||||
i, ac, ac->sched);
|
||||
if (list_empty(&ac->tid_q) || (len >= size))
|
||||
goto done_for;
|
||||
tid = list_first_entry(&ac->tid_q, struct ath_atx_tid,
|
||||
list);
|
||||
len += snprintf(buf + len, size - len,
|
||||
" first-tid: %p sched: %i paused: %i\n",
|
||||
tid, tid->sched, tid->paused);
|
||||
}
|
||||
done_for:
|
||||
spin_unlock_bh(&txq->axq_lock);
|
||||
}
|
||||
|
||||
done:
|
||||
if (len > size)
|
||||
len = size;
|
||||
|
||||
|
@ -652,62 +558,41 @@ done:
|
|||
return retval;
|
||||
}
|
||||
|
||||
static ssize_t read_file_stations(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
static ssize_t read_file_queues(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
struct ath_txq *txq;
|
||||
char *buf;
|
||||
unsigned int len = 0, size = 64000;
|
||||
struct ath_node *an = NULL;
|
||||
unsigned int len = 0, size = 1024;
|
||||
ssize_t retval = 0;
|
||||
int q;
|
||||
int i;
|
||||
char *qname[4] = {"VO", "VI", "BE", "BK"};
|
||||
|
||||
buf = kzalloc(size, GFP_KERNEL);
|
||||
if (buf == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
len += snprintf(buf + len, size - len,
|
||||
"Stations:\n"
|
||||
" tid: addr sched paused buf_q-empty an ac baw\n"
|
||||
" ac: addr sched tid_q-empty txq\n");
|
||||
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
|
||||
txq = sc->tx.txq_map[i];
|
||||
len += snprintf(buf + len, size - len, "(%s): ", qname[i]);
|
||||
|
||||
spin_lock(&sc->nodes_lock);
|
||||
list_for_each_entry(an, &sc->nodes, list) {
|
||||
unsigned short ma = an->maxampdu;
|
||||
if (ma == 0)
|
||||
ma = 65535; /* see ath_lookup_rate */
|
||||
len += snprintf(buf + len, size - len,
|
||||
"iface: %pM sta: %pM max-ampdu: %hu mpdu-density: %uus\n",
|
||||
an->vif->addr, an->sta->addr, ma,
|
||||
(unsigned int)(an->mpdudensity));
|
||||
if (len >= size)
|
||||
goto done;
|
||||
ath_txq_lock(sc, txq);
|
||||
|
||||
for (q = 0; q < WME_NUM_TID; q++) {
|
||||
struct ath_atx_tid *tid = &(an->tid[q]);
|
||||
len += snprintf(buf + len, size - len,
|
||||
" tid: %p %s %s %i %p %p %hu\n",
|
||||
tid, tid->sched ? "sched" : "idle",
|
||||
tid->paused ? "paused" : "running",
|
||||
skb_queue_empty(&tid->buf_q),
|
||||
tid->an, tid->ac, tid->baw_size);
|
||||
if (len >= size)
|
||||
goto done;
|
||||
}
|
||||
len += snprintf(buf + len, size - len, "%s: %d ",
|
||||
"qnum", txq->axq_qnum);
|
||||
len += snprintf(buf + len, size - len, "%s: %2d ",
|
||||
"qdepth", txq->axq_depth);
|
||||
len += snprintf(buf + len, size - len, "%s: %2d ",
|
||||
"ampdu-depth", txq->axq_ampdu_depth);
|
||||
len += snprintf(buf + len, size - len, "%s: %3d ",
|
||||
"pending", txq->pending_frames);
|
||||
len += snprintf(buf + len, size - len, "%s: %d\n",
|
||||
"stopped", txq->stopped);
|
||||
|
||||
for (q = 0; q < WME_NUM_AC; q++) {
|
||||
struct ath_atx_ac *ac = &(an->ac[q]);
|
||||
len += snprintf(buf + len, size - len,
|
||||
" ac: %p %s %i %p\n",
|
||||
ac, ac->sched ? "sched" : "idle",
|
||||
list_empty(&ac->tid_q), ac->txq);
|
||||
if (len >= size)
|
||||
goto done;
|
||||
}
|
||||
ath_txq_unlock(sc, txq);
|
||||
}
|
||||
|
||||
done:
|
||||
spin_unlock(&sc->nodes_lock);
|
||||
if (len > size)
|
||||
len = size;
|
||||
|
||||
|
@ -837,6 +722,9 @@ static ssize_t read_file_reset(struct file *file, char __user *user_buf,
|
|||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
"%17s: %2d\n", "PLL RX Hang",
|
||||
sc->debug.stats.reset[RESET_TYPE_PLL_HANG]);
|
||||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
"%17s: %2d\n", "MCI Reset",
|
||||
sc->debug.stats.reset[RESET_TYPE_MCI]);
|
||||
|
||||
if (len > sizeof(buf))
|
||||
len = sizeof(buf);
|
||||
|
@ -919,8 +807,8 @@ static const struct file_operations fops_xmit = {
|
|||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static const struct file_operations fops_stations = {
|
||||
.read = read_file_stations,
|
||||
static const struct file_operations fops_queues = {
|
||||
.read = read_file_queues,
|
||||
.open = simple_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
|
@ -1599,8 +1487,14 @@ static ssize_t read_file_btcoex(struct file *file, char __user *user_buf,
|
|||
if (buf == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
len = ath9k_dump_btcoex(sc, buf, len, size);
|
||||
if (!sc->sc_ah->common.btcoex_enabled) {
|
||||
len = snprintf(buf, size, "%s\n",
|
||||
"BTCOEX is disabled");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
len = ath9k_dump_btcoex(sc, buf, size);
|
||||
exit:
|
||||
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
kfree(buf);
|
||||
|
||||
|
@ -1638,16 +1532,16 @@ int ath9k_init_debug(struct ath_hw *ah)
|
|||
&fops_interrupt);
|
||||
debugfs_create_file("xmit", S_IRUSR, sc->debug.debugfs_phy, sc,
|
||||
&fops_xmit);
|
||||
debugfs_create_file("queues", S_IRUSR, sc->debug.debugfs_phy, sc,
|
||||
&fops_queues);
|
||||
debugfs_create_u32("qlen_bk", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
|
||||
&sc->tx.txq_max_pending[WME_AC_BK]);
|
||||
&sc->tx.txq_max_pending[IEEE80211_AC_BK]);
|
||||
debugfs_create_u32("qlen_be", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
|
||||
&sc->tx.txq_max_pending[WME_AC_BE]);
|
||||
&sc->tx.txq_max_pending[IEEE80211_AC_BE]);
|
||||
debugfs_create_u32("qlen_vi", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
|
||||
&sc->tx.txq_max_pending[WME_AC_VI]);
|
||||
&sc->tx.txq_max_pending[IEEE80211_AC_VI]);
|
||||
debugfs_create_u32("qlen_vo", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
|
||||
&sc->tx.txq_max_pending[WME_AC_VO]);
|
||||
debugfs_create_file("stations", S_IRUSR, sc->debug.debugfs_phy, sc,
|
||||
&fops_stations);
|
||||
&sc->tx.txq_max_pending[IEEE80211_AC_VO]);
|
||||
debugfs_create_file("misc", S_IRUSR, sc->debug.debugfs_phy, sc,
|
||||
&fops_misc);
|
||||
debugfs_create_file("reset", S_IRUSR, sc->debug.debugfs_phy, sc,
|
||||
|
|
|
@ -41,6 +41,7 @@ enum ath_reset_type {
|
|||
RESET_TYPE_PLL_HANG,
|
||||
RESET_TYPE_MAC_HANG,
|
||||
RESET_TYPE_BEACON_STUCK,
|
||||
RESET_TYPE_MCI,
|
||||
__RESET_TYPE_MAX
|
||||
};
|
||||
|
||||
|
@ -178,6 +179,21 @@ struct ath_tx_stats {
|
|||
u32 txfailed;
|
||||
};
|
||||
|
||||
/*
|
||||
* Various utility macros to print TX/Queue counters.
|
||||
*/
|
||||
#define PR_QNUM(_n) sc->tx.txq_map[_n]->axq_qnum
|
||||
#define TXSTATS sc->debug.stats.txstats
|
||||
#define PR(str, elem) \
|
||||
do { \
|
||||
len += snprintf(buf + len, size - len, \
|
||||
"%s%13u%11u%10u%10u\n", str, \
|
||||
TXSTATS[PR_QNUM(IEEE80211_AC_BE)].elem, \
|
||||
TXSTATS[PR_QNUM(IEEE80211_AC_BK)].elem, \
|
||||
TXSTATS[PR_QNUM(IEEE80211_AC_VI)].elem, \
|
||||
TXSTATS[PR_QNUM(IEEE80211_AC_VO)].elem); \
|
||||
} while(0)
|
||||
|
||||
#define RX_STAT_INC(c) (sc->debug.stats.rxstats.c++)
|
||||
|
||||
/**
|
||||
|
@ -226,7 +242,7 @@ struct ath_rx_stats {
|
|||
|
||||
struct ath_stats {
|
||||
struct ath_interrupt_stats istats;
|
||||
struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES];
|
||||
struct ath_tx_stats txstats[IEEE80211_NUM_ACS];
|
||||
struct ath_rx_stats rxstats;
|
||||
struct ath_dfs_stats dfs_stats;
|
||||
u32 reset[__RESET_TYPE_MAX];
|
||||
|
|
|
@ -42,10 +42,15 @@ struct radar_types {
|
|||
#define MIN_PPB_THRESH 50
|
||||
#define PPB_THRESH(PPB) ((PPB * MIN_PPB_THRESH + 50) / 100)
|
||||
#define PRF2PRI(PRF) ((1000000 + PRF / 2) / PRF)
|
||||
/* percentage of pulse width tolerance */
|
||||
#define WIDTH_TOLERANCE 5
|
||||
#define WIDTH_LOWER(X) ((X*(100-WIDTH_TOLERANCE)+50)/100)
|
||||
#define WIDTH_UPPER(X) ((X*(100+WIDTH_TOLERANCE)+50)/100)
|
||||
|
||||
#define ETSI_PATTERN(ID, WMIN, WMAX, PMIN, PMAX, PRF, PPB) \
|
||||
{ \
|
||||
ID, WMIN, WMAX, (PRF2PRI(PMAX) - PRI_TOLERANCE), \
|
||||
ID, WIDTH_LOWER(WMIN), WIDTH_UPPER(WMAX), \
|
||||
(PRF2PRI(PMAX) - PRI_TOLERANCE), \
|
||||
(PRF2PRI(PMIN) * PRF + PRI_TOLERANCE), PRF, PPB * PRF, \
|
||||
PPB_THRESH(PPB), PRI_TOLERANCE, \
|
||||
}
|
||||
|
@ -274,7 +279,7 @@ static bool dpd_set_domain(struct dfs_pattern_detector *dpd,
|
|||
|
||||
static struct dfs_pattern_detector default_dpd = {
|
||||
.exit = dpd_exit,
|
||||
.set_domain = dpd_set_domain,
|
||||
.set_dfs_domain = dpd_set_domain,
|
||||
.add_pulse = dpd_add_pulse,
|
||||
.region = NL80211_DFS_UNSET,
|
||||
};
|
||||
|
@ -291,10 +296,11 @@ dfs_pattern_detector_init(enum nl80211_dfs_regions region)
|
|||
*dpd = default_dpd;
|
||||
INIT_LIST_HEAD(&dpd->channel_detectors);
|
||||
|
||||
if (dpd->set_domain(dpd, region))
|
||||
if (dpd->set_dfs_domain(dpd, region))
|
||||
return dpd;
|
||||
|
||||
pr_err("Could not set DFS domain to %d. ", region);
|
||||
kfree(dpd);
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(dfs_pattern_detector_init);
|
||||
|
|
|
@ -62,7 +62,7 @@ struct radar_detector_specs {
|
|||
/**
|
||||
* struct dfs_pattern_detector - DFS pattern detector
|
||||
* @exit(): destructor
|
||||
* @set_domain(): set DFS domain, resets detector lines upon domain changes
|
||||
* @set_dfs_domain(): set DFS domain, resets detector lines upon domain changes
|
||||
* @add_pulse(): add radar pulse to detector, returns true on detection
|
||||
* @region: active DFS region, NL80211_DFS_UNSET until set
|
||||
* @num_radar_types: number of different radar types
|
||||
|
@ -72,7 +72,7 @@ struct radar_detector_specs {
|
|||
*/
|
||||
struct dfs_pattern_detector {
|
||||
void (*exit)(struct dfs_pattern_detector *dpd);
|
||||
bool (*set_domain)(struct dfs_pattern_detector *dpd,
|
||||
bool (*set_dfs_domain)(struct dfs_pattern_detector *dpd,
|
||||
enum nl80211_dfs_regions region);
|
||||
bool (*add_pulse)(struct dfs_pattern_detector *dpd,
|
||||
struct pulse_event *pe);
|
||||
|
|
|
@ -247,6 +247,9 @@ static void ath_btcoex_period_timer(unsigned long data)
|
|||
stomp_type = ATH_BTCOEX_STOMP_ALL;
|
||||
timer_period = btcoex->btscan_no_stomp;
|
||||
}
|
||||
} else if (btcoex->stomp_audio >= 5) {
|
||||
stomp_type = ATH_BTCOEX_STOMP_AUDIO;
|
||||
btcoex->stomp_audio = 0;
|
||||
}
|
||||
|
||||
ath9k_hw_btcoex_bt_stomp(ah, stomp_type);
|
||||
|
@ -295,7 +298,7 @@ static void ath_btcoex_no_stomp_timer(void *arg)
|
|||
(!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI) &&
|
||||
test_bit(BT_OP_SCAN, &btcoex->op_flags)))
|
||||
ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE);
|
||||
else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
|
||||
else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
|
||||
ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW);
|
||||
|
||||
ath9k_hw_btcoex_enable(ah);
|
||||
|
@ -471,7 +474,7 @@ int ath9k_init_btcoex(struct ath_softc *sc)
|
|||
r = ath_init_btcoex_timer(sc);
|
||||
if (r)
|
||||
return -1;
|
||||
txq = sc->tx.txq_map[WME_AC_BE];
|
||||
txq = sc->tx.txq_map[IEEE80211_AC_BE];
|
||||
ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum);
|
||||
sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
|
||||
if (ath9k_hw_mci_is_enabled(ah)) {
|
||||
|
@ -494,35 +497,31 @@ int ath9k_init_btcoex(struct ath_softc *sc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 len, u32 size)
|
||||
static int ath9k_dump_mci_btcoex(struct ath_softc *sc, u8 *buf, u32 size)
|
||||
{
|
||||
#define ATH_DUMP_BTCOEX(_s, _val) \
|
||||
do { \
|
||||
len += snprintf(buf + len, size - len, \
|
||||
"%20s : %10d\n", _s, (_val)); \
|
||||
} while (0)
|
||||
|
||||
struct ath_btcoex *btcoex = &sc->btcoex;
|
||||
struct ath_mci_profile *mci = &btcoex->mci;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
|
||||
u32 len = 0;
|
||||
int i;
|
||||
|
||||
ATH_DUMP_BTCOEX("Total BT profiles", NUM_PROF(mci));
|
||||
ATH_DUMP_BTCOEX("Number of MGMT", mci->num_mgmt);
|
||||
ATH_DUMP_BTCOEX("Number of SCO", mci->num_sco);
|
||||
ATH_DUMP_BTCOEX("Number of A2DP", mci->num_a2dp);
|
||||
ATH_DUMP_BTCOEX("Number of HID", mci->num_hid);
|
||||
ATH_DUMP_BTCOEX("Number of PAN", mci->num_pan);
|
||||
ATH_DUMP_BTCOEX("Number of ACL", mci->num_other_acl);
|
||||
ATH_DUMP_BTCOEX("Number of BDR", mci->num_bdr);
|
||||
ATH_DUMP_BTCOEX("MGMT", mci->num_mgmt);
|
||||
ATH_DUMP_BTCOEX("SCO", mci->num_sco);
|
||||
ATH_DUMP_BTCOEX("A2DP", mci->num_a2dp);
|
||||
ATH_DUMP_BTCOEX("HID", mci->num_hid);
|
||||
ATH_DUMP_BTCOEX("PAN", mci->num_pan);
|
||||
ATH_DUMP_BTCOEX("ACL", mci->num_other_acl);
|
||||
ATH_DUMP_BTCOEX("BDR", mci->num_bdr);
|
||||
ATH_DUMP_BTCOEX("Aggr. Limit", mci->aggr_limit);
|
||||
ATH_DUMP_BTCOEX("Stomp Type", btcoex->bt_stomp_type);
|
||||
ATH_DUMP_BTCOEX("BTCoex Period (msec)", btcoex->btcoex_period);
|
||||
ATH_DUMP_BTCOEX("Duty Cycle", btcoex->duty_cycle);
|
||||
ATH_DUMP_BTCOEX("BT Wait time", btcoex->bt_wait_time);
|
||||
ATH_DUMP_BTCOEX("Concurrent Tx", btcoex_hw->mci.concur_tx);
|
||||
ATH_DUMP_BTCOEX("Concur RSSI count", btcoex->rssi_count);
|
||||
ATH_DUMP_BTCOEX("Concurrent RSSI cnt", btcoex->rssi_count);
|
||||
|
||||
len += snprintf(buf + len, size - len, "BT Weights: ");
|
||||
for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++)
|
||||
len += snprintf(buf + len, size - len, "%08x ",
|
||||
|
@ -537,9 +536,32 @@ int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 len, u32 size)
|
|||
for (i = 0; i < ATH_BTCOEX_STOMP_MAX; i++)
|
||||
len += snprintf(buf + len, size - len, "%08x ",
|
||||
btcoex_hw->tx_prio[i]);
|
||||
|
||||
len += snprintf(buf + len, size - len, "\n");
|
||||
#undef ATH_DUMP_BTCOEX
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int ath9k_dump_legacy_btcoex(struct ath_softc *sc, u8 *buf, u32 size)
|
||||
{
|
||||
|
||||
struct ath_btcoex *btcoex = &sc->btcoex;
|
||||
u32 len = 0;
|
||||
|
||||
ATH_DUMP_BTCOEX("Stomp Type", btcoex->bt_stomp_type);
|
||||
ATH_DUMP_BTCOEX("BTCoex Period (msec)", btcoex->btcoex_period);
|
||||
ATH_DUMP_BTCOEX("Duty Cycle", btcoex->duty_cycle);
|
||||
ATH_DUMP_BTCOEX("BT Wait time", btcoex->bt_wait_time);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 size)
|
||||
{
|
||||
if (ath9k_hw_mci_is_enabled(sc->sc_ah))
|
||||
return ath9k_dump_mci_btcoex(sc, buf, size);
|
||||
else
|
||||
return ath9k_dump_legacy_btcoex(sc, buf, size);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
|
||||
|
|
|
@ -331,7 +331,7 @@ struct ath_tx_stats {
|
|||
u32 skb_success;
|
||||
u32 skb_failed;
|
||||
u32 cab_queued;
|
||||
u32 queue_stats[WME_NUM_AC];
|
||||
u32 queue_stats[IEEE80211_NUM_ACS];
|
||||
};
|
||||
|
||||
struct ath_rx_stats {
|
||||
|
@ -493,7 +493,7 @@ struct ath9k_htc_priv {
|
|||
|
||||
int beaconq;
|
||||
int cabq;
|
||||
int hwq_map[WME_NUM_AC];
|
||||
int hwq_map[IEEE80211_NUM_ACS];
|
||||
|
||||
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
|
||||
struct ath_btcoex btcoex;
|
||||
|
|
|
@ -33,7 +33,7 @@ void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv)
|
|||
qi.tqi_cwmin = 0;
|
||||
qi.tqi_cwmax = 0;
|
||||
} else if (priv->ah->opmode == NL80211_IFTYPE_ADHOC) {
|
||||
int qnum = priv->hwq_map[WME_AC_BE];
|
||||
int qnum = priv->hwq_map[IEEE80211_AC_BE];
|
||||
|
||||
ath9k_hw_get_txq_props(ah, qnum, &qi_be);
|
||||
|
||||
|
@ -587,9 +587,9 @@ static bool ath9k_htc_check_beacon_config(struct ath9k_htc_priv *priv,
|
|||
(priv->num_sta_vif > 1) &&
|
||||
(vif->type == NL80211_IFTYPE_STATION)) {
|
||||
beacon_configured = false;
|
||||
ieee80211_iterate_active_interfaces_atomic(priv->hw,
|
||||
ath9k_htc_beacon_iter,
|
||||
&beacon_configured);
|
||||
ieee80211_iterate_active_interfaces_atomic(
|
||||
priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
ath9k_htc_beacon_iter, &beacon_configured);
|
||||
|
||||
if (beacon_configured) {
|
||||
ath_dbg(common, CONFIG,
|
||||
|
|
|
@ -218,16 +218,16 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
|
|||
|
||||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
"%20s : %10u\n", "BE queued",
|
||||
priv->debug.tx_stats.queue_stats[WME_AC_BE]);
|
||||
priv->debug.tx_stats.queue_stats[IEEE80211_AC_BE]);
|
||||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
"%20s : %10u\n", "BK queued",
|
||||
priv->debug.tx_stats.queue_stats[WME_AC_BK]);
|
||||
priv->debug.tx_stats.queue_stats[IEEE80211_AC_BK]);
|
||||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
"%20s : %10u\n", "VI queued",
|
||||
priv->debug.tx_stats.queue_stats[WME_AC_VI]);
|
||||
priv->debug.tx_stats.queue_stats[IEEE80211_AC_VI]);
|
||||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
"%20s : %10u\n", "VO queued",
|
||||
priv->debug.tx_stats.queue_stats[WME_AC_VO]);
|
||||
priv->debug.tx_stats.queue_stats[IEEE80211_AC_VO]);
|
||||
|
||||
if (len > sizeof(buf))
|
||||
len = sizeof(buf);
|
||||
|
|
|
@ -207,7 +207,7 @@ void ath9k_htc_init_btcoex(struct ath9k_htc_priv *priv, char *product)
|
|||
priv->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
|
||||
ath9k_hw_btcoex_init_3wire(priv->ah);
|
||||
ath_htc_init_btcoex_work(priv);
|
||||
qnum = priv->hwq_map[WME_AC_BE];
|
||||
qnum = priv->hwq_map[IEEE80211_AC_BE];
|
||||
ath9k_hw_init_btcoex_hw(priv->ah, qnum);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -549,20 +549,20 @@ static int ath9k_init_queues(struct ath9k_htc_priv *priv)
|
|||
goto err;
|
||||
}
|
||||
|
||||
if (!ath9k_htc_txq_setup(priv, WME_AC_BE)) {
|
||||
if (!ath9k_htc_txq_setup(priv, IEEE80211_AC_BE)) {
|
||||
ath_err(common, "Unable to setup xmit queue for BE traffic\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!ath9k_htc_txq_setup(priv, WME_AC_BK)) {
|
||||
if (!ath9k_htc_txq_setup(priv, IEEE80211_AC_BK)) {
|
||||
ath_err(common, "Unable to setup xmit queue for BK traffic\n");
|
||||
goto err;
|
||||
}
|
||||
if (!ath9k_htc_txq_setup(priv, WME_AC_VI)) {
|
||||
if (!ath9k_htc_txq_setup(priv, IEEE80211_AC_VI)) {
|
||||
ath_err(common, "Unable to setup xmit queue for VI traffic\n");
|
||||
goto err;
|
||||
}
|
||||
if (!ath9k_htc_txq_setup(priv, WME_AC_VO)) {
|
||||
if (!ath9k_htc_txq_setup(priv, IEEE80211_AC_VO)) {
|
||||
ath_err(common, "Unable to setup xmit queue for VO traffic\n");
|
||||
goto err;
|
||||
}
|
||||
|
|
|
@ -127,8 +127,9 @@ static void ath9k_htc_vif_reconfig(struct ath9k_htc_priv *priv)
|
|||
priv->rearm_ani = false;
|
||||
priv->reconfig_beacon = false;
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(priv->hw,
|
||||
ath9k_htc_vif_iter, priv);
|
||||
ieee80211_iterate_active_interfaces_atomic(
|
||||
priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
ath9k_htc_vif_iter, priv);
|
||||
if (priv->rearm_ani)
|
||||
ath9k_htc_start_ani(priv);
|
||||
|
||||
|
@ -165,8 +166,9 @@ static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv,
|
|||
ath9k_htc_bssid_iter(&iter_data, vif->addr, vif);
|
||||
|
||||
/* Get list of all active MAC addresses */
|
||||
ieee80211_iterate_active_interfaces_atomic(priv->hw, ath9k_htc_bssid_iter,
|
||||
&iter_data);
|
||||
ieee80211_iterate_active_interfaces_atomic(
|
||||
priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
ath9k_htc_bssid_iter, &iter_data);
|
||||
|
||||
memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
|
||||
ath_hw_setbssidmask(common);
|
||||
|
@ -1144,8 +1146,9 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
|
|||
*/
|
||||
if ((vif->type == NL80211_IFTYPE_AP) && (priv->num_ap_vif == 0)) {
|
||||
priv->rearm_ani = false;
|
||||
ieee80211_iterate_active_interfaces_atomic(priv->hw,
|
||||
ath9k_htc_vif_iter, priv);
|
||||
ieee80211_iterate_active_interfaces_atomic(
|
||||
priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
ath9k_htc_vif_iter, priv);
|
||||
if (!priv->rearm_ani)
|
||||
ath9k_htc_stop_ani(priv);
|
||||
}
|
||||
|
@ -1346,7 +1349,7 @@ static int ath9k_htc_conf_tx(struct ieee80211_hw *hw,
|
|||
struct ath9k_tx_queue_info qi;
|
||||
int ret = 0, qnum;
|
||||
|
||||
if (queue >= WME_NUM_AC)
|
||||
if (queue >= IEEE80211_NUM_ACS)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
@ -1373,7 +1376,7 @@ static int ath9k_htc_conf_tx(struct ieee80211_hw *hw,
|
|||
}
|
||||
|
||||
if ((priv->ah->opmode == NL80211_IFTYPE_ADHOC) &&
|
||||
(qnum == priv->hwq_map[WME_AC_BE]))
|
||||
(qnum == priv->hwq_map[IEEE80211_AC_BE]))
|
||||
ath9k_htc_beaconq_config(priv);
|
||||
out:
|
||||
ath9k_htc_ps_restore(priv);
|
||||
|
@ -1466,8 +1469,9 @@ static void ath9k_htc_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
|
|||
static void ath9k_htc_choose_set_bssid(struct ath9k_htc_priv *priv)
|
||||
{
|
||||
if (priv->num_sta_assoc_vif == 1) {
|
||||
ieee80211_iterate_active_interfaces_atomic(priv->hw,
|
||||
ath9k_htc_bss_iter, priv);
|
||||
ieee80211_iterate_active_interfaces_atomic(
|
||||
priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
ath9k_htc_bss_iter, priv);
|
||||
ath9k_htc_set_bssid(priv);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,10 +21,10 @@
|
|||
/******/
|
||||
|
||||
static const int subtype_txq_to_hwq[] = {
|
||||
[WME_AC_BE] = ATH_TXQ_AC_BE,
|
||||
[WME_AC_BK] = ATH_TXQ_AC_BK,
|
||||
[WME_AC_VI] = ATH_TXQ_AC_VI,
|
||||
[WME_AC_VO] = ATH_TXQ_AC_VO,
|
||||
[IEEE80211_AC_BE] = ATH_TXQ_AC_BE,
|
||||
[IEEE80211_AC_BK] = ATH_TXQ_AC_BK,
|
||||
[IEEE80211_AC_VI] = ATH_TXQ_AC_VI,
|
||||
[IEEE80211_AC_VO] = ATH_TXQ_AC_VO,
|
||||
};
|
||||
|
||||
#define ATH9K_HTC_INIT_TXQ(subtype) do { \
|
||||
|
@ -41,15 +41,15 @@ int get_hw_qnum(u16 queue, int *hwq_map)
|
|||
{
|
||||
switch (queue) {
|
||||
case 0:
|
||||
return hwq_map[WME_AC_VO];
|
||||
return hwq_map[IEEE80211_AC_VO];
|
||||
case 1:
|
||||
return hwq_map[WME_AC_VI];
|
||||
return hwq_map[IEEE80211_AC_VI];
|
||||
case 2:
|
||||
return hwq_map[WME_AC_BE];
|
||||
return hwq_map[IEEE80211_AC_BE];
|
||||
case 3:
|
||||
return hwq_map[WME_AC_BK];
|
||||
return hwq_map[IEEE80211_AC_BK];
|
||||
default:
|
||||
return hwq_map[WME_AC_BE];
|
||||
return hwq_map[IEEE80211_AC_BE];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,20 +106,20 @@ static inline enum htc_endpoint_id get_htc_epid(struct ath9k_htc_priv *priv,
|
|||
|
||||
switch (qnum) {
|
||||
case 0:
|
||||
TX_QSTAT_INC(WME_AC_VO);
|
||||
TX_QSTAT_INC(IEEE80211_AC_VO);
|
||||
epid = priv->data_vo_ep;
|
||||
break;
|
||||
case 1:
|
||||
TX_QSTAT_INC(WME_AC_VI);
|
||||
TX_QSTAT_INC(IEEE80211_AC_VI);
|
||||
epid = priv->data_vi_ep;
|
||||
break;
|
||||
case 2:
|
||||
TX_QSTAT_INC(WME_AC_BE);
|
||||
TX_QSTAT_INC(IEEE80211_AC_BE);
|
||||
epid = priv->data_be_ep;
|
||||
break;
|
||||
case 3:
|
||||
default:
|
||||
TX_QSTAT_INC(WME_AC_BK);
|
||||
TX_QSTAT_INC(IEEE80211_AC_BK);
|
||||
epid = priv->data_bk_ep;
|
||||
break;
|
||||
}
|
||||
|
@ -1082,7 +1082,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
|
|||
rx_status->freq = hw->conf.channel->center_freq;
|
||||
rx_status->signal = rxbuf->rxstatus.rs_rssi + ATH_DEFAULT_NOISE_FLOOR;
|
||||
rx_status->antenna = rxbuf->rxstatus.rs_antenna;
|
||||
rx_status->flag |= RX_FLAG_MACTIME_MPDU;
|
||||
rx_status->flag |= RX_FLAG_MACTIME_START;
|
||||
|
||||
return true;
|
||||
|
||||
|
|
|
@ -2561,11 +2561,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
|
|||
pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB;
|
||||
}
|
||||
|
||||
if (AR_SREV_9485_10(ah)) {
|
||||
pCap->pcie_lcr_extsync_en = true;
|
||||
pCap->pcie_lcr_offset = 0x80;
|
||||
}
|
||||
|
||||
if (ath9k_hw_dfs_tested(ah))
|
||||
pCap->hw_caps |= ATH9K_HW_CAP_DFS;
|
||||
|
||||
|
|
|
@ -273,8 +273,6 @@ struct ath9k_hw_capabilities {
|
|||
u8 rx_status_len;
|
||||
u8 tx_desc_len;
|
||||
u8 txs_len;
|
||||
u16 pcie_lcr_offset;
|
||||
bool pcie_lcr_extsync_en;
|
||||
};
|
||||
|
||||
struct ath9k_ops_config {
|
||||
|
@ -877,7 +875,6 @@ struct ath_hw {
|
|||
struct ar5416IniArray iniModesTxGain;
|
||||
struct ar5416IniArray iniCckfirNormal;
|
||||
struct ar5416IniArray iniCckfirJapan2484;
|
||||
struct ar5416IniArray ini_japan2484;
|
||||
struct ar5416IniArray iniModes_9271_ANI_reg;
|
||||
struct ar5416IniArray ini_radio_post_sys2ant;
|
||||
|
||||
|
@ -930,7 +927,6 @@ struct ath_bus_ops {
|
|||
void (*read_cachesize)(struct ath_common *common, int *csz);
|
||||
bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
|
||||
void (*bt_coex_prep)(struct ath_common *common);
|
||||
void (*extn_synch_en)(struct ath_common *common);
|
||||
void (*aspm_init)(struct ath_common *common);
|
||||
};
|
||||
|
||||
|
|
|
@ -435,7 +435,7 @@ static int ath9k_init_queues(struct ath_softc *sc)
|
|||
sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
|
||||
ath_cabq_update(sc);
|
||||
|
||||
for (i = 0; i < WME_NUM_AC; i++) {
|
||||
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
|
||||
sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
|
||||
sc->tx.txq_map[i]->mac80211_qnum = i;
|
||||
sc->tx.txq_max_pending[i] = ATH_MAX_QDEPTH;
|
||||
|
@ -563,10 +563,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
|
|||
spin_lock_init(&sc->sc_serial_rw);
|
||||
spin_lock_init(&sc->sc_pm_lock);
|
||||
mutex_init(&sc->mutex);
|
||||
#ifdef CONFIG_ATH9K_DEBUGFS
|
||||
spin_lock_init(&sc->nodes_lock);
|
||||
INIT_LIST_HEAD(&sc->nodes);
|
||||
#endif
|
||||
#ifdef CONFIG_ATH9K_MAC_DEBUG
|
||||
spin_lock_init(&sc->debug.samp_lock);
|
||||
#endif
|
||||
|
|
|
@ -27,9 +27,6 @@ void ath_tx_complete_poll_work(struct work_struct *work)
|
|||
struct ath_txq *txq;
|
||||
int i;
|
||||
bool needreset = false;
|
||||
#ifdef CONFIG_ATH9K_DEBUGFS
|
||||
sc->tx_complete_poll_work_seen++;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
|
||||
if (ATH_TXQ_SETUP(sc, i)) {
|
||||
|
@ -211,7 +208,7 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int
|
|||
int time_left;
|
||||
|
||||
memset(&txctl, 0, sizeof(txctl));
|
||||
txctl.txq = sc->tx.txq_map[WME_AC_BE];
|
||||
txctl.txq = sc->tx.txq_map[IEEE80211_AC_BE];
|
||||
|
||||
memset(tx_info, 0, sizeof(*tx_info));
|
||||
tx_info->band = hw->conf.channel->band;
|
||||
|
|
|
@ -331,11 +331,6 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
|
|||
u8 density;
|
||||
an = (struct ath_node *)sta->drv_priv;
|
||||
|
||||
#ifdef CONFIG_ATH9K_DEBUGFS
|
||||
spin_lock(&sc->nodes_lock);
|
||||
list_add(&an->list, &sc->nodes);
|
||||
spin_unlock(&sc->nodes_lock);
|
||||
#endif
|
||||
an->sta = sta;
|
||||
an->vif = vif;
|
||||
|
||||
|
@ -352,13 +347,6 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
|
|||
{
|
||||
struct ath_node *an = (struct ath_node *)sta->drv_priv;
|
||||
|
||||
#ifdef CONFIG_ATH9K_DEBUGFS
|
||||
spin_lock(&sc->nodes_lock);
|
||||
list_del(&an->list);
|
||||
spin_unlock(&sc->nodes_lock);
|
||||
an->sta = NULL;
|
||||
#endif
|
||||
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
|
||||
ath_tx_node_cleanup(sc, an);
|
||||
}
|
||||
|
@ -494,17 +482,6 @@ irqreturn_t ath_isr(int irq, void *dev)
|
|||
if (status & SCHED_INTR)
|
||||
sched = true;
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
if (status & ATH9K_INT_BMISS) {
|
||||
if (atomic_read(&sc->wow_sleep_proc_intr) == 0) {
|
||||
ath_dbg(common, ANY, "during WoW we got a BMISS\n");
|
||||
atomic_inc(&sc->wow_got_bmiss_intr);
|
||||
atomic_dec(&sc->wow_sleep_proc_intr);
|
||||
}
|
||||
ath_dbg(common, INTERRUPT, "beacon miss interrupt\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If a FATAL or RXORN interrupt is received, we have to reset the
|
||||
* chip immediately.
|
||||
|
@ -523,7 +500,15 @@ irqreturn_t ath_isr(int irq, void *dev)
|
|||
|
||||
goto chip_reset;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
if (status & ATH9K_INT_BMISS) {
|
||||
if (atomic_read(&sc->wow_sleep_proc_intr) == 0) {
|
||||
ath_dbg(common, ANY, "during WoW we got a BMISS\n");
|
||||
atomic_inc(&sc->wow_got_bmiss_intr);
|
||||
atomic_dec(&sc->wow_sleep_proc_intr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (status & ATH9K_INT_SWBA)
|
||||
tasklet_schedule(&sc->bcon_tasklet);
|
||||
|
||||
|
@ -686,9 +671,6 @@ static int ath9k_start(struct ieee80211_hw *hw)
|
|||
|
||||
spin_unlock_bh(&sc->sc_pcu_lock);
|
||||
|
||||
if (ah->caps.pcie_lcr_extsync_en && common->bus_ops->extn_synch_en)
|
||||
common->bus_ops->extn_synch_en(common);
|
||||
|
||||
mutex_unlock(&sc->mutex);
|
||||
|
||||
ath9k_ps_restore(sc);
|
||||
|
@ -924,8 +906,9 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
|
|||
ath9k_vif_iter(iter_data, vif->addr, vif);
|
||||
|
||||
/* Get list of all active MAC addresses */
|
||||
ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter,
|
||||
iter_data);
|
||||
ieee80211_iterate_active_interfaces_atomic(
|
||||
sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
ath9k_vif_iter, iter_data);
|
||||
}
|
||||
|
||||
/* Called with sc->mutex held. */
|
||||
|
@ -975,8 +958,9 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
|
|||
if (ah->opmode == NL80211_IFTYPE_STATION &&
|
||||
old_opmode == NL80211_IFTYPE_AP &&
|
||||
test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {
|
||||
ieee80211_iterate_active_interfaces_atomic(sc->hw,
|
||||
ath9k_sta_vif_iter, sc);
|
||||
ieee80211_iterate_active_interfaces_atomic(
|
||||
sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
ath9k_sta_vif_iter, sc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1329,7 +1313,7 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw,
|
|||
struct ath9k_tx_queue_info qi;
|
||||
int ret = 0;
|
||||
|
||||
if (queue >= WME_NUM_AC)
|
||||
if (queue >= IEEE80211_NUM_ACS)
|
||||
return 0;
|
||||
|
||||
txq = sc->tx.txq_map[queue];
|
||||
|
@ -1505,8 +1489,9 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
|
|||
clear_bit(SC_OP_BEACONS, &sc->sc_flags);
|
||||
}
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(sc->hw,
|
||||
ath9k_bss_assoc_iter, sc);
|
||||
ieee80211_iterate_active_interfaces_atomic(
|
||||
sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
ath9k_bss_assoc_iter, sc);
|
||||
|
||||
if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags) &&
|
||||
ah->opmode == NL80211_IFTYPE_STATION) {
|
||||
|
@ -1956,13 +1941,12 @@ static int ath9k_get_et_sset_count(struct ieee80211_hw *hw,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define PR_QNUM(_n) (sc->tx.txq_map[_n]->axq_qnum)
|
||||
#define AWDATA(elem) \
|
||||
do { \
|
||||
data[i++] = sc->debug.stats.txstats[PR_QNUM(WME_AC_BE)].elem; \
|
||||
data[i++] = sc->debug.stats.txstats[PR_QNUM(WME_AC_BK)].elem; \
|
||||
data[i++] = sc->debug.stats.txstats[PR_QNUM(WME_AC_VI)].elem; \
|
||||
data[i++] = sc->debug.stats.txstats[PR_QNUM(WME_AC_VO)].elem; \
|
||||
data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].elem; \
|
||||
data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].elem; \
|
||||
data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].elem; \
|
||||
data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].elem; \
|
||||
} while (0)
|
||||
|
||||
#define AWDATA_RX(elem) \
|
||||
|
@ -1977,14 +1961,14 @@ static void ath9k_get_et_stats(struct ieee80211_hw *hw,
|
|||
struct ath_softc *sc = hw->priv;
|
||||
int i = 0;
|
||||
|
||||
data[i++] = (sc->debug.stats.txstats[PR_QNUM(WME_AC_BE)].tx_pkts_all +
|
||||
sc->debug.stats.txstats[PR_QNUM(WME_AC_BK)].tx_pkts_all +
|
||||
sc->debug.stats.txstats[PR_QNUM(WME_AC_VI)].tx_pkts_all +
|
||||
sc->debug.stats.txstats[PR_QNUM(WME_AC_VO)].tx_pkts_all);
|
||||
data[i++] = (sc->debug.stats.txstats[PR_QNUM(WME_AC_BE)].tx_bytes_all +
|
||||
sc->debug.stats.txstats[PR_QNUM(WME_AC_BK)].tx_bytes_all +
|
||||
sc->debug.stats.txstats[PR_QNUM(WME_AC_VI)].tx_bytes_all +
|
||||
sc->debug.stats.txstats[PR_QNUM(WME_AC_VO)].tx_bytes_all);
|
||||
data[i++] = (sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].tx_pkts_all +
|
||||
sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].tx_pkts_all +
|
||||
sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].tx_pkts_all +
|
||||
sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].tx_pkts_all);
|
||||
data[i++] = (sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].tx_bytes_all +
|
||||
sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].tx_bytes_all +
|
||||
sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].tx_bytes_all +
|
||||
sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].tx_bytes_all);
|
||||
AWDATA_RX(rx_pkts_all);
|
||||
AWDATA_RX(rx_bytes_all);
|
||||
|
||||
|
|
|
@ -207,23 +207,6 @@ skip_tuning:
|
|||
ath9k_btcoex_timer_resume(sc);
|
||||
}
|
||||
|
||||
static void ath_mci_wait_btcal_done(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
|
||||
/* Stop tx & rx */
|
||||
ieee80211_stop_queues(sc->hw);
|
||||
ath_stoprecv(sc);
|
||||
ath_drain_all_txq(sc, false);
|
||||
|
||||
/* Wait for cal done */
|
||||
ar9003_mci_start_reset(ah, ah->curchan);
|
||||
|
||||
/* Resume tx & rx */
|
||||
ath_startrecv(sc);
|
||||
ieee80211_wake_queues(sc->hw);
|
||||
}
|
||||
|
||||
static void ath_mci_cal_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
|
@ -235,7 +218,7 @@ static void ath_mci_cal_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
|
|||
case MCI_GPM_BT_CAL_REQ:
|
||||
if (mci_hw->bt_state == MCI_BT_AWAKE) {
|
||||
mci_hw->bt_state = MCI_BT_CAL_START;
|
||||
ath_mci_wait_btcal_done(sc);
|
||||
ath9k_queue_reset(sc, RESET_TYPE_MCI);
|
||||
}
|
||||
ath_dbg(common, MCI, "MCI State : %d\n", mci_hw->bt_state);
|
||||
break;
|
||||
|
@ -578,6 +561,8 @@ void ath_mci_intr(struct ath_softc *sc)
|
|||
mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_GPM;
|
||||
|
||||
while (more_data == MCI_GPM_MORE) {
|
||||
if (test_bit(SC_OP_HW_RESET, &sc->sc_flags))
|
||||
return;
|
||||
|
||||
pgpm = mci->gpm_buf.bf_addr;
|
||||
offset = ar9003_mci_get_next_gpm_offset(ah, false,
|
||||
|
@ -744,12 +729,30 @@ void ath9k_mci_set_txpower(struct ath_softc *sc, bool setchannel,
|
|||
ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false);
|
||||
}
|
||||
|
||||
static void ath9k_mci_stomp_audio(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_btcoex *btcoex = &sc->btcoex;
|
||||
struct ath_mci_profile *mci = &btcoex->mci;
|
||||
|
||||
if (!mci->num_sco && !mci->num_a2dp)
|
||||
return;
|
||||
|
||||
if (ah->stats.avgbrssi > 25) {
|
||||
btcoex->stomp_audio = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
btcoex->stomp_audio++;
|
||||
}
|
||||
void ath9k_mci_update_rssi(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_btcoex *btcoex = &sc->btcoex;
|
||||
struct ath9k_hw_mci *mci_hw = &sc->sc_ah->btcoex_hw.mci;
|
||||
|
||||
ath9k_mci_stomp_audio(sc);
|
||||
|
||||
if (!(mci_hw->config & ATH_MCI_CONFIG_CONCUR_TX))
|
||||
return;
|
||||
|
||||
|
|
|
@ -96,17 +96,6 @@ static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void ath_pci_extn_synch_enable(struct ath_common *common)
|
||||
{
|
||||
struct ath_softc *sc = (struct ath_softc *) common->priv;
|
||||
struct pci_dev *pdev = to_pci_dev(sc->dev);
|
||||
u8 lnkctl;
|
||||
|
||||
pci_read_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, &lnkctl);
|
||||
lnkctl |= PCI_EXP_LNKCTL_ES;
|
||||
pci_write_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, lnkctl);
|
||||
}
|
||||
|
||||
/* Need to be called after we discover btcoex capabilities */
|
||||
static void ath_pci_aspm_init(struct ath_common *common)
|
||||
{
|
||||
|
@ -153,7 +142,6 @@ static const struct ath_bus_ops ath_pci_bus_ops = {
|
|||
.ath_bus_type = ATH_PCI,
|
||||
.read_cachesize = ath_pci_read_cachesize,
|
||||
.eeprom_read = ath_pci_eeprom_read,
|
||||
.extn_synch_en = ath_pci_extn_synch_enable,
|
||||
.aspm_init = ath_pci_aspm_init,
|
||||
};
|
||||
|
||||
|
|
|
@ -982,16 +982,6 @@ static void ath_rc_update_per(struct ath_softc *sc,
|
|||
}
|
||||
}
|
||||
|
||||
static void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix,
|
||||
int xretries, int retries, u8 per)
|
||||
{
|
||||
struct ath_rc_stats *stats = &rc->rcstats[rix];
|
||||
|
||||
stats->xretries += xretries;
|
||||
stats->retries += retries;
|
||||
stats->per = per;
|
||||
}
|
||||
|
||||
static void ath_rc_update_ht(struct ath_softc *sc,
|
||||
struct ath_rate_priv *ath_rc_priv,
|
||||
struct ieee80211_tx_info *tx_info,
|
||||
|
@ -1065,14 +1055,6 @@ static void ath_rc_update_ht(struct ath_softc *sc,
|
|||
|
||||
}
|
||||
|
||||
static void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate)
|
||||
{
|
||||
struct ath_rc_stats *stats;
|
||||
|
||||
stats = &rc->rcstats[final_rate];
|
||||
stats->success++;
|
||||
}
|
||||
|
||||
static void ath_rc_tx_status(struct ath_softc *sc,
|
||||
struct ath_rate_priv *ath_rc_priv,
|
||||
struct sk_buff *skb)
|
||||
|
@ -1350,7 +1332,25 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ATH9K_DEBUGFS
|
||||
#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS)
|
||||
|
||||
void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate)
|
||||
{
|
||||
struct ath_rc_stats *stats;
|
||||
|
||||
stats = &rc->rcstats[final_rate];
|
||||
stats->success++;
|
||||
}
|
||||
|
||||
void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix,
|
||||
int xretries, int retries, u8 per)
|
||||
{
|
||||
struct ath_rc_stats *stats = &rc->rcstats[rix];
|
||||
|
||||
stats->xretries += xretries;
|
||||
stats->retries += retries;
|
||||
stats->per = per;
|
||||
}
|
||||
|
||||
static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
|
@ -1428,10 +1428,17 @@ static void ath_rate_add_sta_debugfs(void *priv, void *priv_sta,
|
|||
struct dentry *dir)
|
||||
{
|
||||
struct ath_rate_priv *rc = priv_sta;
|
||||
debugfs_create_file("rc_stats", S_IRUGO, dir, rc, &fops_rcstat);
|
||||
rc->debugfs_rcstats = debugfs_create_file("rc_stats", S_IRUGO,
|
||||
dir, rc, &fops_rcstat);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ATH9K_DEBUGFS */
|
||||
static void ath_rate_remove_sta_debugfs(void *priv, void *priv_sta)
|
||||
{
|
||||
struct ath_rate_priv *rc = priv_sta;
|
||||
debugfs_remove(rc->debugfs_rcstats);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MAC80211_DEBUGFS && CONFIG_ATH9K_DEBUGFS */
|
||||
|
||||
static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
|
||||
{
|
||||
|
@ -1476,8 +1483,10 @@ static struct rate_control_ops ath_rate_ops = {
|
|||
.free = ath_rate_free,
|
||||
.alloc_sta = ath_rate_alloc_sta,
|
||||
.free_sta = ath_rate_free_sta,
|
||||
#ifdef CONFIG_ATH9K_DEBUGFS
|
||||
|
||||
#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS)
|
||||
.add_sta_debugfs = ath_rate_add_sta_debugfs,
|
||||
.remove_sta_debugfs = ath_rate_remove_sta_debugfs,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -211,10 +211,26 @@ struct ath_rate_priv {
|
|||
struct ath_rateset neg_ht_rates;
|
||||
const struct ath_rate_table *rate_table;
|
||||
|
||||
#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS)
|
||||
struct dentry *debugfs_rcstats;
|
||||
struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
|
||||
#endif
|
||||
};
|
||||
|
||||
#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS)
|
||||
void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate);
|
||||
void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix,
|
||||
int xretries, int retries, u8 per);
|
||||
#else
|
||||
static inline void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate)
|
||||
{
|
||||
}
|
||||
static inline void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix,
|
||||
int xretries, int retries, u8 per)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ATH9K_RATE_CONTROL
|
||||
int ath_rate_control_register(void);
|
||||
void ath_rate_control_unregister(void);
|
||||
|
|
|
@ -976,7 +976,7 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common,
|
|||
rx_status->freq = hw->conf.channel->center_freq;
|
||||
rx_status->signal = ah->noise + rx_stats->rs_rssi;
|
||||
rx_status->antenna = rx_stats->rs_antenna;
|
||||
rx_status->flag |= RX_FLAG_MACTIME_MPDU;
|
||||
rx_status->flag |= RX_FLAG_MACTIME_START;
|
||||
if (rx_stats->rs_moreaggr)
|
||||
rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
|
||||
|
||||
|
|
|
@ -1354,10 +1354,10 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
|
|||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath9k_tx_queue_info qi;
|
||||
static const int subtype_txq_to_hwq[] = {
|
||||
[WME_AC_BE] = ATH_TXQ_AC_BE,
|
||||
[WME_AC_BK] = ATH_TXQ_AC_BK,
|
||||
[WME_AC_VI] = ATH_TXQ_AC_VI,
|
||||
[WME_AC_VO] = ATH_TXQ_AC_VO,
|
||||
[IEEE80211_AC_BE] = ATH_TXQ_AC_BE,
|
||||
[IEEE80211_AC_BK] = ATH_TXQ_AC_BK,
|
||||
[IEEE80211_AC_VI] = ATH_TXQ_AC_VI,
|
||||
[IEEE80211_AC_VO] = ATH_TXQ_AC_VO,
|
||||
};
|
||||
int axq_qnum, i;
|
||||
|
||||
|
@ -2319,6 +2319,8 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
|
|||
|
||||
ath_txq_lock(sc, txq);
|
||||
|
||||
TX_STAT_INC(txq->axq_qnum, txprocdesc);
|
||||
|
||||
if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
|
||||
ath_txq_unlock(sc, txq);
|
||||
return;
|
||||
|
@ -2464,7 +2466,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
|
|||
}
|
||||
|
||||
for (acno = 0, ac = &an->ac[acno];
|
||||
acno < WME_NUM_AC; acno++, ac++) {
|
||||
acno < IEEE80211_NUM_ACS; acno++, ac++) {
|
||||
ac->sched = false;
|
||||
ac->txq = sc->tx.txq_map[acno];
|
||||
INIT_LIST_HEAD(&ac->tid_q);
|
||||
|
|
|
@ -28,11 +28,6 @@
|
|||
#include "fwcmd.h"
|
||||
#include "version.h"
|
||||
|
||||
#define MAKE_STR(symbol) #symbol
|
||||
#define TO_STR(symbol) MAKE_STR(symbol)
|
||||
#define CARL9170FW_API_VER_STR TO_STR(CARL9170FW_API_MAX_VER)
|
||||
MODULE_VERSION(CARL9170FW_API_VER_STR ":" CARL9170FW_VERSION_GIT);
|
||||
|
||||
static const u8 otus_magic[4] = { OTUS_MAGIC };
|
||||
|
||||
static const void *carl9170_fw_find_desc(struct ar9170 *ar, const u8 descid[4],
|
||||
|
|
|
@ -796,7 +796,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
|
|||
status.mactime += mactime;
|
||||
if (low_mactime_now <= mactime)
|
||||
status.mactime -= 0x10000;
|
||||
status.flag |= RX_FLAG_MACTIME_MPDU;
|
||||
status.flag |= RX_FLAG_MACTIME_START;
|
||||
}
|
||||
|
||||
chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT;
|
||||
|
|
|
@ -557,7 +557,7 @@ void b43legacy_rx(struct b43legacy_wldev *dev,
|
|||
status.mactime += mactime;
|
||||
if (low_mactime_now <= mactime)
|
||||
status.mactime -= 0x10000;
|
||||
status.flag |= RX_FLAG_MACTIME_MPDU;
|
||||
status.flag |= RX_FLAG_MACTIME_START;
|
||||
}
|
||||
|
||||
chanid = (chanstat & B43legacy_RX_CHAN_ID) >>
|
||||
|
|
|
@ -55,13 +55,16 @@ config BRCMFMAC_USB
|
|||
IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to
|
||||
use the driver for an USB wireless card.
|
||||
|
||||
config BRCMISCAN
|
||||
bool "Broadcom I-Scan (OBSOLETE)"
|
||||
depends on BRCMFMAC
|
||||
config BRCM_TRACING
|
||||
bool "Broadcom device tracing"
|
||||
depends on BRCMSMAC || BRCMFMAC
|
||||
---help---
|
||||
This option enables the I-Scan method. By default fullmac uses the
|
||||
new E-Scan method which uses less memory in firmware and gives no
|
||||
limitation on the number of scan results.
|
||||
If you say Y here, the Broadcom wireless drivers will register
|
||||
with ftrace to dump event information into the trace ringbuffer.
|
||||
Tracing can be enabled at runtime to aid in debugging wireless
|
||||
issues. This option adds a small amount of overhead when tracing
|
||||
is disabled. If unsure, say Y to allow developers to better help
|
||||
you when wireless problems occur.
|
||||
|
||||
config BRCMDBG
|
||||
bool "Broadcom driver debug functions"
|
||||
|
|
|
@ -25,6 +25,7 @@ obj-$(CONFIG_BRCMFMAC) += brcmfmac.o
|
|||
brcmfmac-objs += \
|
||||
wl_cfg80211.o \
|
||||
fwil.o \
|
||||
fweh.o \
|
||||
dhd_cdc.o \
|
||||
dhd_common.o \
|
||||
dhd_linux.o
|
||||
|
|
|
@ -42,7 +42,8 @@
|
|||
#ifdef CONFIG_BRCMFMAC_SDIO_OOB
|
||||
static irqreturn_t brcmf_sdio_irqhandler(int irq, void *dev_id)
|
||||
{
|
||||
struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(dev_id);
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev_id);
|
||||
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
|
||||
|
||||
brcmf_dbg(INTR, "oob intr triggered\n");
|
||||
|
||||
|
@ -71,7 +72,7 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
|
|||
brcmf_dbg(ERROR, "requesting irq %d\n", sdiodev->irq);
|
||||
ret = request_irq(sdiodev->irq, brcmf_sdio_irqhandler,
|
||||
sdiodev->irq_flags, "brcmf_oob_intr",
|
||||
&sdiodev->func[1]->card->dev);
|
||||
&sdiodev->func[1]->dev);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
spin_lock_init(&sdiodev->irq_en_lock);
|
||||
|
@ -84,6 +85,8 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
|
|||
return ret;
|
||||
sdiodev->irq_wake = true;
|
||||
|
||||
sdio_claim_host(sdiodev->func[1]);
|
||||
|
||||
/* must configure SDIO_CCCR_IENx to enable irq */
|
||||
data = brcmf_sdio_regrb(sdiodev, SDIO_CCCR_IENx, &ret);
|
||||
data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
|
||||
|
@ -95,6 +98,8 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
|
|||
data |= SDIO_SEPINT_ACT_HI;
|
||||
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret);
|
||||
|
||||
sdio_release_host(sdiodev->func[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -102,14 +107,16 @@ int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
|
|||
{
|
||||
brcmf_dbg(TRACE, "Entering\n");
|
||||
|
||||
sdio_claim_host(sdiodev->func[1]);
|
||||
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
|
||||
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
|
||||
sdio_release_host(sdiodev->func[1]);
|
||||
|
||||
if (sdiodev->irq_wake) {
|
||||
disable_irq_wake(sdiodev->irq);
|
||||
sdiodev->irq_wake = false;
|
||||
}
|
||||
free_irq(sdiodev->irq, &sdiodev->func[1]->card->dev);
|
||||
free_irq(sdiodev->irq, &sdiodev->func[1]->dev);
|
||||
sdiodev->irq_en = false;
|
||||
|
||||
return 0;
|
||||
|
@ -117,7 +124,8 @@ int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
|
|||
#else /* CONFIG_BRCMFMAC_SDIO_OOB */
|
||||
static void brcmf_sdio_irqhandler(struct sdio_func *func)
|
||||
{
|
||||
struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(&func->dev);
|
||||
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
|
||||
|
||||
brcmf_dbg(INTR, "ib intr triggered\n");
|
||||
|
||||
|
@ -249,9 +257,7 @@ u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
|
|||
int retval;
|
||||
|
||||
brcmf_dbg(INFO, "addr:0x%08x\n", addr);
|
||||
sdio_claim_host(sdiodev->func[1]);
|
||||
retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
|
||||
sdio_release_host(sdiodev->func[1]);
|
||||
brcmf_dbg(INFO, "data:0x%02x\n", data);
|
||||
|
||||
if (ret)
|
||||
|
@ -266,9 +272,7 @@ u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
|
|||
int retval;
|
||||
|
||||
brcmf_dbg(INFO, "addr:0x%08x\n", addr);
|
||||
sdio_claim_host(sdiodev->func[1]);
|
||||
retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
|
||||
sdio_release_host(sdiodev->func[1]);
|
||||
brcmf_dbg(INFO, "data:0x%08x\n", data);
|
||||
|
||||
if (ret)
|
||||
|
@ -283,9 +287,7 @@ void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr,
|
|||
int retval;
|
||||
|
||||
brcmf_dbg(INFO, "addr:0x%08x, data:0x%02x\n", addr, data);
|
||||
sdio_claim_host(sdiodev->func[1]);
|
||||
retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
|
||||
sdio_release_host(sdiodev->func[1]);
|
||||
|
||||
if (ret)
|
||||
*ret = retval;
|
||||
|
@ -297,9 +299,7 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
|
|||
int retval;
|
||||
|
||||
brcmf_dbg(INFO, "addr:0x%08x, data:0x%08x\n", addr, data);
|
||||
sdio_claim_host(sdiodev->func[1]);
|
||||
retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
|
||||
sdio_release_host(sdiodev->func[1]);
|
||||
|
||||
if (ret)
|
||||
*ret = retval;
|
||||
|
@ -364,8 +364,6 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
|
|||
brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
|
||||
fn, addr, pkt->len);
|
||||
|
||||
sdio_claim_host(sdiodev->func[1]);
|
||||
|
||||
width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
|
||||
err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr);
|
||||
if (err)
|
||||
|
@ -376,8 +374,6 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
|
|||
fn, addr, pkt);
|
||||
|
||||
done:
|
||||
sdio_release_host(sdiodev->func[1]);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -391,8 +387,6 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
|
|||
brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
|
||||
fn, addr, pktq->qlen);
|
||||
|
||||
sdio_claim_host(sdiodev->func[1]);
|
||||
|
||||
width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
|
||||
err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr);
|
||||
if (err)
|
||||
|
@ -403,8 +397,6 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
|
|||
pktq);
|
||||
|
||||
done:
|
||||
sdio_release_host(sdiodev->func[1]);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -446,8 +438,6 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
|
|||
if (flags & SDIO_REQ_ASYNC)
|
||||
return -ENOTSUPP;
|
||||
|
||||
sdio_claim_host(sdiodev->func[1]);
|
||||
|
||||
if (bar0 != sdiodev->sbwad) {
|
||||
err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
|
||||
if (err)
|
||||
|
@ -467,8 +457,6 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
|
|||
addr, pkt);
|
||||
|
||||
done:
|
||||
sdio_release_host(sdiodev->func[1]);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -510,10 +498,8 @@ int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
|
|||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
/* issue abort cmd52 command through F0 */
|
||||
sdio_claim_host(sdiodev->func[1]);
|
||||
brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0,
|
||||
SDIO_CCCR_ABORT, &t_func);
|
||||
sdio_release_host(sdiodev->func[1]);
|
||||
|
||||
brcmf_dbg(TRACE, "Exit\n");
|
||||
return 0;
|
||||
|
@ -530,9 +516,6 @@ int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
|
|||
|
||||
regs = SI_ENUM_BASE;
|
||||
|
||||
/* Report the BAR, to fix if needed */
|
||||
sdiodev->sbwad = SI_ENUM_BASE;
|
||||
|
||||
/* try to attach to the target device */
|
||||
sdiodev->bus = brcmf_sdbrcm_probe(regs, sdiodev);
|
||||
if (!sdiodev->bus) {
|
||||
|
@ -551,6 +534,8 @@ EXPORT_SYMBOL(brcmf_sdio_probe);
|
|||
|
||||
int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev)
|
||||
{
|
||||
sdiodev->bus_if->state = BRCMF_BUS_DOWN;
|
||||
|
||||
if (sdiodev->bus) {
|
||||
brcmf_sdbrcm_disconnect(sdiodev->bus);
|
||||
sdiodev->bus = NULL;
|
||||
|
|
|
@ -372,9 +372,7 @@ static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev)
|
|||
}
|
||||
|
||||
/* Enable Function 1 */
|
||||
sdio_claim_host(sdiodev->func[1]);
|
||||
err_ret = sdio_enable_func(sdiodev->func[1]);
|
||||
sdio_release_host(sdiodev->func[1]);
|
||||
if (err_ret)
|
||||
brcmf_dbg(ERROR, "Failed to enable F1 Err: 0x%08x\n", err_ret);
|
||||
|
||||
|
@ -393,16 +391,14 @@ int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev)
|
|||
sdiodev->num_funcs = 2;
|
||||
|
||||
sdio_claim_host(sdiodev->func[1]);
|
||||
|
||||
err_ret = sdio_set_block_size(sdiodev->func[1], SDIO_FUNC1_BLOCKSIZE);
|
||||
sdio_release_host(sdiodev->func[1]);
|
||||
if (err_ret) {
|
||||
brcmf_dbg(ERROR, "Failed to set F1 blocksize\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
sdio_claim_host(sdiodev->func[2]);
|
||||
err_ret = sdio_set_block_size(sdiodev->func[2], SDIO_FUNC2_BLOCKSIZE);
|
||||
sdio_release_host(sdiodev->func[2]);
|
||||
if (err_ret) {
|
||||
brcmf_dbg(ERROR, "Failed to set F2 blocksize\n");
|
||||
goto out;
|
||||
|
@ -411,6 +407,7 @@ int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev)
|
|||
brcmf_sdioh_enablefuncs(sdiodev);
|
||||
|
||||
out:
|
||||
sdio_release_host(sdiodev->func[1]);
|
||||
brcmf_dbg(TRACE, "Done\n");
|
||||
return err_ret;
|
||||
}
|
||||
|
@ -459,95 +456,106 @@ static inline int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev)
|
|||
#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
|
||||
|
||||
static int brcmf_ops_sdio_probe(struct sdio_func *func,
|
||||
const struct sdio_device_id *id)
|
||||
const struct sdio_device_id *id)
|
||||
{
|
||||
int ret = 0;
|
||||
int err;
|
||||
struct brcmf_sdio_dev *sdiodev;
|
||||
struct brcmf_bus *bus_if;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
brcmf_dbg(TRACE, "func->class=%x\n", func->class);
|
||||
brcmf_dbg(TRACE, "sdio_vendor: 0x%04x\n", func->vendor);
|
||||
brcmf_dbg(TRACE, "sdio_device: 0x%04x\n", func->device);
|
||||
brcmf_dbg(TRACE, "Function#: 0x%04x\n", func->num);
|
||||
brcmf_dbg(TRACE, "Class=%x\n", func->class);
|
||||
brcmf_dbg(TRACE, "sdio vendor ID: 0x%04x\n", func->vendor);
|
||||
brcmf_dbg(TRACE, "sdio device ID: 0x%04x\n", func->device);
|
||||
brcmf_dbg(TRACE, "Function#: %d\n", func->num);
|
||||
|
||||
if (func->num == 1) {
|
||||
if (dev_get_drvdata(&func->card->dev)) {
|
||||
brcmf_dbg(ERROR, "card private drvdata occupied\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
bus_if = kzalloc(sizeof(struct brcmf_bus), GFP_KERNEL);
|
||||
if (!bus_if)
|
||||
return -ENOMEM;
|
||||
sdiodev = kzalloc(sizeof(struct brcmf_sdio_dev), GFP_KERNEL);
|
||||
if (!sdiodev) {
|
||||
kfree(bus_if);
|
||||
return -ENOMEM;
|
||||
}
|
||||
sdiodev->func[0] = func;
|
||||
sdiodev->func[1] = func;
|
||||
sdiodev->bus_if = bus_if;
|
||||
bus_if->bus_priv.sdio = sdiodev;
|
||||
bus_if->type = SDIO_BUS;
|
||||
bus_if->align = BRCMF_SDALIGN;
|
||||
dev_set_drvdata(&func->card->dev, sdiodev);
|
||||
/* Consume func num 1 but dont do anything with it. */
|
||||
if (func->num == 1)
|
||||
return 0;
|
||||
|
||||
atomic_set(&sdiodev->suspend, false);
|
||||
init_waitqueue_head(&sdiodev->request_byte_wait);
|
||||
init_waitqueue_head(&sdiodev->request_word_wait);
|
||||
init_waitqueue_head(&sdiodev->request_chain_wait);
|
||||
init_waitqueue_head(&sdiodev->request_buffer_wait);
|
||||
/* Ignore anything but func 2 */
|
||||
if (func->num != 2)
|
||||
return -ENODEV;
|
||||
|
||||
bus_if = kzalloc(sizeof(struct brcmf_bus), GFP_KERNEL);
|
||||
if (!bus_if)
|
||||
return -ENOMEM;
|
||||
sdiodev = kzalloc(sizeof(struct brcmf_sdio_dev), GFP_KERNEL);
|
||||
if (!sdiodev) {
|
||||
kfree(bus_if);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (func->num == 2) {
|
||||
sdiodev = dev_get_drvdata(&func->card->dev);
|
||||
if ((!sdiodev) || (sdiodev->func[1]->card != func->card))
|
||||
return -ENODEV;
|
||||
sdiodev->func[0] = func->card->sdio_func[0];
|
||||
sdiodev->func[1] = func->card->sdio_func[0];
|
||||
sdiodev->func[2] = func;
|
||||
|
||||
ret = brcmf_sdio_getintrcfg(sdiodev);
|
||||
if (ret)
|
||||
return ret;
|
||||
sdiodev->func[2] = func;
|
||||
sdiodev->bus_if = bus_if;
|
||||
bus_if->bus_priv.sdio = sdiodev;
|
||||
bus_if->align = BRCMF_SDALIGN;
|
||||
dev_set_drvdata(&func->dev, bus_if);
|
||||
dev_set_drvdata(&sdiodev->func[1]->dev, bus_if);
|
||||
sdiodev->dev = &sdiodev->func[1]->dev;
|
||||
|
||||
bus_if = sdiodev->bus_if;
|
||||
sdiodev->dev = &func->dev;
|
||||
dev_set_drvdata(&func->dev, bus_if);
|
||||
atomic_set(&sdiodev->suspend, false);
|
||||
init_waitqueue_head(&sdiodev->request_byte_wait);
|
||||
init_waitqueue_head(&sdiodev->request_word_wait);
|
||||
init_waitqueue_head(&sdiodev->request_chain_wait);
|
||||
init_waitqueue_head(&sdiodev->request_buffer_wait);
|
||||
err = brcmf_sdio_getintrcfg(sdiodev);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_probe...\n");
|
||||
ret = brcmf_sdio_probe(sdiodev);
|
||||
brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_probe...\n");
|
||||
err = brcmf_sdio_probe(sdiodev);
|
||||
if (err) {
|
||||
brcmf_dbg(ERROR, "F2 error, probe failed %d...\n", err);
|
||||
goto fail;
|
||||
}
|
||||
brcmf_dbg(TRACE, "F2 init completed...\n");
|
||||
return 0;
|
||||
|
||||
return ret;
|
||||
fail:
|
||||
dev_set_drvdata(&func->dev, NULL);
|
||||
dev_set_drvdata(&sdiodev->func[1]->dev, NULL);
|
||||
kfree(sdiodev);
|
||||
kfree(bus_if);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void brcmf_ops_sdio_remove(struct sdio_func *func)
|
||||
{
|
||||
struct brcmf_bus *bus_if;
|
||||
struct brcmf_sdio_dev *sdiodev;
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
brcmf_dbg(INFO, "func->class=%x\n", func->class);
|
||||
brcmf_dbg(INFO, "sdio_vendor: 0x%04x\n", func->vendor);
|
||||
brcmf_dbg(INFO, "sdio_device: 0x%04x\n", func->device);
|
||||
brcmf_dbg(INFO, "Function#: 0x%04x\n", func->num);
|
||||
|
||||
if (func->num == 2) {
|
||||
bus_if = dev_get_drvdata(&func->dev);
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
brcmf_dbg(TRACE, "sdio vendor ID: 0x%04x\n", func->vendor);
|
||||
brcmf_dbg(TRACE, "sdio device ID: 0x%04x\n", func->device);
|
||||
brcmf_dbg(TRACE, "Function: %d\n", func->num);
|
||||
|
||||
if (func->num != 1 && func->num != 2)
|
||||
return;
|
||||
|
||||
bus_if = dev_get_drvdata(&func->dev);
|
||||
if (bus_if) {
|
||||
sdiodev = bus_if->bus_priv.sdio;
|
||||
brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_remove...\n");
|
||||
brcmf_sdio_remove(sdiodev);
|
||||
dev_set_drvdata(&func->card->dev, NULL);
|
||||
dev_set_drvdata(&func->dev, NULL);
|
||||
|
||||
dev_set_drvdata(&sdiodev->func[1]->dev, NULL);
|
||||
dev_set_drvdata(&sdiodev->func[2]->dev, NULL);
|
||||
|
||||
kfree(bus_if);
|
||||
kfree(sdiodev);
|
||||
}
|
||||
|
||||
brcmf_dbg(TRACE, "Exit\n");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int brcmf_sdio_suspend(struct device *dev)
|
||||
{
|
||||
mmc_pm_flag_t sdio_flags;
|
||||
struct sdio_func *func = dev_to_sdio_func(dev);
|
||||
struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
|
||||
int ret = 0;
|
||||
|
||||
brcmf_dbg(TRACE, "\n");
|
||||
|
@ -573,8 +581,8 @@ static int brcmf_sdio_suspend(struct device *dev)
|
|||
|
||||
static int brcmf_sdio_resume(struct device *dev)
|
||||
{
|
||||
struct sdio_func *func = dev_to_sdio_func(dev);
|
||||
struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
|
||||
|
||||
brcmf_sdio_wdtmr_enable(sdiodev, true);
|
||||
atomic_set(&sdiodev->suspend, false);
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
|
||||
#define BRCMF_VERSION_STR "4.218.248.5"
|
||||
|
||||
#include "fweh.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* IO codes that are interpreted by dongle firmware
|
||||
******************************************************************************/
|
||||
|
@ -38,8 +40,11 @@
|
|||
#define BRCMF_C_GET_SSID 25
|
||||
#define BRCMF_C_SET_SSID 26
|
||||
#define BRCMF_C_GET_CHANNEL 29
|
||||
#define BRCMF_C_SET_CHANNEL 30
|
||||
#define BRCMF_C_GET_SRL 31
|
||||
#define BRCMF_C_SET_SRL 32
|
||||
#define BRCMF_C_GET_LRL 33
|
||||
#define BRCMF_C_SET_LRL 34
|
||||
#define BRCMF_C_GET_RADIO 37
|
||||
#define BRCMF_C_SET_RADIO 38
|
||||
#define BRCMF_C_GET_PHYTYPE 39
|
||||
|
@ -58,6 +63,7 @@
|
|||
#define BRCMF_C_SET_COUNTRY 84
|
||||
#define BRCMF_C_GET_PM 85
|
||||
#define BRCMF_C_SET_PM 86
|
||||
#define BRCMF_C_GET_CURR_RATESET 114
|
||||
#define BRCMF_C_GET_AP 117
|
||||
#define BRCMF_C_SET_AP 118
|
||||
#define BRCMF_C_GET_RSSI 127
|
||||
|
@ -65,6 +71,7 @@
|
|||
#define BRCMF_C_SET_WSEC 134
|
||||
#define BRCMF_C_GET_PHY_NOISE 135
|
||||
#define BRCMF_C_GET_BSS_INFO 136
|
||||
#define BRCMF_C_GET_PHYLIST 180
|
||||
#define BRCMF_C_SET_SCAN_CHANNEL_TIME 185
|
||||
#define BRCMF_C_SET_SCAN_UNASSOC_TIME 187
|
||||
#define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON 201
|
||||
|
@ -100,29 +107,8 @@
|
|||
#define BRCMF_SCAN_PARAMS_COUNT_MASK 0x0000ffff
|
||||
#define BRCMF_SCAN_PARAMS_NSSID_SHIFT 16
|
||||
|
||||
#define BRCMF_SCAN_ACTION_START 1
|
||||
#define BRCMF_SCAN_ACTION_CONTINUE 2
|
||||
#define WL_SCAN_ACTION_ABORT 3
|
||||
|
||||
#define BRCMF_ISCAN_REQ_VERSION 1
|
||||
|
||||
/* brcmf_iscan_results status values */
|
||||
#define BRCMF_SCAN_RESULTS_SUCCESS 0
|
||||
#define BRCMF_SCAN_RESULTS_PARTIAL 1
|
||||
#define BRCMF_SCAN_RESULTS_PENDING 2
|
||||
#define BRCMF_SCAN_RESULTS_ABORTED 3
|
||||
#define BRCMF_SCAN_RESULTS_NO_MEM 4
|
||||
|
||||
/* Indicates this key is using soft encrypt */
|
||||
#define WL_SOFT_KEY (1 << 0)
|
||||
/* primary (ie tx) key */
|
||||
#define BRCMF_PRIMARY_KEY (1 << 1)
|
||||
/* Reserved for backward compat */
|
||||
#define WL_KF_RES_4 (1 << 4)
|
||||
/* Reserved for backward compat */
|
||||
#define WL_KF_RES_5 (1 << 5)
|
||||
/* Indicates a group key for a IBSS PEER */
|
||||
#define WL_IBSS_PEER_GROUP_KEY (1 << 6)
|
||||
|
||||
/* For supporting multiple interfaces */
|
||||
#define BRCMF_MAX_IFS 16
|
||||
|
@ -130,10 +116,6 @@
|
|||
#define DOT11_BSSTYPE_ANY 2
|
||||
#define DOT11_MAX_DEFAULT_KEYS 4
|
||||
|
||||
#define BRCMF_EVENT_MSG_LINK 0x01
|
||||
#define BRCMF_EVENT_MSG_FLUSHTXQ 0x02
|
||||
#define BRCMF_EVENT_MSG_GROUP 0x04
|
||||
|
||||
#define BRCMF_ESCAN_REQ_VERSION 1
|
||||
|
||||
#define WLC_BSS_RSSI_ON_CHANNEL 0x0002
|
||||
|
@ -141,108 +123,6 @@
|
|||
#define BRCMF_MAXRATES_IN_SET 16 /* max # of rates in rateset */
|
||||
#define BRCMF_STA_ASSOC 0x10 /* Associated */
|
||||
|
||||
struct brcmf_event_msg {
|
||||
__be16 version;
|
||||
__be16 flags;
|
||||
__be32 event_type;
|
||||
__be32 status;
|
||||
__be32 reason;
|
||||
__be32 auth_type;
|
||||
__be32 datalen;
|
||||
u8 addr[ETH_ALEN];
|
||||
char ifname[IFNAMSIZ];
|
||||
u8 ifidx;
|
||||
u8 bsscfgidx;
|
||||
} __packed;
|
||||
|
||||
struct brcm_ethhdr {
|
||||
u16 subtype;
|
||||
u16 length;
|
||||
u8 version;
|
||||
u8 oui[3];
|
||||
u16 usr_subtype;
|
||||
} __packed;
|
||||
|
||||
struct brcmf_event {
|
||||
struct ethhdr eth;
|
||||
struct brcm_ethhdr hdr;
|
||||
struct brcmf_event_msg msg;
|
||||
} __packed;
|
||||
|
||||
/* event codes sent by the dongle to this driver */
|
||||
#define BRCMF_E_SET_SSID 0
|
||||
#define BRCMF_E_JOIN 1
|
||||
#define BRCMF_E_START 2
|
||||
#define BRCMF_E_AUTH 3
|
||||
#define BRCMF_E_AUTH_IND 4
|
||||
#define BRCMF_E_DEAUTH 5
|
||||
#define BRCMF_E_DEAUTH_IND 6
|
||||
#define BRCMF_E_ASSOC 7
|
||||
#define BRCMF_E_ASSOC_IND 8
|
||||
#define BRCMF_E_REASSOC 9
|
||||
#define BRCMF_E_REASSOC_IND 10
|
||||
#define BRCMF_E_DISASSOC 11
|
||||
#define BRCMF_E_DISASSOC_IND 12
|
||||
#define BRCMF_E_QUIET_START 13
|
||||
#define BRCMF_E_QUIET_END 14
|
||||
#define BRCMF_E_BEACON_RX 15
|
||||
#define BRCMF_E_LINK 16
|
||||
#define BRCMF_E_MIC_ERROR 17
|
||||
#define BRCMF_E_NDIS_LINK 18
|
||||
#define BRCMF_E_ROAM 19
|
||||
#define BRCMF_E_TXFAIL 20
|
||||
#define BRCMF_E_PMKID_CACHE 21
|
||||
#define BRCMF_E_RETROGRADE_TSF 22
|
||||
#define BRCMF_E_PRUNE 23
|
||||
#define BRCMF_E_AUTOAUTH 24
|
||||
#define BRCMF_E_EAPOL_MSG 25
|
||||
#define BRCMF_E_SCAN_COMPLETE 26
|
||||
#define BRCMF_E_ADDTS_IND 27
|
||||
#define BRCMF_E_DELTS_IND 28
|
||||
#define BRCMF_E_BCNSENT_IND 29
|
||||
#define BRCMF_E_BCNRX_MSG 30
|
||||
#define BRCMF_E_BCNLOST_MSG 31
|
||||
#define BRCMF_E_ROAM_PREP 32
|
||||
#define BRCMF_E_PFN_NET_FOUND 33
|
||||
#define BRCMF_E_PFN_NET_LOST 34
|
||||
#define BRCMF_E_RESET_COMPLETE 35
|
||||
#define BRCMF_E_JOIN_START 36
|
||||
#define BRCMF_E_ROAM_START 37
|
||||
#define BRCMF_E_ASSOC_START 38
|
||||
#define BRCMF_E_IBSS_ASSOC 39
|
||||
#define BRCMF_E_RADIO 40
|
||||
#define BRCMF_E_PSM_WATCHDOG 41
|
||||
#define BRCMF_E_PROBREQ_MSG 44
|
||||
#define BRCMF_E_SCAN_CONFIRM_IND 45
|
||||
#define BRCMF_E_PSK_SUP 46
|
||||
#define BRCMF_E_COUNTRY_CODE_CHANGED 47
|
||||
#define BRCMF_E_EXCEEDED_MEDIUM_TIME 48
|
||||
#define BRCMF_E_ICV_ERROR 49
|
||||
#define BRCMF_E_UNICAST_DECODE_ERROR 50
|
||||
#define BRCMF_E_MULTICAST_DECODE_ERROR 51
|
||||
#define BRCMF_E_TRACE 52
|
||||
#define BRCMF_E_IF 54
|
||||
#define BRCMF_E_RSSI 56
|
||||
#define BRCMF_E_PFN_SCAN_COMPLETE 57
|
||||
#define BRCMF_E_EXTLOG_MSG 58
|
||||
#define BRCMF_E_ACTION_FRAME 59
|
||||
#define BRCMF_E_ACTION_FRAME_COMPLETE 60
|
||||
#define BRCMF_E_PRE_ASSOC_IND 61
|
||||
#define BRCMF_E_PRE_REASSOC_IND 62
|
||||
#define BRCMF_E_CHANNEL_ADOPTED 63
|
||||
#define BRCMF_E_AP_STARTED 64
|
||||
#define BRCMF_E_DFS_AP_STOP 65
|
||||
#define BRCMF_E_DFS_AP_RESUME 66
|
||||
#define BRCMF_E_RESERVED1 67
|
||||
#define BRCMF_E_RESERVED2 68
|
||||
#define BRCMF_E_ESCAN_RESULT 69
|
||||
#define BRCMF_E_ACTION_FRAME_OFF_CHAN_COMPLETE 70
|
||||
#define BRCMF_E_DCS_REQUEST 73
|
||||
|
||||
#define BRCMF_E_FIFO_CREDIT_MAP 74
|
||||
|
||||
#define BRCMF_E_LAST 75
|
||||
|
||||
#define BRCMF_E_STATUS_SUCCESS 0
|
||||
#define BRCMF_E_STATUS_FAIL 1
|
||||
#define BRCMF_E_STATUS_TIMEOUT 2
|
||||
|
@ -403,7 +283,7 @@ struct brcm_rateset_le {
|
|||
/* # rates in this set */
|
||||
__le32 count;
|
||||
/* rates in 500kbps units w/hi bit set if basic */
|
||||
u8 rates[WL_NUMRATES];
|
||||
u8 rates[BRCMF_MAXRATES_IN_SET];
|
||||
};
|
||||
|
||||
struct brcmf_ssid {
|
||||
|
@ -452,14 +332,6 @@ struct brcmf_scan_params_le {
|
|||
__le16 channel_list[1]; /* list of chanspecs */
|
||||
};
|
||||
|
||||
/* incremental scan struct */
|
||||
struct brcmf_iscan_params_le {
|
||||
__le32 version;
|
||||
__le16 action;
|
||||
__le16 scan_duration;
|
||||
struct brcmf_scan_params_le params_le;
|
||||
};
|
||||
|
||||
struct brcmf_scan_results {
|
||||
u32 buflen;
|
||||
u32 version;
|
||||
|
@ -467,12 +339,6 @@ struct brcmf_scan_results {
|
|||
struct brcmf_bss_info_le bss_info_le[];
|
||||
};
|
||||
|
||||
struct brcmf_scan_results_le {
|
||||
__le32 buflen;
|
||||
__le32 version;
|
||||
__le32 count;
|
||||
};
|
||||
|
||||
struct brcmf_escan_params_le {
|
||||
__le32 version;
|
||||
__le16 action;
|
||||
|
@ -508,23 +374,6 @@ struct brcmf_join_params {
|
|||
struct brcmf_assoc_params_le params_le;
|
||||
};
|
||||
|
||||
/* incremental scan results struct */
|
||||
struct brcmf_iscan_results {
|
||||
union {
|
||||
u32 status;
|
||||
__le32 status_le;
|
||||
};
|
||||
union {
|
||||
struct brcmf_scan_results results;
|
||||
struct brcmf_scan_results_le results_le;
|
||||
};
|
||||
};
|
||||
|
||||
/* size of brcmf_iscan_results not including variable length array */
|
||||
#define BRCMF_ISCAN_RESULTS_FIXED_SIZE \
|
||||
(sizeof(struct brcmf_scan_results) + \
|
||||
offsetof(struct brcmf_iscan_results, results))
|
||||
|
||||
struct brcmf_wsec_key {
|
||||
u32 index; /* key index */
|
||||
u32 len; /* key length */
|
||||
|
@ -661,10 +510,11 @@ struct brcmf_pub {
|
|||
struct mutex proto_block;
|
||||
unsigned char proto_buf[BRCMF_DCMD_MAXLEN];
|
||||
|
||||
struct work_struct setmacaddr_work;
|
||||
struct work_struct multicast_work;
|
||||
u8 macvalue[ETH_ALEN];
|
||||
atomic_t pend_8021x_cnt;
|
||||
wait_queue_head_t pend_8021x_wait;
|
||||
|
||||
struct brcmf_fweh_info fweh;
|
||||
#ifdef DEBUG
|
||||
struct dentry *dbgfs_dir;
|
||||
#endif
|
||||
|
@ -701,6 +551,8 @@ struct brcmf_if {
|
|||
struct brcmf_cfg80211_vif *vif;
|
||||
struct net_device *ndev;
|
||||
struct net_device_stats stats;
|
||||
struct work_struct setmacaddr_work;
|
||||
struct work_struct multicast_work;
|
||||
int idx;
|
||||
s32 bssidx;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
|
@ -714,9 +566,6 @@ static inline s32 brcmf_ndev_bssidx(struct net_device *ndev)
|
|||
|
||||
extern const struct bcmevent_name bcmevent_names[];
|
||||
|
||||
extern uint brcmf_c_mkiovar(char *name, char *data, uint datalen,
|
||||
char *buf, uint len);
|
||||
|
||||
extern int brcmf_netdev_wait_pend8021x(struct net_device *ndev);
|
||||
|
||||
/* Return pointer to interface name */
|
||||
|
@ -728,14 +577,9 @@ extern int brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx,
|
|||
extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
|
||||
void *buf, uint len);
|
||||
|
||||
extern int brcmf_ifname2idx(struct brcmf_pub *drvr, char *name);
|
||||
extern int brcmf_c_host_event(struct brcmf_pub *drvr, int *idx,
|
||||
void *pktdata, struct brcmf_event_msg *,
|
||||
void **data_ptr);
|
||||
|
||||
extern int brcmf_net_attach(struct brcmf_if *ifp);
|
||||
extern struct brcmf_if *brcmf_add_if(struct device *dev, int ifidx, s32 bssidx,
|
||||
char *name, u8 *mac_addr);
|
||||
extern struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx,
|
||||
s32 bssidx, char *name, u8 *mac_addr);
|
||||
extern void brcmf_del_if(struct brcmf_pub *drvr, int ifidx);
|
||||
|
||||
#endif /* _BRCMF_H_ */
|
||||
|
|
|
@ -45,7 +45,6 @@ struct brcmf_bus_dcmd {
|
|||
|
||||
/* interface structure between common and bus layer */
|
||||
struct brcmf_bus {
|
||||
u8 type; /* bus type */
|
||||
union {
|
||||
struct brcmf_sdio_dev *sdio;
|
||||
struct brcmf_usbdev *usb;
|
||||
|
@ -85,7 +84,7 @@ extern bool brcmf_c_prec_enq(struct device *dev, struct pktq *q,
|
|||
struct sk_buff *pkt, int prec);
|
||||
|
||||
/* Receive frame for delivery to OS. Callee disposes of rxp. */
|
||||
extern void brcmf_rx_frame(struct device *dev, int ifidx,
|
||||
extern void brcmf_rx_frame(struct device *dev, u8 ifidx,
|
||||
struct sk_buff_head *rxlist);
|
||||
static inline void brcmf_rx_packet(struct device *dev, int ifidx,
|
||||
struct sk_buff *pkt)
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
|
||||
#include <linux/types.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/sched.h>
|
||||
#include <defs.h>
|
||||
|
||||
#include <brcmu_utils.h>
|
||||
#include <brcmu_wifi.h>
|
||||
|
@ -277,76 +275,6 @@ done:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
brcmf_proto_dcmd(struct brcmf_pub *drvr, int ifidx, struct brcmf_dcmd *dcmd,
|
||||
int len)
|
||||
{
|
||||
struct brcmf_proto *prot = drvr->prot;
|
||||
int ret = -1;
|
||||
|
||||
if (drvr->bus_if->state == BRCMF_BUS_DOWN) {
|
||||
brcmf_dbg(ERROR, "bus is down. we have nothing to do.\n");
|
||||
return ret;
|
||||
}
|
||||
mutex_lock(&drvr->proto_block);
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
if (len > BRCMF_DCMD_MAXLEN)
|
||||
goto done;
|
||||
|
||||
if (prot->pending == true) {
|
||||
brcmf_dbg(TRACE, "CDC packet is pending!!!! cmd=0x%x (%lu) lastcmd=0x%x (%lu)\n",
|
||||
dcmd->cmd, (unsigned long)dcmd->cmd, prot->lastcmd,
|
||||
(unsigned long)prot->lastcmd);
|
||||
if (dcmd->cmd == BRCMF_C_SET_VAR ||
|
||||
dcmd->cmd == BRCMF_C_GET_VAR)
|
||||
brcmf_dbg(TRACE, "iovar cmd=%s\n", (char *)dcmd->buf);
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
||||
prot->pending = true;
|
||||
prot->lastcmd = dcmd->cmd;
|
||||
if (dcmd->set)
|
||||
ret = brcmf_proto_cdc_set_dcmd(drvr, ifidx, dcmd->cmd,
|
||||
dcmd->buf, len);
|
||||
else {
|
||||
ret = brcmf_proto_cdc_query_dcmd(drvr, ifidx, dcmd->cmd,
|
||||
dcmd->buf, len);
|
||||
if (ret > 0)
|
||||
dcmd->used = ret -
|
||||
sizeof(struct brcmf_proto_cdc_dcmd);
|
||||
}
|
||||
|
||||
if (ret >= 0)
|
||||
ret = 0;
|
||||
else {
|
||||
struct brcmf_proto_cdc_dcmd *msg = &prot->msg;
|
||||
/* len == needed when set/query fails from dongle */
|
||||
dcmd->needed = le32_to_cpu(msg->len);
|
||||
}
|
||||
|
||||
/* Intercept the wme_dp dongle cmd here */
|
||||
if (!ret && dcmd->cmd == BRCMF_C_SET_VAR &&
|
||||
!strcmp(dcmd->buf, "wme_dp")) {
|
||||
int slen;
|
||||
__le32 val = 0;
|
||||
|
||||
slen = strlen("wme_dp") + 1;
|
||||
if (len >= (int)(slen + sizeof(int)))
|
||||
memcpy(&val, (char *)dcmd->buf + slen, sizeof(int));
|
||||
drvr->wme_dp = (u8) le32_to_cpu(val);
|
||||
}
|
||||
|
||||
prot->pending = false;
|
||||
|
||||
done:
|
||||
mutex_unlock(&drvr->proto_block);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool pkt_sum_needed(struct sk_buff *skb)
|
||||
{
|
||||
return skb->ip_summed == CHECKSUM_PARTIAL;
|
||||
|
|
|
@ -18,10 +18,7 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <defs.h>
|
||||
#include <brcmu_wifi.h>
|
||||
#include <brcmu_utils.h>
|
||||
#include "dhd.h"
|
||||
|
@ -30,9 +27,6 @@
|
|||
#include "dhd_dbg.h"
|
||||
#include "fwil.h"
|
||||
|
||||
#define BRCM_OUI "\x00\x10\x18"
|
||||
#define DOT11_OUI_LEN 3
|
||||
#define BCMILCP_BCM_SUBTYPE_EVENT 1
|
||||
#define PKTFILTER_BUF_SIZE 128
|
||||
#define BRCMF_ARPOL_MODE 0xb /* agent|snoop|peer_autoreply */
|
||||
#define BRCMF_DEFAULT_BCN_TIMEOUT 3
|
||||
|
@ -40,12 +34,6 @@
|
|||
#define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40
|
||||
#define BRCMF_DEFAULT_PACKET_FILTER "100 0 0 0 0x01 0x00"
|
||||
|
||||
#define MSGTRACE_VERSION 1
|
||||
|
||||
#define BRCMF_PKT_FILTER_FIXED_LEN offsetof(struct brcmf_pkt_filter_le, u)
|
||||
#define BRCMF_PKT_FILTER_PATTERN_FIXED_LEN \
|
||||
offsetof(struct brcmf_pkt_filter_pattern_le, mask_and_pattern)
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char brcmf_version[] =
|
||||
"Dongle Host Driver, version " BRCMF_VERSION_STR "\nCompiled on "
|
||||
|
@ -55,43 +43,6 @@ static const char brcmf_version[] =
|
|||
"Dongle Host Driver, version " BRCMF_VERSION_STR;
|
||||
#endif
|
||||
|
||||
/* Message trace header */
|
||||
struct msgtrace_hdr {
|
||||
u8 version;
|
||||
u8 spare;
|
||||
__be16 len; /* Len of the trace */
|
||||
__be32 seqnum; /* Sequence number of message. Useful
|
||||
* if the messsage has been lost
|
||||
* because of DMA error or a bus reset
|
||||
* (ex: SDIO Func2)
|
||||
*/
|
||||
__be32 discarded_bytes; /* Number of discarded bytes because of
|
||||
trace overflow */
|
||||
__be32 discarded_printf; /* Number of discarded printf
|
||||
because of trace overflow */
|
||||
} __packed;
|
||||
|
||||
|
||||
uint
|
||||
brcmf_c_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen)
|
||||
{
|
||||
uint len;
|
||||
|
||||
len = strlen(name) + 1;
|
||||
|
||||
if ((len + datalen) > buflen)
|
||||
return 0;
|
||||
|
||||
strncpy(buf, name, buflen);
|
||||
|
||||
/* append data onto the end of the name string */
|
||||
if (data && datalen) {
|
||||
memcpy(&buf[len], data, datalen);
|
||||
len += datalen;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
bool brcmf_c_prec_enq(struct device *dev, struct pktq *q,
|
||||
struct sk_buff *pkt, int prec)
|
||||
|
@ -143,405 +94,6 @@ bool brcmf_c_prec_enq(struct device *dev, struct pktq *q,
|
|||
return p != NULL;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static void
|
||||
brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data)
|
||||
{
|
||||
uint i, status, reason;
|
||||
bool group = false, flush_txq = false, link = false;
|
||||
char *auth_str, *event_name;
|
||||
unsigned char *buf;
|
||||
char err_msg[256], eabuf[ETHER_ADDR_STR_LEN];
|
||||
static struct {
|
||||
uint event;
|
||||
char *event_name;
|
||||
} event_names[] = {
|
||||
{
|
||||
BRCMF_E_SET_SSID, "SET_SSID"}, {
|
||||
BRCMF_E_JOIN, "JOIN"}, {
|
||||
BRCMF_E_START, "START"}, {
|
||||
BRCMF_E_AUTH, "AUTH"}, {
|
||||
BRCMF_E_AUTH_IND, "AUTH_IND"}, {
|
||||
BRCMF_E_DEAUTH, "DEAUTH"}, {
|
||||
BRCMF_E_DEAUTH_IND, "DEAUTH_IND"}, {
|
||||
BRCMF_E_ASSOC, "ASSOC"}, {
|
||||
BRCMF_E_ASSOC_IND, "ASSOC_IND"}, {
|
||||
BRCMF_E_REASSOC, "REASSOC"}, {
|
||||
BRCMF_E_REASSOC_IND, "REASSOC_IND"}, {
|
||||
BRCMF_E_DISASSOC, "DISASSOC"}, {
|
||||
BRCMF_E_DISASSOC_IND, "DISASSOC_IND"}, {
|
||||
BRCMF_E_QUIET_START, "START_QUIET"}, {
|
||||
BRCMF_E_QUIET_END, "END_QUIET"}, {
|
||||
BRCMF_E_BEACON_RX, "BEACON_RX"}, {
|
||||
BRCMF_E_LINK, "LINK"}, {
|
||||
BRCMF_E_MIC_ERROR, "MIC_ERROR"}, {
|
||||
BRCMF_E_NDIS_LINK, "NDIS_LINK"}, {
|
||||
BRCMF_E_ROAM, "ROAM"}, {
|
||||
BRCMF_E_TXFAIL, "TXFAIL"}, {
|
||||
BRCMF_E_PMKID_CACHE, "PMKID_CACHE"}, {
|
||||
BRCMF_E_RETROGRADE_TSF, "RETROGRADE_TSF"}, {
|
||||
BRCMF_E_PRUNE, "PRUNE"}, {
|
||||
BRCMF_E_AUTOAUTH, "AUTOAUTH"}, {
|
||||
BRCMF_E_EAPOL_MSG, "EAPOL_MSG"}, {
|
||||
BRCMF_E_SCAN_COMPLETE, "SCAN_COMPLETE"}, {
|
||||
BRCMF_E_ADDTS_IND, "ADDTS_IND"}, {
|
||||
BRCMF_E_DELTS_IND, "DELTS_IND"}, {
|
||||
BRCMF_E_BCNSENT_IND, "BCNSENT_IND"}, {
|
||||
BRCMF_E_BCNRX_MSG, "BCNRX_MSG"}, {
|
||||
BRCMF_E_BCNLOST_MSG, "BCNLOST_MSG"}, {
|
||||
BRCMF_E_ROAM_PREP, "ROAM_PREP"}, {
|
||||
BRCMF_E_PFN_NET_FOUND, "PNO_NET_FOUND"}, {
|
||||
BRCMF_E_PFN_NET_LOST, "PNO_NET_LOST"}, {
|
||||
BRCMF_E_RESET_COMPLETE, "RESET_COMPLETE"}, {
|
||||
BRCMF_E_JOIN_START, "JOIN_START"}, {
|
||||
BRCMF_E_ROAM_START, "ROAM_START"}, {
|
||||
BRCMF_E_ASSOC_START, "ASSOC_START"}, {
|
||||
BRCMF_E_IBSS_ASSOC, "IBSS_ASSOC"}, {
|
||||
BRCMF_E_RADIO, "RADIO"}, {
|
||||
BRCMF_E_PSM_WATCHDOG, "PSM_WATCHDOG"}, {
|
||||
BRCMF_E_PROBREQ_MSG, "PROBREQ_MSG"}, {
|
||||
BRCMF_E_SCAN_CONFIRM_IND, "SCAN_CONFIRM_IND"}, {
|
||||
BRCMF_E_PSK_SUP, "PSK_SUP"}, {
|
||||
BRCMF_E_COUNTRY_CODE_CHANGED, "COUNTRY_CODE_CHANGED"}, {
|
||||
BRCMF_E_EXCEEDED_MEDIUM_TIME, "EXCEEDED_MEDIUM_TIME"}, {
|
||||
BRCMF_E_ICV_ERROR, "ICV_ERROR"}, {
|
||||
BRCMF_E_UNICAST_DECODE_ERROR, "UNICAST_DECODE_ERROR"}, {
|
||||
BRCMF_E_MULTICAST_DECODE_ERROR, "MULTICAST_DECODE_ERROR"}, {
|
||||
BRCMF_E_TRACE, "TRACE"}, {
|
||||
BRCMF_E_ACTION_FRAME, "ACTION FRAME"}, {
|
||||
BRCMF_E_ACTION_FRAME_COMPLETE, "ACTION FRAME TX COMPLETE"}, {
|
||||
BRCMF_E_IF, "IF"}, {
|
||||
BRCMF_E_RSSI, "RSSI"}, {
|
||||
BRCMF_E_PFN_SCAN_COMPLETE, "SCAN_COMPLETE"}, {
|
||||
BRCMF_E_ESCAN_RESULT, "ESCAN_RESULT"}
|
||||
};
|
||||
uint event_type, flags, auth_type, datalen;
|
||||
static u32 seqnum_prev;
|
||||
struct msgtrace_hdr hdr;
|
||||
u32 nblost;
|
||||
char *s, *p;
|
||||
|
||||
event_type = be32_to_cpu(event->event_type);
|
||||
flags = be16_to_cpu(event->flags);
|
||||
status = be32_to_cpu(event->status);
|
||||
reason = be32_to_cpu(event->reason);
|
||||
auth_type = be32_to_cpu(event->auth_type);
|
||||
datalen = be32_to_cpu(event->datalen);
|
||||
/* debug dump of event messages */
|
||||
sprintf(eabuf, "%pM", event->addr);
|
||||
|
||||
event_name = "UNKNOWN";
|
||||
for (i = 0; i < ARRAY_SIZE(event_names); i++) {
|
||||
if (event_names[i].event == event_type)
|
||||
event_name = event_names[i].event_name;
|
||||
}
|
||||
|
||||
brcmf_dbg(EVENT, "EVENT: %s, event ID = %d\n", event_name, event_type);
|
||||
brcmf_dbg(EVENT, "flags 0x%04x, status %d, reason %d, auth_type %d MAC %s\n",
|
||||
flags, status, reason, auth_type, eabuf);
|
||||
|
||||
if (flags & BRCMF_EVENT_MSG_LINK)
|
||||
link = true;
|
||||
if (flags & BRCMF_EVENT_MSG_GROUP)
|
||||
group = true;
|
||||
if (flags & BRCMF_EVENT_MSG_FLUSHTXQ)
|
||||
flush_txq = true;
|
||||
|
||||
switch (event_type) {
|
||||
case BRCMF_E_START:
|
||||
case BRCMF_E_DEAUTH:
|
||||
case BRCMF_E_DISASSOC:
|
||||
brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n", event_name, eabuf);
|
||||
break;
|
||||
|
||||
case BRCMF_E_ASSOC_IND:
|
||||
case BRCMF_E_REASSOC_IND:
|
||||
brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n", event_name, eabuf);
|
||||
break;
|
||||
|
||||
case BRCMF_E_ASSOC:
|
||||
case BRCMF_E_REASSOC:
|
||||
if (status == BRCMF_E_STATUS_SUCCESS)
|
||||
brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, SUCCESS\n",
|
||||
event_name, eabuf);
|
||||
else if (status == BRCMF_E_STATUS_TIMEOUT)
|
||||
brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, TIMEOUT\n",
|
||||
event_name, eabuf);
|
||||
else if (status == BRCMF_E_STATUS_FAIL)
|
||||
brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, FAILURE, reason %d\n",
|
||||
event_name, eabuf, (int)reason);
|
||||
else
|
||||
brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, unexpected status %d\n",
|
||||
event_name, eabuf, (int)status);
|
||||
break;
|
||||
|
||||
case BRCMF_E_DEAUTH_IND:
|
||||
case BRCMF_E_DISASSOC_IND:
|
||||
brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, reason %d\n",
|
||||
event_name, eabuf, (int)reason);
|
||||
break;
|
||||
|
||||
case BRCMF_E_AUTH:
|
||||
case BRCMF_E_AUTH_IND:
|
||||
if (auth_type == WLAN_AUTH_OPEN)
|
||||
auth_str = "Open System";
|
||||
else if (auth_type == WLAN_AUTH_SHARED_KEY)
|
||||
auth_str = "Shared Key";
|
||||
else {
|
||||
sprintf(err_msg, "AUTH unknown: %d", (int)auth_type);
|
||||
auth_str = err_msg;
|
||||
}
|
||||
if (event_type == BRCMF_E_AUTH_IND)
|
||||
brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s\n",
|
||||
event_name, eabuf, auth_str);
|
||||
else if (status == BRCMF_E_STATUS_SUCCESS)
|
||||
brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s, SUCCESS\n",
|
||||
event_name, eabuf, auth_str);
|
||||
else if (status == BRCMF_E_STATUS_TIMEOUT)
|
||||
brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s, TIMEOUT\n",
|
||||
event_name, eabuf, auth_str);
|
||||
else if (status == BRCMF_E_STATUS_FAIL) {
|
||||
brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s, FAILURE, reason %d\n",
|
||||
event_name, eabuf, auth_str, (int)reason);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case BRCMF_E_JOIN:
|
||||
case BRCMF_E_ROAM:
|
||||
case BRCMF_E_SET_SSID:
|
||||
if (status == BRCMF_E_STATUS_SUCCESS)
|
||||
brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n",
|
||||
event_name, eabuf);
|
||||
else if (status == BRCMF_E_STATUS_FAIL)
|
||||
brcmf_dbg(EVENT, "MACEVENT: %s, failed\n", event_name);
|
||||
else if (status == BRCMF_E_STATUS_NO_NETWORKS)
|
||||
brcmf_dbg(EVENT, "MACEVENT: %s, no networks found\n",
|
||||
event_name);
|
||||
else
|
||||
brcmf_dbg(EVENT, "MACEVENT: %s, unexpected status %d\n",
|
||||
event_name, (int)status);
|
||||
break;
|
||||
|
||||
case BRCMF_E_BEACON_RX:
|
||||
if (status == BRCMF_E_STATUS_SUCCESS)
|
||||
brcmf_dbg(EVENT, "MACEVENT: %s, SUCCESS\n", event_name);
|
||||
else if (status == BRCMF_E_STATUS_FAIL)
|
||||
brcmf_dbg(EVENT, "MACEVENT: %s, FAIL\n", event_name);
|
||||
else
|
||||
brcmf_dbg(EVENT, "MACEVENT: %s, status %d\n",
|
||||
event_name, status);
|
||||
break;
|
||||
|
||||
case BRCMF_E_LINK:
|
||||
brcmf_dbg(EVENT, "MACEVENT: %s %s\n",
|
||||
event_name, link ? "UP" : "DOWN");
|
||||
break;
|
||||
|
||||
case BRCMF_E_MIC_ERROR:
|
||||
brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, Group %d, Flush %d\n",
|
||||
event_name, eabuf, group, flush_txq);
|
||||
break;
|
||||
|
||||
case BRCMF_E_ICV_ERROR:
|
||||
case BRCMF_E_UNICAST_DECODE_ERROR:
|
||||
case BRCMF_E_MULTICAST_DECODE_ERROR:
|
||||
brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n", event_name, eabuf);
|
||||
break;
|
||||
|
||||
case BRCMF_E_TXFAIL:
|
||||
brcmf_dbg(EVENT, "MACEVENT: %s, RA %s\n", event_name, eabuf);
|
||||
break;
|
||||
|
||||
case BRCMF_E_SCAN_COMPLETE:
|
||||
case BRCMF_E_PMKID_CACHE:
|
||||
brcmf_dbg(EVENT, "MACEVENT: %s\n", event_name);
|
||||
break;
|
||||
|
||||
case BRCMF_E_ESCAN_RESULT:
|
||||
brcmf_dbg(EVENT, "MACEVENT: %s\n", event_name);
|
||||
datalen = 0;
|
||||
break;
|
||||
|
||||
case BRCMF_E_PFN_NET_FOUND:
|
||||
case BRCMF_E_PFN_NET_LOST:
|
||||
case BRCMF_E_PFN_SCAN_COMPLETE:
|
||||
brcmf_dbg(EVENT, "PNOEVENT: %s\n", event_name);
|
||||
break;
|
||||
|
||||
case BRCMF_E_PSK_SUP:
|
||||
case BRCMF_E_PRUNE:
|
||||
brcmf_dbg(EVENT, "MACEVENT: %s, status %d, reason %d\n",
|
||||
event_name, (int)status, (int)reason);
|
||||
break;
|
||||
|
||||
case BRCMF_E_TRACE:
|
||||
buf = (unsigned char *) event_data;
|
||||
memcpy(&hdr, buf, sizeof(struct msgtrace_hdr));
|
||||
|
||||
if (hdr.version != MSGTRACE_VERSION) {
|
||||
brcmf_dbg(ERROR,
|
||||
"MACEVENT: %s [unsupported version --> brcmf"
|
||||
" version:%d dongle version:%d]\n",
|
||||
event_name, MSGTRACE_VERSION, hdr.version);
|
||||
/* Reset datalen to avoid display below */
|
||||
datalen = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* There are 2 bytes available at the end of data */
|
||||
*(buf + sizeof(struct msgtrace_hdr)
|
||||
+ be16_to_cpu(hdr.len)) = '\0';
|
||||
|
||||
if (be32_to_cpu(hdr.discarded_bytes)
|
||||
|| be32_to_cpu(hdr.discarded_printf))
|
||||
brcmf_dbg(ERROR,
|
||||
"WLC_E_TRACE: [Discarded traces in dongle -->"
|
||||
" discarded_bytes %d discarded_printf %d]\n",
|
||||
be32_to_cpu(hdr.discarded_bytes),
|
||||
be32_to_cpu(hdr.discarded_printf));
|
||||
|
||||
nblost = be32_to_cpu(hdr.seqnum) - seqnum_prev - 1;
|
||||
if (nblost > 0)
|
||||
brcmf_dbg(ERROR, "WLC_E_TRACE: [Event lost --> seqnum "
|
||||
" %d nblost %d\n", be32_to_cpu(hdr.seqnum),
|
||||
nblost);
|
||||
seqnum_prev = be32_to_cpu(hdr.seqnum);
|
||||
|
||||
/* Display the trace buffer. Advance from \n to \n to
|
||||
* avoid display big
|
||||
* printf (issue with Linux printk )
|
||||
*/
|
||||
p = (char *)&buf[sizeof(struct msgtrace_hdr)];
|
||||
while ((s = strstr(p, "\n")) != NULL) {
|
||||
*s = '\0';
|
||||
pr_debug("%s\n", p);
|
||||
p = s + 1;
|
||||
}
|
||||
pr_debug("%s\n", p);
|
||||
|
||||
/* Reset datalen to avoid display below */
|
||||
datalen = 0;
|
||||
break;
|
||||
|
||||
case BRCMF_E_RSSI:
|
||||
brcmf_dbg(EVENT, "MACEVENT: %s %d\n",
|
||||
event_name, be32_to_cpu(*((__be32 *)event_data)));
|
||||
break;
|
||||
|
||||
default:
|
||||
brcmf_dbg(EVENT,
|
||||
"MACEVENT: %s %d, MAC %s, status %d, reason %d, "
|
||||
"auth %d\n", event_name, event_type, eabuf,
|
||||
(int)status, (int)reason, (int)auth_type);
|
||||
break;
|
||||
}
|
||||
|
||||
/* show any appended data */
|
||||
brcmf_dbg_hex_dump(datalen, event_data, datalen, "Received data");
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
int
|
||||
brcmf_c_host_event(struct brcmf_pub *drvr, int *ifidx, void *pktdata,
|
||||
struct brcmf_event_msg *event, void **data_ptr)
|
||||
{
|
||||
/* check whether packet is a BRCM event pkt */
|
||||
struct brcmf_event *pvt_data = (struct brcmf_event *) pktdata;
|
||||
struct brcmf_if_event *ifevent;
|
||||
struct brcmf_if *ifp;
|
||||
char *event_data;
|
||||
u32 type, status;
|
||||
u16 flags;
|
||||
int evlen;
|
||||
|
||||
if (memcmp(BRCM_OUI, &pvt_data->hdr.oui[0], DOT11_OUI_LEN)) {
|
||||
brcmf_dbg(ERROR, "mismatched OUI, bailing\n");
|
||||
return -EBADE;
|
||||
}
|
||||
|
||||
/* BRCM event pkt may be unaligned - use xxx_ua to load user_subtype. */
|
||||
if (get_unaligned_be16(&pvt_data->hdr.usr_subtype) !=
|
||||
BCMILCP_BCM_SUBTYPE_EVENT) {
|
||||
brcmf_dbg(ERROR, "mismatched subtype, bailing\n");
|
||||
return -EBADE;
|
||||
}
|
||||
|
||||
*data_ptr = &pvt_data[1];
|
||||
event_data = *data_ptr;
|
||||
|
||||
/* memcpy since BRCM event pkt may be unaligned. */
|
||||
memcpy(event, &pvt_data->msg, sizeof(struct brcmf_event_msg));
|
||||
|
||||
type = get_unaligned_be32(&event->event_type);
|
||||
flags = get_unaligned_be16(&event->flags);
|
||||
status = get_unaligned_be32(&event->status);
|
||||
evlen = get_unaligned_be32(&event->datalen) +
|
||||
sizeof(struct brcmf_event);
|
||||
|
||||
switch (type) {
|
||||
case BRCMF_E_IF:
|
||||
ifevent = (struct brcmf_if_event *) event_data;
|
||||
brcmf_dbg(TRACE, "if event\n");
|
||||
|
||||
if (ifevent->ifidx > 0 && ifevent->ifidx < BRCMF_MAX_IFS) {
|
||||
if (ifevent->action == BRCMF_E_IF_ADD) {
|
||||
ifp = brcmf_add_if(drvr->dev, ifevent->ifidx,
|
||||
ifevent->bssidx,
|
||||
event->ifname,
|
||||
pvt_data->eth.h_dest);
|
||||
if (IS_ERR(ifp))
|
||||
return PTR_ERR(ifp);
|
||||
brcmf_net_attach(ifp);
|
||||
} else {
|
||||
brcmf_del_if(drvr, ifevent->ifidx);
|
||||
}
|
||||
} else {
|
||||
brcmf_dbg(ERROR, "Invalid ifidx %d for %s\n",
|
||||
ifevent->ifidx, event->ifname);
|
||||
}
|
||||
|
||||
/* send up the if event: btamp user needs it */
|
||||
*ifidx = brcmf_ifname2idx(drvr, event->ifname);
|
||||
break;
|
||||
|
||||
/* These are what external supplicant/authenticator wants */
|
||||
case BRCMF_E_LINK:
|
||||
case BRCMF_E_ASSOC_IND:
|
||||
case BRCMF_E_REASSOC_IND:
|
||||
case BRCMF_E_DISASSOC_IND:
|
||||
case BRCMF_E_MIC_ERROR:
|
||||
default:
|
||||
/* Fall through: this should get _everything_ */
|
||||
|
||||
*ifidx = brcmf_ifname2idx(drvr, event->ifname);
|
||||
brcmf_dbg(TRACE, "MAC event %d, flags %x, status %x\n",
|
||||
type, flags, status);
|
||||
|
||||
/* put it back to BRCMF_E_NDIS_LINK */
|
||||
if (type == BRCMF_E_NDIS_LINK) {
|
||||
u32 temp1;
|
||||
__be32 temp2;
|
||||
|
||||
temp1 = get_unaligned_be32(&event->event_type);
|
||||
brcmf_dbg(TRACE, "Converted to WLC_E_LINK type %d\n",
|
||||
temp1);
|
||||
|
||||
temp2 = cpu_to_be32(BRCMF_E_NDIS_LINK);
|
||||
memcpy((void *)(&pvt_data->msg.event_type), &temp2,
|
||||
sizeof(pvt_data->msg.event_type));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (BRCMF_EVENT_ON())
|
||||
brcmf_c_show_host_event(event, event_data);
|
||||
#endif /* DEBUG */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Convert user's input in hex pattern to byte-size mask */
|
||||
static int brcmf_c_pattern_atoh(char *src, char *dst)
|
||||
{
|
||||
|
@ -686,8 +238,8 @@ static void brcmf_c_pktfilter_offload_set(struct brcmf_if *ifp, char *arg)
|
|||
}
|
||||
|
||||
pkt_filter->u.pattern.size_bytes = cpu_to_le32(mask_size);
|
||||
buf_len = sizeof(*pkt_filter);
|
||||
buf_len -= sizeof(pkt_filter->u.pattern.mask_and_pattern);
|
||||
buf_len = offsetof(struct brcmf_pkt_filter_le,
|
||||
u.pattern.mask_and_pattern);
|
||||
buf_len += mask_size + pattern_size;
|
||||
|
||||
err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_add", pkt_filter,
|
||||
|
|
|
@ -14,18 +14,12 @@
|
|||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/ieee80211.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#include <defs.h>
|
||||
#include <brcmu_wifi.h>
|
||||
#include <brcmu_utils.h>
|
||||
#include "dhd.h"
|
||||
#include "dhd_bus.h"
|
||||
#include "dhd_dbg.h"
|
||||
|
||||
static struct dentry *root_folder;
|
||||
|
|
|
@ -27,11 +27,11 @@
|
|||
#define BRCMF_HDRS_VAL 0x0040
|
||||
#define BRCMF_BYTES_VAL 0x0080
|
||||
#define BRCMF_INTR_VAL 0x0100
|
||||
#define BRCMF_GLOM_VAL 0x0400
|
||||
#define BRCMF_EVENT_VAL 0x0800
|
||||
#define BRCMF_BTA_VAL 0x1000
|
||||
#define BRCMF_ISCAN_VAL 0x2000
|
||||
#define BRCMF_FIL_VAL 0x4000
|
||||
#define BRCMF_GLOM_VAL 0x0200
|
||||
#define BRCMF_EVENT_VAL 0x0400
|
||||
#define BRCMF_BTA_VAL 0x0800
|
||||
#define BRCMF_FIL_VAL 0x1000
|
||||
#define BRCMF_USB_VAL 0x2000
|
||||
|
||||
#if defined(DEBUG)
|
||||
|
||||
|
|
|
@ -16,27 +16,11 @@
|
|||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/module.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <net/rtnetlink.h>
|
||||
#include <defs.h>
|
||||
#include <brcmu_utils.h>
|
||||
#include <brcmu_wifi.h>
|
||||
|
||||
|
@ -45,35 +29,19 @@
|
|||
#include "dhd_proto.h"
|
||||
#include "dhd_dbg.h"
|
||||
#include "wl_cfg80211.h"
|
||||
#include "fwil.h"
|
||||
|
||||
MODULE_AUTHOR("Broadcom Corporation");
|
||||
MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN fullmac driver.");
|
||||
MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac cards");
|
||||
MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
|
||||
MODULE_SUPPORTED_DEVICE("Broadcom 802.11 WLAN fullmac cards");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
||||
#define MAX_WAIT_FOR_8021X_TX 50 /* msecs */
|
||||
|
||||
/* Error bits */
|
||||
int brcmf_msg_level = BRCMF_ERROR_VAL;
|
||||
module_param(brcmf_msg_level, int, 0);
|
||||
|
||||
int brcmf_ifname2idx(struct brcmf_pub *drvr, char *name)
|
||||
{
|
||||
int i = BRCMF_MAX_IFS;
|
||||
struct brcmf_if *ifp;
|
||||
|
||||
if (name == NULL || *name == '\0')
|
||||
return 0;
|
||||
|
||||
while (--i > 0) {
|
||||
ifp = drvr->iflist[i];
|
||||
if (ifp && !strncmp(ifp->ndev->name, name, IFNAMSIZ))
|
||||
break;
|
||||
}
|
||||
|
||||
brcmf_dbg(TRACE, "return idx %d for \"%s\"\n", i, name);
|
||||
|
||||
return i; /* default - the primary interface */
|
||||
}
|
||||
|
||||
char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx)
|
||||
{
|
||||
|
@ -95,38 +63,33 @@ char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx)
|
|||
|
||||
static void _brcmf_set_multicast_list(struct work_struct *work)
|
||||
{
|
||||
struct brcmf_if *ifp;
|
||||
struct net_device *ndev;
|
||||
struct netdev_hw_addr *ha;
|
||||
u32 dcmd_value, cnt;
|
||||
u32 cmd_value, cnt;
|
||||
__le32 cnt_le;
|
||||
__le32 dcmd_le_value;
|
||||
|
||||
struct brcmf_dcmd dcmd;
|
||||
char *buf, *bufp;
|
||||
uint buflen;
|
||||
int ret;
|
||||
u32 buflen;
|
||||
s32 err;
|
||||
|
||||
struct brcmf_pub *drvr = container_of(work, struct brcmf_pub,
|
||||
multicast_work);
|
||||
brcmf_dbg(TRACE, "enter\n");
|
||||
|
||||
ndev = drvr->iflist[0]->ndev;
|
||||
cnt = netdev_mc_count(ndev);
|
||||
ifp = container_of(work, struct brcmf_if, multicast_work);
|
||||
ndev = ifp->ndev;
|
||||
|
||||
/* Determine initial value of allmulti flag */
|
||||
dcmd_value = (ndev->flags & IFF_ALLMULTI) ? true : false;
|
||||
cmd_value = (ndev->flags & IFF_ALLMULTI) ? true : false;
|
||||
|
||||
/* Send down the multicast list first. */
|
||||
|
||||
buflen = sizeof("mcast_list") + sizeof(cnt) + (cnt * ETH_ALEN);
|
||||
bufp = buf = kmalloc(buflen, GFP_ATOMIC);
|
||||
if (!bufp)
|
||||
cnt = netdev_mc_count(ndev);
|
||||
buflen = sizeof(cnt) + (cnt * ETH_ALEN);
|
||||
buf = kmalloc(buflen, GFP_ATOMIC);
|
||||
if (!buf)
|
||||
return;
|
||||
|
||||
strcpy(bufp, "mcast_list");
|
||||
bufp += strlen("mcast_list") + 1;
|
||||
bufp = buf;
|
||||
|
||||
cnt_le = cpu_to_le32(cnt);
|
||||
memcpy(bufp, &cnt_le, sizeof(cnt));
|
||||
memcpy(bufp, &cnt_le, sizeof(cnt_le));
|
||||
bufp += sizeof(cnt_le);
|
||||
|
||||
netdev_for_each_mc_addr(ha, ndev) {
|
||||
|
@ -137,129 +100,66 @@ static void _brcmf_set_multicast_list(struct work_struct *work)
|
|||
cnt--;
|
||||
}
|
||||
|
||||
memset(&dcmd, 0, sizeof(dcmd));
|
||||
dcmd.cmd = BRCMF_C_SET_VAR;
|
||||
dcmd.buf = buf;
|
||||
dcmd.len = buflen;
|
||||
dcmd.set = true;
|
||||
|
||||
ret = brcmf_proto_dcmd(drvr, 0, &dcmd, dcmd.len);
|
||||
if (ret < 0) {
|
||||
brcmf_dbg(ERROR, "%s: set mcast_list failed, cnt %d\n",
|
||||
brcmf_ifname(drvr, 0), cnt);
|
||||
dcmd_value = cnt ? true : dcmd_value;
|
||||
err = brcmf_fil_iovar_data_set(ifp, "mcast_list", buf, buflen);
|
||||
if (err < 0) {
|
||||
brcmf_dbg(ERROR, "Setting mcast_list failed, %d\n", err);
|
||||
cmd_value = cnt ? true : cmd_value;
|
||||
}
|
||||
|
||||
kfree(buf);
|
||||
|
||||
/* Now send the allmulti setting. This is based on the setting in the
|
||||
/*
|
||||
* Now send the allmulti setting. This is based on the setting in the
|
||||
* net_device flags, but might be modified above to be turned on if we
|
||||
* were trying to set some addresses and dongle rejected it...
|
||||
*/
|
||||
err = brcmf_fil_iovar_int_set(ifp, "allmulti", cmd_value);
|
||||
if (err < 0)
|
||||
brcmf_dbg(ERROR, "Setting allmulti failed, %d\n", err);
|
||||
|
||||
buflen = sizeof("allmulti") + sizeof(dcmd_value);
|
||||
buf = kmalloc(buflen, GFP_ATOMIC);
|
||||
if (!buf)
|
||||
return;
|
||||
|
||||
dcmd_le_value = cpu_to_le32(dcmd_value);
|
||||
|
||||
if (!brcmf_c_mkiovar
|
||||
("allmulti", (void *)&dcmd_le_value,
|
||||
sizeof(dcmd_le_value), buf, buflen)) {
|
||||
brcmf_dbg(ERROR, "%s: mkiovar failed for allmulti, datalen %d buflen %u\n",
|
||||
brcmf_ifname(drvr, 0),
|
||||
(int)sizeof(dcmd_value), buflen);
|
||||
kfree(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&dcmd, 0, sizeof(dcmd));
|
||||
dcmd.cmd = BRCMF_C_SET_VAR;
|
||||
dcmd.buf = buf;
|
||||
dcmd.len = buflen;
|
||||
dcmd.set = true;
|
||||
|
||||
ret = brcmf_proto_dcmd(drvr, 0, &dcmd, dcmd.len);
|
||||
if (ret < 0) {
|
||||
brcmf_dbg(ERROR, "%s: set allmulti %d failed\n",
|
||||
brcmf_ifname(drvr, 0),
|
||||
le32_to_cpu(dcmd_le_value));
|
||||
}
|
||||
|
||||
kfree(buf);
|
||||
|
||||
/* Finally, pick up the PROMISC flag as well, like the NIC
|
||||
driver does */
|
||||
|
||||
dcmd_value = (ndev->flags & IFF_PROMISC) ? true : false;
|
||||
dcmd_le_value = cpu_to_le32(dcmd_value);
|
||||
|
||||
memset(&dcmd, 0, sizeof(dcmd));
|
||||
dcmd.cmd = BRCMF_C_SET_PROMISC;
|
||||
dcmd.buf = &dcmd_le_value;
|
||||
dcmd.len = sizeof(dcmd_le_value);
|
||||
dcmd.set = true;
|
||||
|
||||
ret = brcmf_proto_dcmd(drvr, 0, &dcmd, dcmd.len);
|
||||
if (ret < 0) {
|
||||
brcmf_dbg(ERROR, "%s: set promisc %d failed\n",
|
||||
brcmf_ifname(drvr, 0),
|
||||
le32_to_cpu(dcmd_le_value));
|
||||
}
|
||||
/*Finally, pick up the PROMISC flag */
|
||||
cmd_value = (ndev->flags & IFF_PROMISC) ? true : false;
|
||||
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PROMISC, cmd_value);
|
||||
if (err < 0)
|
||||
brcmf_dbg(ERROR, "Setting BRCMF_C_SET_PROMISC failed, %d\n",
|
||||
err);
|
||||
}
|
||||
|
||||
static void
|
||||
_brcmf_set_mac_address(struct work_struct *work)
|
||||
{
|
||||
char buf[32];
|
||||
struct brcmf_dcmd dcmd;
|
||||
int ret;
|
||||
|
||||
struct brcmf_pub *drvr = container_of(work, struct brcmf_pub,
|
||||
setmacaddr_work);
|
||||
struct brcmf_if *ifp;
|
||||
s32 err;
|
||||
|
||||
brcmf_dbg(TRACE, "enter\n");
|
||||
if (!brcmf_c_mkiovar("cur_etheraddr", (char *)drvr->macvalue,
|
||||
ETH_ALEN, buf, 32)) {
|
||||
brcmf_dbg(ERROR, "%s: mkiovar failed for cur_etheraddr\n",
|
||||
brcmf_ifname(drvr, 0));
|
||||
return;
|
||||
|
||||
ifp = container_of(work, struct brcmf_if, setmacaddr_work);
|
||||
err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", ifp->mac_addr,
|
||||
ETH_ALEN);
|
||||
if (err < 0) {
|
||||
brcmf_dbg(ERROR, "Setting cur_etheraddr failed, %d\n", err);
|
||||
} else {
|
||||
brcmf_dbg(TRACE, "MAC address updated to %pM\n",
|
||||
ifp->mac_addr);
|
||||
memcpy(ifp->ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
|
||||
}
|
||||
memset(&dcmd, 0, sizeof(dcmd));
|
||||
dcmd.cmd = BRCMF_C_SET_VAR;
|
||||
dcmd.buf = buf;
|
||||
dcmd.len = 32;
|
||||
dcmd.set = true;
|
||||
|
||||
ret = brcmf_proto_dcmd(drvr, 0, &dcmd, dcmd.len);
|
||||
if (ret < 0)
|
||||
brcmf_dbg(ERROR, "%s: set cur_etheraddr failed\n",
|
||||
brcmf_ifname(drvr, 0));
|
||||
else
|
||||
memcpy(drvr->iflist[0]->ndev->dev_addr,
|
||||
drvr->macvalue, ETH_ALEN);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
struct sockaddr *sa = (struct sockaddr *)addr;
|
||||
|
||||
memcpy(&drvr->macvalue, sa->sa_data, ETH_ALEN);
|
||||
schedule_work(&drvr->setmacaddr_work);
|
||||
memcpy(&ifp->mac_addr, sa->sa_data, ETH_ALEN);
|
||||
schedule_work(&ifp->setmacaddr_work);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void brcmf_netdev_set_multicast_list(struct net_device *ndev)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
|
||||
schedule_work(&drvr->multicast_work);
|
||||
schedule_work(&ifp->multicast_work);
|
||||
}
|
||||
|
||||
static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
|
@ -272,7 +172,7 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
|||
|
||||
/* Reject if down */
|
||||
if (!drvr->bus_if->drvr_up ||
|
||||
(drvr->bus_if->state == BRCMF_BUS_DOWN)) {
|
||||
(drvr->bus_if->state != BRCMF_BUS_DATA)) {
|
||||
brcmf_dbg(ERROR, "xmit rejected drvup=%d state=%d\n",
|
||||
drvr->bus_if->drvr_up,
|
||||
drvr->bus_if->state);
|
||||
|
@ -350,32 +250,13 @@ void brcmf_txflowblock(struct device *dev, bool state)
|
|||
}
|
||||
}
|
||||
|
||||
static int brcmf_host_event(struct brcmf_pub *drvr, int *ifidx,
|
||||
void *pktdata, struct brcmf_event_msg *event,
|
||||
void **data)
|
||||
{
|
||||
int bcmerror = 0;
|
||||
|
||||
bcmerror = brcmf_c_host_event(drvr, ifidx, pktdata, event, data);
|
||||
if (bcmerror != 0)
|
||||
return bcmerror;
|
||||
|
||||
if (drvr->iflist[*ifidx]->ndev)
|
||||
brcmf_cfg80211_event(drvr->iflist[*ifidx]->ndev,
|
||||
event, *data);
|
||||
|
||||
return bcmerror;
|
||||
}
|
||||
|
||||
void brcmf_rx_frame(struct device *dev, int ifidx,
|
||||
void brcmf_rx_frame(struct device *dev, u8 ifidx,
|
||||
struct sk_buff_head *skb_list)
|
||||
{
|
||||
unsigned char *eth;
|
||||
uint len;
|
||||
void *data;
|
||||
struct sk_buff *skb, *pnext;
|
||||
struct brcmf_if *ifp;
|
||||
struct brcmf_event_msg event;
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
|
||||
|
@ -422,10 +303,7 @@ void brcmf_rx_frame(struct device *dev, int ifidx,
|
|||
skb_pull(skb, ETH_HLEN);
|
||||
|
||||
/* Process special event packets and then discard them */
|
||||
if (ntohs(skb->protocol) == ETH_P_LINK_CTL)
|
||||
brcmf_host_event(drvr, &ifidx,
|
||||
skb_mac_header(skb),
|
||||
&event, &data);
|
||||
brcmf_fweh_process_skb(drvr, skb, &ifidx);
|
||||
|
||||
if (drvr->iflist[ifidx]) {
|
||||
ifp = drvr->iflist[ifidx];
|
||||
|
@ -461,9 +339,11 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success)
|
|||
eh = (struct ethhdr *)(txp->data);
|
||||
type = ntohs(eh->h_proto);
|
||||
|
||||
if (type == ETH_P_PAE)
|
||||
if (type == ETH_P_PAE) {
|
||||
atomic_dec(&drvr->pend_8021x_cnt);
|
||||
|
||||
if (waitqueue_active(&drvr->pend_8021x_wait))
|
||||
wake_up(&drvr->pend_8021x_wait);
|
||||
}
|
||||
}
|
||||
|
||||
static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
|
||||
|
@ -487,83 +367,26 @@ static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
|
|||
return &ifp->stats;
|
||||
}
|
||||
|
||||
/* Retrieve current toe component enables, which are kept
|
||||
as a bitmap in toe_ol iovar */
|
||||
static int brcmf_toe_get(struct brcmf_pub *drvr, int ifidx, u32 *toe_ol)
|
||||
/*
|
||||
* Set current toe component enables in toe_ol iovar,
|
||||
* and set toe global enable iovar
|
||||
*/
|
||||
static int brcmf_toe_set(struct brcmf_if *ifp, u32 toe_ol)
|
||||
{
|
||||
struct brcmf_dcmd dcmd;
|
||||
__le32 toe_le;
|
||||
char buf[32];
|
||||
int ret;
|
||||
s32 err;
|
||||
|
||||
memset(&dcmd, 0, sizeof(dcmd));
|
||||
|
||||
dcmd.cmd = BRCMF_C_GET_VAR;
|
||||
dcmd.buf = buf;
|
||||
dcmd.len = (uint) sizeof(buf);
|
||||
dcmd.set = false;
|
||||
|
||||
strcpy(buf, "toe_ol");
|
||||
ret = brcmf_proto_dcmd(drvr, ifidx, &dcmd, dcmd.len);
|
||||
if (ret < 0) {
|
||||
/* Check for older dongle image that doesn't support toe_ol */
|
||||
if (ret == -EIO) {
|
||||
brcmf_dbg(ERROR, "%s: toe not supported by device\n",
|
||||
brcmf_ifname(drvr, ifidx));
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
brcmf_dbg(INFO, "%s: could not get toe_ol: ret=%d\n",
|
||||
brcmf_ifname(drvr, ifidx), ret);
|
||||
return ret;
|
||||
err = brcmf_fil_iovar_int_set(ifp, "toe_ol", toe_ol);
|
||||
if (err < 0) {
|
||||
brcmf_dbg(ERROR, "Setting toe_ol failed, %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
memcpy(&toe_le, buf, sizeof(u32));
|
||||
*toe_ol = le32_to_cpu(toe_le);
|
||||
return 0;
|
||||
}
|
||||
err = brcmf_fil_iovar_int_set(ifp, "toe", (toe_ol != 0));
|
||||
if (err < 0)
|
||||
brcmf_dbg(ERROR, "Setting toe failed, %d\n", err);
|
||||
|
||||
/* Set current toe component enables in toe_ol iovar,
|
||||
and set toe global enable iovar */
|
||||
static int brcmf_toe_set(struct brcmf_pub *drvr, int ifidx, u32 toe_ol)
|
||||
{
|
||||
struct brcmf_dcmd dcmd;
|
||||
char buf[32];
|
||||
int ret;
|
||||
__le32 toe_le = cpu_to_le32(toe_ol);
|
||||
return err;
|
||||
|
||||
memset(&dcmd, 0, sizeof(dcmd));
|
||||
|
||||
dcmd.cmd = BRCMF_C_SET_VAR;
|
||||
dcmd.buf = buf;
|
||||
dcmd.len = (uint) sizeof(buf);
|
||||
dcmd.set = true;
|
||||
|
||||
/* Set toe_ol as requested */
|
||||
strcpy(buf, "toe_ol");
|
||||
memcpy(&buf[sizeof("toe_ol")], &toe_le, sizeof(u32));
|
||||
|
||||
ret = brcmf_proto_dcmd(drvr, ifidx, &dcmd, dcmd.len);
|
||||
if (ret < 0) {
|
||||
brcmf_dbg(ERROR, "%s: could not set toe_ol: ret=%d\n",
|
||||
brcmf_ifname(drvr, ifidx), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Enable toe globally only if any components are enabled. */
|
||||
toe_le = cpu_to_le32(toe_ol != 0);
|
||||
|
||||
strcpy(buf, "toe");
|
||||
memcpy(&buf[sizeof("toe")], &toe_le, sizeof(u32));
|
||||
|
||||
ret = brcmf_proto_dcmd(drvr, ifidx, &dcmd, dcmd.len);
|
||||
if (ret < 0) {
|
||||
brcmf_dbg(ERROR, "%s: could not set toe: ret=%d\n",
|
||||
brcmf_ifname(drvr, ifidx), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
|
||||
|
@ -581,8 +404,9 @@ static const struct ethtool_ops brcmf_ethtool_ops = {
|
|||
.get_drvinfo = brcmf_ethtool_get_drvinfo,
|
||||
};
|
||||
|
||||
static int brcmf_ethtool(struct brcmf_pub *drvr, void __user *uaddr)
|
||||
static int brcmf_ethtool(struct brcmf_if *ifp, void __user *uaddr)
|
||||
{
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
struct ethtool_drvinfo info;
|
||||
char drvname[sizeof(info.driver)];
|
||||
u32 cmd;
|
||||
|
@ -633,7 +457,7 @@ static int brcmf_ethtool(struct brcmf_pub *drvr, void __user *uaddr)
|
|||
/* Get toe offload components from dongle */
|
||||
case ETHTOOL_GRXCSUM:
|
||||
case ETHTOOL_GTXCSUM:
|
||||
ret = brcmf_toe_get(drvr, 0, &toe_cmpnt);
|
||||
ret = brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_cmpnt);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -654,7 +478,7 @@ static int brcmf_ethtool(struct brcmf_pub *drvr, void __user *uaddr)
|
|||
return -EFAULT;
|
||||
|
||||
/* Read the current settings, update and write back */
|
||||
ret = brcmf_toe_get(drvr, 0, &toe_cmpnt);
|
||||
ret = brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_cmpnt);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -666,18 +490,16 @@ static int brcmf_ethtool(struct brcmf_pub *drvr, void __user *uaddr)
|
|||
else
|
||||
toe_cmpnt &= ~csum_dir;
|
||||
|
||||
ret = brcmf_toe_set(drvr, 0, toe_cmpnt);
|
||||
ret = brcmf_toe_set(ifp, toe_cmpnt);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* If setting TX checksum mode, tell Linux the new mode */
|
||||
if (cmd == ETHTOOL_STXCSUM) {
|
||||
if (edata.data)
|
||||
drvr->iflist[0]->ndev->features |=
|
||||
NETIF_F_IP_CSUM;
|
||||
ifp->ndev->features |= NETIF_F_IP_CSUM;
|
||||
else
|
||||
drvr->iflist[0]->ndev->features &=
|
||||
~NETIF_F_IP_CSUM;
|
||||
ifp->ndev->features &= ~NETIF_F_IP_CSUM;
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -701,7 +523,7 @@ static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
|
|||
return -1;
|
||||
|
||||
if (cmd == SIOCETHTOOL)
|
||||
return brcmf_ethtool(drvr, ifr->ifr_data);
|
||||
return brcmf_ethtool(ifp, ifr->ifr_data);
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
@ -712,10 +534,12 @@ static int brcmf_netdev_stop(struct net_device *ndev)
|
|||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
brcmf_cfg80211_down(drvr->config);
|
||||
|
||||
if (drvr->bus_if->drvr_up == 0)
|
||||
return 0;
|
||||
|
||||
brcmf_cfg80211_down(ndev);
|
||||
|
||||
/* Set state and stop OS transmissions */
|
||||
drvr->bus_if->drvr_up = false;
|
||||
netif_stop_queue(ndev);
|
||||
|
@ -730,38 +554,35 @@ static int brcmf_netdev_open(struct net_device *ndev)
|
|||
struct brcmf_bus *bus_if = drvr->bus_if;
|
||||
u32 toe_ol;
|
||||
s32 ret = 0;
|
||||
uint up = 0;
|
||||
|
||||
brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx);
|
||||
|
||||
if (ifp->idx == 0) { /* do it only for primary eth0 */
|
||||
/* If bus is not ready, can't continue */
|
||||
if (bus_if->state != BRCMF_BUS_DATA) {
|
||||
brcmf_dbg(ERROR, "failed bus is not ready\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
atomic_set(&drvr->pend_8021x_cnt, 0);
|
||||
|
||||
memcpy(ndev->dev_addr, drvr->mac, ETH_ALEN);
|
||||
|
||||
/* Get current TOE mode from dongle */
|
||||
if (brcmf_toe_get(drvr, ifp->idx, &toe_ol) >= 0
|
||||
&& (toe_ol & TOE_TX_CSUM_OL) != 0)
|
||||
drvr->iflist[ifp->idx]->ndev->features |=
|
||||
NETIF_F_IP_CSUM;
|
||||
else
|
||||
drvr->iflist[ifp->idx]->ndev->features &=
|
||||
~NETIF_F_IP_CSUM;
|
||||
/* If bus is not ready, can't continue */
|
||||
if (bus_if->state != BRCMF_BUS_DATA) {
|
||||
brcmf_dbg(ERROR, "failed bus is not ready\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
atomic_set(&drvr->pend_8021x_cnt, 0);
|
||||
|
||||
memcpy(ndev->dev_addr, drvr->mac, ETH_ALEN);
|
||||
|
||||
/* Get current TOE mode from dongle */
|
||||
if (brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_ol) >= 0
|
||||
&& (toe_ol & TOE_TX_CSUM_OL) != 0)
|
||||
drvr->iflist[ifp->idx]->ndev->features |=
|
||||
NETIF_F_IP_CSUM;
|
||||
else
|
||||
drvr->iflist[ifp->idx]->ndev->features &=
|
||||
~NETIF_F_IP_CSUM;
|
||||
|
||||
/* make sure RF is ready for work */
|
||||
brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_UP, (char *)&up, sizeof(up));
|
||||
brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0);
|
||||
|
||||
/* Allow transmit calls */
|
||||
netif_start_queue(ndev);
|
||||
drvr->bus_if->drvr_up = true;
|
||||
if (brcmf_cfg80211_up(drvr->config)) {
|
||||
if (brcmf_cfg80211_up(ndev)) {
|
||||
brcmf_dbg(ERROR, "failed to bring up cfg80211\n");
|
||||
return -1;
|
||||
}
|
||||
|
@ -779,39 +600,38 @@ static const struct net_device_ops brcmf_netdev_ops_pri = {
|
|||
.ndo_set_rx_mode = brcmf_netdev_set_multicast_list
|
||||
};
|
||||
|
||||
static const struct net_device_ops brcmf_netdev_ops_virt = {
|
||||
.ndo_open = brcmf_cfg80211_up,
|
||||
.ndo_stop = brcmf_cfg80211_down,
|
||||
.ndo_get_stats = brcmf_netdev_get_stats,
|
||||
.ndo_do_ioctl = brcmf_netdev_ioctl_entry,
|
||||
.ndo_start_xmit = brcmf_netdev_start_xmit,
|
||||
.ndo_set_mac_address = brcmf_netdev_set_mac_address,
|
||||
.ndo_set_rx_mode = brcmf_netdev_set_multicast_list
|
||||
};
|
||||
|
||||
int brcmf_net_attach(struct brcmf_if *ifp)
|
||||
{
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
struct net_device *ndev;
|
||||
u8 temp_addr[ETH_ALEN];
|
||||
|
||||
brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx);
|
||||
brcmf_dbg(TRACE, "ifidx %d mac %pM\n", ifp->idx, ifp->mac_addr);
|
||||
ndev = ifp->ndev;
|
||||
|
||||
ndev = drvr->iflist[ifp->idx]->ndev;
|
||||
ndev->netdev_ops = &brcmf_netdev_ops_pri;
|
||||
|
||||
/*
|
||||
* determine mac address to use
|
||||
*/
|
||||
if (is_valid_ether_addr(ifp->mac_addr))
|
||||
memcpy(temp_addr, ifp->mac_addr, ETH_ALEN);
|
||||
/* set appropriate operations */
|
||||
if (!ifp->idx)
|
||||
ndev->netdev_ops = &brcmf_netdev_ops_pri;
|
||||
else
|
||||
memcpy(temp_addr, drvr->mac, ETH_ALEN);
|
||||
ndev->netdev_ops = &brcmf_netdev_ops_virt;
|
||||
|
||||
if (ifp->idx == 1) {
|
||||
brcmf_dbg(TRACE, "ACCESS POINT MAC:\n");
|
||||
/* ACCESSPOINT INTERFACE CASE */
|
||||
temp_addr[0] |= 0X02; /* set bit 2 ,
|
||||
- Locally Administered address */
|
||||
|
||||
}
|
||||
ndev->hard_header_len = ETH_HLEN + drvr->hdrlen;
|
||||
ndev->ethtool_ops = &brcmf_ethtool_ops;
|
||||
|
||||
drvr->rxsz = ndev->mtu + ndev->hard_header_len +
|
||||
drvr->hdrlen;
|
||||
|
||||
memcpy(ndev->dev_addr, temp_addr, ETH_ALEN);
|
||||
/* set the mac address */
|
||||
memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
|
||||
|
||||
if (register_netdev(ndev) != 0) {
|
||||
brcmf_dbg(ERROR, "couldn't register the net device\n");
|
||||
|
@ -824,17 +644,15 @@ int brcmf_net_attach(struct brcmf_if *ifp)
|
|||
|
||||
fail:
|
||||
ndev->netdev_ops = NULL;
|
||||
free_netdev(ndev);
|
||||
return -EBADE;
|
||||
}
|
||||
|
||||
struct brcmf_if *brcmf_add_if(struct device *dev, int ifidx, s32 bssidx,
|
||||
char *name, u8 *mac_addr)
|
||||
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx, s32 bssidx,
|
||||
char *name, u8 *addr_mask)
|
||||
{
|
||||
struct brcmf_if *ifp;
|
||||
struct net_device *ndev;
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
int i;
|
||||
|
||||
brcmf_dbg(TRACE, "idx %d\n", ifidx);
|
||||
|
||||
|
@ -844,12 +662,17 @@ struct brcmf_if *brcmf_add_if(struct device *dev, int ifidx, s32 bssidx,
|
|||
* in case we missed the BRCMF_E_IF_DEL event.
|
||||
*/
|
||||
if (ifp) {
|
||||
brcmf_dbg(ERROR, "ERROR: netdev:%s already exists, try free & unregister\n",
|
||||
brcmf_dbg(ERROR, "ERROR: netdev:%s already exists\n",
|
||||
ifp->ndev->name);
|
||||
netif_stop_queue(ifp->ndev);
|
||||
unregister_netdev(ifp->ndev);
|
||||
free_netdev(ifp->ndev);
|
||||
drvr->iflist[ifidx] = NULL;
|
||||
if (ifidx) {
|
||||
netif_stop_queue(ifp->ndev);
|
||||
unregister_netdev(ifp->ndev);
|
||||
free_netdev(ifp->ndev);
|
||||
drvr->iflist[ifidx] = NULL;
|
||||
} else {
|
||||
brcmf_dbg(ERROR, "ignore IF event\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate netdev, including space for private structure */
|
||||
|
@ -865,11 +688,16 @@ struct brcmf_if *brcmf_add_if(struct device *dev, int ifidx, s32 bssidx,
|
|||
drvr->iflist[ifidx] = ifp;
|
||||
ifp->idx = ifidx;
|
||||
ifp->bssidx = bssidx;
|
||||
if (mac_addr != NULL)
|
||||
memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN);
|
||||
|
||||
brcmf_dbg(TRACE, " ==== pid:%x, net_device for if:%s created ===\n",
|
||||
current->pid, ifp->ndev->name);
|
||||
INIT_WORK(&ifp->setmacaddr_work, _brcmf_set_mac_address);
|
||||
INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list);
|
||||
|
||||
if (addr_mask != NULL)
|
||||
for (i = 0; i < ETH_ALEN; i++)
|
||||
ifp->mac_addr[i] = drvr->mac[i] ^ addr_mask[i];
|
||||
|
||||
brcmf_dbg(TRACE, " ==== pid:%x, if:%s (%pM) created ===\n",
|
||||
current->pid, ifp->ndev->name, ifp->mac_addr);
|
||||
|
||||
return ifp;
|
||||
}
|
||||
|
@ -896,6 +724,9 @@ void brcmf_del_if(struct brcmf_pub *drvr, int ifidx)
|
|||
netif_stop_queue(ifp->ndev);
|
||||
}
|
||||
|
||||
cancel_work_sync(&ifp->setmacaddr_work);
|
||||
cancel_work_sync(&ifp->multicast_work);
|
||||
|
||||
unregister_netdev(ifp->ndev);
|
||||
drvr->iflist[ifidx] = NULL;
|
||||
if (ifidx == 0)
|
||||
|
@ -934,11 +765,13 @@ int brcmf_attach(uint bus_hdrlen, struct device *dev)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
INIT_WORK(&drvr->setmacaddr_work, _brcmf_set_mac_address);
|
||||
INIT_WORK(&drvr->multicast_work, _brcmf_set_multicast_list);
|
||||
/* attach firmware event handler */
|
||||
brcmf_fweh_attach(drvr);
|
||||
|
||||
INIT_LIST_HEAD(&drvr->bus_if->dcmd_list);
|
||||
|
||||
init_waitqueue_head(&drvr->pend_8021x_wait);
|
||||
|
||||
return ret;
|
||||
|
||||
fail:
|
||||
|
@ -964,7 +797,7 @@ int brcmf_bus_start(struct device *dev)
|
|||
}
|
||||
|
||||
/* add primary networking interface */
|
||||
ifp = brcmf_add_if(dev, 0, 0, "wlan%d", NULL);
|
||||
ifp = brcmf_add_if(drvr, 0, 0, "wlan%d", NULL);
|
||||
if (IS_ERR(ifp))
|
||||
return PTR_ERR(ifp);
|
||||
|
||||
|
@ -974,15 +807,25 @@ int brcmf_bus_start(struct device *dev)
|
|||
/* Bus is ready, do any initialization */
|
||||
ret = brcmf_c_preinit_dcmds(ifp);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto fail;
|
||||
|
||||
drvr->config = brcmf_cfg80211_attach(drvr);
|
||||
if (drvr->config == NULL)
|
||||
return -ENOMEM;
|
||||
if (drvr->config == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = brcmf_fweh_activate_events(ifp);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
ret = brcmf_net_attach(ifp);
|
||||
fail:
|
||||
if (ret < 0) {
|
||||
brcmf_dbg(ERROR, "brcmf_net_attach failed");
|
||||
brcmf_dbg(ERROR, "failed: %d\n", ret);
|
||||
if (drvr->config)
|
||||
brcmf_cfg80211_detach(drvr->config);
|
||||
free_netdev(drvr->iflist[0]->ndev);
|
||||
drvr->iflist[0] = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
@ -1011,6 +854,11 @@ void brcmf_detach(struct device *dev)
|
|||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
if (drvr == NULL)
|
||||
return;
|
||||
|
||||
/* stop firmware event handling */
|
||||
brcmf_fweh_detach(drvr);
|
||||
|
||||
/* make sure primary interface removed last */
|
||||
for (i = BRCMF_MAX_IFS-1; i > -1; i--)
|
||||
|
@ -1020,8 +868,6 @@ void brcmf_detach(struct device *dev)
|
|||
brcmf_bus_detach(drvr);
|
||||
|
||||
if (drvr->prot) {
|
||||
cancel_work_sync(&drvr->setmacaddr_work);
|
||||
cancel_work_sync(&drvr->multicast_work);
|
||||
brcmf_proto_detach(drvr);
|
||||
}
|
||||
|
||||
|
@ -1035,26 +881,19 @@ static int brcmf_get_pend_8021x_cnt(struct brcmf_pub *drvr)
|
|||
return atomic_read(&drvr->pend_8021x_cnt);
|
||||
}
|
||||
|
||||
#define MAX_WAIT_FOR_8021X_TX 10
|
||||
|
||||
int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
int timeout = 10 * HZ / 1000;
|
||||
int ntimes = MAX_WAIT_FOR_8021X_TX;
|
||||
int pend = brcmf_get_pend_8021x_cnt(drvr);
|
||||
int err;
|
||||
|
||||
while (ntimes && pend) {
|
||||
if (pend) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(timeout);
|
||||
set_current_state(TASK_RUNNING);
|
||||
ntimes--;
|
||||
}
|
||||
pend = brcmf_get_pend_8021x_cnt(drvr);
|
||||
}
|
||||
return pend;
|
||||
err = wait_event_timeout(drvr->pend_8021x_wait,
|
||||
!brcmf_get_pend_8021x_cnt(drvr),
|
||||
msecs_to_jiffies(MAX_WAIT_FOR_8021X_TX));
|
||||
|
||||
WARN_ON(!err);
|
||||
|
||||
return !err;
|
||||
}
|
||||
|
||||
static void brcmf_driver_init(struct work_struct *work)
|
||||
|
|
|
@ -36,14 +36,7 @@ extern void brcmf_proto_stop(struct brcmf_pub *drvr);
|
|||
extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx,
|
||||
struct sk_buff *txp);
|
||||
|
||||
/* Use protocol to issue command to dongle */
|
||||
extern int brcmf_proto_dcmd(struct brcmf_pub *drvr, int ifidx,
|
||||
struct brcmf_dcmd *dcmd, int len);
|
||||
|
||||
/* Sets dongle media info (drv_version, mac address). */
|
||||
extern int brcmf_c_preinit_dcmds(struct brcmf_if *ifp);
|
||||
|
||||
extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx,
|
||||
uint cmd, void *buf, uint len);
|
||||
|
||||
#endif /* _BRCMF_PROTO_H_ */
|
||||
|
|
|
@ -533,9 +533,11 @@ struct brcmf_sdio {
|
|||
u8 *rxbuf; /* Buffer for receiving control packets */
|
||||
uint rxblen; /* Allocated length of rxbuf */
|
||||
u8 *rxctl; /* Aligned pointer into rxbuf */
|
||||
u8 *rxctl_orig; /* pointer for freeing rxctl */
|
||||
u8 *databuf; /* Buffer for receiving big glom packet */
|
||||
u8 *dataptr; /* Aligned pointer into databuf */
|
||||
uint rxlen; /* Length of valid data in buffer */
|
||||
spinlock_t rxctl_lock; /* protection lock for ctrl frame resources */
|
||||
|
||||
u8 sdpcm_ver; /* Bus protocol reported by dongle */
|
||||
|
||||
|
@ -582,8 +584,6 @@ struct brcmf_sdio {
|
|||
struct list_head dpc_tsklst;
|
||||
spinlock_t dpc_tl_lock;
|
||||
|
||||
struct semaphore sdsem;
|
||||
|
||||
const struct firmware *firmware;
|
||||
u32 fw_ptr;
|
||||
|
||||
|
@ -1037,9 +1037,9 @@ static void brcmf_sdbrcm_free_glom(struct brcmf_sdio *bus)
|
|||
}
|
||||
}
|
||||
|
||||
static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
|
||||
struct brcmf_sdio_read *rd,
|
||||
enum brcmf_sdio_frmtype type)
|
||||
static int brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
|
||||
struct brcmf_sdio_read *rd,
|
||||
enum brcmf_sdio_frmtype type)
|
||||
{
|
||||
u16 len, checksum;
|
||||
u8 rx_seq, fc, tx_seq_max;
|
||||
|
@ -1054,26 +1054,26 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
|
|||
/* All zero means no more to read */
|
||||
if (!(len | checksum)) {
|
||||
bus->rxpending = false;
|
||||
return false;
|
||||
return -ENODATA;
|
||||
}
|
||||
if ((u16)(~(len ^ checksum))) {
|
||||
brcmf_dbg(ERROR, "HW header checksum error\n");
|
||||
bus->sdcnt.rx_badhdr++;
|
||||
brcmf_sdbrcm_rxfail(bus, false, false);
|
||||
return false;
|
||||
return -EIO;
|
||||
}
|
||||
if (len < SDPCM_HDRLEN) {
|
||||
brcmf_dbg(ERROR, "HW header length error\n");
|
||||
return false;
|
||||
return -EPROTO;
|
||||
}
|
||||
if (type == BRCMF_SDIO_FT_SUPER &&
|
||||
(roundup(len, bus->blocksize) != rd->len)) {
|
||||
brcmf_dbg(ERROR, "HW superframe header length error\n");
|
||||
return false;
|
||||
return -EPROTO;
|
||||
}
|
||||
if (type == BRCMF_SDIO_FT_SUB && len > rd->len) {
|
||||
brcmf_dbg(ERROR, "HW subframe header length error\n");
|
||||
return false;
|
||||
return -EPROTO;
|
||||
}
|
||||
rd->len = len;
|
||||
|
||||
|
@ -1091,7 +1091,7 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
|
|||
SDPCM_GLOMDESC(&header[SDPCM_FRAMETAG_LEN])) {
|
||||
brcmf_dbg(ERROR, "Glom descriptor found in superframe head\n");
|
||||
rd->len = 0;
|
||||
return false;
|
||||
return -EINVAL;
|
||||
}
|
||||
rx_seq = SDPCM_PACKET_SEQUENCE(&header[SDPCM_FRAMETAG_LEN]);
|
||||
rd->channel = SDPCM_PACKET_CHANNEL(&header[SDPCM_FRAMETAG_LEN]);
|
||||
|
@ -1102,18 +1102,18 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
|
|||
bus->sdcnt.rx_toolong++;
|
||||
brcmf_sdbrcm_rxfail(bus, false, false);
|
||||
rd->len = 0;
|
||||
return false;
|
||||
return -EPROTO;
|
||||
}
|
||||
if (type == BRCMF_SDIO_FT_SUPER && rd->channel != SDPCM_GLOM_CHANNEL) {
|
||||
brcmf_dbg(ERROR, "Wrong channel for superframe\n");
|
||||
rd->len = 0;
|
||||
return false;
|
||||
return -EINVAL;
|
||||
}
|
||||
if (type == BRCMF_SDIO_FT_SUB && rd->channel != SDPCM_DATA_CHANNEL &&
|
||||
rd->channel != SDPCM_EVENT_CHANNEL) {
|
||||
brcmf_dbg(ERROR, "Wrong channel for subframe\n");
|
||||
rd->len = 0;
|
||||
return false;
|
||||
return -EINVAL;
|
||||
}
|
||||
rd->dat_offset = SDPCM_DOFFSET_VALUE(&header[SDPCM_FRAMETAG_LEN]);
|
||||
if (rd->dat_offset < SDPCM_HDRLEN || rd->dat_offset > rd->len) {
|
||||
|
@ -1121,7 +1121,7 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
|
|||
bus->sdcnt.rx_badhdr++;
|
||||
brcmf_sdbrcm_rxfail(bus, false, false);
|
||||
rd->len = 0;
|
||||
return false;
|
||||
return -ENXIO;
|
||||
}
|
||||
if (rd->seq_num != rx_seq) {
|
||||
brcmf_dbg(ERROR, "seq %d: sequence number error, expect %d\n",
|
||||
|
@ -1131,7 +1131,7 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
|
|||
}
|
||||
/* no need to check the reset for subframe */
|
||||
if (type == BRCMF_SDIO_FT_SUB)
|
||||
return true;
|
||||
return 0;
|
||||
rd->len_nxtfrm = header[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
|
||||
if (rd->len_nxtfrm << 4 > MAX_RX_DATASZ) {
|
||||
/* only warm for NON glom packet */
|
||||
|
@ -1155,7 +1155,7 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
|
|||
}
|
||||
bus->tx_max = tx_seq_max;
|
||||
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
|
||||
|
@ -1272,6 +1272,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
|
|||
* read directly into the chained packet, or allocate a large
|
||||
* packet and and copy into the chain.
|
||||
*/
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
if (usechain) {
|
||||
errcode = brcmf_sdcard_recv_chain(bus->sdiodev,
|
||||
bus->sdiodev->sbwad,
|
||||
|
@ -1293,6 +1294,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
|
|||
dlen);
|
||||
errcode = -1;
|
||||
}
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
bus->sdcnt.f2rxdata++;
|
||||
|
||||
/* On failure, kill the superframe, allow a couple retries */
|
||||
|
@ -1301,6 +1303,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
|
|||
dlen, errcode);
|
||||
bus->sdiodev->bus_if->dstats.rx_errors++;
|
||||
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
if (bus->glomerr++ < 3) {
|
||||
brcmf_sdbrcm_rxfail(bus, true, true);
|
||||
} else {
|
||||
|
@ -1309,6 +1312,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
|
|||
bus->sdcnt.rxglomfail++;
|
||||
brcmf_sdbrcm_free_glom(bus);
|
||||
}
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1318,8 +1322,10 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
|
|||
|
||||
rd_new.seq_num = rxseq;
|
||||
rd_new.len = dlen;
|
||||
errcode = -!brcmf_sdio_hdparser(bus, pfirst->data, &rd_new,
|
||||
BRCMF_SDIO_FT_SUPER);
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
errcode = brcmf_sdio_hdparser(bus, pfirst->data, &rd_new,
|
||||
BRCMF_SDIO_FT_SUPER);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
bus->cur_read.len = rd_new.len_nxtfrm << 4;
|
||||
|
||||
/* Remove superframe header, remember offset */
|
||||
|
@ -1335,9 +1341,10 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
|
|||
|
||||
rd_new.len = pnext->len;
|
||||
rd_new.seq_num = rxseq++;
|
||||
errcode = -!brcmf_sdio_hdparser(bus, pnext->data,
|
||||
&rd_new,
|
||||
BRCMF_SDIO_FT_SUB);
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
errcode = brcmf_sdio_hdparser(bus, pnext->data, &rd_new,
|
||||
BRCMF_SDIO_FT_SUB);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
brcmf_dbg_hex_dump(BRCMF_GLOM_ON(),
|
||||
pnext->data, 32, "subframe:\n");
|
||||
|
||||
|
@ -1347,6 +1354,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
|
|||
if (errcode) {
|
||||
/* Terminate frame on error, request
|
||||
a couple retries */
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
if (bus->glomerr++ < 3) {
|
||||
/* Restore superframe header space */
|
||||
skb_push(pfirst, sfdoff);
|
||||
|
@ -1357,6 +1365,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
|
|||
bus->sdcnt.rxglomfail++;
|
||||
brcmf_sdbrcm_free_glom(bus);
|
||||
}
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
bus->cur_read.len = 0;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1397,11 +1406,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
|
|||
pfirst->prev);
|
||||
}
|
||||
/* sent any remaining packets up */
|
||||
if (bus->glom.qlen) {
|
||||
up(&bus->sdsem);
|
||||
if (bus->glom.qlen)
|
||||
brcmf_rx_frame(bus->sdiodev->dev, ifidx, &bus->glom);
|
||||
down(&bus->sdsem);
|
||||
}
|
||||
|
||||
bus->sdcnt.rxglomframes++;
|
||||
bus->sdcnt.rxglompkts += bus->glom.qlen;
|
||||
|
@ -1442,21 +1448,24 @@ static void
|
|||
brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
|
||||
{
|
||||
uint rdlen, pad;
|
||||
|
||||
u8 *buf = NULL, *rbuf;
|
||||
int sdret;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
/* Set rxctl for frame (w/optional alignment) */
|
||||
bus->rxctl = bus->rxbuf;
|
||||
bus->rxctl += BRCMF_FIRSTREAD;
|
||||
pad = ((unsigned long)bus->rxctl % BRCMF_SDALIGN);
|
||||
if (bus->rxblen)
|
||||
buf = vzalloc(bus->rxblen);
|
||||
if (!buf) {
|
||||
brcmf_dbg(ERROR, "no memory for control frame\n");
|
||||
goto done;
|
||||
}
|
||||
rbuf = bus->rxbuf;
|
||||
pad = ((unsigned long)rbuf % BRCMF_SDALIGN);
|
||||
if (pad)
|
||||
bus->rxctl += (BRCMF_SDALIGN - pad);
|
||||
bus->rxctl -= BRCMF_FIRSTREAD;
|
||||
rbuf += (BRCMF_SDALIGN - pad);
|
||||
|
||||
/* Copy the already-read portion over */
|
||||
memcpy(bus->rxctl, hdr, BRCMF_FIRSTREAD);
|
||||
memcpy(buf, hdr, BRCMF_FIRSTREAD);
|
||||
if (len <= BRCMF_FIRSTREAD)
|
||||
goto gotpkt;
|
||||
|
||||
|
@ -1493,11 +1502,11 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
|
|||
goto done;
|
||||
}
|
||||
|
||||
/* Read remainder of frame body into the rxctl buffer */
|
||||
/* Read remain of frame body */
|
||||
sdret = brcmf_sdcard_recv_buf(bus->sdiodev,
|
||||
bus->sdiodev->sbwad,
|
||||
SDIO_FUNC_2,
|
||||
F2SYNC, (bus->rxctl + BRCMF_FIRSTREAD), rdlen);
|
||||
F2SYNC, rbuf, rdlen);
|
||||
bus->sdcnt.f2rxdata++;
|
||||
|
||||
/* Control frame failures need retransmission */
|
||||
|
@ -1507,16 +1516,26 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
|
|||
bus->sdcnt.rxc_errors++;
|
||||
brcmf_sdbrcm_rxfail(bus, true, true);
|
||||
goto done;
|
||||
}
|
||||
} else
|
||||
memcpy(buf + BRCMF_FIRSTREAD, rbuf, rdlen);
|
||||
|
||||
gotpkt:
|
||||
|
||||
brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_CTL_ON(),
|
||||
bus->rxctl, len, "RxCtrl:\n");
|
||||
buf, len, "RxCtrl:\n");
|
||||
|
||||
/* Point to valid data and indicate its length */
|
||||
bus->rxctl += doff;
|
||||
spin_lock_bh(&bus->rxctl_lock);
|
||||
if (bus->rxctl) {
|
||||
brcmf_dbg(ERROR, "last control frame is being processed.\n");
|
||||
spin_unlock_bh(&bus->rxctl_lock);
|
||||
vfree(buf);
|
||||
goto done;
|
||||
}
|
||||
bus->rxctl = buf + doff;
|
||||
bus->rxctl_orig = buf;
|
||||
bus->rxlen = len - doff;
|
||||
spin_unlock_bh(&bus->rxctl_lock);
|
||||
|
||||
done:
|
||||
/* Awake any waiters */
|
||||
|
@ -1571,6 +1590,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
|
|||
|
||||
rd->len_left = rd->len;
|
||||
/* read header first for unknow frame length */
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
if (!rd->len) {
|
||||
sdret = brcmf_sdcard_recv_buf(bus->sdiodev,
|
||||
bus->sdiodev->sbwad,
|
||||
|
@ -1583,6 +1603,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
|
|||
sdret);
|
||||
bus->sdcnt.rx_hdrfail++;
|
||||
brcmf_sdbrcm_rxfail(bus, true, true);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1590,8 +1611,9 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
|
|||
bus->rxhdr, SDPCM_HDRLEN,
|
||||
"RxHdr:\n");
|
||||
|
||||
if (!brcmf_sdio_hdparser(bus, bus->rxhdr, rd,
|
||||
BRCMF_SDIO_FT_NORMAL)) {
|
||||
if (brcmf_sdio_hdparser(bus, bus->rxhdr, rd,
|
||||
BRCMF_SDIO_FT_NORMAL)) {
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
if (!bus->rxpending)
|
||||
break;
|
||||
else
|
||||
|
@ -1607,6 +1629,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
|
|||
rd->len_nxtfrm = 0;
|
||||
/* treat all packet as event if we don't know */
|
||||
rd->channel = SDPCM_EVENT_CHANNEL;
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
continue;
|
||||
}
|
||||
rd->len_left = rd->len > BRCMF_FIRSTREAD ?
|
||||
|
@ -1624,6 +1647,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
|
|||
bus->sdiodev->bus_if->dstats.rx_dropped++;
|
||||
brcmf_sdbrcm_rxfail(bus, false,
|
||||
RETRYCHAN(rd->channel));
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
continue;
|
||||
}
|
||||
skb_pull(pkt, head_read);
|
||||
|
@ -1632,14 +1656,17 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
|
|||
sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad,
|
||||
SDIO_FUNC_2, F2SYNC, pkt);
|
||||
bus->sdcnt.f2rxdata++;
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
|
||||
if (sdret < 0) {
|
||||
brcmf_dbg(ERROR, "read %d bytes from channel %d failed: %d\n",
|
||||
rd->len, rd->channel, sdret);
|
||||
brcmu_pkt_buf_free_skb(pkt);
|
||||
bus->sdiodev->bus_if->dstats.rx_errors++;
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
brcmf_sdbrcm_rxfail(bus, true,
|
||||
RETRYCHAN(rd->channel));
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1650,8 +1677,9 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
|
|||
} else {
|
||||
memcpy(bus->rxhdr, pkt->data, SDPCM_HDRLEN);
|
||||
rd_new.seq_num = rd->seq_num;
|
||||
if (!brcmf_sdio_hdparser(bus, bus->rxhdr, &rd_new,
|
||||
BRCMF_SDIO_FT_NORMAL)) {
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
if (brcmf_sdio_hdparser(bus, bus->rxhdr, &rd_new,
|
||||
BRCMF_SDIO_FT_NORMAL)) {
|
||||
rd->len = 0;
|
||||
brcmu_pkt_buf_free_skb(pkt);
|
||||
}
|
||||
|
@ -1662,9 +1690,11 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
|
|||
roundup(rd_new.len, 16) >> 4);
|
||||
rd->len = 0;
|
||||
brcmf_sdbrcm_rxfail(bus, true, true);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
brcmu_pkt_buf_free_skb(pkt);
|
||||
continue;
|
||||
}
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
rd->len_nxtfrm = rd_new.len_nxtfrm;
|
||||
rd->channel = rd_new.channel;
|
||||
rd->dat_offset = rd_new.dat_offset;
|
||||
|
@ -1680,7 +1710,9 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
|
|||
rd_new.seq_num);
|
||||
/* Force retry w/normal header read */
|
||||
rd->len = 0;
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
brcmf_sdbrcm_rxfail(bus, false, true);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
brcmu_pkt_buf_free_skb(pkt);
|
||||
continue;
|
||||
}
|
||||
|
@ -1703,7 +1735,9 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
|
|||
} else {
|
||||
brcmf_dbg(ERROR, "%s: glom superframe w/o "
|
||||
"descriptor!\n", __func__);
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
brcmf_sdbrcm_rxfail(bus, false, false);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
}
|
||||
/* prepare the descriptor for the next read */
|
||||
rd->len = rd->len_nxtfrm << 4;
|
||||
|
@ -1734,10 +1768,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
|
|||
continue;
|
||||
}
|
||||
|
||||
/* Unlock during rx call */
|
||||
up(&bus->sdsem);
|
||||
brcmf_rx_packet(bus->sdiodev->dev, ifidx, pkt);
|
||||
down(&bus->sdsem);
|
||||
}
|
||||
|
||||
rxcount = maxframes - rxleft;
|
||||
|
@ -1754,15 +1785,6 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
|
|||
return rxcount;
|
||||
}
|
||||
|
||||
static void
|
||||
brcmf_sdbrcm_wait_for_event(struct brcmf_sdio *bus, bool *lockvar)
|
||||
{
|
||||
up(&bus->sdsem);
|
||||
wait_event_interruptible_timeout(bus->ctrl_wait, !*lockvar, HZ * 2);
|
||||
down(&bus->sdsem);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus)
|
||||
{
|
||||
|
@ -1864,6 +1886,7 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
|
|||
if (len & (ALIGNMENT - 1))
|
||||
len = roundup(len, ALIGNMENT);
|
||||
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
ret = brcmf_sdcard_send_pkt(bus->sdiodev, bus->sdiodev->sbwad,
|
||||
SDIO_FUNC_2, F2SYNC, pkt);
|
||||
bus->sdcnt.f2txdata++;
|
||||
|
@ -1891,15 +1914,14 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
|
|||
}
|
||||
|
||||
}
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
if (ret == 0)
|
||||
bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
|
||||
|
||||
done:
|
||||
/* restore pkt buffer pointer before calling tx complete routine */
|
||||
skb_pull(pkt, SDPCM_HDRLEN + pad);
|
||||
up(&bus->sdsem);
|
||||
brcmf_txcomplete(bus->sdiodev->dev, pkt, ret != 0);
|
||||
down(&bus->sdsem);
|
||||
|
||||
if (free_pkt)
|
||||
brcmu_pkt_buf_free_skb(pkt);
|
||||
|
@ -1940,9 +1962,11 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
|
|||
/* In poll mode, need to check for other events */
|
||||
if (!bus->intr && cnt) {
|
||||
/* Check device status, signal pending interrupt */
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
ret = r_sdreg32(bus, &intstatus,
|
||||
offsetof(struct sdpcmd_regs,
|
||||
intstatus));
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
bus->sdcnt.f2txdata++;
|
||||
if (ret != 0)
|
||||
break;
|
||||
|
@ -1979,7 +2003,7 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
|
|||
bus->watchdog_tsk = NULL;
|
||||
}
|
||||
|
||||
down(&bus->sdsem);
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
|
||||
/* Enable clock for device interrupts */
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
|
||||
|
@ -2013,6 +2037,7 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
|
|||
|
||||
/* Turn off the backplane clock (only) */
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
|
||||
/* Clear the data packet queues */
|
||||
brcmu_pktq_flush(&bus->txq, true, NULL, NULL);
|
||||
|
@ -2023,14 +2048,14 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
|
|||
brcmf_sdbrcm_free_glom(bus);
|
||||
|
||||
/* Clear rx control and wake any waiters */
|
||||
spin_lock_bh(&bus->rxctl_lock);
|
||||
bus->rxlen = 0;
|
||||
spin_unlock_bh(&bus->rxctl_lock);
|
||||
brcmf_sdbrcm_dcmd_resp_wake(bus);
|
||||
|
||||
/* Reset some F2 state stuff */
|
||||
bus->rxskip = false;
|
||||
bus->tx_seq = bus->rx_seq = 0;
|
||||
|
||||
up(&bus->sdsem);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BRCMFMAC_SDIO_OOB
|
||||
|
@ -2114,7 +2139,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
|
|||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
down(&bus->sdsem);
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
|
||||
/* If waiting for HTAVAIL, check status */
|
||||
if (bus->clkstate == CLK_PENDING) {
|
||||
|
@ -2168,9 +2193,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
|
|||
/* Pending interrupt indicates new device status */
|
||||
if (atomic_read(&bus->ipend) > 0) {
|
||||
atomic_set(&bus->ipend, 0);
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
err = brcmf_sdio_intr_rstatus(bus);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
}
|
||||
|
||||
/* Start with leftover status bits */
|
||||
|
@ -2199,6 +2222,8 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
|
|||
intstatus |= brcmf_sdbrcm_hostmail(bus);
|
||||
}
|
||||
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
|
||||
/* Generally don't ask for these, can get CRC errors... */
|
||||
if (intstatus & I_WR_OOSYNC) {
|
||||
brcmf_dbg(ERROR, "Dongle reports WR_OOSYNC\n");
|
||||
|
@ -2245,6 +2270,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
|
|||
(bus->clkstate == CLK_AVAIL)) {
|
||||
int i;
|
||||
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
err = brcmf_sdcard_send_buf(bus->sdiodev, bus->sdiodev->sbwad,
|
||||
SDIO_FUNC_2, F2SYNC, bus->ctrl_frame_buf,
|
||||
(u32) bus->ctrl_frame_len);
|
||||
|
@ -2278,6 +2304,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
|
|||
} else {
|
||||
bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
|
||||
}
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
bus->ctrl_frame_stat = false;
|
||||
brcmf_sdbrcm_wait_event_wakeup(bus);
|
||||
}
|
||||
|
@ -2307,10 +2334,10 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
|
|||
if ((bus->clkstate != CLK_PENDING)
|
||||
&& bus->idletime == BRCMF_IDLE_IMMEDIATE) {
|
||||
bus->activity = false;
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
}
|
||||
|
||||
up(&bus->sdsem);
|
||||
}
|
||||
|
||||
static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
|
||||
|
@ -2601,11 +2628,10 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
|
|||
|
||||
/* precondition: IS_ALIGNED((unsigned long)frame, 2) */
|
||||
|
||||
/* Need to lock here to protect txseq and SDIO tx calls */
|
||||
down(&bus->sdsem);
|
||||
|
||||
/* Make sure backplane clock is on */
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
|
||||
/* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
|
||||
*(__le16 *) frame = cpu_to_le16((u16) msglen);
|
||||
|
@ -2628,7 +2654,9 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
|
|||
bus->ctrl_frame_buf = frame;
|
||||
bus->ctrl_frame_len = len;
|
||||
|
||||
brcmf_sdbrcm_wait_for_event(bus, &bus->ctrl_frame_stat);
|
||||
wait_event_interruptible_timeout(bus->ctrl_wait,
|
||||
!bus->ctrl_frame_stat,
|
||||
msecs_to_jiffies(2000));
|
||||
|
||||
if (!bus->ctrl_frame_stat) {
|
||||
brcmf_dbg(INFO, "ctrl_frame_stat == false\n");
|
||||
|
@ -2647,7 +2675,9 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
|
|||
frame, min_t(u16, len, 16), "TxHdr:\n");
|
||||
|
||||
do {
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
ret = brcmf_tx_frame(bus, frame, len);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
} while (ret < 0 && retries++ < TXRETRIES);
|
||||
}
|
||||
|
||||
|
@ -2657,13 +2687,13 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
|
|||
spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
|
||||
|
||||
bus->activity = false;
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
} else {
|
||||
spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
|
||||
}
|
||||
|
||||
up(&bus->sdsem);
|
||||
|
||||
if (ret)
|
||||
bus->sdcnt.tx_ctlerrs++;
|
||||
else
|
||||
|
@ -2693,8 +2723,10 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
|
|||
* Read last word in socram to determine
|
||||
* address of sdpcm_shared structure
|
||||
*/
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
rv = brcmf_sdbrcm_membytes(bus, false, shaddr,
|
||||
(u8 *)&addr_le, 4);
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
|
@ -2713,8 +2745,10 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
|
|||
}
|
||||
|
||||
/* Read hndrte_shared structure */
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&sh_le,
|
||||
sizeof(struct sdpcm_shared_le));
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
|
@ -2817,12 +2851,14 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh,
|
|||
if ((sh->flags & SDPCM_SHARED_TRAP) == 0)
|
||||
return 0;
|
||||
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
error = brcmf_sdbrcm_membytes(bus, false, sh->trap_addr, (u8 *)&tr,
|
||||
sizeof(struct brcmf_trap_info));
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
nbytes = brcmf_sdio_dump_console(bus, sh, data, count);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
if (nbytes < 0)
|
||||
return nbytes;
|
||||
|
||||
|
@ -2868,6 +2904,7 @@ static int brcmf_sdio_assert_info(struct brcmf_sdio *bus,
|
|||
return 0;
|
||||
}
|
||||
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
if (sh->assert_file_addr != 0) {
|
||||
error = brcmf_sdbrcm_membytes(bus, false, sh->assert_file_addr,
|
||||
(u8 *)file, 80);
|
||||
|
@ -2880,6 +2917,7 @@ static int brcmf_sdio_assert_info(struct brcmf_sdio *bus,
|
|||
if (error < 0)
|
||||
return error;
|
||||
}
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
|
||||
res = scnprintf(buf, sizeof(buf),
|
||||
"dongle assert: %s:%d: assert(%s)\n",
|
||||
|
@ -2892,9 +2930,7 @@ static int brcmf_sdbrcm_checkdied(struct brcmf_sdio *bus)
|
|||
int error;
|
||||
struct sdpcm_shared sh;
|
||||
|
||||
down(&bus->sdsem);
|
||||
error = brcmf_sdio_readshared(bus, &sh);
|
||||
up(&bus->sdsem);
|
||||
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
@ -2921,7 +2957,6 @@ static int brcmf_sdbrcm_died_dump(struct brcmf_sdio *bus, char __user *data,
|
|||
if (pos != 0)
|
||||
return 0;
|
||||
|
||||
down(&bus->sdsem);
|
||||
error = brcmf_sdio_readshared(bus, &sh);
|
||||
if (error < 0)
|
||||
goto done;
|
||||
|
@ -2938,7 +2973,6 @@ static int brcmf_sdbrcm_died_dump(struct brcmf_sdio *bus, char __user *data,
|
|||
error += nbytes;
|
||||
*ppos += error;
|
||||
done:
|
||||
up(&bus->sdsem);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -2989,6 +3023,7 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
|
|||
int timeleft;
|
||||
uint rxlen = 0;
|
||||
bool pending;
|
||||
u8 *buf;
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
|
||||
struct brcmf_sdio *bus = sdiodev->bus;
|
||||
|
@ -2998,11 +3033,15 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
|
|||
/* Wait until control frame is available */
|
||||
timeleft = brcmf_sdbrcm_dcmd_resp_wait(bus, &bus->rxlen, &pending);
|
||||
|
||||
down(&bus->sdsem);
|
||||
spin_lock_bh(&bus->rxctl_lock);
|
||||
rxlen = bus->rxlen;
|
||||
memcpy(msg, bus->rxctl, min(msglen, rxlen));
|
||||
bus->rxctl = NULL;
|
||||
buf = bus->rxctl_orig;
|
||||
bus->rxctl_orig = NULL;
|
||||
bus->rxlen = 0;
|
||||
up(&bus->sdsem);
|
||||
spin_unlock_bh(&bus->rxctl_lock);
|
||||
vfree(buf);
|
||||
|
||||
if (rxlen) {
|
||||
brcmf_dbg(CTL, "resumed on rxctl frame, got %d expected %d\n",
|
||||
|
@ -3338,13 +3377,16 @@ brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
|
|||
{
|
||||
bool ret;
|
||||
|
||||
/* Download the firmware */
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
|
||||
|
||||
ret = _brcmf_sdbrcm_download_firmware(bus) == 0;
|
||||
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
|
||||
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -3373,7 +3415,7 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
|
|||
bus->sdcnt.tickcnt = 0;
|
||||
brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
|
||||
|
||||
down(&bus->sdsem);
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
|
||||
/* Make sure backplane clock is on, needed to generate F2 interrupt */
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
|
||||
|
@ -3442,7 +3484,7 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
|
|||
brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
|
||||
|
||||
exit:
|
||||
up(&bus->sdsem);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -3489,8 +3531,6 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
|
|||
|
||||
brcmf_dbg(TIMER, "Enter\n");
|
||||
|
||||
down(&bus->sdsem);
|
||||
|
||||
/* Poll period: check device if appropriate. */
|
||||
if (bus->poll && (++bus->polltick >= bus->pollrate)) {
|
||||
u32 intstatus = 0;
|
||||
|
@ -3507,9 +3547,11 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
|
|||
u8 devpend;
|
||||
spin_unlock_irqrestore(&bus->dpc_tl_lock,
|
||||
flags);
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
devpend = brcmf_sdio_regrb(bus->sdiodev,
|
||||
SDIO_CCCR_INTx,
|
||||
NULL);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
intstatus =
|
||||
devpend & (INTR_STATUS_FUNC1 |
|
||||
INTR_STATUS_FUNC2);
|
||||
|
@ -3534,16 +3576,18 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
|
|||
}
|
||||
#ifdef DEBUG
|
||||
/* Poll for console output periodically */
|
||||
if (bus_if->state == BRCMF_BUS_DATA &&
|
||||
if (bus_if && bus_if->state == BRCMF_BUS_DATA &&
|
||||
bus->console_interval != 0) {
|
||||
bus->console.count += BRCMF_WD_POLL_MS;
|
||||
if (bus->console.count >= bus->console_interval) {
|
||||
bus->console.count -= bus->console_interval;
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
/* Make sure backplane clock is on */
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
|
||||
if (brcmf_sdbrcm_readconsole(bus) < 0)
|
||||
/* stop on error */
|
||||
bus->console_interval = 0;
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
}
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
@ -3556,13 +3600,13 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
|
|||
bus->activity = false;
|
||||
brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
|
||||
} else {
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
up(&bus->sdsem);
|
||||
|
||||
return (atomic_read(&bus->ipend) > 0);
|
||||
}
|
||||
|
||||
|
@ -3657,6 +3701,8 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
|
|||
|
||||
bus->alp_only = true;
|
||||
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
|
||||
pr_debug("F1 signature read @0x18000000=0x%4x\n",
|
||||
brcmf_sdio_regrl(bus->sdiodev, SI_ENUM_BASE, NULL));
|
||||
|
||||
|
@ -3704,6 +3750,8 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
|
|||
reg_val = brcmf_sdio_regrl(bus->sdiodev, reg_addr, NULL);
|
||||
brcmf_sdio_regwl(bus->sdiodev, reg_addr, reg_val | CC_BPRESEN, NULL);
|
||||
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
|
||||
brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN);
|
||||
|
||||
/* Locate an appropriately-aligned portion of hdrbuf */
|
||||
|
@ -3719,6 +3767,7 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
|
|||
return true;
|
||||
|
||||
fail:
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -3726,6 +3775,8 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus)
|
|||
{
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
|
||||
/* Disable F2 to clear any intermediate frame state on the dongle */
|
||||
brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_IOEx,
|
||||
SDIO_FUNC_ENABLE_1, NULL);
|
||||
|
@ -3736,6 +3787,8 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus)
|
|||
/* Done with backplane-dependent accesses, can drop clock... */
|
||||
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
|
||||
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
|
||||
/* ...and initialize clock/power states */
|
||||
bus->clkstate = CLK_SDONLY;
|
||||
bus->idletime = BRCMF_IDLE_INTERVAL;
|
||||
|
@ -3791,8 +3844,10 @@ static void brcmf_sdbrcm_release_dongle(struct brcmf_sdio *bus)
|
|||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
if (bus->ci) {
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
brcmf_sdio_chip_detach(&bus->ci);
|
||||
if (bus->vars && bus->varsz)
|
||||
kfree(bus->vars);
|
||||
|
@ -3812,7 +3867,8 @@ static void brcmf_sdbrcm_release(struct brcmf_sdio *bus)
|
|||
brcmf_sdio_intr_unregister(bus->sdiodev);
|
||||
|
||||
cancel_work_sync(&bus->datawork);
|
||||
destroy_workqueue(bus->brcmf_wq);
|
||||
if (bus->brcmf_wq)
|
||||
destroy_workqueue(bus->brcmf_wq);
|
||||
|
||||
if (bus->sdiodev->bus_if->drvr) {
|
||||
brcmf_detach(bus->sdiodev->dev);
|
||||
|
@ -3854,31 +3910,29 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
|
|||
bus->txminmax = BRCMF_TXMINMAX;
|
||||
bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1;
|
||||
|
||||
INIT_WORK(&bus->datawork, brcmf_sdio_dataworker);
|
||||
bus->brcmf_wq = create_singlethread_workqueue("brcmf_wq");
|
||||
if (bus->brcmf_wq == NULL) {
|
||||
brcmf_dbg(ERROR, "insufficient memory to create txworkqueue\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* attempt to attach to the dongle */
|
||||
if (!(brcmf_sdbrcm_probe_attach(bus, regsva))) {
|
||||
brcmf_dbg(ERROR, "brcmf_sdbrcm_probe_attach failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
spin_lock_init(&bus->rxctl_lock);
|
||||
spin_lock_init(&bus->txqlock);
|
||||
init_waitqueue_head(&bus->ctrl_wait);
|
||||
init_waitqueue_head(&bus->dcmd_resp_wait);
|
||||
|
||||
bus->brcmf_wq = create_singlethread_workqueue("brcmf_wq");
|
||||
if (bus->brcmf_wq == NULL) {
|
||||
brcmf_dbg(ERROR, "insufficient memory to create txworkqueue\n");
|
||||
goto fail;
|
||||
}
|
||||
INIT_WORK(&bus->datawork, brcmf_sdio_dataworker);
|
||||
|
||||
/* Set up the watchdog timer */
|
||||
init_timer(&bus->timer);
|
||||
bus->timer.data = (unsigned long)bus;
|
||||
bus->timer.function = brcmf_sdbrcm_watchdog;
|
||||
|
||||
/* Initialize thread based operation and lock */
|
||||
sema_init(&bus->sdsem, 1);
|
||||
|
||||
/* Initialize watchdog thread */
|
||||
init_completion(&bus->watchdog_wait);
|
||||
bus->watchdog_tsk = kthread_run(brcmf_sdbrcm_watchdog_thread,
|
||||
|
@ -3941,10 +3995,8 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
|
|||
/* if firmware path present try to download and bring up bus */
|
||||
ret = brcmf_bus_start(bus->sdiodev->dev);
|
||||
if (ret != 0) {
|
||||
if (ret == -ENOLINK) {
|
||||
brcmf_dbg(ERROR, "dongle is not responding\n");
|
||||
goto fail;
|
||||
}
|
||||
brcmf_dbg(ERROR, "dongle is not responding\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return bus;
|
||||
|
|
|
@ -0,0 +1,509 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Broadcom Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#include "brcmu_wifi.h"
|
||||
#include "brcmu_utils.h"
|
||||
|
||||
#include "dhd.h"
|
||||
#include "dhd_dbg.h"
|
||||
#include "fweh.h"
|
||||
#include "fwil.h"
|
||||
|
||||
/**
|
||||
* struct brcm_ethhdr - broadcom specific ether header.
|
||||
*
|
||||
* @subtype: subtype for this packet.
|
||||
* @length: TODO: length of appended data.
|
||||
* @version: version indication.
|
||||
* @oui: OUI of this packet.
|
||||
* @usr_subtype: subtype for this OUI.
|
||||
*/
|
||||
struct brcm_ethhdr {
|
||||
__be16 subtype;
|
||||
__be16 length;
|
||||
u8 version;
|
||||
u8 oui[3];
|
||||
__be16 usr_subtype;
|
||||
} __packed;
|
||||
|
||||
struct brcmf_event_msg_be {
|
||||
__be16 version;
|
||||
__be16 flags;
|
||||
__be32 event_type;
|
||||
__be32 status;
|
||||
__be32 reason;
|
||||
__be32 auth_type;
|
||||
__be32 datalen;
|
||||
u8 addr[ETH_ALEN];
|
||||
char ifname[IFNAMSIZ];
|
||||
u8 ifidx;
|
||||
u8 bsscfgidx;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct brcmf_event - contents of broadcom event packet.
|
||||
*
|
||||
* @eth: standard ether header.
|
||||
* @hdr: broadcom specific ether header.
|
||||
* @msg: common part of the actual event message.
|
||||
*/
|
||||
struct brcmf_event {
|
||||
struct ethhdr eth;
|
||||
struct brcm_ethhdr hdr;
|
||||
struct brcmf_event_msg_be msg;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct brcmf_fweh_queue_item - event item on event queue.
|
||||
*
|
||||
* @q: list element for queuing.
|
||||
* @code: event code.
|
||||
* @ifidx: interface index related to this event.
|
||||
* @ifaddr: ethernet address for interface.
|
||||
* @emsg: common parameters of the firmware event message.
|
||||
* @data: event specific data part of the firmware event.
|
||||
*/
|
||||
struct brcmf_fweh_queue_item {
|
||||
struct list_head q;
|
||||
enum brcmf_fweh_event_code code;
|
||||
u8 ifidx;
|
||||
u8 ifaddr[ETH_ALEN];
|
||||
struct brcmf_event_msg_be emsg;
|
||||
u8 data[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_fweh_event_name - code, name mapping entry.
|
||||
*/
|
||||
struct brcmf_fweh_event_name {
|
||||
enum brcmf_fweh_event_code code;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
/* array for mapping code to event name */
|
||||
static struct brcmf_fweh_event_name fweh_event_names[] = {
|
||||
{ BRCMF_E_SET_SSID, "SET_SSID" },
|
||||
{ BRCMF_E_JOIN, "JOIN" },
|
||||
{ BRCMF_E_START, "START" },
|
||||
{ BRCMF_E_AUTH, "AUTH" },
|
||||
{ BRCMF_E_AUTH_IND, "AUTH_IND" },
|
||||
{ BRCMF_E_DEAUTH, "DEAUTH" },
|
||||
{ BRCMF_E_DEAUTH_IND, "DEAUTH_IND" },
|
||||
{ BRCMF_E_ASSOC, "ASSOC" },
|
||||
{ BRCMF_E_ASSOC_IND, "ASSOC_IND" },
|
||||
{ BRCMF_E_REASSOC, "REASSOC" },
|
||||
{ BRCMF_E_REASSOC_IND, "REASSOC_IND" },
|
||||
{ BRCMF_E_DISASSOC, "DISASSOC" },
|
||||
{ BRCMF_E_DISASSOC_IND, "DISASSOC_IND" },
|
||||
{ BRCMF_E_QUIET_START, "START_QUIET" },
|
||||
{ BRCMF_E_QUIET_END, "END_QUIET" },
|
||||
{ BRCMF_E_BEACON_RX, "BEACON_RX" },
|
||||
{ BRCMF_E_LINK, "LINK" },
|
||||
{ BRCMF_E_MIC_ERROR, "MIC_ERROR" },
|
||||
{ BRCMF_E_NDIS_LINK, "NDIS_LINK" },
|
||||
{ BRCMF_E_ROAM, "ROAM" },
|
||||
{ BRCMF_E_TXFAIL, "TXFAIL" },
|
||||
{ BRCMF_E_PMKID_CACHE, "PMKID_CACHE" },
|
||||
{ BRCMF_E_RETROGRADE_TSF, "RETROGRADE_TSF" },
|
||||
{ BRCMF_E_PRUNE, "PRUNE" },
|
||||
{ BRCMF_E_AUTOAUTH, "AUTOAUTH" },
|
||||
{ BRCMF_E_EAPOL_MSG, "EAPOL_MSG" },
|
||||
{ BRCMF_E_SCAN_COMPLETE, "SCAN_COMPLETE" },
|
||||
{ BRCMF_E_ADDTS_IND, "ADDTS_IND" },
|
||||
{ BRCMF_E_DELTS_IND, "DELTS_IND" },
|
||||
{ BRCMF_E_BCNSENT_IND, "BCNSENT_IND" },
|
||||
{ BRCMF_E_BCNRX_MSG, "BCNRX_MSG" },
|
||||
{ BRCMF_E_BCNLOST_MSG, "BCNLOST_MSG" },
|
||||
{ BRCMF_E_ROAM_PREP, "ROAM_PREP" },
|
||||
{ BRCMF_E_PFN_NET_FOUND, "PNO_NET_FOUND" },
|
||||
{ BRCMF_E_PFN_NET_LOST, "PNO_NET_LOST" },
|
||||
{ BRCMF_E_RESET_COMPLETE, "RESET_COMPLETE" },
|
||||
{ BRCMF_E_JOIN_START, "JOIN_START" },
|
||||
{ BRCMF_E_ROAM_START, "ROAM_START" },
|
||||
{ BRCMF_E_ASSOC_START, "ASSOC_START" },
|
||||
{ BRCMF_E_IBSS_ASSOC, "IBSS_ASSOC" },
|
||||
{ BRCMF_E_RADIO, "RADIO" },
|
||||
{ BRCMF_E_PSM_WATCHDOG, "PSM_WATCHDOG" },
|
||||
{ BRCMF_E_PROBREQ_MSG, "PROBREQ_MSG" },
|
||||
{ BRCMF_E_SCAN_CONFIRM_IND, "SCAN_CONFIRM_IND" },
|
||||
{ BRCMF_E_PSK_SUP, "PSK_SUP" },
|
||||
{ BRCMF_E_COUNTRY_CODE_CHANGED, "COUNTRY_CODE_CHANGED" },
|
||||
{ BRCMF_E_EXCEEDED_MEDIUM_TIME, "EXCEEDED_MEDIUM_TIME" },
|
||||
{ BRCMF_E_ICV_ERROR, "ICV_ERROR" },
|
||||
{ BRCMF_E_UNICAST_DECODE_ERROR, "UNICAST_DECODE_ERROR" },
|
||||
{ BRCMF_E_MULTICAST_DECODE_ERROR, "MULTICAST_DECODE_ERROR" },
|
||||
{ BRCMF_E_TRACE, "TRACE" },
|
||||
{ BRCMF_E_IF, "IF" },
|
||||
{ BRCMF_E_RSSI, "RSSI" },
|
||||
{ BRCMF_E_PFN_SCAN_COMPLETE, "PFN_SCAN_COMPLETE" },
|
||||
{ BRCMF_E_EXTLOG_MSG, "EXTLOG_MSG" },
|
||||
{ BRCMF_E_ACTION_FRAME, "ACTION_FRAME" },
|
||||
{ BRCMF_E_ACTION_FRAME_COMPLETE, "ACTION_FRAME_COMPLETE" },
|
||||
{ BRCMF_E_PRE_ASSOC_IND, "PRE_ASSOC_IND" },
|
||||
{ BRCMF_E_PRE_REASSOC_IND, "PRE_REASSOC_IND" },
|
||||
{ BRCMF_E_CHANNEL_ADOPTED, "CHANNEL_ADOPTED" },
|
||||
{ BRCMF_E_AP_STARTED, "AP_STARTED" },
|
||||
{ BRCMF_E_DFS_AP_STOP, "DFS_AP_STOP" },
|
||||
{ BRCMF_E_DFS_AP_RESUME, "DFS_AP_RESUME" },
|
||||
{ BRCMF_E_ESCAN_RESULT, "ESCAN_RESULT" },
|
||||
{ BRCMF_E_ACTION_FRAME_OFF_CHAN_COMPLETE, "ACTION_FRM_OFF_CHAN_CMPLT" },
|
||||
{ BRCMF_E_DCS_REQUEST, "DCS_REQUEST" },
|
||||
{ BRCMF_E_FIFO_CREDIT_MAP, "FIFO_CREDIT_MAP"}
|
||||
};
|
||||
|
||||
/**
|
||||
* brcmf_fweh_event_name() - returns name for given event code.
|
||||
*
|
||||
* @code: code to lookup.
|
||||
*/
|
||||
static const char *brcmf_fweh_event_name(enum brcmf_fweh_event_code code)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(fweh_event_names); i++) {
|
||||
if (fweh_event_names[i].code == code)
|
||||
return fweh_event_names[i].name;
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
#else
|
||||
static const char *brcmf_fweh_event_name(enum brcmf_fweh_event_code code)
|
||||
{
|
||||
return "nodebug";
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* brcmf_fweh_queue_event() - create and queue event.
|
||||
*
|
||||
* @fweh: firmware event handling info.
|
||||
* @event: event queue entry.
|
||||
*/
|
||||
static void brcmf_fweh_queue_event(struct brcmf_fweh_info *fweh,
|
||||
struct brcmf_fweh_queue_item *event)
|
||||
{
|
||||
ulong flags;
|
||||
|
||||
spin_lock_irqsave(&fweh->evt_q_lock, flags);
|
||||
list_add_tail(&event->q, &fweh->event_q);
|
||||
spin_unlock_irqrestore(&fweh->evt_q_lock, flags);
|
||||
schedule_work(&fweh->event_work);
|
||||
}
|
||||
|
||||
static int brcmf_fweh_call_event_handler(struct brcmf_if *ifp,
|
||||
enum brcmf_fweh_event_code code,
|
||||
struct brcmf_event_msg *emsg,
|
||||
void *data)
|
||||
{
|
||||
struct brcmf_fweh_info *fweh;
|
||||
int err = -EINVAL;
|
||||
|
||||
if (ifp) {
|
||||
fweh = &ifp->drvr->fweh;
|
||||
|
||||
/* handle the event if valid interface and handler */
|
||||
if (ifp->ndev && fweh->evt_handler[code])
|
||||
err = fweh->evt_handler[code](ifp, emsg, data);
|
||||
else
|
||||
brcmf_dbg(ERROR, "unhandled event %d ignored\n", code);
|
||||
} else {
|
||||
brcmf_dbg(ERROR, "no interface object\n");
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_fweh_handle_if_event() - handle IF event.
|
||||
*
|
||||
* @drvr: driver information object.
|
||||
* @item: queue entry.
|
||||
* @ifpp: interface object (may change upon ADD action).
|
||||
*/
|
||||
static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
|
||||
struct brcmf_event_msg *emsg,
|
||||
void *data)
|
||||
{
|
||||
struct brcmf_if_event *ifevent = data;
|
||||
struct brcmf_if *ifp;
|
||||
int err = 0;
|
||||
|
||||
brcmf_dbg(EVENT, "action: %u idx: %u bsscfg: %u flags: %u\n",
|
||||
ifevent->action, ifevent->ifidx,
|
||||
ifevent->bssidx, ifevent->flags);
|
||||
|
||||
if (ifevent->ifidx >= BRCMF_MAX_IFS) {
|
||||
brcmf_dbg(ERROR, "invalid interface index: %u\n",
|
||||
ifevent->ifidx);
|
||||
return;
|
||||
}
|
||||
|
||||
ifp = drvr->iflist[ifevent->ifidx];
|
||||
|
||||
if (ifevent->action == BRCMF_E_IF_ADD) {
|
||||
brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname,
|
||||
emsg->addr);
|
||||
ifp = brcmf_add_if(drvr, ifevent->ifidx, ifevent->bssidx,
|
||||
emsg->ifname, emsg->addr);
|
||||
if (IS_ERR(ifp))
|
||||
return;
|
||||
|
||||
if (!drvr->fweh.evt_handler[BRCMF_E_IF])
|
||||
err = brcmf_net_attach(ifp);
|
||||
}
|
||||
|
||||
err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);
|
||||
|
||||
if (ifevent->action == BRCMF_E_IF_DEL)
|
||||
brcmf_del_if(drvr, ifevent->ifidx);
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_fweh_dequeue_event() - get event from the queue.
|
||||
*
|
||||
* @fweh: firmware event handling info.
|
||||
*/
|
||||
static struct brcmf_fweh_queue_item *
|
||||
brcmf_fweh_dequeue_event(struct brcmf_fweh_info *fweh)
|
||||
{
|
||||
struct brcmf_fweh_queue_item *event = NULL;
|
||||
ulong flags;
|
||||
|
||||
spin_lock_irqsave(&fweh->evt_q_lock, flags);
|
||||
if (!list_empty(&fweh->event_q)) {
|
||||
event = list_first_entry(&fweh->event_q,
|
||||
struct brcmf_fweh_queue_item, q);
|
||||
list_del(&event->q);
|
||||
}
|
||||
spin_unlock_irqrestore(&fweh->evt_q_lock, flags);
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_fweh_event_worker() - firmware event worker.
|
||||
*
|
||||
* @work: worker object.
|
||||
*/
|
||||
static void brcmf_fweh_event_worker(struct work_struct *work)
|
||||
{
|
||||
struct brcmf_pub *drvr;
|
||||
struct brcmf_if *ifp;
|
||||
struct brcmf_fweh_info *fweh;
|
||||
struct brcmf_fweh_queue_item *event;
|
||||
int err = 0;
|
||||
struct brcmf_event_msg_be *emsg_be;
|
||||
struct brcmf_event_msg emsg;
|
||||
|
||||
fweh = container_of(work, struct brcmf_fweh_info, event_work);
|
||||
drvr = container_of(fweh, struct brcmf_pub, fweh);
|
||||
|
||||
while ((event = brcmf_fweh_dequeue_event(fweh))) {
|
||||
ifp = drvr->iflist[event->ifidx];
|
||||
|
||||
brcmf_dbg(EVENT, "event %s (%u) ifidx %u bsscfg %u addr %pM:\n",
|
||||
brcmf_fweh_event_name(event->code), event->code,
|
||||
event->emsg.ifidx, event->emsg.bsscfgidx,
|
||||
event->emsg.addr);
|
||||
|
||||
/* convert event message */
|
||||
emsg_be = &event->emsg;
|
||||
emsg.version = be16_to_cpu(emsg_be->version);
|
||||
emsg.flags = be16_to_cpu(emsg_be->flags);
|
||||
emsg.event_code = event->code;
|
||||
emsg.status = be32_to_cpu(emsg_be->status);
|
||||
emsg.reason = be32_to_cpu(emsg_be->reason);
|
||||
emsg.auth_type = be32_to_cpu(emsg_be->auth_type);
|
||||
emsg.datalen = be32_to_cpu(emsg_be->datalen);
|
||||
memcpy(emsg.addr, emsg_be->addr, ETH_ALEN);
|
||||
memcpy(emsg.ifname, emsg_be->ifname, sizeof(emsg.ifname));
|
||||
emsg.ifidx = emsg_be->ifidx;
|
||||
emsg.bsscfgidx = emsg_be->bsscfgidx;
|
||||
|
||||
brcmf_dbg(EVENT, " version %u flags %u status %u reason %u\n",
|
||||
emsg.version, emsg.flags, emsg.status, emsg.reason);
|
||||
brcmf_dbg_hex_dump(BRCMF_EVENT_ON(), event->data,
|
||||
min_t(u32, emsg.datalen, 64),
|
||||
"appended:");
|
||||
|
||||
/* special handling of interface event */
|
||||
if (event->code == BRCMF_E_IF) {
|
||||
brcmf_fweh_handle_if_event(drvr, &emsg, event->data);
|
||||
goto event_free;
|
||||
}
|
||||
|
||||
err = brcmf_fweh_call_event_handler(ifp, event->code, &emsg,
|
||||
event->data);
|
||||
if (err) {
|
||||
brcmf_dbg(ERROR, "event handler failed (%d)\n",
|
||||
event->code);
|
||||
err = 0;
|
||||
}
|
||||
event_free:
|
||||
kfree(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_fweh_attach() - initialize firmware event handling.
|
||||
*
|
||||
* @drvr: driver information object.
|
||||
*/
|
||||
void brcmf_fweh_attach(struct brcmf_pub *drvr)
|
||||
{
|
||||
struct brcmf_fweh_info *fweh = &drvr->fweh;
|
||||
INIT_WORK(&fweh->event_work, brcmf_fweh_event_worker);
|
||||
spin_lock_init(&fweh->evt_q_lock);
|
||||
INIT_LIST_HEAD(&fweh->event_q);
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_fweh_detach() - cleanup firmware event handling.
|
||||
*
|
||||
* @drvr: driver information object.
|
||||
*/
|
||||
void brcmf_fweh_detach(struct brcmf_pub *drvr)
|
||||
{
|
||||
struct brcmf_fweh_info *fweh = &drvr->fweh;
|
||||
struct brcmf_if *ifp = drvr->iflist[0];
|
||||
s8 eventmask[BRCMF_EVENTING_MASK_LEN];
|
||||
|
||||
if (ifp) {
|
||||
/* clear all events */
|
||||
memset(eventmask, 0, BRCMF_EVENTING_MASK_LEN);
|
||||
(void)brcmf_fil_iovar_data_set(ifp, "event_msgs",
|
||||
eventmask,
|
||||
BRCMF_EVENTING_MASK_LEN);
|
||||
}
|
||||
/* cancel the worker */
|
||||
cancel_work_sync(&fweh->event_work);
|
||||
WARN_ON(!list_empty(&fweh->event_q));
|
||||
memset(fweh->evt_handler, 0, sizeof(fweh->evt_handler));
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_fweh_register() - register handler for given event code.
|
||||
*
|
||||
* @drvr: driver information object.
|
||||
* @code: event code.
|
||||
* @handler: handler for the given event code.
|
||||
*/
|
||||
int brcmf_fweh_register(struct brcmf_pub *drvr, enum brcmf_fweh_event_code code,
|
||||
brcmf_fweh_handler_t handler)
|
||||
{
|
||||
if (drvr->fweh.evt_handler[code]) {
|
||||
brcmf_dbg(ERROR, "event code %d already registered\n", code);
|
||||
return -ENOSPC;
|
||||
}
|
||||
drvr->fweh.evt_handler[code] = handler;
|
||||
brcmf_dbg(TRACE, "event handler registered for %s\n",
|
||||
brcmf_fweh_event_name(code));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_fweh_unregister() - remove handler for given code.
|
||||
*
|
||||
* @drvr: driver information object.
|
||||
* @code: event code.
|
||||
*/
|
||||
void brcmf_fweh_unregister(struct brcmf_pub *drvr,
|
||||
enum brcmf_fweh_event_code code)
|
||||
{
|
||||
brcmf_dbg(TRACE, "event handler cleared for %s\n",
|
||||
brcmf_fweh_event_name(code));
|
||||
drvr->fweh.evt_handler[code] = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_fweh_activate_events() - enables firmware events registered.
|
||||
*
|
||||
* @ifp: primary interface object.
|
||||
*/
|
||||
int brcmf_fweh_activate_events(struct brcmf_if *ifp)
|
||||
{
|
||||
int i, err;
|
||||
s8 eventmask[BRCMF_EVENTING_MASK_LEN];
|
||||
|
||||
for (i = 0; i < BRCMF_E_LAST; i++) {
|
||||
if (ifp->drvr->fweh.evt_handler[i]) {
|
||||
brcmf_dbg(EVENT, "enable event %s\n",
|
||||
brcmf_fweh_event_name(i));
|
||||
setbit(eventmask, i);
|
||||
}
|
||||
}
|
||||
|
||||
/* want to handle IF event as well */
|
||||
brcmf_dbg(EVENT, "enable event IF\n");
|
||||
setbit(eventmask, BRCMF_E_IF);
|
||||
|
||||
err = brcmf_fil_iovar_data_set(ifp, "event_msgs",
|
||||
eventmask, BRCMF_EVENTING_MASK_LEN);
|
||||
if (err)
|
||||
brcmf_dbg(ERROR, "Set event_msgs error (%d)\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_fweh_process_event() - process skb as firmware event.
|
||||
*
|
||||
* @drvr: driver information object.
|
||||
* @event_packet: event packet to process.
|
||||
* @ifidx: index of the firmware interface (may change).
|
||||
*
|
||||
* If the packet buffer contains a firmware event message it will
|
||||
* dispatch the event to a registered handler (using worker).
|
||||
*/
|
||||
void brcmf_fweh_process_event(struct brcmf_pub *drvr,
|
||||
struct brcmf_event *event_packet, u8 *ifidx)
|
||||
{
|
||||
enum brcmf_fweh_event_code code;
|
||||
struct brcmf_fweh_info *fweh = &drvr->fweh;
|
||||
struct brcmf_fweh_queue_item *event;
|
||||
gfp_t alloc_flag = GFP_KERNEL;
|
||||
void *data;
|
||||
u32 datalen;
|
||||
|
||||
/* get event info */
|
||||
code = get_unaligned_be32(&event_packet->msg.event_type);
|
||||
datalen = get_unaligned_be32(&event_packet->msg.datalen);
|
||||
*ifidx = event_packet->msg.ifidx;
|
||||
data = &event_packet[1];
|
||||
|
||||
if (code >= BRCMF_E_LAST)
|
||||
return;
|
||||
|
||||
if (code != BRCMF_E_IF && !fweh->evt_handler[code])
|
||||
return;
|
||||
|
||||
if (in_interrupt())
|
||||
alloc_flag = GFP_ATOMIC;
|
||||
|
||||
event = kzalloc(sizeof(*event) + datalen, alloc_flag);
|
||||
if (!event)
|
||||
return;
|
||||
|
||||
event->code = code;
|
||||
event->ifidx = *ifidx;
|
||||
|
||||
/* use memcpy to get aligned event message */
|
||||
memcpy(&event->emsg, &event_packet->msg, sizeof(event->emsg));
|
||||
memcpy(event->data, data, datalen);
|
||||
memcpy(event->ifaddr, event_packet->eth.h_dest, ETH_ALEN);
|
||||
|
||||
brcmf_fweh_queue_event(fweh, event);
|
||||
}
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Broadcom Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FWEH_H_
|
||||
#define FWEH_H_
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if.h>
|
||||
|
||||
/* formward declarations */
|
||||
struct brcmf_pub;
|
||||
struct brcmf_if;
|
||||
struct brcmf_cfg80211_info;
|
||||
struct brcmf_event;
|
||||
|
||||
/* firmware event codes sent by the dongle */
|
||||
enum brcmf_fweh_event_code {
|
||||
BRCMF_E_SET_SSID = 0,
|
||||
BRCMF_E_JOIN = 1,
|
||||
BRCMF_E_START = 2,
|
||||
BRCMF_E_AUTH = 3,
|
||||
BRCMF_E_AUTH_IND = 4,
|
||||
BRCMF_E_DEAUTH = 5,
|
||||
BRCMF_E_DEAUTH_IND = 6,
|
||||
BRCMF_E_ASSOC = 7,
|
||||
BRCMF_E_ASSOC_IND = 8,
|
||||
BRCMF_E_REASSOC = 9,
|
||||
BRCMF_E_REASSOC_IND = 10,
|
||||
BRCMF_E_DISASSOC = 11,
|
||||
BRCMF_E_DISASSOC_IND = 12,
|
||||
BRCMF_E_QUIET_START = 13,
|
||||
BRCMF_E_QUIET_END = 14,
|
||||
BRCMF_E_BEACON_RX = 15,
|
||||
BRCMF_E_LINK = 16,
|
||||
BRCMF_E_MIC_ERROR = 17,
|
||||
BRCMF_E_NDIS_LINK = 18,
|
||||
BRCMF_E_ROAM = 19,
|
||||
BRCMF_E_TXFAIL = 20,
|
||||
BRCMF_E_PMKID_CACHE = 21,
|
||||
BRCMF_E_RETROGRADE_TSF = 22,
|
||||
BRCMF_E_PRUNE = 23,
|
||||
BRCMF_E_AUTOAUTH = 24,
|
||||
BRCMF_E_EAPOL_MSG = 25,
|
||||
BRCMF_E_SCAN_COMPLETE = 26,
|
||||
BRCMF_E_ADDTS_IND = 27,
|
||||
BRCMF_E_DELTS_IND = 28,
|
||||
BRCMF_E_BCNSENT_IND = 29,
|
||||
BRCMF_E_BCNRX_MSG = 30,
|
||||
BRCMF_E_BCNLOST_MSG = 31,
|
||||
BRCMF_E_ROAM_PREP = 32,
|
||||
BRCMF_E_PFN_NET_FOUND = 33,
|
||||
BRCMF_E_PFN_NET_LOST = 34,
|
||||
BRCMF_E_RESET_COMPLETE = 35,
|
||||
BRCMF_E_JOIN_START = 36,
|
||||
BRCMF_E_ROAM_START = 37,
|
||||
BRCMF_E_ASSOC_START = 38,
|
||||
BRCMF_E_IBSS_ASSOC = 39,
|
||||
BRCMF_E_RADIO = 40,
|
||||
BRCMF_E_PSM_WATCHDOG = 41,
|
||||
BRCMF_E_PROBREQ_MSG = 44,
|
||||
BRCMF_E_SCAN_CONFIRM_IND = 45,
|
||||
BRCMF_E_PSK_SUP = 46,
|
||||
BRCMF_E_COUNTRY_CODE_CHANGED = 47,
|
||||
BRCMF_E_EXCEEDED_MEDIUM_TIME = 48,
|
||||
BRCMF_E_ICV_ERROR = 49,
|
||||
BRCMF_E_UNICAST_DECODE_ERROR = 50,
|
||||
BRCMF_E_MULTICAST_DECODE_ERROR = 51,
|
||||
BRCMF_E_TRACE = 52,
|
||||
BRCMF_E_IF = 54,
|
||||
BRCMF_E_RSSI = 56,
|
||||
BRCMF_E_PFN_SCAN_COMPLETE = 57,
|
||||
BRCMF_E_EXTLOG_MSG = 58,
|
||||
BRCMF_E_ACTION_FRAME = 59,
|
||||
BRCMF_E_ACTION_FRAME_COMPLETE = 60,
|
||||
BRCMF_E_PRE_ASSOC_IND = 61,
|
||||
BRCMF_E_PRE_REASSOC_IND = 62,
|
||||
BRCMF_E_CHANNEL_ADOPTED = 63,
|
||||
BRCMF_E_AP_STARTED = 64,
|
||||
BRCMF_E_DFS_AP_STOP = 65,
|
||||
BRCMF_E_DFS_AP_RESUME = 66,
|
||||
BRCMF_E_ESCAN_RESULT = 69,
|
||||
BRCMF_E_ACTION_FRAME_OFF_CHAN_COMPLETE = 70,
|
||||
BRCMF_E_DCS_REQUEST = 73,
|
||||
BRCMF_E_FIFO_CREDIT_MAP = 74,
|
||||
BRCMF_E_LAST
|
||||
};
|
||||
|
||||
/* flags field values in struct brcmf_event_msg */
|
||||
#define BRCMF_EVENT_MSG_LINK 0x01
|
||||
#define BRCMF_EVENT_MSG_FLUSHTXQ 0x02
|
||||
#define BRCMF_EVENT_MSG_GROUP 0x04
|
||||
|
||||
/**
|
||||
* definitions for event packet validation.
|
||||
*/
|
||||
#define BRCMF_EVENT_OUI_OFFSET 19
|
||||
#define BRCM_OUI "\x00\x10\x18"
|
||||
#define DOT11_OUI_LEN 3
|
||||
#define BCMILCP_BCM_SUBTYPE_EVENT 1
|
||||
|
||||
|
||||
/**
|
||||
* struct brcmf_event_msg - firmware event message.
|
||||
*
|
||||
* @version: version information.
|
||||
* @flags: event flags.
|
||||
* @event_code: firmware event code.
|
||||
* @status: status information.
|
||||
* @reason: reason code.
|
||||
* @auth_type: authentication type.
|
||||
* @datalen: lenght of event data buffer.
|
||||
* @addr: ether address.
|
||||
* @ifname: interface name.
|
||||
* @ifidx: interface index.
|
||||
* @bsscfgidx: bsscfg index.
|
||||
*/
|
||||
struct brcmf_event_msg {
|
||||
u16 version;
|
||||
u16 flags;
|
||||
u32 event_code;
|
||||
u32 status;
|
||||
u32 reason;
|
||||
s32 auth_type;
|
||||
u32 datalen;
|
||||
u8 addr[ETH_ALEN];
|
||||
char ifname[IFNAMSIZ];
|
||||
u8 ifidx;
|
||||
u8 bsscfgidx;
|
||||
};
|
||||
|
||||
typedef int (*brcmf_fweh_handler_t)(struct brcmf_if *ifp,
|
||||
const struct brcmf_event_msg *evtmsg,
|
||||
void *data);
|
||||
|
||||
/**
|
||||
* struct brcmf_fweh_info - firmware event handling information.
|
||||
*
|
||||
* @event_work: event worker.
|
||||
* @evt_q_lock: lock for event queue protection.
|
||||
* @event_q: event queue.
|
||||
* @evt_handler: registered event handlers.
|
||||
*/
|
||||
struct brcmf_fweh_info {
|
||||
struct work_struct event_work;
|
||||
struct spinlock evt_q_lock;
|
||||
struct list_head event_q;
|
||||
int (*evt_handler[BRCMF_E_LAST])(struct brcmf_if *ifp,
|
||||
const struct brcmf_event_msg *evtmsg,
|
||||
void *data);
|
||||
};
|
||||
|
||||
void brcmf_fweh_attach(struct brcmf_pub *drvr);
|
||||
void brcmf_fweh_detach(struct brcmf_pub *drvr);
|
||||
int brcmf_fweh_register(struct brcmf_pub *drvr, enum brcmf_fweh_event_code code,
|
||||
int (*handler)(struct brcmf_if *ifp,
|
||||
const struct brcmf_event_msg *evtmsg,
|
||||
void *data));
|
||||
void brcmf_fweh_unregister(struct brcmf_pub *drvr,
|
||||
enum brcmf_fweh_event_code code);
|
||||
int brcmf_fweh_activate_events(struct brcmf_if *ifp);
|
||||
void brcmf_fweh_process_event(struct brcmf_pub *drvr,
|
||||
struct brcmf_event *event_packet, u8 *ifidx);
|
||||
|
||||
static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr,
|
||||
struct sk_buff *skb, u8 *ifidx)
|
||||
{
|
||||
struct brcmf_event *event_packet;
|
||||
u8 *data;
|
||||
u16 usr_stype;
|
||||
|
||||
/* only process events when protocol matches */
|
||||
if (skb->protocol != cpu_to_be16(ETH_P_LINK_CTL))
|
||||
return;
|
||||
|
||||
/* check for BRCM oui match */
|
||||
event_packet = (struct brcmf_event *)skb_mac_header(skb);
|
||||
data = (u8 *)event_packet;
|
||||
data += BRCMF_EVENT_OUI_OFFSET;
|
||||
if (memcmp(BRCM_OUI, data, DOT11_OUI_LEN))
|
||||
return;
|
||||
|
||||
/* final match on usr_subtype */
|
||||
data += DOT11_OUI_LEN;
|
||||
usr_stype = get_unaligned_be16(data);
|
||||
if (usr_stype != BCMILCP_BCM_SUBTYPE_EVENT)
|
||||
return;
|
||||
|
||||
brcmf_fweh_process_event(drvr, event_packet, ifidx);
|
||||
}
|
||||
|
||||
#endif /* FWEH_H_ */
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <defs.h>
|
||||
#include <brcmu_utils.h>
|
||||
#include <brcmu_wifi.h>
|
||||
#include "dhd.h"
|
||||
|
@ -29,13 +28,16 @@
|
|||
#include "fwil.h"
|
||||
|
||||
|
||||
#define MAX_HEX_DUMP_LEN 64
|
||||
|
||||
|
||||
static s32
|
||||
brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
|
||||
{
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
s32 err;
|
||||
|
||||
if (drvr->bus_if->state == BRCMF_BUS_DOWN) {
|
||||
if (drvr->bus_if->state != BRCMF_BUS_DATA) {
|
||||
brcmf_dbg(ERROR, "bus is down. we have nothing to do.\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -64,7 +66,8 @@ brcmf_fil_cmd_data_set(struct brcmf_if *ifp, u32 cmd, void *data, u32 len)
|
|||
mutex_lock(&ifp->drvr->proto_block);
|
||||
|
||||
brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len);
|
||||
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data");
|
||||
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
|
||||
min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
|
||||
|
||||
err = brcmf_fil_cmd_data(ifp, cmd, data, len, true);
|
||||
mutex_unlock(&ifp->drvr->proto_block);
|
||||
|
@ -81,7 +84,8 @@ brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len)
|
|||
err = brcmf_fil_cmd_data(ifp, cmd, data, len, false);
|
||||
|
||||
brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len);
|
||||
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data");
|
||||
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
|
||||
min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
|
||||
|
||||
mutex_unlock(&ifp->drvr->proto_block);
|
||||
|
||||
|
@ -147,7 +151,8 @@ brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, void *data,
|
|||
mutex_lock(&drvr->proto_block);
|
||||
|
||||
brcmf_dbg(FIL, "name=%s, len=%d\n", name, len);
|
||||
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data");
|
||||
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
|
||||
min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
|
||||
|
||||
buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf,
|
||||
sizeof(drvr->proto_buf));
|
||||
|
@ -186,7 +191,8 @@ brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data,
|
|||
}
|
||||
|
||||
brcmf_dbg(FIL, "name=%s, len=%d\n", name, len);
|
||||
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data");
|
||||
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
|
||||
min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
|
||||
|
||||
mutex_unlock(&drvr->proto_block);
|
||||
return err;
|
||||
|
@ -268,7 +274,8 @@ brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name,
|
|||
mutex_lock(&drvr->proto_block);
|
||||
|
||||
brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len);
|
||||
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data");
|
||||
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
|
||||
min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
|
||||
|
||||
buflen = brcmf_create_bsscfg(ifp->bssidx, name, data, len,
|
||||
drvr->proto_buf, sizeof(drvr->proto_buf));
|
||||
|
@ -294,7 +301,7 @@ brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name,
|
|||
|
||||
mutex_lock(&drvr->proto_block);
|
||||
|
||||
buflen = brcmf_create_bsscfg(ifp->bssidx, name, NULL, len,
|
||||
buflen = brcmf_create_bsscfg(ifp->bssidx, name, data, len,
|
||||
drvr->proto_buf, sizeof(drvr->proto_buf));
|
||||
if (buflen) {
|
||||
err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf,
|
||||
|
@ -306,7 +313,8 @@ brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name,
|
|||
brcmf_dbg(ERROR, "Creating bsscfg failed\n");
|
||||
}
|
||||
brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len);
|
||||
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data");
|
||||
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
|
||||
min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
|
||||
|
||||
mutex_unlock(&drvr->proto_block);
|
||||
return err;
|
||||
|
|
|
@ -14,24 +14,12 @@
|
|||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <net/cfg80211.h>
|
||||
|
||||
#include <defs.h>
|
||||
#include <brcmu_utils.h>
|
||||
#include <brcmu_wifi.h>
|
||||
#include <dhd_bus.h>
|
||||
|
@ -42,13 +30,11 @@
|
|||
|
||||
#define IOCTL_RESP_TIMEOUT 2000
|
||||
|
||||
#define BRCMF_USB_DLIMAGE_SPINWAIT 100 /* in unit of ms */
|
||||
#define BRCMF_USB_DLIMAGE_LIMIT 500 /* spinwait limit (ms) */
|
||||
#define BRCMF_USB_RESET_GETVER_SPINWAIT 100 /* in unit of ms */
|
||||
#define BRCMF_USB_RESET_GETVER_LOOP_CNT 10
|
||||
|
||||
#define BRCMF_POSTBOOT_ID 0xA123 /* ID to detect if dongle
|
||||
has boot up */
|
||||
#define BRCMF_USB_RESETCFG_SPINWAIT 1 /* wait after resetcfg (ms) */
|
||||
|
||||
#define BRCMF_USB_NRXQ 50
|
||||
#define BRCMF_USB_NTXQ 50
|
||||
|
||||
|
@ -69,16 +55,6 @@
|
|||
#define BRCMF_USB_43236_FW_NAME "brcm/brcmfmac43236b.bin"
|
||||
#define BRCMF_USB_43242_FW_NAME "brcm/brcmfmac43242a.bin"
|
||||
|
||||
enum usbdev_suspend_state {
|
||||
USBOS_SUSPEND_STATE_DEVICE_ACTIVE = 0, /* Device is busy, won't allow
|
||||
suspend */
|
||||
USBOS_SUSPEND_STATE_SUSPEND_PENDING, /* Device is idle, can be
|
||||
* suspended. Wating PM to
|
||||
* suspend the device
|
||||
*/
|
||||
USBOS_SUSPEND_STATE_SUSPENDED /* Device suspended */
|
||||
};
|
||||
|
||||
struct brcmf_usb_image {
|
||||
struct list_head list;
|
||||
s8 *fwname;
|
||||
|
@ -99,10 +75,8 @@ struct brcmf_usbdev_info {
|
|||
struct list_head rx_postq;
|
||||
struct list_head tx_freeq;
|
||||
struct list_head tx_postq;
|
||||
enum usbdev_suspend_state suspend_state;
|
||||
uint rx_pipe, tx_pipe, intr_pipe, rx_pipe2;
|
||||
|
||||
bool activity;
|
||||
int rx_low_watermark;
|
||||
int tx_low_watermark;
|
||||
int tx_high_watermark;
|
||||
|
@ -170,6 +144,7 @@ static void brcmf_usb_ioctl_resp_wake(struct brcmf_usbdev_info *devinfo)
|
|||
static void
|
||||
brcmf_usb_ctl_complete(struct brcmf_usbdev_info *devinfo, int type, int status)
|
||||
{
|
||||
brcmf_dbg(USB, "Enter, status=%d\n", status);
|
||||
|
||||
if (unlikely(devinfo == NULL))
|
||||
return;
|
||||
|
@ -197,6 +172,7 @@ brcmf_usb_ctlread_complete(struct urb *urb)
|
|||
struct brcmf_usbdev_info *devinfo =
|
||||
(struct brcmf_usbdev_info *)urb->context;
|
||||
|
||||
brcmf_dbg(USB, "Enter\n");
|
||||
devinfo->ctl_urb_actual_length = urb->actual_length;
|
||||
brcmf_usb_ctl_complete(devinfo, BRCMF_USB_CBCTL_READ,
|
||||
urb->status);
|
||||
|
@ -208,33 +184,22 @@ brcmf_usb_ctlwrite_complete(struct urb *urb)
|
|||
struct brcmf_usbdev_info *devinfo =
|
||||
(struct brcmf_usbdev_info *)urb->context;
|
||||
|
||||
brcmf_dbg(USB, "Enter\n");
|
||||
brcmf_usb_ctl_complete(devinfo, BRCMF_USB_CBCTL_WRITE,
|
||||
urb->status);
|
||||
}
|
||||
|
||||
static int brcmf_usb_pnp(struct brcmf_usbdev_info *devinfo, uint state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
brcmf_usb_send_ctl(struct brcmf_usbdev_info *devinfo, u8 *buf, int len)
|
||||
{
|
||||
int ret;
|
||||
u16 size;
|
||||
|
||||
brcmf_dbg(USB, "Enter\n");
|
||||
if (devinfo == NULL || buf == NULL ||
|
||||
len == 0 || devinfo->ctl_urb == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
/* If the USB/HSIC bus in sleep state, wake it up */
|
||||
if (devinfo->suspend_state == USBOS_SUSPEND_STATE_SUSPENDED)
|
||||
if (brcmf_usb_pnp(devinfo, BCMFMAC_USB_PNP_RESUME) != 0) {
|
||||
brcmf_dbg(ERROR, "Could not Resume the bus!\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
devinfo->activity = true;
|
||||
size = len;
|
||||
devinfo->ctl_write.wLength = cpu_to_le16p(&size);
|
||||
devinfo->ctl_urb->transfer_buffer_length = size;
|
||||
|
@ -262,6 +227,7 @@ brcmf_usb_recv_ctl(struct brcmf_usbdev_info *devinfo, u8 *buf, int len)
|
|||
int ret;
|
||||
u16 size;
|
||||
|
||||
brcmf_dbg(USB, "Enter\n");
|
||||
if ((devinfo == NULL) || (buf == NULL) || (len == 0)
|
||||
|| (devinfo->ctl_urb == NULL))
|
||||
return -EINVAL;
|
||||
|
@ -295,10 +261,9 @@ static int brcmf_usb_tx_ctlpkt(struct device *dev, u8 *buf, u32 len)
|
|||
int timeout = 0;
|
||||
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
|
||||
|
||||
if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
|
||||
/* TODO: handle suspend/resume */
|
||||
brcmf_dbg(USB, "Enter\n");
|
||||
if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (test_and_set_bit(0, &devinfo->ctl_op))
|
||||
return -EIO;
|
||||
|
@ -325,10 +290,10 @@ static int brcmf_usb_rx_ctlpkt(struct device *dev, u8 *buf, u32 len)
|
|||
int timeout = 0;
|
||||
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
|
||||
|
||||
if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
|
||||
/* TODO: handle suspend/resume */
|
||||
brcmf_dbg(USB, "Enter\n");
|
||||
if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (test_and_set_bit(0, &devinfo->ctl_op))
|
||||
return -EIO;
|
||||
|
||||
|
@ -453,6 +418,8 @@ static void brcmf_usb_tx_complete(struct urb *urb)
|
|||
struct brcmf_usbreq *req = (struct brcmf_usbreq *)urb->context;
|
||||
struct brcmf_usbdev_info *devinfo = req->devinfo;
|
||||
|
||||
brcmf_dbg(USB, "Enter, urb->status=%d, skb=%p\n", urb->status,
|
||||
req->skb);
|
||||
brcmf_usb_del_fromq(devinfo, req);
|
||||
if (urb->status == 0)
|
||||
devinfo->bus_pub.bus->dstats.tx_packets++;
|
||||
|
@ -478,6 +445,7 @@ static void brcmf_usb_rx_complete(struct urb *urb)
|
|||
struct sk_buff *skb;
|
||||
int ifidx = 0;
|
||||
|
||||
brcmf_dbg(USB, "Enter, urb->status=%d\n", urb->status);
|
||||
brcmf_usb_del_fromq(devinfo, req);
|
||||
skb = req->skb;
|
||||
req->skb = NULL;
|
||||
|
@ -491,7 +459,7 @@ static void brcmf_usb_rx_complete(struct urb *urb)
|
|||
return;
|
||||
}
|
||||
|
||||
if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP) {
|
||||
if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) {
|
||||
skb_put(skb, urb->actual_length);
|
||||
if (brcmf_proto_hdrpull(devinfo->dev, &ifidx, skb) != 0) {
|
||||
brcmf_dbg(ERROR, "rx protocol error\n");
|
||||
|
@ -544,8 +512,8 @@ static void brcmf_usb_rx_fill_all(struct brcmf_usbdev_info *devinfo)
|
|||
{
|
||||
struct brcmf_usbreq *req;
|
||||
|
||||
if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
|
||||
brcmf_dbg(ERROR, "bus is not up\n");
|
||||
if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) {
|
||||
brcmf_dbg(ERROR, "bus is not up=%d\n", devinfo->bus_pub.state);
|
||||
return;
|
||||
}
|
||||
while ((req = brcmf_usb_deq(devinfo, &devinfo->rx_freeq, NULL)) != NULL)
|
||||
|
@ -558,29 +526,24 @@ brcmf_usb_state_change(struct brcmf_usbdev_info *devinfo, int state)
|
|||
struct brcmf_bus *bcmf_bus = devinfo->bus_pub.bus;
|
||||
int old_state;
|
||||
|
||||
brcmf_dbg(USB, "Enter, current state=%d, new state=%d\n",
|
||||
devinfo->bus_pub.state, state);
|
||||
|
||||
if (devinfo->bus_pub.state == state)
|
||||
return;
|
||||
|
||||
old_state = devinfo->bus_pub.state;
|
||||
brcmf_dbg(TRACE, "dbus state change from %d to to %d\n",
|
||||
old_state, state);
|
||||
|
||||
/* Don't update state if it's PnP firmware re-download */
|
||||
if (state != BCMFMAC_USB_STATE_PNP_FWDL) /* TODO */
|
||||
devinfo->bus_pub.state = state;
|
||||
|
||||
if ((old_state == BCMFMAC_USB_STATE_SLEEP)
|
||||
&& (state == BCMFMAC_USB_STATE_UP)) {
|
||||
brcmf_usb_rx_fill_all(devinfo);
|
||||
}
|
||||
devinfo->bus_pub.state = state;
|
||||
|
||||
/* update state of upper layer */
|
||||
if (state == BCMFMAC_USB_STATE_DOWN) {
|
||||
brcmf_dbg(INFO, "DBUS is down\n");
|
||||
if (state == BRCMFMAC_USB_STATE_DOWN) {
|
||||
brcmf_dbg(USB, "DBUS is down\n");
|
||||
bcmf_bus->state = BRCMF_BUS_DOWN;
|
||||
} else if (state == BRCMFMAC_USB_STATE_UP) {
|
||||
brcmf_dbg(USB, "DBUS is up\n");
|
||||
bcmf_bus->state = BRCMF_BUS_DATA;
|
||||
} else {
|
||||
brcmf_dbg(INFO, "DBUS current state=%d\n", state);
|
||||
brcmf_dbg(USB, "DBUS current state=%d\n", state);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -589,30 +552,32 @@ brcmf_usb_intr_complete(struct urb *urb)
|
|||
{
|
||||
struct brcmf_usbdev_info *devinfo =
|
||||
(struct brcmf_usbdev_info *)urb->context;
|
||||
bool killed;
|
||||
int err;
|
||||
|
||||
brcmf_dbg(USB, "Enter, urb->status=%d\n", urb->status);
|
||||
|
||||
if (devinfo == NULL)
|
||||
return;
|
||||
|
||||
if (unlikely(urb->status)) {
|
||||
if (devinfo->suspend_state ==
|
||||
USBOS_SUSPEND_STATE_SUSPEND_PENDING)
|
||||
killed = true;
|
||||
|
||||
if ((urb->status == -ENOENT && (!killed))
|
||||
|| urb->status == -ESHUTDOWN ||
|
||||
urb->status == -ENODEV) {
|
||||
brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_DOWN);
|
||||
if (urb->status == -ENOENT ||
|
||||
urb->status == -ESHUTDOWN ||
|
||||
urb->status == -ENODEV) {
|
||||
brcmf_usb_state_change(devinfo,
|
||||
BRCMFMAC_USB_STATE_DOWN);
|
||||
}
|
||||
}
|
||||
|
||||
if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_DOWN) {
|
||||
if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_DOWN) {
|
||||
brcmf_dbg(ERROR, "intr cb when DBUS down, ignoring\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP)
|
||||
usb_submit_urb(devinfo->intr_urb, GFP_ATOMIC);
|
||||
if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) {
|
||||
err = usb_submit_urb(devinfo->intr_urb, GFP_ATOMIC);
|
||||
if (err)
|
||||
brcmf_dbg(ERROR, "usb_submit_urb, err=%d\n", err);
|
||||
}
|
||||
}
|
||||
|
||||
static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
|
||||
|
@ -621,10 +586,9 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
|
|||
struct brcmf_usbreq *req;
|
||||
int ret;
|
||||
|
||||
if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
|
||||
/* TODO: handle suspend/resume */
|
||||
brcmf_dbg(USB, "Enter, skb=%p\n", skb);
|
||||
if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq,
|
||||
&devinfo->tx_freecount);
|
||||
|
@ -664,25 +628,16 @@ static int brcmf_usb_up(struct device *dev)
|
|||
{
|
||||
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
|
||||
u16 ifnum;
|
||||
int ret;
|
||||
|
||||
if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP)
|
||||
brcmf_dbg(USB, "Enter\n");
|
||||
if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP)
|
||||
return 0;
|
||||
|
||||
/* If the USB/HSIC bus in sleep state, wake it up */
|
||||
if (devinfo->suspend_state == USBOS_SUSPEND_STATE_SUSPENDED) {
|
||||
if (brcmf_usb_pnp(devinfo, BCMFMAC_USB_PNP_RESUME) != 0) {
|
||||
brcmf_dbg(ERROR, "Could not Resume the bus!\n");
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
devinfo->activity = true;
|
||||
|
||||
/* Success, indicate devinfo is fully up */
|
||||
brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_UP);
|
||||
brcmf_usb_state_change(devinfo, BRCMFMAC_USB_STATE_UP);
|
||||
|
||||
if (devinfo->intr_urb) {
|
||||
int ret;
|
||||
|
||||
usb_fill_int_urb(devinfo->intr_urb, devinfo->usbdev,
|
||||
devinfo->intr_pipe,
|
||||
&devinfo->intr,
|
||||
|
@ -727,14 +682,14 @@ static void brcmf_usb_down(struct device *dev)
|
|||
{
|
||||
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
|
||||
|
||||
brcmf_dbg(USB, "Enter\n");
|
||||
if (devinfo == NULL)
|
||||
return;
|
||||
|
||||
brcmf_dbg(TRACE, "enter\n");
|
||||
if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_DOWN)
|
||||
if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_DOWN)
|
||||
return;
|
||||
|
||||
brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_DOWN);
|
||||
brcmf_usb_state_change(devinfo, BRCMFMAC_USB_STATE_DOWN);
|
||||
if (devinfo->intr_urb)
|
||||
usb_kill_urb(devinfo->intr_urb);
|
||||
|
||||
|
@ -808,27 +763,25 @@ brcmf_usb_dlneeded(struct brcmf_usbdev_info *devinfo)
|
|||
struct bootrom_id_le id;
|
||||
u32 chipid, chiprev;
|
||||
|
||||
brcmf_dbg(TRACE, "enter\n");
|
||||
brcmf_dbg(USB, "Enter\n");
|
||||
|
||||
if (devinfo == NULL)
|
||||
return false;
|
||||
|
||||
/* Check if firmware downloaded already by querying runtime ID */
|
||||
id.chip = cpu_to_le32(0xDEAD);
|
||||
brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id,
|
||||
sizeof(struct bootrom_id_le));
|
||||
brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id, sizeof(id));
|
||||
|
||||
chipid = le32_to_cpu(id.chip);
|
||||
chiprev = le32_to_cpu(id.chiprev);
|
||||
|
||||
if ((chipid & 0x4300) == 0x4300)
|
||||
brcmf_dbg(INFO, "chip %x rev 0x%x\n", chipid, chiprev);
|
||||
brcmf_dbg(USB, "chip %x rev 0x%x\n", chipid, chiprev);
|
||||
else
|
||||
brcmf_dbg(INFO, "chip %d rev 0x%x\n", chipid, chiprev);
|
||||
brcmf_dbg(USB, "chip %d rev 0x%x\n", chipid, chiprev);
|
||||
if (chipid == BRCMF_POSTBOOT_ID) {
|
||||
brcmf_dbg(INFO, "firmware already downloaded\n");
|
||||
brcmf_usb_dl_cmd(devinfo, DL_RESETCFG, &id,
|
||||
sizeof(struct bootrom_id_le));
|
||||
brcmf_dbg(USB, "firmware already downloaded\n");
|
||||
brcmf_usb_dl_cmd(devinfo, DL_RESETCFG, &id, sizeof(id));
|
||||
return false;
|
||||
} else {
|
||||
devinfo->bus_pub.devid = chipid;
|
||||
|
@ -841,38 +794,29 @@ static int
|
|||
brcmf_usb_resetcfg(struct brcmf_usbdev_info *devinfo)
|
||||
{
|
||||
struct bootrom_id_le id;
|
||||
u16 wait = 0, wait_time;
|
||||
u32 loop_cnt;
|
||||
|
||||
brcmf_dbg(TRACE, "enter\n");
|
||||
brcmf_dbg(USB, "Enter\n");
|
||||
|
||||
if (devinfo == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
/* Give dongle chance to boot */
|
||||
wait_time = BRCMF_USB_DLIMAGE_SPINWAIT;
|
||||
while (wait < BRCMF_USB_DLIMAGE_LIMIT) {
|
||||
mdelay(wait_time);
|
||||
wait += wait_time;
|
||||
loop_cnt = 0;
|
||||
do {
|
||||
mdelay(BRCMF_USB_RESET_GETVER_SPINWAIT);
|
||||
loop_cnt++;
|
||||
id.chip = cpu_to_le32(0xDEAD); /* Get the ID */
|
||||
brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id,
|
||||
sizeof(struct bootrom_id_le));
|
||||
brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id, sizeof(id));
|
||||
if (id.chip == cpu_to_le32(BRCMF_POSTBOOT_ID))
|
||||
break;
|
||||
}
|
||||
} while (loop_cnt < BRCMF_USB_RESET_GETVER_LOOP_CNT);
|
||||
|
||||
if (id.chip == cpu_to_le32(BRCMF_POSTBOOT_ID)) {
|
||||
brcmf_dbg(INFO, "download done %d ms postboot chip 0x%x/rev 0x%x\n",
|
||||
wait, le32_to_cpu(id.chip), le32_to_cpu(id.chiprev));
|
||||
brcmf_dbg(USB, "postboot chip 0x%x/rev 0x%x\n",
|
||||
le32_to_cpu(id.chip), le32_to_cpu(id.chiprev));
|
||||
|
||||
brcmf_usb_dl_cmd(devinfo, DL_RESETCFG, &id,
|
||||
sizeof(struct bootrom_id_le));
|
||||
|
||||
/* XXX this wait may not be necessary */
|
||||
mdelay(BRCMF_USB_RESETCFG_SPINWAIT);
|
||||
brcmf_usb_dl_cmd(devinfo, DL_RESETCFG, &id, sizeof(id));
|
||||
return 0;
|
||||
} else {
|
||||
brcmf_dbg(ERROR, "Cannot talk to Dongle. Firmware is not UP, %d ms\n",
|
||||
wait);
|
||||
BRCMF_USB_RESET_GETVER_SPINWAIT * loop_cnt);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
@ -911,7 +855,8 @@ brcmf_usb_dl_writeimage(struct brcmf_usbdev_info *devinfo, u8 *fw, int fwlen)
|
|||
struct rdl_state_le state;
|
||||
u32 rdlstate, rdlbytes;
|
||||
int err = 0;
|
||||
brcmf_dbg(TRACE, "fw %p, len %d\n", fw, fwlen);
|
||||
|
||||
brcmf_dbg(USB, "Enter, fw %p, len %d\n", fw, fwlen);
|
||||
|
||||
bulkchunk = kmalloc(RDL_CHUNK, GFP_ATOMIC);
|
||||
if (bulkchunk == NULL) {
|
||||
|
@ -986,7 +931,7 @@ brcmf_usb_dl_writeimage(struct brcmf_usbdev_info *devinfo, u8 *fw, int fwlen)
|
|||
|
||||
fail:
|
||||
kfree(bulkchunk);
|
||||
brcmf_dbg(TRACE, "err=%d\n", err);
|
||||
brcmf_dbg(USB, "Exit, err=%d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -994,7 +939,7 @@ static int brcmf_usb_dlstart(struct brcmf_usbdev_info *devinfo, u8 *fw, int len)
|
|||
{
|
||||
int err;
|
||||
|
||||
brcmf_dbg(TRACE, "enter\n");
|
||||
brcmf_dbg(USB, "Enter\n");
|
||||
|
||||
if (devinfo == NULL)
|
||||
return -EINVAL;
|
||||
|
@ -1004,10 +949,10 @@ static int brcmf_usb_dlstart(struct brcmf_usbdev_info *devinfo, u8 *fw, int len)
|
|||
|
||||
err = brcmf_usb_dl_writeimage(devinfo, fw, len);
|
||||
if (err == 0)
|
||||
devinfo->bus_pub.state = BCMFMAC_USB_STATE_DL_DONE;
|
||||
devinfo->bus_pub.state = BRCMFMAC_USB_STATE_DL_DONE;
|
||||
else
|
||||
devinfo->bus_pub.state = BCMFMAC_USB_STATE_DL_PENDING;
|
||||
brcmf_dbg(TRACE, "exit: err=%d\n", err);
|
||||
devinfo->bus_pub.state = BRCMFMAC_USB_STATE_DL_FAIL;
|
||||
brcmf_dbg(USB, "Exit, err=%d\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -1016,7 +961,7 @@ static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo)
|
|||
{
|
||||
struct rdl_state_le state;
|
||||
|
||||
brcmf_dbg(TRACE, "enter\n");
|
||||
brcmf_dbg(USB, "Enter\n");
|
||||
if (!devinfo)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -1039,7 +984,7 @@ static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo)
|
|||
brcmf_dbg(ERROR, "Dongle not runnable\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
brcmf_dbg(TRACE, "exit\n");
|
||||
brcmf_dbg(USB, "Exit\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1066,7 +1011,7 @@ brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo)
|
|||
int devid, chiprev;
|
||||
int err;
|
||||
|
||||
brcmf_dbg(TRACE, "enter\n");
|
||||
brcmf_dbg(USB, "Enter\n");
|
||||
if (devinfo == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
|
@ -1094,7 +1039,7 @@ brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo)
|
|||
|
||||
static void brcmf_usb_detach(struct brcmf_usbdev_info *devinfo)
|
||||
{
|
||||
brcmf_dbg(TRACE, "devinfo %p\n", devinfo);
|
||||
brcmf_dbg(USB, "Enter, devinfo %p\n", devinfo);
|
||||
|
||||
/* free the URBS */
|
||||
brcmf_usb_free_q(&devinfo->rx_freeq, false);
|
||||
|
@ -1129,6 +1074,7 @@ static int check_file(const u8 *headers)
|
|||
struct trx_header_le *trx;
|
||||
int actual_len = -1;
|
||||
|
||||
brcmf_dbg(USB, "Enter\n");
|
||||
/* Extract trx header */
|
||||
trx = (struct trx_header_le *) headers;
|
||||
if (trx->magic != cpu_to_le32(TRX_MAGIC))
|
||||
|
@ -1150,6 +1096,7 @@ static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo)
|
|||
struct brcmf_usb_image *fw_image;
|
||||
int err;
|
||||
|
||||
brcmf_dbg(USB, "Enter\n");
|
||||
switch (devinfo->bus_pub.devid) {
|
||||
case 43143:
|
||||
fwname = BRCMF_USB_43143_FW_NAME;
|
||||
|
@ -1166,7 +1113,7 @@ static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo)
|
|||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
brcmf_dbg(USB, "Loading FW %s\n", fwname);
|
||||
list_for_each_entry(fw_image, &fw_image_list, list) {
|
||||
if (fw_image->fwname == fwname) {
|
||||
devinfo->image = fw_image->image;
|
||||
|
@ -1211,10 +1158,13 @@ static
|
|||
struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo,
|
||||
int nrxq, int ntxq)
|
||||
{
|
||||
brcmf_dbg(USB, "Enter\n");
|
||||
|
||||
devinfo->bus_pub.nrxq = nrxq;
|
||||
devinfo->rx_low_watermark = nrxq / 2;
|
||||
devinfo->bus_pub.devinfo = devinfo;
|
||||
devinfo->bus_pub.ntxq = ntxq;
|
||||
devinfo->bus_pub.state = BRCMFMAC_USB_STATE_DOWN;
|
||||
|
||||
/* flow control when too many tx urbs posted */
|
||||
devinfo->tx_low_watermark = ntxq / 4;
|
||||
|
@ -1263,7 +1213,7 @@ struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo,
|
|||
if (!brcmf_usb_dlneeded(devinfo))
|
||||
return &devinfo->bus_pub;
|
||||
|
||||
brcmf_dbg(TRACE, "start fw downloading\n");
|
||||
brcmf_dbg(USB, "Start fw downloading\n");
|
||||
if (brcmf_usb_get_fw(devinfo))
|
||||
goto error;
|
||||
|
||||
|
@ -1278,14 +1228,14 @@ error:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo,
|
||||
const char *desc, u32 bustype, u32 hdrlen)
|
||||
static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
|
||||
{
|
||||
struct brcmf_bus *bus = NULL;
|
||||
struct brcmf_usbdev *bus_pub = NULL;
|
||||
int ret;
|
||||
struct device *dev = devinfo->dev;
|
||||
|
||||
brcmf_dbg(USB, "Enter\n");
|
||||
bus_pub = brcmf_usb_attach(devinfo, BRCMF_USB_NRXQ, BRCMF_USB_NTXQ);
|
||||
if (!bus_pub)
|
||||
return -ENODEV;
|
||||
|
@ -1302,14 +1252,13 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo,
|
|||
bus->brcmf_bus_stop = brcmf_usb_down;
|
||||
bus->brcmf_bus_txctl = brcmf_usb_tx_ctlpkt;
|
||||
bus->brcmf_bus_rxctl = brcmf_usb_rx_ctlpkt;
|
||||
bus->type = bustype;
|
||||
bus->bus_priv.usb = bus_pub;
|
||||
dev_set_drvdata(dev, bus);
|
||||
|
||||
/* Attach to the common driver interface */
|
||||
ret = brcmf_attach(hdrlen, dev);
|
||||
ret = brcmf_attach(0, dev);
|
||||
if (ret) {
|
||||
brcmf_dbg(ERROR, "dhd_attach failed\n");
|
||||
brcmf_dbg(ERROR, "brcmf_attach failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -1333,7 +1282,7 @@ brcmf_usb_disconnect_cb(struct brcmf_usbdev_info *devinfo)
|
|||
{
|
||||
if (!devinfo)
|
||||
return;
|
||||
brcmf_dbg(TRACE, "enter: bus_pub %p\n", devinfo);
|
||||
brcmf_dbg(USB, "Enter, bus_pub %p\n", devinfo);
|
||||
|
||||
brcmf_detach(devinfo->dev);
|
||||
kfree(devinfo->bus_pub.bus);
|
||||
|
@ -1351,7 +1300,7 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
|||
u8 endpoint_num;
|
||||
struct brcmf_usbdev_info *devinfo;
|
||||
|
||||
brcmf_dbg(TRACE, "enter\n");
|
||||
brcmf_dbg(USB, "Enter\n");
|
||||
|
||||
devinfo = kzalloc(sizeof(*devinfo), GFP_ATOMIC);
|
||||
if (devinfo == NULL)
|
||||
|
@ -1452,11 +1401,11 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
|||
devinfo->interval = IFEPDESC(usb, CONTROL_IF, 0).bInterval;
|
||||
|
||||
if (usb->speed == USB_SPEED_HIGH)
|
||||
brcmf_dbg(INFO, "Broadcom high speed USB wireless device detected\n");
|
||||
brcmf_dbg(USB, "Broadcom high speed USB wireless device detected\n");
|
||||
else
|
||||
brcmf_dbg(INFO, "Broadcom full speed USB wireless device detected\n");
|
||||
brcmf_dbg(USB, "Broadcom full speed USB wireless device detected\n");
|
||||
|
||||
ret = brcmf_usb_probe_cb(devinfo, "", USB_BUS, 0);
|
||||
ret = brcmf_usb_probe_cb(devinfo);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
|
@ -1476,40 +1425,55 @@ brcmf_usb_disconnect(struct usb_interface *intf)
|
|||
{
|
||||
struct brcmf_usbdev_info *devinfo;
|
||||
|
||||
brcmf_dbg(TRACE, "enter\n");
|
||||
brcmf_dbg(USB, "Enter\n");
|
||||
devinfo = (struct brcmf_usbdev_info *)usb_get_intfdata(intf);
|
||||
brcmf_usb_disconnect_cb(devinfo);
|
||||
kfree(devinfo);
|
||||
brcmf_dbg(USB, "Exit\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* only need to signal the bus being down and update the suspend state.
|
||||
* only need to signal the bus being down and update the state.
|
||||
*/
|
||||
static int brcmf_usb_suspend(struct usb_interface *intf, pm_message_t state)
|
||||
{
|
||||
struct usb_device *usb = interface_to_usbdev(intf);
|
||||
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
|
||||
|
||||
brcmf_dbg(TRACE, "enter\n");
|
||||
devinfo->bus_pub.state = BCMFMAC_USB_STATE_DOWN;
|
||||
devinfo->suspend_state = USBOS_SUSPEND_STATE_SUSPENDED;
|
||||
brcmf_dbg(USB, "Enter\n");
|
||||
devinfo->bus_pub.state = BRCMFMAC_USB_STATE_SLEEP;
|
||||
brcmf_detach(&usb->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* mark suspend state active and crank up the bus.
|
||||
* (re-) start the bus.
|
||||
*/
|
||||
static int brcmf_usb_resume(struct usb_interface *intf)
|
||||
{
|
||||
struct usb_device *usb = interface_to_usbdev(intf);
|
||||
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
|
||||
|
||||
brcmf_dbg(TRACE, "enter\n");
|
||||
devinfo->suspend_state = USBOS_SUSPEND_STATE_DEVICE_ACTIVE;
|
||||
brcmf_bus_start(&usb->dev);
|
||||
brcmf_dbg(USB, "Enter\n");
|
||||
if (!brcmf_attach(0, devinfo->dev))
|
||||
return brcmf_bus_start(&usb->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int brcmf_usb_reset_resume(struct usb_interface *intf)
|
||||
{
|
||||
struct usb_device *usb = interface_to_usbdev(intf);
|
||||
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
|
||||
|
||||
brcmf_dbg(USB, "Enter\n");
|
||||
|
||||
if (!brcmf_usb_fw_download(devinfo))
|
||||
return brcmf_usb_resume(intf);
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
#define BRCMF_USB_VENDOR_ID_BROADCOM 0x0a5c
|
||||
#define BRCMF_USB_DEVICE_ID_43143 0xbd1e
|
||||
#define BRCMF_USB_DEVICE_ID_43236 0xbd17
|
||||
|
@ -1529,7 +1493,6 @@ MODULE_FIRMWARE(BRCMF_USB_43143_FW_NAME);
|
|||
MODULE_FIRMWARE(BRCMF_USB_43236_FW_NAME);
|
||||
MODULE_FIRMWARE(BRCMF_USB_43242_FW_NAME);
|
||||
|
||||
/* TODO: suspend and resume entries */
|
||||
static struct usb_driver brcmf_usbdrvr = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.probe = brcmf_usb_probe,
|
||||
|
@ -1537,6 +1500,7 @@ static struct usb_driver brcmf_usbdrvr = {
|
|||
.id_table = brcmf_usb_devid_table,
|
||||
.suspend = brcmf_usb_suspend,
|
||||
.resume = brcmf_usb_resume,
|
||||
.reset_resume = brcmf_usb_reset_resume,
|
||||
.supports_autosuspend = 1,
|
||||
.disable_hub_initiated_lpm = 1,
|
||||
};
|
||||
|
@ -1554,12 +1518,14 @@ static void brcmf_release_fw(struct list_head *q)
|
|||
|
||||
void brcmf_usb_exit(void)
|
||||
{
|
||||
brcmf_dbg(USB, "Enter\n");
|
||||
usb_deregister(&brcmf_usbdrvr);
|
||||
brcmf_release_fw(&fw_image_list);
|
||||
}
|
||||
|
||||
void brcmf_usb_init(void)
|
||||
{
|
||||
brcmf_dbg(USB, "Enter\n");
|
||||
INIT_LIST_HEAD(&fw_image_list);
|
||||
usb_register(&brcmf_usbdrvr);
|
||||
}
|
||||
|
|
|
@ -17,19 +17,11 @@
|
|||
#define BRCMFMAC_USB_H
|
||||
|
||||
enum brcmf_usb_state {
|
||||
BCMFMAC_USB_STATE_DL_PENDING,
|
||||
BCMFMAC_USB_STATE_DL_DONE,
|
||||
BCMFMAC_USB_STATE_UP,
|
||||
BCMFMAC_USB_STATE_DOWN,
|
||||
BCMFMAC_USB_STATE_PNP_FWDL,
|
||||
BCMFMAC_USB_STATE_DISCONNECT,
|
||||
BCMFMAC_USB_STATE_SLEEP
|
||||
};
|
||||
|
||||
enum brcmf_usb_pnp_state {
|
||||
BCMFMAC_USB_PNP_DISCONNECT,
|
||||
BCMFMAC_USB_PNP_SLEEP,
|
||||
BCMFMAC_USB_PNP_RESUME,
|
||||
BRCMFMAC_USB_STATE_DOWN,
|
||||
BRCMFMAC_USB_STATE_DL_FAIL,
|
||||
BRCMFMAC_USB_STATE_DL_DONE,
|
||||
BRCMFMAC_USB_STATE_UP,
|
||||
BRCMFMAC_USB_STATE_SLEEP
|
||||
};
|
||||
|
||||
struct brcmf_stats {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -84,31 +84,12 @@ do { \
|
|||
#define WL_CONN(fmt, args...)
|
||||
#endif /* (defined DEBUG) */
|
||||
|
||||
#define WL_NUM_SCAN_MAX 1
|
||||
#define WL_NUM_PMKIDS_MAX MAXPMKID /* will be used
|
||||
* for 2.6.33 kernel
|
||||
* or later
|
||||
*/
|
||||
#define WL_SCAN_BUF_MAX (1024 * 8)
|
||||
#define WL_NUM_SCAN_MAX 10
|
||||
#define WL_NUM_PMKIDS_MAX MAXPMKID
|
||||
#define WL_TLV_INFO_MAX 1024
|
||||
#define WL_BSS_INFO_MAX 2048
|
||||
#define WL_ASSOC_INFO_MAX 512 /*
|
||||
* needs to grab assoc info from dongle to
|
||||
* report it to cfg80211 through "connect"
|
||||
* event
|
||||
*/
|
||||
#define WL_DCMD_LEN_MAX 1024
|
||||
#define WL_EXTRA_BUF_MAX 2048
|
||||
#define WL_ISCAN_BUF_MAX 2048 /*
|
||||
* the buf length can be BRCMF_DCMD_MAXLEN
|
||||
* to reduce iteration
|
||||
*/
|
||||
#define WL_ISCAN_TIMER_INTERVAL_MS 3000
|
||||
#define WL_SCAN_ERSULTS_LAST (BRCMF_SCAN_RESULTS_NO_MEM+1)
|
||||
#define WL_AP_MAX 256 /* virtually unlimitted as long
|
||||
* as kernel memory allows
|
||||
*/
|
||||
|
||||
#define WL_ASSOC_INFO_MAX 512 /* assoc related fil max buf */
|
||||
#define WL_EXTRA_BUF_MAX 2048
|
||||
#define WL_ROAM_TRIGGER_LEVEL -75
|
||||
#define WL_ROAM_DELTA 20
|
||||
#define WL_BEACON_TIMEOUT 3
|
||||
|
@ -145,12 +126,6 @@ enum wl_mode {
|
|||
WL_MODE_AP
|
||||
};
|
||||
|
||||
/* dongle iscan state */
|
||||
enum wl_iscan_state {
|
||||
WL_ISCAN_STATE_IDLE,
|
||||
WL_ISCAN_STATE_SCANING
|
||||
};
|
||||
|
||||
/* dongle configuration */
|
||||
struct brcmf_cfg80211_conf {
|
||||
u32 mode; /* adhoc , infrastructure or ap */
|
||||
|
@ -162,17 +137,6 @@ struct brcmf_cfg80211_conf {
|
|||
struct ieee80211_channel channel;
|
||||
};
|
||||
|
||||
/* forward declaration */
|
||||
struct brcmf_cfg80211_info;
|
||||
|
||||
/* cfg80211 main event loop */
|
||||
struct brcmf_cfg80211_event_loop {
|
||||
s32(*handler[BRCMF_E_LAST]) (struct brcmf_cfg80211_info *cfg,
|
||||
struct net_device *ndev,
|
||||
const struct brcmf_event_msg *e,
|
||||
void *data);
|
||||
};
|
||||
|
||||
/* basic structure of scan request */
|
||||
struct brcmf_cfg80211_scan_req {
|
||||
struct brcmf_ssid_le ssid_le;
|
||||
|
@ -184,14 +148,6 @@ struct brcmf_cfg80211_ie {
|
|||
u8 buf[WL_TLV_INFO_MAX];
|
||||
};
|
||||
|
||||
/* event queue for cfg80211 main event */
|
||||
struct brcmf_cfg80211_event_q {
|
||||
struct list_head evt_q_list;
|
||||
u32 etype;
|
||||
struct brcmf_event_msg emsg;
|
||||
s8 edata[1];
|
||||
};
|
||||
|
||||
/* security information with currently associated ap */
|
||||
struct brcmf_cfg80211_security {
|
||||
u32 wpa_versions;
|
||||
|
@ -270,26 +226,6 @@ struct brcmf_cfg80211_vif {
|
|||
struct list_head list;
|
||||
};
|
||||
|
||||
/* dongle iscan event loop */
|
||||
struct brcmf_cfg80211_iscan_eloop {
|
||||
s32 (*handler[WL_SCAN_ERSULTS_LAST])
|
||||
(struct brcmf_cfg80211_info *cfg);
|
||||
};
|
||||
|
||||
/* dongle iscan controller */
|
||||
struct brcmf_cfg80211_iscan_ctrl {
|
||||
struct net_device *ndev;
|
||||
struct timer_list timer;
|
||||
u32 timer_ms;
|
||||
u32 timer_on;
|
||||
s32 state;
|
||||
struct work_struct work;
|
||||
struct brcmf_cfg80211_iscan_eloop el;
|
||||
void *data;
|
||||
s8 dcmd_buf[BRCMF_DCMD_SMLEN];
|
||||
s8 scan_buf[WL_ISCAN_BUF_MAX];
|
||||
};
|
||||
|
||||
/* association inform */
|
||||
struct brcmf_cfg80211_connect_info {
|
||||
u8 *req_ie;
|
||||
|
@ -323,17 +259,6 @@ struct escan_info {
|
|||
struct net_device *ndev;
|
||||
};
|
||||
|
||||
/* Structure to hold WPS, WPA IEs for a AP */
|
||||
struct ap_info {
|
||||
u8 probe_res_ie[IE_MAX_LEN];
|
||||
u8 beacon_ie[IE_MAX_LEN];
|
||||
u32 probe_res_ie_len;
|
||||
u32 beacon_ie_len;
|
||||
u8 *wpa_ie;
|
||||
u8 *rsn_ie;
|
||||
bool security_mode;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_pno_param_le - PNO scan configuration parameters
|
||||
*
|
||||
|
@ -421,24 +346,16 @@ struct brcmf_pno_scanresults_le {
|
|||
* @wiphy: wiphy object for cfg80211 interface.
|
||||
* @conf: dongle configuration.
|
||||
* @scan_request: cfg80211 scan request object.
|
||||
* @el: main event loop.
|
||||
* @evt_q_list: used for event queue.
|
||||
* @evt_q_lock: for event queue synchronization.
|
||||
* @usr_sync: mainly for dongle up/down synchronization.
|
||||
* @bss_list: bss_list holding scanned ap information.
|
||||
* @scan_results: results of the last scan.
|
||||
* @scan_req_int: internal scan request object.
|
||||
* @bss_info: bss information for cfg80211 layer.
|
||||
* @ie: information element object for internal purpose.
|
||||
* @iscan: iscan controller information.
|
||||
* @conn_info: association info.
|
||||
* @pmk_list: wpa2 pmk list.
|
||||
* @event_work: event handler work struct.
|
||||
* @scan_status: scan activity on the dongle.
|
||||
* @pub: common driver information.
|
||||
* @channel: current channel.
|
||||
* @iscan_on: iscan on/off switch.
|
||||
* @iscan_kickstart: indicate iscan already started.
|
||||
* @active_scan: current scan mode.
|
||||
* @sched_escan: e-scan for scheduled scan support running.
|
||||
* @ibss_starter: indicates this sta is ibss starter.
|
||||
|
@ -450,12 +367,10 @@ struct brcmf_pno_scanresults_le {
|
|||
* @dcmd_buf: dcmd buffer.
|
||||
* @extra_buf: mainly to grab assoc information.
|
||||
* @debugfsdir: debugfs folder for this device.
|
||||
* @escan_on: escan on/off switch.
|
||||
* @escan_info: escan information.
|
||||
* @escan_timeout: Timer for catch scan timeout.
|
||||
* @escan_timeout_work: scan timeout worker.
|
||||
* @escan_ioctl_buf: dongle command buffer for escan commands.
|
||||
* @ap_info: host ap information.
|
||||
* @vif_list: linked list of vif instances.
|
||||
* @vif_cnt: number of vif instances.
|
||||
*/
|
||||
|
@ -463,24 +378,16 @@ struct brcmf_cfg80211_info {
|
|||
struct wiphy *wiphy;
|
||||
struct brcmf_cfg80211_conf *conf;
|
||||
struct cfg80211_scan_request *scan_request;
|
||||
struct brcmf_cfg80211_event_loop el;
|
||||
struct list_head evt_q_list;
|
||||
spinlock_t evt_q_lock;
|
||||
struct mutex usr_sync;
|
||||
struct brcmf_scan_results *bss_list;
|
||||
struct brcmf_scan_results *scan_results;
|
||||
struct brcmf_cfg80211_scan_req *scan_req_int;
|
||||
struct brcmf_cfg80211_scan_req scan_req_int;
|
||||
struct wl_cfg80211_bss_info *bss_info;
|
||||
struct brcmf_cfg80211_ie ie;
|
||||
struct brcmf_cfg80211_iscan_ctrl *iscan;
|
||||
struct brcmf_cfg80211_connect_info conn_info;
|
||||
struct brcmf_cfg80211_pmk_list *pmk_list;
|
||||
struct work_struct event_work;
|
||||
unsigned long scan_status;
|
||||
struct brcmf_pub *pub;
|
||||
u32 channel;
|
||||
bool iscan_on;
|
||||
bool iscan_kickstart;
|
||||
bool active_scan;
|
||||
bool sched_escan;
|
||||
bool ibss_starter;
|
||||
|
@ -492,12 +399,10 @@ struct brcmf_cfg80211_info {
|
|||
u8 *dcmd_buf;
|
||||
u8 *extra_buf;
|
||||
struct dentry *debugfsdir;
|
||||
bool escan_on;
|
||||
struct escan_info escan_info;
|
||||
struct timer_list escan_timeout;
|
||||
struct work_struct escan_timeout_work;
|
||||
u8 *escan_ioctl_buf;
|
||||
struct ap_info *ap_info;
|
||||
struct list_head vif_list;
|
||||
u8 vif_cnt;
|
||||
};
|
||||
|
@ -536,8 +441,11 @@ static inline struct brcmf_cfg80211_profile *ndev_to_prof(struct net_device *nd)
|
|||
return &ifp->vif->profile;
|
||||
}
|
||||
|
||||
#define iscan_to_cfg(i) ((struct brcmf_cfg80211_info *)(i->data))
|
||||
#define cfg_to_iscan(w) (w->iscan)
|
||||
static inline struct brcmf_cfg80211_vif *ndev_to_vif(struct net_device *ndev)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
return ifp->vif;
|
||||
}
|
||||
|
||||
static inline struct
|
||||
brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_info *cfg)
|
||||
|
@ -547,11 +455,7 @@ brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_info *cfg)
|
|||
|
||||
struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr);
|
||||
void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg);
|
||||
|
||||
/* event handler from dongle */
|
||||
void brcmf_cfg80211_event(struct net_device *ndev,
|
||||
const struct brcmf_event_msg *e, void *data);
|
||||
s32 brcmf_cfg80211_up(struct brcmf_cfg80211_info *cfg);
|
||||
s32 brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg);
|
||||
s32 brcmf_cfg80211_up(struct net_device *ndev);
|
||||
s32 brcmf_cfg80211_down(struct net_device *ndev);
|
||||
|
||||
#endif /* _wl_cfg80211_h_ */
|
||||
|
|
|
@ -40,7 +40,8 @@ BRCMSMAC_OFILES := \
|
|||
phy/phytbl_n.o \
|
||||
phy/phy_qmath.o \
|
||||
dma.o \
|
||||
brcms_trace_events.o
|
||||
brcms_trace_events.o \
|
||||
debug.o
|
||||
|
||||
MODULEPFX := brcmsmac
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include "antsel.h"
|
||||
#include "main.h"
|
||||
#include "ampdu.h"
|
||||
#include "debug.h"
|
||||
#include "brcms_trace_events.h"
|
||||
|
||||
/* max number of mpdus in an ampdu */
|
||||
#define AMPDU_MAX_MPDU 32
|
||||
|
@ -40,8 +42,6 @@
|
|||
#define AMPDU_DEF_RETRY_LIMIT 5
|
||||
/* default tx retry limit at reg rate */
|
||||
#define AMPDU_DEF_RR_RETRY_LIMIT 2
|
||||
/* default weight of ampdu in txfifo */
|
||||
#define AMPDU_DEF_TXPKT_WEIGHT 2
|
||||
/* default ffpld reserved bytes */
|
||||
#define AMPDU_DEF_FFPLD_RSVD 2048
|
||||
/* # of inis to be freed on detach */
|
||||
|
@ -114,7 +114,6 @@ struct brcms_fifo_info {
|
|||
* mpdu_density: min mpdu spacing (0-7) ==> 2^(x-1)/8 usec
|
||||
* max_pdu: max pdus allowed in ampdu
|
||||
* dur: max duration of an ampdu (in msec)
|
||||
* txpkt_weight: weight of ampdu in txfifo; reduces rate lag
|
||||
* rx_factor: maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes
|
||||
* ffpld_rsvd: number of bytes to reserve for preload
|
||||
* max_txlen: max size of ampdu per mcs, bw and sgi
|
||||
|
@ -136,7 +135,6 @@ struct ampdu_info {
|
|||
u8 mpdu_density;
|
||||
s8 max_pdu;
|
||||
u8 dur;
|
||||
u8 txpkt_weight;
|
||||
u8 rx_factor;
|
||||
u32 ffpld_rsvd;
|
||||
u32 max_txlen[MCS_TABLE_SIZE][2][2];
|
||||
|
@ -183,18 +181,19 @@ static bool brcms_c_ampdu_cap(struct ampdu_info *ampdu)
|
|||
static int brcms_c_ampdu_set(struct ampdu_info *ampdu, bool on)
|
||||
{
|
||||
struct brcms_c_info *wlc = ampdu->wlc;
|
||||
struct bcma_device *core = wlc->hw->d11core;
|
||||
|
||||
wlc->pub->_ampdu = false;
|
||||
|
||||
if (on) {
|
||||
if (!(wlc->pub->_n_enab & SUPPORT_11N)) {
|
||||
wiphy_err(ampdu->wlc->wiphy, "wl%d: driver not "
|
||||
"nmode enabled\n", wlc->pub->unit);
|
||||
brcms_err(core, "wl%d: driver not nmode enabled\n",
|
||||
wlc->pub->unit);
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
if (!brcms_c_ampdu_cap(ampdu)) {
|
||||
wiphy_err(ampdu->wlc->wiphy, "wl%d: device not "
|
||||
"ampdu capable\n", wlc->pub->unit);
|
||||
brcms_err(core, "wl%d: device not ampdu capable\n",
|
||||
wlc->pub->unit);
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
wlc->pub->_ampdu = on;
|
||||
|
@ -247,7 +246,6 @@ struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc)
|
|||
ampdu->mpdu_density = AMPDU_DEF_MPDU_DENSITY;
|
||||
ampdu->max_pdu = AUTO;
|
||||
ampdu->dur = AMPDU_MAX_DUR;
|
||||
ampdu->txpkt_weight = AMPDU_DEF_TXPKT_WEIGHT;
|
||||
|
||||
ampdu->ffpld_rsvd = AMPDU_DEF_FFPLD_RSVD;
|
||||
/*
|
||||
|
@ -374,7 +372,8 @@ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
|
|||
offsetof(struct macstat, txfunfl[fid]));
|
||||
new_txunfl = (u16) (cur_txunfl - fifo->prev_txfunfl);
|
||||
if (new_txunfl == 0) {
|
||||
BCMMSG(wlc->wiphy, "TX status FRAG set but no tx underflows\n");
|
||||
brcms_dbg_ht(wlc->hw->d11core,
|
||||
"TX status FRAG set but no tx underflows\n");
|
||||
return -1;
|
||||
}
|
||||
fifo->prev_txfunfl = cur_txunfl;
|
||||
|
@ -396,8 +395,8 @@ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
|
|||
if (fifo->accum_txfunfl < 10)
|
||||
return 0;
|
||||
|
||||
BCMMSG(wlc->wiphy, "ampdu_count %d tx_underflows %d\n",
|
||||
current_ampdu_cnt, fifo->accum_txfunfl);
|
||||
brcms_dbg_ht(wlc->hw->d11core, "ampdu_count %d tx_underflows %d\n",
|
||||
current_ampdu_cnt, fifo->accum_txfunfl);
|
||||
|
||||
/*
|
||||
compute the current ratio of tx unfl per ampdu.
|
||||
|
@ -450,9 +449,10 @@ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
|
|||
(max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
|
||||
/ (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
|
||||
|
||||
BCMMSG(wlc->wiphy, "DMA estimated transfer rate %d; "
|
||||
"pre-load size %d\n",
|
||||
fifo->dmaxferrate, fifo->ampdu_pld_size);
|
||||
brcms_dbg_ht(wlc->hw->d11core,
|
||||
"DMA estimated transfer rate %d; "
|
||||
"pre-load size %d\n",
|
||||
fifo->dmaxferrate, fifo->ampdu_pld_size);
|
||||
} else {
|
||||
|
||||
/* decrease ampdu size */
|
||||
|
@ -486,7 +486,7 @@ brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
|
|||
scb_ampdu = &scb->scb_ampdu;
|
||||
|
||||
if (!ampdu->ini_enable[tid]) {
|
||||
wiphy_err(ampdu->wlc->wiphy, "%s: Rejecting tid %d\n",
|
||||
brcms_err(wlc->hw->d11core, "%s: Rejecting tid %d\n",
|
||||
__func__, tid);
|
||||
return;
|
||||
}
|
||||
|
@ -498,378 +498,324 @@ brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
|
|||
scb_ampdu->max_rx_ampdu_bytes = max_rx_ampdu_bytes;
|
||||
}
|
||||
|
||||
int
|
||||
brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
|
||||
struct sk_buff **pdu, int prec)
|
||||
void brcms_c_ampdu_reset_session(struct brcms_ampdu_session *session,
|
||||
struct brcms_c_info *wlc)
|
||||
{
|
||||
struct brcms_c_info *wlc;
|
||||
struct sk_buff *p, *pkt[AMPDU_MAX_MPDU];
|
||||
u8 tid, ndelim;
|
||||
int err = 0;
|
||||
session->wlc = wlc;
|
||||
skb_queue_head_init(&session->skb_list);
|
||||
session->max_ampdu_len = 0; /* determined from first MPDU */
|
||||
session->max_ampdu_frames = 0; /* determined from first MPDU */
|
||||
session->ampdu_len = 0;
|
||||
session->dma_len = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Preps the given packet for AMPDU based on the session data. If the
|
||||
* frame cannot be accomodated in the current session, -ENOSPC is
|
||||
* returned.
|
||||
*/
|
||||
int brcms_c_ampdu_add_frame(struct brcms_ampdu_session *session,
|
||||
struct sk_buff *p)
|
||||
{
|
||||
struct brcms_c_info *wlc = session->wlc;
|
||||
struct ampdu_info *ampdu = wlc->ampdu;
|
||||
struct scb *scb = &wlc->pri_scb;
|
||||
struct scb_ampdu *scb_ampdu = &scb->scb_ampdu;
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p);
|
||||
struct ieee80211_tx_rate *txrate = tx_info->status.rates;
|
||||
struct d11txh *txh = (struct d11txh *)p->data;
|
||||
unsigned ampdu_frames;
|
||||
u8 ndelim, tid;
|
||||
u8 *plcp;
|
||||
uint len;
|
||||
u16 mcl;
|
||||
bool fbr_iscck;
|
||||
bool rr;
|
||||
|
||||
ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
|
||||
plcp = (u8 *)(txh + 1);
|
||||
fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x03);
|
||||
len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback) :
|
||||
BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
|
||||
len = roundup(len, 4) + (ndelim + 1) * AMPDU_DELIMITER_LEN;
|
||||
|
||||
ampdu_frames = skb_queue_len(&session->skb_list);
|
||||
if (ampdu_frames != 0) {
|
||||
struct sk_buff *first;
|
||||
|
||||
if (ampdu_frames + 1 > session->max_ampdu_frames ||
|
||||
session->ampdu_len + len > session->max_ampdu_len)
|
||||
return -ENOSPC;
|
||||
|
||||
/*
|
||||
* We aren't really out of space if the new frame is of
|
||||
* a different priority, but we want the same behaviour
|
||||
* so return -ENOSPC anyway.
|
||||
*
|
||||
* XXX: The old AMPDU code did this, but is it really
|
||||
* necessary?
|
||||
*/
|
||||
first = skb_peek(&session->skb_list);
|
||||
if (p->priority != first->priority)
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now that we're sure this frame can be accomodated, update the
|
||||
* session information.
|
||||
*/
|
||||
session->ampdu_len += len;
|
||||
session->dma_len += p->len;
|
||||
|
||||
tid = (u8)p->priority;
|
||||
|
||||
/* Handle retry limits */
|
||||
if (txrate[0].count <= ampdu->rr_retry_limit_tid[tid]) {
|
||||
txrate[0].count++;
|
||||
rr = true;
|
||||
} else {
|
||||
txrate[1].count++;
|
||||
rr = false;
|
||||
}
|
||||
|
||||
if (ampdu_frames == 0) {
|
||||
u8 plcp0, plcp3, is40, sgi, mcs;
|
||||
uint fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK;
|
||||
struct brcms_fifo_info *f = &du->fifo_tb[fifo];
|
||||
|
||||
if (rr) {
|
||||
plcp0 = plcp[0];
|
||||
plcp3 = plcp[3];
|
||||
} else {
|
||||
plcp0 = txh->FragPLCPFallback[0];
|
||||
plcp3 = txh->FragPLCPFallback[3];
|
||||
|
||||
}
|
||||
|
||||
/* Limit AMPDU size based on MCS */
|
||||
is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
|
||||
sgi = plcp3_issgi(plcp3) ? 1 : 0;
|
||||
mcs = plcp0 & ~MIMO_PLCP_40MHZ;
|
||||
session->max_ampdu_len = min(scb_ampdu->max_rx_ampdu_bytes,
|
||||
ampdu->max_txlen[mcs][is40][sgi]);
|
||||
|
||||
session->max_ampdu_frames = scb_ampdu->max_pdu;
|
||||
if (mcs_2_rate(mcs, true, false) >= f->dmaxferrate) {
|
||||
session->max_ampdu_frames =
|
||||
min_t(u16, f->mcs2ampdu_table[mcs],
|
||||
session->max_ampdu_frames);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Treat all frames as "middle" frames of AMPDU here. First and
|
||||
* last frames must be fixed up after all MPDUs have been prepped.
|
||||
*/
|
||||
mcl = le16_to_cpu(txh->MacTxControlLow);
|
||||
mcl &= ~TXC_AMPDU_MASK;
|
||||
mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT);
|
||||
mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS);
|
||||
txh->MacTxControlLow = cpu_to_le16(mcl);
|
||||
txh->PreloadSize = 0; /* always default to 0 */
|
||||
|
||||
skb_queue_tail(&session->skb_list, p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void brcms_c_ampdu_finalize(struct brcms_ampdu_session *session)
|
||||
{
|
||||
struct brcms_c_info *wlc = session->wlc;
|
||||
struct ampdu_info *ampdu = wlc->ampdu;
|
||||
struct sk_buff *first, *last;
|
||||
struct d11txh *txh;
|
||||
struct ieee80211_tx_info *tx_info;
|
||||
struct ieee80211_tx_rate *txrate;
|
||||
u8 ndelim;
|
||||
u8 *plcp;
|
||||
uint len;
|
||||
uint fifo;
|
||||
struct brcms_fifo_info *f;
|
||||
u16 mcl;
|
||||
bool fbr;
|
||||
bool fbr_iscck;
|
||||
struct ieee80211_rts *rts;
|
||||
bool use_rts = false, use_cts = false;
|
||||
u16 dma_len = session->dma_len;
|
||||
u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
|
||||
u32 rspec = 0, rspec_fallback = 0;
|
||||
u32 rts_rspec = 0, rts_rspec_fallback = 0;
|
||||
u8 plcp0, plcp3, is40, sgi, mcs;
|
||||
u16 mch;
|
||||
u8 preamble_type = BRCMS_GF_PREAMBLE;
|
||||
u8 fbr_preamble_type = BRCMS_GF_PREAMBLE;
|
||||
u8 rts_preamble_type = BRCMS_LONG_PREAMBLE;
|
||||
u8 rts_fbr_preamble_type = BRCMS_LONG_PREAMBLE;
|
||||
|
||||
bool rr = true, fbr = false;
|
||||
uint i, count = 0, fifo, seg_cnt = 0;
|
||||
u16 plen, len, seq = 0, mcl, mch, index, frameid, dma_len = 0;
|
||||
u32 ampdu_len, max_ampdu_bytes = 0;
|
||||
struct d11txh *txh = NULL;
|
||||
u8 *plcp;
|
||||
struct ieee80211_hdr *h;
|
||||
struct scb *scb;
|
||||
struct scb_ampdu *scb_ampdu;
|
||||
struct scb_ampdu_tid_ini *ini;
|
||||
u8 mcs = 0;
|
||||
bool use_rts = false, use_cts = false;
|
||||
u32 rspec = 0, rspec_fallback = 0;
|
||||
u32 rts_rspec = 0, rts_rspec_fallback = 0;
|
||||
u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
|
||||
struct ieee80211_rts *rts;
|
||||
u8 rr_retry_limit;
|
||||
struct brcms_fifo_info *f;
|
||||
bool fbr_iscck;
|
||||
struct ieee80211_tx_info *tx_info;
|
||||
u16 qlen;
|
||||
struct wiphy *wiphy;
|
||||
if (skb_queue_empty(&session->skb_list))
|
||||
return;
|
||||
|
||||
wlc = ampdu->wlc;
|
||||
wiphy = wlc->wiphy;
|
||||
p = *pdu;
|
||||
first = skb_peek(&session->skb_list);
|
||||
last = skb_peek_tail(&session->skb_list);
|
||||
|
||||
tid = (u8) (p->priority);
|
||||
/* Need to fix up last MPDU first to adjust AMPDU length */
|
||||
txh = (struct d11txh *)last->data;
|
||||
fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK;
|
||||
f = &du->fifo_tb[fifo];
|
||||
|
||||
f = ampdu->fifo_tb + prio2fifo[tid];
|
||||
mcl = le16_to_cpu(txh->MacTxControlLow);
|
||||
mcl &= ~TXC_AMPDU_MASK;
|
||||
mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT);
|
||||
txh->MacTxControlLow = cpu_to_le16(mcl);
|
||||
|
||||
scb = &wlc->pri_scb;
|
||||
scb_ampdu = &scb->scb_ampdu;
|
||||
ini = &scb_ampdu->ini[tid];
|
||||
/* remove the null delimiter after last mpdu */
|
||||
ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
|
||||
txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0;
|
||||
session->ampdu_len -= ndelim * AMPDU_DELIMITER_LEN;
|
||||
|
||||
/* Let pressure continue to build ... */
|
||||
qlen = pktq_plen(&qi->q, prec);
|
||||
if (ini->tx_in_transit > 0 &&
|
||||
qlen < min(scb_ampdu->max_pdu, ini->ba_wsize))
|
||||
/* Collect multiple MPDU's to be sent in the next AMPDU */
|
||||
return -EBUSY;
|
||||
/* remove the pad len from last mpdu */
|
||||
fbr_iscck = ((le16_to_cpu(txh->XtraFrameTypes) & 0x3) == 0);
|
||||
len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback) :
|
||||
BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
|
||||
session->ampdu_len -= roundup(len, 4) - len;
|
||||
|
||||
/* at this point we intend to transmit an AMPDU */
|
||||
rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
|
||||
ampdu_len = 0;
|
||||
dma_len = 0;
|
||||
while (p) {
|
||||
struct ieee80211_tx_rate *txrate;
|
||||
/* Now fix up the first MPDU */
|
||||
tx_info = IEEE80211_SKB_CB(first);
|
||||
txrate = tx_info->status.rates;
|
||||
txh = (struct d11txh *)first->data;
|
||||
plcp = (u8 *)(txh + 1);
|
||||
rts = (struct ieee80211_rts *)&txh->rts_frame;
|
||||
|
||||
tx_info = IEEE80211_SKB_CB(p);
|
||||
txrate = tx_info->status.rates;
|
||||
|
||||
if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
|
||||
err = brcms_c_prep_pdu(wlc, p, &fifo);
|
||||
} else {
|
||||
wiphy_err(wiphy, "%s: AMPDU flag is off!\n", __func__);
|
||||
*pdu = NULL;
|
||||
err = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
if (err == -EBUSY) {
|
||||
wiphy_err(wiphy, "wl%d: sendampdu: "
|
||||
"prep_xdu retry; seq 0x%x\n",
|
||||
wlc->pub->unit, seq);
|
||||
*pdu = p;
|
||||
break;
|
||||
}
|
||||
|
||||
/* error in the packet; reject it */
|
||||
wiphy_err(wiphy, "wl%d: sendampdu: prep_xdu "
|
||||
"rejected; seq 0x%x\n", wlc->pub->unit, seq);
|
||||
*pdu = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* pkt is good to be aggregated */
|
||||
txh = (struct d11txh *) p->data;
|
||||
plcp = (u8 *) (txh + 1);
|
||||
h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
|
||||
seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
|
||||
index = TX_SEQ_TO_INDEX(seq);
|
||||
|
||||
/* check mcl fields and test whether it can be agg'd */
|
||||
mcl = le16_to_cpu(txh->MacTxControlLow);
|
||||
mcl = le16_to_cpu(txh->MacTxControlLow);
|
||||
/* If only one MPDU leave it marked as last */
|
||||
if (first != last) {
|
||||
mcl &= ~TXC_AMPDU_MASK;
|
||||
fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x3);
|
||||
txh->PreloadSize = 0; /* always default to 0 */
|
||||
|
||||
/* Handle retry limits */
|
||||
if (txrate[0].count <= rr_retry_limit) {
|
||||
txrate[0].count++;
|
||||
rr = true;
|
||||
fbr = false;
|
||||
} else {
|
||||
fbr = true;
|
||||
rr = false;
|
||||
txrate[1].count++;
|
||||
}
|
||||
|
||||
/* extract the length info */
|
||||
len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
|
||||
: BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
|
||||
|
||||
/* retrieve null delimiter count */
|
||||
ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
|
||||
seg_cnt += 1;
|
||||
|
||||
BCMMSG(wlc->wiphy, "wl%d: mpdu %d plcp_len %d\n",
|
||||
wlc->pub->unit, count, len);
|
||||
|
||||
/*
|
||||
* aggregateable mpdu. For ucode/hw agg,
|
||||
* test whether need to break or change the epoch
|
||||
*/
|
||||
if (count == 0) {
|
||||
mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT);
|
||||
/* refill the bits since might be a retx mpdu */
|
||||
mcl |= TXC_STARTMSDU;
|
||||
rts = (struct ieee80211_rts *)&txh->rts_frame;
|
||||
|
||||
if (ieee80211_is_rts(rts->frame_control)) {
|
||||
mcl |= TXC_SENDRTS;
|
||||
use_rts = true;
|
||||
}
|
||||
if (ieee80211_is_cts(rts->frame_control)) {
|
||||
mcl |= TXC_SENDCTS;
|
||||
use_cts = true;
|
||||
}
|
||||
} else {
|
||||
mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT);
|
||||
mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS);
|
||||
}
|
||||
|
||||
len = roundup(len, 4);
|
||||
ampdu_len += (len + (ndelim + 1) * AMPDU_DELIMITER_LEN);
|
||||
|
||||
dma_len += (u16) p->len;
|
||||
|
||||
BCMMSG(wlc->wiphy, "wl%d: ampdu_len %d"
|
||||
" seg_cnt %d null delim %d\n",
|
||||
wlc->pub->unit, ampdu_len, seg_cnt, ndelim);
|
||||
|
||||
txh->MacTxControlLow = cpu_to_le16(mcl);
|
||||
|
||||
/* this packet is added */
|
||||
pkt[count++] = p;
|
||||
|
||||
/* patch the first MPDU */
|
||||
if (count == 1) {
|
||||
u8 plcp0, plcp3, is40, sgi;
|
||||
|
||||
if (rr) {
|
||||
plcp0 = plcp[0];
|
||||
plcp3 = plcp[3];
|
||||
} else {
|
||||
plcp0 = txh->FragPLCPFallback[0];
|
||||
plcp3 = txh->FragPLCPFallback[3];
|
||||
|
||||
}
|
||||
is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
|
||||
sgi = plcp3_issgi(plcp3) ? 1 : 0;
|
||||
mcs = plcp0 & ~MIMO_PLCP_40MHZ;
|
||||
max_ampdu_bytes =
|
||||
min(scb_ampdu->max_rx_ampdu_bytes,
|
||||
ampdu->max_txlen[mcs][is40][sgi]);
|
||||
|
||||
if (is40)
|
||||
mimo_ctlchbw =
|
||||
CHSPEC_SB_UPPER(wlc_phy_chanspec_get(
|
||||
wlc->band->pi))
|
||||
? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ;
|
||||
|
||||
/* rebuild the rspec and rspec_fallback */
|
||||
rspec = RSPEC_MIMORATE;
|
||||
rspec |= plcp[0] & ~MIMO_PLCP_40MHZ;
|
||||
if (plcp[0] & MIMO_PLCP_40MHZ)
|
||||
rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
|
||||
|
||||
if (fbr_iscck) /* CCK */
|
||||
rspec_fallback = cck_rspec(cck_phy2mac_rate
|
||||
(txh->FragPLCPFallback[0]));
|
||||
else { /* MIMO */
|
||||
rspec_fallback = RSPEC_MIMORATE;
|
||||
rspec_fallback |=
|
||||
txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ;
|
||||
if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ)
|
||||
rspec_fallback |=
|
||||
(PHY_TXC1_BW_40MHZ <<
|
||||
RSPEC_BW_SHIFT);
|
||||
}
|
||||
|
||||
if (use_rts || use_cts) {
|
||||
rts_rspec =
|
||||
brcms_c_rspec_to_rts_rspec(wlc,
|
||||
rspec, false, mimo_ctlchbw);
|
||||
rts_rspec_fallback =
|
||||
brcms_c_rspec_to_rts_rspec(wlc,
|
||||
rspec_fallback, false, mimo_ctlchbw);
|
||||
}
|
||||
}
|
||||
|
||||
/* if (first mpdu for host agg) */
|
||||
/* test whether to add more */
|
||||
if ((mcs_2_rate(mcs, true, false) >= f->dmaxferrate) &&
|
||||
(count == f->mcs2ampdu_table[mcs])) {
|
||||
BCMMSG(wlc->wiphy, "wl%d: PR 37644: stopping"
|
||||
" ampdu at %d for mcs %d\n",
|
||||
wlc->pub->unit, count, mcs);
|
||||
break;
|
||||
}
|
||||
|
||||
if (count == scb_ampdu->max_pdu)
|
||||
break;
|
||||
|
||||
/*
|
||||
* check to see if the next pkt is
|
||||
* a candidate for aggregation
|
||||
*/
|
||||
p = pktq_ppeek(&qi->q, prec);
|
||||
if (p) {
|
||||
tx_info = IEEE80211_SKB_CB(p);
|
||||
if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
|
||||
((u8) (p->priority) == tid)) {
|
||||
plen = p->len + AMPDU_MAX_MPDU_OVERHEAD;
|
||||
plen = max(scb_ampdu->min_len, plen);
|
||||
|
||||
if ((plen + ampdu_len) > max_ampdu_bytes) {
|
||||
p = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* check if there are enough
|
||||
* descriptors available
|
||||
*/
|
||||
if (*wlc->core->txavail[fifo] <= seg_cnt + 1) {
|
||||
wiphy_err(wiphy, "%s: No fifo space "
|
||||
"!!\n", __func__);
|
||||
p = NULL;
|
||||
continue;
|
||||
}
|
||||
/* next packet fit for aggregation so dequeue */
|
||||
p = brcmu_pktq_pdeq(&qi->q, prec);
|
||||
} else {
|
||||
p = NULL;
|
||||
}
|
||||
}
|
||||
} /* end while(p) */
|
||||
|
||||
ini->tx_in_transit += count;
|
||||
|
||||
if (count) {
|
||||
/* patch up the last txh */
|
||||
txh = (struct d11txh *) pkt[count - 1]->data;
|
||||
mcl = le16_to_cpu(txh->MacTxControlLow);
|
||||
mcl &= ~TXC_AMPDU_MASK;
|
||||
mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT);
|
||||
txh->MacTxControlLow = cpu_to_le16(mcl);
|
||||
|
||||
/* remove the null delimiter after last mpdu */
|
||||
ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
|
||||
txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0;
|
||||
ampdu_len -= ndelim * AMPDU_DELIMITER_LEN;
|
||||
|
||||
/* remove the pad len from last mpdu */
|
||||
fbr_iscck = ((le16_to_cpu(txh->XtraFrameTypes) & 0x3) == 0);
|
||||
len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
|
||||
: BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
|
||||
ampdu_len -= roundup(len, 4) - len;
|
||||
|
||||
/* patch up the first txh & plcp */
|
||||
txh = (struct d11txh *) pkt[0]->data;
|
||||
plcp = (u8 *) (txh + 1);
|
||||
|
||||
BRCMS_SET_MIMO_PLCP_LEN(plcp, ampdu_len);
|
||||
/* mark plcp to indicate ampdu */
|
||||
BRCMS_SET_MIMO_PLCP_AMPDU(plcp);
|
||||
|
||||
/* reset the mixed mode header durations */
|
||||
if (txh->MModeLen) {
|
||||
u16 mmodelen =
|
||||
brcms_c_calc_lsig_len(wlc, rspec, ampdu_len);
|
||||
txh->MModeLen = cpu_to_le16(mmodelen);
|
||||
preamble_type = BRCMS_MM_PREAMBLE;
|
||||
}
|
||||
if (txh->MModeFbrLen) {
|
||||
u16 mmfbrlen =
|
||||
brcms_c_calc_lsig_len(wlc, rspec_fallback,
|
||||
ampdu_len);
|
||||
txh->MModeFbrLen = cpu_to_le16(mmfbrlen);
|
||||
fbr_preamble_type = BRCMS_MM_PREAMBLE;
|
||||
}
|
||||
|
||||
/* set the preload length */
|
||||
if (mcs_2_rate(mcs, true, false) >= f->dmaxferrate) {
|
||||
dma_len = min(dma_len, f->ampdu_pld_size);
|
||||
txh->PreloadSize = cpu_to_le16(dma_len);
|
||||
} else
|
||||
txh->PreloadSize = 0;
|
||||
|
||||
mch = le16_to_cpu(txh->MacTxControlHigh);
|
||||
|
||||
/* update RTS dur fields */
|
||||
if (use_rts || use_cts) {
|
||||
u16 durid;
|
||||
rts = (struct ieee80211_rts *)&txh->rts_frame;
|
||||
if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) ==
|
||||
TXC_PREAMBLE_RTS_MAIN_SHORT)
|
||||
rts_preamble_type = BRCMS_SHORT_PREAMBLE;
|
||||
|
||||
if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) ==
|
||||
TXC_PREAMBLE_RTS_FB_SHORT)
|
||||
rts_fbr_preamble_type = BRCMS_SHORT_PREAMBLE;
|
||||
|
||||
durid =
|
||||
brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec,
|
||||
rspec, rts_preamble_type,
|
||||
preamble_type, ampdu_len,
|
||||
true);
|
||||
rts->duration = cpu_to_le16(durid);
|
||||
durid = brcms_c_compute_rtscts_dur(wlc, use_cts,
|
||||
rts_rspec_fallback,
|
||||
rspec_fallback,
|
||||
rts_fbr_preamble_type,
|
||||
fbr_preamble_type,
|
||||
ampdu_len, true);
|
||||
txh->RTSDurFallback = cpu_to_le16(durid);
|
||||
/* set TxFesTimeNormal */
|
||||
txh->TxFesTimeNormal = rts->duration;
|
||||
/* set fallback rate version of TxFesTimeNormal */
|
||||
txh->TxFesTimeFallback = txh->RTSDurFallback;
|
||||
}
|
||||
|
||||
/* set flag and plcp for fallback rate */
|
||||
if (fbr) {
|
||||
mch |= TXC_AMPDU_FBR;
|
||||
txh->MacTxControlHigh = cpu_to_le16(mch);
|
||||
BRCMS_SET_MIMO_PLCP_AMPDU(plcp);
|
||||
BRCMS_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback);
|
||||
}
|
||||
|
||||
BCMMSG(wlc->wiphy, "wl%d: count %d ampdu_len %d\n",
|
||||
wlc->pub->unit, count, ampdu_len);
|
||||
|
||||
/* inform rate_sel if it this is a rate probe pkt */
|
||||
frameid = le16_to_cpu(txh->TxFrameID);
|
||||
if (frameid & TXFID_RATE_PROBE_MASK)
|
||||
wiphy_err(wiphy, "%s: XXX what to do with "
|
||||
"TXFID_RATE_PROBE_MASK!?\n", __func__);
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
brcms_c_txfifo(wlc, fifo, pkt[i], i == (count - 1),
|
||||
ampdu->txpkt_weight);
|
||||
|
||||
mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT);
|
||||
}
|
||||
/* endif (count) */
|
||||
return err;
|
||||
mcl |= TXC_STARTMSDU;
|
||||
if (ieee80211_is_rts(rts->frame_control)) {
|
||||
mcl |= TXC_SENDRTS;
|
||||
use_rts = true;
|
||||
}
|
||||
if (ieee80211_is_cts(rts->frame_control)) {
|
||||
mcl |= TXC_SENDCTS;
|
||||
use_cts = true;
|
||||
}
|
||||
txh->MacTxControlLow = cpu_to_le16(mcl);
|
||||
|
||||
fbr = txrate[1].count > 0;
|
||||
if (!fbr) {
|
||||
plcp0 = plcp[0];
|
||||
plcp3 = plcp[3];
|
||||
} else {
|
||||
plcp0 = txh->FragPLCPFallback[0];
|
||||
plcp3 = txh->FragPLCPFallback[3];
|
||||
}
|
||||
is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
|
||||
sgi = plcp3_issgi(plcp3) ? 1 : 0;
|
||||
mcs = plcp0 & ~MIMO_PLCP_40MHZ;
|
||||
|
||||
if (is40) {
|
||||
if (CHSPEC_SB_UPPER(wlc_phy_chanspec_get(wlc->band->pi)))
|
||||
mimo_ctlchbw = PHY_TXC1_BW_20MHZ_UP;
|
||||
else
|
||||
mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
|
||||
}
|
||||
|
||||
/* rebuild the rspec and rspec_fallback */
|
||||
rspec = RSPEC_MIMORATE;
|
||||
rspec |= plcp[0] & ~MIMO_PLCP_40MHZ;
|
||||
if (plcp[0] & MIMO_PLCP_40MHZ)
|
||||
rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
|
||||
|
||||
fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x03);
|
||||
if (fbr_iscck) {
|
||||
rspec_fallback =
|
||||
cck_rspec(cck_phy2mac_rate(txh->FragPLCPFallback[0]));
|
||||
} else {
|
||||
rspec_fallback = RSPEC_MIMORATE;
|
||||
rspec_fallback |= txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ;
|
||||
if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ)
|
||||
rspec_fallback |= PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT;
|
||||
}
|
||||
|
||||
if (use_rts || use_cts) {
|
||||
rts_rspec =
|
||||
brcms_c_rspec_to_rts_rspec(wlc, rspec,
|
||||
false, mimo_ctlchbw);
|
||||
rts_rspec_fallback =
|
||||
brcms_c_rspec_to_rts_rspec(wlc, rspec_fallback,
|
||||
false, mimo_ctlchbw);
|
||||
}
|
||||
|
||||
BRCMS_SET_MIMO_PLCP_LEN(plcp, session->ampdu_len);
|
||||
/* mark plcp to indicate ampdu */
|
||||
BRCMS_SET_MIMO_PLCP_AMPDU(plcp);
|
||||
|
||||
/* reset the mixed mode header durations */
|
||||
if (txh->MModeLen) {
|
||||
u16 mmodelen = brcms_c_calc_lsig_len(wlc, rspec,
|
||||
session->ampdu_len);
|
||||
txh->MModeLen = cpu_to_le16(mmodelen);
|
||||
preamble_type = BRCMS_MM_PREAMBLE;
|
||||
}
|
||||
if (txh->MModeFbrLen) {
|
||||
u16 mmfbrlen = brcms_c_calc_lsig_len(wlc, rspec_fallback,
|
||||
session->ampdu_len);
|
||||
txh->MModeFbrLen = cpu_to_le16(mmfbrlen);
|
||||
fbr_preamble_type = BRCMS_MM_PREAMBLE;
|
||||
}
|
||||
|
||||
/* set the preload length */
|
||||
if (mcs_2_rate(mcs, true, false) >= f->dmaxferrate) {
|
||||
dma_len = min(dma_len, f->ampdu_pld_size);
|
||||
txh->PreloadSize = cpu_to_le16(dma_len);
|
||||
} else {
|
||||
txh->PreloadSize = 0;
|
||||
}
|
||||
|
||||
mch = le16_to_cpu(txh->MacTxControlHigh);
|
||||
|
||||
/* update RTS dur fields */
|
||||
if (use_rts || use_cts) {
|
||||
u16 durid;
|
||||
if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) ==
|
||||
TXC_PREAMBLE_RTS_MAIN_SHORT)
|
||||
rts_preamble_type = BRCMS_SHORT_PREAMBLE;
|
||||
|
||||
if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) ==
|
||||
TXC_PREAMBLE_RTS_FB_SHORT)
|
||||
rts_fbr_preamble_type = BRCMS_SHORT_PREAMBLE;
|
||||
|
||||
durid = brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec,
|
||||
rspec, rts_preamble_type,
|
||||
preamble_type,
|
||||
session->ampdu_len, true);
|
||||
rts->duration = cpu_to_le16(durid);
|
||||
durid = brcms_c_compute_rtscts_dur(wlc, use_cts,
|
||||
rts_rspec_fallback,
|
||||
rspec_fallback,
|
||||
rts_fbr_preamble_type,
|
||||
fbr_preamble_type,
|
||||
session->ampdu_len, true);
|
||||
txh->RTSDurFallback = cpu_to_le16(durid);
|
||||
/* set TxFesTimeNormal */
|
||||
txh->TxFesTimeNormal = rts->duration;
|
||||
/* set fallback rate version of TxFesTimeNormal */
|
||||
txh->TxFesTimeFallback = txh->RTSDurFallback;
|
||||
}
|
||||
|
||||
/* set flag and plcp for fallback rate */
|
||||
if (fbr) {
|
||||
mch |= TXC_AMPDU_FBR;
|
||||
txh->MacTxControlHigh = cpu_to_le16(mch);
|
||||
BRCMS_SET_MIMO_PLCP_AMPDU(plcp);
|
||||
BRCMS_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback);
|
||||
}
|
||||
|
||||
brcms_dbg_ht(wlc->hw->d11core, "wl%d: count %d ampdu_len %d\n",
|
||||
wlc->pub->unit, skb_queue_len(&session->skb_list),
|
||||
session->ampdu_len);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -909,7 +855,6 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
|
|||
u8 antselid = 0;
|
||||
u8 retry_limit, rr_retry_limit;
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p);
|
||||
struct wiphy *wiphy = wlc->wiphy;
|
||||
|
||||
#ifdef DEBUG
|
||||
u8 hole[AMPDU_MAX_MPDU];
|
||||
|
@ -955,13 +900,14 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
|
|||
if (supr_status) {
|
||||
update_rate = false;
|
||||
if (supr_status == TX_STATUS_SUPR_BADCH) {
|
||||
wiphy_err(wiphy,
|
||||
brcms_err(wlc->hw->d11core,
|
||||
"%s: Pkt tx suppressed, illegal channel possibly %d\n",
|
||||
__func__, CHSPEC_CHANNEL(
|
||||
wlc->default_bss->chanspec));
|
||||
} else {
|
||||
if (supr_status != TX_STATUS_SUPR_FRAG)
|
||||
wiphy_err(wiphy, "%s: supr_status 0x%x\n",
|
||||
brcms_err(wlc->hw->d11core,
|
||||
"%s: supr_status 0x%x\n",
|
||||
__func__, supr_status);
|
||||
}
|
||||
/* no need to retry for badch; will fail again */
|
||||
|
@ -977,20 +923,14 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
|
|||
* if there were underflows, but pre-loading
|
||||
* is not active, notify rate adaptation.
|
||||
*/
|
||||
if (brcms_c_ffpld_check_txfunfl(wlc,
|
||||
prio2fifo[tid]) > 0)
|
||||
if (brcms_c_ffpld_check_txfunfl(wlc, queue) > 0)
|
||||
tx_error = true;
|
||||
}
|
||||
} else if (txs->phyerr) {
|
||||
update_rate = false;
|
||||
wiphy_err(wiphy, "%s: ampdu tx phy error (0x%x)\n",
|
||||
brcms_err(wlc->hw->d11core,
|
||||
"%s: ampdu tx phy error (0x%x)\n",
|
||||
__func__, txs->phyerr);
|
||||
|
||||
if (brcm_msg_level & LOG_ERROR_VAL) {
|
||||
brcmu_prpkt("txpkt (AMPDU)", p);
|
||||
brcms_c_print_txdesc((struct d11txh *) p->data);
|
||||
}
|
||||
brcms_c_print_txstatus(txs);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1003,6 +943,8 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
|
|||
h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
|
||||
seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
|
||||
|
||||
trace_brcms_txdesc(&wlc->hw->d11core->dev, txh, sizeof(*txh));
|
||||
|
||||
if (tot_mpdu == 0) {
|
||||
mcs = plcp[0] & MIMO_PLCP_MCS_MASK;
|
||||
mimoantsel = le16_to_cpu(txh->ABI_MimoAntSel);
|
||||
|
@ -1012,10 +954,10 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
|
|||
ack_recd = false;
|
||||
if (ba_recd) {
|
||||
bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX);
|
||||
BCMMSG(wiphy,
|
||||
"tid %d seq %d, start_seq %d, bindex %d set %d, index %d\n",
|
||||
tid, seq, start_seq, bindex,
|
||||
isset(bitmap, bindex), index);
|
||||
brcms_dbg_ht(wlc->hw->d11core,
|
||||
"tid %d seq %d, start_seq %d, bindex %d set %d, index %d\n",
|
||||
tid, seq, start_seq, bindex,
|
||||
isset(bitmap, bindex), index);
|
||||
/* if acked then clear bit and free packet */
|
||||
if ((bindex < AMPDU_TX_BA_MAX_WSIZE)
|
||||
&& isset(bitmap, bindex)) {
|
||||
|
@ -1046,14 +988,16 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
|
|||
/* either retransmit or send bar if ack not recd */
|
||||
if (!ack_recd) {
|
||||
if (retry && (ini->txretry[index] < (int)retry_limit)) {
|
||||
int ret;
|
||||
ini->txretry[index]++;
|
||||
ini->tx_in_transit--;
|
||||
ret = brcms_c_txfifo(wlc, queue, p);
|
||||
/*
|
||||
* Use high prededence for retransmit to
|
||||
* give some punch
|
||||
* We shouldn't be out of space in the DMA
|
||||
* ring here since we're reinserting a frame
|
||||
* that was just pulled out.
|
||||
*/
|
||||
brcms_c_txq_enq(wlc, scb, p,
|
||||
BRCMS_PRIO_TO_HI_PREC(tid));
|
||||
WARN_ONCE(ret, "queue %d out of txds\n", queue);
|
||||
} else {
|
||||
/* Retry timeout */
|
||||
ini->tx_in_transit--;
|
||||
|
@ -1064,9 +1008,9 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
|
|||
IEEE80211_TX_STAT_AMPDU_NO_BACK;
|
||||
skb_pull(p, D11_PHY_HDR_LEN);
|
||||
skb_pull(p, D11_TXH_LEN);
|
||||
BCMMSG(wiphy,
|
||||
"BA Timeout, seq %d, in_transit %d\n",
|
||||
seq, ini->tx_in_transit);
|
||||
brcms_dbg_ht(wlc->hw->d11core,
|
||||
"BA Timeout, seq %d, in_transit %d\n",
|
||||
seq, ini->tx_in_transit);
|
||||
ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
|
||||
p);
|
||||
}
|
||||
|
@ -1080,12 +1024,9 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
|
|||
|
||||
p = dma_getnexttxp(wlc->hw->di[queue], DMA_RANGE_TRANSMITTED);
|
||||
}
|
||||
brcms_c_send_q(wlc);
|
||||
|
||||
/* update rate state */
|
||||
antselid = brcms_c_antsel_antsel2id(wlc->asi, mimoantsel);
|
||||
|
||||
brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1133,6 +1074,8 @@ brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
|
|||
while (p) {
|
||||
tx_info = IEEE80211_SKB_CB(p);
|
||||
txh = (struct d11txh *) p->data;
|
||||
trace_brcms_txdesc(&wlc->hw->d11core->dev, txh,
|
||||
sizeof(*txh));
|
||||
mcl = le16_to_cpu(txh->MacTxControlLow);
|
||||
brcmu_pkt_buf_free_skb(p);
|
||||
/* break out if last packet of ampdu */
|
||||
|
@ -1142,7 +1085,6 @@ brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
|
|||
p = dma_getnexttxp(wlc->hw->di[queue],
|
||||
DMA_RANGE_TRANSMITTED);
|
||||
}
|
||||
brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1181,23 +1123,6 @@ void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* callback function that helps flushing ampdu packets from a priority queue
|
||||
*/
|
||||
static bool cb_del_ampdu_pkt(struct sk_buff *mpdu, void *arg_a)
|
||||
{
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(mpdu);
|
||||
struct cb_del_ampdu_pars *ampdu_pars =
|
||||
(struct cb_del_ampdu_pars *)arg_a;
|
||||
bool rc;
|
||||
|
||||
rc = tx_info->flags & IEEE80211_TX_CTL_AMPDU ? true : false;
|
||||
rc = rc && (tx_info->rate_driver_data[0] == NULL || ampdu_pars->sta == NULL ||
|
||||
tx_info->rate_driver_data[0] == ampdu_pars->sta);
|
||||
rc = rc && ((u8)(mpdu->priority) == ampdu_pars->tid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* callback function that helps invalidating ampdu packets in a DMA queue
|
||||
*/
|
||||
|
@ -1218,15 +1143,5 @@ static void dma_cb_fn_ampdu(void *txi, void *arg_a)
|
|||
void brcms_c_ampdu_flush(struct brcms_c_info *wlc,
|
||||
struct ieee80211_sta *sta, u16 tid)
|
||||
{
|
||||
struct brcms_txq_info *qi = wlc->pkt_queue;
|
||||
struct pktq *pq = &qi->q;
|
||||
int prec;
|
||||
struct cb_del_ampdu_pars ampdu_pars;
|
||||
|
||||
ampdu_pars.sta = sta;
|
||||
ampdu_pars.tid = tid;
|
||||
for (prec = 0; prec < pq->num_prec; prec++)
|
||||
brcmu_pktq_pflush(pq, prec, true, cb_del_ampdu_pkt,
|
||||
(void *)&du_pars);
|
||||
brcms_c_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu);
|
||||
}
|
||||
|
|
|
@ -17,11 +17,34 @@
|
|||
#ifndef _BRCM_AMPDU_H_
|
||||
#define _BRCM_AMPDU_H_
|
||||
|
||||
/*
|
||||
* Data structure representing an in-progress session for accumulating
|
||||
* frames for AMPDU.
|
||||
*
|
||||
* wlc: pointer to common driver data
|
||||
* skb_list: queue of skb's for AMPDU
|
||||
* max_ampdu_len: maximum length for this AMPDU
|
||||
* max_ampdu_frames: maximum number of frames for this AMPDU
|
||||
* ampdu_len: total number of bytes accumulated for this AMPDU
|
||||
* dma_len: DMA length of this AMPDU
|
||||
*/
|
||||
struct brcms_ampdu_session {
|
||||
struct brcms_c_info *wlc;
|
||||
struct sk_buff_head skb_list;
|
||||
unsigned max_ampdu_len;
|
||||
u16 max_ampdu_frames;
|
||||
u16 ampdu_len;
|
||||
u16 dma_len;
|
||||
};
|
||||
|
||||
extern void brcms_c_ampdu_reset_session(struct brcms_ampdu_session *session,
|
||||
struct brcms_c_info *wlc);
|
||||
extern int brcms_c_ampdu_add_frame(struct brcms_ampdu_session *session,
|
||||
struct sk_buff *p);
|
||||
extern void brcms_c_ampdu_finalize(struct brcms_ampdu_session *session);
|
||||
|
||||
extern struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc);
|
||||
extern void brcms_c_ampdu_detach(struct ampdu_info *ampdu);
|
||||
extern int brcms_c_sendampdu(struct ampdu_info *ampdu,
|
||||
struct brcms_txq_info *qi,
|
||||
struct sk_buff **aggp, int prec);
|
||||
extern void brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
|
||||
struct sk_buff *p, struct tx_status *txs);
|
||||
extern void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc);
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "main.h"
|
||||
#include "phy_shim.h"
|
||||
#include "antsel.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define ANT_SELCFG_AUTO 0x80 /* bit indicates antenna sel AUTO */
|
||||
#define ANT_SELCFG_MASK 0x33 /* antenna configuration mask */
|
||||
|
@ -137,7 +138,8 @@ struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc)
|
|||
asi->antsel_avail = false;
|
||||
} else {
|
||||
asi->antsel_avail = false;
|
||||
wiphy_err(wlc->wiphy, "antsel_attach: 2o3 "
|
||||
brcms_err(wlc->hw->d11core,
|
||||
"antsel_attach: 2o3 "
|
||||
"board cfg invalid\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -14,22 +14,29 @@
|
|||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM brcmsmac
|
||||
|
||||
#if !defined(__TRACE_BRCMSMAC_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
|
||||
#define __TRACE_BRCMSMAC_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/tracepoint.h>
|
||||
#include "mac80211_if.h"
|
||||
|
||||
#ifndef CONFIG_BRCMDBG
|
||||
#ifndef CONFIG_BRCM_TRACING
|
||||
#undef TRACE_EVENT
|
||||
#define TRACE_EVENT(name, proto, ...) \
|
||||
static inline void trace_ ## name(proto) {}
|
||||
#undef DECLARE_EVENT_CLASS
|
||||
#define DECLARE_EVENT_CLASS(...)
|
||||
#undef DEFINE_EVENT
|
||||
#define DEFINE_EVENT(evt_class, name, proto, ...) \
|
||||
static inline void trace_ ## name(proto) {}
|
||||
#endif
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM brcmsmac
|
||||
|
||||
/*
|
||||
* We define a tracepoint, its arguments, its printk format and its
|
||||
* 'fast binary record' layout.
|
||||
|
@ -78,9 +85,165 @@ TRACE_EVENT(brcms_dpc,
|
|||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(brcms_macintstatus,
|
||||
TP_PROTO(const struct device *dev, int in_isr, u32 macintstatus,
|
||||
u32 mask),
|
||||
TP_ARGS(dev, in_isr, macintstatus, mask),
|
||||
TP_STRUCT__entry(
|
||||
__string(dev, dev_name(dev))
|
||||
__field(int, in_isr)
|
||||
__field(u32, macintstatus)
|
||||
__field(u32, mask)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__assign_str(dev, dev_name(dev));
|
||||
__entry->in_isr = in_isr;
|
||||
__entry->macintstatus = macintstatus;
|
||||
__entry->mask = mask;
|
||||
),
|
||||
TP_printk("[%s] in_isr=%d macintstatus=%#x mask=%#x", __get_str(dev),
|
||||
__entry->in_isr, __entry->macintstatus, __entry->mask)
|
||||
);
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM brcmsmac_tx
|
||||
|
||||
TRACE_EVENT(brcms_txdesc,
|
||||
TP_PROTO(const struct device *dev,
|
||||
void *txh, size_t txh_len),
|
||||
TP_ARGS(dev, txh, txh_len),
|
||||
TP_STRUCT__entry(
|
||||
__string(dev, dev_name(dev))
|
||||
__dynamic_array(u8, txh, txh_len)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__assign_str(dev, dev_name(dev));
|
||||
memcpy(__get_dynamic_array(txh), txh, txh_len);
|
||||
),
|
||||
TP_printk("[%s] txdesc", __get_str(dev))
|
||||
);
|
||||
|
||||
TRACE_EVENT(brcms_txstatus,
|
||||
TP_PROTO(const struct device *dev, u16 framelen, u16 frameid,
|
||||
u16 status, u16 lasttxtime, u16 sequence, u16 phyerr,
|
||||
u16 ackphyrxsh),
|
||||
TP_ARGS(dev, framelen, frameid, status, lasttxtime, sequence, phyerr,
|
||||
ackphyrxsh),
|
||||
TP_STRUCT__entry(
|
||||
__string(dev, dev_name(dev))
|
||||
__field(u16, framelen)
|
||||
__field(u16, frameid)
|
||||
__field(u16, status)
|
||||
__field(u16, lasttxtime)
|
||||
__field(u16, sequence)
|
||||
__field(u16, phyerr)
|
||||
__field(u16, ackphyrxsh)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__assign_str(dev, dev_name(dev));
|
||||
__entry->framelen = framelen;
|
||||
__entry->frameid = frameid;
|
||||
__entry->status = status;
|
||||
__entry->lasttxtime = lasttxtime;
|
||||
__entry->sequence = sequence;
|
||||
__entry->phyerr = phyerr;
|
||||
__entry->ackphyrxsh = ackphyrxsh;
|
||||
),
|
||||
TP_printk("[%s] FrameId %#04x TxStatus %#04x LastTxTime %#04x "
|
||||
"Seq %#04x PHYTxStatus %#04x RxAck %#04x",
|
||||
__get_str(dev), __entry->frameid, __entry->status,
|
||||
__entry->lasttxtime, __entry->sequence, __entry->phyerr,
|
||||
__entry->ackphyrxsh)
|
||||
);
|
||||
|
||||
TRACE_EVENT(brcms_ampdu_session,
|
||||
TP_PROTO(const struct device *dev, unsigned max_ampdu_len,
|
||||
u16 max_ampdu_frames, u16 ampdu_len, u16 ampdu_frames,
|
||||
u16 dma_len),
|
||||
TP_ARGS(dev, max_ampdu_len, max_ampdu_frames, ampdu_len, ampdu_frames,
|
||||
dma_len),
|
||||
TP_STRUCT__entry(
|
||||
__string(dev, dev_name(dev))
|
||||
__field(unsigned, max_ampdu_len)
|
||||
__field(u16, max_ampdu_frames)
|
||||
__field(u16, ampdu_len)
|
||||
__field(u16, ampdu_frames)
|
||||
__field(u16, dma_len)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__assign_str(dev, dev_name(dev));
|
||||
__entry->max_ampdu_len = max_ampdu_len;
|
||||
__entry->max_ampdu_frames = max_ampdu_frames;
|
||||
__entry->ampdu_len = ampdu_len;
|
||||
__entry->ampdu_frames = ampdu_frames;
|
||||
__entry->dma_len = dma_len;
|
||||
),
|
||||
TP_printk("[%s] ampdu session max_len=%u max_frames=%u len=%u frames=%u dma_len=%u",
|
||||
__get_str(dev), __entry->max_ampdu_len,
|
||||
__entry->max_ampdu_frames, __entry->ampdu_len,
|
||||
__entry->ampdu_frames, __entry->dma_len)
|
||||
);
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM brcmsmac_msg
|
||||
|
||||
#define MAX_MSG_LEN 100
|
||||
|
||||
DECLARE_EVENT_CLASS(brcms_msg_event,
|
||||
TP_PROTO(struct va_format *vaf),
|
||||
TP_ARGS(vaf),
|
||||
TP_STRUCT__entry(
|
||||
__dynamic_array(char, msg, MAX_MSG_LEN)
|
||||
),
|
||||
TP_fast_assign(
|
||||
WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
|
||||
MAX_MSG_LEN, vaf->fmt,
|
||||
*vaf->va) >= MAX_MSG_LEN);
|
||||
),
|
||||
TP_printk("%s", __get_str(msg))
|
||||
);
|
||||
|
||||
DEFINE_EVENT(brcms_msg_event, brcms_info,
|
||||
TP_PROTO(struct va_format *vaf),
|
||||
TP_ARGS(vaf)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(brcms_msg_event, brcms_warn,
|
||||
TP_PROTO(struct va_format *vaf),
|
||||
TP_ARGS(vaf)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(brcms_msg_event, brcms_err,
|
||||
TP_PROTO(struct va_format *vaf),
|
||||
TP_ARGS(vaf)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(brcms_msg_event, brcms_crit,
|
||||
TP_PROTO(struct va_format *vaf),
|
||||
TP_ARGS(vaf)
|
||||
);
|
||||
|
||||
TRACE_EVENT(brcms_dbg,
|
||||
TP_PROTO(u32 level, const char *func, struct va_format *vaf),
|
||||
TP_ARGS(level, func, vaf),
|
||||
TP_STRUCT__entry(
|
||||
__field(u32, level)
|
||||
__string(func, func)
|
||||
__dynamic_array(char, msg, MAX_MSG_LEN)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->level = level;
|
||||
__assign_str(func, func);
|
||||
WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
|
||||
MAX_MSG_LEN, vaf->fmt,
|
||||
*vaf->va) >= MAX_MSG_LEN);
|
||||
),
|
||||
TP_printk("%s: %s", __get_str(func), __get_str(msg))
|
||||
);
|
||||
|
||||
#endif /* __TRACE_BRCMSMAC_H */
|
||||
|
||||
#ifdef CONFIG_BRCMDBG
|
||||
#ifdef CONFIG_BRCM_TRACING
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
#define TRACE_INCLUDE_PATH .
|
||||
|
@ -89,4 +252,4 @@ TRACE_EVENT(brcms_dpc,
|
|||
|
||||
#include <trace/define_trace.h>
|
||||
|
||||
#endif /* CONFIG_BRCMDBG */
|
||||
#endif /* CONFIG_BRCM_TRACING */
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "stf.h"
|
||||
#include "channel.h"
|
||||
#include "mac80211_if.h"
|
||||
#include "debug.h"
|
||||
|
||||
/* QDB() macro takes a dB value and converts to a quarter dB value */
|
||||
#define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR)
|
||||
|
@ -336,8 +337,6 @@ struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)
|
|||
const char *ccode = sprom->alpha2;
|
||||
int ccode_len = sizeof(sprom->alpha2);
|
||||
|
||||
BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
|
||||
|
||||
wlc_cm = kzalloc(sizeof(struct brcms_cm_info), GFP_ATOMIC);
|
||||
if (wlc_cm == NULL)
|
||||
return NULL;
|
||||
|
@ -615,8 +614,8 @@ brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec)
|
|||
|
||||
/* check the chanspec */
|
||||
if (brcms_c_chspec_malformed(chspec)) {
|
||||
wiphy_err(wlc->wiphy, "wl%d: malformed chanspec 0x%x\n",
|
||||
wlc->pub->unit, chspec);
|
||||
brcms_err(wlc->hw->d11core, "wl%d: malformed chanspec 0x%x\n",
|
||||
wlc->pub->unit, chspec);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -738,7 +737,8 @@ static int brcms_reg_notifier(struct wiphy *wiphy,
|
|||
mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
|
||||
} else {
|
||||
mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
|
||||
wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\"\n",
|
||||
brcms_err(wlc->hw->d11core,
|
||||
"wl%d: %s: no valid channel for \"%s\"\n",
|
||||
wlc->pub->unit, __func__, request->alpha2);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
#include <linux/net.h>
|
||||
#include "types.h"
|
||||
#include "debug.h"
|
||||
#include "brcms_trace_events.h"
|
||||
|
||||
#define __brcms_fn(fn) \
|
||||
void __brcms_ ##fn(struct device *dev, const char *fmt, ...) \
|
||||
{ \
|
||||
struct va_format vaf = { \
|
||||
.fmt = fmt, \
|
||||
}; \
|
||||
va_list args; \
|
||||
\
|
||||
va_start(args, fmt); \
|
||||
vaf.va = &args; \
|
||||
dev_ ##fn(dev, "%pV", &vaf); \
|
||||
trace_brcms_ ##fn(&vaf); \
|
||||
va_end(args); \
|
||||
}
|
||||
|
||||
__brcms_fn(info)
|
||||
__brcms_fn(warn)
|
||||
__brcms_fn(err)
|
||||
__brcms_fn(crit)
|
||||
|
||||
#if defined(CONFIG_BRCMDBG) || defined(CONFIG_BRCM_TRACING)
|
||||
void __brcms_dbg(struct device *dev, u32 level, const char *func,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
struct va_format vaf = {
|
||||
.fmt = fmt,
|
||||
};
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
vaf.va = &args;
|
||||
#ifdef CONFIG_BRCMDBG
|
||||
if ((brcm_msg_level & level) && net_ratelimit())
|
||||
dev_err(dev, "%s %pV", func, &vaf);
|
||||
#endif
|
||||
trace_brcms_dbg(level, func, &vaf);
|
||||
va_end(args);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,52 @@
|
|||
#ifndef _BRCMS_DEBUG_H_
|
||||
#define _BRCMS_DEBUG_H_
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/bcma/bcma.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <net/mac80211.h>
|
||||
#include "main.h"
|
||||
#include "mac80211_if.h"
|
||||
|
||||
__printf(2, 3)
|
||||
void __brcms_info(struct device *dev, const char *fmt, ...);
|
||||
__printf(2, 3)
|
||||
void __brcms_warn(struct device *dev, const char *fmt, ...);
|
||||
__printf(2, 3)
|
||||
void __brcms_err(struct device *dev, const char *fmt, ...);
|
||||
__printf(2, 3)
|
||||
void __brcms_crit(struct device *dev, const char *fmt, ...);
|
||||
|
||||
#if defined(CONFIG_BRCMDBG) || defined(CONFIG_BRCM_TRACING)
|
||||
__printf(4, 5)
|
||||
void __brcms_dbg(struct device *dev, u32 level, const char *func,
|
||||
const char *fmt, ...);
|
||||
#else
|
||||
static inline __printf(4, 5)
|
||||
void __brcms_dbg(struct device *dev, u32 level, const char *func,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Debug macros cannot be used when wlc is uninitialized. Generally
|
||||
* this means any code that could run before brcms_c_attach() has
|
||||
* returned successfully probably shouldn't use the following macros.
|
||||
*/
|
||||
|
||||
#define brcms_dbg(core, l, f, a...) __brcms_dbg(&(core)->dev, l, __func__, f, ##a)
|
||||
#define brcms_info(core, f, a...) __brcms_info(&(core)->dev, f, ##a)
|
||||
#define brcms_warn(core, f, a...) __brcms_warn(&(core)->dev, f, ##a)
|
||||
#define brcms_err(core, f, a...) __brcms_err(&(core)->dev, f, ##a)
|
||||
#define brcms_crit(core, f, a...) __brcms_crit(&(core)->dev, f, ##a)
|
||||
|
||||
#define brcms_dbg_info(core, f, a...) brcms_dbg(core, BRCM_DL_INFO, f, ##a)
|
||||
#define brcms_dbg_mac80211(core, f, a...) brcms_dbg(core, BRCM_DL_MAC80211, f, ##a)
|
||||
#define brcms_dbg_rx(core, f, a...) brcms_dbg(core, BRCM_DL_RX, f, ##a)
|
||||
#define brcms_dbg_tx(core, f, a...) brcms_dbg(core, BRCM_DL_TX, f, ##a)
|
||||
#define brcms_dbg_int(core, f, a...) brcms_dbg(core, BRCM_DL_INT, f, ##a)
|
||||
#define brcms_dbg_dma(core, f, a...) brcms_dbg(core, BRCM_DL_DMA, f, ##a)
|
||||
#define brcms_dbg_ht(core, f, a...) brcms_dbg(core, BRCM_DL_HT, f, ##a)
|
||||
|
||||
#endif /* _BRCMS_DEBUG_H_ */
|
|
@ -14,17 +14,22 @@
|
|||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pci.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include <brcmu_utils.h>
|
||||
#include <aiutils.h>
|
||||
#include "types.h"
|
||||
#include "main.h"
|
||||
#include "dma.h"
|
||||
#include "soc.h"
|
||||
#include "scb.h"
|
||||
#include "ampdu.h"
|
||||
#include "debug.h"
|
||||
#include "brcms_trace_events.h"
|
||||
|
||||
/*
|
||||
* dma register field offset calculation
|
||||
|
@ -176,28 +181,6 @@
|
|||
|
||||
#define BCMEXTRAHDROOM 172
|
||||
|
||||
/* debug/trace */
|
||||
#ifdef DEBUG
|
||||
#define DMA_ERROR(fmt, ...) \
|
||||
do { \
|
||||
if (*di->msg_level & 1) \
|
||||
pr_debug("%s: " fmt, __func__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define DMA_TRACE(fmt, ...) \
|
||||
do { \
|
||||
if (*di->msg_level & 2) \
|
||||
pr_debug("%s: " fmt, __func__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define DMA_ERROR(fmt, ...) \
|
||||
no_printk(fmt, ##__VA_ARGS__)
|
||||
#define DMA_TRACE(fmt, ...) \
|
||||
no_printk(fmt, ##__VA_ARGS__)
|
||||
#endif /* DEBUG */
|
||||
|
||||
#define DMA_NONE(fmt, ...) \
|
||||
no_printk(fmt, ##__VA_ARGS__)
|
||||
|
||||
#define MAXNAMEL 8 /* 8 char names */
|
||||
|
||||
/* macros to convert between byte offsets and indexes */
|
||||
|
@ -224,12 +207,14 @@ struct dma64desc {
|
|||
/* dma engine software state */
|
||||
struct dma_info {
|
||||
struct dma_pub dma; /* exported structure */
|
||||
uint *msg_level; /* message level pointer */
|
||||
char name[MAXNAMEL]; /* callers name for diag msgs */
|
||||
|
||||
struct bcma_device *core;
|
||||
struct device *dmadev;
|
||||
|
||||
/* session information for AMPDU */
|
||||
struct brcms_ampdu_session ampdu_session;
|
||||
|
||||
bool dma64; /* this dma engine is operating in 64-bit mode */
|
||||
bool addrext; /* this dma engine supports DmaExtendedAddrChanges */
|
||||
|
||||
|
@ -298,12 +283,6 @@ struct dma_info {
|
|||
bool aligndesc_4k;
|
||||
};
|
||||
|
||||
/*
|
||||
* default dma message level (if input msg_level
|
||||
* pointer is null in dma_attach())
|
||||
*/
|
||||
static uint dma_msg_level;
|
||||
|
||||
/* Check for odd number of 1's */
|
||||
static u32 parity32(__le32 data)
|
||||
{
|
||||
|
@ -353,7 +332,7 @@ static uint prevtxd(struct dma_info *di, uint i)
|
|||
|
||||
static uint nextrxd(struct dma_info *di, uint i)
|
||||
{
|
||||
return txd(di, i + 1);
|
||||
return rxd(di, i + 1);
|
||||
}
|
||||
|
||||
static uint ntxdactive(struct dma_info *di, uint h, uint t)
|
||||
|
@ -371,7 +350,7 @@ static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags)
|
|||
uint dmactrlflags;
|
||||
|
||||
if (di == NULL) {
|
||||
DMA_ERROR("NULL dma handle\n");
|
||||
brcms_dbg_dma(di->core, "NULL dma handle\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -423,13 +402,15 @@ static bool _dma_isaddrext(struct dma_info *di)
|
|||
/* not all tx or rx channel are available */
|
||||
if (di->d64txregbase != 0) {
|
||||
if (!_dma64_addrext(di, DMA64TXREGOFFS(di, control)))
|
||||
DMA_ERROR("%s: DMA64 tx doesn't have AE set\n",
|
||||
di->name);
|
||||
brcms_dbg_dma(di->core,
|
||||
"%s: DMA64 tx doesn't have AE set\n",
|
||||
di->name);
|
||||
return true;
|
||||
} else if (di->d64rxregbase != 0) {
|
||||
if (!_dma64_addrext(di, DMA64RXREGOFFS(di, control)))
|
||||
DMA_ERROR("%s: DMA64 rx doesn't have AE set\n",
|
||||
di->name);
|
||||
brcms_dbg_dma(di->core,
|
||||
"%s: DMA64 rx doesn't have AE set\n",
|
||||
di->name);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -530,8 +511,9 @@ static bool dma64_alloc(struct dma_info *di, uint direction)
|
|||
va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,
|
||||
&alloced, &di->txdpaorig);
|
||||
if (va == NULL) {
|
||||
DMA_ERROR("%s: DMA_ALLOC_CONSISTENT(ntxd) failed\n",
|
||||
di->name);
|
||||
brcms_dbg_dma(di->core,
|
||||
"%s: DMA_ALLOC_CONSISTENT(ntxd) failed\n",
|
||||
di->name);
|
||||
return false;
|
||||
}
|
||||
align = (1 << align_bits);
|
||||
|
@ -544,8 +526,9 @@ static bool dma64_alloc(struct dma_info *di, uint direction)
|
|||
va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,
|
||||
&alloced, &di->rxdpaorig);
|
||||
if (va == NULL) {
|
||||
DMA_ERROR("%s: DMA_ALLOC_CONSISTENT(nrxd) failed\n",
|
||||
di->name);
|
||||
brcms_dbg_dma(di->core,
|
||||
"%s: DMA_ALLOC_CONSISTENT(nrxd) failed\n",
|
||||
di->name);
|
||||
return false;
|
||||
}
|
||||
align = (1 << align_bits);
|
||||
|
@ -564,12 +547,13 @@ static bool _dma_alloc(struct dma_info *di, uint direction)
|
|||
return dma64_alloc(di, direction);
|
||||
}
|
||||
|
||||
struct dma_pub *dma_attach(char *name, struct si_pub *sih,
|
||||
struct bcma_device *core,
|
||||
struct dma_pub *dma_attach(char *name, struct brcms_c_info *wlc,
|
||||
uint txregbase, uint rxregbase, uint ntxd, uint nrxd,
|
||||
uint rxbufsize, int rxextheadroom,
|
||||
uint nrxpost, uint rxoffset, uint *msg_level)
|
||||
uint nrxpost, uint rxoffset)
|
||||
{
|
||||
struct si_pub *sih = wlc->hw->sih;
|
||||
struct bcma_device *core = wlc->hw->d11core;
|
||||
struct dma_info *di;
|
||||
u8 rev = core->id.rev;
|
||||
uint size;
|
||||
|
@ -580,9 +564,6 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
|
|||
if (di == NULL)
|
||||
return NULL;
|
||||
|
||||
di->msg_level = msg_level ? msg_level : &dma_msg_level;
|
||||
|
||||
|
||||
di->dma64 =
|
||||
((bcma_aread32(core, BCMA_IOST) & SISF_DMA64) == SISF_DMA64);
|
||||
|
||||
|
@ -598,11 +579,11 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
|
|||
*/
|
||||
_dma_ctrlflags(di, DMA_CTRL_ROC | DMA_CTRL_PEN, 0);
|
||||
|
||||
DMA_TRACE("%s: %s flags 0x%x ntxd %d nrxd %d "
|
||||
"rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d "
|
||||
"txregbase %u rxregbase %u\n", name, "DMA64",
|
||||
di->dma.dmactrlflags, ntxd, nrxd, rxbufsize,
|
||||
rxextheadroom, nrxpost, rxoffset, txregbase, rxregbase);
|
||||
brcms_dbg_dma(di->core, "%s: %s flags 0x%x ntxd %d nrxd %d "
|
||||
"rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d "
|
||||
"txregbase %u rxregbase %u\n", name, "DMA64",
|
||||
di->dma.dmactrlflags, ntxd, nrxd, rxbufsize,
|
||||
rxextheadroom, nrxpost, rxoffset, txregbase, rxregbase);
|
||||
|
||||
/* make a private copy of our callers name */
|
||||
strncpy(di->name, name, MAXNAMEL);
|
||||
|
@ -664,8 +645,8 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
|
|||
di->dmadesc_align = 4; /* 16 byte alignment */
|
||||
}
|
||||
|
||||
DMA_NONE("DMA descriptor align_needed %d, align %d\n",
|
||||
di->aligndesc_4k, di->dmadesc_align);
|
||||
brcms_dbg_dma(di->core, "DMA descriptor align_needed %d, align %d\n",
|
||||
di->aligndesc_4k, di->dmadesc_align);
|
||||
|
||||
/* allocate tx packet pointer vector */
|
||||
if (ntxd) {
|
||||
|
@ -703,21 +684,27 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
|
|||
|
||||
if ((di->ddoffsetlow != 0) && !di->addrext) {
|
||||
if (di->txdpa > SI_PCI_DMA_SZ) {
|
||||
DMA_ERROR("%s: txdpa 0x%x: addrext not supported\n",
|
||||
di->name, (u32)di->txdpa);
|
||||
brcms_dbg_dma(di->core,
|
||||
"%s: txdpa 0x%x: addrext not supported\n",
|
||||
di->name, (u32)di->txdpa);
|
||||
goto fail;
|
||||
}
|
||||
if (di->rxdpa > SI_PCI_DMA_SZ) {
|
||||
DMA_ERROR("%s: rxdpa 0x%x: addrext not supported\n",
|
||||
di->name, (u32)di->rxdpa);
|
||||
brcms_dbg_dma(di->core,
|
||||
"%s: rxdpa 0x%x: addrext not supported\n",
|
||||
di->name, (u32)di->rxdpa);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
DMA_TRACE("ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x dataoffsethigh 0x%x addrext %d\n",
|
||||
di->ddoffsetlow, di->ddoffsethigh,
|
||||
di->dataoffsetlow, di->dataoffsethigh,
|
||||
di->addrext);
|
||||
/* Initialize AMPDU session */
|
||||
brcms_c_ampdu_reset_session(&di->ampdu_session, wlc);
|
||||
|
||||
brcms_dbg_dma(di->core,
|
||||
"ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x dataoffsethigh 0x%x addrext %d\n",
|
||||
di->ddoffsetlow, di->ddoffsethigh,
|
||||
di->dataoffsetlow, di->dataoffsethigh,
|
||||
di->addrext);
|
||||
|
||||
return (struct dma_pub *) di;
|
||||
|
||||
|
@ -763,7 +750,7 @@ void dma_detach(struct dma_pub *pub)
|
|||
{
|
||||
struct dma_info *di = (struct dma_info *)pub;
|
||||
|
||||
DMA_TRACE("%s:\n", di->name);
|
||||
brcms_dbg_dma(di->core, "%s:\n", di->name);
|
||||
|
||||
/* free dma descriptor rings */
|
||||
if (di->txd64)
|
||||
|
@ -839,7 +826,7 @@ static void _dma_rxenable(struct dma_info *di)
|
|||
uint dmactrlflags = di->dma.dmactrlflags;
|
||||
u32 control;
|
||||
|
||||
DMA_TRACE("%s:\n", di->name);
|
||||
brcms_dbg_dma(di->core, "%s:\n", di->name);
|
||||
|
||||
control = D64_RC_RE | (bcma_read32(di->core,
|
||||
DMA64RXREGOFFS(di, control)) &
|
||||
|
@ -859,7 +846,7 @@ void dma_rxinit(struct dma_pub *pub)
|
|||
{
|
||||
struct dma_info *di = (struct dma_info *)pub;
|
||||
|
||||
DMA_TRACE("%s:\n", di->name);
|
||||
brcms_dbg_dma(di->core, "%s:\n", di->name);
|
||||
|
||||
if (di->nrxd == 0)
|
||||
return;
|
||||
|
@ -954,7 +941,7 @@ int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list)
|
|||
return 0;
|
||||
|
||||
len = le16_to_cpu(*(__le16 *) (p->data));
|
||||
DMA_TRACE("%s: dma_rx len %d\n", di->name, len);
|
||||
brcms_dbg_dma(di->core, "%s: dma_rx len %d\n", di->name, len);
|
||||
dma_spin_for_len(len, p);
|
||||
|
||||
/* set actual length */
|
||||
|
@ -981,14 +968,15 @@ int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list)
|
|||
DMA64RXREGOFFS(di, status0)) &
|
||||
D64_RS0_CD_MASK) - di->rcvptrbase) &
|
||||
D64_RS0_CD_MASK, struct dma64desc);
|
||||
DMA_ERROR("rxin %d rxout %d, hw_curr %d\n",
|
||||
di->rxin, di->rxout, cur);
|
||||
brcms_dbg_dma(di->core,
|
||||
"rxin %d rxout %d, hw_curr %d\n",
|
||||
di->rxin, di->rxout, cur);
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
if ((di->dma.dmactrlflags & DMA_CTRL_RXMULTI) == 0) {
|
||||
DMA_ERROR("%s: bad frame length (%d)\n",
|
||||
di->name, len);
|
||||
brcms_dbg_dma(di->core, "%s: bad frame length (%d)\n",
|
||||
di->name, len);
|
||||
skb_queue_walk_safe(&dma_frames, p, next) {
|
||||
skb_unlink(p, &dma_frames);
|
||||
brcmu_pkt_buf_free_skb(p);
|
||||
|
@ -1005,7 +993,7 @@ int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list)
|
|||
|
||||
static bool dma64_rxidle(struct dma_info *di)
|
||||
{
|
||||
DMA_TRACE("%s:\n", di->name);
|
||||
brcms_dbg_dma(di->core, "%s:\n", di->name);
|
||||
|
||||
if (di->nrxd == 0)
|
||||
return true;
|
||||
|
@ -1016,6 +1004,17 @@ static bool dma64_rxidle(struct dma_info *di)
|
|||
D64_RS0_CD_MASK));
|
||||
}
|
||||
|
||||
static bool dma64_txidle(struct dma_info *di)
|
||||
{
|
||||
if (di->ntxd == 0)
|
||||
return true;
|
||||
|
||||
return ((bcma_read32(di->core,
|
||||
DMA64TXREGOFFS(di, status0)) & D64_XS0_CD_MASK) ==
|
||||
(bcma_read32(di->core, DMA64TXREGOFFS(di, ptr)) &
|
||||
D64_XS0_CD_MASK));
|
||||
}
|
||||
|
||||
/*
|
||||
* post receive buffers
|
||||
* return false is refill failed completely and ring is empty this will stall
|
||||
|
@ -1047,7 +1046,7 @@ bool dma_rxfill(struct dma_pub *pub)
|
|||
|
||||
n = di->nrxpost - nrxdactive(di, rxin, rxout);
|
||||
|
||||
DMA_TRACE("%s: post %d\n", di->name, n);
|
||||
brcms_dbg_dma(di->core, "%s: post %d\n", di->name, n);
|
||||
|
||||
if (di->rxbufsize > BCMEXTRAHDROOM)
|
||||
extra_offset = di->rxextrahdrroom;
|
||||
|
@ -1060,9 +1059,11 @@ bool dma_rxfill(struct dma_pub *pub)
|
|||
p = brcmu_pkt_buf_get_skb(di->rxbufsize + extra_offset);
|
||||
|
||||
if (p == NULL) {
|
||||
DMA_ERROR("%s: out of rxbufs\n", di->name);
|
||||
brcms_dbg_dma(di->core, "%s: out of rxbufs\n",
|
||||
di->name);
|
||||
if (i == 0 && dma64_rxidle(di)) {
|
||||
DMA_ERROR("%s: ring is empty !\n", di->name);
|
||||
brcms_dbg_dma(di->core, "%s: ring is empty !\n",
|
||||
di->name);
|
||||
ring_empty = true;
|
||||
}
|
||||
di->dma.rxnobuf++;
|
||||
|
@ -1107,7 +1108,7 @@ void dma_rxreclaim(struct dma_pub *pub)
|
|||
struct dma_info *di = (struct dma_info *)pub;
|
||||
struct sk_buff *p;
|
||||
|
||||
DMA_TRACE("%s:\n", di->name);
|
||||
brcms_dbg_dma(di->core, "%s:\n", di->name);
|
||||
|
||||
while ((p = _dma_getnextrxp(di, true)))
|
||||
brcmu_pkt_buf_free_skb(p);
|
||||
|
@ -1138,7 +1139,7 @@ void dma_txinit(struct dma_pub *pub)
|
|||
struct dma_info *di = (struct dma_info *)pub;
|
||||
u32 control = D64_XC_XE;
|
||||
|
||||
DMA_TRACE("%s:\n", di->name);
|
||||
brcms_dbg_dma(di->core, "%s:\n", di->name);
|
||||
|
||||
if (di->ntxd == 0)
|
||||
return;
|
||||
|
@ -1170,7 +1171,7 @@ void dma_txsuspend(struct dma_pub *pub)
|
|||
{
|
||||
struct dma_info *di = (struct dma_info *)pub;
|
||||
|
||||
DMA_TRACE("%s:\n", di->name);
|
||||
brcms_dbg_dma(di->core, "%s:\n", di->name);
|
||||
|
||||
if (di->ntxd == 0)
|
||||
return;
|
||||
|
@ -1182,7 +1183,7 @@ void dma_txresume(struct dma_pub *pub)
|
|||
{
|
||||
struct dma_info *di = (struct dma_info *)pub;
|
||||
|
||||
DMA_TRACE("%s:\n", di->name);
|
||||
brcms_dbg_dma(di->core, "%s:\n", di->name);
|
||||
|
||||
if (di->ntxd == 0)
|
||||
return;
|
||||
|
@ -1205,11 +1206,11 @@ void dma_txreclaim(struct dma_pub *pub, enum txd_range range)
|
|||
struct dma_info *di = (struct dma_info *)pub;
|
||||
struct sk_buff *p;
|
||||
|
||||
DMA_TRACE("%s: %s\n",
|
||||
di->name,
|
||||
range == DMA_RANGE_ALL ? "all" :
|
||||
range == DMA_RANGE_TRANSMITTED ? "transmitted" :
|
||||
"transferred");
|
||||
brcms_dbg_dma(di->core, "%s: %s\n",
|
||||
di->name,
|
||||
range == DMA_RANGE_ALL ? "all" :
|
||||
range == DMA_RANGE_TRANSMITTED ? "transmitted" :
|
||||
"transferred");
|
||||
|
||||
if (di->txin == di->txout)
|
||||
return;
|
||||
|
@ -1264,39 +1265,25 @@ bool dma_rxreset(struct dma_pub *pub)
|
|||
return status == D64_RS0_RS_DISABLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* !! tx entry routine
|
||||
* WARNING: call must check the return value for error.
|
||||
* the error(toss frames) could be fatal and cause many subsequent hard
|
||||
* to debug problems
|
||||
*/
|
||||
int dma_txfast(struct dma_pub *pub, struct sk_buff *p, bool commit)
|
||||
static void dma_txenq(struct dma_info *di, struct sk_buff *p)
|
||||
{
|
||||
struct dma_info *di = (struct dma_info *)pub;
|
||||
unsigned char *data;
|
||||
uint len;
|
||||
u16 txout;
|
||||
u32 flags = 0;
|
||||
dma_addr_t pa;
|
||||
|
||||
DMA_TRACE("%s:\n", di->name);
|
||||
|
||||
txout = di->txout;
|
||||
|
||||
if (WARN_ON(nexttxd(di, txout) == di->txin))
|
||||
return;
|
||||
|
||||
/*
|
||||
* obtain and initialize transmit descriptor entry.
|
||||
*/
|
||||
data = p->data;
|
||||
len = p->len;
|
||||
|
||||
/* no use to transmit a zero length packet */
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
/* return nonzero if out of tx descriptors */
|
||||
if (nexttxd(di, txout) == di->txin)
|
||||
goto outoftxd;
|
||||
|
||||
/* get physical address of buffer start */
|
||||
pa = dma_map_single(di->dmadev, data, len, DMA_TO_DEVICE);
|
||||
|
||||
|
@ -1318,23 +1305,147 @@ int dma_txfast(struct dma_pub *pub, struct sk_buff *p, bool commit)
|
|||
|
||||
/* bump the tx descriptor index */
|
||||
di->txout = txout;
|
||||
}
|
||||
|
||||
/* kick the chip */
|
||||
if (commit)
|
||||
bcma_write32(di->core, DMA64TXREGOFFS(di, ptr),
|
||||
di->xmtptrbase + I2B(txout, struct dma64desc));
|
||||
static void ampdu_finalize(struct dma_info *di)
|
||||
{
|
||||
struct brcms_ampdu_session *session = &di->ampdu_session;
|
||||
struct sk_buff *p;
|
||||
|
||||
trace_brcms_ampdu_session(&session->wlc->hw->d11core->dev,
|
||||
session->max_ampdu_len,
|
||||
session->max_ampdu_frames,
|
||||
session->ampdu_len,
|
||||
skb_queue_len(&session->skb_list),
|
||||
session->dma_len);
|
||||
|
||||
if (WARN_ON(skb_queue_empty(&session->skb_list)))
|
||||
return;
|
||||
|
||||
brcms_c_ampdu_finalize(session);
|
||||
|
||||
while (!skb_queue_empty(&session->skb_list)) {
|
||||
p = skb_dequeue(&session->skb_list);
|
||||
dma_txenq(di, p);
|
||||
}
|
||||
|
||||
bcma_write32(di->core, DMA64TXREGOFFS(di, ptr),
|
||||
di->xmtptrbase + I2B(di->txout, struct dma64desc));
|
||||
brcms_c_ampdu_reset_session(session, session->wlc);
|
||||
}
|
||||
|
||||
static void prep_ampdu_frame(struct dma_info *di, struct sk_buff *p)
|
||||
{
|
||||
struct brcms_ampdu_session *session = &di->ampdu_session;
|
||||
int ret;
|
||||
|
||||
ret = brcms_c_ampdu_add_frame(session, p);
|
||||
if (ret == -ENOSPC) {
|
||||
/*
|
||||
* AMPDU cannot accomodate this frame. Close out the in-
|
||||
* progress AMPDU session and start a new one.
|
||||
*/
|
||||
ampdu_finalize(di);
|
||||
ret = brcms_c_ampdu_add_frame(session, p);
|
||||
}
|
||||
|
||||
WARN_ON(ret);
|
||||
}
|
||||
|
||||
/* Update count of available tx descriptors based on current DMA state */
|
||||
static void dma_update_txavail(struct dma_info *di)
|
||||
{
|
||||
/*
|
||||
* Available space is number of descriptors less the number of
|
||||
* active descriptors and the number of queued AMPDU frames.
|
||||
*/
|
||||
di->dma.txavail = di->ntxd - ntxdactive(di, di->txin, di->txout) -
|
||||
skb_queue_len(&di->ampdu_session.skb_list) - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* !! tx entry routine
|
||||
* WARNING: call must check the return value for error.
|
||||
* the error(toss frames) could be fatal and cause many subsequent hard
|
||||
* to debug problems
|
||||
*/
|
||||
int dma_txfast(struct brcms_c_info *wlc, struct dma_pub *pub,
|
||||
struct sk_buff *p)
|
||||
{
|
||||
struct dma_info *di = (struct dma_info *)pub;
|
||||
struct brcms_ampdu_session *session = &di->ampdu_session;
|
||||
struct ieee80211_tx_info *tx_info;
|
||||
bool is_ampdu;
|
||||
|
||||
/* no use to transmit a zero length packet */
|
||||
if (p->len == 0)
|
||||
return 0;
|
||||
|
||||
/* return nonzero if out of tx descriptors */
|
||||
if (di->dma.txavail == 0 || nexttxd(di, di->txout) == di->txin)
|
||||
goto outoftxd;
|
||||
|
||||
tx_info = IEEE80211_SKB_CB(p);
|
||||
is_ampdu = tx_info->flags & IEEE80211_TX_CTL_AMPDU;
|
||||
if (is_ampdu)
|
||||
prep_ampdu_frame(di, p);
|
||||
else
|
||||
dma_txenq(di, p);
|
||||
|
||||
/* tx flow control */
|
||||
di->dma.txavail = di->ntxd - ntxdactive(di, di->txin, di->txout) - 1;
|
||||
dma_update_txavail(di);
|
||||
|
||||
/* kick the chip */
|
||||
if (is_ampdu) {
|
||||
/*
|
||||
* Start sending data if we've got a full AMPDU, there's
|
||||
* no more space in the DMA ring, or the ring isn't
|
||||
* currently transmitting.
|
||||
*/
|
||||
if (skb_queue_len(&session->skb_list) == session->max_ampdu_frames ||
|
||||
di->dma.txavail == 0 || dma64_txidle(di))
|
||||
ampdu_finalize(di);
|
||||
} else {
|
||||
bcma_write32(di->core, DMA64TXREGOFFS(di, ptr),
|
||||
di->xmtptrbase + I2B(di->txout, struct dma64desc));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
outoftxd:
|
||||
DMA_ERROR("%s: out of txds !!!\n", di->name);
|
||||
brcms_dbg_dma(di->core, "%s: out of txds !!!\n", di->name);
|
||||
brcmu_pkt_buf_free_skb(p);
|
||||
di->dma.txavail = 0;
|
||||
di->dma.txnobuf++;
|
||||
return -1;
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
void dma_txflush(struct dma_pub *pub)
|
||||
{
|
||||
struct dma_info *di = (struct dma_info *)pub;
|
||||
struct brcms_ampdu_session *session = &di->ampdu_session;
|
||||
|
||||
if (!skb_queue_empty(&session->skb_list))
|
||||
ampdu_finalize(di);
|
||||
}
|
||||
|
||||
int dma_txpending(struct dma_pub *pub)
|
||||
{
|
||||
struct dma_info *di = (struct dma_info *)pub;
|
||||
return ntxdactive(di, di->txin, di->txout);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have an active AMPDU session and are not transmitting,
|
||||
* this function will force tx to start.
|
||||
*/
|
||||
void dma_kick_tx(struct dma_pub *pub)
|
||||
{
|
||||
struct dma_info *di = (struct dma_info *)pub;
|
||||
struct brcms_ampdu_session *session = &di->ampdu_session;
|
||||
|
||||
if (!skb_queue_empty(&session->skb_list) && dma64_txidle(di))
|
||||
ampdu_finalize(di);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1354,11 +1465,11 @@ struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range)
|
|||
u16 active_desc;
|
||||
struct sk_buff *txp;
|
||||
|
||||
DMA_TRACE("%s: %s\n",
|
||||
di->name,
|
||||
range == DMA_RANGE_ALL ? "all" :
|
||||
range == DMA_RANGE_TRANSMITTED ? "transmitted" :
|
||||
"transferred");
|
||||
brcms_dbg_dma(di->core, "%s: %s\n",
|
||||
di->name,
|
||||
range == DMA_RANGE_ALL ? "all" :
|
||||
range == DMA_RANGE_TRANSMITTED ? "transmitted" :
|
||||
"transferred");
|
||||
|
||||
if (di->ntxd == 0)
|
||||
return NULL;
|
||||
|
@ -1412,13 +1523,13 @@ struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range)
|
|||
di->txin = i;
|
||||
|
||||
/* tx flow control */
|
||||
di->dma.txavail = di->ntxd - ntxdactive(di, di->txin, di->txout) - 1;
|
||||
dma_update_txavail(di);
|
||||
|
||||
return txp;
|
||||
|
||||
bogus:
|
||||
DMA_NONE("bogus curr: start %d end %d txout %d\n",
|
||||
start, end, di->txout);
|
||||
brcms_dbg_dma(di->core, "bogus curr: start %d end %d txout %d\n",
|
||||
start, end, di->txout);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -74,12 +74,11 @@ struct dma_pub {
|
|||
uint txnobuf; /* tx out of dma descriptors */
|
||||
};
|
||||
|
||||
extern struct dma_pub *dma_attach(char *name, struct si_pub *sih,
|
||||
struct bcma_device *d11core,
|
||||
extern struct dma_pub *dma_attach(char *name, struct brcms_c_info *wlc,
|
||||
uint txregbase, uint rxregbase,
|
||||
uint ntxd, uint nrxd,
|
||||
uint rxbufsize, int rxextheadroom,
|
||||
uint nrxpost, uint rxoffset, uint *msg_level);
|
||||
uint nrxpost, uint rxoffset);
|
||||
|
||||
void dma_rxinit(struct dma_pub *pub);
|
||||
int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list);
|
||||
|
@ -87,7 +86,11 @@ bool dma_rxfill(struct dma_pub *pub);
|
|||
bool dma_rxreset(struct dma_pub *pub);
|
||||
bool dma_txreset(struct dma_pub *pub);
|
||||
void dma_txinit(struct dma_pub *pub);
|
||||
int dma_txfast(struct dma_pub *pub, struct sk_buff *p0, bool commit);
|
||||
int dma_txfast(struct brcms_c_info *wlc, struct dma_pub *pub,
|
||||
struct sk_buff *p0);
|
||||
void dma_txflush(struct dma_pub *pub);
|
||||
int dma_txpending(struct dma_pub *pub);
|
||||
void dma_kick_tx(struct dma_pub *pub);
|
||||
void dma_txsuspend(struct dma_pub *pub);
|
||||
bool dma_txsuspended(struct dma_pub *pub);
|
||||
void dma_txresume(struct dma_pub *pub);
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "ucode_loader.h"
|
||||
#include "mac80211_if.h"
|
||||
#include "main.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define N_TX_QUEUES 4 /* #tx queues on mac80211<->driver interface */
|
||||
|
||||
|
@ -98,10 +99,14 @@ static struct bcma_device_id brcms_coreid_table[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(bcma, brcms_coreid_table);
|
||||
|
||||
#ifdef DEBUG
|
||||
static int msglevel = 0xdeadbeef;
|
||||
module_param(msglevel, int, 0);
|
||||
#endif /* DEBUG */
|
||||
#if defined(CONFIG_BRCMDBG)
|
||||
/*
|
||||
* Module parameter for setting the debug message level. Available
|
||||
* flags are specified by the BRCM_DL_* macros in
|
||||
* drivers/net/wireless/brcm80211/include/defs.h.
|
||||
*/
|
||||
module_param_named(debug, brcm_msg_level, uint, S_IRUGO | S_IWUSR);
|
||||
#endif
|
||||
|
||||
static struct ieee80211_channel brcms_2ghz_chantable[] = {
|
||||
CHAN2GHZ(1, 2412, IEEE80211_CHAN_NO_HT40MINUS),
|
||||
|
@ -276,7 +281,7 @@ static void brcms_ops_tx(struct ieee80211_hw *hw,
|
|||
|
||||
spin_lock_bh(&wl->lock);
|
||||
if (!wl->pub->up) {
|
||||
wiphy_err(wl->wiphy, "ops->tx called while down\n");
|
||||
brcms_err(wl->wlc->hw->d11core, "ops->tx called while down\n");
|
||||
kfree_skb(skb);
|
||||
goto done;
|
||||
}
|
||||
|
@ -313,8 +318,8 @@ static int brcms_ops_start(struct ieee80211_hw *hw)
|
|||
spin_unlock_bh(&wl->lock);
|
||||
|
||||
if (err != 0)
|
||||
wiphy_err(hw->wiphy, "%s: brcms_up() returned %d\n", __func__,
|
||||
err);
|
||||
brcms_err(wl->wlc->hw->d11core, "%s: brcms_up() returned %d\n",
|
||||
__func__, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -332,7 +337,7 @@ static void brcms_ops_stop(struct ieee80211_hw *hw)
|
|||
status = brcms_c_chipmatch(wl->wlc->hw->d11core);
|
||||
spin_unlock_bh(&wl->lock);
|
||||
if (!status) {
|
||||
wiphy_err(wl->wiphy,
|
||||
brcms_err(wl->wlc->hw->d11core,
|
||||
"wl: brcms_ops_stop: chipmatch failed\n");
|
||||
return;
|
||||
}
|
||||
|
@ -350,8 +355,9 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
|||
|
||||
/* Just STA for now */
|
||||
if (vif->type != NL80211_IFTYPE_STATION) {
|
||||
wiphy_err(hw->wiphy, "%s: Attempt to add type %d, only"
|
||||
" STA for now\n", __func__, vif->type);
|
||||
brcms_err(wl->wlc->hw->d11core,
|
||||
"%s: Attempt to add type %d, only STA for now\n",
|
||||
__func__, vif->type);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
|
@ -370,9 +376,9 @@ static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed)
|
|||
{
|
||||
struct ieee80211_conf *conf = &hw->conf;
|
||||
struct brcms_info *wl = hw->priv;
|
||||
struct bcma_device *core = wl->wlc->hw->d11core;
|
||||
int err = 0;
|
||||
int new_int;
|
||||
struct wiphy *wiphy = hw->wiphy;
|
||||
|
||||
spin_lock_bh(&wl->lock);
|
||||
if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {
|
||||
|
@ -380,25 +386,26 @@ static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed)
|
|||
conf->listen_interval);
|
||||
}
|
||||
if (changed & IEEE80211_CONF_CHANGE_MONITOR)
|
||||
wiphy_dbg(wiphy, "%s: change monitor mode: %s\n",
|
||||
__func__, conf->flags & IEEE80211_CONF_MONITOR ?
|
||||
"true" : "false");
|
||||
brcms_dbg_info(core, "%s: change monitor mode: %s\n",
|
||||
__func__, conf->flags & IEEE80211_CONF_MONITOR ?
|
||||
"true" : "false");
|
||||
if (changed & IEEE80211_CONF_CHANGE_PS)
|
||||
wiphy_err(wiphy, "%s: change power-save mode: %s (implement)\n",
|
||||
brcms_err(core, "%s: change power-save mode: %s (implement)\n",
|
||||
__func__, conf->flags & IEEE80211_CONF_PS ?
|
||||
"true" : "false");
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_POWER) {
|
||||
err = brcms_c_set_tx_power(wl->wlc, conf->power_level);
|
||||
if (err < 0) {
|
||||
wiphy_err(wiphy, "%s: Error setting power_level\n",
|
||||
brcms_err(core, "%s: Error setting power_level\n",
|
||||
__func__);
|
||||
goto config_out;
|
||||
}
|
||||
new_int = brcms_c_get_tx_power(wl->wlc);
|
||||
if (new_int != conf->power_level)
|
||||
wiphy_err(wiphy, "%s: Power level req != actual, %d %d"
|
||||
"\n", __func__, conf->power_level,
|
||||
brcms_err(core,
|
||||
"%s: Power level req != actual, %d %d\n",
|
||||
__func__, conf->power_level,
|
||||
new_int);
|
||||
}
|
||||
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
|
||||
|
@ -425,13 +432,13 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
|
|||
struct ieee80211_bss_conf *info, u32 changed)
|
||||
{
|
||||
struct brcms_info *wl = hw->priv;
|
||||
struct wiphy *wiphy = hw->wiphy;
|
||||
struct bcma_device *core = wl->wlc->hw->d11core;
|
||||
|
||||
if (changed & BSS_CHANGED_ASSOC) {
|
||||
/* association status changed (associated/disassociated)
|
||||
* also implies a change in the AID.
|
||||
*/
|
||||
wiphy_err(wiphy, "%s: %s: %sassociated\n", KBUILD_MODNAME,
|
||||
brcms_err(core, "%s: %s: %sassociated\n", KBUILD_MODNAME,
|
||||
__func__, info->assoc ? "" : "dis");
|
||||
spin_lock_bh(&wl->lock);
|
||||
brcms_c_associate_upd(wl->wlc, info->assoc);
|
||||
|
@ -491,7 +498,7 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
|
|||
error = brcms_c_set_rateset(wl->wlc, &rs);
|
||||
spin_unlock_bh(&wl->lock);
|
||||
if (error)
|
||||
wiphy_err(wiphy, "changing basic rates failed: %d\n",
|
||||
brcms_err(core, "changing basic rates failed: %d\n",
|
||||
error);
|
||||
}
|
||||
if (changed & BSS_CHANGED_BEACON_INT) {
|
||||
|
@ -508,30 +515,30 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
|
|||
}
|
||||
if (changed & BSS_CHANGED_BEACON)
|
||||
/* Beacon data changed, retrieve new beacon (beaconing modes) */
|
||||
wiphy_err(wiphy, "%s: beacon changed\n", __func__);
|
||||
brcms_err(core, "%s: beacon changed\n", __func__);
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED) {
|
||||
/* Beaconing should be enabled/disabled (beaconing modes) */
|
||||
wiphy_err(wiphy, "%s: Beacon enabled: %s\n", __func__,
|
||||
brcms_err(core, "%s: Beacon enabled: %s\n", __func__,
|
||||
info->enable_beacon ? "true" : "false");
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_CQM) {
|
||||
/* Connection quality monitor config changed */
|
||||
wiphy_err(wiphy, "%s: cqm change: threshold %d, hys %d "
|
||||
brcms_err(core, "%s: cqm change: threshold %d, hys %d "
|
||||
" (implement)\n", __func__, info->cqm_rssi_thold,
|
||||
info->cqm_rssi_hyst);
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_IBSS) {
|
||||
/* IBSS join status changed */
|
||||
wiphy_err(wiphy, "%s: IBSS joined: %s (implement)\n", __func__,
|
||||
info->ibss_joined ? "true" : "false");
|
||||
brcms_err(core, "%s: IBSS joined: %s (implement)\n",
|
||||
__func__, info->ibss_joined ? "true" : "false");
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_ARP_FILTER) {
|
||||
/* Hardware ARP filter address list or state changed */
|
||||
wiphy_err(wiphy, "%s: arp filtering: enabled %s, count %d"
|
||||
brcms_err(core, "%s: arp filtering: enabled %s, count %d"
|
||||
" (implement)\n", __func__, info->arp_filter_enabled ?
|
||||
"true" : "false", info->arp_addr_cnt);
|
||||
}
|
||||
|
@ -541,8 +548,8 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
|
|||
* QoS for this association was enabled/disabled.
|
||||
* Note that it is only ever disabled for station mode.
|
||||
*/
|
||||
wiphy_err(wiphy, "%s: qos enabled: %s (implement)\n", __func__,
|
||||
info->qos ? "true" : "false");
|
||||
brcms_err(core, "%s: qos enabled: %s (implement)\n",
|
||||
__func__, info->qos ? "true" : "false");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -553,25 +560,25 @@ brcms_ops_configure_filter(struct ieee80211_hw *hw,
|
|||
unsigned int *total_flags, u64 multicast)
|
||||
{
|
||||
struct brcms_info *wl = hw->priv;
|
||||
struct wiphy *wiphy = hw->wiphy;
|
||||
struct bcma_device *core = wl->wlc->hw->d11core;
|
||||
|
||||
changed_flags &= MAC_FILTERS;
|
||||
*total_flags &= MAC_FILTERS;
|
||||
|
||||
if (changed_flags & FIF_PROMISC_IN_BSS)
|
||||
wiphy_dbg(wiphy, "FIF_PROMISC_IN_BSS\n");
|
||||
brcms_dbg_info(core, "FIF_PROMISC_IN_BSS\n");
|
||||
if (changed_flags & FIF_ALLMULTI)
|
||||
wiphy_dbg(wiphy, "FIF_ALLMULTI\n");
|
||||
brcms_dbg_info(core, "FIF_ALLMULTI\n");
|
||||
if (changed_flags & FIF_FCSFAIL)
|
||||
wiphy_dbg(wiphy, "FIF_FCSFAIL\n");
|
||||
brcms_dbg_info(core, "FIF_FCSFAIL\n");
|
||||
if (changed_flags & FIF_CONTROL)
|
||||
wiphy_dbg(wiphy, "FIF_CONTROL\n");
|
||||
brcms_dbg_info(core, "FIF_CONTROL\n");
|
||||
if (changed_flags & FIF_OTHER_BSS)
|
||||
wiphy_dbg(wiphy, "FIF_OTHER_BSS\n");
|
||||
brcms_dbg_info(core, "FIF_OTHER_BSS\n");
|
||||
if (changed_flags & FIF_PSPOLL)
|
||||
wiphy_dbg(wiphy, "FIF_PSPOLL\n");
|
||||
brcms_dbg_info(core, "FIF_PSPOLL\n");
|
||||
if (changed_flags & FIF_BCN_PRBRESP_PROMISC)
|
||||
wiphy_dbg(wiphy, "FIF_BCN_PRBRESP_PROMISC\n");
|
||||
brcms_dbg_info(core, "FIF_BCN_PRBRESP_PROMISC\n");
|
||||
|
||||
spin_lock_bh(&wl->lock);
|
||||
brcms_c_mac_promisc(wl->wlc, *total_flags);
|
||||
|
@ -653,8 +660,8 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw,
|
|||
status = brcms_c_aggregatable(wl->wlc, tid);
|
||||
spin_unlock_bh(&wl->lock);
|
||||
if (!status) {
|
||||
wiphy_err(wl->wiphy, "START: tid %d is not agg\'able\n",
|
||||
tid);
|
||||
brcms_err(wl->wlc->hw->d11core,
|
||||
"START: tid %d is not agg\'able\n", tid);
|
||||
return -EINVAL;
|
||||
}
|
||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
|
@ -681,8 +688,8 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw,
|
|||
/* Power save wakeup */
|
||||
break;
|
||||
default:
|
||||
wiphy_err(wl->wiphy, "%s: Invalid command, ignoring\n",
|
||||
__func__);
|
||||
brcms_err(wl->wlc->hw->d11core,
|
||||
"%s: Invalid command, ignoring\n", __func__);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1144,14 +1151,13 @@ static int brcms_suspend(struct bcma_device *pdev)
|
|||
wl->pub->hw_up = false;
|
||||
spin_unlock_bh(&wl->lock);
|
||||
|
||||
pr_debug("brcms_suspend ok\n");
|
||||
brcms_dbg_info(wl->wlc->hw->d11core, "brcms_suspend ok\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int brcms_resume(struct bcma_device *pdev)
|
||||
{
|
||||
pr_debug("brcms_resume ok\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1184,10 +1190,6 @@ static DECLARE_WORK(brcms_driver_work, brcms_driver_init);
|
|||
|
||||
static int __init brcms_module_init(void)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (msglevel != 0xdeadbeef)
|
||||
brcm_msg_level = msglevel;
|
||||
#endif
|
||||
if (!schedule_work(&brcms_driver_work))
|
||||
return -EBUSY;
|
||||
|
||||
|
@ -1216,7 +1218,7 @@ module_exit(brcms_module_exit);
|
|||
void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif,
|
||||
bool state, int prio)
|
||||
{
|
||||
wiphy_err(wl->wiphy, "Shouldn't be here %s\n", __func__);
|
||||
brcms_err(wl->wlc->hw->d11core, "Shouldn't be here %s\n", __func__);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1224,7 +1226,8 @@ void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif,
|
|||
*/
|
||||
void brcms_init(struct brcms_info *wl)
|
||||
{
|
||||
BCMMSG(wl->pub->ieee_hw->wiphy, "wl%d\n", wl->pub->unit);
|
||||
brcms_dbg_info(wl->wlc->hw->d11core, "Initializing wl%d\n",
|
||||
wl->pub->unit);
|
||||
brcms_reset(wl);
|
||||
brcms_c_init(wl->wlc, wl->mute_tx);
|
||||
}
|
||||
|
@ -1234,7 +1237,7 @@ void brcms_init(struct brcms_info *wl)
|
|||
*/
|
||||
uint brcms_reset(struct brcms_info *wl)
|
||||
{
|
||||
BCMMSG(wl->pub->ieee_hw->wiphy, "wl%d\n", wl->pub->unit);
|
||||
brcms_dbg_info(wl->wlc->hw->d11core, "Resetting wl%d\n", wl->pub->unit);
|
||||
brcms_c_reset(wl->wlc);
|
||||
|
||||
/* dpc will not be rescheduled */
|
||||
|
@ -1248,7 +1251,7 @@ uint brcms_reset(struct brcms_info *wl)
|
|||
|
||||
void brcms_fatal_error(struct brcms_info *wl)
|
||||
{
|
||||
wiphy_err(wl->wlc->wiphy, "wl%d: fatal error, reinitializing\n",
|
||||
brcms_err(wl->wlc->hw->d11core, "wl%d: fatal error, reinitializing\n",
|
||||
wl->wlc->pub->unit);
|
||||
brcms_reset(wl);
|
||||
ieee80211_restart_hw(wl->pub->ieee_hw);
|
||||
|
@ -1396,8 +1399,9 @@ void brcms_add_timer(struct brcms_timer *t, uint ms, int periodic)
|
|||
|
||||
#ifdef DEBUG
|
||||
if (t->set)
|
||||
wiphy_err(hw->wiphy, "%s: Already set. Name: %s, per %d\n",
|
||||
__func__, t->name, periodic);
|
||||
brcms_dbg_info(t->wl->wlc->hw->d11core,
|
||||
"%s: Already set. Name: %s, per %d\n",
|
||||
__func__, t->name, periodic);
|
||||
#endif
|
||||
t->ms = ms;
|
||||
t->periodic = (bool) periodic;
|
||||
|
@ -1486,8 +1490,8 @@ int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, u32 idx)
|
|||
}
|
||||
}
|
||||
}
|
||||
wiphy_err(wl->wiphy, "ERROR: ucode buf tag:%d can not be found!\n",
|
||||
idx);
|
||||
brcms_err(wl->wlc->hw->d11core,
|
||||
"ERROR: ucode buf tag:%d can not be found!\n", idx);
|
||||
*pbuf = NULL;
|
||||
fail:
|
||||
return -ENODATA;
|
||||
|
@ -1510,7 +1514,7 @@ int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes, u32 idx)
|
|||
pdata = wl->fw.fw_bin[i]->data +
|
||||
le32_to_cpu(hdr->offset);
|
||||
if (le32_to_cpu(hdr->len) != 4) {
|
||||
wiphy_err(wl->wiphy,
|
||||
brcms_err(wl->wlc->hw->d11core,
|
||||
"ERROR: fw hdr len\n");
|
||||
return -ENOMSG;
|
||||
}
|
||||
|
@ -1519,7 +1523,8 @@ int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes, u32 idx)
|
|||
}
|
||||
}
|
||||
}
|
||||
wiphy_err(wl->wiphy, "ERROR: ucode tag:%d can not be found!\n", idx);
|
||||
brcms_err(wl->wlc->hw->d11core,
|
||||
"ERROR: ucode tag:%d can not be found!\n", idx);
|
||||
return -ENOMSG;
|
||||
}
|
||||
|
||||
|
@ -1560,8 +1565,8 @@ int brcms_check_firmwares(struct brcms_info *wl)
|
|||
sizeof(struct firmware_hdr));
|
||||
rc = -EBADF;
|
||||
} else if (fw->size < MIN_FW_SIZE || fw->size > MAX_FW_SIZE) {
|
||||
wiphy_err(wl->wiphy, "%s: out of bounds fw file size "
|
||||
"%zu\n", __func__, fw->size);
|
||||
wiphy_err(wl->wiphy, "%s: out of bounds fw file size %zu\n",
|
||||
__func__, fw->size);
|
||||
rc = -EBADF;
|
||||
} else {
|
||||
/* check if ucode section overruns firmware image */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -101,9 +101,6 @@
|
|||
|
||||
#define DATA_BLOCK_TX_SUPR (1 << 4)
|
||||
|
||||
/* 802.1D Priority to TX FIFO number for wme */
|
||||
extern const u8 prio2fifo[];
|
||||
|
||||
/* Ucode MCTL_WAKE override bits */
|
||||
#define BRCMS_WAKE_OVERRIDE_CLKCTL 0x01
|
||||
#define BRCMS_WAKE_OVERRIDE_PHYREG 0x02
|
||||
|
@ -242,7 +239,6 @@ struct brcms_core {
|
|||
|
||||
/* fifo */
|
||||
uint *txavail[NFIFO]; /* # tx descriptors available */
|
||||
s16 txpktpend[NFIFO]; /* tx admission control */
|
||||
|
||||
struct macstat *macstat_snapshot; /* mac hw prev read values */
|
||||
};
|
||||
|
@ -382,19 +378,6 @@ struct brcms_hardware {
|
|||
*/
|
||||
};
|
||||
|
||||
/* TX Queue information
|
||||
*
|
||||
* Each flow of traffic out of the device has a TX Queue with independent
|
||||
* flow control. Several interfaces may be associated with a single TX Queue
|
||||
* if they belong to the same flow of traffic from the device. For multi-channel
|
||||
* operation there are independent TX Queues for each channel.
|
||||
*/
|
||||
struct brcms_txq_info {
|
||||
struct brcms_txq_info *next;
|
||||
struct pktq q;
|
||||
uint stopped; /* tx flow control bits */
|
||||
};
|
||||
|
||||
/*
|
||||
* Principal common driver data structure.
|
||||
*
|
||||
|
@ -435,11 +418,8 @@ struct brcms_txq_info {
|
|||
* WDlast: last time wlc_watchdog() was called.
|
||||
* edcf_txop[IEEE80211_NUM_ACS]: current txop for each ac.
|
||||
* wme_retries: per-AC retry limits.
|
||||
* tx_prec_map: Precedence map based on HW FIFO space.
|
||||
* fifo2prec_map[NFIFO]: pointer to fifo2_prec map based on WME.
|
||||
* bsscfg: set of BSS configurations, idx 0 is default and always valid.
|
||||
* cfg: the primary bsscfg (can be AP or STA).
|
||||
* tx_queues: common TX Queue list.
|
||||
* modulecb:
|
||||
* mimoft: SIGN or 11N.
|
||||
* cck_40txbw: 11N, cck tx b/w override when in 40MHZ mode.
|
||||
|
@ -469,7 +449,6 @@ struct brcms_txq_info {
|
|||
* tempsense_lasttime;
|
||||
* tx_duty_cycle_ofdm: maximum allowed duty cycle for OFDM.
|
||||
* tx_duty_cycle_cck: maximum allowed duty cycle for CCK.
|
||||
* pkt_queue: txq for transmit packets.
|
||||
* wiphy:
|
||||
* pri_scb: primary Station Control Block
|
||||
*/
|
||||
|
@ -533,14 +512,9 @@ struct brcms_c_info {
|
|||
u16 edcf_txop[IEEE80211_NUM_ACS];
|
||||
|
||||
u16 wme_retries[IEEE80211_NUM_ACS];
|
||||
u16 tx_prec_map;
|
||||
u16 fifo2prec_map[NFIFO];
|
||||
|
||||
struct brcms_bss_cfg *bsscfg;
|
||||
|
||||
/* tx queue */
|
||||
struct brcms_txq_info *tx_queues;
|
||||
|
||||
struct modulecb *modulecb;
|
||||
|
||||
u8 mimoft;
|
||||
|
@ -585,7 +559,6 @@ struct brcms_c_info {
|
|||
u16 tx_duty_cycle_ofdm;
|
||||
u16 tx_duty_cycle_cck;
|
||||
|
||||
struct brcms_txq_info *pkt_queue;
|
||||
struct wiphy *wiphy;
|
||||
struct scb pri_scb;
|
||||
};
|
||||
|
@ -637,30 +610,13 @@ struct brcms_bss_cfg {
|
|||
struct brcms_bss_info *current_bss;
|
||||
};
|
||||
|
||||
extern void brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo,
|
||||
struct sk_buff *p,
|
||||
bool commit, s8 txpktpend);
|
||||
extern void brcms_c_txfifo_complete(struct brcms_c_info *wlc, uint fifo,
|
||||
s8 txpktpend);
|
||||
extern void brcms_c_txq_enq(struct brcms_c_info *wlc, struct scb *scb,
|
||||
struct sk_buff *sdu, uint prec);
|
||||
extern void brcms_c_print_txstatus(struct tx_status *txs);
|
||||
extern int brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo,
|
||||
struct sk_buff *p);
|
||||
extern int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
|
||||
uint *blocks);
|
||||
|
||||
#if defined(DEBUG)
|
||||
extern void brcms_c_print_txdesc(struct d11txh *txh);
|
||||
#else
|
||||
static inline void brcms_c_print_txdesc(struct d11txh *txh)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
extern int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config);
|
||||
extern void brcms_c_mac_promisc(struct brcms_c_info *wlc, uint filter_flags);
|
||||
extern void brcms_c_send_q(struct brcms_c_info *wlc);
|
||||
extern int brcms_c_prep_pdu(struct brcms_c_info *wlc, struct sk_buff *pdu,
|
||||
uint *fifo);
|
||||
extern u16 brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec,
|
||||
uint mac_len);
|
||||
extern u32 brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc,
|
||||
|
|
|
@ -200,43 +200,6 @@ enum wlc_par_id {
|
|||
/* WL11N Support */
|
||||
#define AMPDU_AGG_HOST 1
|
||||
|
||||
/* pri is priority encoded in the packet. This maps the Packet priority to
|
||||
* enqueue precedence as defined in wlc_prec_map
|
||||
*/
|
||||
extern const u8 wlc_prio2prec_map[];
|
||||
#define BRCMS_PRIO_TO_PREC(pri) wlc_prio2prec_map[(pri) & 7]
|
||||
|
||||
#define BRCMS_PREC_COUNT 16 /* Max precedence level implemented */
|
||||
|
||||
/* Mask to describe all precedence levels */
|
||||
#define BRCMS_PREC_BMP_ALL MAXBITVAL(BRCMS_PREC_COUNT)
|
||||
|
||||
/*
|
||||
* This maps priority to one precedence higher - Used by PS-Poll response
|
||||
* packets to simulate enqueue-at-head operation, but still maintain the
|
||||
* order on the queue
|
||||
*/
|
||||
#define BRCMS_PRIO_TO_HI_PREC(pri) min(BRCMS_PRIO_TO_PREC(pri) + 1,\
|
||||
BRCMS_PREC_COUNT - 1)
|
||||
|
||||
/* Define a bitmap of precedences comprised by each AC */
|
||||
#define BRCMS_PREC_BMP_AC_BE (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_BE)) | \
|
||||
NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_BE)) | \
|
||||
NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_EE)) | \
|
||||
NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_EE)))
|
||||
#define BRCMS_PREC_BMP_AC_BK (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_BK)) | \
|
||||
NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_BK)) | \
|
||||
NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_NONE)) | \
|
||||
NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_NONE)))
|
||||
#define BRCMS_PREC_BMP_AC_VI (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_CL)) | \
|
||||
NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_CL)) | \
|
||||
NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_VI)) | \
|
||||
NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_VI)))
|
||||
#define BRCMS_PREC_BMP_AC_VO (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_VO)) | \
|
||||
NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_VO)) | \
|
||||
NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_NC)) | \
|
||||
NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_NC)))
|
||||
|
||||
/* network protection config */
|
||||
#define BRCMS_PROT_G_SPEC 1 /* SPEC g protection */
|
||||
#define BRCMS_PROT_G_OVR 2 /* SPEC g prot override */
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "channel.h"
|
||||
#include "main.h"
|
||||
#include "stf.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define MIN_SPATIAL_EXPANSION 0
|
||||
#define MAX_SPATIAL_EXPANSION 1
|
||||
|
@ -160,8 +161,8 @@ bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val)
|
|||
static int brcms_c_stf_txcore_set(struct brcms_c_info *wlc, u8 Nsts,
|
||||
u8 core_mask)
|
||||
{
|
||||
BCMMSG(wlc->wiphy, "wl%d: Nsts %d core_mask %x\n",
|
||||
wlc->pub->unit, Nsts, core_mask);
|
||||
brcms_dbg_ht(wlc->hw->d11core, "wl%d: Nsts %d core_mask %x\n",
|
||||
wlc->pub->unit, Nsts, core_mask);
|
||||
|
||||
if (hweight8(core_mask) > wlc->stf->txstreams)
|
||||
core_mask = 0;
|
||||
|
@ -194,7 +195,8 @@ static int brcms_c_stf_spatial_policy_set(struct brcms_c_info *wlc, int val)
|
|||
int i;
|
||||
u8 core_mask = 0;
|
||||
|
||||
BCMMSG(wlc->wiphy, "wl%d: val %x\n", wlc->pub->unit, val);
|
||||
brcms_dbg_ht(wlc->hw->d11core, "wl%d: val %x\n", wlc->pub->unit,
|
||||
val);
|
||||
|
||||
wlc->stf->spatial_policy = (s8) val;
|
||||
for (i = 1; i <= MAX_STREAMS_SUPPORTED; i++) {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue