Commit e1b83586 authored by Franky Lin's avatar Franky Lin Committed by John W. Linville

brcm80211: fmac: store brcmf_if in net device private data

Make a proper use of private data area of net device by storing
interface related data structure instead of generic driver data
Reported-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Reviewed-by: default avatarRoland Vossen <rvossen@broadcom.com>
Reviewed-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarFranky (Zhenhui) Lin <frankyl@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 15d45b6f
...@@ -123,7 +123,6 @@ ...@@ -123,7 +123,6 @@
/* For supporting multiple interfaces */ /* For supporting multiple interfaces */
#define BRCMF_MAX_IFS 16 #define BRCMF_MAX_IFS 16
#define BRCMF_DEL_IF -0xe #define BRCMF_DEL_IF -0xe
#define BRCMF_BAD_IF -0xf
#define DOT11_BSSTYPE_ANY 2 #define DOT11_BSSTYPE_ANY 2
#define DOT11_MAX_DEFAULT_KEYS 4 #define DOT11_MAX_DEFAULT_KEYS 4
......
...@@ -80,20 +80,6 @@ struct brcmf_info { ...@@ -80,20 +80,6 @@ struct brcmf_info {
/* Error bits */ /* Error bits */
module_param(brcmf_msg_level, int, 0); module_param(brcmf_msg_level, int, 0);
static int brcmf_net2idx(struct brcmf_info *drvr_priv, struct net_device *ndev)
{
int i = 0;
while (i < BRCMF_MAX_IFS) {
if (drvr_priv->iflist[i] && drvr_priv->iflist[i]->ndev == ndev)
return i;
i++;
}
return BRCMF_BAD_IF;
}
int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name) int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name)
{ {
int i = BRCMF_MAX_IFS; int i = BRCMF_MAX_IFS;
...@@ -285,14 +271,9 @@ _brcmf_set_mac_address(struct work_struct *work) ...@@ -285,14 +271,9 @@ _brcmf_set_mac_address(struct work_struct *work)
static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr) static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr)
{ {
struct brcmf_info *drvr_priv = *(struct brcmf_info **) struct brcmf_if *ifp = netdev_priv(ndev);
netdev_priv(ndev); struct brcmf_info *drvr_priv = ifp->info;
struct sockaddr *sa = (struct sockaddr *)addr; struct sockaddr *sa = (struct sockaddr *)addr;
int ifidx;
ifidx = brcmf_net2idx(drvr_priv, ndev);
if (ifidx == BRCMF_BAD_IF)
return -1;
memcpy(&drvr_priv->macvalue, sa->sa_data, ETH_ALEN); memcpy(&drvr_priv->macvalue, sa->sa_data, ETH_ALEN);
schedule_work(&drvr_priv->setmacaddr_work); schedule_work(&drvr_priv->setmacaddr_work);
...@@ -301,13 +282,8 @@ static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr) ...@@ -301,13 +282,8 @@ static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr)
static void brcmf_netdev_set_multicast_list(struct net_device *ndev) static void brcmf_netdev_set_multicast_list(struct net_device *ndev)
{ {
struct brcmf_info *drvr_priv = *(struct brcmf_info **) struct brcmf_if *ifp = netdev_priv(ndev);
netdev_priv(ndev); struct brcmf_info *drvr_priv = ifp->info;
int ifidx;
ifidx = brcmf_net2idx(drvr_priv, ndev);
if (ifidx == BRCMF_BAD_IF)
return;
schedule_work(&drvr_priv->multicast_work); schedule_work(&drvr_priv->multicast_work);
} }
...@@ -341,9 +317,8 @@ int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx, struct sk_buff *pktbuf) ...@@ -341,9 +317,8 @@ int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx, struct sk_buff *pktbuf)
static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev) static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{ {
int ret; int ret;
struct brcmf_info *drvr_priv = *(struct brcmf_info **) struct brcmf_if *ifp = netdev_priv(ndev);
netdev_priv(ndev); struct brcmf_info *drvr_priv = ifp->info;
int ifidx;
brcmf_dbg(TRACE, "Enter\n"); brcmf_dbg(TRACE, "Enter\n");
...@@ -355,9 +330,8 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -355,9 +330,8 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
return -ENODEV; return -ENODEV;
} }
ifidx = brcmf_net2idx(drvr_priv, ndev); if (!drvr_priv->iflist[ifp->idx]) {
if (ifidx == BRCMF_BAD_IF) { brcmf_dbg(ERROR, "bad ifidx %d\n", ifp->idx);
brcmf_dbg(ERROR, "bad ifidx %d\n", ifidx);
netif_stop_queue(ndev); netif_stop_queue(ndev);
return -ENODEV; return -ENODEV;
} }
...@@ -367,20 +341,20 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -367,20 +341,20 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
struct sk_buff *skb2; struct sk_buff *skb2;
brcmf_dbg(INFO, "%s: insufficient headroom\n", brcmf_dbg(INFO, "%s: insufficient headroom\n",
brcmf_ifname(&drvr_priv->pub, ifidx)); brcmf_ifname(&drvr_priv->pub, ifp->idx));
drvr_priv->pub.tx_realloc++; drvr_priv->pub.tx_realloc++;
skb2 = skb_realloc_headroom(skb, drvr_priv->pub.hdrlen); skb2 = skb_realloc_headroom(skb, drvr_priv->pub.hdrlen);
dev_kfree_skb(skb); dev_kfree_skb(skb);
skb = skb2; skb = skb2;
if (skb == NULL) { if (skb == NULL) {
brcmf_dbg(ERROR, "%s: skb_realloc_headroom failed\n", brcmf_dbg(ERROR, "%s: skb_realloc_headroom failed\n",
brcmf_ifname(&drvr_priv->pub, ifidx)); brcmf_ifname(&drvr_priv->pub, ifp->idx));
ret = -ENOMEM; ret = -ENOMEM;
goto done; goto done;
} }
} }
ret = brcmf_sendpkt(&drvr_priv->pub, ifidx, skb); ret = brcmf_sendpkt(&drvr_priv->pub, ifp->idx, skb);
done: done:
if (ret) if (ret)
...@@ -524,19 +498,11 @@ void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp, bool success) ...@@ -524,19 +498,11 @@ void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp, bool success)
static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev) static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
{ {
struct brcmf_info *drvr_priv = *(struct brcmf_info **) struct brcmf_if *ifp = netdev_priv(ndev);
netdev_priv(ndev); struct brcmf_info *drvr_priv = ifp->info;
struct brcmf_if *ifp;
int ifidx;
brcmf_dbg(TRACE, "Enter\n"); brcmf_dbg(TRACE, "Enter\n");
ifidx = brcmf_net2idx(drvr_priv, ndev);
if (ifidx == BRCMF_BAD_IF)
return NULL;
ifp = drvr_priv->iflist[ifidx];
if (drvr_priv->pub.up) if (drvr_priv->pub.up)
/* Use the protocol to get dongle stats */ /* Use the protocol to get dongle stats */
brcmf_proto_dstats(&drvr_priv->pub); brcmf_proto_dstats(&drvr_priv->pub);
...@@ -637,8 +603,8 @@ static int brcmf_toe_set(struct brcmf_info *drvr_priv, int ifidx, u32 toe_ol) ...@@ -637,8 +603,8 @@ static int brcmf_toe_set(struct brcmf_info *drvr_priv, int ifidx, u32 toe_ol)
static void brcmf_ethtool_get_drvinfo(struct net_device *ndev, static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
struct ethtool_drvinfo *info) struct ethtool_drvinfo *info)
{ {
struct brcmf_info *drvr_priv = *(struct brcmf_info **) struct brcmf_if *ifp = netdev_priv(ndev);
netdev_priv(ndev); struct brcmf_info *drvr_priv = ifp->info;
sprintf(info->driver, KBUILD_MODNAME); sprintf(info->driver, KBUILD_MODNAME);
sprintf(info->version, "%lu", drvr_priv->pub.drv_version); sprintf(info->version, "%lu", drvr_priv->pub.drv_version);
...@@ -765,14 +731,12 @@ static int brcmf_ethtool(struct brcmf_info *drvr_priv, void __user *uaddr) ...@@ -765,14 +731,12 @@ static int brcmf_ethtool(struct brcmf_info *drvr_priv, void __user *uaddr)
static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr, static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
int cmd) int cmd)
{ {
struct brcmf_info *drvr_priv = *(struct brcmf_info **) struct brcmf_if *ifp = netdev_priv(ndev);
netdev_priv(ndev); struct brcmf_info *drvr_priv = ifp->info;
int ifidx;
ifidx = brcmf_net2idx(drvr_priv, ndev); brcmf_dbg(TRACE, "ifidx %d, cmd 0x%04x\n", ifp->idx, cmd);
brcmf_dbg(TRACE, "ifidx %d, cmd 0x%04x\n", ifidx, cmd);
if (ifidx == BRCMF_BAD_IF) if (!drvr_priv->iflist[ifp->idx])
return -1; return -1;
if (cmd == SIOCETHTOOL) if (cmd == SIOCETHTOOL)
...@@ -788,17 +752,14 @@ s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len) ...@@ -788,17 +752,14 @@ s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len)
s32 err = 0; s32 err = 0;
int buflen = 0; int buflen = 0;
bool is_set_key_cmd; bool is_set_key_cmd;
struct brcmf_info *drvr_priv = *(struct brcmf_info **) struct brcmf_if *ifp = netdev_priv(ndev);
netdev_priv(ndev); struct brcmf_info *drvr_priv = ifp->info;
int ifidx;
memset(&dcmd, 0, sizeof(dcmd)); memset(&dcmd, 0, sizeof(dcmd));
dcmd.cmd = cmd; dcmd.cmd = cmd;
dcmd.buf = arg; dcmd.buf = arg;
dcmd.len = len; dcmd.len = len;
ifidx = brcmf_net2idx(drvr_priv, ndev);
if (dcmd.buf != NULL) if (dcmd.buf != NULL)
buflen = min_t(uint, dcmd.len, BRCMF_DCMD_MAXLEN); buflen = min_t(uint, dcmd.len, BRCMF_DCMD_MAXLEN);
...@@ -826,7 +787,7 @@ s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len) ...@@ -826,7 +787,7 @@ s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len)
if (is_set_key_cmd) if (is_set_key_cmd)
brcmf_netdev_wait_pend8021x(ndev); brcmf_netdev_wait_pend8021x(ndev);
err = brcmf_proto_dcmd(&drvr_priv->pub, ifidx, &dcmd, buflen); err = brcmf_proto_dcmd(&drvr_priv->pub, ifp->idx, &dcmd, buflen);
done: done:
if (err > 0) if (err > 0)
...@@ -837,7 +798,8 @@ s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len) ...@@ -837,7 +798,8 @@ s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len)
static int brcmf_netdev_stop(struct net_device *ndev) static int brcmf_netdev_stop(struct net_device *ndev)
{ {
struct brcmf_pub *drvr = *(struct brcmf_pub **) netdev_priv(ndev); struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_pub *drvr = &ifp->info->pub;
brcmf_dbg(TRACE, "Enter\n"); brcmf_dbg(TRACE, "Enter\n");
brcmf_cfg80211_down(drvr->config); brcmf_cfg80211_down(drvr->config);
...@@ -853,16 +815,14 @@ static int brcmf_netdev_stop(struct net_device *ndev) ...@@ -853,16 +815,14 @@ static int brcmf_netdev_stop(struct net_device *ndev)
static int brcmf_netdev_open(struct net_device *ndev) static int brcmf_netdev_open(struct net_device *ndev)
{ {
struct brcmf_info *drvr_priv = *(struct brcmf_info **) struct brcmf_if *ifp = netdev_priv(ndev);
netdev_priv(ndev); struct brcmf_info *drvr_priv = ifp->info;
u32 toe_ol; u32 toe_ol;
int ifidx = brcmf_net2idx(drvr_priv, ndev);
s32 ret = 0; s32 ret = 0;
brcmf_dbg(TRACE, "ifidx %d\n", ifidx); brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx);
if (ifidx == 0) { /* do it only for primary eth0 */
if (ifp->idx == 0) { /* do it only for primary eth0 */
/* try to bring up bus */ /* try to bring up bus */
ret = brcmf_bus_start(&drvr_priv->pub); ret = brcmf_bus_start(&drvr_priv->pub);
if (ret != 0) { if (ret != 0) {
...@@ -874,12 +834,12 @@ static int brcmf_netdev_open(struct net_device *ndev) ...@@ -874,12 +834,12 @@ static int brcmf_netdev_open(struct net_device *ndev)
memcpy(ndev->dev_addr, drvr_priv->pub.mac, ETH_ALEN); memcpy(ndev->dev_addr, drvr_priv->pub.mac, ETH_ALEN);
/* Get current TOE mode from dongle */ /* Get current TOE mode from dongle */
if (brcmf_toe_get(drvr_priv, ifidx, &toe_ol) >= 0 if (brcmf_toe_get(drvr_priv, ifp->idx, &toe_ol) >= 0
&& (toe_ol & TOE_TX_CSUM_OL) != 0) && (toe_ol & TOE_TX_CSUM_OL) != 0)
drvr_priv->iflist[ifidx]->ndev->features |= drvr_priv->iflist[ifp->idx]->ndev->features |=
NETIF_F_IP_CSUM; NETIF_F_IP_CSUM;
else else
drvr_priv->iflist[ifidx]->ndev->features &= drvr_priv->iflist[ifp->idx]->ndev->features &=
~NETIF_F_IP_CSUM; ~NETIF_F_IP_CSUM;
} }
/* Allow transmit calls */ /* Allow transmit calls */
...@@ -907,53 +867,45 @@ int ...@@ -907,53 +867,45 @@ int
brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, char *name, u8 *mac_addr) brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, char *name, u8 *mac_addr)
{ {
struct brcmf_if *ifp; struct brcmf_if *ifp;
int err = 0; struct net_device *ndev;
brcmf_dbg(TRACE, "idx %d\n", ifidx); brcmf_dbg(TRACE, "idx %d\n", ifidx);
ifp = drvr_priv->iflist[ifidx]; ifp = drvr_priv->iflist[ifidx];
if (!ifp) {
ifp = kmalloc(sizeof(struct brcmf_if), GFP_ATOMIC);
if (!ifp)
return -ENOMEM;
drvr_priv->iflist[ifidx] = ifp;
} else {
/* /*
* Delete the existing interface before overwriting it * Delete the existing interface before overwriting it
* in case we missed the BRCMF_E_IF_DEL event. * in case we missed the BRCMF_E_IF_DEL event.
*/ */
if (ifp->ndev != NULL) { if (ifp) {
brcmf_dbg(ERROR, "ERROR: netdev:%s already exists, try free & unregister\n", brcmf_dbg(ERROR, "ERROR: netdev:%s already exists, try free & unregister\n",
ifp->ndev->name); ifp->ndev->name);
netif_stop_queue(ifp->ndev); netif_stop_queue(ifp->ndev);
unregister_netdev(ifp->ndev); unregister_netdev(ifp->ndev);
free_netdev(ifp->ndev); free_netdev(ifp->ndev);
drvr_priv->iflist[ifidx] = NULL;
} }
}
memset(ifp, 0, sizeof(struct brcmf_if));
ifp->info = drvr_priv;
drvr_priv->iflist[ifidx] = ifp;
ifp->state = BRCMF_E_IF_ADD;
ifp->idx = ifidx;
/* Allocate netdev, including space for private structure */ /* Allocate netdev, including space for private structure */
ifp->ndev = alloc_netdev(sizeof(drvr_priv), name, ether_setup); ndev = alloc_netdev(sizeof(struct brcmf_if), name, ether_setup);
if (!ifp->ndev) { if (!ndev) {
brcmf_dbg(ERROR, "OOM - alloc_netdev\n"); brcmf_dbg(ERROR, "OOM - alloc_netdev\n");
err = -ENOMEM; return -ENOMEM;
goto errout;
} }
ifp = netdev_priv(ndev);
ifp->ndev = ndev;
ifp->info = drvr_priv;
drvr_priv->iflist[ifidx] = ifp;
ifp->state = BRCMF_E_IF_ADD;
ifp->idx = ifidx;
if (mac_addr != NULL) if (mac_addr != NULL)
memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN); memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN);
memcpy(netdev_priv(ifp->ndev), &drvr_priv, sizeof(drvr_priv));
if (brcmf_net_attach(&drvr_priv->pub, ifp->idx)) { if (brcmf_net_attach(&drvr_priv->pub, ifp->idx)) {
brcmf_dbg(ERROR, "brcmf_net_attach failed"); brcmf_dbg(ERROR, "brcmf_net_attach failed");
free_netdev(ifp->ndev); free_netdev(ifp->ndev);
err = -EOPNOTSUPP; drvr_priv->iflist[ifidx] = NULL;
goto errout; return -EOPNOTSUPP;
} }
brcmf_dbg(TRACE, " ==== pid:%x, net_device for if:%s created ===\n", brcmf_dbg(TRACE, " ==== pid:%x, net_device for if:%s created ===\n",
...@@ -961,11 +913,6 @@ brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, char *name, u8 *mac_addr) ...@@ -961,11 +913,6 @@ brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, char *name, u8 *mac_addr)
ifp->state = 0; ifp->state = 0;
return 0; return 0;
errout:
kfree(ifp);
drvr_priv->iflist[ifidx] = NULL;
return err;
} }
void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx) void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx)
...@@ -996,7 +943,6 @@ void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx) ...@@ -996,7 +943,6 @@ void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx)
if (ifidx == 0) if (ifidx == 0)
brcmf_cfg80211_detach(drvr_priv->pub.config); brcmf_cfg80211_detach(drvr_priv->pub.config);
free_netdev(ifp->ndev); free_netdev(ifp->ndev);
kfree(ifp);
} }
} }
...@@ -1268,7 +1214,8 @@ static int brcmf_get_pend_8021x_cnt(struct brcmf_info *drvr_priv) ...@@ -1268,7 +1214,8 @@ static int brcmf_get_pend_8021x_cnt(struct brcmf_info *drvr_priv)
int brcmf_netdev_wait_pend8021x(struct net_device *ndev) int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
{ {
struct brcmf_info *drvr_priv = *(struct brcmf_info **)netdev_priv(ndev); struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_info *drvr_priv = ifp->info;
int timeout = 10 * HZ / 1000; int timeout = 10 * HZ / 1000;
int ntimes = MAX_WAIT_FOR_8021X_TX; int ntimes = MAX_WAIT_FOR_8021X_TX;
int pend = brcmf_get_pend_8021x_cnt(drvr_priv); int pend = brcmf_get_pend_8021x_cnt(drvr_priv);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment