wireless/bcm43xxx: add Packet Traffic Arbitration Priority support

For Bluetooth wifi co-existence

Signed-off-by: chao.an <anchao@xiaomi.com>
This commit is contained in:
chao.an 2022-06-21 22:26:59 +08:00 committed by Xiang Xiao
parent 8f5a6930e8
commit ff2b87c298
5 changed files with 184 additions and 20 deletions

View File

@ -156,6 +156,12 @@ config IEEE80211_BROADCOM_SCAN_RESULT_ENTRIES
---help--- ---help---
This parameter should be set the bcmf escan result buffer entries This parameter should be set the bcmf escan result buffer entries
config IEEE80211_BROADCOM_PTA_PRIORITY
bool "Broadcom BCMF Packet Traffic Arbitration priority"
default n
---help---
This parameter should be enable the bcmf PTA priority feature
config IEEE80211_BROADCOM_LOWPOWER config IEEE80211_BROADCOM_LOWPOWER
bool "Broadcom BCMF lower power" bool "Broadcom BCMF lower power"
depends on IEEE80211_BROADCOM_FULLMAC depends on IEEE80211_BROADCOM_FULLMAC

View File

@ -419,6 +419,34 @@ int bcmf_driver_download_clm(FAR struct bcmf_dev_s *priv)
#endif #endif
#endif /* CONFIG_IEEE80211_BROADCOM_HAVE_CLM */ #endif /* CONFIG_IEEE80211_BROADCOM_HAVE_CLM */
int bcmf_wl_set_pm(FAR struct bcmf_dev_s *priv, int mode)
{
int interface = CHIP_STA_INTERFACE;
uint32_t out_len;
uint32_t value;
int ret = OK;
/* Set default power save mode */
#ifdef CONFIG_IEEE80211_BROADCOM_LOWPOWER
if (priv->lp_mode != mode)
#endif
{
out_len = 4;
value = mode;
ret = bcmf_cdc_ioctl(priv, interface, true, WLC_SET_PM,
(uint8_t *)&value, &out_len);
#ifdef CONFIG_IEEE80211_BROADCOM_LOWPOWER
if (ret == OK)
{
priv->lp_mode = mode;
}
#endif
}
return ret;
}
/**************************************************************************** /****************************************************************************
* Name: bcmf_wl_active * Name: bcmf_wl_active
****************************************************************************/ ****************************************************************************/
@ -1714,13 +1742,23 @@ int bcmf_wl_get_bssid(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
* Get the channel for the device * Get the channel for the device
****************************************************************************/ ****************************************************************************/
int bcmf_wl_get_channel(FAR struct bcmf_dev_s *priv, struct iwreq *iwr) int bcmf_wl_get_channel(FAR struct bcmf_dev_s *priv, int interface)
{ {
channel_info_t ci; channel_info_t ci;
uint32_t out_len; uint32_t out_len;
int interface;
int ret; int ret;
out_len = sizeof(ci);
ret = bcmf_cdc_ioctl(priv, interface, false,
WLC_GET_CHANNEL, (uint8_t *)&ci, &out_len);
return ret == OK ? ci.target_channel : ret;
}
int bcmf_wl_get_frequency(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
{
int interface;
int channel;
interface = bcmf_wl_get_interface(priv, iwr); interface = bcmf_wl_get_interface(priv, iwr);
if (interface < 0) if (interface < 0)
@ -1728,15 +1766,15 @@ int bcmf_wl_get_channel(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
return -EINVAL; return -EINVAL;
} }
out_len = sizeof(ci); channel = bcmf_wl_get_channel(priv, interface);
ret = bcmf_cdc_ioctl(priv, interface, false, if (channel < 0)
WLC_GET_CHANNEL, (FAR uint8_t *)&ci, &out_len);
if (ret == OK)
{ {
iwr->u.freq.m = bcmf_wl_channel_to_frequency(ci.target_channel); return channel;
} }
return ret; iwr->u.freq.m = bcmf_wl_channel_to_frequency(channel);
return OK;
} }
/**************************************************************************** /****************************************************************************
@ -1827,10 +1865,8 @@ int bcmf_wl_get_txpower(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
int bcmf_wl_get_iwrange(FAR struct bcmf_dev_s *priv, struct iwreq *iwr) int bcmf_wl_get_iwrange(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
{ {
struct iw_range *range; struct iw_range *range;
channel_info_t ci;
uint32_t out_len;
int interface; int interface;
int ret; int channel;
interface = bcmf_wl_get_interface(priv, iwr); interface = bcmf_wl_get_interface(priv, iwr);
@ -1848,16 +1884,16 @@ int bcmf_wl_get_iwrange(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
memset(range, 0, sizeof(*range)); memset(range, 0, sizeof(*range));
out_len = sizeof(ci); channel = bcmf_wl_get_channel(priv, interface);
ret = bcmf_cdc_ioctl(priv, interface, false, if (channel < 0)
WLC_GET_CHANNEL, (FAR uint8_t *)&ci, &out_len);
if (ret == OK)
{ {
range->num_frequency = 1; return channel;
range->freq[0].m = bcmf_wl_channel_to_frequency(ci.target_channel);
range->freq[0].i = ci.target_channel;
} }
range->num_frequency = 1;
range->freq[0].m = bcmf_wl_channel_to_frequency(channel);
range->freq[0].i = channel;
return OK; return OK;
} }
@ -2193,3 +2229,61 @@ int bcmf_wl_set_dtim(FAR struct bcmf_dev_s *priv,
} }
#endif #endif
#ifdef CONFIG_IEEE80211_BROADCOM_PTA_PRIORITY
int bcmf_wl_get_pta(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
{
iwr->u.param.value = priv->pta_priority;
return OK;
}
int bcmf_wl_set_pta_priority(FAR struct bcmf_dev_s *priv, uint32_t prio)
{
uint32_t out_len;
int ret;
wl_pta_t pta_prio_map[IW_PTA_PRIORITY_WLAN_MAXIMIZED + 1] =
{
{ 0, 50, },
{ 10, 50, },
{ 25, 50, },
{ 40, 50, },
{ 50, 50, },
};
if (prio > IW_PTA_PRIORITY_WLAN_MAXIMIZED)
{
return -EINVAL;
}
if (priv->pta_priority == prio)
{
return OK;
}
out_len = sizeof(wl_pta_t);
ret = bcmf_cdc_iovar_request(priv, CHIP_STA_INTERFACE, true,
IOVAR_STR_COEX_PARA,
(uint8_t *)&pta_prio_map[prio],
&out_len);
if (ret == OK)
{
priv->pta_priority = prio;
}
return ret;
}
int bcmf_wl_set_pta(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
{
if (bcmf_wl_get_interface(priv, iwr) < 0)
{
return -EINVAL;
}
return bcmf_wl_set_pta_priority(priv, iwr->u.param.value);
}
#endif

View File

@ -103,6 +103,9 @@ struct bcmf_dev_s
int lp_dtim; /* Listen interval Delivery Traffic Indication Message */ int lp_dtim; /* Listen interval Delivery Traffic Indication Message */
sclock_t lp_ticks; /* Ticks of last tx time */ sclock_t lp_ticks; /* Ticks of last tx time */
#endif #endif
#ifdef CONFIG_IEEE80211_BROADCOM_PTA_PRIORITY
int pta_priority; /* Current priority of Packet Traffic Arbitration */
#endif
}; };
/* Default bus interface structure */ /* Default bus interface structure */
@ -187,7 +190,7 @@ int bcmf_wl_get_ssid(FAR struct bcmf_dev_s *priv, FAR struct iwreq *iwr);
int bcmf_wl_set_bssid(FAR struct bcmf_dev_s *priv, FAR struct iwreq *iwr); int bcmf_wl_set_bssid(FAR struct bcmf_dev_s *priv, FAR struct iwreq *iwr);
int bcmf_wl_get_bssid(FAR struct bcmf_dev_s *priv, FAR struct iwreq *iwr); int bcmf_wl_get_bssid(FAR struct bcmf_dev_s *priv, FAR struct iwreq *iwr);
int bcmf_wl_get_channel(FAR struct bcmf_dev_s *priv, FAR struct iwreq *iwr); int bcmf_wl_get_frequency(FAR struct bcmf_dev_s *priv, struct iwreq *iwr);
int bcmf_wl_get_rate(FAR struct bcmf_dev_s *priv, FAR struct iwreq *iwr); int bcmf_wl_get_rate(FAR struct bcmf_dev_s *priv, FAR struct iwreq *iwr);
@ -200,4 +203,17 @@ int bcmf_wl_get_iwrange(FAR struct bcmf_dev_s *priv, FAR struct iwreq *iwr);
int bcmf_wl_set_country(FAR struct bcmf_dev_s *priv, FAR struct iwreq *iwr); int bcmf_wl_set_country(FAR struct bcmf_dev_s *priv, FAR struct iwreq *iwr);
int bcmf_wl_get_country(FAR struct bcmf_dev_s *priv, FAR struct iwreq *iwr); int bcmf_wl_get_country(FAR struct bcmf_dev_s *priv, FAR struct iwreq *iwr);
int bcmf_wl_get_channel(FAR struct bcmf_dev_s *priv, int interface);
#ifdef CONFIG_IEEE80211_BROADCOM_PTA_PRIORITY
int bcmf_wl_get_pta(FAR struct bcmf_dev_s *priv, struct iwreq *iwr);
int bcmf_wl_set_pta(FAR struct bcmf_dev_s *priv, struct iwreq *iwr);
int bcmf_wl_set_pta_priority(FAR struct bcmf_dev_s *priv, uint32_t prio);
#else
# define bcmf_wl_get_pta(...)
# define bcmf_wl_set_pta(...)
# define bcmf_wl_set_pta_priority(...)
#endif
#endif /* __DRIVERS_WIRELESS_IEEE80211_BCM43XXX_BCMF_DRIVER_H */ #endif /* __DRIVERS_WIRELESS_IEEE80211_BCM43XXX_BCMF_DRIVER_H */

View File

@ -873,6 +873,7 @@ end_packed_struct wlc_iov_trx_t;
#define IOVAR_STR_CCGPIOIN "ccgpioin" #define IOVAR_STR_CCGPIOIN "ccgpioin"
#define IOVAR_STR_CCGPIOOUT "ccgpioout" #define IOVAR_STR_CCGPIOOUT "ccgpioout"
#define IOVAR_STR_CCGPIOPUTEN "ccgpioputen" #define IOVAR_STR_CCGPIOPUTEN "ccgpioputen"
#define IOVAR_STR_COEX_PARA "coex_para"
#define WLC_IOCTL_MAGIC ( 0x14e46c77 ) #define WLC_IOCTL_MAGIC ( 0x14e46c77 )
#define WLC_IOCTL_VERSION ( 1 ) #define WLC_IOCTL_VERSION ( 1 )
@ -3025,6 +3026,14 @@ end_packed_struct;
typedef struct edcf_acparam edcf_acparam_t; typedef struct edcf_acparam edcf_acparam_t;
/* Packet Traffic Arbitration */
typedef struct wl_pta
{
uint16_t radio;
uint16_t duration;
} wl_pta_t;
/* Stop packing structures */ /* Stop packing structures */
#pragma pack() #pragma pack()

View File

@ -652,6 +652,8 @@ static int bcmf_ifup(FAR struct net_driver_s *dev)
bcmf_lowpower_poll(priv); bcmf_lowpower_poll(priv);
#endif #endif
bcmf_wl_set_pta_priority(priv, IW_PTA_PRIORITY_COEX_HIGH);
goto errout_in_critical_section; goto errout_in_critical_section;
errout_in_wl_active: errout_in_wl_active:
@ -708,6 +710,8 @@ static int bcmf_ifdown(FAR struct net_driver_s *dev)
} }
#endif #endif
bcmf_wl_set_pta_priority(priv, IW_PTA_PRIORITY_COEX_MAXIMIZED);
bcmf_wl_enable(priv, false); bcmf_wl_enable(priv, false);
bcmf_wl_active(priv, false); bcmf_wl_active(priv, false);
} }
@ -1022,11 +1026,24 @@ static int bcmf_ioctl(FAR struct net_driver_s *dev, int cmd,
switch (cmd) switch (cmd)
{ {
case SIOCSIWSCAN: case SIOCSIWSCAN:
bcmf_wl_set_pta_priority(priv, IW_PTA_PRIORITY_WLAN_MAXIMIZED);
ret = bcmf_wl_start_scan(priv, (struct iwreq *)arg); ret = bcmf_wl_start_scan(priv, (struct iwreq *)arg);
if (ret != OK)
{
bcmf_wl_set_pta_priority(priv, IFF_IS_RUNNING(dev->d_flags) ?
IW_PTA_PRIORITY_BALANCED :
IW_PTA_PRIORITY_COEX_HIGH);
}
break; break;
case SIOCGIWSCAN: case SIOCGIWSCAN:
ret = bcmf_wl_get_scan_results(priv, (struct iwreq *)arg); ret = bcmf_wl_get_scan_results(priv, (struct iwreq *)arg);
if (ret != -EAGAIN)
{
bcmf_wl_set_pta_priority(priv, IFF_IS_RUNNING(dev->d_flags) ?
IW_PTA_PRIORITY_BALANCED :
IW_PTA_PRIORITY_COEX_HIGH);
}
break; break;
case SIOCSIFHWADDR: /* Set device MAC address */ case SIOCSIFHWADDR: /* Set device MAC address */
@ -1047,7 +1064,7 @@ static int bcmf_ioctl(FAR struct net_driver_s *dev, int cmd,
break; break;
case SIOCGIWFREQ: /* Get channel/frequency (Hz) */ case SIOCGIWFREQ: /* Get channel/frequency (Hz) */
ret = bcmf_wl_get_channel(priv, (struct iwreq *)arg); ret = bcmf_wl_get_frequency(priv, (struct iwreq *)arg);
break; break;
case SIOCSIWMODE: /* Set operation mode */ case SIOCSIWMODE: /* Set operation mode */
@ -1067,7 +1084,19 @@ static int bcmf_ioctl(FAR struct net_driver_s *dev, int cmd,
break; break;
case SIOCSIWESSID: /* Set ESSID (network name) */ case SIOCSIWESSID: /* Set ESSID (network name) */
bcmf_wl_set_pta_priority(priv, IW_PTA_PRIORITY_WLAN_MAXIMIZED);
ret = bcmf_wl_set_ssid(priv, (struct iwreq *)arg); ret = bcmf_wl_set_ssid(priv, (struct iwreq *)arg);
if (ret != OK)
{
bcmf_wl_set_pta_priority(priv, IW_PTA_PRIORITY_COEX_HIGH);
}
else
{
bcmf_wl_set_pta_priority(priv, (bcmf_wl_get_channel(priv,
CHIP_STA_INTERFACE) > 14) ?
IW_PTA_PRIORITY_COEX_MAXIMIZED :
IW_PTA_PRIORITY_BALANCED);
}
break; break;
case SIOCGIWESSID: /* Get ESSID */ case SIOCGIWESSID: /* Get ESSID */
@ -1108,6 +1137,16 @@ static int bcmf_ioctl(FAR struct net_driver_s *dev, int cmd,
ret = bcmf_wl_get_country(priv, (struct iwreq *)arg); ret = bcmf_wl_get_country(priv, (struct iwreq *)arg);
break; break;
#ifdef CONFIG_IEEE80211_BROADCOM_PTA_PRIORITY
case SIOCGIWPTAPRIO: /* Get Packet Traffic Arbitration */
ret = bcmf_wl_get_pta(priv, (struct iwreq *)arg);
break;
case SIOCSIWPTAPRIO: /* Set Packet Traffic Arbitration */
ret = bcmf_wl_set_pta(priv, (struct iwreq *)arg);
break;
#endif
default: default:
nerr("ERROR: Unrecognized IOCTL command: %x\n", cmd); nerr("ERROR: Unrecognized IOCTL command: %x\n", cmd);
ret = -ENOTTY; /* Special return value for this case */ ret = -ENOTTY; /* Special return value for this case */