s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, u32 len) { struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_if *ifp = bus_if->drvr->iflist[0]; return brcmf_fil_iovar_data_set(ifp, name, data, len); }
s32 brcmf_fil_iovar_int_set(struct brcmf_if *ifp, char *name, u32 data) { __le32 data_le = cpu_to_le32(data); return brcmf_fil_iovar_data_set(ifp, name, &data_le, sizeof(data_le)); }
/** * brcmf_btcoex_params_write() - write btc_params firmware variable * @ifp: interface * @addr: btc_params register number * @data: data to write */ static s32 brcmf_btcoex_params_write(struct brcmf_if *ifp, u32 addr, u32 data) { struct { __le32 addr; __le32 data; } reg_write; reg_write.addr = cpu_to_le32(addr); reg_write.data = cpu_to_le32(data); return brcmf_fil_iovar_data_set(ifp, "btc_params", ®_write, sizeof(reg_write)); }
static void _brcmf_update_ndtable(struct work_struct *work) { struct brcmf_if *ifp; int i, ret; ifp = container_of(work, struct brcmf_if, ndoffload_work); /* clear the table in firmware */ ret = brcmf_fil_iovar_data_set(ifp, "nd_hostip_clear", NULL, 0); if (ret) { brcmf_dbg(TRACE, "fail to clear nd ip table err:%d\n", ret); return; } for (i = 0; i < ifp->ipv6addr_idx; i++) { ret = brcmf_fil_iovar_data_set(ifp, "nd_hostip", &ifp->ipv6_addr_tbl[i], sizeof(struct in6_addr)); if (ret) brcmf_err("add nd ip err %d\n", ret); } }
static int brcmf_netdev_stop(struct net_device *ndev) { struct brcmf_if *ifp = netdev_priv(ndev); brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx); brcmf_cfg80211_down(ndev); brcmf_fil_iovar_data_set(ifp, "arp_hostip_clear", NULL, 0); brcmf_net_setcarrier(ifp, false); return 0; }
static void brcmf_c_pktfilter_offload_enable(struct brcmf_if *ifp, char *arg, int enable, int master_mode) { unsigned long res; char *argv; char *arg_save = NULL, *arg_org = NULL; s32 err; struct brcmf_pkt_filter_enable_le enable_parm; arg_save = kstrdup(arg, GFP_ATOMIC); if (!arg_save) goto fail; arg_org = arg_save; argv = strsep(&arg_save, " "); if (argv == NULL) { brcmf_err("No args provided\n"); goto fail; } /* Parse packet filter id. */ enable_parm.id = 0; if (!kstrtoul(argv, 0, &res)) enable_parm.id = cpu_to_le32((u32)res); /* Enable/disable the specified filter. */ enable_parm.enable = cpu_to_le32(enable); err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_enable", &enable_parm, sizeof(enable_parm)); if (err) brcmf_err("Set pkt_filter_enable error (%d)\n", err); /* Control the master mode */ err = brcmf_fil_iovar_int_set(ifp, "pkt_filter_mode", master_mode); if (err) brcmf_err("Set pkt_filter_mode error (%d)\n", err); fail: kfree(arg_org); }
static void _brcmf_set_mac_address(struct work_struct *work) { struct brcmf_if *ifp; s32 err; brcmf_dbg(TRACE, "enter\n"); ifp = container_of(work, struct brcmf_if, setmacaddr_work); err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", ifp->mac_addr, ETH_ALEN); if (err < 0) { brcmf_err("Setting cur_etheraddr failed, %d\n", err); } else { brcmf_dbg(TRACE, "MAC address updated to %pM\n", ifp->mac_addr); memcpy(ifp->ndev->dev_addr, ifp->mac_addr, ETH_ALEN); } }
void brcmf_c_set_joinpref_default(struct brcmf_if *ifp) { struct brcmf_join_pref_params join_pref_params[2]; int err; /* Setup join_pref to select target by RSSI (boost on 5GHz) */ join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA; join_pref_params[0].len = 2; join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST; join_pref_params[0].band = WLC_BAND_5G; join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI; join_pref_params[1].len = 2; join_pref_params[1].rssi_gain = 0; join_pref_params[1].band = 0; err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params, sizeof(join_pref_params)); if (err) brcmf_err("Set join_pref error (%d)\n", err); }
static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr) { struct brcmf_if *ifp = netdev_priv(ndev); struct sockaddr *sa = (struct sockaddr *)addr; struct brcmf_pub *drvr = ifp->drvr; int err; brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx); err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", sa->sa_data, ETH_ALEN); if (err < 0) { bphy_err(drvr, "Setting cur_etheraddr failed, %d\n", err); } else { brcmf_dbg(TRACE, "updated to %pM\n", sa->sa_data); memcpy(ifp->mac_addr, sa->sa_data, ETH_ALEN); memcpy(ifp->ndev->dev_addr, ifp->mac_addr, ETH_ALEN); } return err; }
int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) { s8 eventmask[BRCMF_EVENTING_MASK_LEN]; u8 buf[BRCMF_DCMD_SMLEN]; struct brcmf_rev_info_le revinfo; struct brcmf_rev_info *ri; char *ptr; s32 err; /* retreive mac address */ err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr, sizeof(ifp->mac_addr)); if (err < 0) { brcmf_err("Retreiving cur_etheraddr failed, %d\n", err); goto done; } memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac)); err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_REVINFO, &revinfo, sizeof(revinfo)); ri = &ifp->drvr->revinfo; if (err < 0) { brcmf_err("retrieving revision info failed, %d\n", err); } else { ri->vendorid = le32_to_cpu(revinfo.vendorid); ri->deviceid = le32_to_cpu(revinfo.deviceid); ri->radiorev = le32_to_cpu(revinfo.radiorev); ri->chiprev = le32_to_cpu(revinfo.chiprev); ri->corerev = le32_to_cpu(revinfo.corerev); ri->boardid = le32_to_cpu(revinfo.boardid); ri->boardvendor = le32_to_cpu(revinfo.boardvendor); ri->boardrev = le32_to_cpu(revinfo.boardrev); ri->driverrev = le32_to_cpu(revinfo.driverrev); ri->ucoderev = le32_to_cpu(revinfo.ucoderev); ri->bus = le32_to_cpu(revinfo.bus); ri->chipnum = le32_to_cpu(revinfo.chipnum); ri->phytype = le32_to_cpu(revinfo.phytype); ri->phyrev = le32_to_cpu(revinfo.phyrev); ri->anarev = le32_to_cpu(revinfo.anarev); ri->chippkg = le32_to_cpu(revinfo.chippkg); ri->nvramrev = le32_to_cpu(revinfo.nvramrev); } ri->result = err; /* query for 'ver' to get version info from firmware */ memset(buf, 0, sizeof(buf)); strcpy(buf, "ver"); err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf)); if (err < 0) { brcmf_err("Retreiving version information failed, %d\n", err); goto done; } ptr = (char *)buf; strsep(&ptr, "\n"); /* Print fw version info */ brcmf_err("Firmware version = %s\n", buf); /* locate firmware version number for ethtool */ ptr = strrchr(buf, ' ') + 1; strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver)); /* set mpc */ err = brcmf_fil_iovar_int_set(ifp, "mpc", 1); if (err) { brcmf_err("failed setting mpc\n"); goto done; } brcmf_c_set_joinpref_default(ifp); /* Setup event_msgs, enable E_IF */ err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN); if (err) { brcmf_err("Get event_msgs error (%d)\n", err); goto done; } setbit(eventmask, BRCMF_E_IF); err = brcmf_fil_iovar_data_set(ifp, "event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN); if (err) { brcmf_err("Set event_msgs error (%d)\n", err); goto done; } /* Setup default scan channel time */ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME, BRCMF_DEFAULT_SCAN_CHANNEL_TIME); if (err) { brcmf_err("BRCMF_C_SET_SCAN_CHANNEL_TIME error (%d)\n", err); goto done; } /* Setup default scan unassoc time */ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME, BRCMF_DEFAULT_SCAN_UNASSOC_TIME); if (err) { brcmf_err("BRCMF_C_SET_SCAN_UNASSOC_TIME error (%d)\n", err); goto done; } /* Enable tx beamforming, errors can be ignored (not supported) */ (void)brcmf_fil_iovar_int_set(ifp, "txbf", 1); /* do bus specific preinit here */ err = brcmf_bus_preinit(ifp->drvr->bus_if); done: return 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; }
static void _brcmf_set_multicast_list(struct work_struct *work) { struct brcmf_if *ifp; struct net_device *ndev; struct netdev_hw_addr *ha; u32 cmd_value, cnt; __le32 cnt_le; char *buf, *bufp; u32 buflen; s32 err; ifp = container_of(work, struct brcmf_if, multicast_work); brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx); ndev = ifp->ndev; /* Determine initial value of allmulti flag */ cmd_value = (ndev->flags & IFF_ALLMULTI) ? true : false; /* Send down the multicast list first. */ cnt = netdev_mc_count(ndev); buflen = sizeof(cnt) + (cnt * ETH_ALEN); buf = kmalloc(buflen, GFP_ATOMIC); if (!buf) return; bufp = buf; cnt_le = cpu_to_le32(cnt); memcpy(bufp, &cnt_le, sizeof(cnt_le)); bufp += sizeof(cnt_le); netdev_for_each_mc_addr(ha, ndev) { if (!cnt) break; memcpy(bufp, ha->addr, ETH_ALEN); bufp += ETH_ALEN; cnt--; } err = brcmf_fil_iovar_data_set(ifp, "mcast_list", buf, buflen); if (err < 0) { brcmf_err("Setting mcast_list failed, %d\n", err); cmd_value = cnt ? true : cmd_value; } kfree(buf); /* * Now send the allmulti setting. This is based on the setting in the * net_device flags, but might be modified above to be turned on if we * were trying to set some addresses and dongle rejected it... */ err = brcmf_fil_iovar_int_set(ifp, "allmulti", cmd_value); if (err < 0) brcmf_err("Setting allmulti failed, %d\n", err); /*Finally, pick up the PROMISC flag */ cmd_value = (ndev->flags & IFF_PROMISC) ? true : false; err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PROMISC, cmd_value); if (err < 0) brcmf_err("Setting BRCMF_C_SET_PROMISC failed, %d\n", err); }
int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) { s8 eventmask[BRCMF_EVENTING_MASK_LEN]; u8 buf[BRCMF_DCMD_SMLEN]; struct brcmf_join_pref_params join_pref_params[2]; char *ptr; s32 err; /* retreive mac address */ err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr, sizeof(ifp->mac_addr)); if (err < 0) { brcmf_err("Retreiving cur_etheraddr failed, %d\n", err); goto done; } memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac)); /* query for 'ver' to get version info from firmware */ memset(buf, 0, sizeof(buf)); strcpy(buf, "ver"); err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf)); if (err < 0) { brcmf_err("Retreiving version information failed, %d\n", err); goto done; } ptr = (char *)buf; strsep(&ptr, "\n"); /* Print fw version info */ brcmf_err("Firmware version = %s\n", buf); /* locate firmware version number for ethtool */ ptr = strrchr(buf, ' ') + 1; strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver)); /* set mpc */ err = brcmf_fil_iovar_int_set(ifp, "mpc", 1); if (err) { brcmf_err("failed setting mpc\n"); goto done; } /* * Setup timeout if Beacons are lost and roam is off to report * link down */ err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", BRCMF_DEFAULT_BCN_TIMEOUT); if (err) { brcmf_err("bcn_timeout error (%d)\n", err); goto done; } /* Enable/Disable build-in roaming to allowed ext supplicant to take * of romaing */ err = brcmf_fil_iovar_int_set(ifp, "roam_off", 1); if (err) { brcmf_err("roam_off error (%d)\n", err); goto done; } /* Setup join_pref to select target by RSSI(with boost on 5GHz) */ join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA; join_pref_params[0].len = 2; join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST; join_pref_params[0].band = WLC_BAND_5G; join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI; join_pref_params[1].len = 2; join_pref_params[1].rssi_gain = 0; join_pref_params[1].band = 0; err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params, sizeof(join_pref_params)); if (err) brcmf_err("Set join_pref error (%d)\n", err); /* Setup event_msgs, enable E_IF */ err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN); if (err) { brcmf_err("Get event_msgs error (%d)\n", err); goto done; } setbit(eventmask, BRCMF_E_IF); err = brcmf_fil_iovar_data_set(ifp, "event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN); if (err) { brcmf_err("Set event_msgs error (%d)\n", err); goto done; } /* Setup default scan channel time */ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME, BRCMF_DEFAULT_SCAN_CHANNEL_TIME); if (err) { brcmf_err("BRCMF_C_SET_SCAN_CHANNEL_TIME error (%d)\n", err); goto done; } /* Setup default scan unassoc time */ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME, BRCMF_DEFAULT_SCAN_UNASSOC_TIME); if (err) { brcmf_err("BRCMF_C_SET_SCAN_UNASSOC_TIME error (%d)\n", err); goto done; } /* Setup packet filter */ brcmf_c_pktfilter_offload_set(ifp, BRCMF_DEFAULT_PACKET_FILTER); brcmf_c_pktfilter_offload_enable(ifp, BRCMF_DEFAULT_PACKET_FILTER, 0, true); /* do bus specific preinit here */ err = brcmf_bus_preinit(ifp->drvr->bus_if); done: return err; }
static void brcmf_c_pktfilter_offload_set(struct brcmf_if *ifp, char *arg) { struct brcmf_pkt_filter_le *pkt_filter; unsigned long res; int buf_len; s32 err; u32 mask_size; u32 pattern_size; char *argv[8], *buf = NULL; int i = 0; char *arg_save = NULL, *arg_org = NULL; arg_save = kstrdup(arg, GFP_ATOMIC); if (!arg_save) goto fail; arg_org = arg_save; buf = kmalloc(PKTFILTER_BUF_SIZE, GFP_ATOMIC); if (!buf) goto fail; argv[i] = strsep(&arg_save, " "); while (argv[i]) { i++; if (i >= 8) { brcmf_err("Too many parameters\n"); goto fail; } argv[i] = strsep(&arg_save, " "); } if (i != 6) { brcmf_err("Not enough args provided %d\n", i); goto fail; } pkt_filter = (struct brcmf_pkt_filter_le *)buf; /* Parse packet filter id. */ pkt_filter->id = 0; if (!kstrtoul(argv[0], 0, &res)) pkt_filter->id = cpu_to_le32((u32)res); /* Parse filter polarity. */ pkt_filter->negate_match = 0; if (!kstrtoul(argv[1], 0, &res)) pkt_filter->negate_match = cpu_to_le32((u32)res); /* Parse filter type. */ pkt_filter->type = 0; if (!kstrtoul(argv[2], 0, &res)) pkt_filter->type = cpu_to_le32((u32)res); /* Parse pattern filter offset. */ pkt_filter->u.pattern.offset = 0; if (!kstrtoul(argv[3], 0, &res)) pkt_filter->u.pattern.offset = cpu_to_le32((u32)res); /* Parse pattern filter mask. */ mask_size = brcmf_c_pattern_atoh(argv[4], (char *)pkt_filter->u.pattern.mask_and_pattern); /* Parse pattern filter pattern. */ pattern_size = brcmf_c_pattern_atoh(argv[5], (char *)&pkt_filter->u.pattern.mask_and_pattern[mask_size]); if (mask_size != pattern_size) { brcmf_err("Mask and pattern not the same size\n"); goto fail; } pkt_filter->u.pattern.size_bytes = cpu_to_le32(mask_size); buf_len = offsetof(struct brcmf_pkt_filter_le, u.pattern.mask_and_pattern); buf_len += mask_size + pattern_size; err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_add", pkt_filter, buf_len); if (err) brcmf_err("Set pkt_filter_add error (%d)\n", err); fail: kfree(arg_org); kfree(buf); }