소스 검색

[802.11] Enhance support for driver PHY differences

The prior net80211 model of physical-layer behavior for drivers was
overly simplistic and limited the drivers that could be written.  To
be more flexible, split the driver-provided list of supported rates by
band, and add a means for specifying a list of supported channels.
Allow drivers to specify a hardware channel value that will be tied to
uses of the channel.

Expose net80211_duration() to drivers, and make the rate it uses in
its computations configurable, so that it can be used in calculating
durations that must be set in hardware for ACK and CTS packets. Add
net80211_cts_duration() for the common case of calculating the
duration for a CTS packet.

Signed-off-by: Michael Brown <mcb30@etherboot.org>
tags/v0.9.8
Joshua Oreman 14 년 전
부모
커밋
f128a6db21
3개의 변경된 파일147개의 추가작업 그리고 44개의 파일을 삭제
  1. 32
    24
      src/drivers/net/rtl818x/rtl818x.c
  2. 39
    6
      src/include/gpxe/net80211.h
  3. 76
    14
      src/net/80211/net80211.c

+ 32
- 24
src/drivers/net/rtl818x/rtl818x.c 파일 보기

@@ -186,13 +186,16 @@ static int rtl818x_tx(struct net80211_device *dev, struct io_buffer *iob)
186 186
 			plcp_len |= 1 << 15;
187 187
 	}
188 188
 
189
+	entry = &priv->tx_ring[priv->tx_prod];
190
+
189 191
 	if (dev->phy_flags & NET80211_PHY_USE_PROTECTION) {
190 192
 		tx_flags |= RTL818X_TX_DESC_FLAG_CTS;
191 193
 		tx_flags |= priv->hw_rtscts_rate << 19;
194
+		entry->rts_duration = net80211_cts_duration(dev, len);
195
+	} else {
196
+		entry->rts_duration = 0;
192 197
 	}
193 198
 
194
-	entry = &priv->tx_ring[priv->tx_prod];
195
-
196 199
 	if (entry->flags & RTL818X_TX_DESC_FLAG_OWN) {
197 200
 		/* card hasn't processed the old packet yet! */
198 201
 		return -EBUSY;
@@ -201,7 +204,6 @@ static int rtl818x_tx(struct net80211_device *dev, struct io_buffer *iob)
201 204
 	priv->tx_buf[priv->tx_prod] = iob;
202 205
 	priv->tx_prod = (priv->tx_prod + 1) % RTL818X_TX_RING_SIZE;
203 206
 
204
-	entry->rts_duration = 0;
205 207
 	entry->plcp_len = cpu_to_le16(plcp_len);
206 208
 	entry->tx_buf = cpu_to_le32(virt_to_bus(iob->data));
207 209
 	entry->frame_len = cpu_to_le32(len);
@@ -626,20 +628,7 @@ static struct bit_basher_operations rtl818x_basher_ops = {
626 628
 	.write = rtl818x_spi_write_bit,
627 629
 };
628 630
 
629
-/* The net80211 code makes a copy of this, so we're OK modifying the
630
-   static version as we initialize the card, as long as we don't
631
-   depend on possibly-modified values in case there are multiple cards. */
632
-static struct net80211_hw_info rtl818x_hwinfo = {
633
-	/* MAC address filled in at runtime */
634
-	/* modes filled in at runtime */
635
-	.bands = NET80211_BAND_2GHZ,
636
-	.flags = NET80211_HW_RX_HAS_FCS,
637
-	.signal_type = NET80211_SIGNAL_ARBITRARY,
638
-	/* supported rates filled in at runtime */
639
-	.signal_max = 65,
640
-	.channel_change_time = 1000, /* no idea what the actual value is */
641
-};
642
-
631
+#if DBGLVL_MAX
643 632
 static const char *rtl818x_rf_names[] = {
644 633
 	NULL,			/* no 0 */
645 634
 	"Intersil", "RFMD",	/* unsupported 1-2 */
@@ -649,6 +638,7 @@ static const char *rtl818x_rf_names[] = {
649 638
 	"RTL8255",		/* unsupported 10 */
650 639
 };
651 640
 #define RTL818X_NR_RF_NAMES 11
641
+#endif
652 642
 
653 643
 struct net80211_device_operations rtl818x_operations = {
654 644
 	.open = rtl818x_start,
@@ -669,6 +659,13 @@ static int rtl818x_probe(struct pci_device *pdev,
669 659
 	const char *chip_name;
670 660
 	u32 reg;
671 661
 	u16 eeprom_val;
662
+	struct net80211_hw_info *hwinfo;
663
+
664
+	hwinfo = zalloc(sizeof(*hwinfo));
665
+	if (!hwinfo) {
666
+		DBG("rtl818x: hwinfo alloc failed\n");
667
+		return -ENOMEM;
668
+	}
672 669
 
673 670
 	adjust_pci_device(pdev);
674 671
 
@@ -715,15 +712,21 @@ static int rtl818x_probe(struct pci_device *pdev,
715 712
 
716 713
 	priv->r8185 = reg & RTL818X_TX_CONF_R8185_ABC;
717 714
 
718
-	memcpy(rtl818x_hwinfo.supported_rates, rtl818x_rates,
715
+	hwinfo->bands = NET80211_BAND_BIT_2GHZ;
716
+	hwinfo->flags = NET80211_HW_RX_HAS_FCS;
717
+	hwinfo->signal_type = NET80211_SIGNAL_ARBITRARY;
718
+	hwinfo->signal_max = 65;
719
+	hwinfo->channel_change_time = 1000;
720
+
721
+	memcpy(hwinfo->rates[NET80211_BAND_2GHZ], rtl818x_rates,
719 722
 	       sizeof(*rtl818x_rates) * RTL818X_NR_RATES);
720 723
 
721 724
 	if (priv->r8185) {
722
-		rtl818x_hwinfo.modes = NET80211_MODE_B | NET80211_MODE_G;
723
-		rtl818x_hwinfo.nr_supported_rates = RTL818X_NR_RATES;
725
+		hwinfo->modes = NET80211_MODE_B | NET80211_MODE_G;
726
+		hwinfo->nr_rates[NET80211_BAND_2GHZ] = RTL818X_NR_RATES;
724 727
 	} else {
725
-		rtl818x_hwinfo.modes = NET80211_MODE_B;
726
-		rtl818x_hwinfo.nr_supported_rates = RTL818X_NR_B_RATES;
728
+		hwinfo->modes = NET80211_MODE_B;
729
+		hwinfo->nr_rates[NET80211_BAND_2GHZ] = RTL818X_NR_B_RATES;
727 730
 	}
728 731
 
729 732
 	priv->spibit.basher.op = &rtl818x_basher_ops;
@@ -755,6 +758,7 @@ static int rtl818x_probe(struct pci_device *pdev,
755 758
 	}
756 759
 
757 760
 	if (!priv->rf) {
761
+#if DBGLVL_MAX
758 762
 		if (eeprom_val < RTL818X_NR_RF_NAMES &&
759 763
 		    rtl818x_rf_names[eeprom_val] != NULL)
760 764
 			DBG("rtl818x: %s RF frontend not supported!\n",
@@ -762,6 +766,7 @@ static int rtl818x_probe(struct pci_device *pdev,
762 766
 		else
763 767
 			DBG("rtl818x: RF frontend #%d not recognized!\n",
764 768
 			    eeprom_val);
769
+#endif
765 770
 
766 771
 		err = -ENOSYS;
767 772
 		goto err_free_dev;
@@ -777,7 +782,7 @@ static int rtl818x_probe(struct pci_device *pdev,
777 782
 	}
778 783
 
779 784
 	/* read the MAC address */
780
-	nvs_read(&priv->eeprom.nvs, 0x7, rtl818x_hwinfo.hwaddr, 6);
785
+	nvs_read(&priv->eeprom.nvs, 0x7, hwinfo->hwaddr, 6);
781 786
 
782 787
 	/* CCK TX power */
783 788
 	for (i = 0; i < 14; i += 2) {
@@ -799,12 +804,14 @@ static int rtl818x_probe(struct pci_device *pdev,
799 804
 
800 805
 	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
801 806
 
802
-	err = net80211_register(dev, &rtl818x_operations, &rtl818x_hwinfo);
807
+	err = net80211_register(dev, &rtl818x_operations, hwinfo);
803 808
 	if (err) {
804 809
 		DBG("rtl818x: cannot register device\n");
805 810
 		goto err_free_dev;
806 811
 	}
807 812
 
813
+	free(hwinfo);
814
+
808 815
 	DBG("rtl818x: Realtek RTL818%s (RF chip %s) with address %s\n",
809 816
 	    chip_name, priv->rf->name, netdev_hwaddr(dev->netdev));
810 817
 
@@ -813,6 +820,7 @@ static int rtl818x_probe(struct pci_device *pdev,
813 820
  err_free_dev:
814 821
 	pci_set_drvdata(pdev, NULL);
815 822
 	net80211_free(dev);
823
+	free(hwinfo);
816 824
 	return err;
817 825
 }
818 826
 

+ 39
- 6
src/include/gpxe/net80211.h 파일 보기

@@ -42,9 +42,16 @@ FILE_LICENCE ( GPL2_OR_LATER );
42 42
 /** @{ */
43 43
 
44 44
 /** The 2.4 GHz ISM band, unlicensed in most countries */
45
-#define NET80211_BAND_2GHZ	(1 << 0)
45
+#define NET80211_BAND_2GHZ	0
46 46
 /** The band from 4.9 GHz to 5.7 GHz, which tends to be more restricted */
47
-#define NET80211_BAND_5GHZ	(1 << 1)
47
+#define NET80211_BAND_5GHZ	1
48
+/** Number of RF bands */
49
+#define NET80211_NR_BANDS	2
50
+
51
+/** Bitmask for the 2GHz band */
52
+#define NET80211_BAND_BIT_2GHZ	(1 << 0)
53
+/** Bitmask for the 5GHz band */
54
+#define NET80211_BAND_BIT_5GHZ	(1 << 1)
48 55
 
49 56
 /** @} */
50 57
 
@@ -397,6 +404,9 @@ struct net80211_channel
397 404
 	 */
398 405
 	u16 center_freq;
399 406
 
407
+	/** Hardware channel value */
408
+	u16 hw_value;
409
+
400 410
 	/** Maximum allowable transmit power, in dBm
401 411
 	 *
402 412
 	 * This should be interpreted as EIRP, the power supplied to
@@ -478,15 +488,21 @@ struct net80211_hw_info
478 488
 	 */
479 489
 	unsigned signal_max;
480 490
 
481
-	/** List of transmission rates supported by the card
491
+	/** List of RF channels supported by the card */
492
+	struct net80211_channel channels[NET80211_MAX_CHANNELS];
493
+
494
+	/** Number of supported channels */
495
+	int nr_channels;
496
+
497
+	/** List of transmission rates supported by the card, indexed by band
482 498
 	 *
483 499
 	 * Rates should be in 100kbps increments (e.g. 11 Mbps would
484 500
 	 * be represented as the number 110).
485 501
 	 */
486
-	u16 supported_rates[NET80211_MAX_RATES];
502
+	u16 rates[NET80211_NR_BANDS][NET80211_MAX_RATES];
487 503
 
488
-	/** Number of supported rates */
489
-	int nr_supported_rates;
504
+	/** Number of supported rates, indexed by band */
505
+	int nr_rates[NET80211_NR_BANDS];
490 506
 
491 507
 	/** Estimate of the time required to change channels, in microseconds
492 508
 	 *
@@ -969,6 +985,7 @@ struct net80211_device *net80211_alloc ( size_t priv_size );
969 985
 int net80211_register ( struct net80211_device *dev,
970 986
 			struct net80211_device_operations *ops,
971 987
 			struct net80211_hw_info *hw );
988
+u16 net80211_duration ( struct net80211_device *dev, int bytes, u16 rate );
972 989
 void net80211_rx ( struct net80211_device *dev, struct io_buffer *iob,
973 990
 		   int signal, u16 rate );
974 991
 void net80211_rx_err ( struct net80211_device *dev,
@@ -979,5 +996,21 @@ void net80211_unregister ( struct net80211_device *dev );
979 996
 void net80211_free ( struct net80211_device *dev );
980 997
 /** @} */
981 998
 
999
+/**
1000
+ * Calculate duration field for a CTS control frame
1001
+ *
1002
+ * @v dev	802.11 device
1003
+ * @v size	Size of the packet being cleared to send
1004
+ *
1005
+ * A CTS control frame's duration field captures the frame being
1006
+ * protected and its 10-byte ACK.
1007
+ */
1008
+static inline u16 net80211_cts_duration ( struct net80211_device *dev,
1009
+					  int size )
1010
+{
1011
+	return ( net80211_duration ( dev, 10,
1012
+				     dev->rates[dev->rtscts_rate] ) +
1013
+		 net80211_duration ( dev, size, dev->rates[dev->rate] ) );
1014
+}
982 1015
 
983 1016
 #endif

+ 76
- 14
src/net/80211/net80211.c 파일 보기

@@ -154,7 +154,6 @@ static void net80211_netdev_irq ( struct net_device *netdev, int enable );
154 154
  * @defgroup net80211_linklayer 802.11 link-layer protocol functions
155 155
  * @{
156 156
  */
157
-static u16 net80211_duration ( struct net80211_device *dev, int bytes );
158 157
 static int net80211_ll_push ( struct net_device *netdev,
159 158
 			      struct io_buffer *iobuf, const void *ll_dest,
160 159
 			      const void *ll_source, uint16_t net_proto );
@@ -171,6 +170,7 @@ static int net80211_ll_mc_hash ( unsigned int af, const void *net_addr,
171 170
  */
172 171
 static void net80211_add_channels ( struct net80211_device *dev, int start,
173 172
 				    int len, int txpower );
173
+static void net80211_filter_hw_channels ( struct net80211_device *dev );
174 174
 static void net80211_set_rtscts_rate ( struct net80211_device *dev );
175 175
 static int net80211_process_capab ( struct net80211_device *dev,
176 176
 				    u16 capab );
@@ -430,10 +430,9 @@ static inline int net80211_rate_is_erp ( u16 rate )
430 430
  *
431 431
  * No other frame types are currently supported by gPXE.
432 432
  */
433
-static u16 net80211_duration ( struct net80211_device *dev, int bytes )
433
+u16 net80211_duration ( struct net80211_device *dev, int bytes, u16 rate )
434 434
 {
435 435
 	struct net80211_channel *chan = &dev->channels[dev->channel];
436
-	u16 rate = dev->rates[dev->rate];
437 436
 	u32 kbps = rate * 100;
438 437
 
439 438
 	if ( chan->band == NET80211_BAND_5GHZ || net80211_rate_is_erp ( rate ) ) {
@@ -496,7 +495,7 @@ static int net80211_ll_push ( struct net_device *netdev,
496 495
 
497 496
 	/* We don't send fragmented frames, so duration is the time
498 497
 	   for an SIFS + 10-byte ACK. */
499
-	hdr->duration = net80211_duration ( dev, 10 );
498
+	hdr->duration = net80211_duration ( dev, 10, dev->rates[dev->rate] );
500 499
 
501 500
 	memcpy ( hdr->addr1, dev->bssid, ETH_ALEN );
502 501
 	memcpy ( hdr->addr2, ll_source, ETH_ALEN );
@@ -712,7 +711,7 @@ int net80211_tx_mgmt ( struct net80211_device *dev, u16 fc, u8 dest[6],
712 711
 
713 712
 	hdr->fc = IEEE80211_THIS_VERSION | IEEE80211_TYPE_MGMT |
714 713
 	    ( fc & ~IEEE80211_FC_PROTECTED );
715
-	hdr->duration = net80211_duration ( dev, 10 );
714
+	hdr->duration = net80211_duration ( dev, 10, dev->rates[dev->rate] );
716 715
 	hdr->seq = IEEE80211_MAKESEQ ( ++dev->last_tx_seqnr, 0 );
717 716
 
718 717
 	memcpy ( hdr->addr1, dest, ETH_ALEN );	/* DA = RA */
@@ -908,6 +907,7 @@ static void net80211_add_channels ( struct net80211_device *dev, int start,
908 907
 	for ( i = dev->nr_channels; len-- && i < NET80211_MAX_CHANNELS; i++ ) {
909 908
 		dev->channels[i].channel_nr = chan;
910 909
 		dev->channels[i].maxpower = txpower;
910
+		dev->channels[i].hw_value = 0;
911 911
 
912 912
 		if ( chan >= 1 && chan <= 14 ) {
913 913
 			dev->channels[i].band = NET80211_BAND_2GHZ;
@@ -926,6 +926,65 @@ static void net80211_add_channels ( struct net80211_device *dev, int start,
926 926
 	dev->nr_channels = i;
927 927
 }
928 928
 
929
+/**
930
+ * Filter 802.11 device channels for hardware capabilities
931
+ *
932
+ * @v dev	802.11 device
933
+ *
934
+ * Hardware may support fewer channels than regulatory restrictions
935
+ * allow; this function filters out channels in dev->channels that are
936
+ * not supported by the hardware list in dev->hwinfo. It also copies
937
+ * over the net80211_channel::hw_value and limits maximum TX power
938
+ * appropriately.
939
+ *
940
+ * Channels are matched based on center frequency, ignoring band and
941
+ * channel number.
942
+ *
943
+ * If the driver specifies no supported channels, the effect will be
944
+ * as though all were supported.
945
+ */
946
+static void net80211_filter_hw_channels ( struct net80211_device *dev )
947
+{
948
+	int delta = 0, i = 0;
949
+	int old_freq = dev->channels[dev->channel].center_freq;
950
+	struct net80211_channel *chan, *hwchan;
951
+
952
+	if ( ! dev->hw->nr_channels )
953
+		return;
954
+
955
+	dev->channel = 0;
956
+	for ( chan = dev->channels; chan < dev->channels + dev->nr_channels;
957
+	      chan++, i++ ) {
958
+		int ok = 0;
959
+		for ( hwchan = dev->hw->channels;
960
+		      hwchan < dev->hw->channels + dev->hw->nr_channels;
961
+		      hwchan++ ) {
962
+			if ( hwchan->center_freq == chan->center_freq ) {
963
+				ok = 1;
964
+				break;
965
+			}
966
+		}
967
+
968
+		if ( ! ok )
969
+			delta++;
970
+		else {
971
+			chan->hw_value = hwchan->hw_value;
972
+			if ( hwchan->maxpower != 0 &&
973
+			     chan->maxpower > hwchan->maxpower )
974
+				chan->maxpower = hwchan->maxpower;
975
+			if ( old_freq == chan->center_freq )
976
+				dev->channel = i - delta;
977
+			if ( delta )
978
+				chan[-delta] = *chan;
979
+		}
980
+	}
981
+
982
+	dev->nr_channels -= delta;
983
+
984
+	if ( dev->channels[dev->channel].center_freq != old_freq )
985
+		dev->op->config ( dev, NET80211_CFG_CHANNEL );
986
+}
987
+
929 988
 /**
930 989
  * Update 802.11 device state to reflect received capabilities field
931 990
  *
@@ -981,6 +1040,7 @@ static int net80211_process_ie ( struct net80211_device *dev,
981 1040
 	int have_rates = 0, i;
982 1041
 	int ds_channel = 0;
983 1042
 	int changed = 0;
1043
+	int band = dev->channels[dev->channel].band;
984 1044
 
985 1045
 	if ( ( void * ) ie >= ie_end )
986 1046
 		return 0;
@@ -1042,6 +1102,7 @@ static int net80211_process_ie ( struct net80211_device *dev,
1042 1102
 							t->band.max_txpower );
1043 1103
 				}
1044 1104
 			}
1105
+			net80211_filter_hw_channels ( dev );
1045 1106
 			break;
1046 1107
 
1047 1108
 		case IEEE80211_IE_ERP_INFO:
@@ -1067,9 +1128,8 @@ static int net80211_process_ie ( struct net80211_device *dev,
1067 1128
 		dev->rate = 0;
1068 1129
 		for ( i = 0; i < dev->nr_rates; i++ ) {
1069 1130
 			int ok = 0;
1070
-			for ( j = 0; j < dev->hw->nr_supported_rates; j++ ) {
1071
-				if ( dev->hw->supported_rates[j] ==
1072
-				     dev->rates[i] ) {
1131
+			for ( j = 0; j < dev->hw->nr_rates[band]; j++ ) {
1132
+				if ( dev->hw->rates[band][j] == dev->rates[i] ){
1073 1133
 					ok = 1;
1074 1134
 					break;
1075 1135
 				}
@@ -1597,7 +1657,7 @@ static void net80211_step_associate ( struct process *proc )
1597 1657
 			int band = dev->hw->bands;
1598 1658
 
1599 1659
 			if ( active )
1600
-				band &= ~NET80211_BAND_5GHZ;
1660
+				band &= ~NET80211_BAND_BIT_5GHZ;
1601 1661
 
1602 1662
 			rc = net80211_prepare_probe ( dev, band, active );
1603 1663
 			if ( rc )
@@ -1916,7 +1976,7 @@ int net80211_prepare_probe ( struct net80211_device *dev, int band,
1916 1976
 {
1917 1977
 	assert ( dev->netdev->state & NETDEV_OPEN );
1918 1978
 
1919
-	if ( active && band != NET80211_BAND_2GHZ ) {
1979
+	if ( active && ( band & NET80211_BAND_BIT_5GHZ ) ) {
1920 1980
 		DBGC ( dev, "802.11 %p cannot perform active scanning on "
1921 1981
 		       "5GHz band\n", dev );
1922 1982
 		return -EINVAL_ACTIVE_SCAN;
@@ -1935,22 +1995,24 @@ int net80211_prepare_probe ( struct net80211_device *dev, int band,
1935 1995
 	if ( active )
1936 1996
 		net80211_add_channels ( dev, 1, 11, NET80211_REG_TXPOWER );
1937 1997
 	else {
1938
-		if ( band & NET80211_BAND_2GHZ )
1998
+		if ( band & NET80211_BAND_BIT_2GHZ )
1939 1999
 			net80211_add_channels ( dev, 1, 14,
1940 2000
 						NET80211_REG_TXPOWER );
1941
-		if ( band & NET80211_BAND_5GHZ )
2001
+		if ( band & NET80211_BAND_BIT_5GHZ )
1942 2002
 			net80211_add_channels ( dev, 36, 8,
1943 2003
 						NET80211_REG_TXPOWER );
1944 2004
 	}
1945 2005
 
2006
+	net80211_filter_hw_channels ( dev );
2007
+
1946 2008
 	/* Use channel 1 for now */
1947 2009
 	dev->channel = 0;
1948 2010
 	dev->op->config ( dev, NET80211_CFG_CHANNEL );
1949 2011
 
1950
-	/* Always do active probes at 1Mbps */
2012
+	/* Always do active probes at lowest (presumably first) speed */
1951 2013
 	dev->rate = 0;
1952 2014
 	dev->nr_rates = 1;
1953
-	dev->rates[0] = 10;
2015
+	dev->rates[0] = dev->hw->rates[dev->channels[0].band][0];
1954 2016
 	dev->op->config ( dev, NET80211_CFG_RATE );
1955 2017
 
1956 2018
 	return 0;

Loading…
취소
저장