aboutsummaryrefslogtreecommitdiffstats
path: root/package/system/mtd
Commit message (Expand)AuthorAgeFilesLines
* mtd: add fixwrgg commandStijn Tintel2016-10-275-3/+239
* mtd: fix endianness detection on muslStijn Tintel2016-10-272-0/+2
* package/system/mtd: fix usage messagePaul Wassi2016-10-261-1/+1
* system/mtd: drop Build/Prepare rule in favor of default oneAlexandru Ardelean2016-10-151-5/+0
* mtd: fix up error messagesJohn Crispin2016-10-152-2/+2
* mtd: fix building with glibcJosua Mayer2016-08-181-0/+1
* mtd: support -c (datasize) option for fixseama commandRafał Miłecki2016-06-203-7/+9
* mtd: add linksys_bootcount for ipq806xAdrian Panella2016-06-131-0/+1
* mtd: fix typo in error message for 'c' optionRafał Miłecki2016-06-111-1/+1
* treewide: replace nbd@openwrt.org with nbd@nbd.nameFelix Fietkau2016-06-076-6/+6
* mtd: imagetag: fix compilation with changed mtd_fixtrx callRafał Miłecki2016-05-111-1/+4
* mtd: add -c option for specifying amount of data to be used for checksumRafał Miłecki2016-05-093-12/+31
* mtd: trx: use separated buffer for TRX headerRafał Miłecki2016-05-091-5/+18
* mtd: seama: exit with error if Seama header wasn't foundrmilecki2016-05-091-1/+1
* mtd: seama: fix image data handlingrmilecki2016-05-091-28/+18
* mtd: seama: move buf allocation to the MD5 functionrmilecki2016-05-091-16/+22
* mtd: seama: update MD5 using header in the first block bufferrmilecki2016-05-091-4/+3
* mtd: seama: add md5 to header structrmilecki2016-05-092-12/+11
* mtd: check for Seama magic early when fixing MD5rmilecki2016-05-091-7/+21
* mtd: add missing breaks in a switchrmilecki2016-05-091-0/+2
* mtd: use tabs for indentsrmilecki2016-05-091-7/+7
* mtd: fix reading of image magic bytes in smaller chunksJohn Crispin2016-03-031-5/+12
* mtd: fix Seama format after replacing EOF with sysupgrade dataRafał Miłecki2016-02-101-2/+13
* mtd: detect image format when writingRafał Miłecki2016-02-063-13/+60
* mtd: allow writing Seama files to "firmware" on Broadcom targetsRafał Miłecki2016-01-281-0/+6
* mtd: enable "fixseama" on bcm53xxRafał Miłecki2016-01-281-1/+1
* kirkwood: support Linksys boot counter on EA[34]500Luka Perkov2015-11-101-0/+1
* mvebu: add support for the Linksys boot counterImre Kaloz2015-08-195-1/+129
* mtd: add missing <endian.h> includeFelix Fietkau2015-06-051-0/+1
* mtd: fix md5sum error checkingJohn Crispin2015-03-051-1/+1
* package: mtd: move bcm963xx_tag definition into source codeJonas Gorski2015-02-271-1/+92
* mtd: make the dump commnd honour the -o optionJohn Crispin2014-12-031-6/+5
* mtd: make the mtd dump call run properly on nand flashJohn Crispin2014-12-021-5/+18
* mtd: add ability to dump a mtd deviceJohn Crispin2014-12-021-5/+57
* mtd: fix 2 compiler warningsJohn Crispin2014-11-261-2/+1
* license info - revert r43155John Crispin2014-11-031-1/+1
* Add more license tags with SPDX identifiersJohn Crispin2014-11-031-1/+1
* Add a few SPDX tagsSteven Barth2014-11-021-1/+1
* bcm53xx: add fixtrxHauke Mehrtens2014-09-211-0/+1
* mtd: disable trx_check() for ar71xx, fixes a regression introduced in r42403Felix Fietkau2014-09-021-0/+2
* mtd: Fix trx check after partition rename ("linux" to "firmware")Felix Fietkau2014-09-021-1/+1
* mtd: fix compile error with muslFelix Fietkau2014-05-211-0/+1
* mtd: improve mtd detectionJohn Crispin2014-03-301-1/+3
* mtd: add support for bad blocks in NAND flashFelix Fietkau2014-03-263-5/+56
* mtd: add a "mtd verify" callJohn Crispin2013-11-193-2/+72
* ar71xx: Unifi AP Pro sysupgrade patchFelix Fietkau2013-11-141-3/+12
* package/mtd: enable seama fixup code for ar71xxGabor Juhos2013-09-191-1/+1
* kernel/base-files: clean up old code related to refreshing mtd partitions, it...Felix Fietkau2013-07-141-38/+0
* packages: clean up the package folderJohn Crispin2013-06-2116-0/+3026
569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875
--- a/net80211/ieee80211_scan_sta.c
+++ b/net80211/ieee80211_scan_sta.c
@@ -317,147 +317,6 @@
 #undef ISPROBE
 }
 
-static struct ieee80211_channel *
-find11gchannel(struct ieee80211com *ic, int i, int freq)
-{
-	struct ieee80211_channel *c;
-	int j;
-
-	/*
-	 * The normal ordering in the channel list is b channel
-	 * immediately followed by g so optimize the search for
-	 * this.  We'll still do a full search just in case.
-	 */
-	for (j = i+1; j < ic->ic_nchans; j++) {
-		c = &ic->ic_channels[j];
-		if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
-			return c;
-	}
-	for (j = 0; j < i; j++) {
-		c = &ic->ic_channels[j];
-		if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
-			return c;
-	}
-	return NULL;
-}
-static const u_int chanflags[] = {
-	IEEE80211_CHAN_B,	/* IEEE80211_MODE_AUTO */
-	IEEE80211_CHAN_A,	/* IEEE80211_MODE_11A */
-	IEEE80211_CHAN_B,	/* IEEE80211_MODE_11B */
-	IEEE80211_CHAN_PUREG,	/* IEEE80211_MODE_11G */
-	IEEE80211_CHAN_FHSS,	/* IEEE80211_MODE_FH */
-	IEEE80211_CHAN_A,	/* IEEE80211_MODE_TURBO_A */ /* for turbo mode look for AP in normal channel */
-	IEEE80211_CHAN_PUREG,	/* IEEE80211_MODE_TURBO_G */
-	IEEE80211_CHAN_ST,	/* IEEE80211_MODE_TURBO_STATIC_A */
-};
-
-static void
-add_channels(struct ieee80211com *ic,
-	struct ieee80211_scan_state *ss,
-	enum ieee80211_phymode mode, const u_int16_t freq[], int nfreq)
-{
-	struct ieee80211_channel *c, *cg;
-	u_int modeflags;
-	int i;
-
-	KASSERT(mode < ARRAY_SIZE(chanflags), ("Unexpected mode %u", mode));
-	modeflags = chanflags[mode];
-	for (i = 0; i < nfreq; i++) {
-		c = ieee80211_find_channel(ic, freq[i], modeflags);
-		if (c == NULL || isclr(ic->ic_chan_active, c->ic_ieee))
-			continue;
-		if (mode == IEEE80211_MODE_AUTO) {
-			/*
-			 * XXX special-case 11b/g channels so we select
-			 *     the g channel if both are present.
-			 */
-			if (IEEE80211_IS_CHAN_B(c) &&
-			    (cg = find11gchannel(ic, i, c->ic_freq)) != NULL)
-				c = cg;
-		}
-		if (ss->ss_last >= IEEE80211_SCAN_MAX)
-			break;
-		ss->ss_chans[ss->ss_last++] = c;
-	}
-}
-
-static const u_int16_t rcl1[] =		/* 8 FCC channel: 52, 56, 60, 64, 36, 40, 44, 48 */
-{ 5260, 5280, 5300, 5320, 5180, 5200, 5220, 5240 };
-static const u_int16_t rcl2[] =		/* 4 MKK channels: 34, 38, 42, 46 */
-{ 5170, 5190, 5210, 5230 };
-static const u_int16_t rcl3[] =		/* 2.4Ghz ch: 1,6,11,7,13 */
-{ 2412, 2437, 2462, 2442, 2472 };
-static const u_int16_t rcl4[] =		/* 5 FCC channel: 149, 153, 161, 165 */
-{ 5745, 5765, 5785, 5805, 5825 };
-static const u_int16_t rcl7[] =		/* 11 ETSI channel: 100,104,108,112,116,120,124,128,132,136,140 */
-{ 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680, 5700 };
-static const u_int16_t rcl8[] =		/* 2.4Ghz ch: 2,3,4,5,8,9,10,12 */
-{ 2417, 2422, 2427, 2432, 2447, 2452, 2457, 2467 };
-static const u_int16_t rcl9[] =		/* 2.4Ghz ch: 14 */
-{ 2484 };
-static const u_int16_t rcl10[] =	/* Added Korean channels 2312-2372 */
-{ 2312, 2317, 2322, 2327, 2332, 2337, 2342, 2347, 2352, 2357, 2362, 2367, 2372 };
-static const u_int16_t rcl11[] =	/* Added Japan channels in 4.9/5.0 spectrum */
-{ 5040, 5060, 5080, 4920, 4940, 4960, 4980 };
-#ifdef ATH_TURBO_SCAN
-static const u_int16_t rcl5[] =		/* 3 static turbo channels */
-{ 5210, 5250, 5290 };
-static const u_int16_t rcl6[] =		/* 2 static turbo channels */
-{ 5760, 5800 };
-static const u_int16_t rcl6x[] =		/* 4 FCC3 turbo channels */
-{ 5540, 5580, 5620, 5660 };
-static const u_int16_t rcl12[] =		/* 2.4Ghz Turbo channel 6 */
-{ 2437 };
-static const u_int16_t rcl13[] =		/* dynamic Turbo channels */
-{ 5200, 5240, 5280, 5765, 5805 };
-#endif /* ATH_TURBO_SCAN */
-
-struct scanlist {
-	u_int16_t	mode;
-	u_int16_t	count;
-	const u_int16_t	*list;
-};
-
-#define	IEEE80211_MODE_TURBO_STATIC_A	IEEE80211_MODE_MAX
-#define	X(a)	.count = sizeof(a)/sizeof(a[0]), .list = a
-
-static const struct scanlist staScanTable[] = {
-	{ IEEE80211_MODE_11B,   		X(rcl3) },
-	{ IEEE80211_MODE_11A,   		X(rcl1) },
-	{ IEEE80211_MODE_11A,   		X(rcl2) },
-	{ IEEE80211_MODE_11B,   		X(rcl8) },
-	{ IEEE80211_MODE_11B,   		X(rcl9) },
-	{ IEEE80211_MODE_11A,   		X(rcl4) },
-#ifdef ATH_TURBO_SCAN
-	{ IEEE80211_MODE_TURBO_STATIC_A,	X(rcl5) },
-	{ IEEE80211_MODE_TURBO_STATIC_A,	X(rcl6) },
-	{ IEEE80211_MODE_TURBO_A,		X(rcl6x) },
-	{ IEEE80211_MODE_TURBO_A,		X(rcl13) },
-#endif /* ATH_TURBO_SCAN */
-	{ IEEE80211_MODE_11A,			X(rcl7) },
-	{ IEEE80211_MODE_11B,			X(rcl10) },
-	{ IEEE80211_MODE_11A,			X(rcl11) },
-#ifdef ATH_TURBO_SCAN
-	{ IEEE80211_MODE_TURBO_G,		X(rcl12) },
-#endif /* ATH_TURBO_SCAN */
-	{ .list = NULL }
-};
-
-#undef X
-
-static int
-checktable(const struct scanlist *scan, const struct ieee80211_channel *c)
-{
-	int i;
-
-	for (; scan->list != NULL; scan++) {
-		for (i = 0; i < scan->count; i++)
-			if (scan->list[i] == c->ic_freq)
-				return 1;
-	}
-	return 0;
-}
-
 /*
  * Start a station-mode scan by populating the channel list.
  */
@@ -466,81 +325,14 @@
 {
 	struct ieee80211com *ic = vap->iv_ic;
 	struct sta_table *st = ss->ss_priv;
-	const struct scanlist *scan;
 	enum ieee80211_phymode mode;
 	struct ieee80211_channel *c;
 	int i;
 
 	ss->ss_last = 0;
-	/*
-	 * Use the table of ordered channels to construct the list
-	 * of channels for scanning.  Any channels in the ordered
-	 * list not in the master list will be discarded.
-	 */
-	for (scan = staScanTable; scan->list != NULL; scan++) {
-		mode = scan->mode;
-		if (vap->iv_des_mode != IEEE80211_MODE_AUTO) {
-			/*
-			 * If a desired mode was specified, scan only 
-			 * channels that satisfy that constraint.
-			 */
-			if (vap->iv_des_mode != mode) {
-				/*
-				 * The scan table marks 2.4Ghz channels as b
-				 * so if the desired mode is 11g, then use
-				 * the 11b channel list but upgrade the mode.
-				 */
-				if (vap->iv_des_mode != IEEE80211_MODE_11G ||
-				    mode != IEEE80211_MODE_11B)
-					continue;
-				mode = IEEE80211_MODE_11G;	/* upgrade */
-			}
-		} else {
-			/*
-			 * This lets ieee80211_scan_add_channels
-			 * upgrade an 11b channel to 11g if available.
-			 */
-			if (mode == IEEE80211_MODE_11B)
-				mode = IEEE80211_MODE_AUTO;
-		}
-		/* XR does not operate on turbo channels */
-		if ((vap->iv_flags & IEEE80211_F_XR) &&
-		    (mode == IEEE80211_MODE_TURBO_A ||
-		     mode == IEEE80211_MODE_TURBO_G))
-			continue;
-		/*
-		 * Add the list of the channels; any that are not
-		 * in the master channel list will be discarded.
-		 */
-		add_channels(ic, ss, mode, scan->list, scan->count);
-	}
-
-	/*
-	 * Add the channels from the ic (from HAL) that are not present
-	 * in the staScanTable.
-	 */
-	for (i = 0; i < ic->ic_nchans; i++) {
-		c = &ic->ic_channels[i];
-		/*
-		 * scan dynamic turbo channels in normal mode.
-		 */
-		if (IEEE80211_IS_CHAN_DTURBO(c))
-			continue;
-		mode = ieee80211_chan2mode(c);
-		if (vap->iv_des_mode != IEEE80211_MODE_AUTO) {
-			/*
-			 * If a desired mode was specified, scan only 
-			 * channels that satisfy that constraint.
-			 */
-			if (vap->iv_des_mode != mode)
-				continue;
-
-		}
-		if (!checktable(staScanTable, c))
-			ss->ss_chans[ss->ss_last++] = c;
-	}
-
+	ieee80211_scan_add_channels(ic, ss, vap->iv_des_mode);
 	ss->ss_next = 0;
+
 	/* XXX tunables */
 	/* 
 	 * The scanner will stay on station for ss_maxdwell ms (using a 
@@ -749,17 +541,7 @@
 	fail = 0;
 	if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, se->se_chan)))
 		fail |= 0x01;
-	/*
-	 * NB: normally the desired mode is used to construct
-	 * the channel list, but it's possible for the scan
-	 * cache to include entries for stations outside this
-	 * list so we check the desired mode here to weed them
-	 * out.
-	 */
-	if (vap->iv_des_mode != IEEE80211_MODE_AUTO &&
-	    (se->se_chan->ic_flags & IEEE80211_CHAN_ALLTURBO) !=
-	    chanflags[vap->iv_des_mode])
-		fail |= 0x01;
+
 	if (vap->iv_opmode == IEEE80211_M_IBSS) {
 		if ((se->se_capinfo & IEEE80211_CAPINFO_IBSS) == 0)
 			fail |= 0x02;
@@ -1168,78 +950,6 @@
 	.scan_default		= ieee80211_sta_join,
 };
 
-/*
- * Start an adhoc-mode scan by populating the channel list.
- */
-static int
-adhoc_start(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
-{
-	struct ieee80211com *ic = vap->iv_ic;
-	struct sta_table *st = ss->ss_priv;
-	const struct scanlist *scan;
-	enum ieee80211_phymode mode;
-
-	ss->ss_last = 0;
-	/*
-	 * Use the table of ordered channels to construct the list
-	 * of channels for scanning.  Any channels in the ordered
-	 * list not in the master list will be discarded.
-	 */
-	for (scan = staScanTable; scan->list != NULL; scan++) {
-		mode = scan->mode;
-		if (vap->iv_des_mode != IEEE80211_MODE_AUTO) {
-			/*
-			 * If a desired mode was specified, scan only 
-			 * channels that satisfy that constraint.
-			 */
-			if (vap->iv_des_mode != mode) {
-				/*
-				 * The scan table marks 2.4Ghz channels as b
-				 * so if the desired mode is 11g, then use
-				 * the 11b channel list but upgrade the mode.
-				 */
-				if (vap->iv_des_mode != IEEE80211_MODE_11G ||
-				    mode != IEEE80211_MODE_11B)
-					continue;
-				mode = IEEE80211_MODE_11G;	/* upgrade */
-			}
-		} else {
-			/*
-			 * This lets ieee80211_scan_add_channels
-			 * upgrade an 11b channel to 11g if available.
-			 */
-			if (mode == IEEE80211_MODE_11B)
-				mode = IEEE80211_MODE_AUTO;
-		}
-		/* XR does not operate on turbo channels */
-		if ((vap->iv_flags & IEEE80211_F_XR) &&
-		    (mode == IEEE80211_MODE_TURBO_A ||
-		     mode == IEEE80211_MODE_TURBO_G))
-			continue;
-		/*
-		 * Add the list of the channels; any that are not
-		 * in the master channel list will be discarded.
-		 */
-		add_channels(ic, ss, mode, scan->list, scan->count);
-	}
-	ss->ss_next = 0;
-	/* XXX tunables */
-	ss->ss_mindwell = msecs_to_jiffies(200);	/* 200ms */
-	ss->ss_maxdwell = msecs_to_jiffies(200);	/* 200ms */
-
-#ifdef IEEE80211_DEBUG
-	if (ieee80211_msg_scan(vap)) {
-		printk("%s: scan set ", vap->iv_dev->name);
-		ieee80211_scan_dump_channels(ss);
-		printk(" dwell min %ld max %ld\n",
-			ss->ss_mindwell, ss->ss_maxdwell);
-	}
-#endif /* IEEE80211_DEBUG */
-
-	st->st_newscan = 1;
-
-	return 0;
-}
 
 /*
  * Select a channel to start an adhoc network on.
@@ -1405,7 +1115,7 @@
 	.scan_name		= "default",
 	.scan_attach		= sta_attach,
 	.scan_detach		= sta_detach,
-	.scan_start		= adhoc_start,
+	.scan_start		= sta_start,
 	.scan_restart		= sta_restart,
 	.scan_cancel		= sta_cancel,
 	.scan_end		= adhoc_pick_bss,
--- a/net80211/ieee80211.c
+++ b/net80211/ieee80211.c
@@ -278,6 +278,11 @@
 			("channel with bogus ieee number %u", c->ic_ieee));
 		setbit(ic->ic_chan_avail, c->ic_ieee);
 
+		if (c->ic_scanflags & IEEE80211_NOSCAN_DEFAULT)
+			c->ic_scanflags |= IEEE80211_NOSCAN_SET;
+		else
+			c->ic_scanflags &= ~IEEE80211_NOSCAN_SET;
+
 		/* Identify mode capabilities. */
 		if (IEEE80211_IS_CHAN_A(c))
 			ic->ic_modecaps |= 1 << IEEE80211_MODE_11A;
--- a/net80211/_ieee80211.h
+++ b/net80211/_ieee80211.h
@@ -132,6 +132,11 @@
 	IEEE80211_SCAN_FIRST	= 2,	/* take first suitable candidate */
 };
 
+enum ieee80211_scanflags {
+	IEEE80211_NOSCAN_DEFAULT = (1 << 0),
+	IEEE80211_NOSCAN_SET     = (1 << 1),
+};
+
 /*
  * Channels are specified by frequency and attributes.
  */
@@ -142,6 +147,7 @@
 	int8_t ic_maxregpower;	/* maximum regulatory tx power in dBm */
 	int8_t ic_maxpower;	/* maximum tx power in dBm */
 	int8_t ic_minpower;	/* minimum tx power in dBm */
+	u_int8_t ic_scanflags;
 };
 
 #define	IEEE80211_CHAN_MAX	255
--- a/net80211/ieee80211_ioctl.h
+++ b/net80211/ieee80211_ioctl.h
@@ -555,6 +555,7 @@
 #define	IEEE80211_IOCTL_WDSADDMAC	(SIOCIWFIRSTPRIV+26)
 #define	IEEE80211_IOCTL_WDSDELMAC	(SIOCIWFIRSTPRIV+28)
 #define	IEEE80211_IOCTL_KICKMAC		(SIOCIWFIRSTPRIV+30)
+#define	IEEE80211_IOCTL_SETSCANLIST	(SIOCIWFIRSTPRIV+31)
 
 enum {
 	IEEE80211_WMMPARAMS_CWMIN       = 1,
--- a/net80211/ieee80211_scan_ap.c
+++ b/net80211/ieee80211_scan_ap.c
@@ -129,131 +129,7 @@
 
 static int ap_flush(struct ieee80211_scan_state *);
 static void action_tasklet(IEEE80211_TQUEUE_ARG);
-static struct ieee80211_channel *find11gchannel(struct ieee80211com *ic, 
-		int i, int freq);
 
-static const u_int chanflags[] = {
-	IEEE80211_CHAN_B,	/* IEEE80211_MODE_AUTO */
-	IEEE80211_CHAN_A,	/* IEEE80211_MODE_11A */
-	IEEE80211_CHAN_B,	/* IEEE80211_MODE_11B */
-	IEEE80211_CHAN_PUREG,	/* IEEE80211_MODE_11G */
-	IEEE80211_CHAN_FHSS,	/* IEEE80211_MODE_FH */
-	IEEE80211_CHAN_A,	/* IEEE80211_MODE_TURBO_A */ /* for turbo mode 
-							      * look for AP in 
-							      * normal channel 
-							      */
-	IEEE80211_CHAN_PUREG,	/* IEEE80211_MODE_TURBO_G */
-	IEEE80211_CHAN_ST,	/* IEEE80211_MODE_TURBO_STATIC_A */
-};
-
-static const u_int16_t rcl1[] =		/* 8 FCC channel: 52, 56, 60, 64, 
-					 *                36, 40, 44, 48 */
-{ 5260, 5280, 5300, 5320, 5180, 5200, 5220, 5240 };
-static const u_int16_t rcl2[] =		/* 4 MKK channels: 34, 38, 42, 46 */
-{ 5170, 5190, 5210, 5230 };
-static const u_int16_t rcl3[] =		/* 2.4Ghz ch: 1,6,11,7,13 */
-{ 2412, 2437, 2462, 2442, 2472 };
-static const u_int16_t rcl4[] =		/* 5 FCC channel: 149, 153, 161, 165 */
-{ 5745, 5765, 5785, 5805, 5825 };
-static const u_int16_t rcl7[] =		/* 11 ETSI channel: 100, 104, 108, 112,
-					 *                  116, 120, 124, 128, 
-					 *                  132, 136, 140 */
-{ 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680, 5700 };
-static const u_int16_t rcl8[] =		/* 2.4Ghz ch: 2,3,4,5,8,9,10,12 */
-{ 2417, 2422, 2427, 2432, 2447, 2452, 2457, 2467 };
-static const u_int16_t rcl9[] =		/* 2.4Ghz ch: 14 */
-{ 2484 };
-static const u_int16_t rcl10[] =	/* Added Korean channels 2312-2372 */
-{ 2312, 2317, 2322, 2327, 2332, 2337, 2342, 2347, 2352, 2357, 2362, 2367, 2372 };
-static const u_int16_t rcl11[] =	/* Added Japan channels in 4.9/5.0 spectrum */
-{ 5040, 5060, 5080, 4920, 4940, 4960, 4980 };
-#ifdef ATH_TURBO_SCAN
-static const u_int16_t rcl5[] =		/* 3 static turbo channels */
-{ 5210, 5250, 5290 };
-static const u_int16_t rcl6[] =		/* 2 static turbo channels */
-{ 5760, 5800 };
-static const u_int16_t rcl6x[] =		/* 4 FCC3 turbo channels */
-{ 5540, 5580, 5620, 5660 };
-static const u_int16_t rcl12[] =		/* 2.4Ghz Turbo channel 6 */
-{ 2437 };
-static const u_int16_t rcl13[] =		/* dynamic Turbo channels */
-{ 5200, 5240, 5280, 5765, 5805 };
-#endif /* ATH_TURBO_SCAN */
-
-struct scanlist {
-	u_int16_t	mode;
-	u_int16_t	count;
-	const u_int16_t	*list;
-};
-
-#define	IEEE80211_MODE_TURBO_STATIC_A	IEEE80211_MODE_MAX
-#define	X(a)	.count = ARRAY_SIZE(a), .list = a
-
-static const struct scanlist staScanTable[] = {
-	{ IEEE80211_MODE_11B,   		X(rcl3)  },
-	{ IEEE80211_MODE_11A,   		X(rcl1)  },
-	{ IEEE80211_MODE_11A,   		X(rcl2)  },
-	{ IEEE80211_MODE_11B,   		X(rcl8)  },
-	{ IEEE80211_MODE_11B,   		X(rcl9)  },
-	{ IEEE80211_MODE_11A,   		X(rcl4)  },
-#ifdef ATH_TURBO_SCAN
-	{ IEEE80211_MODE_TURBO_STATIC_A,	X(rcl5)  },
-	{ IEEE80211_MODE_TURBO_STATIC_A,	X(rcl6)  },
-	{ IEEE80211_MODE_TURBO_A,		X(rcl6x) },
-	{ IEEE80211_MODE_TURBO_A,		X(rcl13) },
-#endif /* ATH_TURBO_SCAN */
-	{ IEEE80211_MODE_11A,			X(rcl7)  },
-	{ IEEE80211_MODE_11B,			X(rcl10) },
-	{ IEEE80211_MODE_11A,			X(rcl11) },
-#ifdef ATH_TURBO_SCAN
-	{ IEEE80211_MODE_TURBO_G,		X(rcl12) },
-#endif /* ATH_TURBO_SCAN */
-	{ .list = NULL }
-};
-
-#undef X
-/* This function must be invoked with locks acquired */
-static void
-add_channels(struct ieee80211com *ic,
-	struct ieee80211_scan_state *ss,
-	enum ieee80211_phymode mode, const u_int16_t freq[], int nfreq)
-{
-	struct ieee80211_channel *c, *cg;
-	u_int modeflags;
-	int i;
-
-	KASSERT(mode < ARRAY_SIZE(chanflags), ("Unexpected mode %u", mode));
-	modeflags = chanflags[mode];
-	for (i = 0; i < nfreq; i++) {
-		c = ieee80211_find_channel(ic, freq[i], modeflags);
-		if ((c == NULL) || isclr(ic->ic_chan_active, c->ic_ieee))
-			continue;
-		if (mode == IEEE80211_MODE_AUTO) {
-			/* XXX special-case 11b/g channels so we select
-			 *     the g channel if both are present. */
-			if (IEEE80211_IS_CHAN_B(c) &&
-			    (cg = find11gchannel(ic, i, c->ic_freq)) != NULL)
-				c = cg;
-		}
-		if (ss->ss_last >= IEEE80211_SCAN_MAX)
-			break;
-		ss->ss_chans[ss->ss_last++] = c;
-	}
-}
-
-/* This function must be invoked with locks acquired */
-static int
-checktable(const struct scanlist *scan, const struct ieee80211_channel *c)
-{
-	int i;
-
-	for (; scan->list != NULL; scan++) {
-		for (i = 0; i < scan->count; i++)
-			if (scan->list[i] == c->ic_freq)
-				return 1;
-	}
-	return 0;
-}
 
 /*
  * Attach prior to any scanning work.
@@ -327,29 +203,6 @@
 		ieee80211_saveie(iep, ie);
 }
 
-/* This function must be invoked with locks acquired */
-static struct ieee80211_channel *
-find11gchannel(struct ieee80211com *ic, int i, int freq)
-{
-	struct ieee80211_channel *c;
-	int j;
-
-	/* The normal ordering in the channel list is b channel
-	 * immediately followed by g so optimize the search for
-	 * this.  We'll still do a full search just in case. */
-	for (j = i + 1; j < ic->ic_nchans; j++) {
-		c = &ic->ic_channels[j];
-		if ((c->ic_freq == freq) && IEEE80211_IS_CHAN_ANYG(c))
-			return c;
-	}
-	for (j = 0; j < i; j++) {
-		c = &ic->ic_channels[j];
-		if ((c->ic_freq == freq) && IEEE80211_IS_CHAN_ANYG(c))
-			return c;
-	}
-	return NULL;
-}
-
 /*
  * Start an ap scan by populating the channel list.
  */
@@ -358,8 +211,6 @@
 {
 	struct ap_state *as 	    = ss->ss_priv;
 	struct ieee80211com *ic     = NULL;
-	const struct scanlist *sl   = NULL;
-	struct ieee80211_channel *c = NULL;
 	int i;
 	unsigned int mode = 0;
 
@@ -368,80 +219,8 @@
 	/* Determine mode flags to match, or leave zero for auto mode */
 	as->as_vap_desired_mode = vap->iv_des_mode;
 	as->as_required_mode    = 0;
-	if (as->as_vap_desired_mode != IEEE80211_MODE_AUTO) {
-		as->as_required_mode = chanflags[as->as_vap_desired_mode];
-		if ((vap->iv_ath_cap & IEEE80211_ATHC_TURBOP) && 
-		    (as->as_required_mode != IEEE80211_CHAN_ST)) {
-			/* Fixup for dynamic turbo flags */
-			if (as->as_vap_desired_mode == IEEE80211_MODE_11G)
-				as->as_required_mode = IEEE80211_CHAN_108G;
-			else
-				as->as_required_mode = IEEE80211_CHAN_108A;
-		}
-	}
-
-	ss->ss_last = 0;
-	/* Use the table of ordered channels to construct the list
-	 * of channels for scanning.  Any channels in the ordered
-	 * list not in the master list will be discarded. */
-	for (sl = staScanTable; sl->list != NULL; sl++) {
-		mode = sl->mode;
-
-		/* The scan table marks 2.4Ghz channels as b
-		 * so if the desired mode is 11g, then use
-		 * the 11b channel list but upgrade the mode. */
-		if (as->as_vap_desired_mode &&
-		    (as->as_vap_desired_mode != mode) && 
-		    (as->as_vap_desired_mode == IEEE80211_MODE_11G) && 
-		    (mode == IEEE80211_MODE_11B))
-			mode = IEEE80211_MODE_11G;
-
-		/* If we are in "AUTO" mode, upgrade the mode to auto. 
-		 * This lets add_channels upgrade an 11b channel to 
-		 * 11g if available. */
-		if (!as->as_vap_desired_mode && (mode == IEEE80211_MODE_11B))
-			mode = IEEE80211_MODE_AUTO;
-
-		/* Add the list of the channels; any that are not
-		 * in the master channel list will be discarded. */
-		add_channels(ic, ss, mode, sl->list, sl->count);
-	}
-
-	/* Add the channels from the ic (from HAL) that are not present
-	 * in the staScanTable, assuming they pass the sanity checks... */
-	for (i = 0; i < ic->ic_nchans; i++) {
-		c = &ic->ic_channels[i];
-
-		/* XR is not supported on turbo channels */
-		if (IEEE80211_IS_CHAN_TURBO(c) && vap->iv_flags & IEEE80211_F_XR)
-			continue;
+	ieee80211_scan_add_channels(ic, ss, vap->iv_des_mode);
 
-		/* Dynamic channels are scanned in base mode */
-		if (!as->as_required_mode && !IEEE80211_IS_CHAN_ST(c))
-			continue;
-
-		/* Use any 11g channel instead of 11b one. */
-		if (vap->iv_des_mode == IEEE80211_MODE_AUTO && 
-		    IEEE80211_IS_CHAN_B(c) &&
-		    find11gchannel(ic, i, c->ic_freq))
-			continue;
-
-		/* Do not add channels already put into the scan list by the
-		 * scan table - these have already been filtered by mode
-		 * and for whether they are in the active channel list. */
-		if (checktable(staScanTable, c))
-			continue;
-
-		/* Make sure the channel is active */
-		if ((c == NULL) || isclr(ic->ic_chan_active, c->ic_ieee))
-			continue;
-
-		/* Don't overrun */
-		if (ss->ss_last >= IEEE80211_SCAN_MAX)
-			break;
-
-		ss->ss_chans[ss->ss_last++] = c;
-	}
 	ss->ss_next = 0;
 	/* XXX tunables */
 	ss->ss_mindwell = msecs_to_jiffies(200);	/* 200ms */
@@ -761,13 +540,6 @@
 		if (IEEE80211_IS_CHAN_RADAR(c->chan))
 			continue;
 
-		/* Do not select 802.11a ST if mode is specified and is not 
-		 * 802.11a ST */
-		if (as->as_required_mode &&
-		    IEEE80211_IS_CHAN_STURBO(c->chan) &&
-		    (as->as_vap_desired_mode != IEEE80211_MODE_TURBO_STATIC_A))
-			continue;
-
 		/* Verify mode matches any fixed mode specified */
 		if((c->chan->ic_flags & as->as_required_mode) != 
 				as->as_required_mode)
--- a/net80211/ieee80211_scan.c
+++ b/net80211/ieee80211_scan.c
@@ -958,6 +958,80 @@
 	}
 }
 
+static const u_int chanflags[] = {
+	0,	/* IEEE80211_MODE_AUTO */
+	IEEE80211_CHAN_A,	/* IEEE80211_MODE_11A */
+	IEEE80211_CHAN_B,	/* IEEE80211_MODE_11B */
+	IEEE80211_CHAN_PUREG,	/* IEEE80211_MODE_11G */
+	IEEE80211_CHAN_FHSS,	/* IEEE80211_MODE_FH */
+	IEEE80211_CHAN_A,	/* IEEE80211_MODE_TURBO_A */ /* for turbo mode look for AP in normal channel */
+	IEEE80211_CHAN_PUREG,	/* IEEE80211_MODE_TURBO_G */
+	IEEE80211_CHAN_ST,	/* IEEE80211_MODE_TURBO_STATIC_A */
+};
+
+static struct ieee80211_channel *
+find11gchannel(struct ieee80211com *ic, int i, int freq)
+{
+	struct ieee80211_channel *c;
+	int j;
+
+	/*
+	 * The normal ordering in the channel list is b channel
+	 * immediately followed by g so optimize the search for
+	 * this.  We'll still do a full search just in case.
+	 */
+	for (j = i+1; j < ic->ic_nchans; j++) {
+		c = &ic->ic_channels[j];
+		if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
+			return c;
+	}
+	for (j = 0; j < i; j++) {
+		c = &ic->ic_channels[j];
+		if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
+			return c;
+	}
+	return NULL;
+}
+
+
+void
+ieee80211_scan_add_channels(struct ieee80211com *ic,
+	struct ieee80211_scan_state *ss,
+	enum ieee80211_phymode mode)
+{
+	struct ieee80211_channel *c, *cg;
+	u_int modeflags;
+	int i;
+
+	KASSERT(mode < ARRAY_SIZE(chanflags), ("Unexpected mode %u", mode));
+	modeflags = chanflags[mode];
+	for (i = 0; i < ic->ic_nchans; i++) {
+		c = &ic->ic_channels[i];
+		if (c == NULL || isclr(ic->ic_chan_active, c->ic_ieee))
+			continue;
+		if (c->ic_scanflags & IEEE80211_NOSCAN_SET)
+			continue;
+		if (modeflags &&
+			((c->ic_flags & IEEE80211_CHAN_ALLTURBO) !=
+			 (modeflags & IEEE80211_CHAN_ALLTURBO)))
+			continue;
+		if (mode == IEEE80211_MODE_AUTO) {
+			/*
+			 * XXX special-case 11b/g channels so we select
+			 *     the g channel if both are present.
+			 */
+			if (IEEE80211_IS_CHAN_B(c) &&
+			    (cg = find11gchannel(ic, i, c->ic_freq)) != NULL)
+				continue;
+		}
+		if (ss->ss_last >= IEEE80211_SCAN_MAX)
+			break;
+		ss->ss_chans[ss->ss_last++] = c;
+	}
+}
+EXPORT_SYMBOL(ieee80211_scan_add_channels);
+
+
 /*
  * Execute radar channel change. This is called when a radar/dfs
  * signal is detected.  AP mode only.  Return 1 on success, 0 on
--- a/net80211/ieee80211_scan.h
+++ b/net80211/ieee80211_scan.h
@@ -219,4 +219,7 @@
 void ieee80211_scanner_unregister(enum ieee80211_opmode,
 	const struct ieee80211_scanner *);
 void ieee80211_scanner_unregister_all(const struct ieee80211_scanner *);
+void ieee80211_scan_add_channels(struct ieee80211com *ic,
+	struct ieee80211_scan_state *ss,
+	enum ieee80211_phymode mode);
 #endif /* _NET80211_IEEE80211_SCAN_H_ */
--- a/net80211/ieee80211_wireless.c
+++ b/net80211/ieee80211_wireless.c
@@ -3873,6 +3873,106 @@
 	return ieee80211_ioctl_setmlme(dev, info, w, (char *)&mlme);
 }
 
+static inline void setflag(struct ieee80211_channel *c, int flag)
+{
+	if (flag)
+		c->ic_scanflags |= IEEE80211_NOSCAN_SET;
+	else
+		c->ic_scanflags &= ~IEEE80211_NOSCAN_SET;
+}
+
+static void setscanflag(struct ieee80211com *ic, int min, int max, int set)
+{
+	int i;
+
+	for (i = 0; i < ic->ic_nchans; i++) {
+		struct ieee80211_channel *c = &ic->ic_channels[i];
+
+		if (min == -1) {
+			if (!(c->ic_scanflags & IEEE80211_NOSCAN_DEFAULT))
+				setflag(c, set);
+		} else if ((c->ic_freq >= min) && (c->ic_freq <= max)) {
+			setflag(c, set);
+		}
+	}
+}
+
+static int
+ieee80211_ioctl_setscanlist(struct net_device *dev,
+	struct iw_request_info *info,
+	struct iw_point *data, char *extra)
+{
+	struct ieee80211vap *vap = dev->priv;
+	struct ieee80211com *ic = vap->iv_ic;
+	char *s, *next;
+	int val = 1;
+
+	if (data->length <= 0)
+		return -EINVAL;
+
+	s = kmalloc(data->length + 1, GFP_KERNEL);
+	if (!s)
+		return -ENOMEM;
+
+	memset(s, 0, data->length + 1);
+	if (copy_from_user(s, data->pointer, data->length))
+		return -EFAULT;
+
+	s[data->length - 1] = '\0';		/* ensure null termination */
+
+	switch(*s) {
+		case '-':
+			val = 1;
+			break;
+		case '+':
+			val = 0;
+			break;
+		default:
+			goto error;
+	}
+	s++;
+	next = s;
+	do {
+		next = strchr(s, ',');
+		if (next) {
+			*next = 0;
+			next++;
+		}
+		if (!strcmp(s, "ALL")) {
+			setscanflag(ic, 0, 10000, val);
+		} else if (!strcmp(s, "REG")) {
+			setscanflag(ic, -1, -1, val);
+		} else {
+			int min, max;
+			char *n, *end = NULL;
+
+			n = strchr(s, '-');
+			if (n) {
+				*n = 0;
+				n++;
+			}
+			min = simple_strtoul(s, &end, 10);
+			if (end && *end)
+				goto error;
+			if (n) {
+				max = simple_strtoul(n, &end, 10);
+				if (end && *end)
+					goto error;
+			} else {
+				max = min;
+			}
+			setscanflag(ic, min, max, val);
+		}
+		s = next;
+	} while (next);
+	return 0;
+
+error:
+	if (s)
+		kfree(s);
+	return -EINVAL;
+}
+
 static int
 ieee80211_ioctl_addmac(struct net_device *dev, struct iw_request_info *info,
 	void *w, char *extra)
@@ -5656,6 +5756,8 @@
 	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "minrate"},
 	{IEEE80211_PARAM_MINRATE,
 	 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_minrate"},
+	{ IEEE80211_IOCTL_SETSCANLIST,
+	 IW_PRIV_TYPE_CHAR | 255, 0, "setscanlist"},
 
 #ifdef ATH_REVERSE_ENGINEERING
 	/*
@@ -5753,6 +5855,7 @@
 	set_priv(IEEE80211_IOCTL_WDSADDMAC, ieee80211_ioctl_wdsmac),
 	set_priv(IEEE80211_IOCTL_WDSDELMAC, ieee80211_ioctl_wdsdelmac),
 	set_priv(IEEE80211_IOCTL_KICKMAC, ieee80211_ioctl_kickmac),
+	set_priv(IEEE80211_IOCTL_SETSCANLIST, ieee80211_ioctl_setscanlist),
 #ifdef ATH_REVERSE_ENGINEERING
 	set_priv(IEEE80211_IOCTL_READREG, ieee80211_ioctl_readreg),
 	set_priv(IEEE80211_IOCTL_WRITEREG, ieee80211_ioctl_writereg),