static int brcmf_netdev_open(struct net_device *ndev) { struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_pub *drvr = ifp->drvr; struct brcmf_bus *bus_if = drvr->bus_if; u32 toe_ol; brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx); /* If bus is not ready, can't continue */ if (bus_if->state != BRCMF_BUS_UP) { brcmf_err("failed bus is not ready\n"); return -EAGAIN; } atomic_set(&ifp->pend_8021x_cnt, 0); /* 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) ndev->features |= NETIF_F_IP_CSUM; else ndev->features &= ~NETIF_F_IP_CSUM; if (brcmf_cfg80211_up(ndev)) { brcmf_err("failed to bring up cfg80211\n"); return -EIO; } /* Clear, carrier, set when connected or AP mode. */ netif_carrier_off(ndev); return 0; }
/** * brcmf_feat_iovar_int_get() - determine feature through iovar query. * * @ifp: interface to query. * @id: feature id. * @name: iovar name. */ static void brcmf_feat_iovar_int_get(struct brcmf_if *ifp, enum brcmf_feat_id id, char *name) { u32 data; int err; err = brcmf_fil_iovar_int_get(ifp, name, &data); if (err == 0) { brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]); ifp->drvr->feat_flags |= BIT(id); } else { brcmf_dbg(TRACE, "%s feature check failed: %d\n", brcmf_feat_names[id], err); } }
static int brcmf_inetaddr_changed(struct notifier_block *nb, unsigned long action, void *data) { struct brcmf_pub *drvr = container_of(nb, struct brcmf_pub, inetaddr_notifier); struct in_ifaddr *ifa = data; struct net_device *ndev = ifa->ifa_dev->dev; struct brcmf_if *ifp; int idx, i, ret; u32 val; __be32 addr_table[ARPOL_MAX_ENTRIES] = {0}; /* Find out if the notification is meant for us */ for (idx = 0; idx < BRCMF_MAX_IFS; idx++) { ifp = drvr->iflist[idx]; if (ifp && ifp->ndev == ndev) break; if (idx == BRCMF_MAX_IFS - 1) return NOTIFY_DONE; } /* check if arp offload is supported */ ret = brcmf_fil_iovar_int_get(ifp, "arpoe", &val); if (ret) return NOTIFY_OK; /* old version only support primary index */ ret = brcmf_fil_iovar_int_get(ifp, "arp_version", &val); if (ret) val = 1; if (val == 1) ifp = drvr->iflist[0]; /* retrieve the table from firmware */ ret = brcmf_fil_iovar_data_get(ifp, "arp_hostip", addr_table, sizeof(addr_table)); if (ret) { brcmf_err("fail to get arp ip table err:%d\n", ret); return NOTIFY_OK; } for (i = 0; i < ARPOL_MAX_ENTRIES; i++) if (ifa->ifa_address == addr_table[i]) break; switch (action) { case NETDEV_UP: if (i == ARPOL_MAX_ENTRIES) { brcmf_dbg(TRACE, "add %pI4 to arp table\n", &ifa->ifa_address); /* set it directly */ ret = brcmf_fil_iovar_data_set(ifp, "arp_hostip", &ifa->ifa_address, sizeof(ifa->ifa_address)); if (ret) brcmf_err("add arp ip err %d\n", ret); } break; case NETDEV_DOWN: if (i < ARPOL_MAX_ENTRIES) { addr_table[i] = 0; brcmf_dbg(TRACE, "remove %pI4 from arp table\n", &ifa->ifa_address); /* clear the table in firmware */ ret = brcmf_fil_iovar_data_set(ifp, "arp_hostip_clear", NULL, 0); if (ret) { brcmf_err("fail to clear arp ip table err:%d\n", ret); return NOTIFY_OK; } for (i = 0; i < ARPOL_MAX_ENTRIES; i++) { if (addr_table[i] == 0) continue; ret = brcmf_fil_iovar_data_set(ifp, "arp_hostip", &addr_table[i], sizeof(addr_table[i])); if (ret) brcmf_err("add arp ip err %d\n", ret); } } break; default: break; } return NOTIFY_OK; }
/** * brcmf_btcoex_params_read() - read btc_params firmware variable * @ifp: interface * @addr: btc_params register number * @data: read data */ static s32 brcmf_btcoex_params_read(struct brcmf_if *ifp, u32 addr, u32 *data) { *data = addr; return brcmf_fil_iovar_int_get(ifp, "btc_params", data); }