mirror of
https://github.com/torvalds/linux.git
synced 2024-11-15 00:21:59 +00:00
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: Johannes Berg <johannes@sipsolutions.net> Reviewed-by: Roland Vossen <rvossen@broadcom.com> Reviewed-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: Franky (Zhenhui) Lin <frankyl@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
15d45b6fbd
commit
e1b835865c
@ -123,7 +123,6 @@
|
||||
/* For supporting multiple interfaces */
|
||||
#define BRCMF_MAX_IFS 16
|
||||
#define BRCMF_DEL_IF -0xe
|
||||
#define BRCMF_BAD_IF -0xf
|
||||
|
||||
#define DOT11_BSSTYPE_ANY 2
|
||||
#define DOT11_MAX_DEFAULT_KEYS 4
|
||||
|
@ -80,20 +80,6 @@ struct brcmf_info {
|
||||
/* Error bits */
|
||||
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 i = BRCMF_MAX_IFS;
|
||||
@ -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)
|
||||
{
|
||||
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;
|
||||
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);
|
||||
schedule_work(&drvr_priv->setmacaddr_work);
|
||||
@ -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)
|
||||
{
|
||||
struct brcmf_info *drvr_priv = *(struct brcmf_info **)
|
||||
netdev_priv(ndev);
|
||||
int ifidx;
|
||||
|
||||
ifidx = brcmf_net2idx(drvr_priv, ndev);
|
||||
if (ifidx == BRCMF_BAD_IF)
|
||||
return;
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_info *drvr_priv = ifp->info;
|
||||
|
||||
schedule_work(&drvr_priv->multicast_work);
|
||||
}
|
||||
@ -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)
|
||||
{
|
||||
int ret;
|
||||
struct brcmf_info *drvr_priv = *(struct brcmf_info **)
|
||||
netdev_priv(ndev);
|
||||
int ifidx;
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_info *drvr_priv = ifp->info;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
@ -355,9 +330,8 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ifidx = brcmf_net2idx(drvr_priv, ndev);
|
||||
if (ifidx == BRCMF_BAD_IF) {
|
||||
brcmf_dbg(ERROR, "bad ifidx %d\n", ifidx);
|
||||
if (!drvr_priv->iflist[ifp->idx]) {
|
||||
brcmf_dbg(ERROR, "bad ifidx %d\n", ifp->idx);
|
||||
netif_stop_queue(ndev);
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -367,20 +341,20 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
struct sk_buff *skb2;
|
||||
|
||||
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++;
|
||||
skb2 = skb_realloc_headroom(skb, drvr_priv->pub.hdrlen);
|
||||
dev_kfree_skb(skb);
|
||||
skb = skb2;
|
||||
if (skb == NULL) {
|
||||
brcmf_dbg(ERROR, "%s: skb_realloc_headroom failed\n",
|
||||
brcmf_ifname(&drvr_priv->pub, ifidx));
|
||||
brcmf_ifname(&drvr_priv->pub, ifp->idx));
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
ret = brcmf_sendpkt(&drvr_priv->pub, ifidx, skb);
|
||||
ret = brcmf_sendpkt(&drvr_priv->pub, ifp->idx, skb);
|
||||
|
||||
done:
|
||||
if (ret)
|
||||
@ -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)
|
||||
{
|
||||
struct brcmf_info *drvr_priv = *(struct brcmf_info **)
|
||||
netdev_priv(ndev);
|
||||
struct brcmf_if *ifp;
|
||||
int ifidx;
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_info *drvr_priv = ifp->info;
|
||||
|
||||
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)
|
||||
/* Use the protocol to get dongle stats */
|
||||
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)
|
||||
static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
|
||||
struct ethtool_drvinfo *info)
|
||||
{
|
||||
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;
|
||||
|
||||
sprintf(info->driver, KBUILD_MODNAME);
|
||||
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)
|
||||
static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
|
||||
int cmd)
|
||||
{
|
||||
struct brcmf_info *drvr_priv = *(struct brcmf_info **)
|
||||
netdev_priv(ndev);
|
||||
int ifidx;
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_info *drvr_priv = ifp->info;
|
||||
|
||||
ifidx = brcmf_net2idx(drvr_priv, ndev);
|
||||
brcmf_dbg(TRACE, "ifidx %d, cmd 0x%04x\n", ifidx, cmd);
|
||||
brcmf_dbg(TRACE, "ifidx %d, cmd 0x%04x\n", ifp->idx, cmd);
|
||||
|
||||
if (ifidx == BRCMF_BAD_IF)
|
||||
if (!drvr_priv->iflist[ifp->idx])
|
||||
return -1;
|
||||
|
||||
if (cmd == SIOCETHTOOL)
|
||||
@ -788,17 +752,14 @@ s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len)
|
||||
s32 err = 0;
|
||||
int buflen = 0;
|
||||
bool is_set_key_cmd;
|
||||
struct brcmf_info *drvr_priv = *(struct brcmf_info **)
|
||||
netdev_priv(ndev);
|
||||
int ifidx;
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_info *drvr_priv = ifp->info;
|
||||
|
||||
memset(&dcmd, 0, sizeof(dcmd));
|
||||
dcmd.cmd = cmd;
|
||||
dcmd.buf = arg;
|
||||
dcmd.len = len;
|
||||
|
||||
ifidx = brcmf_net2idx(drvr_priv, ndev);
|
||||
|
||||
if (dcmd.buf != NULL)
|
||||
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)
|
||||
if (is_set_key_cmd)
|
||||
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:
|
||||
if (err > 0)
|
||||
@ -837,7 +798,8 @@ done:
|
||||
|
||||
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_cfg80211_down(drvr->config);
|
||||
@ -853,16 +815,14 @@ static int brcmf_netdev_stop(struct net_device *ndev)
|
||||
|
||||
static int brcmf_netdev_open(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;
|
||||
u32 toe_ol;
|
||||
int ifidx = brcmf_net2idx(drvr_priv, ndev);
|
||||
s32 ret = 0;
|
||||
|
||||
brcmf_dbg(TRACE, "ifidx %d\n", ifidx);
|
||||
|
||||
if (ifidx == 0) { /* do it only for primary eth0 */
|
||||
brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx);
|
||||
|
||||
if (ifp->idx == 0) { /* do it only for primary eth0 */
|
||||
/* try to bring up bus */
|
||||
ret = brcmf_bus_start(&drvr_priv->pub);
|
||||
if (ret != 0) {
|
||||
@ -874,12 +834,12 @@ static int brcmf_netdev_open(struct net_device *ndev)
|
||||
memcpy(ndev->dev_addr, drvr_priv->pub.mac, ETH_ALEN);
|
||||
|
||||
/* 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)
|
||||
drvr_priv->iflist[ifidx]->ndev->features |=
|
||||
drvr_priv->iflist[ifp->idx]->ndev->features |=
|
||||
NETIF_F_IP_CSUM;
|
||||
else
|
||||
drvr_priv->iflist[ifidx]->ndev->features &=
|
||||
drvr_priv->iflist[ifp->idx]->ndev->features &=
|
||||
~NETIF_F_IP_CSUM;
|
||||
}
|
||||
/* Allow transmit calls */
|
||||
@ -907,53 +867,45 @@ int
|
||||
brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, char *name, u8 *mac_addr)
|
||||
{
|
||||
struct brcmf_if *ifp;
|
||||
int err = 0;
|
||||
struct net_device *ndev;
|
||||
|
||||
brcmf_dbg(TRACE, "idx %d\n", 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
|
||||
* in case we missed the BRCMF_E_IF_DEL event.
|
||||
*/
|
||||
if (ifp->ndev != NULL) {
|
||||
brcmf_dbg(ERROR, "ERROR: netdev:%s already exists, try free & unregister\n",
|
||||
ifp->ndev->name);
|
||||
netif_stop_queue(ifp->ndev);
|
||||
unregister_netdev(ifp->ndev);
|
||||
free_netdev(ifp->ndev);
|
||||
}
|
||||
/*
|
||||
* Delete the existing interface before overwriting it
|
||||
* in case we missed the BRCMF_E_IF_DEL event.
|
||||
*/
|
||||
if (ifp) {
|
||||
brcmf_dbg(ERROR, "ERROR: netdev:%s already exists, try free & unregister\n",
|
||||
ifp->ndev->name);
|
||||
netif_stop_queue(ifp->ndev);
|
||||
unregister_netdev(ifp->ndev);
|
||||
free_netdev(ifp->ndev);
|
||||
drvr_priv->iflist[ifidx] = NULL;
|
||||
}
|
||||
memset(ifp, 0, sizeof(struct brcmf_if));
|
||||
|
||||
/* Allocate netdev, including space for private structure */
|
||||
ndev = alloc_netdev(sizeof(struct brcmf_if), name, ether_setup);
|
||||
if (!ndev) {
|
||||
brcmf_dbg(ERROR, "OOM - alloc_netdev\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/* Allocate netdev, including space for private structure */
|
||||
ifp->ndev = alloc_netdev(sizeof(drvr_priv), name, ether_setup);
|
||||
if (!ifp->ndev) {
|
||||
brcmf_dbg(ERROR, "OOM - alloc_netdev\n");
|
||||
err = -ENOMEM;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (mac_addr != NULL)
|
||||
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)) {
|
||||
brcmf_dbg(ERROR, "brcmf_net_attach failed");
|
||||
free_netdev(ifp->ndev);
|
||||
err = -EOPNOTSUPP;
|
||||
goto errout;
|
||||
drvr_priv->iflist[ifidx] = NULL;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
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)
|
||||
ifp->state = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
errout:
|
||||
kfree(ifp);
|
||||
drvr_priv->iflist[ifidx] = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
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)
|
||||
brcmf_cfg80211_detach(drvr_priv->pub.config);
|
||||
free_netdev(ifp->ndev);
|
||||
kfree(ifp);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
{
|
||||
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 ntimes = MAX_WAIT_FOR_8021X_TX;
|
||||
int pend = brcmf_get_pend_8021x_cnt(drvr_priv);
|
||||
|
Loading…
Reference in New Issue
Block a user