Skip to content

Commit

Permalink
brcmfmac: use brcmf_if::bssidx as index in interface list
Browse files Browse the repository at this point in the history
Upon receiving an IF event from the firmware the interface
was created and stored on a list using the interface index.
With upcoming P2P feature the firmware will send a IF event
in which two interfaces have the same interface index. To
uniquely locate them on the list the bss index is now used.

Reviewed-by: Arend Van Spriel <arend@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Hante Meuleman authored and John W. Linville committed Feb 8, 2013
1 parent 4fe238b commit 2880b86
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 49 deletions.
10 changes: 5 additions & 5 deletions drivers/net/wireless/brcm80211/brcmfmac/dhd.h
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ struct brcmf_cfg80211_vif;
* @vif: points to cfg80211 specific interface information.
* @ndev: associated network device.
* @stats: interface specific network statistics.
* @idx: interface index in device firmware.
* @ifidx: interface index in device firmware.
* @bssidx: index of bss associated with this interface.
* @mac_addr: assigned mac address.
* @pend_8021x_cnt: tracks outstanding number of 802.1x frames.
Expand All @@ -525,7 +525,7 @@ struct brcmf_if {
struct net_device_stats stats;
struct work_struct setmacaddr_work;
struct work_struct multicast_work;
int idx;
int ifidx;
s32 bssidx;
u8 mac_addr[ETH_ALEN];
atomic_t pend_8021x_cnt;
Expand All @@ -549,9 +549,9 @@ extern int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx,
struct sk_buff *rxp);

extern int brcmf_net_attach(struct brcmf_if *ifp);
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);
extern struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx,
s32 ifidx, char *name, u8 *mac_addr);
extern void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx);
extern u32 brcmf_get_chip_info(struct brcmf_if *ifp);

#endif /* _BRCMF_H_ */
8 changes: 8 additions & 0 deletions drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,14 @@ int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx,
brcmf_err("rx data ifnum out of range (%d)\n", *ifidx);
return -EBADE;
}
/* The ifidx is the idx to map to matching netdev/ifp. When receiving
* events this is easy because it contains the bssidx which maps
* 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd.
* bssidx 1 is used for p2p0 and no data can be received or
* transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0
*/
if (*ifidx)
(*ifidx)++;

if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) !=
BDC_PROTO_VER) {
Expand Down
72 changes: 35 additions & 37 deletions drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ static void _brcmf_set_multicast_list(struct work_struct *work)

ifp = container_of(work, struct brcmf_if, multicast_work);

brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->idx);
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);

ndev = ifp->ndev;

Expand Down Expand Up @@ -132,7 +132,7 @@ _brcmf_set_mac_address(struct work_struct *work)

ifp = container_of(work, struct brcmf_if, setmacaddr_work);

brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->idx);
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);

err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", ifp->mac_addr,
ETH_ALEN);
Expand Down Expand Up @@ -170,7 +170,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
struct brcmf_pub *drvr = ifp->drvr;
struct ethhdr *eh;

brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->idx);
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);

/* Can the device send data? */
if (drvr->bus_if->state != BRCMF_BUS_DATA) {
Expand All @@ -181,8 +181,8 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
goto done;
}

if (!drvr->iflist[ifp->idx]) {
brcmf_err("bad ifidx %d\n", ifp->idx);
if (!drvr->iflist[ifp->bssidx]) {
brcmf_err("bad ifidx %d\n", ifp->bssidx);
netif_stop_queue(ndev);
dev_kfree_skb(skb);
ret = -ENODEV;
Expand All @@ -194,14 +194,14 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
struct sk_buff *skb2;

brcmf_dbg(INFO, "%s: insufficient headroom\n",
brcmf_ifname(drvr, ifp->idx));
brcmf_ifname(drvr, ifp->bssidx));
drvr->bus_if->tx_realloc++;
skb2 = skb_realloc_headroom(skb, drvr->hdrlen);
dev_kfree_skb(skb);
skb = skb2;
if (skb == NULL) {
brcmf_err("%s: skb_realloc_headroom failed\n",
brcmf_ifname(drvr, ifp->idx));
brcmf_ifname(drvr, ifp->bssidx));
ret = -ENOMEM;
goto done;
}
Expand All @@ -222,7 +222,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
atomic_inc(&ifp->pend_8021x_cnt);

/* If the protocol uses a data header, apply it */
brcmf_proto_hdrpush(drvr, ifp->idx, skb);
brcmf_proto_hdrpush(drvr, ifp->ifidx, skb);

/* Use bus module to send data frame */
ret = brcmf_bus_txdata(drvr->bus_if, skb);
Expand Down Expand Up @@ -372,7 +372,7 @@ static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
{
struct brcmf_if *ifp = netdev_priv(ndev);

brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->idx);
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);

return &ifp->stats;
}
Expand Down Expand Up @@ -424,7 +424,7 @@ static int brcmf_ethtool(struct brcmf_if *ifp, void __user *uaddr)
u32 toe_cmpnt, csum_dir;
int ret;

brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->idx);
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);

/* all ethtool calls start with a cmd word */
if (copy_from_user(&cmd, uaddr, sizeof(u32)))
Expand Down Expand Up @@ -521,9 +521,9 @@ static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_pub *drvr = ifp->drvr;

brcmf_dbg(TRACE, "Enter, bssidx=%d, cmd=0x%04x\n", ifp->idx, cmd);
brcmf_dbg(TRACE, "Enter, idx=%d, cmd=0x%04x\n", ifp->bssidx, cmd);

if (!drvr->iflist[ifp->idx])
if (!drvr->iflist[ifp->bssidx])
return -1;

if (cmd == SIOCETHTOOL)
Expand All @@ -536,7 +536,7 @@ static int brcmf_netdev_stop(struct net_device *ndev)
{
struct brcmf_if *ifp = netdev_priv(ndev);

brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->idx);
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);

brcmf_cfg80211_down(ndev);

Expand All @@ -554,7 +554,7 @@ static int brcmf_netdev_open(struct net_device *ndev)
u32 toe_ol;
s32 ret = 0;

brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->idx);
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);

/* If bus is not ready, can't continue */
if (bus_if->state != BRCMF_BUS_DATA) {
Expand Down Expand Up @@ -606,12 +606,12 @@ int brcmf_net_attach(struct brcmf_if *ifp)
struct brcmf_pub *drvr = ifp->drvr;
struct net_device *ndev;

brcmf_dbg(TRACE, "Enter, idx=%d mac=%pM\n", ifp->idx,
brcmf_dbg(TRACE, "Enter, idx=%d mac=%pM\n", ifp->bssidx,
ifp->mac_addr);
ndev = ifp->ndev;

/* set appropriate operations */
if (!ifp->idx)
if (!ifp->bssidx)
ndev->netdev_ops = &brcmf_netdev_ops_pri;
else
ndev->netdev_ops = &brcmf_netdev_ops_virt;
Expand Down Expand Up @@ -639,28 +639,27 @@ int brcmf_net_attach(struct brcmf_if *ifp)
return -EBADE;
}

struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx, s32 bssidx,
char *name, u8 *addr_mask)
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
char *name, u8 *mac_addr)
{
struct brcmf_if *ifp;
struct net_device *ndev;
int i;

brcmf_dbg(TRACE, "Enter, bssidx=%d, ifidx=%d\n", bssidx, ifidx);
brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifidx);

ifp = drvr->iflist[ifidx];
ifp = drvr->iflist[bssidx];
/*
* Delete the existing interface before overwriting it
* in case we missed the BRCMF_E_IF_DEL event.
*/
if (ifp) {
brcmf_err("ERROR: netdev:%s already exists\n",
ifp->ndev->name);
if (ifidx) {
if (bssidx) {
netif_stop_queue(ifp->ndev);
unregister_netdev(ifp->ndev);
free_netdev(ifp->ndev);
drvr->iflist[ifidx] = NULL;
drvr->iflist[bssidx] = NULL;
} else {
brcmf_err("ignore IF event\n");
return ERR_PTR(-EINVAL);
Expand All @@ -677,37 +676,36 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx, s32 bssidx,
ifp = netdev_priv(ndev);
ifp->ndev = ndev;
ifp->drvr = drvr;
drvr->iflist[ifidx] = ifp;
ifp->idx = ifidx;
drvr->iflist[bssidx] = ifp;
ifp->ifidx = ifidx;
ifp->bssidx = bssidx;

INIT_WORK(&ifp->setmacaddr_work, _brcmf_set_mac_address);
INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list);

init_waitqueue_head(&ifp->pend_8021x_wait);

if (addr_mask != NULL)
for (i = 0; i < ETH_ALEN; i++)
ifp->mac_addr[i] = drvr->mac[i] ^ addr_mask[i];
if (mac_addr != NULL)
memcpy(ifp->mac_addr, mac_addr, ETH_ALEN);

brcmf_dbg(TRACE, " ==== pid:%x, if:%s (%pM) created ===\n",
current->pid, ifp->ndev->name, ifp->mac_addr);

return ifp;
}

void brcmf_del_if(struct brcmf_pub *drvr, int ifidx)
void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
{
struct brcmf_if *ifp;

ifp = drvr->iflist[ifidx];
ifp = drvr->iflist[bssidx];
if (!ifp) {
brcmf_err("Null interface, idx=%d\n", ifidx);
brcmf_err("Null interface, idx=%d\n", bssidx);
return;
}
brcmf_dbg(TRACE, "Enter, idx=%d, bssidx=%d\n", ifidx, ifp->bssidx);
brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifp->ifidx);
if (ifp->ndev) {
if (ifidx == 0) {
if (bssidx == 0) {
if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
rtnl_lock();
brcmf_netdev_stop(ifp->ndev);
Expand All @@ -721,8 +719,8 @@ void brcmf_del_if(struct brcmf_pub *drvr, int ifidx)
cancel_work_sync(&ifp->multicast_work);

unregister_netdev(ifp->ndev);
drvr->iflist[ifidx] = NULL;
if (ifidx == 0)
drvr->iflist[bssidx] = NULL;
if (bssidx == 0)
brcmf_cfg80211_detach(drvr->config);
free_netdev(ifp->ndev);
}
Expand Down Expand Up @@ -815,7 +813,7 @@ int brcmf_bus_start(struct device *dev)
brcmf_err("failed: %d\n", ret);
if (drvr->config)
brcmf_cfg80211_detach(drvr->config);
free_netdev(drvr->iflist[0]->ndev);
free_netdev(ifp->ndev);
drvr->iflist[0] = NULL;
return ret;
}
Expand Down Expand Up @@ -849,7 +847,7 @@ void brcmf_dev_reset(struct device *dev)

void brcmf_detach(struct device *dev)
{
int i;
s32 i;
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_pub *drvr = bus_if->drvr;

Expand Down
9 changes: 4 additions & 5 deletions drivers/net/wireless/brcm80211/brcmfmac/fweh.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,12 +189,12 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
return;
}

ifp = drvr->iflist[ifevent->ifidx];
ifp = drvr->iflist[ifevent->bssidx];

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,
ifp = brcmf_add_if(drvr, ifevent->bssidx, ifevent->ifidx,
emsg->ifname, emsg->addr);
if (IS_ERR(ifp))
return;
Expand All @@ -206,7 +206,7 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
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_del_if(drvr, ifevent->bssidx);
}

/**
Expand Down Expand Up @@ -250,8 +250,6 @@ static void brcmf_fweh_event_worker(struct work_struct *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,
Expand Down Expand Up @@ -283,6 +281,7 @@ static void brcmf_fweh_event_worker(struct work_struct *work)
goto event_free;
}

ifp = drvr->iflist[emsg.bsscfgidx];
err = brcmf_fweh_call_event_handler(ifp, event->code, &emsg,
event->data);
if (err) {
Expand Down
5 changes: 3 additions & 2 deletions drivers/net/wireless/brcm80211/brcmfmac/fwil.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,10 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
if (data != NULL)
len = min_t(uint, len, BRCMF_DCMD_MAXLEN);
if (set)
err = brcmf_proto_cdc_set_dcmd(drvr, ifp->idx, cmd, data, len);
err = brcmf_proto_cdc_set_dcmd(drvr, ifp->ifidx, cmd, data,
len);
else
err = brcmf_proto_cdc_query_dcmd(drvr, ifp->idx, cmd, data,
err = brcmf_proto_cdc_query_dcmd(drvr, ifp->ifidx, cmd, data,
len);

if (err >= 0)
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -3546,6 +3546,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
if (err < 0) {
brcmf_err("BRCMF_C_UP error (%d)\n", err);
goto exit;
brcmf_fil_iovar_int_set(ifp, "apsta", 0);
}

memset(&join_params, 0, sizeof(join_params));
Expand Down Expand Up @@ -4242,6 +4243,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,

cfg80211_attach_out:
brcmf_free_vif(vif);
wiphy_free(wiphy);
return NULL;
}

Expand Down

0 comments on commit 2880b86

Please sign in to comment.