Skip to contentSkip to conversation

Add iwlwifi wireless drivers

PATCH In review James Ketrenos 10 participants 52 messages May 16, 2007 – May 23, 2007

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Add iwlwifi wireless drivers

This patch adds the iwlwifi project directory and sources needed to build the mac80211 based wireless drivers for the Intel PRO/Wireless 3945ABG/BG Network Connection and Intel Wireless WiFi Link AGN adapters.

---

drivers/net/wireless/mac80211/Kconfig              |    1 +
drivers/net/wireless/mac80211/Makefile             |    1 +
drivers/net/wireless/mac80211/iwlwifi/Kconfig      |   96 +
drivers/net/wireless/mac80211/iwlwifi/Makefile     |   27 +
drivers/net/wireless/mac80211/iwlwifi/base.c       | 8146 ++++++++++++++++++++
.../net/wireless/mac80211/iwlwifi/iwl-3945-hw.h    |   88 +
.../net/wireless/mac80211/iwlwifi/iwl-3945-rs.h    |  175 +
drivers/net/wireless/mac80211/iwlwifi/iwl-3945.c   | 2389 ++++++
drivers/net/wireless/mac80211/iwlwifi/iwl-3945.h   |   54 +
.../net/wireless/mac80211/iwlwifi/iwl-4965-hw.h    |  909 +++
drivers/net/wireless/mac80211/iwlwifi/iwl-4965.c   | 3637 +++++++++
drivers/net/wireless/mac80211/iwlwifi/iwl-4965.h   |  177 +
.../net/wireless/mac80211/iwlwifi/iwl-channel.h    |  164 +
.../net/wireless/mac80211/iwlwifi/iwl-commands.h   |  664 ++
drivers/net/wireless/mac80211/iwlwifi/iwl-debug.h  |  141 +
drivers/net/wireless/mac80211/iwlwifi/iwl-eeprom.h |  325 +
.../net/wireless/mac80211/iwlwifi/iwl-helpers.h    |  250 +
drivers/net/wireless/mac80211/iwlwifi/iwl-hw.h     | 1490 ++++
drivers/net/wireless/mac80211/iwlwifi/iwl-io.h     |  454 ++
drivers/net/wireless/mac80211/iwlwifi/iwl-priv.h   |  344 +
.../net/wireless/mac80211/iwlwifi/iwl-spectrum.h   |   91 +
drivers/net/wireless/mac80211/iwlwifi/iwlwifi.h    |  665 ++
22 files changed, 20288 insertions(+), 0 deletions(-)

create mode 100644 drivers/net/wireless/mac80211/iwlwifi/Kconfig create mode 100644 drivers/net/wireless/mac80211/iwlwifi/Makefile create mode 100644 drivers/net/wireless/mac80211/iwlwifi/base.c create mode 100644 drivers/net/wireless/mac80211/iwlwifi/iwl-3945-hw.h create mode 100644 drivers/net/wireless/mac80211/iwlwifi/iwl-3945-rs.h create mode 100644 drivers/net/wireless/mac80211/iwlwifi/iwl-3945.c create mode 100644 drivers/net/wireless/mac80211/iwlwifi/iwl-3945.h create mode 100644 drivers/net/wireless/mac80211/iwlwifi/iwl-4965-hw.h create mode 100644 drivers/net/wireless/mac80211/iwlwifi/iwl-4965.c create mode 100644 drivers/net/wireless/mac80211/iwlwifi/iwl-4965.h create mode 100644 drivers/net/wireless/mac80211/iwlwifi/iwl-channel.h create mode 100644 drivers/net/wireless/mac80211/iwlwifi/iwl-commands.h create mode 100644 drivers/net/wireless/mac80211/iwlwifi/iwl-debug.h create mode 100644 drivers/net/wireless/mac80211/iwlwifi/iwl-eeprom.h create mode 100644 drivers/net/wireless/mac80211/iwlwifi/iwl-helpers.h create mode 100644 drivers/net/wireless/mac80211/iwlwifi/iwl-hw.h create mode 100644 drivers/net/wireless/mac80211/iwlwifi/iwl-io.h create mode 100644 drivers/net/wireless/mac80211/iwlwifi/iwl-priv.h create mode 100644 drivers/net/wireless/mac80211/iwlwifi/iwl-spectrum.h create mode 100644 drivers/net/wireless/mac80211/iwlwifi/iwlwifi.h

NOTE: The patch is 597k and can be found at:

http://intellinuxwireless.org/iwlwifi/0001-Add-iwlwifi-wireless-drivers.patch

Patch is against wireless-dev commit-id be8662897~

#1 lore raw
Quoted 4 lines · On Wed, 16 May 2007 14:45:32 -0700 James Ketrenos wrote:

This patch adds the iwlwifi project directory and sources needed to build the mac80211 based wireless drivers for the Intel PRO/Wireless 3945ABG/BG Network Connection and Intel Wireless WiFi Link AGN adapters.

Quoted 8 lines

---

NOTE: The patch is 597k and can be found at:

http://intellinuxwireless.org/iwlwifi/0001-Add-iwlwifi-wireless-drivers.patch

Patch is against wireless-dev commit-id be8662897~

Some comments/review, mostly not-code-related:

1. Indent Kconfig help text with one tab + 2 spaces (not 8 spaces).

2. Convert function comment blocks into kernel-doc. E.g., this one:

+/**
+ * Deallocate DMA queue.
+ *
+ * Empty queue by removing and destroying all BD's.
+ * Free all buffers.
+ *
+ * @param dev
+ * @param q

(These param names are not correct.)

+ */

would be:

/**
* iwl_tx_queue_free - Deallocate DMA queue
* @priv: describe this param
* @txq: describe this param
*
* Empty queue by removing and destroying all BD's.
* Free all buffers.
*/

Preferably at least all non-static functions will be documented with kernel-doc.

3. Indent labels: with 0 or 1 space, not with 7 spaces. Using 7 spaces hides them, makes them too difficult to see/find.

4. Please don't use /** to begin comment blocks that are not in kernel-doc format.

5. Some inline functions may be too large. E.g., this one:
+static inline int full_rxon_required(struct iwl_priv *priv)

6. What does 0x40 mean here? (don't use magic values)
+ if (res->hdr.flags & 0x40) {

7. This test can be shortened (lots of instances):

+ if (is_broadcast_ether_addr(header->addr1) ||
+ is_multicast_ether_addr(header->addr1))
+ return !compare_ether_addr(header->addr3, priv->bssid);

since (quoting include/linux/etherdevic.h):
* By definition the broadcast address is also a multicast address.

8. Multi-line comment format has a '*' on each line:
+/*
+ handle build REPLY_TX command notification. +*/

so add '*' in lots of places.

9. in is_duplicate_packet(), the
+ case IEEE80211_IF_TYPE_IBSS:{
block is indented one extra tab.

10. typo:
+ * When FW adwances 'R' index, all entries between old and advances

11. Don't indent #endif like this:

+#if IWL == 3945
+ u8 rate = beacon->beacon_notify_hdr.rate;
+#elif IWL == 4965
+ u8 rate = beacon->beacon_notify_hdr.rate.rate;
+ #endif

12. 36 lines end with trailing whitespace. :(

13. Need blank line before and after functions (several of these):

+#define ERROR_START_OFFSET (1 * sizeof(u32))
+#define ERROR_ELEM_SIZE (7 * sizeof(u32))
+static void iwl_dump_nic_error_log(struct iwl_priv *priv) +{

14. sysfs files should contain only 1 value. Compare

+static ssize_t show_tune(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+
+ return sprintf(buf, "%d %d\n",
+ priv->phymode, priv->active_rxon.channel);
+}

and show_channels() [probably others].

15. Limit source lines to <= 80 columns (this patch contains over 200 lines that are > 80 columns).

16. Don't use such obfuscated wrappers like these:

+#define IWL_NOP {}
+#define IWL_NOP_RET(x) { return x; }

just open-code them.

OK, my eyes are glazing over. I'll check the rest of it later.

I hope that some of the wireless developers also review it (since I'm not one).

---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***

#2 lore raw
Quoted 15 lines · Randy Dunlap
Quoted 10 lines · On Wed, 16 May 2007 14:45:32 -0700 James Ketrenos wrote:

This patch adds the iwlwifi project directory and sources needed to build the mac80211 based wireless drivers for the Intel PRO/Wireless 3945ABG/BG Network Connection and Intel Wireless WiFi Link AGN adapters.

---

NOTE: The patch is 597k and can be found at:

http://intellinuxwireless.org/iwlwifi/0001-Add-iwlwifi-wireless-drivers.patch

Patch is against wireless-dev commit-id be8662897~

Some comments/review, mostly not-code-related:

...

Quoted 2 lines

3. Indent labels: with 0 or 1 space, not with 7 spaces. Using 7 spaces hides them, makes them too difficult to see/find.

I can correct this with:

	sed -i -e 's,^\(.*\)default:,foo\1default:,g' \
		-e 's,^[[:space:]]*\([[:alpha:]]\+[[:alnum:]]*:\)$, \1,g' \
		-e 's,^foo\(.*\)default:,\1default:,g' origin/*.[ch]

However scripts/Lindent undoes it. Is there a way to keep Lindent from indenting labels? When I looked at indent's man page it only talked about case labels.

...

Quoted 1 line

12. 36 lines end with trailing whitespace. :(

I must have forgotten to run Lindent on the final code. I'll run it (or just a sed to remove the trailing whitespace) on the code before I submit the version that addresses all the comments.

...

Quoted 3 lines

15. Limit source lines to <= 80 columns (this patch contains over 200 lines that are > 80 columns).

Confirmed 239 instances of > 80 columns by:

	for i in *.[ch]; do 
		echo $i
		sed -e 's,\t,        ,g' $i | 
			grep -n '^.\{80\}.\+$'
	done

I thought Lindent would handle that prettily, but I guess not.

It seems to have enforced 80-column on some lines (sticking a bunch of right justified parameters) and on others it has made things a lot worse.

Lindent seems to have converted space-justified column alignment into tab-justified column alignment, which frequently doesn't fit in 80 columns. For example:

1 2 3 4 5 6 7
01234567890123456789012345678901234567890123456789012345678901234567890123456789 int param_antenna = 0;<-10spc->/* def: 0 = both antennas (use diversity) */

was changed to:

1 2 3 4 5 6 7
01234567890123456789012345678901234567890123456789012345678901234567890123456789 int param_antenna = 0;<- two tabs ->/* def: 0 = both antennas (use diversity) */

Is there another tool people use besides Lindent to enforce style?

Thanks,
James

#3 lore raw

Lindent is only the first step.

You then have to go through the code and undo the damage it does.

For instance,

Review

Quoted 6 lines
(quoted diff) +6 -0
+               rc = wait_event_interruptible_timeout(priv->
+                                                     wait_command_queue,
+                                                     !(priv->
+                                                       status &
+                                                       STATUS_HCMD_ACTIVE),
+                                                     HOST_COMPLETE_TIMEOUT);

you SHOULD (using IETF RFC language) violate the 80-column limit, when the alternative is word-wrapping at silly boundaries like the middle of a de-ref.

Or,

Quoted 5 lines
(quoted diff) +5 -0
+       iwl_write_restricted(priv, FH_RCSR_CONFIG(0),
+                            ALM_FH_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE
+                            |
+                            ALM_FH_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE
+                            |

Review

Quoted 10 lines
(quoted diff) +10 -0
+                            ALM_FH_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN
+                            |
+                            ALM_FH_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128
+                            | (RX_QUEUE_SIZE_LOG <<
+                               ALM_FH_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE)
+                            |
+                            ALM_FH_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST
+                            | (1 << ALM_FH_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH)
+                            | ALM_FH_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH);
+

you SHOULD NOT waste an entire line on a single '|'.

As an aside, remove the redundant "_REG_BIT_" and "_REG_VAL_" stuff. It makes too-long symbols even longer.

As an aside #2,

Review

Quoted 7 lines
(quoted diff) +7 -0
+#if IWL == 4965
+           (rxon1->ofdm_ht_single_stream_basic_rates ==
+            rxon2->ofdm_ht_single_stream_basic_rates) &&
+           (rxon1->ofdm_ht_dual_stream_basic_rates ==
+            rxon2->ofdm_ht_dual_stream_basic_rates) &&
+           (rxon1->rx_chain == rxon2->rx_chain) &&
+#endif

those #if's should go away.

Jeff

#4 lore raw
Quoted 12 lines · Jeff Garzik

As an aside #2,

Review

Quoted 7 lines
(quoted diff) +7 -0
+#if IWL == 4965
+           (rxon1->ofdm_ht_single_stream_basic_rates ==
+            rxon2->ofdm_ht_single_stream_basic_rates) &&
+           (rxon1->ofdm_ht_dual_stream_basic_rates ==
+            rxon2->ofdm_ht_dual_stream_basic_rates) &&
+           (rxon1->rx_chain == rxon2->rx_chain) &&
+#endif

those #if's should go away.

Agreed. We'll continue working to remove those over time.

Originally the intent was to have a single driver that supported the 4965 and 3945 via run-time switching. As development moved forward, switching to a build-time approach made more sense. base.c was then isolated from the hardware specific code and the specific HW functionality was moved into iwl-3945 and iwl-4965. The remaining chunks are small code pieces where that work hasn't yet completed.

James

Quoted 8 lines

Jeff

-
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#5 lore raw
In reply to Randy Dunlap
Quoted 3 lines · Randy Dunlap
Quoted 1 line

http://intellinuxwireless.org/iwlwifi/0001-Add-iwlwifi-wireless-drivers.patch

Some comments/review, mostly not-code-related:

Here is the current status (everything not described below has been fixed in GIT, and is available in the patch at http://intellinuxwireless.org/iwlwifi/0001-v2-Add-iwlwifi-wireless-drivers.patch:

Quoted 1 line

2. Convert function comment blocks into kernel-doc. E.g., this one:

Fixed this part.
...

Quoted 2 lines

Preferably at least all non-static functions will be documented with kernel-doc.

I updated and added some of these. Improving the kernel-doc (and comments in general) over time is on the list of things to do.

Quoted 11 lines

14. sysfs files should contain only 1 value. Compare

(quoted diff) +8 -0
+static ssize_t show_tune(struct device *d,
+			 struct device_attribute *attr, char *buf)
+{
+	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+
+	return sprintf(buf, "%d %d\n",
+		       priv->phymode, priv->active_rxon.channel);
+}
Quoted 1 line

and show_channels() [probably others].

I've modified show/store_tune to take and return a single value encoding the band and channel (since they are locked together and can't be set separately without introducing temporary state logic; tuning to channel 6 could be done in the 2.4GHz band or the 5.2GHz band)

I've added fixing show_channels to the list of things to change; the approach currently used has been *very* useful, without any additional tools or scripts, to be able to just cat a file and see the supported channel map by the driver. Having to do an ls on a directory to see the bands, and within each band to do an ls to see the channels, and within each channel to then have a single flags attribute seems painful from a system overhead as well as usability standpoint (although making a graphical tool on top of it would be easier...)

We also need to look at cleaning up / fixing how the measurement requests can be performed, etc.

The power_level sysfs attribute currently has a single parameter for setting it, and in showing it it provides back the single parameter and a text translation with additional information about the setting. Ex (with a slight change I committed vs. what was in the original patch):

% echo 3 > /sys/bus/pci/drivers/iwl3945/*/power_level % cat /sys/bus/pci/drivers/iwl3945/*/power_level 3 (Timeout 75ms, Period 1000ms)

Quoted 2 lines

15. Limit source lines to <= 80 columns (this patch contains over 200 lines that are > 80 columns).

Fixed in the .c files. Still have 155 instances in the .h files (most due to mid-line tabs)

---

Are you OK with iwlwifi addressing the above post-merge into wireless-dev?

James

#6 lore raw
Quoted 5 lines · James Ketrenos
Quoted 2 lines · Randy Dunlap

15. Limit source lines to <= 80 columns (this patch contains over 200 lines that are > 80 columns).

Fixed in the .c files. Still have 155 instances in the .h files (most due to mid-line tabs)

See my email on this subject. This is NOT a hard and fast rule. If you have to do something stupid to the formatting to get it to fit, then you are moving in the wrong direction.

As an aside, sometimes long lines are an indication that a function needs to be broken up into smaller sub-functions.

Jeff

#7 lore raw
Quoted 8 lines · Jeff Garzik
Quoted 5 lines · James Ketrenos
Quoted 2 lines · Randy Dunlap

15. Limit source lines to <= 80 columns (this patch contains over 200 lines that are > 80 columns).

Fixed in the .c files. Still have 155 instances in the .h files (most due to mid-line tabs)

See my email on this subject. This is NOT a hard and fast rule. If you have to do something stupid to the formatting to get it to fit, then you are moving in the wrong direction.

The bulk of the problems in the .h files are caused by Lindent injecting tabs instead of spaces between the C language item and the comment describing it, blowing the comments over 80.

That said, some of the define names are horrendously long... over time we can get those cleaned up w/ some sed scripts.

Quoted 1 line

As an aside, sometimes long lines are an indication that a function needs to be broken up into smaller sub-functions.

Nod.

James

#8 lore raw
In reply to James Ketrenos
Quoted 7 lines · On Fri, 18 May 2007 12:01:16 -0700 James Ketrenos wrote:
Quoted 3 lines · Randy Dunlap
Quoted 1 line

http://intellinuxwireless.org/iwlwifi/0001-Add-iwlwifi-wireless-drivers.patch

Some comments/review, mostly not-code-related:

Here is the current status (everything not described below has been fixed in GIT, and is available in the patch at http://intellinuxwireless.org/iwlwifi/0001-v2-Add-iwlwifi-wireless-drivers.patch:

[specific updates clipped]

Quoted 1 line

Are you OK with iwlwifi addressing the above post-merge into wireless-dev?

/me points to Mr. Linville. :)

There are still some review items that need quick attention IMO, like the 32/64-bit dma_addr_t issue.

However, I'm in favor of merging into wireless-dev if that's what will speed up general intel wireless merging and maintainence on a more timely basis instead of seeing giant patches every few months.

---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***

#9 lore raw
Quoted 7 lines · Randy Dunlap
Quoted 5 lines · On Fri, 18 May 2007 12:01:16 -0700 James Ketrenos wrote:
Quoted 3 lines · Randy Dunlap
Quoted 1 line

http://intellinuxwireless.org/iwlwifi/0001-Add-iwlwifi-wireless-drivers.patch

Some comments/review, mostly not-code-related:

Quoted 8 lines
Quoted 2 lines

Here is the current status (everything not described below has been fixed in GIT, and is available in the patch at http://intellinuxwireless.org/iwlwifi/0001-v2-Add-iwlwifi-wireless-drivers.patch:

[specific updates clipped]

Quoted 1 line

Are you OK with iwlwifi addressing the above post-merge into wireless-dev?

/me points to Mr. Linville. :)

I'm happy to take it into wireless-dev at this point.

James, will you be posting an updated patch?

John

Signature · 2 lines
John W. Linville
[email protected]
#10 lore raw
Quoted 9 lines · John W. Linville
Quoted 8 lines · Randy Dunlap
Quoted 6 lines · On Fri, 18 May 2007 12:01:16 -0700 James Ketrenos wrote:
Quoted 3 lines · Randy Dunlap
Quoted 1 line

http://intellinuxwireless.org/iwlwifi/0001-Add-iwlwifi-wireless-drivers.patch

Some comments/review, mostly not-code-related:

Here is the current status (everything not described below has been fixed in GIT, and is available in the patch at http://intellinuxwireless.org/iwlwifi/0001-v2-Add-iwlwifi-wireless-drivers.patch:

Quoted 8 lines
Quoted 4 lines

[specific updates clipped]

Quoted 1 line

Are you OK with iwlwifi addressing the above post-merge into wireless-dev?

/me points to Mr. Linville. :)

I'm happy to take it into wireless-dev at this point.

James, will you be posting an updated patch?

Yes. I'm testing the code w/ the bitfield usage removed and finishing up a few of the items from Michael's list. By end of day today I hope to have an updated patch for you.

Thanks,
James

#11 lore raw
In reply to James Ketrenos
Quoted 4 lines · James Ketrenos

This patch adds the iwlwifi project directory and sources needed to build the mac80211 based wireless drivers for the Intel PRO/Wireless 3945ABG/BG Network Connection and Intel Wireless WiFi Link AGN adapters.

Looks much better than when I last checked. A few comments:

- The enter/leave stuff should be removed.
- Many of the in_interrupt() checks are unnecessary. Jiri recently documented which callbacks need to be atomic - the ones that don't need to be atomic definitely won't be called in an interrupt.
- Get rid of the stub functions for callbacks, like set_multicast_list and reset. mac80211 checks if those callbacks are defined before calling them.
- CONFIG_IWLWIFI_QOS doesn't appear to be defined.
- Read and set the MAC address before calling ieee80211_register_hw.
- flush_scheduled_work in d_stop can lead to deadlocks since RTNL is held. It looks like everything is running on a dedicated workqueue so that doesn't really even do anything. priv->workqueue should be flushed instead if needed.
- mac80211 (very recently) sets up a workqueue for the driver to use so you don't need to create your own anymore.
- param_auto_create looks very suspicious. mac80211 already creates an adhoc station if it can't join one.. what's this for?
- The suspend and resume callback setting in struct pci_driver iwl_driver needs to be put on two lines.
- Why are probe requests being dropped in adhoc mode? (assuming hardware handles it.. but the message output for that doesn't sound like it)
- The bitwise ORs shouldn't be getting a line to itself in iwl3945_rx_init and iwl3945_tx_reset.
- Mixed case variable name in iwl_hw_txq_ctx_stop: queueId.
- CONFIG_IWLWIFI_MONITOR and CONFIG_IEEE80211_RADIOTAP doesn't look right.
- RX_FLAG_RADIOTAP should be set in the ieee80211_rx_status flag when a radiotap header is added to a frame. (otherwise, mac80211 will add its own radiotap header)
- If you don't want to add a radiotap header all the time, you should check the IEEE80211_CONF_RADIOTAP flag to see if a radiotap header is desired by the stack. (not whether or not we're configured as IEEE80211_IF_TYPE_MNTR)
- Splitting rx_start->phy_flags over two lines in iwl4965_rx_reply_rx doesn't look good.
- The IEEE80211_FTYPE_MGMT case in the switch statement inside iwl4965_rx_reply_rx doesn't need that extra set of braces. Also, the && and || don't need their own lines.
- param_channel looks suspicious too.
- ieee80211chan2mhz is provided by ieee80211_radiotap.h.

Haven't seen anything severe enough to be a blocker for wireless-dev, however.

-Michael Wu

#12 lore raw
Quoted 8 lines · Michael Wu
Quoted 4 lines · James Ketrenos

This patch adds the iwlwifi project directory and sources needed to build the mac80211 based wireless drivers for the Intel PRO/Wireless 3945ABG/BG Network Connection and Intel Wireless WiFi Link AGN adapters.

Looks much better than when I last checked. A few comments:

- The enter/leave stuff should be removed.

This is the maintainer's personal preference. I put them in all my drivers, and they look perfectly fine here.

Jeff

#13 lore raw
Quoted 3 lines · Jeff Garzik

This is the maintainer's personal preference. I put them in all my drivers, and they look perfectly fine here.

I consider it generally ugly and to be avoided. These seem to be placed only in the mac80211 callbacks so it's more of a tool to figure out when mac80211 uses callbacks.. doesn't really belong here IMHO.

But.. if James likes them, fine. I haven't seen anything better using the gcc mcount stuff Christoph Hellwig was talking about so this is the only option.

-Michael Wu

#14 lore raw
In reply to Michael Wu
Quoted 11 lines · Michael Wu
Quoted 4 lines · James Ketrenos

This patch adds the iwlwifi project directory and sources needed to build the mac80211 based wireless drivers for the Intel PRO/Wireless 3945ABG/BG Network Connection and Intel Wireless WiFi Link AGN adapters.

Looks much better than when I last checked. A few comments:

- The enter/leave stuff should be removed.
- Many of the in_interrupt() checks are unnecessary. Jiri recently documented which callbacks need to be atomic - the ones that don't need to be atomic definitely won't be called in an interrupt.

Actually not some but all. Drivers should never use in_interrupt().

#15 lore raw
In reply to Michael Wu
Quoted 6 lines · Michael Wu
Quoted 4 lines · James Ketrenos

This patch adds the iwlwifi project directory and sources needed to build the mac80211 based wireless drivers for the Intel PRO/Wireless 3945ABG/BG Network Connection and Intel Wireless WiFi Link AGN adapters.

Looks much better than when I last checked. A few comments:

I've attempted to address everything not discussed below in the updated code. That said --

Quoted 1 line

- Read and set the MAC address before calling ieee80211_register_hw.

We're calling SET_IEEE80211_PERM_ADDR before we call ieee80211_register_hw. Is there something else we should be doing?

Quoted 2 lines

- mac80211 (very recently) sets up a workqueue for the driver to use so you don't need to create your own anymore.

In addition to the workqueue created when you call ieee80211_register_hw? We need to have a workqueue for initializing the adapter and uCode before we call ieee80211_register_hw. If ieee80211_alloc_hw created the workqueue, that would work for us (assuming there aren't going to be any side effects from us flushing the workqueue before we call ieee80211_free_hw/ieee80211_unregister_hw)

That said -- if the driver can execute in parallel to the stack for some operations, shouldn't they remain on their own workqueues so the work can be divided up vs. having *everything* routed through one singlethread workqueue?

Quoted 2 lines

- Why are probe requests being dropped in adhoc mode? (assuming hardware handles it.. but the message output for that doesn't sound like it)

It only drops them if the adapter is not in the associated state (the card is configured with the RXON_FLAG_ASSOC_MSK bit clear)

Quoted 2 lines

- If you don't want to add a radiotap header all the time, you should check
the IEEE80211_CONF_RADIOTAP flag to see if a radiotap header is desired by the stack. (not whether or not we're configured as IEEE80211_IF_TYPE_MNTR)

I have this on the todo list.

Thanks for the time you spent looking over the code.

James

#16 lore raw
Quoted 1 line · James Ketrenos

That said -- if the driver can execute in parallel to the stack for some operations, shouldn't they remain on their own workqueues so the work can be divided up vs. having *everything* routed through one singlethread workqueue?

Just because it -can-, does not mean it should.

Unless there is a -proven- need for the operations to be parallel, you should avoid the burden of such complexity.

Jeff

#17 lore raw
Quoted 6 lines · Jeff Garzik
Quoted 1 line · James Ketrenos

That said -- if the driver can execute in parallel to the stack for some operations, shouldn't they remain on their own workqueues so the work can be divided up vs. having *everything* routed through one singlethread workqueue?

Just because it -can-, does not mean it should.

Unless there is a -proven- need for the operations to be parallel, you should avoid the burden of such complexity.

There is no additional complexity by having the driver create its own workqueue; it just calls create_workqueue during probe and destroy_workqueue during remove.

James

#18 lore raw
Quoted 9 lines · James Ketrenos
Quoted 6 lines · Jeff Garzik
Quoted 1 line · James Ketrenos

That said -- if the driver can execute in parallel to the stack for some operations, shouldn't they remain on their own workqueues so the work can be divided up vs. having *everything* routed through one singlethread workqueue?

Just because it -can-, does not mean it should.

Unless there is a -proven- need for the operations to be parallel, you should avoid the burden of such complexity.

There is no additional complexity by having the driver create its own workqueue; it just calls create_workqueue during probe and destroy_workqueue during remove.

That is obviously false. Ignoring the additional code and memory usage, you must additionally evaluate the potential for deadlocks and races.

And then there is the Linus mantra: do what you must, and no more. No need for additional workqueues has been demonstrated. (which I noticed your response completely skipped -- an implicit admission of lack of need)

Jeff

#19 lore raw
Quoted 5 lines · Jeff Garzik
Quoted 4 lines · James Ketrenos
Quoted 3 lines · Jeff Garzik
Quoted 1 line · James Ketrenos

That said -- if the driver can execute in parallel to the stack for some operations, shouldn't they remain on their own workqueues so the work can be divided up vs. having *everything* routed through one singlethread workqueue?

Quoted 7 lines
Quoted 5 lines
Quoted 3 lines

Just because it -can-, does not mean it should.

Unless there is a -proven- need for the operations to be parallel, you should avoid the burden of such complexity.

There is no additional complexity by having the driver create its own workqueue; it just calls create_workqueue during probe and destroy_workqueue during remove.

That is obviously false. Ignoring the additional code and memory usage, you must additionally evaluate the potential for deadlocks and races.

So you're saying that by using mac80211's workqueue a driver no longer has to worry about any deadlocks or race conditions? That is obviously false.

Quoted 1 line

And then there is the Linus mantra: do what you must, and no more. No need for additional workqueues has been demonstrated. (which I noticed your response completely skipped -- an implicit admission of lack of need)

Funny. I noticed you completely deleted the part of my original email that listed one reason why we can't just use mac80211's workqueue currently:

"We need to have a workqueue for initializing the adapter and uCode before we call ieee80211_register_hw. If ieee80211_alloc_hw created the workqueue, that would work for us (assuming there aren't going to be any side effects from us flushing the workqueue before we call ieee80211_free_hw/ieee80211_unregister_hw) "

I didn't say we can't use mac80211's workqueue if it was created/destroyed during alloc/free vs. hw register.

I asked a question about if work can execute in parallel, shouldn't we let it -- and you came back saying I have to prove a need to execute in parallel. I get your point -- Linux isn't about innovation, discussion, or putting code out and having it evolve and stand the test of time. Its about doing exhaustive experimentation in house, putting together a thesis, and then submitting it to the mailing list. I'll do my best to follow that model moving forward.

Thanks,
James

Quoted 3 lines

Jeff

#20 lore raw
Quoted 8 lines · James Ketrenos
Quoted 7 lines · Jeff Garzik
Quoted 6 lines · James Ketrenos
Quoted 5 lines · Jeff Garzik
Quoted 1 line · James Ketrenos

That said -- if the driver can execute in parallel to the stack for some operations, shouldn't they remain on their own workqueues so the work can be divided up vs. having *everything* routed through one singlethread workqueue?

Just because it -can-, does not mean it should.

Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line

Unless there is a -proven- need for the operations to be parallel, you should avoid the burden of such complexity.

There is no additional complexity by having the driver create its own workqueue; it just calls create_workqueue during probe and destroy_workqueue during remove.

That is obviously false. Ignoring the additional code and memory usage, you must additionally evaluate the potential for deadlocks and races.

So you're saying that by using mac80211's workqueue a driver no longer has to worry about any deadlocks or race conditions? That is obviously false.

Don't be dense. If two operations are guaranteed to go down the same pipeline, then there is a clear sequence guarantee that is not present if operations are [needlessly] parallel.

Quoted 1 line

I didn't say we can't use mac80211's workqueue if it was created/destroyed during alloc/free vs. hw register. I asked a question about if work can execute in parallel, shouldn't we let it

Without justification for the additional complexity, the answer is no.

Jeff

#21 lore raw
Quoted 11 lines · Jeff Garzik
Quoted 10 lines · James Ketrenos
Quoted 9 lines · Jeff Garzik
Quoted 8 lines · James Ketrenos
Quoted 6 lines · Jeff Garzik
Quoted 1 line · James Ketrenos

That said -- if the driver can execute in parallel to the stack for some operations, shouldn't they remain on their own workqueues so the work can be divided up vs. having *everything* routed through one singlethread workqueue?

Just because it -can-, does not mean it should.

Unless there is a -proven- need for the operations to be parallel, you should avoid the burden of such complexity.

Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line

There is no additional complexity by having the driver create its own workqueue; it just calls create_workqueue during probe and destroy_workqueue during remove.

That is obviously false. Ignoring the additional code and memory usage, you must additionally evaluate the potential for deadlocks and races.

So you're saying that by using mac80211's workqueue a driver no longer has to worry about any deadlocks or race conditions? That is obviously false.

Don't be dense. If two operations are guaranteed to go down the same pipeline, then there is a clear sequence guarantee that is not present if operations are [needlessly] parallel.

Being on ifsta->work doesn't guarantee any sequence--it just means ieee80211_sta_work can't process management frames at the same time the driver is doing things on that workqueue. ieee80211_sta_work does make some driver callbacks, however those callbacks are also be made from ioctls and cfg80211. Additionally there is other work that ieee80211_sta_work does that does not make any callbacks or state transitions into the driver.

There is no guarantee that driver callbacks from mac80211 will not occur in parallel or in different contexts.

The driver has to protect access to memory shared across those contexts regardless of which workqueue it happens to use.

Quoted 3 lines
Quoted 1 line

I didn't say we can't use mac80211's workqueue if it was created/destroyed during alloc/free vs. hw register. I asked a question about if work can execute in parallel, shouldn't we let it

Without justification for the additional complexity, the answer is no.

Can you show me how the complexity is reduced?

"Ignoring the additional code and memory usage, you must additionally evaluate the potential for deadlocks and races."

Given the API mac80211 exposes, and how the stack operates, I don't see how using ifsta->work as the workqueue allows the driver to no longer evaluate the potential for deadlocks and races.

The second argument you made:

"And then there is the Linus mantra: do what you must, and no more. No need for additional workqueues has been demonstrated."

To make the most use of the processing and power resources available, you must execute in parallel.

I haven't seen a need, or benefit, to serialize unrelated work onto a single workqueue.

James

#22 lore raw
Quoted 1 line · James Ketrenos

Given the API mac80211 exposes, and how the stack operates, I don't see how using ifsta->work as the workqueue allows the driver to no longer evaluate the potential for deadlocks and races.

For the operations in the workqueue, they are obviously serialized.

Quoted 6 lines

The second argument you made:

"And then there is the Linus mantra: do what you must, and no more.
No need for additional workqueues has been demonstrated."

To make the most use of the processing and power resources available, you must execute in parallel.

That's some impressive English parsing, but clearly wrong on the face of it. The Linus mantra cited is about MINIMALIZATION. When you say "to make the most use of..." you are MAXIMIZING something that need not be maximized.

As repeated many times, there is no NEED to execute this slow path stuff in parallel. Though yes, I agree parallel execution maximized power drain.

Jeff

#23 lore raw
Quoted 4 lines · Jeff Garzik
Quoted 1 line · James Ketrenos

Given the API mac80211 exposes, and how the stack operates, I don't see how using ifsta->work as the workqueue allows the driver to no longer evaluate the potential for deadlocks and races.

For the operations in the workqueue, they are obviously serialized.

And the inverse is also true -- operations not on the workqueue are not serialized. The driver must handle both.

Quoted 3 lines
Quoted 1 line

To make the most use of the processing and power resources available, you must execute in parallel.

That's some impressive English parsing, but clearly wrong on the face of it.

If you have N cores on a CPU and more than one is up, but only one gets to do anything because you've serialized everything onto a single workqueue, you are wasting CPU resources. When you waste CPU resources you decrease system efficiency and increase power consumption.

If you have N cores and only one is up, then the scheduler can decide to run serially if it wants, or wake up a core, or do whatever it wants. The driver certainly shouldn't dictate policy and force everything to run serially.

Quoted 1 line

The Linus mantra cited is about MINIMALIZATION. When you say "to make the most use of..." you are MAXIMIZING something that need not be maximized.

I'm really not following what your point is here. In an attempt to twist my words, you're now saying we shouldn't maximize system efficiency.

Quoted 1 line

As repeated many times, there is no NEED to execute this slow path stuff in parallel.

I must have missed the thread where you said that many times, let alone where you proved that there is no benefit or need to running "this slow path stuff" (however you are defining that to be) in parallel.

A driver should not be written in a way which suppresses the kernel's ability to optimize execution by forcing serialization of disjointed operations through a single workqueue.

James

#24 lore raw
In reply to James Ketrenos
Quoted 5 lines · James Ketrenos
Quoted 1 line

- Read and set the MAC address before calling ieee80211_register_hw.

We're calling SET_IEEE80211_PERM_ADDR before we call ieee80211_register_hw.
Is there something else we should be doing?

Well, after jumping through a few hoops to find ieee80211_register_hw, it appears you're right.

However, I don't like it. Bringing the hardware up should be deferred as much as possible to when the user actually brings the interface up. ipw2200 can defer firmware loading to interface open time while still reading the mac address from the eeprom.. why not ipw3945? (the ipw2200 driver doesn't actually do this, but it should. I know it can.)

Also, the code doesn't appear to support changing the mac address at all. The mac address given by conf->mac_addr should be the address that your driver uses.

Quoted 5 lines

That said -- if the driver can execute in parallel to the stack for some operations, shouldn't they remain on their own workqueues so the work can be divided up vs. having *everything* routed through one singlethread workqueue?

Your choice. mac80211 needs a workqueue regardless so it's made available to drivers. Many callbacks are called on this workqueue so drivers don't need to defer work to their own workqueue (and can actually return error values).

Quoted 6 lines
Quoted 2 lines

- Why are probe requests being dropped in adhoc mode? (assuming hardware handles it.. but the message output for that doesn't sound like it)

It only drops them if the adapter is not in the associated state (the card is configured with the RXON_FLAG_ASSOC_MSK bit clear)

I think this decision making belongs in mac80211.

-Michael Wu

#25 lore raw
Quoted 1 line · Michael Wu

However, I don't like it. Bringing the hardware up should be deferred as much as possible to when the user actually brings the interface up. ipw2200 can defer firmware loading to interface open time while still reading the mac address from the eeprom.. why not ipw3945? (the ipw2200 driver doesn't actually do this, but it should. I know it can.)

VERY good point. This is the standard for ethernet drivers:

probe:
basic hardware init, read MAC address from EEPROM
interface up:
full hardware power-up, reset and init write MAC address to hardware
request irq
net stack up
interface down:
net stack down
hardware, power & irq down

And I would hope that wireless drivers would follow a similar pattern.

Jeff

#26 lore raw

Re: [PATCH] Add iwlwifi wireless drivers [part 2/2]

In reply to James Ketrenos
Quoted 11 lines · On Wed, 16 May 2007 14:45:32 -0700 James Ketrenos wrote:

This patch adds the iwlwifi project directory and sources needed to build the mac80211 based wireless drivers for the Intel PRO/Wireless 3945ABG/BG Network Connection and Intel Wireless WiFi Link AGN adapters.

NOTE: The patch is 597k and can be found at:

http://intellinuxwireless.org/iwlwifi/0001-Add-iwlwifi-wireless-drivers.patch

Patch is against wireless-dev commit-id be8662897~

1. Can't this:

+ if (sizeof(priv->eeprom) != 1024) {
+ IWL_ERROR("EEPROM structure size incorrect!\n");
+ return -EINVAL;
+ }

use this instead of 1024 ?
+#define IWL4965_EEPROM_IMAGE_SIZE (0x200 * sizeof(u16))

2. Use of bitfields: bitfields are not (guaranteed to be) portable across a wire interface to some other CPU architecture. Are all bitfield uses always local to the running driver? They should be.

3. What are all of those "volatile" C keywords doing in struct iwl_shared?
See http://lwn.net/Articles/232961/ : "The trouble with volatile"

4. Don't list the parameters like this:

+static const struct iwl_channel_info *iwl4965_get_current_txpower_info(struct

+								       iwl_priv
+								       *priv,
+								       u8 *
+								       band,
+								       u8 *
+								       channel,
+								       u8 *
+								       is_fat,
+								       u8 *
+								       ctrl_chan_high)

+{

Just do more like this:

+static const struct iwl_channel_info *iwl4965_get_current_txpower_info(
+ struct iwl_priv *priv,
+ u8 *band,
+ u8 *channel,
+ u8 *is_fat,
+ u8 *ctrl_chan_high)
+{

5. This function:

+static inline u8 iwl4965_get_dma_hi_address(dma_addr_t addr) +{
+#ifdef _X86_64_TYPES_H
+ return addr >> 32;
+#else
+#ifdef _I386_TYPES_H
+ return 0;
+#else
+#error "unsupported architecture"
+#endif
+#endif
+}

a. For i386, dma_addr_t can still be 64 bits. See asm-i386/types.h:

#ifdef CONFIG_HIGHMEM64G
typedef u64 dma_addr_t;
#else
typedef u32 dma_addr_t;
#endif

b. Should use CONFIG_64BIT instead of checking _X64_64_TYPES_H or _I386_TYPES_H.

c. can just shift addr 32 bits right (in 2 shifts) in all cases:

	return (addr >> 16) >> 16;

6. No need to init rc:

+int iwl_hw_setup_bootstrap(struct iwl_priv *priv) +{
+ int rc = 0;
+
+ /* Load bootstrap instructions into bootstrap state machine, for
+ * restoring after suspend/resume and rfkill power-downs */
+ rc = iwl4965_load_bsm(priv, priv->ucode_boot.v_addr,
+ priv->ucode_boot.len);

7. No need to init hwVersion:

+void iwl_hw_card_show_info(struct iwl_priv *priv) +{
+ u16 hwVersion = 0;
+
+ hwVersion = priv->eeprom.board_revision_4965;

8. Too many BUG_ON()s. Try to recover or return -ERRORs instead.

9. printk() calls should use KERN_* levels.

10. Don't use C99-style // comments.

and as Andrew's -mm announcements and my sig say, use Documentation/SubmitChecklist to see what else needs to be done.

---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***

#27 lore raw

Re: [PATCH] Add iwlwifi wireless drivers [part 2/2]

Quoted 22 lines · On Wed, 16 May 2007 20:35:05 -0700 Randy Dunlap <[email protected]> wrote:
Quoted 11 lines · On Wed, 16 May 2007 14:45:32 -0700 James Ketrenos wrote:

This patch adds the iwlwifi project directory and sources needed to build the mac80211 based wireless drivers for the Intel PRO/Wireless 3945ABG/BG Network Connection and Intel Wireless WiFi Link AGN adapters.

NOTE: The patch is 597k and can be found at:

http://intellinuxwireless.org/iwlwifi/0001-Add-iwlwifi-wireless-drivers.patch

Patch is against wireless-dev commit-id be8662897~

1. Can't this:

(quoted diff) +4 -0
+	if (sizeof(priv->eeprom) != 1024) {
+		IWL_ERROR("EEPROM structure size incorrect!\n");
+		return -EINVAL;
+	}
Quoted 2 lines

use this instead of 1024 ?
+#define IWL4965_EEPROM_IMAGE_SIZE (0x200 * sizeof(u16))

Why not BUILD_BUG_ON()?

Signature · 1 line
Stephen Hemminger <[email protected]>
#28 lore raw

Re: [PATCH] Add iwlwifi wireless drivers [part 2/2]

In reply to Randy Dunlap
Quoted 24 lines · On Wed, 16 May 2007 20:35:05 -0700 Randy Dunlap <[email protected]> wrote:

5. This function:

(quoted diff) +12 -0
+static inline u8 iwl4965_get_dma_hi_address(dma_addr_t addr)
+{
+#ifdef _X86_64_TYPES_H
+	return addr >> 32;
+#else
+#ifdef _I386_TYPES_H
+	return 0;
+#else
+#error "unsupported architecture"
+#endif
+#endif
+}

a. For i386, dma_addr_t can still be 64 bits. See asm-i386/types.h:

#ifdef CONFIG_HIGHMEM64G
typedef u64 dma_addr_t;
#else
typedef u32 dma_addr_t;
#endif

Quoted 7 lines

b. Should use CONFIG_64BIT instead of checking _X64_64_TYPES_H or _I386_TYPES_H.

c. can just shift addr 32 bits right (in 2 shifts) in all cases:

	return (addr >> 16) >> 16;

I did this in sky2 driver:

/* Return high part of DMA address (could be 32 or 64 bit) */ static inline u32 high32(dma_addr_t a)

{
	return sizeof(a) > sizeof(u32) ? (a >> 16) >> 16 : 0;
}
Signature · 1 line
Stephen Hemminger <[email protected]>
#29 lore raw

Re: [PATCH] Add iwlwifi wireless drivers [part 2/2]

Quoted 7 lines · Stephen Hemminger

I did this in sky2 driver:

/* Return high part of DMA address (could be 32 or 64 bit) */ static inline u32 high32(dma_addr_t a)

{
	return sizeof(a) > sizeof(u32) ? (a >> 16) >> 16 : 0;
}

Note that akpm recently added a macro/inline for this to the tree which IIRC went to Linus.

johannes

#30 lore raw

Re: [PATCH] Add iwlwifi wireless drivers [part 2/2]

In reply to Randy Dunlap
Quoted 15 lines · Randy Dunlap
Quoted 9 lines · On Wed, 16 May 2007 14:45:32 -0700 James Ketrenos wrote:

This patch adds the iwlwifi project directory and sources needed to build the mac80211 based wireless drivers for the Intel PRO/Wireless 3945ABG/BG Network Connection and Intel Wireless WiFi Link AGN adapters.

NOTE: The patch is 597k and can be found at:

http://intellinuxwireless.org/iwlwifi/0001-Add-iwlwifi-wireless-drivers.patch

Patch is against wireless-dev commit-id be8662897~

1. Can't this:

(quoted diff) +1 -0
+	if (sizeof(priv->eeprom) != 1024) {

...

Quoted 2 lines

use this instead of 1024 ?
+#define IWL4965_EEPROM_IMAGE_SIZE (0x200 * sizeof(u16))

Changed to BUILD_BUG_ON(sizeof(priv->eeprom) != IWL_EEPROM_IMAGE_SIZE) and defined IWL_EEPROM_IMAGE_SIZE in iwl-eeprom.h

Quoted 4 lines

2. Use of bitfields: bitfields are not (guaranteed to be) portable across a wire interface to some other CPU architecture. Are all bitfield uses always local to the running driver? They should be.

The bitfields are between the hw/ucode (__le) and the driver. Are you saying the bitfields won't be compatible if the driver is compiled and running on big endian? Shouldn't le16_to_cpu() fix that? I just noticed the types in iwl-4965-hw.h weren't endian specific; I've updated that (u16, u32, u64 -> __le16, __le32, __le64)

Quoted 3 lines

3. What are all of those "volatile" C keywords doing in struct iwl_shared?
See http://lwn.net/Articles/232961/ : "The trouble with volatile"

If a reference shared through memory mapped IO with a device that can change the value at any time, doesn't it need to be volatile? 'struct iwl_shared' is allocated with pci_alloc_consistent and the physical address is provided to the hardware for it to update whenever it sees fit.

Quoted 1 line

4. Don't list the parameters like this:

Lindent == bad. I've fixed the instances of this munging I've come across.

Quoted 3 lines

5. This function:

+static inline u8 iwl4965_get_dma_hi_address(dma_addr_t addr)

Fixed to do what Stephen did in sky2.

Quoted 1 line

6. No need to init rc:

Fixed those and several others. I'm sure there are more we'll have to weed out over time (unless you know a sparse option that will say 'initializing variable unnecessarily')

Quoted 1 line

8. Too many BUG_ON()s. Try to recover or return -ERRORs instead.

I pulled out two that shouldn't have been there.

The rest are currently there map to bugs which are easily introduced through code changes but which may not cause an immediately visible bug at run-time. Typically they are placed where an eventual printk() at that location during debugging of a user bug resulted in the critical "ah-ha!" that led to fixing it. I've added comments to the BUG_ON's that didn't have comments already.

I suppose we could try and introduce a new driver recovery mechanism that, upon detection, throws a stack trace and then shuts down the driver (vs. throwing a kernel OOPs) requiring user space to unload and reload the driver. That would still be a sucky situation, but at least it wouldn't cause a system failure requiring a reboot... does such a mechanism already exist?

Quoted 2 lines

9. printk() calls should use KERN_* levels.

Fixed.

Quoted 1 line

10. Don't use C99-style // comments.

Fixed.

Quoted 2 lines

and as Andrew's -mm announcements and my sig say, use Documentation/SubmitChecklist to see what else needs to be done.

Will do.

Above changes in GIT (http://intellinuxwireless.org/repos/iwlwifi.git/)

Thanks,
James

#31 lore raw

Re: [PATCH] Add iwlwifi wireless drivers [part 2/2]

Quoted 7 lines · James Ketrenos
Quoted 4 lines · Randy Dunlap

2. Use of bitfields: bitfields are not (guaranteed to be) portable across a wire interface to some other CPU architecture. Are all bitfield uses always local to the running driver? They should be.

The bitfields are between the hw/ucode (__le) and the driver. Are you saying the bitfields won't be compatible if the driver is compiled and running on big endian? Shouldn't le16_to_cpu() fix that? I just noticed the types in iwl-4965-hw.h weren't endian specific; I've updated that (u16, u32, u64 -> __le16, __le32, __le64)

Use of bitfields, as defined in the C standard, should be avoided at all costs. It requires you to define structures twice -- once for LE, and once for BE. It generates demonstrably sub-optimal code on all known compilers. And in general, people tend to screw them up.

Drivers should be using bitwise integer math rather than bitfields.

As for u8/u16/u32/u64 integer mixes, you must still pay attention to structure layout and compiler padding, in addition to endian issues (which are lessened once bitfields are gone).

Quoted 5 lines
Quoted 3 lines

3. What are all of those "volatile" C keywords doing in struct iwl_shared?
See http://lwn.net/Articles/232961/ : "The trouble with volatile"

If a reference shared through memory mapped IO with a device that can change the value at any time, doesn't it need to be volatile? 'struct iwl_shared' is allocated with pci_alloc_consistent and the physical address is provided to the hardware for it to update whenever it sees fit.

volatile should not be in your driver at all.

See the innumerable threads on LKML, including one current one.

Quoted 7 lines
Quoted 1 line

8. Too many BUG_ON()s. Try to recover or return -ERRORs instead.

I pulled out two that shouldn't have been there.

The rest are currently there map to bugs which are easily introduced through code changes but which may not cause an immediately visible bug at run-time. Typically they are placed where an eventual printk() at that location during debugging of a user bug resulted in the critical "ah-ha!" that led to fixing it. I've added comments to the BUG_ON's that didn't have comments already.

I suppose we could try and introduce a new driver recovery mechanism that, upon detection, throws a stack trace and then shuts down the driver (vs. throwing a kernel OOPs) requiring user space to unload and reload the driver. That would still be a sucky situation, but at least it wouldn't cause a system failure requiring a reboot... does such a mechanism already exist?

In general, you should not be checking for programmer mistakes at every level. Only use BUG_ON() for mistakes that have happened in the past in this driver, AND are likely to occur in the future, AND do not cause problems easily detectable simply by allowing the code to screw up.

Quoted 2 lines
Quoted 1 line

9. printk() calls should use KERN_* levels.

Fixed.

dev_xxx stuff is preferred over printk(), actually :)

Jeff

#32 lore raw

Re: [PATCH] Add iwlwifi wireless drivers [part 2/2]

Quoted 7 lines · Jeff Garzik
Quoted 6 lines · James Ketrenos
Quoted 4 lines · Randy Dunlap

2. Use of bitfields: bitfields are not (guaranteed to be) portable across a wire interface to some other CPU architecture. Are all bitfield uses always local to the running driver? They should be.

Quoted 7 lines
Quoted 1 line

The bitfields are between the hw/ucode (__le) and the driver. Are you saying the bitfields won't be compatible if the driver is compiled and running on big endian? Shouldn't le16_to_cpu() fix that? I just noticed the types in iwl-4965-hw.h weren't endian specific; I've updated that (u16, u32, u64 -> __le16, __le32, __le64)

Use of bitfields, as defined in the C standard, should be avoided at all costs. It requires you to define structures twice -- once for LE, and once for BE. It generates demonstrably sub-optimal code on all known compilers. And in general, people tend to screw them up.

Drivers should be using bitwise integer math rather than bitfields.

As for u8/u16/u32/u64 integer mixes, you must still pay attention to structure layout and compiler padding, in addition to endian issues (which are lessened once bitfields are gone).

Alright; I'll add replacing the bitfields with bitwise access to the todo list.

Are you OK with us marking the driver as not working on big endian for now and getting this one fixed over time?

Quoted 9 lines
Quoted 5 lines
Quoted 3 lines

3. What are all of those "volatile" C keywords doing in struct iwl_shared?
See http://lwn.net/Articles/232961/ : "The trouble with volatile"

If a reference shared through memory mapped IO with a device that can change the value at any time, doesn't it need to be volatile? 'struct iwl_shared' is allocated with pci_alloc_consistent and the physical address is provided to the hardware for it to update whenever it sees fit.

volatile should not be in your driver at all.

See the innumerable threads on LKML, including one current one.

I tried reading through the thread. From what I gathered, it sounds like if I want to read a value from a memory location where the adapter could be writing to it I would just call rmb() before I access the memory? And when writing to a value, call wmb() immediately after I write to it? And expunge 'volatile' from my vocabulary.

Quoted 10 lines
Quoted 8 lines
Quoted 2 lines

8. Too many BUG_ON()s. Try to recover or return -ERRORs instead.

I pulled out two that shouldn't have been there.

The rest are currently there map to bugs which are easily introduced through code changes but which may not cause an immediately visible bug at run-time. Typically they are placed where an eventual printk() at that location during debugging of a user bug resulted in the critical "ah-ha!" that led to fixing it. I've added comments to the BUG_ON's that didn't have comments already.

I suppose we could try and introduce a new driver recovery mechanism that, upon detection, throws a stack trace and then shuts down the driver (vs. throwing a kernel OOPs) requiring user space to unload and reload the driver. That would still be a sucky situation, but at least it wouldn't cause a system failure requiring a reboot... does such a mechanism already exist?

In general, you should not be checking for programmer mistakes at every level. Only use BUG_ON() for mistakes that have happened in the past in this driver, AND are likely to occur in the future, AND do not cause problems easily detectable simply by allowing the code to screw up.

That has been the general goal in where the BUG_ONs are.

There were a couple that weren't doing that (which were yanked).

I've updated iwl_send_cmd which was using BUG_ON but could use printk and return a failure code.

James

#33 lore raw

Re: [PATCH] Add iwlwifi wireless drivers [part 2/2]

Quoted 1 line · James Ketrenos

Are you OK with us marking the driver as not working on big endian for now and getting this one fixed over time?

No.

Getting this right is a key merge requirement for all drivers.

Getting this right has also, in the past, been a proven way to find hidden bugs in your driver that wanted fixing anyway.

Quoted 1 line

I tried reading through the thread. From what I gathered, it sounds like if I want to read a value from a memory location where the adapter could be writing to it I would just call rmb() before I access the memory? And when writing to a value, call wmb() immediately after I write to it? And expunge 'volatile' from my vocabulary.

MMIO - no. Accessors handle that for you in most cases. For rare cases you might need mmiowb() or whatnot, but that is unlikely.

DMA, generally that's what people do, but it's not perfect.

Jeff

#34 lore raw

Re: [PATCH] Add iwlwifi wireless drivers [part 2/2]

In reply to James Ketrenos
Quoted 5 lines · James Ketrenos

Alright; I'll add replacing the bitfields with bitwise access to the todo list.

Are you OK with us marking the driver as not working on big endian for now and getting this one fixed over time?

Given that Intel still hasn't fixed the older ipw2X00 drivers for big endian despite clong-time onstant prodding I'm dead set against this. It just won't happen if you don't do it now.

#35 lore raw

Re: [PATCH] Add iwlwifi wireless drivers [part 2/2]

Quoted 7 lines · Christoph Hellwig
Quoted 3 lines · James Ketrenos

Alright; I'll add replacing the bitfields with bitwise access to the todo list.

Are you OK with us marking the driver as not working on big endian for now and getting this one fixed over time?

Given that Intel still hasn't fixed the older ipw2X00 drivers for big endian despite clong-time onstant prodding I'm dead set against this.

Really? Long time constant prodding?

I'll admit I'm not CC:'d on every email regarding the ipw2100 and ipw2200, so if I missed a long-time and constant thread, please forward it my way.

Searching Google for 'ipw endian' (and several other searches) found a reference to a fix for an endian issue when it was raised for the ipw2200. For the ipw2100 I see a post back in 2004 by one person asking if anyone had tried the ipw2100 on a big endian system.

Quoted 1 line

It just won't happen if you don't do it now.

Well, if you have evidence to this then great. If not, please don't spread FUD.

Historical footnote #1 -- the ipw2200 driver was added to the kernel w/out big endian support:

	commit: 43f66a6ce8da299344cf1bc2ac2311889cc88555

Historical footnote #2 -- we fixed big endian problems with the driver in August 2005
commit: a613bffd3aac89bb0a8c9b7afa72af9b0ae30f0a (and a few other commits as users reported issues)

For the ipw2100, aside from one post in 2004 referencing it, I don't see anything.

James

#36 lore raw

Re: [PATCH] Add iwlwifi wireless drivers [part 2/2]

Quoted 11 lines · James Ketrenos
Quoted 9 lines · Christoph Hellwig
Quoted 5 lines · James Ketrenos

Alright; I'll add replacing the bitfields with bitwise access to the todo list.

Are you OK with us marking the driver as not working on big endian for now and getting this one fixed over time?

Given that Intel still hasn't fixed the older ipw2X00 drivers for big endian despite clong-time onstant prodding I'm dead set against this.

Quoted 6 lines

Really? Long time constant prodding?

I'll admit I'm not CC:'d on every email regarding the ipw2100 and ipw2200, so if I missed a long-time and constant thread, please forward it my way. Searching Google for 'ipw endian' (and several other searches) found a reference to a fix for an endian issue when it was raised for the ipw2200.

Just from my outbox I have a thread in August 2006 where I tell Zhu Yi to fix the endianess problems instead of masking them, and even offer testing on big endian when Intel sends me hardware. Despite that this got completely ignored and resubmitted in december, where I replied again. And probably quite a few more I haven't caught.

#37 lore raw

Re: [PATCH] Add iwlwifi wireless drivers [part 2/2]

Quoted 10 lines · Christoph Hellwig
Quoted 9 lines · James Ketrenos
Quoted 6 lines · Christoph Hellwig
Quoted 3 lines · James Ketrenos

Alright; I'll add replacing the bitfields with bitwise access to the todo list.

Are you OK with us marking the driver as not working on big endian for now and getting this one fixed over time?

Given that Intel still hasn't fixed the older ipw2X00 drivers for big endian despite clong-time onstant prodding I'm dead set against this.

Really? Long time constant prodding?

Quoted 7 lines
Quoted 1 line

I'll admit I'm not CC:'d on every email regarding the ipw2100 and ipw2200, so if I missed a long-time and constant thread, please forward it my way. Searching Google for 'ipw endian' (and several other searches) found a reference to a fix for an endian issue when it was raised for the ipw2200.

Just from my outbox I have a thread in August 2006 where I tell Zhu Yi to fix the endianess problems instead of masking them, and even offer testing on big endian when Intel sends me hardware. Despite that this got completely ignored and resubmitted in december, where I replied again. And probably quite a few more I haven't caught.

Ok, first, you said 'ipw2x00' Which is false. The ipw2200 does work on big endian. We have worked to enable it. You also said merging w/out fixing big endian leads to big endian never being fixed. Again, false (see prior email with specific references demonstrating that). So, Please don't generalize and make false accusations.

Second, regarding your prior thread, you more or less demanded that the driver maintainer send you hardware. That isn't fair or reasonable.

If you have a bug, and users that can help resolve the bug, we'd love to work with them fix the issues. But demanding that Yi send you hardware and then making stuff up about him and the ipw2100, ipw2200, and iwlwifi projects when he doesn't is really not appropriate.

James

#38 lore raw

Re: [PATCH] Add iwlwifi wireless drivers [part 2/2]

Quoted 2 lines · James Ketrenos

Second, regarding your prior thread, you more or less demanded that the driver maintainer send you hardware. That isn't fair or reasonable.

No, that's entirely false. I'd more than happy to have it fixed without me beeing involved. I offered to test it in case it's really that difficult to get a foreign endian machine inside intel.

#39 lore raw

RE: [PATCH] Add iwlwifi wireless drivers [part 2/2]

Hi,

Support for big-endian platforms (as well as AP mode) for iwlwifi is currently *planned* to be added by Intel in the near future for several purposes.

However, the vast majority of iwlwifi users at this point run it over little-endian platforms. _Delaying_ the inclusion of iwlwifi driver will not assist iwlwifi-over-big-endian-platform users in any way, but the impact on the rest of the users is clear.

We got many comments from the community and we thank you for that. We do our best to fix all of them in timely manner for the benefit of everyone. If something falls between the cracks it is only because of limited resources, priority issues, human mistakes or alike and not because of flippancy or anything like that. I hope you understand that.

Guy.

PS
I marked *planned* with asterisks so no one mixes it by mistake with *committed* and attack me if Intel stops making HW and SW, etc :)

Quoted 2 lines · Christoph Hellwig
Quoted 1 line · James Ketrenos

Second, regarding your prior thread, you more or less demanded that

the

Quoted 3 lines
Quoted 1 line

driver maintainer send you hardware. That isn't fair or reasonable.

No, that's entirely false. I'd more than happy to have it fixed

without

Quoted 2 lines

me beeing involved. I offered to test it in case it's really that difficult to get a foreign endian machine inside intel.

#40 lore raw

Re: [PATCH] Add iwlwifi wireless drivers [part 2/2]

Quoted 8 lines · Guy

Support for big-endian platforms (as well as AP mode) for iwlwifi is currently *planned* to be added by Intel in the near future for several purposes.

However, the vast majority of iwlwifi users at this point run it over little-endian platforms. _Delaying_ the inclusion of iwlwifi driver will not assist iwlwifi-over-big-endian-platform users in any way, but the impact on the rest of the users is clear.

All Linux drivers that use the proper APIs are transparently portable to either little endian or big endian, 32-bit or 64-bit machines.

If your driver is not portable, then it is not using the proper APIs, and needs updating.

Next time, write the driver using the correct APIs and you will not run into these sort of problems...

Jeff

#41 lore raw

Re: [PATCH] Add iwlwifi wireless drivers [part 2/2]

Quoted 11 lines · Jeff Garzik
Quoted 8 lines · Guy

Support for big-endian platforms (as well as AP mode) for iwlwifi is currently *planned* to be added by Intel in the near future for several purposes.

However, the vast majority of iwlwifi users at this point run it over little-endian platforms. _Delaying_ the inclusion of iwlwifi driver will not assist iwlwifi-over-big-endian-platform users in any way, but the impact on the rest of the users is clear.

Quoted 5 lines

All Linux drivers that use the proper APIs are transparently portable to either little endian or big endian, 32-bit or 64-bit machines.

If your driver is not portable, then it is not using the proper APIs, and needs updating.

Next time, write the driver using the correct APIs and you will not run into these sort of problems...

Ack. Basically same idea for coding style issues also. Do it right the first time, don't have to redo it.

Signature · 2 lines
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
#42 lore raw

RE: [PATCH] Add iwlwifi wireless drivers [part 2/2]

From: Randy Dunlap [mailto:[email protected]]

Quoted 4 lines
Quoted 3 lines · Jeff Garzik
Quoted 2 lines · Guy

Support for big-endian platforms (as well as AP mode) for iwlwifi is currently *planned* to be added by Intel in the near future for

several

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

purposes.

However, the vast majority of iwlwifi users at this point run it

over

Quoted 1 line
Quoted 1 line
Quoted 1 line

little-endian platforms. _Delaying_ the inclusion of iwlwifi driver

will

Quoted 1 line
Quoted 1 line
Quoted 1 line

not assist iwlwifi-over-big-endian-platform users in any way, but

the

Quoted 4 lines
Quoted 4 lines
Quoted 1 line

impact on the rest of the users is clear.

All Linux drivers that use the proper APIs are transparently portable

to

Quoted 6 lines
Quoted 6 lines

either little endian or big endian, 32-bit or 64-bit machines.

If your driver is not portable, then it is not using the proper APIs, and needs updating.

Next time, write the driver using the correct APIs and you will not

run

Quoted 5 lines
Quoted 1 line

into these sort of problems...

Ack. Basically same idea for coding style issues also. Do it right the first time, don't have to redo it.

You two are right. Any other reply from my side will be dumb... We will learn the lesson...

But at this point (we can't change the past nor the present), we would like to focus on more urgent issues with iwlwifi in the immediate term and delay a bit the big-endian support. Is this acceptable?

Quoted 3 lines

--
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your

code

Quoted 1 line

***

#43 lore raw

Re: [PATCH] Add iwlwifi wireless drivers [part 2/2]

Quoted 3 lines · Guy

But at this point (we can't change the past nor the present), we would like to focus on more urgent issues with iwlwifi in the immediate term and delay a bit the big-endian support. Is this acceptable?

Your internal schedule is your internal schedule.

But as I previously stated, getting rid of the bitfields and using the proper (portable) Linux driver API is a hard merge requirement.

Jeff

#44 lore raw

Re: [PATCH] Add iwlwifi wireless drivers [part 2/2]

In reply to Cohen, Guy
Quoted 2 lines · Guy

However, the vast majority of iwlwifi users at this point run it over little-endian platforms.

That would be 100% as it doesn't yet support big-endian platforms?

ciao
Joerg

Signature · 3 lines
Joerg Mayer                                           <[email protected]>
We are stuck with technology when what we really want is just stuff that
works. Some say that should read Microsoft instead of technology.
#45 lore raw

RE: [PATCH] Add iwlwifi wireless drivers [part 2/2]

From: Joerg Mayer [mailto:[email protected]]

Quoted 6 lines · Guy
Quoted 2 lines

However, the vast majority of iwlwifi users at this point run it over little-endian platforms.

That would be 100% as it doesn't yet support big-endian platforms?

:)

I meant potential users...

Quoted 2 lines

ciao
Joerg

#46 lore raw

Re: [PATCH] Add iwlwifi wireless drivers [part 2/2]

In reply to James Ketrenos
Quoted 6 lines · On Fri, 18 May 2007 13:33:57 -0700 James Ketrenos wrote:
Quoted 4 lines

2. Use of bitfields: bitfields are not (guaranteed to be) portable across a wire interface to some other CPU architecture. Are all bitfield uses always local to the running driver? They should be.

The bitfields are between the hw/ucode (__le) and the driver. Are you saying the bitfields won't be compatible if the driver is compiled and running on big endian? Shouldn't le16_to_cpu() fix that? I just noticed the types in iwl-4965-hw.h weren't endian specific; I've updated that (u16, u32, u64 -> __le16, __le32, __le64)

I'm just saying that something like

	struct bits {
		u32	priority :4;
		u32	flags :12;
		u32	direction :1;
		u32	status :15;
	};

when built on x86[-64] and then sent over a network connection to a big-endian machine won't necessarily be looked at correctly on the receiving machine. There is no guarantee of bitfield order from one platform to another.

Quoted 5 lines
Quoted 3 lines

3. What are all of those "volatile" C keywords doing in struct iwl_shared?
See http://lwn.net/Articles/232961/ : "The trouble with volatile"

If a reference shared through memory mapped IO with a device that can change the value at any time, doesn't it need to be volatile? 'struct iwl_shared' is allocated with pci_alloc_consistent and the physical address is provided to the hardware for it to update whenever it sees fit.

That's a good question. You probably know as much about it as I do.

Does the driver access those mmIO regions by something direct like

	*mmio =

or does the driver use some kind of access routines to read/write the mmIO regions, such as readb()/writeb()?

If the former, then I expect that those should be changed/fixed, but I'd prefer to have Jeff G. answer that if he would.

Quoted 3 lines
Quoted 1 line

4. Don't list the parameters like this:

Lindent == bad. I've fixed the instances of this munging I've come across.

Indeed. Too bad.

Quoted 7 lines
Quoted 1 line

8. Too many BUG_ON()s. Try to recover or return -ERRORs instead.

I pulled out two that shouldn't have been there.

The rest are currently there map to bugs which are easily introduced through code changes but which may not cause an immediately visible bug at run-time. Typically they are placed where an eventual printk() at that location during debugging of a user bug resulted in the critical "ah-ha!" that led to fixing it. I've added comments to the BUG_ON's that didn't have comments already.

I suppose we could try and introduce a new driver recovery mechanism that, upon detection, throws a stack trace and then shuts down the driver (vs. throwing a kernel OOPs) requiring user space to unload and reload the driver. That would still be a sucky situation, but at least it wouldn't cause a system failure requiring a reboot... does such a mechanism already exist?

You can call dump_stack() or use WARN_ON(), but you'll have roll your own shut-down-the-driver methods AFAIK.

---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***

#47 lore raw
In reply to James Ketrenos
Quoted 5 lines · James Ketrenos
drivers/net/wireless/mac80211/Kconfig              |    1 +
drivers/net/wireless/mac80211/Makefile             |    1 +
drivers/net/wireless/mac80211/iwlwifi/Kconfig      |   96 +
drivers/net/wireless/mac80211/iwlwifi/Makefile     |   27 +
drivers/net/wireless/mac80211/iwlwifi/base.c       | 8146 

You're not reading linux-wireless a lot, are you? The last driver submission got a pretty clear answer that there should not be a drivers/net/wireless/mac80211/ subdirectory.

#48 lore raw
Quoted 11 lines · Christoph Hellwig
Quoted 5 lines · James Ketrenos
drivers/net/wireless/mac80211/Kconfig              |    1 +
drivers/net/wireless/mac80211/Makefile             |    1 +
drivers/net/wireless/mac80211/iwlwifi/Kconfig      |   96 +
drivers/net/wireless/mac80211/iwlwifi/Makefile     |   27 +
drivers/net/wireless/mac80211/iwlwifi/base.c       | 8146

You're not reading linux-wireless a lot, are you? The last driver submission got a pretty clear answer that there should not be a drivers/net/wireless/mac80211/ subdirectory.

This is just for wireless-dev. When it's being pushed for wireless-2.6 and upstream it should go away then.

-Michael Wu

#49 lore raw
In reply to James Ketrenos

An updated full patch (v3) to add the driver is available at:

http://intellinuxwireless.org/iwlwifi/0001-v3-Add-iwlwifi-wireless-drivers.patch

And if interested, here is the diff between the first version and this version:

http://intellinuxwireless.org/iwlwifi/iwlwifi-v1_to_v3.patch

The short log since the first submission:

Hong Liu (8):
remove param_channel module parameter
rename queueId to queue in iwl_hw_txq_ctx_stop
remove unused callback reset set_multicast_list
remove CONFIG_IWLWIFI_MONITOR and CONFIG_IWLWIFI_RADIOTAP in iwl4965_handle_data_packet set RX_FLAG_RADIOTAP in iwl_handle_data_packet_monitor
ieee80211chan2mhz is defined in ieee80211_radiotap.h
reformat iwl4965_rx_reply_rx
remove unnecessary in_interrupt() checks according to the ieee80211_ops comments

James Ketrenos (38):
Fixed Kconfig help indentation to be {tab}{sp}{sp}
Fixed indentation of non-case labels
Updated some function kernel-doc info; removed usage of /** for non kdoc Fixed up some usage of magic numbers to #defines, etc.
Removed is_broadast_ether_addr redundancy with is_multicast_ether_addr Updated block comments to conform to kernel style
Removed // style comments
Fixed indentation in is_duplicate_packet
Comment typo adwances -> advances
Whitespace, some 80-column, kernel doc, and other non-functional changes Trailing whitespace cleanup
Fix > 80 column problems in .c files (still have to do it in .h files) Removed usage of IWL_NOP and IWL_NOP_RET
Converted existing comment blocks into kernel-doc format
Add missing linebreak in pci_driver declrataion for suspend/resume Removed inline on non-trivial (>~3 lines) functions
Modified tune sysfs attribute to show/store a single value. Removed unused static function iwl4965_toggle_antennta from iwl-4965.c Change show_power_level to not prefix text before the power_level attr. Fixed trailing whitespace (again)
Set check to BUILD_BUG_ON(sizeof(priv->eeprom) != IWL_EEPROM_IMAGE_SIZE) u16, u32, u64 -> __le16, __le32, __le64 in iwl-4965-hw.h (hardware/uCode API Moved struct iwl_txpower_comp_entry out of iwl-4965-hw.h
Fixed iwl4965_get_dma_hi_address to work on all architectures Whitespace fixups.
Fixed printk() w/out KERN_ level
Removed several unnecessary variable initializers.
Whitespace and added line to todo
Added comments to BUG_ON code, and removed two BUG_ONs
Changed iwl_send_cmd BUG_ONs to printk errors and return -EINVAL. Fixed build for CONFIG_IWL4965=m
Removed all direct bitfield usage
Removed several deprecated CFG_ and CAP_ declarations and use Removed CONFIG_IWLWIFI_QOS blocks until they are buildable. Replace flush_scheduled_work in d_stop with flush_workqueue Removed Tx cmd message spam on iwl4965
Fixed a couple > 80 column width lines
Set CONFIG_IWL4965 to default to =m. Disabled =y configurations.

Yi Zhu (1):
Fix volatile usage

#50 lore raw
Quoted 3 lines · James Ketrenos

An updated full patch (v3) to add the driver is available at:

http://intellinuxwireless.org/iwlwifi/0001-v3-Add-iwlwifi-wireless-drivers.patch

Quick review attached.

Jeff

1) iwl_queue_inc_wrap and iwl_queue_dec_wrap can usually avoid a branch, if you use power-of-two queue size.

2) Using '%' to calculate index is more expensive than a mask

3) delete all casts to/from void pointers, such as

	txq->bd = (u8 *)
		pci_alloc_consistent(dev,

4) the difference in the TX queue size calculations is very error-prone:

	len = (sizeof(struct iwl_cmd) * count) + IWL_MAX_SCAN_SIZE;
		and
	len = (sizeof(txq->cmd[0]) * q->n_window) + IWL_MAX_SCAN_SIZE;

5) more Lindent damage to undo, in iwl_remove_station():

+ for (i = IWL_STA_ID; i < (priv->num_stations + IWL_STA_ID);
+ i++) {
+ if ((priv->stations[i].used)
+ &&
+ (!compare_ether_addr(
+ priv->stations[i].sta.sta.addr, bssid))) {

+                               index = i;
+                               priv->stations[index].used = 0;
+                               break;

+ }
+ }

6) iwl_delete_stations_table() and iwl_clear_stations_table() are exactly the same implementation. remove one.

7) ditto #5 in iwl_add_station()

8) obtain a ptr rather than repeatedly referencing priv->stations[i], in iwl_add_station()

9) de-indent the primary code block in iwl_sync_station(), by returning immediately if the sta_id is invalid

10) remove a lot of the 'inline' markers. let the compiler decide that.

11) eliminate this compile-the-code-twice scheme

12) delete the myriad checks in iwl_send_cmd() that are never hit in real life. Mark others WARN_ON() or whatever.

That is just way too many needless checks in a hot path.

13) delete the conditional locking in iwl_send_cmd(). spinlocking should not be conditional. it's error prone and usually wrong. the spinlocking in this routine is an excellent example of that. [reads further]
Yuck, it is -even worse- than I thought.

14) you don't need a prototype right before the function def:
+static int iwl_send_cmd_u32(struct iwl_priv *priv, u8 id, u32 val)
+ __attribute__ ((warn_unused_result));
+static int iwl_send_cmd_u32(struct iwl_priv *priv, u8 id, u32 val) +{

15) more Lindent damage in iwl_check_rxon_cmd():
+ error |=
+ ((rxon->
+ flags & (RXON_FLG_AUTO_DETECT_MSK |

16) This whole CMD_ASYNC paradigm is problematic. Use the standard Linux style: Make EVERYTHING async, and then have separate helpers that allow the code to wait for completion.

17) more Lindent damage:
+ if (priv->frames_count) {
+ IWL_WARNING
+ ("%d frames still in use. Did we lose one?\n",
+ priv->frames_count);

18) remove nonsense tests:
+ if (list_empty(&priv->free_frames)) {
...
+ if (priv->frames_count >= FREE_FRAME_THRESHOLD) {
+ IWL_WARNING("%d frames allocated. "
+ "Are we losing them?\n",
+ priv->frames_count);

19) iwl_free_frame() does not pay attention to FREE_FRAME_THRESHOLD

20) Lindent damage:
+ IWL_ERROR
+ ("Coult not obtain free frame buffer for beacon "
+ "command.\n");
+ return -ENOMEM;
+ }
+
+ if (!(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)) {
+ rate =
+ iwl_rate_get_lowest_plcp(priv->active_rate_basic & 0xFF0);

21) poorly named function:
+static void eeprom_parse_mac(struct iwl_priv *priv, u8 * mac) +{
+ memcpy(mac, priv->eeprom.mac_address, 6);
+}

22) kill magic numbers in iwl_eeprom_init()

23) bogus comment and messy declarations in iwl_report_frame():
+ /* these are declared without "=" to avoid compiler warnings if
we
+ * don't use them in the debug messages below */

+       u16 frame_ctl;
+       u16 seq_ctl;
+       u16 channel;

CLEARLY you will get 'unused variable' warnings, if you don't use them

24) as akpm said, don't break up variables, it makes decls look like code blocks:

+       u8 agc;
+       u16 sig_avg;
+       u16 noise_diff;
+
+       struct iwl_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
+       struct iwl_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
+       struct iwl_rx_frame_end *rx_end = IWL_RX_END(pkt);
+       u8 *data = IWL_RX_DATA(pkt);

25) this loop needs some sort of fencing:
+ mutex_unlock(&priv->mutex);
+ if (ms)
+ while (!time_after(jiffies,
+ now + msecs_to_jiffies(ms)) &&
+ priv->status & STATUS_SCANNING)
+ msleep(1);
+
+ mutex_lock(&priv->mutex);

26) overall, priv->status accesses look racy in many instances

27) ditch private workqueue

28) weird indentation:
+ IWL_DEBUG_RATE("station Id %d\n", sta_id);
+
+ qc = ieee80211_get_qos_ctrl(hdr);
+ if (qc) {
+ u8 tid = (u8)(*qc & 0xf);

29) are some uses of control_flags in iwl_tx_skb() endian-unsafe?

30) replace "todoG" with something standard to Linux like FIXME or TODO

31) iwl_rx_reply_scan() does nothing

32) racy priv->status manipulation in iwl_rx_scan_complete_notif()

33) kill braces around single C statements:
+ if (rxq->free_count <= RX_LOW_WATERMARK) {
+ queue_work(priv->workqueue, &priv->rx_replenish);
+ }

34) dont do this in your interrupt handler:
* mask events
* handle events
* unmask events
delete the mask/unmask stuff

35) your irq tasklet is unneeded. just do it in the irq handler, and eliminate the races.

36) way too many allocations are GFP_ATOMIC. that tells me you are often doing initialization in the wrong context

37) looks like iwl_read_ucode() needs endian accessors?

38) after disabling interrupts you need to do a read, to ensure your request is flushed to the hardware

39) rename d_xxx functions. those are ambiguous in a trace

40) no need to zero stuff in iwl_pci_probe(), priv should already be zeroed for you

41) use pci_iomap() rather than ioremap_nocache()

42) you queue stuff to a workqueue, when it is obvious from context (e.g. iwl_pci_probe) it can sleep

43) naming your module parameters param_xxx, and making them global symbols, pollutes the global namespace and potentially introduces conflicts

44) don't use reg_xxx as a function prefix, that is ambiguous in a trace

45) fix long function names:
reg_txpower_compensate_for_temperature_dif()

46) ditto:
iwl_write_restricted(), iwl_release_restricted_access()

47) kill magic numbers in pci_{read,write}_config_xxx calls

48) shorten too-long constant names:
CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE
CSR_RESET_REG_FLAG_MASTER_DISABLED,

49) PCI posting bug?
+
+ iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+
+ udelay(10);
+
+ iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);

50) this is just silly:
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ spin_lock_irqsave(&priv->lock, flags);
+

51) fix long struct names:
struct iwl_eeprom_calib_measurement

52) and struct member names:

	ch_i1 = priv->eeprom.calib_info.band_info_tbl[s].ch1.ch_num;

53) etc.

	iwl4965_get_txatten_group_from_channel()

54) magic number
+ if (-40 > current_temp) {
+ IWL_WARNING("Invalid temperature %d, can't calculate "

55) no need for all this casting and masking:
+static inline u32 iwl4965_get_dma_lo_address(dma_addr_t addr) +{
+ return (u32) (addr & 0xffffffff);
+}

56) endian-ness in iwl4965_load_bsm()

57) no need to lock around a single MMIO write:
+ spin_lock_irqsave(&priv->lock, flags);
+
+ iwl_write32(priv, CSR_RESET, 0);
+
+ spin_unlock_irqrestore(&priv->lock, flags);

58) separate declarations and code:

+       };
+       u8 network_packet;
+       if ((unlikely(rx_start->cfg_mib_cnt > 20))) {

59) too long:
iwl_write_restricted_reg_buffer()

#51 lore raw
Quoted 9 lines · Jeff Garzik
Quoted 3 lines · James Ketrenos

An updated full patch (v3) to add the driver is available at:

http://intellinuxwireless.org/iwlwifi/0001-v3-Add-iwlwifi-wireless-drivers.patch

Quick review attached.

Jeff

Thanks for the review.

Hopefully once in wireless-dev, we (more than just me, myself, and I) can work to get these knocked off in iterative small commits vs. having to paste a monolithic driver add patch that makes git-bisect near useless. Some of your review comments impact code which can have significant ripple effects -- I would like to be able to manage those changes here vs. solely with the iwlwifi community of users.

James