--- a/Makefile 2013-07-04 13:06:00.717790365 +0200 +++ b/Makefile 2013-07-04 13:15:20.607786877 +0200 @@ -16,7 +16,7 @@ ifneq ($(KERNELRELEASE),) LINUXVER_GOODFOR_CFG80211:=$(strip $(shell \ - if [ "$(VERSION)" -ge "2" -a "$(PATCHLEVEL)" -ge "6" -a "$(SUBLEVEL)" -ge "32" ]; then \ + if [ "$(VERSION)" -ge "3" -o "$(VERSION)" -ge "2" -a "$(PATCHLEVEL)" -ge "6" -a "$(SUBLEVEL)" -ge "32" ]; then \ echo TRUE; \ else \ echo FALSE; \ @@ -24,7 +24,7 @@ )) LINUXVER_WEXT_ONLY:=$(strip $(shell \ - if [ "$(VERSION)" -ge "2" -a "$(PATCHLEVEL)" -ge "6" -a "$(SUBLEVEL)" -ge "17" ]; then \ + if [ "$(VERSION)" -ge "3" -o "$(VERSION)" -ge "2" -a "$(PATCHLEVEL)" -ge "6" -a "$(SUBLEVEL)" -ge "17" ]; then \ echo FALSE; \ else \ echo TRUE; \ --- a/src/include/bcmutils.h 2011-10-22 18:55:54.000000000 +0200 +++ b/src/include/bcmutils.h 2013-07-04 13:15:20.607786877 +0200 @@ -555,7 +555,11 @@ extern void prhex(const char *msg, uchar *buf, uint len); extern bcm_tlv_t *BCMROMFN(bcm_next_tlv)(bcm_tlv_t *elt, int *buflen); +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) extern bcm_tlv_t *BCMROMFN(bcm_parse_tlvs)(void *buf, int buflen, uint key); +#else +extern bcm_tlv_t *BCMROMFN(bcm_parse_tlvs)(const void *buf, int buflen, uint key); +#endif extern bcm_tlv_t *BCMROMFN(bcm_parse_ordered_tlvs)(void *buf, int buflen, uint key); extern const char *bcmerrorstr(int bcmerror); --- a/src/wl/sys/wl_cfg80211.c 2011-10-22 18:55:54.000000000 +0200 +++ b/src/wl/sys/wl_cfg80211.c 2013-07-04 13:15:20.614453543 +0200 @@ -42,8 +42,12 @@ enum nl80211_iftype type, u32 *flags, struct vif_params *params); static s32 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_scan_request *request, struct cfg80211_ssid *this_ssid); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) +static s32 wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request); +#else static s32 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_scan_request *request); +#endif static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed); static s32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ibss_params *params); @@ -56,7 +60,11 @@ struct cfg80211_connect_params *sme); static s32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) +static int wl_cfg80211_set_tx_power(struct wiphy *wiphy, + struct wireless_dev *wdev, + enum nl80211_tx_power_setting type, int dbm); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) static s32 wl_cfg80211_set_tx_power(struct wiphy *wiphy, enum nl80211_tx_power_setting type, s32 dbm); #else @@ -64,7 +72,12 @@ enum tx_power_setting type, s32 dbm); #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) +static int wl_cfg80211_get_tx_power(struct wiphy *wiphy, + struct wireless_dev *wdev, int *dbm); +#else static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm); +#endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38) static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy, @@ -570,10 +583,18 @@ } static s32 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) +wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) +#else wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_scan_request *request) +#endif { s32 err = 0; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) + struct wl_priv *wl = wiphy_to_wl(wiphy); + struct net_device *ndev = wl_to_ndev(wl); +#endif CHECK_SYS_UP(); err = __wl_cfg80211_scan(wiphy, ndev, request, NULL); @@ -742,7 +763,11 @@ else memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN); - wl_ch_to_chanspec(params->channel, &join_params, &join_params_size); +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) + wl_ch_to_chanspec(params->channel, &join_params, &join_params_size); +#else + wl_ch_to_chanspec(params->chandef.chan, &join_params, &join_params_size); +#endif err = wl_dev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size); if (err) { @@ -1099,7 +1124,12 @@ return err; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) +static int +wl_cfg80211_set_tx_power(struct wiphy *wiphy, + struct wireless_dev *wdev, + enum nl80211_tx_power_setting type, int dbm) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) static s32 wl_cfg80211_set_tx_power(struct wiphy *wiphy, enum nl80211_tx_power_setting type, s32 dbm) #else @@ -1155,16 +1185,29 @@ } wl->conf->tx_power = dbm; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) return err; +#else + return (int) err; +#endif } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) +static int wl_cfg80211_get_tx_power(struct wiphy *wiphy, + struct wireless_dev *wdev, int *dbm) +#else static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm) +#endif { struct wl_priv *wl = wiphy_to_wl(wiphy); struct net_device *ndev = wl_to_ndev(wl); s32 txpwrdbm; u8 result; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) s32 err = 0; +#else + int err = 0; +#endif CHECK_SYS_UP(); err = wl_dev_intvar_get(ndev, "qtxpower", &txpwrdbm); @@ -1173,8 +1216,11 @@ return err; } result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE); +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) *dbm = (s32) bcm_qdbm_to_mw(result); - +#else + *dbm = (int) bcm_qdbm_to_mw(result); +#endif return err; } @@ -1466,7 +1512,10 @@ scb_val.val = 0; err = wl_dev_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t)); if (err) { - WL_ERR(("Could not get rssi (%d)\n", err)); + if (err != -EINVAL) { + // Don't fill syslog with EINVAL error + WL_ERR(("Could not get rssi (%d)\n", err)); + } return err; } rssi = dtoh32(scb_val.val); @@ -1811,7 +1860,7 @@ notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt, u.beacon.variable) + wl_get_ielen(wl); freq = ieee80211_channel_to_frequency(notif_bss_info->channel -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39) ,(notif_bss_info->channel <= CH_MAX_2G_CHANNEL) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ #endif ); @@ -2042,9 +2091,14 @@ struct bcm_tlv *tim; u16 beacon_interval; s32 dtim_period; - size_t ie_len; - u8 *ie; s32 err = 0; + size_t ie_len; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) + u8 *ie; +#else + const u8 *ie; + const struct cfg80211_bss_ies *ies; +#endif ssid = &wl->profile->ssid; bss = cfg80211_get_bss(wl_to_wiphy(wl), NULL, (s8 *)&wl->bssid, @@ -2074,10 +2128,25 @@ beacon_interval = cpu_to_le16(bi->beacon_period); } else { WL_DBG(("Found the AP in the list - BSSID %pM\n", bss->bssid)); - ie = bss->information_elements; - ie_len = bss->len_information_elements; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) + ie = bss->information_elements; + ie_len = bss->len_information_elements; +#else + ies = (const struct cfg80211_bss_ies*)rcu_dereference(bss->ies); + if (!ies) { + /* This should never happen */ + err = -EIO; + goto update_bss_info_out; + } + ie = ies->data; + ie_len = (size_t)(ies->len); +#endif beacon_interval = bss->beacon_interval; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0) cfg80211_put_bss(bss); +#else + cfg80211_put_bss(wl_to_wiphy(wl), bss); +#endif } tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM); --- a/src/wl/sys/wl_iw.h 2011-10-22 18:55:54.000000000 +0200 +++ b/src/wl/sys/wl_iw.h 2013-07-04 13:15:20.617786877 +0200 @@ -16,6 +16,7 @@ #define _wl_iw_h_ #include +#include #include #include --- a/src/wl/sys/wl_linux.c 2013-07-04 13:06:00.721123699 +0200 +++ b/src/wl/sys/wl_linux.c 2013-07-04 13:23:17.847783903 +0200 @@ -40,7 +40,9 @@ #include #define WLC_MAXBSSCFG 1 +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) #include +#endif #include #include #include @@ -387,7 +389,11 @@ #endif .ndo_get_stats = wl_get_stats, .ndo_set_mac_address = wl_set_mac_address, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) + .ndo_set_rx_mode = wl_set_multicast_list, +#else .ndo_set_multicast_list = wl_set_multicast_list, +#endif .ndo_do_ioctl = wl_ioctl }; @@ -845,7 +851,11 @@ pci_set_drvdata(pdev, NULL); } +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) static struct pci_driver wl_pci_driver = { +#else +static struct pci_driver wl_pci_driver __refdata = { +#endif name: "wl", probe: wl_pci_probe, suspend: wl_suspend, @@ -1581,11 +1591,7 @@ } WL_LOCK(wl); - if (!capable(CAP_NET_ADMIN)) { - bcmerror = BCME_EPERM; - } else { - bcmerror = wlc_ioctl(wl->wlc, ioc.cmd, buf, ioc.len, wlif->wlcif); - } + bcmerror = wlc_ioctl(wl->wlc, ioc.cmd, buf, ioc.len, wlif->wlcif); WL_UNLOCK(wl); done1: @@ -2962,7 +2968,7 @@ void wl_tkip_printstats(wl_info_t *wl, bool group_key) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) && LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) char debug_buf[512]; int idx; if (wl->tkipmodops) { @@ -3121,6 +3127,7 @@ return 0; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) static int wl_proc_read(char *buffer, char **start, off_t offset, int length, int *eof, void *data) { @@ -3175,18 +3182,89 @@ return length; } +#else + +static int +wl_proc_read(struct seq_file *seq, void *offset) +{ + wl_info_t * wl = (wl_info_t *)seq->private; + int bcmerror, to_user; + + WL_LOCK(wl); + bcmerror = wlc_ioctl(wl->wlc, WLC_GET_MONITOR, &to_user, sizeof(int), NULL); + WL_UNLOCK(wl); + + seq_printf(seq, "%d\n", to_user); + return bcmerror; +} + +static ssize_t wl_proc_write(struct file *file, const char __user *buff, + size_t length, loff_t *ppos) +{ + struct seq_file *seq = file->private_data; + wl_info_t * wl = (wl_info_t *)seq->private; + int bcmerror, from_user = 0; + + if (length != 1) { + WL_ERROR(("%s: Invalid data length\n", __FUNCTION__)); + return -EIO; + } + + if (copy_from_user(&from_user, buff, 1)) { + WL_ERROR(("%s: copy from user failed\n", __FUNCTION__)); + return -EFAULT; + } + + if (from_user >= 0x30) + from_user -= 0x30; + + WL_LOCK(wl); + bcmerror = wlc_ioctl(wl->wlc, WLC_SET_MONITOR, &from_user, sizeof(int), NULL); + WL_UNLOCK(wl); + + if (bcmerror < 0) { + WL_ERROR(("%s: SET_MONITOR failed with %d\n", __FUNCTION__, bcmerror)); + return -EIO; + } + *ppos += length; + return length; +} + +static int wl_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, wl_proc_read, PDE_DATA(inode)); +} + +static const struct file_operations wl_proc_fops = { + .owner = THIS_MODULE, + .open = wl_proc_open, + .read = seq_read, + .write = wl_proc_write, + .llseek = seq_lseek, + .release = single_release, +}; +#endif + static int wl_reg_proc_entry(wl_info_t *wl) { char tmp[32]; sprintf(tmp, "%s%d", HYBRID_PROC, wl->pub->unit); - if ((wl->proc_entry = create_proc_entry(tmp, 0644, NULL)) == NULL) { + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) + wl->proc_entry = create_proc_entry(tmp, 0644, NULL); + if (wl->proc_entry) { + wl->proc_entry->read_proc = wl_proc_read; + wl->proc_entry->write_proc = wl_proc_write; + wl->proc_entry->data = wl; + } +#else + wl->proc_entry = proc_create_data(tmp, 0644, NULL, &wl_proc_fops, wl); +#endif + if (!wl->proc_entry) { WL_ERROR(("%s: create_proc_entry %s failed\n", __FUNCTION__, tmp)); ASSERT(0); return -1; } - wl->proc_entry->read_proc = wl_proc_read; - wl->proc_entry->write_proc = wl_proc_write; - wl->proc_entry->data = wl; return 0; }