[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

rpms/kernel/FC-4 0085-drivers-net-fix-up-schedule_timeout-usage.txt, 1.1.2.2, 1.1.2.3 0089-C99-initializers-in-ray_cs.c.txt, 1.1.2.2, 1.1.2.3 0091-Add-rapidio-net-driver.txt, NONE, 1.1.2.1 0101-orinoco-Remove-conditionals-that-are-useless-in-the-kernel-drivers.txt, 1.1.2.2, 1.1.2.3 0102-orinoco-Don-t-include-net-ieee80211.h-twice.txt, 1.1.2.2, 1.1.2.3 0103-orinoco-Update-PCMCIA-ID-s.txt, 1.1.2.2, 1.1.2.3 0104-Fixed-some-endian-issues-with-802.11-header-usage-in-ieee80211_rx.c.txt, NONE, 1.1.2.1 0105-ieee80211-quality-scaling-algorithm-extension-handler.txt, NONE, 1.1.2.1 0106-ieee80211-Added-wireless-spy-support.txt, NONE, 1.1.2.1 0107-Changed-802.11-headers-to-use-ieee80211_info_element-0.txt, NONE, 1.1.2.1 0108-ieee80211-Removed-ieee80211_info_element_hdr.txt, NONE, 1.1.2.1 0109-ieee80211-Cleanup-memcpy-parameters.txt, NONE, 1.1.2.1 0110-ieee80211-Switched-to-sscanf-in-store_debug_level.txt, NONE, 1.1.2.1 0111-ieee80211-Fixed-type-o-of-abg_ture-abg_true.txt, NONE, 1.1.2.1 0112-Updated-ipw220! 0-to-compile-with-ieee80211-abg_ture-to-abg_true-change.txt, 1.1.2.2, 1.1.2.3 0161-ieee80211-Updated-ipw2100-to-be-compatible-with-ieee80211_hdr-changes.txt, 1.1.2.2, 1.1.2.3 0162-ieee80211-Updated-ipw2100-to-be-compatible-with-ieee80211-s-hard_start_xmit-change.txt, 1.1.2.2, 1.1.2.3 0163-ieee80211-Updated-ipw2200-to-be-compatible-with-ieee80211_hdr-changes.txt, 1.1.2.2, 1.1.2.3 0164-ieee80211-Updated-ipw2200-to-be-compatible-with-ieee80211-s-hard_start_xmit-change.txt, 1.1.2.2, 1.1.2.3 0165-ieee80211-Updated-atmel-to-be-compatible-with-ieee80211_hdr-changes.txt, 1.1.2.2, 1.1.2.3 0166-ieee80211-Fixed-a-kernel-oops-on-module-unload.txt, NONE, 1.1.2.1 0167-ieee80211-Hardware-crypto-and-fragmentation-offload-support.txt, NONE, 1.1.2.1 0168-ieee80211-Fix-time-calculation-switching-to-use-jiffies_to_msecs.txt, NONE, 1.1.2.1 0169-ieee80211-Fix-kernel-Oops-when-module-unload.txt, NONE, 1.1.2.1 0170-ieee80211-Allow-drivers-to-fix-an-issue-when-using-wpa_supplicant-with-WEP.txt, NONE, 1.1.2.1 0171-ieee82! 011-Added-WE-18-support-to-default-wireless-extension-handler.! txt,NONE



Author: linville

Update of /cvs/dist/rpms/kernel/FC-4
In directory cvs.devel.redhat.com:/tmp/cvs-serv10802

Added Files:
      Tag: private-linville-netdev-fc4-1-branch
	0085-drivers-net-fix-up-schedule_timeout-usage.txt 
	0089-C99-initializers-in-ray_cs.c.txt 
	0091-Add-rapidio-net-driver.txt 
	0101-orinoco-Remove-conditionals-that-are-useless-in-the-kernel-drivers.txt 
	0102-orinoco-Don-t-include-net-ieee80211.h-twice.txt 
	0103-orinoco-Update-PCMCIA-ID-s.txt 
	0104-Fixed-some-endian-issues-with-802.11-header-usage-in-ieee80211_rx.c.txt 
	0105-ieee80211-quality-scaling-algorithm-extension-handler.txt 
	0106-ieee80211-Added-wireless-spy-support.txt 
	0107-Changed-802.11-headers-to-use-ieee80211_info_element-0.txt 
	0108-ieee80211-Removed-ieee80211_info_element_hdr.txt 
	0109-ieee80211-Cleanup-memcpy-parameters.txt 
	0110-ieee80211-Switched-to-sscanf-in-store_debug_level.txt 
	0111-ieee80211-Fixed-type-o-of-abg_ture-abg_true.txt 
	0112-Updated-ipw2200-to-compile-with-ieee80211-abg_ture-to-abg_true-change.txt 
	0161-ieee80211-Updated-ipw2100-to-be-compatible-with-ieee80211_hdr-changes.txt 
	0162-ieee80211-Updated-ipw2100-to-be-compatible-with-ieee80211-s-hard_start_xmit-change.txt 
	0163-ieee80211-Updated-ipw2200-to-be-compatible-with-ieee80211_hdr-changes.txt 
	0164-ieee80211-Updated-ipw2200-to-be-compatible-with-ieee80211-s-hard_start_xmit-change.txt 
	0165-ieee80211-Updated-atmel-to-be-compatible-with-ieee80211_hdr-changes.txt 
	0166-ieee80211-Fixed-a-kernel-oops-on-module-unload.txt 
	0167-ieee80211-Hardware-crypto-and-fragmentation-offload-support.txt 
	0168-ieee80211-Fix-time-calculation-switching-to-use-jiffies_to_msecs.txt 
	0169-ieee80211-Fix-kernel-Oops-when-module-unload.txt 
	0170-ieee80211-Allow-drivers-to-fix-an-issue-when-using-wpa_supplicant-with-WEP.txt 
	0171-ieee82011-Added-WE-18-support-to-default-wireless-extension-handler.txt 
	0172-ieee80211-Renamed-ieee80211_hdr-to-ieee80211_hdr_3addr.txt 
	0173-ieee80211-adds-support-for-the-creation-of-RTS-packets.txt 
	0174-ieee82011-Added-ieee80211_tx_frame-to-convert-generic-802.11-data-frames-and-callbacks.txt 
	0175-ieee80211-Fix-TKIP-repeated-fragmentation-problem-and-payload_size-reporting.txt 
	0176-ieee80211-Return-NETDEV_TX_BUSY-when-QoS-buffer-full.txt 
	0177-ieee80211-Add-QoS-WME-support-to-the-ieee80211-subsystem.txt 
	0178-ieee80211-Added-ieee80211_geo-to-provide-helper-functions.txt 
	0179-ieee80211-Added-ieee80211_radiotap.h.txt 
	0180-ieee80211-Additional-fixes-for-endian-aware-types.txt 
	0181-ieee80211-extern-inline-to-static-inline.txt 
	0182-ieee80211-Type-o-capbility-definition-for-QoS-and-ERP-parsing.txt 
	0183-ieee80211-Mixed-PTK-GTK-CCMP-TKIP-support.txt 
	0184-ieee80211-Keep-auth-mode-unchanged-after-iwconfig-key-off-on-cycle.txt 
	0185-ieee80211-Updated-copyright-dates.txt 
	0186-ieee80211-Updated-hostap-to-be-compatible-with-ieee80211_hdr-changes.txt 
	0187-ieee80211-Updated-hostap-to-be-compatible-with-extra_prefix_len-changes.txt 
	0188-ieee82011-Remove-WIRELESS_EXT-ifdefs.txt 
	0194-ieee80211-Added-subsystem-version-string-and-reporting-via-MODULE_VERSION.txt 
	0195-ieee80211-Added-handle_deauth-callback-enhanced-tkip-ccmp-support-of-varying-hw-sw-offload.txt 
	0196-ieee80211-added-IE-comments-reason_code-to-reason-removed-info_element-from-ieee80211_disassoc.txt 
	0197-ieee80211-in-tree-driver-updates-to-sync-with-latest-ieee80211-series.txt 
	0198-ieee80211-update-orinoco-wl3501-drivers-for-latest-struct-naming.txt 
	0211-orinoco-Remove-inneeded-system-includes.txt 
	0212-orinoco-Make-nortel_pci_hw_init-static.txt 
	0213-orinoco-Fix-memory-leak-and-unneeded-unlock-in-orinoco_join_ap.txt 
	0214-orinoco-orinoco_send_wevents-could-return-without-unlocking.txt 
	0215-orinoco-Remove-unneeded-forward-declarations.txt 
	0216-orinoco-Annotate-endianess-of-variables-and-structure-members.txt 
	0217-orinoco-Read-only-needed-data-in-__orinoco_ev_txexc.txt 
	0218-orinoco-Bump-version-to-0.15rc3.txt 
	0222-RPC-Report-connection-errors-properly-when-mounting-with-soft.txt 
	0223-RPC-proper-soft-timeout-behavior-for-rpcbind.txt 
	0224-NFS-use-a-constant-value-for-TCP-retransmit-timeouts.txt 
	0225-RPC-portmapper-doesn-t-need-a-reserved-port.txt 
	0226-RPC-extract-socket-logic-common-to-both-client-and-server.txt 
	0227-RPC-introduce-client-side-transport-switch.txt 
	0228-RPC-transport-switch-function-naming.txt 
	0229-RPC-Reduce-stack-utilization-in-xs_sendpages.txt 
	0230-RPC-Rename-sock_lock.txt 0231-RPC-Rename-xprt_lock.txt 
	0232-RPC-rename-the-sockstate-field.txt 
	0233-RPC-Eliminate-socket.h-includes-in-RPC-client.txt 
	0234-RPC-Add-helper-for-waking-tasks-pending-on-a-transport.txt 
	0235-RPC-client-side-transport-switch-cleanup.txt 
	0236-RPC-separate-TCP-and-UDP-write-space-callbacks.txt 
	0237-RPC-separate-TCP-and-UDP-transport-connection-logic.txt 
	0238-RPC-separate-TCP-and-UDP-socket-write-paths.txt 
	0239-RPC-skip-over-transport-specific-heads-automatically.txt 
	0240-RPC-get-rid-of-xprt-stream.txt 
	0241-RPC-add-API-to-set-transport-specific-timeouts.txt 
	0242-RPC-expose-API-for-serializing-access-to-RPC-transports.txt 
	0243-RPC-expose-API-for-serializing-access-to-RPC-transports.txt 
	0244-RPC-separate-xprt_timer-implementations.txt 
	0245-RPC-add-generic-interface-for-adjusting-the-congestion-window.txt 
	0246-RPC-add-a-release_rqst-callout-to-the-RPC-transport-switch.txt 
	0247-RPC-remove-xprt-nocong.txt 
	0248-RPC-clean-up-after-nocong-was-removed.txt 
	0249-RPC-allow-RPC-client-s-port-range-to-be-adjustable.txt 
	0250-RPC-make-sure-to-get-the-same-local-port-number-when-reconnecting.txt 
	0251-RPC-parametrize-various-transport-connect-timeouts.txt 
	0252-RPC-rationalize-set_buffer_size.txt 
	0253-RPC-NFS-new-rpc_pipefs-patch.txt 
	0255-Revert-PATCH-RPC-NFS-new-rpc_pipefs-patch.txt 
	0257-SUNRPC-fix-bug-in-patch-portmapper-doesn-t-need-a-reserved-port.txt 
	0261-netdrvr-gianfar-use-new-phy-layer.txt 
	0262-netdrvr-delete-CONFIG_PHYCONTROL.txt 
	0263-hostap-Fix-pci_driver-name-for-hostap_plx-and-hostap_pci.txt 
	0264-hostap-Add-support-for-WE-19.txt 
	0265-hostap-Use-GFP_ATOMIC-to-get-rid-of-weird-might_sleep-issue.txt 
	0266-hostap-Remove-iwe_stream_add_event-kludge.txt 
	0267-Remove-WIRELESS_EXT-ifdefs-from-several-wireless-drivers.txt 
	0268-wireless-airo-remove-needed-dma_addr_t-obfuscation.txt 
	0312-This-patch-fixes-a-typo-in-ieee80211.h-ieee82011_deauth-ieee80211_deauth.txt 
	0335-This-will-move-the-ieee80211_is_ofdm_rate-function-to-the-ieee80211.h.txt 
	0337-Currently-the-info_element-is-parsed-by-2-seperate-functions-this.txt 
	0338-When-an-assoc_resp-is-received-the-network-structure-is-not-completely.txt 
	0339-Lindent-and-trailing-whitespace-script-executed-ieee80211-subsystem.txt 
	0345-hostap-Remove-hw-specific-dev_open-close-handlers.txt 
	0346-hostap-Fix-hostap_pci-build-with-PRISM2_IO_DEBUG.txt 
	0347-hostap-Do-not-free-local-hw_priv-before-unregistering-netdev.txt 
	0348-hostap-Unregister-netdevs-before-freeing-local-data.txt 
	0366-airo-fix-resume.txt 
	0371-wireless-ipw2200-remove-redundant-return-statement.txt 
	0543-SUNRPC-Retry-rpcbind-requests-if-the-server-s-portmapper-isn-t-up.txt 
	0544-RPC-allow-call_encode-to-delay-transmission-of-an-RPC-call.txt 
	0563-ieee80211-division-by-zero-fix.txt 
	0576-mipsnet-Virtual-ethernet-driver-for-MIPSsim.txt 
	0584-bonding-cleanup-comment-for-mode-1-IGMP-xmit-hack.txt 
	0586-orinoco-remove-redundance-skb-length-check-before-padding.txt 
	0591-RPC-stops-the-release_pipe-funtion-from-being-called-twice.txt 
	0594-SUNRPC-Add-support-for-privacy-to-generic-gss-api-code.txt 
	0595-SUNRPC-Provide-a-callback-to-allow-free-pages-allocated-during-xdr-encoding.txt 
	0596-SUNRPC-Retry-wrap-in-case-of-memory-allocation-failure.txt 
	0597-RPCSEC_GSS-cleanup-au_rslack-calculation.txt 
	0598-RPCSEC_GSS-client-side-privacy-support.txt 
	0599-RPCSEC_GSS-Simplify-rpcsec_gss-crypto-code.txt 
	0600-RPCSEC_GSS-krb5-pre-privacy-cleanup.txt 
	0601-RPCSEC_GSS-Add-support-for-privacy-to-krb5-rpcsec_gss-mechanism.txt 
	0602-RPCSEC_GSS-remove-all-qop-parameters.txt 
	0603-RPCSEC_GSS-krb5-cleanup.txt 
	0610-Fixed-problem-with-not-being-able-to-decrypt-encrypt-broadcast-packets.txt 
	0635-Fixed-oops-if-an-uninitialized-key-is-used-for-encryption.txt 
	0658-ieee80211-subsystem.txt 
	0659-Update-version-ieee80211-stamp-to-1.1.6.txt 
	0759-DECNET-Remove-some-redundant-ifdeffed-code.txt 
	0760-NET-Wider-use-of-for_each_-cpu.txt 
	0761-PKTGEN-Sleeping-function-called-under-lock.txt 
	0762-PKTGEN-Use-kzalloc.txt 
	0763-PKTGEN-Spelling-and-white-space.txt 
	0764-PKTGEN-proc-interface-revision.txt 
	0765-NETFILTER-ip_conntrack-Make-hashsize-conntrack-parameter-writable.txt 
	0766-IPV4-Kill-redundant-rcu_dereference-on-fa_info.txt 
	0767-IPSEC-Kill-obsolete-get_mss-function.txt 
	0768-NETLINK-Remove-dead-code-in-af_netlink.c.txt 
	0769-IPV4-Remove-dead-code-from-ip_output.c.txt 
	0770-SK_BUFF-kernel-doc-fix-skbuff-warnings.txt 
	0771-AX.25-Use-constant-instead-of-magic-number.txt 
	0772-IPV4-Fix-setting-broadcast-for-SIOCSIFNETMASK.txt 
	0774-ieee80211-build-fix.txt 
	0822-Revert-RPC-stops-the-release_pipe-funtion-from-being-called-twice.txt 
	0843-RPC-Ensure-that-nobody-can-queue-up-new-upcalls-after-rpc_close_pipes.txt 
	0919-gfp_t-net.txt 0951-ARM-2897-2-PXA2xx-IRDA-support.txt 
	0997-Input-convert-net-bluetooth-to-dynamic-input_dev-allocation.txt 
	1017-Bluetooth-Move-CRC-table-into-RFCOMM-core.txt 
	1020-Bluetooth-Make-more-functions-static.txt 
	1021-Bluetooth-Update-security-filter-for-Extended-Inquiry-Response.txt 
	1026-IPv4-IPv6-UFO-Scatter-gather-approach.txt 
	1027-MCAST-IPv6-Fix-algorithm-to-compute-Querier-s-Query-Interval.txt 
	1058-New-PowerPC-4xx-on-chip-ethernet-controller-driver.txt 
	1062-drivers-net-Remove-pointless-checks-for-NULL-prior-to-calling-kfree.txt 
	1065-ipw2200-Missing-kmalloc-check.txt 
	1141-SCTP-Rename-SCTP-specific-control-message-flags.txt 
	1145-SCTP-Fix-SCTP_SETADAPTION-sockopt-to-use-the-correct-structure.txt 
	1146-SCTP-Allow-SCTP_MAXSEG-to-revert-to-default-frag-point-with-a-0-value.txt 
	1178-SCTP-Do-not-allow-unprivileged-programs-initiating-new-associations-on.txt 
	1186-revert-orinoco-Information-leakage-due-to-incorrect-padding.txt 
	1187-Better-fixup-for-the-orinoco-driver.txt 
	1302-ETH-ether-address-compare.txt 
	1311-IPV4-Fix-issue-reported-by-Coverity-in-ipv4-fib_frontend.c.txt 
	1379-bluetooth-hidp-is-broken-on-s390.txt 
	1387-prism54-Free-skb-after-disabling-interrupts.txt 
	1731-PPC-44x-EMAC-driver-add-440SPe-support.txt 
	1732-PPC-44x-EMAC-driver-add-440GR-support.txt 
	1733-PPC-4xx-EMAC-driver-fix-VSC8201-PHY-initialization.txt 
	1743-vmalloc_node.txt 
	1836-ARM-3066-1-Fix-PXA-irda-driver-suspend-resume-functions.txt 
	1911-smsc-ircc2-PM-cleanup-do-not-close-device-when-suspending.txt 
	1943-Typo-fix-dot-after-newline-in-printk-strings.txt 
	2059-BRIDGE-Use-ether_compare.txt 
	2060-NETFILTER-Add-revision-support-to-arp_tables-and-ip6_tables.txt 
	2061-ROSE-rose_heartbeat_expiry-locking-fix.txt 
	2062-IPV6-Fix-behavior-of-ip6_route_input-for-link-local-address.txt 
	2064-DCCP-Simplify-skb_set_owner_w-semantics.txt 
	2069-DCCP-Set-socket-owner-iff-packet-is-not-data.txt 
	2070-MCAST-IPv6-Check-packet-size-when-process-Multicast.txt 
	2224-MCAST-ip-6-_mc_add_src-should-be-called-when-number-of-sources-is-zero.txt 
	2235-IPV6-inet6_ifinfo_notify-should-use-RTM_DELLINK-in-addrconf_ifdown.txt 
	2246-PKT_SCHED-Rework-QoS-and-or-fair-queueing-configuration.txt 
	2374-ARM-Reverted-2919-1-CS8900A-ethernet-driver-modifications-for-the-Comdial-MP1000.txt 
	2387-SUNRPC-allow-sunrpc.o-to-link-when-CONFIG_SYSCTL-is-disabled.txt 
	2388-NFS-SUNRPC-NLM-fix-unused-variable-warnings-when-CONFIG_SYSCTL-is-disabled.txt 
	2393-NETFILTER-PPTP-helper-Fix-compilation-of-conntrack-helper-without-NAT.txt 
	2394-NETFILTER-PPTP-helper-Fix-endianness-bug-in-GRE-key-CallID-NAT.txt 
	2397-NETFILTER-NAT-Fix-module-refcount-dropping-too-far.txt 
	2399-NETFILTER-Fix-double-free-after-netlink_unicast-in-ctnetlink.txt 
	2404-NETFILTER-nfnetlink-Use-kzalloc.txt 
	2405-NETFILTER-CONNMARK-target-needs-ip_conntrack.txt 
	2406-NETFILTER-nf_queue-Fix-Ooops-when-no-queue-handler-registered.txt 
	2407-NETEM-use-PSCHED_LESS.txt 
	2409-drivers-net-wireless-airo.c-unsigned-comparason.txt 
	2410-S2io-Multi-buffer-mode-support.txt 
	2416-PKT_SCHED-Generic-RED-layer.txt 
	2417-NET-Introduce-INET_ECN_set_ce-function.txt 
	2418-PKT_SCHED-RED-Use-new-generic-red-interface.txt 
	2419-PKT_SCHED-RED-Use-generic-queue-management-interface.txt 
	2420-PKT_SCHED-RED-Dont-start-idle-periods-while-already-idling.txt 
	2421-PKT_SCHED-RED-Cleanup-and-remove-unnecessary-code.txt 
	2422-PKT_SCHED-GRED-Cleanup-equalize-flag-and-add-new-WRED-mode-detection.txt 
	2423-PKT_SCHED-GRED-Transform-grio-to-GRED_RIO_MODE.txt 
	2424-PKT_SCHED-GRED-Cleanup-dumping.txt 
	2425-PKT_SCHED-GRED-Dump-table-definition.txt 
	2426-PKT_SCHED-GRED-Use-a-central-table-definition-change-procedure.txt 
	2427-PKT_SCHED-GRED-Report-out-of-bound-DPs-as-illegal.txt 
	2428-PKT_SCHED-GRED-Use-central-VQ-change-procedure.txt 
	2429-PKT_SCHED-GRED-Use-new-generic-red-interface.txt 
	2430-PKT_SCHED-GRED-Do-not-reset-statistics-in-gred_reset-gred_change.txt 
	2431-PKT_SCHED-GRED-Report-congestion-related-drops-as-NET_XMIT_CN.txt 
	2432-PKT_SCHED-GRED-Use-generic-queue-management-interface.txt 
	2433-PKT_SCHED-GRED-Introduce-tc_index_to_dp.txt 
	2434-PKT_SCHED-GRED-Improve-error-handling-and-messages.txt 
	2435-PKT_SCHED-GRED-Remove-initd-flag.txt 
	2436-PKT_SCHED-GRED-Dont-abuse-default-VQ-for-equalizing.txt 
	2437-PKT_SCHED-GRED-Remove-auto-creation-of-default-VQ.txt 
	2438-PKT_SCHED-GRED-Cleanup-and-remove-unnecessary-code.txt 
	2439-PKT_SCHED-GRED-Fix-restart-of-idle-period-in-WRED-mode-upon-dequeue-and-drop.txt 
	2440-PKT_SCHED-GRED-Support-ECN-marking.txt 
	2441-PKT_SCHED-G-RED-Introduce-hard-dropping.txt 
	2450-NETEM-Support-time-based-reordering.txt 
	2451-NETEM-Add-version-string.txt 
	2452-NET-Fix-race-condition-in-sk_stream_wait_connect.txt 
	2453-TCP-DCCP-Randomize-port-selection.txt 
	2458-prism54-Remove-redundant-assignment.txt 
	2467-Remove-linux-version.h-include-from-drivers-net-phy-and-net-ieee80211.txt 
	2469-netdrvr-s2io-warning-fixes.txt 
	2577-b44-miscellaneous-cleanup.txt 
	2578-b44-expose-counters-through-ethtool.txt 
	2752-knfsd-make-sure-svc_process-call-the-correct-pg_authenticate-for-multi-service-port.txt 
	2907-scripts-Lindent-on-ieee80211-subsystem.txt 
	2908-Fix-problem-with-WEP-unicast-key-index-0.txt 
	2909-Update-version-ieee80211-stamp-to-1.1.7.txt 
	2910-Ran-scripts-Lindent-on-drivers-net-wireless-ipw2-1-2-00.-c-h.txt 
	2911-IPW_DEBUG-has-already-included-DRV_NAME-remove-double-prefix-print.txt 
	2912-Catch-ipw2200-up-to-equivelancy-with-v1.0.1.txt 
	2913-Catch-ipw2200-up-to-equivelancy-with-v1.0.2.txt 
	2914-Catch-ipw2200-up-to-equivelancy-with-v1.0.3.txt 
	2915-Catch-ipw2200-up-to-equivelancy-with-v1.0.4.txt 
	2916-Catch-ipw2100-up-to-equivelancy-with-v1.1.1.txt 
	2917-Fixed-WEP-on-ipw2100-priv-sec-was-being-used-instead-of.txt 
	2918-Bug-339-Fix-ipw2100-iwconfig-set-get-txpower.txt 
	2919-Move-code-from-ipw2100_wpa_enable-to-IPW2100_PARAM_DROP_UNENCRYPTED-to.txt 
	2920-Catch-ipw2200-up-to-equivelancy-with-v1.0.5.txt 
	2921-Fix-hardware-encryption-both-WEP-and-AES-doesn-t-work-with-fragmentation.txt 
	2922-Fix-is_duplicate_packet-bug-for-fragmentation-number-setting.txt 
	2923-bug-667-Fix-the-notorious-No-space-for-Tx-bug.txt 
	2924-Bug-637-Set-tx-power-for-A-band.txt 
	2925-Changed-default-of-missed-beacons-to-miss-before-disassociation-to-24.txt 
	2926-Updated-to-support-ieee80211-callback-to-is_queue_full-for-802.11e.txt 
	2927-Fixed-some-compiler-issues-if-CONFIG_IPW2200_QOS-is-enabled.txt 
	2928-Added-more-useful-geography-encoding-so-people-s-experience-with.txt 
	2929-Workaround-kernel-BUG_ON-panic-caused-by-unexpected-duplicate-packets.txt 
	2930-Disable-host-fragmentation-in-open-mode-since-IPW2200-2915-hardware.txt 
	2931-Bug-792-Fix-WPA-PSK-AES-both-for-Dipw-and-Dwext.txt 
	2932-Fixes-the-ad-hoc-network-WEP-key-list-issue.txt 
	2933-Bug-701-Fix-a-misuse-of-ieee-mode-with-ieee-iw_mode.txt 
	2934-Fix-ipw_wx_get_txpow-shows-wrong-disabled-value.txt 
	2935-Fix-firmware-error-when-setting-tx_power.txt 
	2936-Modified-ipw_config-and-STATUS_INIT-setting-to-correct-race-condition.txt 
	2937-Switched-firmware-error-dumping-so-that-it-will-capture-a-log-available.txt 
	2938-Changed-all-of-the-ipw_send_cmd-calls-to-return-any-ipw_send_cmd-error.txt 
	2939-Added-cmdlog-in-non-debug-systems.txt 
	2940-Migrated-some-of-the-channel-verification-code-back-into-the-driver-to.txt 
	2941-Updated-ipw2200-to-use-the-new-ieee80211-callbacks.txt 
	2942-Added-wait_state-wakeup-on-scan-completion.txt 
	2943-Bug-455-Fix-frequent-channel-change-generates-firmware-fatal-error.txt 
	2944-Bug-760-Fix-setting-WEP-key-in-monitor-mode-causes-IV-lost.txt 
	2945-Don-t-set-hardware-WEP-if-we-are-actually-using-TKIP-AES.txt 
	2946-Make-all-the-places-the-firmware-fails-to-load-showerrors-in-decimal.txt 
	2947-Adds-radiotap-support-to-ipw2200-in-monitor-mode.txt 
	2948-Fixed-is_network_packet-to-include-checking-for-broadcast-packets.txt 
	2949-Mixed-PTK-GTK-CCMP-TKIP-support.txt 
	2950-Card-with-WEP-enabled-and-using-shared-key-auth-will-have-firmware.txt 
	2951-Fixed-problem-with-get_cmd_string-not-existing-if-CONFIG_IPW_DEBUG-disabled.txt 
	2952-Removed-PF_SYNCTHREAD-legacy.txt 
	2953-Fixes-problem-with-WEP-not-working-association-succeeds-but-no-Tx-Rx.txt 
	2954-Fix-bug-771-Too-many-8-bytes-recieved-when-using-AES-hwcrypto.txt 
	2955-Fixes-WEP-firmware-error-condition.txt 
	2956-Updated-driver-version-stamps-for-ipw2100-1.1.3-and-ipw2200-1.0.7.txt 
	2957-Pulled-out-a-stray-KERNEL_VERSION-check-around-the-suspend-handler.txt 
	2958-Fix-Driver-using-old-proc-net-wireless-support-please-fix-driver-message.txt 
	2959-Removed-legacy-WIRELESS_EXT-checks-from-ipw2200.c.txt 
	2960-Fixes-missed-beacon-logic-in-relation-to-on-network-AP-roaming.txt 
	2961-Removed-warning-about-TKIP-not-being-configured-if-countermeasures-are.txt 
	2962-Added-channel-support-for-ipw2200-cards-identified-as-ZZR.txt 
	2963-Fixed-problem-with-not-being-able-to-send-broadcast-packets.txt 
	2964-Fixed-parameter-reordering-in-firmware-log-routine.txt 
	2965-Updated-firmware-version-stamp-to-2.4-from-2.3-so-it-will-use-the-latest-firmware.txt 
	2966-Update-version-ipw2200-stamp-to-1.0.8.txt 
	3004-fix-NET_RADIO-n-IEEE80211-y-compile.txt 
	3006-kill-include-linux-eeprom.h.txt 
	3008-prism54-Unused-variable-extraneous-udelay.txt 
	3009-prism54-Transmit-stats-updated-in-wrong-place.txt 
	3011-atmel-memset-correct-range.txt 
	3021-IPV6-Put-addr_diff-into-common-header-for-future-use.txt 
	3022-IPV6-Make-ipv6_addr_type-more-generic-so-that-we-can-use-it-for-source-address-selection.txt 
	3023-IPV6-RFC3484-compliant-source-address-selection.txt 
	3025-PKT_SCHED-Correctly-handle-empty-ematch-trees.txt 
	3026-NET-sk_add_backlog-convert-from-macro-to-inline.txt 
	3029-PPP-add-PPP-MPPE-encryption-module.txt 
	3031-NET-kfree-cleanup.txt 
	3032-IPV4-Fix-ip_queue_xmit-identity-increment-for-TSO-packets.txt 
	3034-Bluetooth-Add-endian-annotations-to-the-core.txt 
	3035-Bluetooth-Remove-the-usage-of-proc-completely.txt 
	3062-wireless-ipw2100-kill-unused-var-warnings-for-debug-disabled-code.txt 
	3063-ieee80211-cleanup-crypto-list-handling-other-minor-cleanups.txt 
	3067-cris-v10-eth-use-ethtool_ops.txt 
	3120-add-a-vfs_permission-helper.txt 
	3122-sanitize-lookup_hash-prototype.txt 
	3417-NETFILTER-packet-counter-of-conntrack-is-32bits.txt 
	3418-NETFILTER-refcount-leak-of-proto-when-ctnetlink-dumping-tuple.txt 
	3419-NETFILTER-nfnetlink-nfattr_parse-can-never-fail-make-it-void.txt 
	3420-NETFILTER-ctnetlink-check-if-protoinfo-is-present.txt 
	3421-NETFILTER-ctnetlink-add-marking-support-from-userspace.txt 
	3422-NETFILTER-ctnetlink-add-module-alias-to-fix-autoloading.txt 
	3423-NETFILTER-ctnetlink-kill-unused-includes.txt 
	3424-NETFILTER-ctnetlink-get_conntrack-can-use-GFP_KERNEL.txt 
	3425-NETFILTER-PPTP-helper-fix-PNS-PAC-expectation-call-id.txt 
	3426-NETFILTER-nfnetlink-only-load-subsystems-if-CAP_NET_ADMIN-is-set.txt 
	3427-NETFILTER-stop-tracking-ICMP-error-at-early-point.txt 
	3428-NETFILTER-ctnetlink-return-EINVAL-if-size-is-wrong.txt 
	3429-NETFILTER-ctnetlink-propagate-error-instaed-of-returning-EPERM.txt 
	3430-NETFILTER-ctnetlink-Add-support-to-identify-expectations-by-ID-s.txt 
	3431-NETFILTER-ctnetlink-Fix-oops-when-no-ICMP-ID-info-in-message.txt 
	3432-NETFILTER-ctnetlink-ICMP_ID-is-u_int16_t-not-u_int8_t.txt 
	3433-IPV6-Fix-fallout-from-CONFIG_IPV6_PRIVACY.txt 
	3434-IPV6-ip6ip6_lock-is-not-unlocked-in-error-path.txt 
	3447-NETFILTER-Add-nf_conntrack-subsystem.txt 
	3448-NETLINK-Type-safe-netlink-messages-attributes-interface.txt 
	3449-NETLINK-Make-netlink_callback-done-optional.txt 
	3450-NETLINK-Generic-netlink-receive-queue-processor.txt 
	3451-XFRM-Use-generic-netlink-receive-queue-processor.txt 
	3452-RTNETLINK-Use-generic-netlink-receive-queue-processor.txt 
	3453-NETLINK-Generic-netlink-family.txt 
	3454-SUNRPC-don-t-reencode-when-looping-in-call-transmit.txt 
Removed Files:
      Tag: private-linville-netdev-fc4-1-branch
	2443-DRIVER-MODEL-Fix-depca.txt 
	2444-DRIVER-MODEL-Fix-jazzsonic.txt 
	2445-DRIVER-MODEL-Fix-macsonic.txt 
	2652-uml-fix-UML-network-driver-endianness-bugs.txt 
	3069-uml_net-use-ethtool_ops.txt 
Log Message:



Index: 0085-drivers-net-fix-up-schedule_timeout-usage.txt
===================================================================
RCS file: 0085-drivers-net-fix-up-schedule_timeout-usage.txt
diff -N 0085-drivers-net-fix-up-schedule_timeout-usage.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0085-drivers-net-fix-up-schedule_timeout-usage.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,498 @@
+Subject: [PATCH] drivers/net: fix-up schedule_timeout() usage
+From: Nishanth Aravamudan <nacc us ibm com>
+Date: 1126429795 -0700
+
+Use schedule_timeout_interruptible() instead of
+set_current_state()/schedule_timeout() to reduce kernel size.
+
+Signed-off-by: Nishanth Aravamudan <nacc us ibm com>
+Cc: Jeff Garzik <jgarzik pobox com>
+Cc: "David S. Miller" <davem davemloft net>
+Signed-off-by: Andrew Morton <akpm osdl org>
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/8139cp.c                      |    3 +-
+ drivers/net/hp100.c                       |   48 ++++++++++-------------------
+ drivers/net/irda/stir4200.c               |    7 ++--
+ drivers/net/ixgb/ixgb_ethtool.c           |    7 ++--
+ drivers/net/ns83820.c                     |    3 +-
+ drivers/net/tokenring/ibmtr.c             |    9 ++---
+ drivers/net/tokenring/olympic.c           |    2 +
+ drivers/net/tokenring/tms380tr.c          |    3 +-
+ drivers/net/typhoon.c                     |    7 ++--
+ drivers/net/wan/cosa.c                    |    6 +---
+ drivers/net/wan/dscc4.c                   |    9 ++---
+ drivers/net/wan/farsync.c                 |    3 +-
+ drivers/net/wireless/ipw2100.c            |   17 ++++------
+ drivers/net/wireless/prism54/islpci_dev.c |    6 +---
+ drivers/net/wireless/prism54/islpci_mgt.c |    5 +--
+ include/linux/ibmtr.h                     |    4 +-
+ include/linux/netdevice.h                 |    6 +---
+ 17 files changed, 53 insertions(+), 92 deletions(-)
+
+applies-to: 2713fbd5e71f7a7dbe94634a1bc4eb81a1ed8af5
+3173c8907ffb2c64456142da3df2bd0500bd59e0
+diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
+index ebc20d9..bd99c26 100644
+--- a/drivers/net/8139cp.c
++++ b/drivers/net/8139cp.c
+@@ -1029,8 +1029,7 @@ static void cp_reset_hw (struct cp_priva
+ 		if (!(cpr8(Cmd) & CmdReset))
+ 			return;
+ 
+-		set_current_state(TASK_UNINTERRUPTIBLE);
+-		schedule_timeout(10);
++		schedule_timeout_uninterruptible(10);
+ 	}
+ 
+ 	printk(KERN_ERR "%s: hardware reset timeout\n", cp->dev->name);
+diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
+index cf0ac6f..b71fab6 100644
+--- a/drivers/net/hp100.c
++++ b/drivers/net/hp100.c
+@@ -2517,10 +2517,8 @@ static int hp100_down_vg_link(struct net
+ 	do {
+ 		if (hp100_inb(VG_LAN_CFG_1) & HP100_LINK_CABLE_ST)
+ 			break;
+-		if (!in_interrupt()) {
+-			set_current_state(TASK_INTERRUPTIBLE);
+-			schedule_timeout(1);
+-		}
++		if (!in_interrupt())
++			schedule_timeout_interruptible(1);
+ 	} while (time_after(time, jiffies));
+ 
+ 	if (time_after_eq(jiffies, time))	/* no signal->no logout */
+@@ -2536,10 +2534,8 @@ static int hp100_down_vg_link(struct net
+ 	do {
+ 		if (!(hp100_inb(VG_LAN_CFG_1) & HP100_LINK_UP_ST))
+ 			break;
+-		if (!in_interrupt()) {
+-			set_current_state(TASK_INTERRUPTIBLE);
+-			schedule_timeout(1);
+-		}
++		if (!in_interrupt())
++			schedule_timeout_interruptible(1);
+ 	} while (time_after(time, jiffies));
+ 
+ #ifdef HP100_DEBUG
+@@ -2577,10 +2573,8 @@ static int hp100_down_vg_link(struct net
+ 		do {
+ 			if (!(hp100_inb(MAC_CFG_4) & HP100_MAC_SEL_ST))
+ 				break;
+-			if (!in_interrupt()) {
+-				set_current_state(TASK_INTERRUPTIBLE);
+-				schedule_timeout(1);
+-			}
++			if (!in_interrupt())
++				schedule_timeout_interruptible(1);
+ 		} while (time_after(time, jiffies));
+ 
+ 		hp100_orb(HP100_AUTO_MODE, MAC_CFG_3);	/* Autosel back on */
+@@ -2591,10 +2585,8 @@ static int hp100_down_vg_link(struct net
+ 	do {
+ 		if ((hp100_inb(VG_LAN_CFG_1) & HP100_LINK_CABLE_ST) == 0)
+ 			break;
+-		if (!in_interrupt()) {
+-			set_current_state(TASK_INTERRUPTIBLE);
+-			schedule_timeout(1);
+-		}
++		if (!in_interrupt())
++			schedule_timeout_interruptible(1);
+ 	} while (time_after(time, jiffies));
+ 
+ 	if (time_before_eq(time, jiffies)) {
+@@ -2606,10 +2598,8 @@ static int hp100_down_vg_link(struct net
+ 
+ 	time = jiffies + (2 * HZ);	/* This seems to take a while.... */
+ 	do {
+-		if (!in_interrupt()) {
+-			set_current_state(TASK_INTERRUPTIBLE);
+-			schedule_timeout(1);
+-		}
++		if (!in_interrupt())
++			schedule_timeout_interruptible(1);
+ 	} while (time_after(time, jiffies));
+ 
+ 	return 0;
+@@ -2659,10 +2649,8 @@ static int hp100_login_to_vg_hub(struct 
+ 		do {
+ 			if (~(hp100_inb(VG_LAN_CFG_1) & HP100_LINK_UP_ST))
+ 				break;
+-			if (!in_interrupt()) {
+-				set_current_state(TASK_INTERRUPTIBLE);
+-				schedule_timeout(1);
+-			}
++			if (!in_interrupt())
++				schedule_timeout_interruptible(1);
+ 		} while (time_after(time, jiffies));
+ 
+ 		/* Start an addressed training and optionally request promiscuous port */
+@@ -2697,10 +2685,8 @@ static int hp100_login_to_vg_hub(struct 
+ 		do {
+ 			if (hp100_inb(VG_LAN_CFG_1) & HP100_LINK_CABLE_ST)
+ 				break;
+-			if (!in_interrupt()) {
+-				set_current_state(TASK_INTERRUPTIBLE);
+-				schedule_timeout(1);
+-			}
++			if (!in_interrupt())
++				schedule_timeout_interruptible(1);
+ 		} while (time_before(jiffies, time));
+ 
+ 		if (time_after_eq(jiffies, time)) {
+@@ -2723,10 +2709,8 @@ static int hp100_login_to_vg_hub(struct 
+ #endif
+ 					break;
+ 				}
+-				if (!in_interrupt()) {
+-					set_current_state(TASK_INTERRUPTIBLE);
+-					schedule_timeout(1);
+-				}
++				if (!in_interrupt())
++					schedule_timeout_interruptible(1);
+ 			} while (time_after(time, jiffies));
+ 		}
+ 
+diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
+index 15f2073..3961a75 100644
+--- a/drivers/net/irda/stir4200.c
++++ b/drivers/net/irda/stir4200.c
+@@ -678,10 +678,9 @@ static void turnaround_delay(const struc
+ 		return;
+ 
+ 	ticks = us / (1000000 / HZ);
+-	if (ticks > 0) {
+-		current->state = TASK_INTERRUPTIBLE;
+-		schedule_timeout(1 + ticks);
+-	} else
++	if (ticks > 0)
++		schedule_timeout_interruptible(1 + ticks);
++	else
+ 		udelay(us);
+ }
+ 
+diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
+index 319ee4c..04e4718 100644
+--- a/drivers/net/ixgb/ixgb_ethtool.c
++++ b/drivers/net/ixgb/ixgb_ethtool.c
+@@ -645,11 +645,10 @@ ixgb_phys_id(struct net_device *netdev, 
+ 
+ 	mod_timer(&adapter->blink_timer, jiffies);
+ 
+-	set_current_state(TASK_INTERRUPTIBLE);
+-	if(data)
+-		schedule_timeout(data * HZ);
++	if (data)
++		schedule_timeout_interruptible(data * HZ);
+ 	else
+-		schedule_timeout(MAX_SCHEDULE_TIMEOUT);
++		schedule_timeout_interruptible(MAX_SCHEDULE_TIMEOUT);
+ 
+ 	del_timer_sync(&adapter->blink_timer);
+ 	ixgb_led_off(&adapter->hw);
+diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
+index e64df4d..ed72a23 100644
+--- a/drivers/net/ns83820.c
++++ b/drivers/net/ns83820.c
+@@ -1632,8 +1632,7 @@ static void ns83820_run_bist(struct net_
+ 			timed_out = 1;
+ 			break;
+ 		}
+-		set_current_state(TASK_UNINTERRUPTIBLE);
+-		schedule_timeout(1);
++		schedule_timeout_uninterruptible(1);
+ 	}
+ 
+ 	if (status & fail)
+diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
+index e7b0010..8154bbb 100644
+--- a/drivers/net/tokenring/ibmtr.c
++++ b/drivers/net/tokenring/ibmtr.c
+@@ -318,7 +318,7 @@ static void ibmtr_cleanup_card(struct ne
+ 	if (dev->base_addr) {
+ 		outb(0,dev->base_addr+ADAPTRESET);
+ 		
+-		schedule_timeout(TR_RST_TIME); /* wait 50ms */
++		schedule_timeout_uninterruptible(TR_RST_TIME); /* wait 50ms */
+ 
+ 		outb(0,dev->base_addr+ADAPTRESETREL);
+ 	}
+@@ -859,8 +859,7 @@ static int tok_init_card(struct net_devi
+ 	writeb(~INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN);
+ 	outb(0, PIOaddr + ADAPTRESET);
+ 
+-	current->state=TASK_UNINTERRUPTIBLE;
+-	schedule_timeout(TR_RST_TIME); /* wait 50ms */
++	schedule_timeout_uninterruptible(TR_RST_TIME); /* wait 50ms */
+ 
+ 	outb(0, PIOaddr + ADAPTRESETREL);
+ #ifdef ENABLE_PAGING
+@@ -908,8 +907,8 @@ static int tok_open(struct net_device *d
+ 			DPRINTK("Adapter is up and running\n");
+ 			return 0;
+ 		}
+-		current->state=TASK_INTERRUPTIBLE;
+-		i=schedule_timeout(TR_RETRY_INTERVAL); /* wait 30 seconds */
++		i=schedule_timeout_interruptible(TR_RETRY_INTERVAL);
++							/* wait 30 seconds */
+ 		if(i!=0) break; /*prob. a signal, like the i>24*HZ case above */
+ 	}
+ 	outb(0, dev->base_addr + ADAPTRESET);/* kill pending interrupts*/
+diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c
+index 9e79231..05477d2 100644
+--- a/drivers/net/tokenring/olympic.c
++++ b/drivers/net/tokenring/olympic.c
+@@ -1101,7 +1101,7 @@ static int olympic_close(struct net_devi
+ 
+ 	while(olympic_priv->srb_queued) {
+ 
+-		t = schedule_timeout(60*HZ); 
++		t = schedule_timeout_interruptible(60*HZ);
+ 
+         	if(signal_pending(current))	{            
+ 			printk(KERN_WARNING "%s: SRB timed out.\n",dev->name);
+diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c
+index 2e39bf1..c192559 100644
+--- a/drivers/net/tokenring/tms380tr.c
++++ b/drivers/net/tokenring/tms380tr.c
+@@ -1243,8 +1243,7 @@ void tms380tr_wait(unsigned long time)
+ 	
+ 	tmp = jiffies + time/(1000000/HZ);
+ 	do {
+-  		current->state 		= TASK_INTERRUPTIBLE;
+-		tmp = schedule_timeout(tmp);
++		tmp = schedule_timeout_interruptible(tmp);
+ 	} while(time_after(tmp, jiffies));
+ #else
+ 	udelay(time);
+diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
+index ecfa6f8..4c76cb7 100644
+--- a/drivers/net/typhoon.c
++++ b/drivers/net/typhoon.c
+@@ -419,10 +419,9 @@ typhoon_reset(void __iomem *ioaddr, int 
+ 			   TYPHOON_STATUS_WAITING_FOR_HOST)
+ 				goto out;
+ 
+-			if(wait_type == WaitSleep) {
+-				set_current_state(TASK_UNINTERRUPTIBLE);
+-				schedule_timeout(1);
+-			} else
++			if(wait_type == WaitSleep)
++				schedule_timeout_uninterruptible(1);
++			else
+ 				udelay(TYPHOON_UDELAY);
+ 		}
+ 
+diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
+index 7ff814f..ae9e897 100644
+--- a/drivers/net/wan/cosa.c
++++ b/drivers/net/wan/cosa.c
+@@ -1617,8 +1617,7 @@ static int get_wait_data(struct cosa_dat
+ 			return r;
+ 		}
+ 		/* sleep if not ready to read */
+-		set_current_state(TASK_INTERRUPTIBLE);
+-		schedule_timeout(1);
++		schedule_timeout_interruptible(1);
+ 	}
+ 	printk(KERN_INFO "cosa: timeout in get_wait_data (status 0x%x)\n",
+ 		cosa_getstatus(cosa));
+@@ -1644,8 +1643,7 @@ static int put_wait_data(struct cosa_dat
+ 		}
+ #if 0
+ 		/* sleep if not ready to read */
+-		current->state = TASK_INTERRUPTIBLE;
+-		schedule_timeout(1);
++		schedule_timeout_interruptible(1);
+ #endif
+ 	}
+ 	printk(KERN_INFO "cosa%d: timeout in put_wait_data (status 0x%x)\n",
+diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
+index 520a77a..0c1ab4a 100644
+--- a/drivers/net/wan/dscc4.c
++++ b/drivers/net/wan/dscc4.c
+@@ -542,8 +542,7 @@ static int dscc4_wait_ack_cec(struct dsc
+ 			       msg, i);
+ 			goto done;
+ 		}
+-		set_current_state(TASK_UNINTERRUPTIBLE);
+-		schedule_timeout(10);
++		schedule_timeout_uninterruptible(10);
+ 		rmb();
+ 	} while (++i > 0);
+ 	printk(KERN_ERR "%s: %s timeout\n", dev->name, msg);
+@@ -588,8 +587,7 @@ static inline int dscc4_xpr_ack(struct d
+ 		    (dpriv->iqtx[cur] & Xpr))
+ 			break;
+ 		smp_rmb();
+-		set_current_state(TASK_UNINTERRUPTIBLE);
+-		schedule_timeout(10);
++		schedule_timeout_uninterruptible(10);
+ 	} while (++i > 0);
+ 
+ 	return (i >= 0 ) ? i : -EAGAIN;
+@@ -1035,8 +1033,7 @@ static void dscc4_pci_reset(struct pci_d
+ 	/* Flush posted writes */
+ 	readl(ioaddr + GSTAR);
+ 
+-	set_current_state(TASK_UNINTERRUPTIBLE);
+-	schedule_timeout(10);
++	schedule_timeout_uninterruptible(10);
+ 
+ 	for (i = 0; i < 16; i++)
+ 		pci_write_config_dword(pdev, i << 2, dscc4_pci_config_store[i]);
+diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
+index 2c83cca..10befb0 100644
+--- a/drivers/net/wan/farsync.c
++++ b/drivers/net/wan/farsync.c
+@@ -980,8 +980,7 @@ fst_issue_cmd(struct fst_port_info *port
+ 	/* Wait for any previous command to complete */
+ 	while (mbval > NAK) {
+ 		spin_unlock_irqrestore(&card->card_lock, flags);
+-		set_current_state(TASK_UNINTERRUPTIBLE);
+-		schedule_timeout(1);
++		schedule_timeout_uninterruptible(1);
+ 		spin_lock_irqsave(&card->card_lock, flags);
+ 
+ 		if (++safety > 2000) {
+diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
+index 2414e64..e5cdb5b 100644
+--- a/drivers/net/wireless/ipw2100.c
++++ b/drivers/net/wireless/ipw2100.c
+@@ -800,8 +800,7 @@ static int ipw2100_hw_send_command(struc
+ 	 * doesn't seem to have as many firmware restart cycles...
+ 	 *
+ 	 * As a test, we're sticking in a 1/100s delay here */
+-	set_current_state(TASK_UNINTERRUPTIBLE);
+-	schedule_timeout(HZ / 100);
++	schedule_timeout_uninterruptible(msecs_to_jiffies(10));
+ 
+ 	return 0;
+ 
+@@ -1256,8 +1255,7 @@ static int ipw2100_start_adapter(struct 
+ 	IPW_DEBUG_FW("Waiting for f/w initialization to complete...\n");
+ 	i = 5000;
+ 	do {
+-  		set_current_state(TASK_UNINTERRUPTIBLE);
+-		schedule_timeout(40 * HZ / 1000);
++		schedule_timeout_uninterruptible(msecs_to_jiffies(40));
+ 		/* Todo... wait for sync command ... */
+ 
+ 		read_register(priv->net_dev, IPW_REG_INTA, &inta);
+@@ -1411,8 +1409,7 @@ static int ipw2100_hw_phy_off(struct ipw
+ 		    (val2 & IPW2100_COMMAND_PHY_OFF))
+ 			return 0;
+ 
+-		set_current_state(TASK_UNINTERRUPTIBLE);
+-		schedule_timeout(HW_PHY_OFF_LOOP_DELAY);
++		schedule_timeout_uninterruptible(HW_PHY_OFF_LOOP_DELAY);
+ 	}
+ 
+ 	return -EIO;
+@@ -1466,7 +1463,7 @@ fail_up:
+ 
+ static int ipw2100_hw_stop_adapter(struct ipw2100_priv *priv)
+ {
+-#define HW_POWER_DOWN_DELAY (HZ / 10)
++#define HW_POWER_DOWN_DELAY (msecs_to_jiffies(100))
+ 
+ 	struct host_command cmd = {
+ 		.host_command = HOST_PRE_POWER_DOWN,
+@@ -1520,10 +1517,8 @@ static int ipw2100_hw_stop_adapter(struc
+ 			printk(KERN_WARNING DRV_NAME ": "
+ 			       "%s: Power down command failed: Error %d\n",
+ 			       priv->net_dev->name, err);
+-		else {
+-			set_current_state(TASK_UNINTERRUPTIBLE);
+-			schedule_timeout(HW_POWER_DOWN_DELAY);
+-		}
++		else
++			schedule_timeout_uninterruptible(HW_POWER_DOWN_DELAY);
+ 	}
+ 
+ 	priv->status &= ~STATUS_ENABLED;
+diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c
+index 6f13d4a..10cce51 100644
+--- a/drivers/net/wireless/prism54/islpci_dev.c
++++ b/drivers/net/wireless/prism54/islpci_dev.c
+@@ -439,8 +439,7 @@ prism54_bring_down(islpci_private *priv)
+ 	wmb();
+ 
+ 	/* wait a while for the device to reset */
+-	set_current_state(TASK_UNINTERRUPTIBLE);
+-	schedule_timeout(50*HZ/1000);
++	schedule_timeout_uninterruptible(msecs_to_jiffies(50));
+ 
+ 	return 0;
+ }
+@@ -491,8 +490,7 @@ islpci_reset_if(islpci_private *priv)
+ 		/* The software reset acknowledge needs about 220 msec here.
+ 		 * Be conservative and wait for up to one second. */
+ 	
+-		set_current_state(TASK_UNINTERRUPTIBLE);
+-		remaining = schedule_timeout(HZ);
++		remaining = schedule_timeout_uninterruptible(HZ);
+ 
+ 		if(remaining > 0) {
+ 			result = 0;
+diff --git a/drivers/net/wireless/prism54/islpci_mgt.c b/drivers/net/wireless/prism54/islpci_mgt.c
+index b6f2e5a..4937a5a 100644
+--- a/drivers/net/wireless/prism54/islpci_mgt.c
++++ b/drivers/net/wireless/prism54/islpci_mgt.c
+@@ -455,7 +455,7 @@ islpci_mgt_transaction(struct net_device
+ 		       struct islpci_mgmtframe **recvframe)
+ {
+ 	islpci_private *priv = netdev_priv(ndev);
+-	const long wait_cycle_jiffies = (ISL38XX_WAIT_CYCLE * 10 * HZ) / 1000;
++	const long wait_cycle_jiffies = msecs_to_jiffies(ISL38XX_WAIT_CYCLE * 10);
+ 	long timeout_left = ISL38XX_MAX_WAIT_CYCLES * wait_cycle_jiffies;
+ 	int err;
+ 	DEFINE_WAIT(wait);
+@@ -475,8 +475,7 @@ islpci_mgt_transaction(struct net_device
+ 		int timeleft;
+ 		struct islpci_mgmtframe *frame;
+ 
+-		set_current_state(TASK_UNINTERRUPTIBLE);
+-		timeleft = schedule_timeout(wait_cycle_jiffies);
++		timeleft = schedule_timeout_uninterruptible(wait_cycle_jiffies);
+ 		frame = xchg(&priv->mgmt_received, NULL);
+ 		if (frame) {
+ 			if (frame->header->oid == oid) {
+diff --git a/include/linux/ibmtr.h b/include/linux/ibmtr.h
+index 2ef0b21..1c7a0dd 100644
+--- a/include/linux/ibmtr.h
++++ b/include/linux/ibmtr.h
+@@ -7,8 +7,8 @@
+ /* ported to the Alpha architecture 02/20/96 (just used the HZ macro) */
+ 
+ #define TR_RETRY_INTERVAL	(30*HZ)	/* 500 on PC = 5 s */
+-#define TR_RST_TIME		(HZ/20) /* 5 on PC = 50 ms */
+-#define TR_BUSY_INTERVAL	(HZ/5)	/* 5 on PC = 200 ms */
++#define TR_RST_TIME		(msecs_to_jiffies(50))	/* 5 on PC = 50 ms */
++#define TR_BUSY_INTERVAL	(msecs_to_jiffies(200))	/* 5 on PC = 200 ms */
+ #define TR_SPIN_INTERVAL	(3*HZ)	/* 3 seconds before init timeout */
+ 
+ #define TR_ISA 1
+diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
+index 7c71790..98c98e6 100644
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -852,11 +852,9 @@ static inline void netif_rx_complete(str
+ 
+ static inline void netif_poll_disable(struct net_device *dev)
+ {
+-	while (test_and_set_bit(__LINK_STATE_RX_SCHED, &dev->state)) {
++	while (test_and_set_bit(__LINK_STATE_RX_SCHED, &dev->state))
+ 		/* No hurry. */
+-		current->state = TASK_INTERRUPTIBLE;
+-		schedule_timeout(1);
+-	}
++		schedule_timeout_interruptible(1);
+ }
+ 
+ static inline void netif_poll_enable(struct net_device *dev)
+---
+0.99.8.GIT


Index: 0089-C99-initializers-in-ray_cs.c.txt
===================================================================
RCS file: 0089-C99-initializers-in-ray_cs.c.txt
diff -N 0089-C99-initializers-in-ray_cs.c.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0089-C99-initializers-in-ray_cs.c.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,82 @@
+Subject: [PATCH] C99 initializers in ray_cs.c
+From: viro ZenIV linux org uk <viro ZenIV linux org uk>
+Date: 1126294823 +0100
+
+Signed-off-by: Al Viro <viro zeniv linux org uk>
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/ray_cs.c |   46 +++++++++++++++++++++--------------------
+ 1 files changed, 23 insertions(+), 23 deletions(-)
+
+applies-to: aa18b1e9c91b43cccc76949bba8b2c56b5b8cfed
+7a700fafbed55eee2cc766fbe47cf68e229da281
+diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
+index e9c5ea0..70fd6fd 100644
+--- a/drivers/net/wireless/ray_cs.c
++++ b/drivers/net/wireless/ray_cs.c
+@@ -1649,28 +1649,28 @@ static iw_stats * ray_get_wireless_stats
+  */
+ 
+ static const iw_handler	ray_handler[] = {
+-	[SIOCSIWCOMMIT-SIOCIWFIRST] (iw_handler) ray_commit,
+-	[SIOCGIWNAME  -SIOCIWFIRST] (iw_handler) ray_get_name,
+-	[SIOCSIWFREQ  -SIOCIWFIRST] (iw_handler) ray_set_freq,
+-	[SIOCGIWFREQ  -SIOCIWFIRST] (iw_handler) ray_get_freq,
+-	[SIOCSIWMODE  -SIOCIWFIRST] (iw_handler) ray_set_mode,
+-	[SIOCGIWMODE  -SIOCIWFIRST] (iw_handler) ray_get_mode,
+-	[SIOCGIWRANGE -SIOCIWFIRST] (iw_handler) ray_get_range,
++	[SIOCSIWCOMMIT-SIOCIWFIRST] = (iw_handler) ray_commit,
++	[SIOCGIWNAME  -SIOCIWFIRST] = (iw_handler) ray_get_name,
++	[SIOCSIWFREQ  -SIOCIWFIRST] = (iw_handler) ray_set_freq,
++	[SIOCGIWFREQ  -SIOCIWFIRST] = (iw_handler) ray_get_freq,
++	[SIOCSIWMODE  -SIOCIWFIRST] = (iw_handler) ray_set_mode,
++	[SIOCGIWMODE  -SIOCIWFIRST] = (iw_handler) ray_get_mode,
++	[SIOCGIWRANGE -SIOCIWFIRST] = (iw_handler) ray_get_range,
+ #ifdef WIRELESS_SPY
+- 	[SIOCSIWSPY   -SIOCIWFIRST] (iw_handler) iw_handler_set_spy,
+-	[SIOCGIWSPY   -SIOCIWFIRST] (iw_handler) iw_handler_get_spy,
+-	[SIOCSIWTHRSPY-SIOCIWFIRST] (iw_handler) iw_handler_set_thrspy,
+-	[SIOCGIWTHRSPY-SIOCIWFIRST] (iw_handler) iw_handler_get_thrspy,
++ 	[SIOCSIWSPY   -SIOCIWFIRST] = (iw_handler) iw_handler_set_spy,
++	[SIOCGIWSPY   -SIOCIWFIRST] = (iw_handler) iw_handler_get_spy,
++	[SIOCSIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_set_thrspy,
++	[SIOCGIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_get_thrspy,
+ #endif	/* WIRELESS_SPY */
+-	[SIOCGIWAP    -SIOCIWFIRST] (iw_handler) ray_get_wap,
+-	[SIOCSIWESSID -SIOCIWFIRST] (iw_handler) ray_set_essid,
+-	[SIOCGIWESSID -SIOCIWFIRST] (iw_handler) ray_get_essid,
+-	[SIOCSIWRATE  -SIOCIWFIRST] (iw_handler) ray_set_rate,
+-	[SIOCGIWRATE  -SIOCIWFIRST] (iw_handler) ray_get_rate,
+-	[SIOCSIWRTS   -SIOCIWFIRST] (iw_handler) ray_set_rts,
+-	[SIOCGIWRTS   -SIOCIWFIRST] (iw_handler) ray_get_rts,
+-	[SIOCSIWFRAG  -SIOCIWFIRST] (iw_handler) ray_set_frag,
+-	[SIOCGIWFRAG  -SIOCIWFIRST] (iw_handler) ray_get_frag,
++	[SIOCGIWAP    -SIOCIWFIRST] = (iw_handler) ray_get_wap,
++	[SIOCSIWESSID -SIOCIWFIRST] = (iw_handler) ray_set_essid,
++	[SIOCGIWESSID -SIOCIWFIRST] = (iw_handler) ray_get_essid,
++	[SIOCSIWRATE  -SIOCIWFIRST] = (iw_handler) ray_set_rate,
++	[SIOCGIWRATE  -SIOCIWFIRST] = (iw_handler) ray_get_rate,
++	[SIOCSIWRTS   -SIOCIWFIRST] = (iw_handler) ray_set_rts,
++	[SIOCGIWRTS   -SIOCIWFIRST] = (iw_handler) ray_get_rts,
++	[SIOCSIWFRAG  -SIOCIWFIRST] = (iw_handler) ray_set_frag,
++	[SIOCGIWFRAG  -SIOCIWFIRST] = (iw_handler) ray_get_frag,
+ };
+ 
+ #define SIOCSIPFRAMING	SIOCIWFIRSTPRIV		/* Set framing mode */
+@@ -1678,9 +1678,9 @@ static const iw_handler	ray_handler[] = 
+ #define SIOCGIPCOUNTRY	SIOCIWFIRSTPRIV + 3	/* Get country code */
+ 
+ static const iw_handler	ray_private_handler[] = {
+-	[0] (iw_handler) ray_set_framing,
+-	[1] (iw_handler) ray_get_framing,
+-	[3] (iw_handler) ray_get_country,
++	[0] = (iw_handler) ray_set_framing,
++	[1] = (iw_handler) ray_get_framing,
++	[3] = (iw_handler) ray_get_country,
+ };
+ 
+ static const struct iw_priv_args	ray_private_args[] = {
+---
+0.99.8.GIT


--- NEW FILE 0091-Add-rapidio-net-driver.txt ---
Subject: [PATCH] Add rapidio net driver
From: Matt Porter <mporter kernel crashing org>
Date: 1126293010 -0700

Adds an "Ethernet" driver which sends Ethernet packets over the standard
RapidIO messaging.  This depends on the core RIO patch for mailbox/doorbell
access.

Signed-off-by: Matt Porter <mporter kernel crashing org>
Cc: Jeff Garzik <jgarzik pobox com>
Signed-off-by: Andrew Morton <akpm osdl org>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 drivers/net/Kconfig  |   14 +
 drivers/net/Makefile |    1 
 drivers/net/rionet.c |  574 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 589 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/rionet.c

applies-to: e42008bc2e42ea42498229360f995d39357d6c62
f89efd523b25cc1702e074dafdcac283da657002
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 54fff9c..82603e4 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2235,6 +2235,20 @@ config ISERIES_VETH
 	tristate "iSeries Virtual Ethernet driver support"
 	depends on PPC_ISERIES
 
+config RIONET
+	tristate "RapidIO Ethernet over messaging driver support"
+	depends on NETDEVICES && RAPIDIO
+
+config RIONET_TX_SIZE
+	int "Number of outbound queue entries"
+	depends on RIONET
+	default "128"
+
+config RIONET_RX_SIZE
+	int "Number of inbound queue entries"
+	depends on RIONET
+	default "128"
+
 config FDDI
 	bool "FDDI driver support"
 	depends on (PCI || EISA)
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 8645c84..e6acba6 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -63,6 +63,7 @@ obj-$(CONFIG_SKFP) += skfp/
 obj-$(CONFIG_VIA_RHINE) += via-rhine.o
 obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
 obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
+obj-$(CONFIG_RIONET) += rionet.o
 
 #
 # end link order section
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
new file mode 100644
index 0000000..12cde06
--- /dev/null
+++ b/drivers/net/rionet.c
@@ -0,0 +1,574 @@
+/*
+ * rionet - Ethernet driver over RapidIO messaging services
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter kernel crashing org>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/rio.h>
+#include <linux/rio_drv.h>
+#include <linux/rio_ids.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/crc32.h>
+#include <linux/ethtool.h>
+
+#define DRV_NAME        "rionet"
+#define DRV_VERSION     "0.2"
+#define DRV_AUTHOR      "Matt Porter <mporter kernel crashing org>"
+#define DRV_DESC        "Ethernet over RapidIO"
+
+MODULE_AUTHOR(DRV_AUTHOR);
+MODULE_DESCRIPTION(DRV_DESC);
+MODULE_LICENSE("GPL");
+
+#define RIONET_DEFAULT_MSGLEVEL \
+			(NETIF_MSG_DRV          | \
+			 NETIF_MSG_LINK         | \
+			 NETIF_MSG_RX_ERR       | \
+			 NETIF_MSG_TX_ERR)
+
+#define RIONET_DOORBELL_JOIN	0x1000
+#define RIONET_DOORBELL_LEAVE	0x1001
+
+#define RIONET_MAILBOX		0
+
+#define RIONET_TX_RING_SIZE	CONFIG_RIONET_TX_SIZE
+#define RIONET_RX_RING_SIZE	CONFIG_RIONET_RX_SIZE
+
+static LIST_HEAD(rionet_peers);
+
+struct rionet_private {
+	struct rio_mport *mport;
+	struct sk_buff *rx_skb[RIONET_RX_RING_SIZE];
+	struct sk_buff *tx_skb[RIONET_TX_RING_SIZE];
+	struct net_device_stats stats;
+	int rx_slot;
+	int tx_slot;
+	int tx_cnt;
+	int ack_slot;
+	spinlock_t lock;
+	spinlock_t tx_lock;
+	u32 msg_enable;
+};
+
+struct rionet_peer {
+	struct list_head node;
+	struct rio_dev *rdev;
+	struct resource *res;
+};
+
+static int rionet_check = 0;
+static int rionet_capable = 1;
+
+/*
+ * This is a fast lookup table for for translating TX
+ * Ethernet packets into a destination RIO device. It
+ * could be made into a hash table to save memory depending
+ * on system trade-offs.
+ */
+static struct rio_dev *rionet_active[RIO_MAX_ROUTE_ENTRIES];
+
+#define is_rionet_capable(pef, src_ops, dst_ops)		\
+			((pef & RIO_PEF_INB_MBOX) &&		\
+			 (pef & RIO_PEF_INB_DOORBELL) &&	\
+			 (src_ops & RIO_SRC_OPS_DOORBELL) &&	\
+			 (dst_ops & RIO_DST_OPS_DOORBELL))
+#define dev_rionet_capable(dev) \
+	is_rionet_capable(dev->pef, dev->src_ops, dev->dst_ops)
+
+#define RIONET_MAC_MATCH(x)	(*(u32 *)x == 0x00010001)
+#define RIONET_GET_DESTID(x)	(*(u16 *)(x + 4))
+
+static struct net_device_stats *rionet_stats(struct net_device *ndev)
+{
+	struct rionet_private *rnet = ndev->priv;
+	return &rnet->stats;
+}
+
+static int rionet_rx_clean(struct net_device *ndev)
+{
+	int i;
+	int error = 0;
+	struct rionet_private *rnet = ndev->priv;
+	void *data;
+
+	i = rnet->rx_slot;
+
+	do {
+		if (!rnet->rx_skb[i])
+			continue;
+
+		if (!(data = rio_get_inb_message(rnet->mport, RIONET_MAILBOX)))
+			break;
+
+		rnet->rx_skb[i]->data = data;
+		skb_put(rnet->rx_skb[i], RIO_MAX_MSG_SIZE);
+		rnet->rx_skb[i]->dev = ndev;
+		rnet->rx_skb[i]->protocol =
+		    eth_type_trans(rnet->rx_skb[i], ndev);
+		error = netif_rx(rnet->rx_skb[i]);
+
+		if (error == NET_RX_DROP) {
+			rnet->stats.rx_dropped++;
+		} else if (error == NET_RX_BAD) {
+			if (netif_msg_rx_err(rnet))
+				printk(KERN_WARNING "%s: bad rx packet\n",
+				       DRV_NAME);
+			rnet->stats.rx_errors++;
+		} else {
+			rnet->stats.rx_packets++;
+			rnet->stats.rx_bytes += RIO_MAX_MSG_SIZE;
+		}
+
+	} while ((i = (i + 1) % RIONET_RX_RING_SIZE) != rnet->rx_slot);
+
+	return i;
+}
+
+static void rionet_rx_fill(struct net_device *ndev, int end)
+{
+	int i;
+	struct rionet_private *rnet = ndev->priv;
+
+	i = rnet->rx_slot;
+	do {
+		rnet->rx_skb[i] = dev_alloc_skb(RIO_MAX_MSG_SIZE);
+
+		if (!rnet->rx_skb[i])
+			break;
+
+		rio_add_inb_buffer(rnet->mport, RIONET_MAILBOX,
+				   rnet->rx_skb[i]->data);
+	} while ((i = (i + 1) % RIONET_RX_RING_SIZE) != end);
+
+	rnet->rx_slot = i;
+}
+
+static int rionet_queue_tx_msg(struct sk_buff *skb, struct net_device *ndev,
+			       struct rio_dev *rdev)
+{
+	struct rionet_private *rnet = ndev->priv;
+
+	rio_add_outb_message(rnet->mport, rdev, 0, skb->data, skb->len);
+	rnet->tx_skb[rnet->tx_slot] = skb;
+
+	rnet->stats.tx_packets++;
+	rnet->stats.tx_bytes += skb->len;
+
+	if (++rnet->tx_cnt == RIONET_TX_RING_SIZE)
+		netif_stop_queue(ndev);
+
+	++rnet->tx_slot;
+	rnet->tx_slot &= (RIONET_TX_RING_SIZE - 1);
+
+	if (netif_msg_tx_queued(rnet))
+		printk(KERN_INFO "%s: queued skb %8.8x len %8.8x\n", DRV_NAME,
+		       (u32) skb, skb->len);
+
+	return 0;
+}
+
+static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+	int i;
+	struct rionet_private *rnet = ndev->priv;
+	struct ethhdr *eth = (struct ethhdr *)skb->data;
+	u16 destid;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	if (!spin_trylock(&rnet->tx_lock)) {
+		local_irq_restore(flags);
+		return NETDEV_TX_LOCKED;
+	}
+
+	if ((rnet->tx_cnt + 1) > RIONET_TX_RING_SIZE) {
+		netif_stop_queue(ndev);
+		spin_unlock_irqrestore(&rnet->tx_lock, flags);
+		printk(KERN_ERR "%s: BUG! Tx Ring full when queue awake!\n",
+		       ndev->name);
+		return NETDEV_TX_BUSY;
+	}
+
+	if (eth->h_dest[0] & 0x01) {
+		for (i = 0; i < RIO_MAX_ROUTE_ENTRIES; i++)
+			if (rionet_active[i])
+				rionet_queue_tx_msg(skb, ndev,
+						    rionet_active[i]);
+	} else if (RIONET_MAC_MATCH(eth->h_dest)) {
+		destid = RIONET_GET_DESTID(eth->h_dest);
+		if (rionet_active[destid])
+			rionet_queue_tx_msg(skb, ndev, rionet_active[destid]);
+	}
+
+	spin_unlock_irqrestore(&rnet->tx_lock, flags);
+
+	return 0;
+}
+
+static void rionet_dbell_event(struct rio_mport *mport, void *dev_id, u16 sid, u16 tid,
+			       u16 info)
+{
+	struct net_device *ndev = dev_id;
+	struct rionet_private *rnet = ndev->priv;
+	struct rionet_peer *peer;
+
+	if (netif_msg_intr(rnet))
+		printk(KERN_INFO "%s: doorbell sid %4.4x tid %4.4x info %4.4x",
+		       DRV_NAME, sid, tid, info);
+	if (info == RIONET_DOORBELL_JOIN) {
+		if (!rionet_active[sid]) {
+			list_for_each_entry(peer, &rionet_peers, node) {
+				if (peer->rdev->destid == sid)
+					rionet_active[sid] = peer->rdev;
+			}
+			rio_mport_send_doorbell(mport, sid,
+						RIONET_DOORBELL_JOIN);
+		}
+	} else if (info == RIONET_DOORBELL_LEAVE) {
+		rionet_active[sid] = NULL;
+	} else {
+		if (netif_msg_intr(rnet))
+			printk(KERN_WARNING "%s: unhandled doorbell\n",
+			       DRV_NAME);
+	}
+}
+
+static void rionet_inb_msg_event(struct rio_mport *mport, void *dev_id, int mbox, int slot)
+{
+	int n;
+	struct net_device *ndev = dev_id;
+	struct rionet_private *rnet = (struct rionet_private *)ndev->priv;
+
+	if (netif_msg_intr(rnet))
+		printk(KERN_INFO "%s: inbound message event, mbox %d slot %d\n",
+		       DRV_NAME, mbox, slot);
+
+	spin_lock(&rnet->lock);
+	if ((n = rionet_rx_clean(ndev)) != rnet->rx_slot)
+		rionet_rx_fill(ndev, n);
+	spin_unlock(&rnet->lock);
+}
+
+static void rionet_outb_msg_event(struct rio_mport *mport, void *dev_id, int mbox, int slot)
+{
+	struct net_device *ndev = dev_id;
+	struct rionet_private *rnet = ndev->priv;
+
+	spin_lock(&rnet->lock);
+
+	if (netif_msg_intr(rnet))
+		printk(KERN_INFO
+		       "%s: outbound message event, mbox %d slot %d\n",
+		       DRV_NAME, mbox, slot);
+
+	while (rnet->tx_cnt && (rnet->ack_slot != slot)) {
+		/* dma unmap single */
+		dev_kfree_skb_irq(rnet->tx_skb[rnet->ack_slot]);
+		rnet->tx_skb[rnet->ack_slot] = NULL;
+		++rnet->ack_slot;
+		rnet->ack_slot &= (RIONET_TX_RING_SIZE - 1);
+		rnet->tx_cnt--;
+	}
+
+	if (rnet->tx_cnt < RIONET_TX_RING_SIZE)
+		netif_wake_queue(ndev);
+
+	spin_unlock(&rnet->lock);
+}
+
+static int rionet_open(struct net_device *ndev)
+{
+	int i, rc = 0;
+	struct rionet_peer *peer, *tmp;
+	u32 pwdcsr;
+	struct rionet_private *rnet = ndev->priv;
+
+	if (netif_msg_ifup(rnet))
+		printk(KERN_INFO "%s: open\n", DRV_NAME);
+
+	if ((rc = rio_request_inb_dbell(rnet->mport,
+					(void *)ndev,
+					RIONET_DOORBELL_JOIN,
+					RIONET_DOORBELL_LEAVE,
+					rionet_dbell_event)) < 0)
+		goto out;
+
+	if ((rc = rio_request_inb_mbox(rnet->mport,
+				       (void *)ndev,
+				       RIONET_MAILBOX,
+				       RIONET_RX_RING_SIZE,
+				       rionet_inb_msg_event)) < 0)
+		goto out;
+
+	if ((rc = rio_request_outb_mbox(rnet->mport,
+					(void *)ndev,
+					RIONET_MAILBOX,
+					RIONET_TX_RING_SIZE,
+					rionet_outb_msg_event)) < 0)
+		goto out;
+
+	/* Initialize inbound message ring */
+	for (i = 0; i < RIONET_RX_RING_SIZE; i++)
+		rnet->rx_skb[i] = NULL;
+	rnet->rx_slot = 0;
+	rionet_rx_fill(ndev, 0);
+
+	rnet->tx_slot = 0;
+	rnet->tx_cnt = 0;
+	rnet->ack_slot = 0;
+
+	netif_carrier_on(ndev);
+	netif_start_queue(ndev);
+
+	list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
+		if (!(peer->res = rio_request_outb_dbell(peer->rdev,
+							 RIONET_DOORBELL_JOIN,
+							 RIONET_DOORBELL_LEAVE)))
+		{
+			printk(KERN_ERR "%s: error requesting doorbells\n",
+			       DRV_NAME);
+			continue;
+		}
+
+		/*
+		 * If device has initialized inbound doorbells,
+		 * send a join message
+		 */
+		rio_read_config_32(peer->rdev, RIO_WRITE_PORT_CSR, &pwdcsr);
+		if (pwdcsr & RIO_DOORBELL_AVAIL)
+			rio_send_doorbell(peer->rdev, RIONET_DOORBELL_JOIN);
+	}
+
+      out:
+	return rc;
+}
+
+static int rionet_close(struct net_device *ndev)
+{
+	struct rionet_private *rnet = (struct rionet_private *)ndev->priv;
+	struct rionet_peer *peer, *tmp;
+	int i;
+
+	if (netif_msg_ifup(rnet))
+		printk(KERN_INFO "%s: close\n", DRV_NAME);
+
+	netif_stop_queue(ndev);
+	netif_carrier_off(ndev);
+
+	for (i = 0; i < RIONET_RX_RING_SIZE; i++)
+		if (rnet->rx_skb[i])
+			kfree_skb(rnet->rx_skb[i]);
+
+	list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
+		if (rionet_active[peer->rdev->destid]) {
+			rio_send_doorbell(peer->rdev, RIONET_DOORBELL_LEAVE);
+			rionet_active[peer->rdev->destid] = NULL;
+		}
+		rio_release_outb_dbell(peer->rdev, peer->res);
+	}
+
+	rio_release_inb_dbell(rnet->mport, RIONET_DOORBELL_JOIN,
+			      RIONET_DOORBELL_LEAVE);
+	rio_release_inb_mbox(rnet->mport, RIONET_MAILBOX);
+	rio_release_outb_mbox(rnet->mport, RIONET_MAILBOX);
+
+	return 0;
+}
+
+static void rionet_remove(struct rio_dev *rdev)
+{
+	struct net_device *ndev = NULL;
+	struct rionet_peer *peer, *tmp;
+
+	unregister_netdev(ndev);
+	kfree(ndev);
+
+	list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
+		list_del(&peer->node);
+		kfree(peer);
+	}
+}
+
+static void rionet_get_drvinfo(struct net_device *ndev,
+			       struct ethtool_drvinfo *info)
+{
+	struct rionet_private *rnet = ndev->priv;
+
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	strcpy(info->fw_version, "n/a");
+	strcpy(info->bus_info, rnet->mport->name);
+}
+
+static u32 rionet_get_msglevel(struct net_device *ndev)
+{
+	struct rionet_private *rnet = ndev->priv;
+
+	return rnet->msg_enable;
+}
+
+static void rionet_set_msglevel(struct net_device *ndev, u32 value)
+{
+	struct rionet_private *rnet = ndev->priv;
+
+	rnet->msg_enable = value;
+}
+
+static struct ethtool_ops rionet_ethtool_ops = {
+	.get_drvinfo = rionet_get_drvinfo,
+	.get_msglevel = rionet_get_msglevel,
+	.set_msglevel = rionet_set_msglevel,
+	.get_link = ethtool_op_get_link,
+};
+
+static int rionet_setup_netdev(struct rio_mport *mport)
+{
+	int rc = 0;
+	struct net_device *ndev = NULL;
+	struct rionet_private *rnet;
+	u16 device_id;
+
+	/* Allocate our net_device structure */
+	ndev = alloc_etherdev(sizeof(struct rionet_private));
+	if (ndev == NULL) {
+		printk(KERN_INFO "%s: could not allocate ethernet device.\n",
+		       DRV_NAME);
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	/* Set up private area */
+	rnet = (struct rionet_private *)ndev->priv;
+	rnet->mport = mport;
+
+	/* Set the default MAC address */
+	device_id = rio_local_get_device_id(mport);
+	ndev->dev_addr[0] = 0x00;
+	ndev->dev_addr[1] = 0x01;
+	ndev->dev_addr[2] = 0x00;
+	ndev->dev_addr[3] = 0x01;
+	ndev->dev_addr[4] = device_id >> 8;
+	ndev->dev_addr[5] = device_id & 0xff;
+
+	/* Fill in the driver function table */
+	ndev->open = &rionet_open;
+	ndev->hard_start_xmit = &rionet_start_xmit;
+	ndev->stop = &rionet_close;
+	ndev->get_stats = &rionet_stats;
+	ndev->mtu = RIO_MAX_MSG_SIZE - 14;
+	ndev->features = NETIF_F_LLTX;
+	SET_ETHTOOL_OPS(ndev, &rionet_ethtool_ops);
+
+	SET_MODULE_OWNER(ndev);
+
+	spin_lock_init(&rnet->lock);
+	spin_lock_init(&rnet->tx_lock);
+
+	rnet->msg_enable = RIONET_DEFAULT_MSGLEVEL;
+
+	rc = register_netdev(ndev);
+	if (rc != 0)
+		goto out;
+
+	printk("%s: %s %s Version %s, MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       ndev->name,
+	       DRV_NAME,
+	       DRV_DESC,
+	       DRV_VERSION,
+	       ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2],
+	       ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]);
+
+      out:
+	return rc;
+}
+
+/*
+ * XXX Make multi-net safe
+ */
+static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id)
+{
+	int rc = -ENODEV;
+	u32 lpef, lsrc_ops, ldst_ops;
+	struct rionet_peer *peer;
+
+	/* If local device is not rionet capable, give up quickly */
+	if (!rionet_capable)
+		goto out;
+
+	/*
+	 * First time through, make sure local device is rionet
+	 * capable, setup netdev,  and set flags so this is skipped
+	 * on later probes
+	 */
+	if (!rionet_check) {
+		rio_local_read_config_32(rdev->net->hport, RIO_PEF_CAR, &lpef);
+		rio_local_read_config_32(rdev->net->hport, RIO_SRC_OPS_CAR,
+					 &lsrc_ops);
+		rio_local_read_config_32(rdev->net->hport, RIO_DST_OPS_CAR,
+					 &ldst_ops);
+		if (!is_rionet_capable(lpef, lsrc_ops, ldst_ops)) {
+			printk(KERN_ERR
+			       "%s: local device is not network capable\n",
+			       DRV_NAME);
+			rionet_check = 1;
+			rionet_capable = 0;
+			goto out;
+		}
+
+		rc = rionet_setup_netdev(rdev->net->hport);
+		rionet_check = 1;
+	}
+
+	/*
+	 * If the remote device has mailbox/doorbell capabilities,
+	 * add it to the peer list.
+	 */
+	if (dev_rionet_capable(rdev)) {
+		if (!(peer = kmalloc(sizeof(struct rionet_peer), GFP_KERNEL))) {
+			rc = -ENOMEM;
+			goto out;
+		}
+		peer->rdev = rdev;
+		list_add_tail(&peer->node, &rionet_peers);
+	}
+
+      out:
+	return rc;
+}
+
+static struct rio_device_id rionet_id_table[] = {
+	{RIO_DEVICE(RIO_ANY_ID, RIO_ANY_ID)}
+};
+
+static struct rio_driver rionet_driver = {
+	.name = "rionet",
+	.id_table = rionet_id_table,
+	.probe = rionet_probe,
+	.remove = rionet_remove,
+};
+
+static int __init rionet_init(void)
+{
+	return rio_register_driver(&rionet_driver);
+}
+
+static void __exit rionet_exit(void)
+{
+	rio_unregister_driver(&rionet_driver);
+}
+
+module_init(rionet_init);
+module_exit(rionet_exit);
---
0.99.8.GIT


Index: 0101-orinoco-Remove-conditionals-that-are-useless-in-the-kernel-drivers.txt
===================================================================
RCS file: 0101-orinoco-Remove-conditionals-that-are-useless-in-the-kernel-drivers.txt
diff -N 0101-orinoco-Remove-conditionals-that-are-useless-in-the-kernel-drivers.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0101-orinoco-Remove-conditionals-that-are-useless-in-the-kernel-drivers.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,108 @@
+Subject: [PATCH] orinoco: Remove conditionals that are useless in the kernel drivers.
+From: Pavel Roskin <proski gnu org>
+Date: 1126851313 -0400
+
+Author: Pavel Roskin <proski gnu org>
+Date:   Fri Sep 16 00:49:05 2005 -0400
+
+    Remove conditionals that are useless in the kernel drivers.
+
+    Kernel drivers are never compiled against pcmcia-cs headers.
+    Firmware is never embedded into spectrum_cs module.
+
+Signed-off-by: Pavel Roskin <proski gnu org>
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/orinoco_cs.c  |    3 ---
+ drivers/net/wireless/spectrum_cs.c |   26 +-------------------------
+ 2 files changed, 1 insertions(+), 28 deletions(-)
+
+applies-to: 173b55358f0864026fe9957407409f8613448ed4
+65853b133d0256786df25f03eea0e5a6799e8d17
+diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
+index bedd7f9..1cedabf 100644
+--- a/drivers/net/wireless/orinoco_cs.c
++++ b/drivers/net/wireless/orinoco_cs.c
+@@ -14,9 +14,6 @@
+ #define PFX DRIVER_NAME ": "
+ 
+ #include <linux/config.h>
+-#ifdef  __IN_PCMCIA_PACKAGE__
+-#include <pcmcia/k_compat.h>
+-#endif /* __IN_PCMCIA_PACKAGE__ */
+ 
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
+index 39c6cdf..256d31b 100644
+--- a/drivers/net/wireless/spectrum_cs.c
++++ b/drivers/net/wireless/spectrum_cs.c
+@@ -22,9 +22,6 @@
+ #define PFX DRIVER_NAME ": "
+ 
+ #include <linux/config.h>
+-#ifdef  __IN_PCMCIA_PACKAGE__
+-#include <pcmcia/k_compat.h>
+-#endif /* __IN_PCMCIA_PACKAGE__ */
+ 
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+@@ -38,6 +35,7 @@
+ #include <linux/if_arp.h>
+ #include <linux/etherdevice.h>
+ #include <linux/wireless.h>
++#include <linux/firmware.h>
+ 
+ #include <pcmcia/cs_types.h>
+ #include <pcmcia/cs.h>
+@@ -51,29 +49,10 @@
+ 
+ #include "orinoco.h"
+ 
+-/*
+- * If SPECTRUM_FW_INCLUDED is defined, the firmware is hardcoded into
+- * the driver.  Use get_symbol_fw script to generate spectrum_fw.h and
+- * copy it to the same directory as spectrum_cs.c.
+- *
+- * If SPECTRUM_FW_INCLUDED is not defined, the firmware is loaded at the
+- * runtime using hotplug.  Use the same get_symbol_fw script to generate
+- * files symbol_sp24t_prim_fw symbol_sp24t_sec_fw, copy them to the
+- * hotplug firmware directory (typically /usr/lib/hotplug/firmware) and
+- * make sure that you have hotplug installed and enabled in the kernel.
+- */
+-/* #define SPECTRUM_FW_INCLUDED 1 */
+-
+-#ifdef SPECTRUM_FW_INCLUDED
+-/* Header with the firmware */
+-#include "spectrum_fw.h"
+-#else	/* !SPECTRUM_FW_INCLUDED */
+-#include <linux/firmware.h>
+ static unsigned char *primsym;
+ static unsigned char *secsym;
+ static const char primary_fw_name[] = "symbol_sp24t_prim_fw";
+ static const char secondary_fw_name[] = "symbol_sp24t_sec_fw";
+-#endif	/* !SPECTRUM_FW_INCLUDED */
+ 
+ /********************************************************************/
+ /* Module stuff							    */
+@@ -571,8 +550,6 @@ spectrum_dl_firmware(hermes_t *hw, dev_l
+ {
+ 	int ret;
+ 	client_handle_t handle = link->handle;
+-
+-#ifndef SPECTRUM_FW_INCLUDED
+ 	const struct firmware *fw_entry;
+ 
+ 	if (request_firmware(&fw_entry, primary_fw_name,
+@@ -592,7 +569,6 @@ spectrum_dl_firmware(hermes_t *hw, dev_l
+ 		       secondary_fw_name);
+ 		return -ENOENT;
+ 	}
+-#endif
+ 
+ 	/* Load primary firmware */
+ 	ret = spectrum_dl_image(hw, link, primsym);
+---
+0.99.8.GIT


Index: 0102-orinoco-Don-t-include-net-ieee80211.h-twice.txt
===================================================================
RCS file: 0102-orinoco-Don-t-include-net-ieee80211.h-twice.txt
diff -N 0102-orinoco-Don-t-include-net-ieee80211.h-twice.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0102-orinoco-Don-t-include-net-ieee80211.h-twice.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,34 @@
+Subject: [PATCH] orinoco: Don't include <net/ieee80211.h> twice.
+From: Pavel Roskin <proski gnu org>
+Date: 1126851412 -0400
+
+Author: Pavel Roskin <proski gnu org>
+Date:   Fri Sep 16 00:50:00 2005 -0400
+
+    Don't include <net/ieee80211.h> twice.
+
+Signed-off-by: Pavel Roskin <proski gnu org>
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/orinoco.c |    2 --
+ 1 files changed, 0 insertions(+), 2 deletions(-)
+
+applies-to: 38c3d8007e70992829271a2fcf453624d4afadd2
+27c91efba4c121f90c0e6d371c7064733b286a69
+diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
+index 639b8e4..77e93a2 100644
+--- a/drivers/net/wireless/orinoco.c
++++ b/drivers/net/wireless/orinoco.c
+@@ -94,8 +94,6 @@
+ #include <net/iw_handler.h>
+ #include <net/ieee80211.h>
+ 
+-#include <net/ieee80211.h>
+-
+ #include <asm/uaccess.h>
+ #include <asm/io.h>
+ #include <asm/system.h>
+---
+0.99.8.GIT


Index: 0103-orinoco-Update-PCMCIA-ID-s.txt
===================================================================
RCS file: 0103-orinoco-Update-PCMCIA-ID-s.txt
diff -N 0103-orinoco-Update-PCMCIA-ID-s.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0103-orinoco-Update-PCMCIA-ID-s.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,156 @@
+Subject: [PATCH] orinoco: Update PCMCIA ID's.
+From: Pavel Roskin <proski gnu org>
+Date: 1126851511 -0400
+
+Author: Pavel Roskin <proski gnu org>
+Date:   Fri Sep 16 01:07:47 2005 -0400
+
+    Update PCMCIA ID's.
+
+    Intel Pro/Wireless 2011 and 2011B have the same numeric ID, so use
+    strings instead.
+
+    Take all entries from *.conf for Orinoco, HostAP and linux-wlan-ng and
+    adds them with minimal changes (e.g. we don't need a revision string
+    after a string that identifies the chipset).
+
+    Add comments with card names to all numeric entries.  Note: the comments
+    don't and cannot cover all cards, since the main reason of having
+    numeric IDs is to cover cards that are often rebranded.
+
+Signed-off-by: Pavel Roskin <proski gnu org>
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/orinoco_cs.c  |   76 +++++++++++++++++++++++++++---------
+ drivers/net/wireless/spectrum_cs.c |    2 -
+ 2 files changed, 57 insertions(+), 21 deletions(-)
+
+applies-to: 78dd96949dcb026a37f182255db3d804a4274706
+9c8a11d7c2298680ff3ee8acda54575c88668bfc
+diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
+index 1cedabf..80920b1 100644
+--- a/drivers/net/wireless/orinoco_cs.c
++++ b/drivers/net/wireless/orinoco_cs.c
+@@ -600,49 +600,85 @@ static char version[] __initdata = DRIVE
+ 	"Pavel Roskin <proski gnu org>, et al)";
+ 
+ static struct pcmcia_device_id orinoco_cs_ids[] = {
+-	PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300),
+-	PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002),
+-	PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002),
+-	PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a),
+-	PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002),
+-	PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001),
+-	PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305),
+-	PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613),
+-	PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002),
+-	PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673),
+-	PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002),
+-	PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002),
+-	PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001),
+-	PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300),
+-	PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021),
+-	PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002),
+-	PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002),
+-	PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005),
++	PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), /* SonicWALL Long Range Wireless Card */
++	PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), /* Sohoware NCP110, Philips 802.11b */
++	PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), /* AnyPoint(TM) Wireless II PC Card */
++	PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), /* 3Com AirConnect PCI 777A */
++	PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000), /* PROXIM RangeLAN-DS/LAN PC CARD */
++	PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), /* Compaq WL100 11 Mbps Wireless Adapter */
++	PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), /* Lucent Orinoco and old Intersil */
++	PCMCIA_DEVICE_MANF_CARD(0x016b, 0x0001), /* Ericsson WLAN Card C11 */
++	PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a), /* Nortel Networks eMobility 802.11 Wireless Adapter */
++	PCMCIA_DEVICE_MANF_CARD(0x01ff, 0x0008), /* Intermec MobileLAN 11Mbps 802.11b WLAN Card */
++	PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */
++	PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002), /* AirWay 802.11 Adapter (PCMCIA) */
++	PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001), /* ARtem Onair */
++	PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305), /* Buffalo WLI-PCM-S11 */
++	PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */
++	PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */
++	PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), /* Compaq HNW-100 11 Mbps Wireless Adapter */
++	PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), /* Linksys WCF12 Wireless CompactFlash Card */
++	PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002), /* ASUS SpaceLink WL-100 */
++	PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002), /* SpeedStream SS1021 Wireless Adapter */
++	PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001), /* PLANEX RoadLannerWave GW-NS11H */
++	PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), /* Airvast WN-100 */
++	PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), /* Adaptec Ultra Wireless ANW-8030 */
++	PCMCIA_DEVICE_MANF_CARD(0xc001, 0x0008), /* CONTEC FLEXSCAN/FX-DDS110-PCC */
++	PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), /* Conceptronic CON11Cpro, EMTAC A2424i */
++	PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), /* Safeway 802.11b, ZCOMAX AirRunner/XI-300 */
++	PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), /* D-Link DCF660, Sandisk Connect SDWCFB-000 */
++	PCMCIA_DEVICE_PROD_ID12(" ", "IEEE 802.11 Wireless LAN/PC Card", 0x3b6e20c8, 0xefccafe9),
+ 	PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3),
+-	PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0),
+ 	PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5),
++	PCMCIA_DEVICE_PROD_ID12("Addtron", "AWP-100 Wireless PCMCIA", 0xe6ec52ce, 0x08649af2),
++	PCMCIA_DEVICE_PROD_ID123("AIRVAST", "IEEE 802.11b Wireless PCMCIA Card", "HFA3863", 0xea569531, 0x4bcb9645, 0x355cb092),
++	PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f),
++	PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842),
++	PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e),
+ 	PCMCIA_DEVICE_PROD_ID12("Avaya Communication", "Avaya Wireless PC Card", 0xd8a43b78, 0x0d341169),
++	PCMCIA_DEVICE_PROD_ID12("BENQ", "AWL100 PCMCIA ADAPTER", 0x35dadc74, 0x01f7fedb),
+ 	PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3),
++	PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18),
+ 	PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90),
++	PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 0x54f7c49c, 0x15a75e5b),
++	PCMCIA_DEVICE_PROD_ID123("corega", "WL PCCL-11", "ISL37300P", 0x0a21501a, 0x59868926, 0xc9049a39),
+ 	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584),
+ 	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9),
+ 	PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae),
+ 	PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac),
+ 	PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab),
++	PCMCIA_DEVICE_PROD_ID12("D-Link Corporation", "D-Link DWL-650H 11Mbps WLAN Adapter", 0xef544d24, 0xcd8ea916),
++	PCMCIA_DEVICE_PROD_ID12("Digital Data Communications", "WPC-0100", 0xfdd73470, 0xe0b6f146),
+ 	PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3),
+ 	PCMCIA_DEVICE_PROD_ID12("HyperLink", "Wireless PC Card 11Mbps", 0x56cc3f1a, 0x0bcf220c),
++	PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0),
++	PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless 2011 LAN PC Card", 0x816cc815, 0x07f58077),
+ 	PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18),
++	PCMCIA_DEVICE_PROD_ID12("INTERSIL", "I-GATE 11M PC Card / PC Card plus", 0x74c5e40d, 0x8304ff77),
++	PCMCIA_DEVICE_PROD_ID12("Intersil", "PRISM 2_5 PCMCIA ADAPTER", 0x4b801a17, 0x6345a0bf),
++	PCMCIA_DEVICE_PROD_ID123("Intersil", "PRISM Freedom PCMCIA Adapter", "ISL37100P", 0x4b801a17, 0xf222ec2d, 0x630d52b2),
++	PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92),
++	PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 0x0733cc81, 0x0c52f395),
+ 	PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a),
+ 	PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11", 0x481e0094, 0x7360e410),
+ 	PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11G", 0x481e0094, 0xf57ca4b3),
+ 	PCMCIA_DEVICE_PROD_ID12("Microsoft", "Wireless Notebook Adapter MN-520", 0x5961bf85, 0x6eec8c01),
+ 	PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/IEEE", 0x24358cd4, 0xc562e72a),
++	PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401 Wireless PC", "Card", 0xa37434e9, 0x9762e8f1),
+ 	PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401RA Wireless PC", "Card", 0x0306467f, 0x9762e8f1),
++	PCMCIA_DEVICE_PROD_ID12("Nortel Networks", "emobility 802.11 Wireless LAN PC Card", 0x2d617ea0, 0x88cd5767),
++	PCMCIA_DEVICE_PROD_ID12("OEM", "PRISM2 IEEE 802.11 PC-Card", 0xfea54c90, 0x48f2bdd6),
++	PCMCIA_DEVICE_PROD_ID12("OTC", "Wireless AirEZY 2411-PCC WLAN Card", 0x4ac44287, 0x235a6bed),
++	PCMCIA_DEVICE_PROD_ID123("PCMCIA", "11M WLAN Card v2.5", "ISL37300P", 0x281f1c5d, 0x6e440487, 0xc9049a39),
+ 	PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-CF110", 0x209f40ab, 0xd9715264),
++	PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178),
+ 	PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9),
+ 	PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26),
+ 	PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b),
+-	PCMCIA_DEVICE_PROD_ID1("Symbol Technologies", 0x3f02b4d6),
++	PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a),
++	PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e),
++	PCMCIA_DEVICE_PROD_ID123("The Linksys Group, Inc.", "Instant Wireless Network PC Card", "ISL37300P", 0xa5f472c2, 0x590eb502, 0xc9049a39),
++	PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee),
+ 	PCMCIA_DEVICE_NULL,
+ };
+ MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids);
+diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
+index 256d31b..63e0042 100644
+--- a/drivers/net/wireless/spectrum_cs.c
++++ b/drivers/net/wireless/spectrum_cs.c
+@@ -1061,7 +1061,7 @@ static char version[] __initdata = DRIVE
+ static struct pcmcia_device_id spectrum_cs_ids[] = {
+ 	PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4100 */
+ 	PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0001), /* Socket Communications CF */
+-	PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0001), /* Intel PRO/Wireless 2011B */
++	PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless LAN PC Card", 0x816cc815, 0x6fbf459a), /* 2011B, not 2011 */
+ 	PCMCIA_DEVICE_NULL,
+ };
+ MODULE_DEVICE_TABLE(pcmcia, spectrum_cs_ids);
+---
+0.99.8.GIT


--- NEW FILE 0104-Fixed-some-endian-issues-with-802.11-header-usage-in-ieee80211_rx.c.txt ---
Subject: [PATCH] Fixed some endian issues with 802.11 header usage in ieee80211_rx.c
From: James Ketrenos <jketreno linux intel com>
Date: 1126650351 -0500

Fixed some endian issues with 802.11 header usage in ieee80211_rx.c

Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 net/ieee80211/ieee80211_rx.c |   43 +++++++++++++++++++++++++-----------------
 1 files changed, 26 insertions(+), 17 deletions(-)

applies-to: a183ce73c486bfe86ea5e96e9619f2088784bbae
fd27817ce941c7134adefd2852f8a5f274315ff4
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index f7dcd85..74c4ed7 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -787,11 +787,11 @@ static inline int ieee80211_network_init
 
 	/* Pull out fixed field data */
 	memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
-	network->capability = beacon->capability;
+	network->capability = le16_to_cpu(beacon->capability);
 	network->last_scanned = jiffies;
-	network->time_stamp[0] = beacon->time_stamp[0];
-	network->time_stamp[1] = beacon->time_stamp[1];
-	network->beacon_interval = beacon->beacon_interval;
+	network->time_stamp[0] = le32_to_cpu(beacon->time_stamp[0]);
+	network->time_stamp[1] = le32_to_cpu(beacon->time_stamp[1]);
+	network->beacon_interval = le16_to_cpu(beacon->beacon_interval);
 	/* Where to pull this? beacon->listen_interval; */
 	network->listen_interval = 0x0A;
 	network->rates_len = network->rates_ex_len = 0;
@@ -1070,8 +1070,9 @@ static inline void ieee80211_process_pro
 				     escape_essid(info_element->data,
 						  info_element->len),
 				     MAC_ARG(beacon->header.addr3),
-				     WLAN_FC_GET_STYPE(beacon->header.
-						       frame_ctl) ==
+				     WLAN_FC_GET_STYPE(le16_to_cpu
+						       (beacon->header.
+							frame_ctl)) ==
 				     IEEE80211_STYPE_PROBE_RESP ?
 				     "PROBE RESPONSE" : "BEACON");
 		return;
@@ -1122,8 +1123,9 @@ static inline void ieee80211_process_pro
 				     escape_essid(network.ssid,
 						  network.ssid_len),
 				     MAC_ARG(network.bssid),
-				     WLAN_FC_GET_STYPE(beacon->header.
-						       frame_ctl) ==
+				     WLAN_FC_GET_STYPE(le16_to_cpu
+						       (beacon->header.
+							frame_ctl)) ==
 				     IEEE80211_STYPE_PROBE_RESP ?
 				     "PROBE RESPONSE" : "BEACON");
 #endif
@@ -1134,8 +1136,9 @@ static inline void ieee80211_process_pro
 				     escape_essid(target->ssid,
 						  target->ssid_len),
 				     MAC_ARG(target->bssid),
-				     WLAN_FC_GET_STYPE(beacon->header.
-						       frame_ctl) ==
+				     WLAN_FC_GET_STYPE(le16_to_cpu
+						       (beacon->header.
+							frame_ctl)) ==
 				     IEEE80211_STYPE_PROBE_RESP ?
 				     "PROBE RESPONSE" : "BEACON");
 		update_network(target, &network);
@@ -1148,20 +1151,23 @@ void ieee80211_rx_mgt(struct ieee80211_d
 		      struct ieee80211_hdr *header,
 		      struct ieee80211_rx_stats *stats)
 {
-	switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
+	switch (WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl))) {
 	case IEEE80211_STYPE_ASSOC_RESP:
 		IEEE80211_DEBUG_MGMT("received ASSOCIATION RESPONSE (%d)\n",
-				     WLAN_FC_GET_STYPE(header->frame_ctl));
+				     WLAN_FC_GET_STYPE(le16_to_cpu
+						       (header->frame_ctl)));
 		break;
 
 	case IEEE80211_STYPE_REASSOC_RESP:
 		IEEE80211_DEBUG_MGMT("received REASSOCIATION RESPONSE (%d)\n",
-				     WLAN_FC_GET_STYPE(header->frame_ctl));
+				     WLAN_FC_GET_STYPE(le16_to_cpu
+						       (header->frame_ctl)));
 		break;
 
 	case IEEE80211_STYPE_PROBE_RESP:
 		IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n",
-				     WLAN_FC_GET_STYPE(header->frame_ctl));
+				     WLAN_FC_GET_STYPE(le16_to_cpu
+						       (header->frame_ctl)));
 		IEEE80211_DEBUG_SCAN("Probe response\n");
 		ieee80211_process_probe_response(ieee,
 						 (struct
@@ -1171,7 +1177,8 @@ void ieee80211_rx_mgt(struct ieee80211_d
 
 	case IEEE80211_STYPE_BEACON:
 		IEEE80211_DEBUG_MGMT("received BEACON (%d)\n",
-				     WLAN_FC_GET_STYPE(header->frame_ctl));
+				     WLAN_FC_GET_STYPE(le16_to_cpu
+						       (header->frame_ctl)));
 		IEEE80211_DEBUG_SCAN("Beacon\n");
 		ieee80211_process_probe_response(ieee,
 						 (struct
@@ -1181,10 +1188,12 @@ void ieee80211_rx_mgt(struct ieee80211_d
 
 	default:
 		IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n",
-				     WLAN_FC_GET_STYPE(header->frame_ctl));
+				     WLAN_FC_GET_STYPE(le16_to_cpu
+						       (header->frame_ctl)));
 		IEEE80211_WARNING("%s: Unknown management packet: %d\n",
 				  ieee->dev->name,
-				  WLAN_FC_GET_STYPE(header->frame_ctl));
+				  WLAN_FC_GET_STYPE(le16_to_cpu
+						    (header->frame_ctl)));
 		break;
 	}
 }
---
0.99.8.GIT


--- NEW FILE 0105-ieee80211-quality-scaling-algorithm-extension-handler.txt ---
Subject: [PATCH] ieee80211 quality scaling algorithm extension handler
From: James Ketrenos <jketreno linux intel com>
Date: 1126650439 -0500

Incorporated Bill Moss' quality scaling algorithm into default wireless
extension handler.

Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/net/ieee80211.h      |    3 +++
 net/ieee80211/ieee80211_wx.c |   40 ++++++++++++++++++++++++++++++----------
 2 files changed, 33 insertions(+), 10 deletions(-)

applies-to: 152c2194e03c104bb34fc105494ee5238f31acb9
b1b508e1b13529b3cc5b59c352f49b9b58a302b6
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index dc36b1b..ce966b7 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -719,6 +719,9 @@ struct ieee80211_device {
 	int freq_band;  /* 2.4Ghz, 5.2Ghz, Mixed */
 	int abg_ture;   /* ABG flag              */
 
+	int perfect_rssi;
+	int worst_rssi;
+
 	/* Callback functions */
 	void (*set_security)(struct net_device *dev,
 			     struct ieee80211_security *sec);
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index 94882f3..04f0897 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -140,18 +140,38 @@ static inline char *ipw2100_translate_sc
 		start = iwe_stream_add_point(start, stop, &iwe, custom);
 
 	/* Add quality statistics */
-	/* TODO: Fix these values... */
 	iwe.cmd = IWEVQUAL;
-	iwe.u.qual.qual = network->stats.signal;
-	iwe.u.qual.level = network->stats.rssi;
-	iwe.u.qual.noise = network->stats.noise;
-	iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK;
-	if (!(network->stats.mask & IEEE80211_STATMASK_RSSI))
-		iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
-	if (!(network->stats.mask & IEEE80211_STATMASK_NOISE))
+	iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
+	    IW_QUAL_NOISE_UPDATED;
+
+	if (!(network->stats.mask & IEEE80211_STATMASK_RSSI)) {
+		iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID |
+		    IW_QUAL_LEVEL_INVALID;
+		iwe.u.qual.qual = 0;
+		iwe.u.qual.level = 0;
+	} else {
+		iwe.u.qual.level = network->stats.rssi;
+		iwe.u.qual.qual =
+		    (100 *
+		     (ieee->perfect_rssi - ieee->worst_rssi) *
+		     (ieee->perfect_rssi - ieee->worst_rssi) -
+		     (ieee->perfect_rssi - network->stats.rssi) *
+		     (15 * (ieee->perfect_rssi - ieee->worst_rssi) +
+		      62 * (ieee->perfect_rssi - network->stats.rssi))) /
+		    ((ieee->perfect_rssi - ieee->worst_rssi) *
+		     (ieee->perfect_rssi - ieee->worst_rssi));
+		if (iwe.u.qual.qual > 100)
+			iwe.u.qual.qual = 100;
+		else if (iwe.u.qual.qual < 1)
+			iwe.u.qual.qual = 0;
+	}
+
+	if (!(network->stats.mask & IEEE80211_STATMASK_NOISE)) {
 		iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
-	if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL))
-		iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
+		iwe.u.qual.noise = 0;
+	} else {
+		iwe.u.qual.noise = network->stats.noise;
+	}
 
 	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN);
 
---
0.99.8.GIT


--- NEW FILE 0106-ieee80211-Added-wireless-spy-support.txt ---
Subject: [PATCH] ieee80211 Added wireless spy support
From: James Ketrenos <jketreno linux intel com>
Date: 1126650921 -0500

Added wireless spy support to Rx code path.

Signed-off-by: James Ketrenos <jketreno linux intel com>

NOTE:  Looks like scripts/Lindent generated output different
than the Lindented version already in-kernel, hence all the
whitespace deltas...  *sigh*
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/net/ieee80211.h              |  109 ++++++++++++++--------------------
 include/net/ieee80211_crypt.h        |   24 ++++---
 net/ieee80211/ieee80211_crypt.c      |   24 ++++---
 net/ieee80211/ieee80211_crypt_ccmp.c |   26 ++++----
 net/ieee80211/ieee80211_crypt_tkip.c |   26 ++++----
 net/ieee80211/ieee80211_crypt_wep.c  |   26 ++++----
 net/ieee80211/ieee80211_rx.c         |   43 ++++++++-----
 7 files changed, 134 insertions(+), 144 deletions(-)

applies-to: 6321572a9bca16928b57e936376af616a1868dc0
74079fdce472a2b16d502fe39e06b135ef06c69b
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index ce966b7..d8bb8f7 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -20,8 +20,8 @@
  */
 #ifndef IEEE80211_H
 #define IEEE80211_H
-#include <linux/if_ether.h> /* ETH_ALEN */
-#include <linux/kernel.h>   /* ARRAY_SIZE */
+#include <linux/if_ether.h>	/* ETH_ALEN */
+#include <linux/kernel.h>	/* ARRAY_SIZE */
 #include <linux/wireless.h>
 
 #define IEEE80211_DATA_LEN		2304
@@ -33,7 +33,6 @@
    represents the 2304 bytes of real data, plus a possible 8 bytes of
    WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */
 
-
 #define IEEE80211_HLEN			30
 #define IEEE80211_FRAME_LEN		(IEEE80211_DATA_LEN + IEEE80211_HLEN)
 
@@ -117,7 +116,6 @@ struct ieee80211_hdr_3addr {
 #define IEEE80211_SCTL_FRAG		0x000F
 #define IEEE80211_SCTL_SEQ		0xFFF0
 
-
 /* debug macros */
 
 #ifdef CONFIG_IEEE80211_DEBUG
@@ -128,8 +126,7 @@ do { if (ieee80211_debug_level & (level)
          in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
 #else
 #define IEEE80211_DEBUG(level, fmt, args...) do {} while (0)
-#endif	/* CONFIG_IEEE80211_DEBUG */
-
+#endif				/* CONFIG_IEEE80211_DEBUG */
 
 /* debug macros not dependent on CONFIG_IEEE80211_DEBUG */
 
@@ -140,7 +137,6 @@ do { if (ieee80211_debug_level & (level)
  * messages. It should never be used for passing essid to user space. */
 const char *escape_essid(const char *essid, u8 essid_len);
 
-
 /*
  * To use the debug system:
  *
@@ -192,7 +188,7 @@ const char *escape_essid(const char *ess
 #define IEEE80211_DEBUG_RX(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a)
 #include <linux/netdevice.h>
 #include <linux/wireless.h>
-#include <linux/if_arp.h> /* ARPHRD_ETHER */
+#include <linux/if_arp.h>	/* ARPHRD_ETHER */
 
 #ifndef WIRELESS_SPY
 #define WIRELESS_SPY		/* enable iwspy support */
@@ -200,10 +196,10 @@ const char *escape_essid(const char *ess
 #include <net/iw_handler.h>	/* new driver API */
 
 #ifndef ETH_P_PAE
-#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
-#endif /* ETH_P_PAE */
+#define ETH_P_PAE 0x888E	/* Port Access Entity (IEEE 802.1X) */
+#endif				/* ETH_P_PAE */
 
-#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */
+#define ETH_P_PREAUTH 0x88C7	/* IEEE 802.11i pre-authentication */
 
 #ifndef ETH_P_80211_RAW
 #define ETH_P_80211_RAW (ETH_P_ECONET + 1)
@@ -215,10 +211,10 @@ const char *escape_essid(const char *ess
 
 struct ieee80211_snap_hdr {
 
-        u8    dsap;   /* always 0xAA */
-        u8    ssap;   /* always 0xAA */
-        u8    ctrl;   /* always 0x03 */
-        u8    oui[P80211_OUI_LEN];    /* organizational universal id */
+	u8 dsap;		/* always 0xAA */
+	u8 ssap;		/* always 0xAA */
+	u8 ctrl;		/* always 0x03 */
+	u8 oui[P80211_OUI_LEN];	/* organizational universal id */
 
 } __attribute__ ((packed));
 
@@ -312,14 +308,12 @@ enum ieee80211_reasoncode {
 	WLAN_REASON_CIPHER_SUITE_REJECTED = 24,
 };
 
-
 #define IEEE80211_STATMASK_SIGNAL (1<<0)
 #define IEEE80211_STATMASK_RSSI (1<<1)
 #define IEEE80211_STATMASK_NOISE (1<<2)
 #define IEEE80211_STATMASK_RATE (1<<3)
 #define IEEE80211_STATMASK_WEMASK 0x7
 
-
 #define IEEE80211_CCK_MODULATION    (1<<0)
 #define IEEE80211_OFDM_MODULATION   (1<<1)
 
@@ -377,9 +371,6 @@ enum ieee80211_reasoncode {
 #define IEEE80211_NUM_CCK_RATES	            4
 #define IEEE80211_OFDM_SHIFT_MASK_A         4
 
-
-
-
 /* NOTE: This data is for statistical purposes; not all hardware provides this
  *       information for frames received.  Not setting these will not cause
  *       any adverse affects. */
@@ -388,7 +379,7 @@ struct ieee80211_rx_stats {
 	s8 rssi;
 	u8 signal;
 	u8 noise;
-	u16 rate; /* in 100 kbps */
+	u16 rate;		/* in 100 kbps */
 	u8 received_channel;
 	u8 control;
 	u8 mask;
@@ -449,28 +440,24 @@ struct ieee80211_device;
 #define SEC_LEVEL         (1<<7)
 #define SEC_ENABLED       (1<<8)
 
-#define SEC_LEVEL_0      0 /* None */
-#define SEC_LEVEL_1      1 /* WEP 40 and 104 bit */
-#define SEC_LEVEL_2      2 /* Level 1 + TKIP */
-#define SEC_LEVEL_2_CKIP 3 /* Level 1 + CKIP */
-#define SEC_LEVEL_3      4 /* Level 2 + CCMP */
+#define SEC_LEVEL_0      0	/* None */
+#define SEC_LEVEL_1      1	/* WEP 40 and 104 bit */
+#define SEC_LEVEL_2      2	/* Level 1 + TKIP */
+#define SEC_LEVEL_2_CKIP 3	/* Level 1 + CKIP */
+#define SEC_LEVEL_3      4	/* Level 2 + CCMP */
 
 #define WEP_KEYS 4
 #define WEP_KEY_LEN 13
 
 struct ieee80211_security {
 	u16 active_key:2,
-            enabled:1,
-	    auth_mode:2,
-            auth_algo:4,
-            unicast_uses_group:1;
+	    enabled:1, auth_mode:2, auth_algo:4, unicast_uses_group:1;
 	u8 key_sizes[WEP_KEYS];
 	u8 keys[WEP_KEYS][WEP_KEY_LEN];
 	u8 level;
 	u16 flags;
 } __attribute__ ((packed));
 
-
 /*
 
  802.11 data frame from AP
@@ -494,7 +481,7 @@ enum ieee80211_mfie {
 	MFIE_TYPE_RATES = 1,
 	MFIE_TYPE_FH_SET = 2,
 	MFIE_TYPE_DS_SET = 3,
-	MFIE_TYPE_CF_SET =  4,
+	MFIE_TYPE_CF_SET = 4,
 	MFIE_TYPE_TIM = 5,
 	MFIE_TYPE_IBSS_SET = 6,
 	MFIE_TYPE_COUNTRY = 7,
@@ -554,7 +541,6 @@ struct ieee80211_authentication {
 	struct ieee80211_info_element info_element;
 } __attribute__ ((packed));
 
-
 struct ieee80211_probe_response {
 	struct ieee80211_hdr_3addr header;
 	u32 time_stamp[2];
@@ -575,10 +561,9 @@ struct ieee80211_assoc_response_frame {
 	__le16 capability;
 	__le16 status;
 	__le16 aid;
-	struct ieee80211_info_element info_element; /* supported rates */
+	struct ieee80211_info_element info_element;	/* supported rates */
 } __attribute__ ((packed));
 
-
 struct ieee80211_txb {
 	u8 nr_frags;
 	u8 encrypted;
@@ -588,7 +573,6 @@ struct ieee80211_txb {
 	struct sk_buff *fragments[0];
 };
 
-
 /* SWEEP TABLE ENTRIES NUMBER */
 #define MAX_SWEEP_TAB_ENTRIES		  42
 #define MAX_SWEEP_TAB_ENTRIES_PER_PACKET  7
@@ -651,7 +635,6 @@ enum ieee80211_state {
 #define DEFAULT_MAX_SCAN_AGE (15 * HZ)
 #define DEFAULT_FTS 2346
 
-
 #define CFG_IEEE80211_RESERVE_FCS (1<<0)
 #define CFG_IEEE80211_COMPUTE_FCS (1<<1)
 
@@ -669,24 +652,25 @@ struct ieee80211_device {
 	int scans;
 	int scan_age;
 
-	int iw_mode; /* operating mode (IW_MODE_*) */
+	int iw_mode;		/* operating mode (IW_MODE_*) */
+	struct iw_spy_data spy_data;	/* iwspy support */
 
 	spinlock_t lock;
 
-	int tx_headroom; /* Set to size of any additional room needed at front
-			  * of allocated Tx SKBs */
+	int tx_headroom;	/* Set to size of any additional room needed at front
+				 * of allocated Tx SKBs */
 	u32 config;
 
 	/* WEP and other encryption related settings at the device level */
-	int open_wep; /* Set to 1 to allow unencrypted frames */
+	int open_wep;		/* Set to 1 to allow unencrypted frames */
 
-	int reset_on_keychange; /* Set to 1 if the HW needs to be reset on
+	int reset_on_keychange;	/* Set to 1 if the HW needs to be reset on
 				 * WEP key changes */
 
 	/* If the host performs {en,de}cryption, then set to 1 */
 	int host_encrypt;
 	int host_decrypt;
-	int ieee802_1x; /* is IEEE 802.1X used */
+	int ieee802_1x;		/* is IEEE 802.1X used */
 
 	/* WPA data */
 	int wpa_enabled;
@@ -698,36 +682,36 @@ struct ieee80211_device {
 
 	struct list_head crypt_deinit_list;
 	struct ieee80211_crypt_data *crypt[WEP_KEYS];
-	int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */
+	int tx_keyidx;		/* default TX key index (crypt[tx_keyidx]) */
 	struct timer_list crypt_deinit_timer;
 
-	int bcrx_sta_key; /* use individual keys to override default keys even
-			   * with RX of broad/multicast frames */
+	int bcrx_sta_key;	/* use individual keys to override default keys even
+				 * with RX of broad/multicast frames */
 
 	/* Fragmentation structures */
 	struct ieee80211_frag_entry frag_cache[IEEE80211_FRAG_CACHE_LEN];
 	unsigned int frag_next_idx;
-	u16 fts; /* Fragmentation Threshold */
+	u16 fts;		/* Fragmentation Threshold */
 
 	/* Association info */
 	u8 bssid[ETH_ALEN];
 
 	enum ieee80211_state state;
 
-	int mode;       /* A, B, G */
-	int modulation; /* CCK, OFDM */
-	int freq_band;  /* 2.4Ghz, 5.2Ghz, Mixed */
-	int abg_ture;   /* ABG flag              */
+	int mode;		/* A, B, G */
+	int modulation;		/* CCK, OFDM */
+	int freq_band;		/* 2.4Ghz, 5.2Ghz, Mixed */
+	int abg_ture;		/* ABG flag              */
 
 	int perfect_rssi;
 	int worst_rssi;
 
 	/* Callback functions */
-	void (*set_security)(struct net_device *dev,
-			     struct ieee80211_security *sec);
-	int (*hard_start_xmit)(struct ieee80211_txb *txb,
-			       struct net_device *dev);
-	int (*reset_port)(struct net_device *dev);
+	void (*set_security) (struct net_device * dev,
+			      struct ieee80211_security * sec);
+	int (*hard_start_xmit) (struct ieee80211_txb * txb,
+				struct net_device * dev);
+	int (*reset_port) (struct net_device * dev);
 
 	/* This must be the last item so that it points to the data
 	 * allocated beyond this structure by alloc_ieee80211 */
@@ -760,7 +744,8 @@ extern inline int ieee80211_is_empty_ess
 	return 1;
 }
 
-extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mode)
+extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee,
+					  int mode)
 {
 	/*
 	 * It is possible for both access points and our device to support
@@ -811,8 +796,6 @@ extern inline int ieee80211_get_hdrlen(u
 	return hdrlen;
 }
 
-
-
 /* ieee80211.c */
 extern void free_ieee80211(struct net_device *dev);
 extern struct net_device *alloc_ieee80211(int sizeof_priv);
@@ -820,11 +803,9 @@ extern struct net_device *alloc_ieee8021
 extern int ieee80211_set_encryption(struct ieee80211_device *ieee);
 
 /* ieee80211_tx.c */
-extern int ieee80211_xmit(struct sk_buff *skb,
-			  struct net_device *dev);
+extern int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev);
 extern void ieee80211_txb_free(struct ieee80211_txb *);
 
-
 /* ieee80211_rx.c */
 extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 			struct ieee80211_rx_stats *rx_stats);
@@ -843,7 +824,6 @@ extern int ieee80211_wx_get_encode(struc
 				   struct iw_request_info *info,
 				   union iwreq_data *wrqu, char *key);
 
-
 extern inline void ieee80211_increment_scans(struct ieee80211_device *ieee)
 {
 	ieee->scans++;
@@ -854,5 +834,4 @@ extern inline int ieee80211_get_scans(st
 	return ieee->scans;
 }
 
-
-#endif /* IEEE80211_H */
+#endif				/* IEEE80211_H */
diff --git a/include/net/ieee80211_crypt.h b/include/net/ieee80211_crypt.h
index b58a3bc..93bf91f 100644
--- a/include/net/ieee80211_crypt.h
+++ b/include/net/ieee80211_crypt.h
@@ -31,10 +31,10 @@ struct ieee80211_crypto_ops {
 	/* init new crypto context (e.g., allocate private data space,
 	 * select IV, etc.); returns NULL on failure or pointer to allocated
 	 * private data on success */
-	void * (*init)(int keyidx);
+	void *(*init) (int keyidx);
 
 	/* deinitialize crypto context and free allocated private data */
-	void (*deinit)(void *priv);
+	void (*deinit) (void *priv);
 
 	/* encrypt/decrypt return < 0 on error or >= 0 on success. The return
 	 * value from decrypt_mpdu is passed as the keyidx value for
@@ -42,21 +42,21 @@ struct ieee80211_crypto_ops {
 	 * encryption; if not, error will be returned; these functions are
 	 * called for all MPDUs (i.e., fragments).
 	 */
-	int (*encrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
-	int (*decrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
+	int (*encrypt_mpdu) (struct sk_buff * skb, int hdr_len, void *priv);
+	int (*decrypt_mpdu) (struct sk_buff * skb, int hdr_len, void *priv);
 
 	/* These functions are called for full MSDUs, i.e. full frames.
 	 * These can be NULL if full MSDU operations are not needed. */
-	int (*encrypt_msdu)(struct sk_buff *skb, int hdr_len, void *priv);
-	int (*decrypt_msdu)(struct sk_buff *skb, int keyidx, int hdr_len,
-			    void *priv);
+	int (*encrypt_msdu) (struct sk_buff * skb, int hdr_len, void *priv);
+	int (*decrypt_msdu) (struct sk_buff * skb, int keyidx, int hdr_len,
+			     void *priv);
 
-	int (*set_key)(void *key, int len, u8 *seq, void *priv);
-	int (*get_key)(void *key, int len, u8 *seq, void *priv);
+	int (*set_key) (void *key, int len, u8 * seq, void *priv);
+	int (*get_key) (void *key, int len, u8 * seq, void *priv);
 
 	/* procfs handler for printing out key information and possible
 	 * statistics */
-	char * (*print_stats)(char *p, void *priv);
+	char *(*print_stats) (char *p, void *priv);
 
 	/* maximum number of bytes added by encryption; encrypt buf is
 	 * allocated with extra_prefix_len bytes, copy of in_buf, and
@@ -69,7 +69,7 @@ struct ieee80211_crypto_ops {
 };
 
 struct ieee80211_crypt_data {
-	struct list_head list; /* delayed deletion list */
+	struct list_head list;	/* delayed deletion list */
 	struct ieee80211_crypto_ops *ops;
 	void *priv;
 	atomic_t refcnt;
@@ -77,7 +77,7 @@ struct ieee80211_crypt_data {
 
 int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops);
 int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops);
-struct ieee80211_crypto_ops * ieee80211_get_crypto_ops(const char *name);
+struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name);
 void ieee80211_crypt_deinit_entries(struct ieee80211_device *, int);
 void ieee80211_crypt_deinit_handler(unsigned long);
 void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
diff --git a/net/ieee80211/ieee80211_crypt.c b/net/ieee80211/ieee80211_crypt.c
index 61a9d92..dc835f6 100644
--- a/net/ieee80211/ieee80211_crypt.c
+++ b/net/ieee80211/ieee80211_crypt.c
@@ -191,18 +191,18 @@ static void ieee80211_crypt_null_deinit(
 }
 
 static struct ieee80211_crypto_ops ieee80211_crypt_null = {
-	.name			= "NULL",
-	.init			= ieee80211_crypt_null_init,
-	.deinit			= ieee80211_crypt_null_deinit,
-	.encrypt_mpdu		= NULL,
-	.decrypt_mpdu		= NULL,
-	.encrypt_msdu		= NULL,
-	.decrypt_msdu		= NULL,
-	.set_key		= NULL,
-	.get_key		= NULL,
-	.extra_prefix_len	= 0,
-	.extra_postfix_len	= 0,
-	.owner			= THIS_MODULE,
+	.name = "NULL",
+	.init = ieee80211_crypt_null_init,
+	.deinit = ieee80211_crypt_null_deinit,
+	.encrypt_mpdu = NULL,
+	.decrypt_mpdu = NULL,
+	.encrypt_msdu = NULL,
+	.decrypt_msdu = NULL,
+	.set_key = NULL,
+	.get_key = NULL,
+	.extra_prefix_len = 0,
+	.extra_postfix_len = 0,
+	.owner = THIS_MODULE,
 };
 
 static int __init ieee80211_crypto_init(void)
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c
index 8fc13f4..7b62908 100644
--- a/net/ieee80211/ieee80211_crypt_ccmp.c
+++ b/net/ieee80211/ieee80211_crypt_ccmp.c
@@ -426,19 +426,19 @@ static char *ieee80211_ccmp_print_stats(
 }
 
 static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = {
-	.name			= "CCMP",
-	.init			= ieee80211_ccmp_init,
-	.deinit			= ieee80211_ccmp_deinit,
-	.encrypt_mpdu		= ieee80211_ccmp_encrypt,
-	.decrypt_mpdu		= ieee80211_ccmp_decrypt,
-	.encrypt_msdu		= NULL,
-	.decrypt_msdu		= NULL,
-	.set_key		= ieee80211_ccmp_set_key,
-	.get_key		= ieee80211_ccmp_get_key,
-	.print_stats		= ieee80211_ccmp_print_stats,
-	.extra_prefix_len	= CCMP_HDR_LEN,
-	.extra_postfix_len	= CCMP_MIC_LEN,
-	.owner			= THIS_MODULE,
+	.name = "CCMP",
+	.init = ieee80211_ccmp_init,
+	.deinit = ieee80211_ccmp_deinit,
+	.encrypt_mpdu = ieee80211_ccmp_encrypt,
+	.decrypt_mpdu = ieee80211_ccmp_decrypt,
+	.encrypt_msdu = NULL,
+	.decrypt_msdu = NULL,
+	.set_key = ieee80211_ccmp_set_key,
+	.get_key = ieee80211_ccmp_get_key,
+	.print_stats = ieee80211_ccmp_print_stats,
+	.extra_prefix_len = CCMP_HDR_LEN,
+	.extra_postfix_len = CCMP_MIC_LEN,
+	.owner = THIS_MODULE,
 };
 
 static int __init ieee80211_crypto_ccmp_init(void)
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c
index d4f9164..dca380e 100644
--- a/net/ieee80211/ieee80211_crypt_tkip.c
+++ b/net/ieee80211/ieee80211_crypt_tkip.c
@@ -654,19 +654,19 @@ static char *ieee80211_tkip_print_stats(
 }
 
 static struct ieee80211_crypto_ops ieee80211_crypt_tkip = {
-	.name			= "TKIP",
-	.init			= ieee80211_tkip_init,
-	.deinit			= ieee80211_tkip_deinit,
-	.encrypt_mpdu		= ieee80211_tkip_encrypt,
-	.decrypt_mpdu		= ieee80211_tkip_decrypt,
-	.encrypt_msdu		= ieee80211_michael_mic_add,
-	.decrypt_msdu		= ieee80211_michael_mic_verify,
-	.set_key		= ieee80211_tkip_set_key,
-	.get_key		= ieee80211_tkip_get_key,
-	.print_stats		= ieee80211_tkip_print_stats,
-	.extra_prefix_len	= 4 + 4,	/* IV + ExtIV */
-	.extra_postfix_len	= 8 + 4,	/* MIC + ICV */
-	.owner			= THIS_MODULE,
+	.name = "TKIP",
+	.init = ieee80211_tkip_init,
+	.deinit = ieee80211_tkip_deinit,
+	.encrypt_mpdu = ieee80211_tkip_encrypt,
+	.decrypt_mpdu = ieee80211_tkip_decrypt,
+	.encrypt_msdu = ieee80211_michael_mic_add,
+	.decrypt_msdu = ieee80211_michael_mic_verify,
+	.set_key = ieee80211_tkip_set_key,
+	.get_key = ieee80211_tkip_get_key,
+	.print_stats = ieee80211_tkip_print_stats,
+	.extra_prefix_len = 4 + 4,	/* IV + ExtIV */
+	.extra_postfix_len = 8 + 4,	/* MIC + ICV */
+	.owner = THIS_MODULE,
 };
 
 static int __init ieee80211_crypto_tkip_init(void)
diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c
index b4d2514..ebe1615 100644
--- a/net/ieee80211/ieee80211_crypt_wep.c
+++ b/net/ieee80211/ieee80211_crypt_wep.c
@@ -229,19 +229,19 @@ static char *prism2_wep_print_stats(char
 }
 
 static struct ieee80211_crypto_ops ieee80211_crypt_wep = {
-	.name			= "WEP",
-	.init			= prism2_wep_init,
-	.deinit			= prism2_wep_deinit,
-	.encrypt_mpdu		= prism2_wep_encrypt,
-	.decrypt_mpdu		= prism2_wep_decrypt,
-	.encrypt_msdu		= NULL,
-	.decrypt_msdu		= NULL,
-	.set_key		= prism2_wep_set_key,
-	.get_key		= prism2_wep_get_key,
-	.print_stats		= prism2_wep_print_stats,
-	.extra_prefix_len	= 4,	/* IV */
-	.extra_postfix_len	= 4,	/* ICV */
-	.owner			= THIS_MODULE,
+	.name = "WEP",
+	.init = prism2_wep_init,
+	.deinit = prism2_wep_deinit,
+	.encrypt_mpdu = prism2_wep_encrypt,
+	.decrypt_mpdu = prism2_wep_decrypt,
+	.encrypt_msdu = NULL,
+	.decrypt_msdu = NULL,
+	.set_key = prism2_wep_set_key,
+	.get_key = prism2_wep_get_key,
+	.print_stats = prism2_wep_print_stats,
+	.extra_prefix_len = 4,	/* IV */
+	.extra_postfix_len = 4,	/* ICV */
+	.owner = THIS_MODULE,
 };
 
 static int __init ieee80211_crypto_wep_init(void)
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 74c4ed7..6bbaa44 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -378,33 +378,47 @@ int ieee80211_rx(struct ieee80211_device
 	frag = WLAN_GET_SEQ_FRAG(sc);
 	hdrlen = ieee80211_get_hdrlen(fc);
 
-#ifdef NOT_YET
-#if WIRELESS_EXT > 15
 	/* Put this code here so that we avoid duplicating it in all
 	 * Rx paths. - Jean II */
 #ifdef IW_WIRELESS_SPY		/* defined in iw_handler.h */
 	/* If spy monitoring on */
-	if (iface->spy_data.spy_number > 0) {
+	if (ieee->spy_data.spy_number > 0) {
 		struct iw_quality wstats;
-		wstats.level = rx_stats->signal;
-		wstats.noise = rx_stats->noise;
-		wstats.updated = 6;	/* No qual value */
+
+		wstats.updated = 0;
+		if (rx_stats->mask & IEEE80211_STATMASK_RSSI) {
+			wstats.level = rx_stats->rssi;
+			wstats.updated |= IW_QUAL_LEVEL_UPDATED;
+		} else
+			wstats.updated |= IW_QUAL_LEVEL_INVALID;
+
+		if (rx_stats->mask & IEEE80211_STATMASK_NOISE) {
+			wstats.noise = rx_stats->noise;
+			wstats.updated |= IW_QUAL_NOISE_UPDATED;
+		} else
+			wstats.updated |= IW_QUAL_NOISE_INVALID;
+
+		if (rx_stats->mask & IEEE80211_STATMASK_SIGNAL) {
+			wstats.qual = rx_stats->signal;
+			wstats.updated |= IW_QUAL_QUAL_UPDATED;
+		} else
+			wstats.updated |= IW_QUAL_QUAL_INVALID;
+
 		/* Update spy records */
-		wireless_spy_update(dev, hdr->addr2, &wstats);
+		wireless_spy_update(ieee->dev, hdr->addr2, &wstats);
 	}
 #endif				/* IW_WIRELESS_SPY */
-#endif				/* WIRELESS_EXT > 15 */
+
+#ifdef NOT_YET
 	hostap_update_rx_stats(local->ap, hdr, rx_stats);
 #endif
 
-#if WIRELESS_EXT > 15
 	if (ieee->iw_mode == IW_MODE_MONITOR) {
 		ieee80211_monitor_rx(ieee, skb, rx_stats);
 		stats->rx_packets++;
 		stats->rx_bytes += skb->len;
 		return 1;
 	}
-#endif
 
 	if (ieee->host_decrypt) {
 		int idx = 0;
@@ -771,8 +785,7 @@ static inline int ieee80211_is_ofdm_rate
 	return 0;
 }
 
-static inline int ieee80211_network_init(struct ieee80211_device *ieee,
-					 struct ieee80211_probe_response
+static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response
 					 *beacon,
 					 struct ieee80211_network *network,
 					 struct ieee80211_rx_stats *stats)
@@ -1028,11 +1041,9 @@ static inline void update_network(struct
 }
 
 static inline void ieee80211_process_probe_response(struct ieee80211_device
-						    *ieee,
-						    struct
+						    *ieee, struct
 						    ieee80211_probe_response
-						    *beacon,
-						    struct ieee80211_rx_stats
+						    *beacon, struct ieee80211_rx_stats
 						    *stats)
 {
 	struct ieee80211_network network;
---
0.99.8.GIT


--- NEW FILE 0107-Changed-802.11-headers-to-use-ieee80211_info_element-0.txt ---
Subject: [PATCH] Changed 802.11 headers to use ieee80211_info_element[0]
From: James Ketrenos <jketreno linux intel com>
Date: 1126651042 -0500

Changed 802.11 headers to use ieee80211_info_element as zero sized
array so that sizeof calculations do not account for IE sizes.

Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/net/ieee80211.h      |    8 ++++----
 net/ieee80211/ieee80211_rx.c |    4 ++--
 2 files changed, 6 insertions(+), 6 deletions(-)

applies-to: a2f097836efccc5b4758888bd97599aecd56e37e
68e4e036b841d5fb23ae1ac51b1e40baf9d582bf
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index d8bb8f7..6394ae4 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -538,7 +538,7 @@ struct ieee80211_authentication {
 	__le16 algorithm;
 	__le16 transaction;
 	__le16 status;
-	struct ieee80211_info_element info_element;
+	struct ieee80211_info_element info_element[0];
 } __attribute__ ((packed));
 
 struct ieee80211_probe_response {
@@ -546,14 +546,14 @@ struct ieee80211_probe_response {
 	u32 time_stamp[2];
 	__le16 beacon_interval;
 	__le16 capability;
-	struct ieee80211_info_element info_element;
+	struct ieee80211_info_element info_element[0];
 } __attribute__ ((packed));
 
 struct ieee80211_assoc_request_frame {
 	__le16 capability;
 	__le16 listen_interval;
 	u8 current_ap[ETH_ALEN];
-	struct ieee80211_info_element info_element;
+	struct ieee80211_info_element info_element[0];
 } __attribute__ ((packed));
 
 struct ieee80211_assoc_response_frame {
@@ -561,7 +561,7 @@ struct ieee80211_assoc_response_frame {
 	__le16 capability;
 	__le16 status;
 	__le16 aid;
-	struct ieee80211_info_element info_element;	/* supported rates */
+	struct ieee80211_info_element info_element[0];	/* supported rates */
 } __attribute__ ((packed));
 
 struct ieee80211_txb {
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 6bbaa44..cae55e5 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -822,7 +822,7 @@ static inline int ieee80211_network_init
 	network->wpa_ie_len = 0;
 	network->rsn_ie_len = 0;
 
-	info_element = &beacon->info_element;
+	info_element = beacon->info_element;
 	left = stats->len - ((void *)info_element - (void *)beacon);
 	while (left >= sizeof(struct ieee80211_info_element_hdr)) {
 		if (sizeof(struct ieee80211_info_element_hdr) +
@@ -1050,7 +1050,7 @@ static inline void ieee80211_process_pro
 	struct ieee80211_network *target;
 	struct ieee80211_network *oldest = NULL;
 #ifdef CONFIG_IEEE80211_DEBUG
-	struct ieee80211_info_element *info_element = &beacon->info_element;
+	struct ieee80211_info_element *info_element = beacon->info_element;
 #endif
 	unsigned long flags;
 
---
0.99.8.GIT


--- NEW FILE 0108-ieee80211-Removed-ieee80211_info_element_hdr.txt ---
Subject: [PATCH] ieee80211 Removed ieee80211_info_element_hdr
From: James Ketrenos <jketreno linux intel com>
Date: 1126651093 -0500

Removed ieee80211_info_element_hdr structure as ieee80211_info_element
provides the same use.

Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/net/ieee80211.h      |    5 -----
 net/ieee80211/ieee80211_rx.c |   10 +++++-----
 2 files changed, 5 insertions(+), 10 deletions(-)

applies-to: a5fe3c6c7ef9fa132b5719790f7c1fc0084da083
7b1fa54020985fa4b154f9f5d2f04ba174c7f1a5
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 6394ae4..27374c2 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -505,11 +505,6 @@ enum ieee80211_mfie {
 	MFIE_TYPE_GENERIC = 221,
 };
 
-struct ieee80211_info_element_hdr {
-	u8 id;
-	u8 len;
-} __attribute__ ((packed));
-
 struct ieee80211_info_element {
 	u8 id;
 	u8 len;
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index cae55e5..e0337c8 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -823,10 +823,10 @@ static inline int ieee80211_network_init
 	network->rsn_ie_len = 0;
 
 	info_element = beacon->info_element;
-	left = stats->len - ((void *)info_element - (void *)beacon);
-	while (left >= sizeof(struct ieee80211_info_element_hdr)) {
-		if (sizeof(struct ieee80211_info_element_hdr) +
-		    info_element->len > left) {
+	left = stats->len - sizeof(*beacon);
+	while (left >= sizeof(struct ieee80211_info_element)) {
+		if (sizeof(struct ieee80211_info_element) + info_element->len >
+		    left) {
 			IEEE80211_DEBUG_SCAN
 			    ("SCAN: parse failed: info_element->len + 2 > left : info_element->len+2=%Zd left=%d.\n",
 			     info_element->len +
@@ -967,7 +967,7 @@ static inline int ieee80211_network_init
 			break;
 		}
 
-		left -= sizeof(struct ieee80211_info_element_hdr) +
+		left -= sizeof(struct ieee80211_info_element) +
 		    info_element->len;
 		info_element = (struct ieee80211_info_element *)
 		    &info_element->data[info_element->len];
---
0.99.8.GIT


--- NEW FILE 0109-ieee80211-Cleanup-memcpy-parameters.txt ---
Subject: [PATCH] ieee80211 Cleanup memcpy parameters.
From: James Ketrenos <jketreno linux intel com>
Date: 1126651229 -0500

Cleanup memcpy parameters.

Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 net/ieee80211/ieee80211_tx.c |   16 ++++++++--------
 1 files changed, 8 insertions(+), 8 deletions(-)

applies-to: 01bd894cfcca1a9bc70de6bf3163e379244ee46e
18294d8727b825eb2f3f98d6b6ae4a999dff854a
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index c9aaff3..1a09448 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -285,8 +285,8 @@ int ieee80211_xmit(struct sk_buff *skb, 
 	}
 
 	/* Save source and destination addresses */
-	memcpy(&dest, skb->data, ETH_ALEN);
-	memcpy(&src, skb->data + ETH_ALEN, ETH_ALEN);
+	memcpy(dest, skb->data, ETH_ALEN);
+	memcpy(src, skb->data + ETH_ALEN, ETH_ALEN);
 
 	/* Advance the SKB to the start of the payload */
 	skb_pull(skb, sizeof(struct ethhdr));
@@ -304,15 +304,15 @@ int ieee80211_xmit(struct sk_buff *skb, 
 		fc |= IEEE80211_FCTL_TODS;
 		/* To DS: Addr1 = BSSID, Addr2 = SA,
 		   Addr3 = DA */
-		memcpy(&header.addr1, ieee->bssid, ETH_ALEN);
-		memcpy(&header.addr2, &src, ETH_ALEN);
-		memcpy(&header.addr3, &dest, ETH_ALEN);
+		memcpy(header.addr1, ieee->bssid, ETH_ALEN);
+		memcpy(header.addr2, src, ETH_ALEN);
+		memcpy(header.addr3, dest, ETH_ALEN);
 	} else if (ieee->iw_mode == IW_MODE_ADHOC) {
 		/* not From/To DS: Addr1 = DA, Addr2 = SA,
 		   Addr3 = BSSID */
-		memcpy(&header.addr1, dest, ETH_ALEN);
-		memcpy(&header.addr2, src, ETH_ALEN);
-		memcpy(&header.addr3, ieee->bssid, ETH_ALEN);
+		memcpy(header.addr1, dest, ETH_ALEN);
+		memcpy(header.addr2, src, ETH_ALEN);
+		memcpy(header.addr3, ieee->bssid, ETH_ALEN);
 	}
 	header.frame_ctl = cpu_to_le16(fc);
 	hdr_len = IEEE80211_3ADDR_LEN;
---
0.99.8.GIT


--- NEW FILE 0110-ieee80211-Switched-to-sscanf-in-store_debug_level.txt ---
Subject: [PATCH] ieee80211 Switched to sscanf in store_debug_level
From: James Ketrenos <jketreno linux intel com>
Date: 1126651373 -0500

Switched to sscanf as per friendly comment in store_debug_level.

Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 net/ieee80211/ieee80211_module.c |   26 ++++++--------------------
 1 files changed, 6 insertions(+), 20 deletions(-)

applies-to: 869c9254e4211fb2cea8184575f65184f207ec60
262d8e467710a1c870717bc432caaf74cde3ce20
diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c
index 03a4734..4b43ae1 100644
--- a/net/ieee80211/ieee80211_module.c
+++ b/net/ieee80211/ieee80211_module.c
@@ -195,34 +195,20 @@ static int show_debug_level(char *page, 
 static int store_debug_level(struct file *file, const char __user * buffer,
 			     unsigned long count, void *data)
 {
-	char buf[] = "0x00000000";
-	char *p = (char *)buf;
+	char buf[] = "0x00000000\n";
+	unsigned long len = min((unsigned long)sizeof(buf) - 1, count);
 	unsigned long val;
 
-	if (count > sizeof(buf) - 1)
-		count = sizeof(buf) - 1;
-
-	if (copy_from_user(buf, buffer, count))
+	if (copy_from_user(buf, buffer, len))
 		return count;
-	buf[count] = 0;
-	/*
-	 * what a FPOS...  What, sscanf(buf, "%i", &val) would be too
-	 * scary?
-	 */
-	if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
-		p++;
-		if (p[0] == 'x' || p[0] == 'X')
-			p++;
-		val = simple_strtoul(p, &p, 16);
-	} else
-		val = simple_strtoul(p, &p, 10);
-	if (p == buf)
+	buf[len] = 0;
+	if (sscanf(buf, "%li", &val) != 1)
 		printk(KERN_INFO DRV_NAME
 		       ": %s is not in hex or decimal form.\n", buf);
 	else
 		ieee80211_debug_level = val;
 
-	return strlen(buf);
+	return strnlen(buf, len);
 }
 
 static int __init ieee80211_init(void)
---
0.99.8.GIT


--- NEW FILE 0111-ieee80211-Fixed-type-o-of-abg_ture-abg_true.txt ---
Subject: [PATCH] ieee80211 Fixed type-o of abg_ture -> abg_true
From: James Ketrenos <jketreno linux intel com>
Date: 1126651734 -0500

[PATCH 14/29] Fixed type-o of abg_ture -> abg_true.

Signed-off-by: James Ketrenos <jketreno linux intel com>

NOTE: This patch requires drivers using abg_ture to be updated.
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/net/ieee80211.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

applies-to: 17ce405907e553bdb8691a60df3d4805461bec72
3bc5ed684253f407b1567799d13cb06a0d86fe80
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 27374c2..2d9c679 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -696,7 +696,7 @@ struct ieee80211_device {
 	int mode;		/* A, B, G */
 	int modulation;		/* CCK, OFDM */
 	int freq_band;		/* 2.4Ghz, 5.2Ghz, Mixed */
-	int abg_ture;		/* ABG flag              */
+	int abg_true;		/* ABG flag              */
 
 	int perfect_rssi;
 	int worst_rssi;
---
0.99.8.GIT


Index: 0112-Updated-ipw2200-to-compile-with-ieee80211-abg_ture-to-abg_true-change.txt
===================================================================
RCS file: 0112-Updated-ipw2200-to-compile-with-ieee80211-abg_ture-to-abg_true-change.txt
diff -N 0112-Updated-ipw2200-to-compile-with-ieee80211-abg_ture-to-abg_true-change.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0112-Updated-ipw2200-to-compile-with-ieee80211-abg_ture-to-abg_true-change.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,82 @@
+Subject: [PATCH] Updated ipw2200 to compile with ieee80211 abg_ture to abg_true change
+From: James Ketrenos <jketreno linux intel com>
+Date: 1126726139 -0500
+
+author James Ketrenos <jketreno linux intel com> 1126713327 -0500
+committer James Ketrenos <jketreno linux intel com> 1126713327 -0500
+
+Updated ipw2200 to compile with ieee80211 abg_ture to abg_true change.
+
+Signed-off-by: James Ketrenos <jketreno linux intel com>
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/ipw2200.c |   14 +++++++-------
+ 1 files changed, 7 insertions(+), 7 deletions(-)
+
+applies-to: fec657fe7a87aedc5a60e5c1128c6ba509ae18f8
+a33a1982012e9070736e3717231714dc9892303b
+diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
+index b7f275c..86feef7 100644
+--- a/drivers/net/wireless/ipw2200.c
++++ b/drivers/net/wireless/ipw2200.c
+@@ -6010,12 +6010,12 @@ static int ipw_wx_set_wireless_mode(stru
+ 	}
+ 
+ 	if (priv->adapter == IPW_2915ABG) {
+-		priv->ieee->abg_ture = 1;
++		priv->ieee->abg_true = 1;
+ 		if (mode & IEEE_A) {
+ 			band |= IEEE80211_52GHZ_BAND;
+ 			modulation |= IEEE80211_OFDM_MODULATION;
+ 		} else
+-			priv->ieee->abg_ture = 0;
++			priv->ieee->abg_true = 0;
+ 	} else {
+ 		if (mode & IEEE_A) {
+ 			IPW_WARNING("Attempt to set 2200BG into "
+@@ -6023,20 +6023,20 @@ static int ipw_wx_set_wireless_mode(stru
+ 			return -EINVAL;
+ 		}
+ 
+-		priv->ieee->abg_ture = 0;
++		priv->ieee->abg_true = 0;
+ 	}
+ 
+ 	if (mode & IEEE_B) {
+ 		band |= IEEE80211_24GHZ_BAND;
+ 		modulation |= IEEE80211_CCK_MODULATION;
+ 	} else
+-		priv->ieee->abg_ture = 0;
++		priv->ieee->abg_true = 0;
+ 
+ 	if (mode & IEEE_G) {
+ 		band |= IEEE80211_24GHZ_BAND;
+ 		modulation |= IEEE80211_OFDM_MODULATION;
+ 	} else
+-		priv->ieee->abg_ture = 0;
++		priv->ieee->abg_true = 0;
+ 
+ 	priv->ieee->mode = mode;
+ 	priv->ieee->freq_band = band;
+@@ -7108,7 +7108,7 @@ static int ipw_pci_probe(struct pci_dev 
+ 		printk(KERN_INFO DRV_NAME
+ 		       ": Detected Intel PRO/Wireless 2915ABG Network "
+ 		       "Connection\n");
+-		priv->ieee->abg_ture = 1;
++		priv->ieee->abg_true = 1;
+ 		band = IEEE80211_52GHZ_BAND | IEEE80211_24GHZ_BAND;
+ 		modulation = IEEE80211_OFDM_MODULATION |
+ 		    IEEE80211_CCK_MODULATION;
+@@ -7124,7 +7124,7 @@ static int ipw_pci_probe(struct pci_dev 
+ 			       ": Detected Intel PRO/Wireless 2200BG Network "
+ 			       "Connection\n");
+ 
+-		priv->ieee->abg_ture = 0;
++		priv->ieee->abg_true = 0;
+ 		band = IEEE80211_24GHZ_BAND;
+ 		modulation = IEEE80211_OFDM_MODULATION |
+ 		    IEEE80211_CCK_MODULATION;
+---
+0.99.8.GIT


Index: 0161-ieee80211-Updated-ipw2100-to-be-compatible-with-ieee80211_hdr-changes.txt
===================================================================
RCS file: 0161-ieee80211-Updated-ipw2100-to-be-compatible-with-ieee80211_hdr-changes.txt
diff -N 0161-ieee80211-Updated-ipw2100-to-be-compatible-with-ieee80211_hdr-changes.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0161-ieee80211-Updated-ipw2100-to-be-compatible-with-ieee80211_hdr-changes.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,59 @@
+Subject: [PATCH] ieee80211: Updated ipw2100 to be compatible with ieee80211_hdr changes
+From: James Ketrenos <jketreno linux intel com>
+Date: 1127323405 -0500
+
+tree 992b203395c50342f1cced415acae6177344e270
+parent c59bb604a2ff4e40232ff0422e7adc44e3b007a0
+author James Ketrenos <jketreno linux intel com> 1126714006 -0500
+committer James Ketrenos <jketreno linux intel com> 1127315910 -0500
+
+Updated ipw2100 to be compatible with ieee80211_hdr changes.
+
+Signed-off-by: James Ketrenos <jketreno linux intel com>
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/ipw2100.c |    4 ++--
+ drivers/net/wireless/ipw2100.h |    2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+applies-to: 92c26ea74c0ffb9b83a2285ad2539cc271b09856
+99a4b232b6682a847c70d877e4a3c15e9138c8f6
+diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
+index e5cdb5b..8dc80f8 100644
+--- a/drivers/net/wireless/ipw2100.c
++++ b/drivers/net/wireless/ipw2100.c
+@@ -2948,7 +2948,7 @@ static void ipw2100_tx_send_data(struct 
+ 	int next = txq->next;
+         int i = 0;
+ 	struct ipw2100_data_header *ipw_hdr;
+-	struct ieee80211_hdr *hdr;
++	struct ieee80211_hdr_3addr *hdr;
+ 
+ 	while (!list_empty(&priv->tx_pend_list)) {
+ 		/* if there isn't enough space in TBD queue, then
+@@ -2984,7 +2984,7 @@ static void ipw2100_tx_send_data(struct 
+ 		packet->index = txq->next;
+ 
+ 		ipw_hdr = packet->info.d_struct.data;
+-		hdr = (struct ieee80211_hdr *)packet->info.d_struct.txb->
++		hdr = (struct ieee80211_hdr_3addr *)packet->info.d_struct.txb->
+ 			fragments[0]->data;
+ 
+ 		if (priv->ieee->iw_mode == IW_MODE_INFRA) {
+diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h
+index 2a3cdbd..c9e99ce 100644
+--- a/drivers/net/wireless/ipw2100.h
++++ b/drivers/net/wireless/ipw2100.h
+@@ -808,7 +808,7 @@ struct ipw2100_priv {
+ struct ipw2100_rx {
+ 	union {
+ 		unsigned char payload[IPW_RX_NIC_BUFFER_LENGTH];
+-		struct ieee80211_hdr header;
++		struct ieee80211_hdr_4addr header;
+ 		u32 status;
+ 		struct ipw2100_notification notification;
+ 		struct ipw2100_cmd_header command;
+---
+0.99.8.GIT


Index: 0162-ieee80211-Updated-ipw2100-to-be-compatible-with-ieee80211-s-hard_start_xmit-change.txt
===================================================================
RCS file: 0162-ieee80211-Updated-ipw2100-to-be-compatible-with-ieee80211-s-hard_start_xmit-change.txt
diff -N 0162-ieee80211-Updated-ipw2100-to-be-compatible-with-ieee80211-s-hard_start_xmit-change.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0162-ieee80211-Updated-ipw2100-to-be-compatible-with-ieee80211-s-hard_start_xmit-change.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,37 @@
+Subject: [PATCH] ieee80211: Updated ipw2100 to be compatible with ieee80211's hard_start_xmit change
+From: James Ketrenos <jketreno linux intel com>
+Date: 1127323417 -0500
+
+tree ee48cbe413b795d6be454b9baf4f3bd3d74814cb
+parent 49856b147763bd6847e0d8f53aee1ddd61385638
+author James Ketrenos <jketreno linux intel com> 1126716634 -0500
+committer James Ketrenos <jketreno linux intel com> 1127316024 -0500
+
+Updated ipw2100 to be compatible with ieee80211's hard_start_xmit change.
+
+Signed-off-by: James Ketrenos <jketreno linux intel com>
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/ipw2100.c |    3 ++-
+ 1 files changed, 2 insertions(+), 1 deletions(-)
+
+applies-to: 7dacb727771de8dc9318beb81752f3c5f22adab2
+3a5becf720d6346ffca2d6be6473f603b39322a2
+diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
+index 8dc80f8..ad7f8cd 100644
+--- a/drivers/net/wireless/ipw2100.c
++++ b/drivers/net/wireless/ipw2100.c
+@@ -3269,7 +3269,8 @@ static irqreturn_t ipw2100_interrupt(int
+ 	return IRQ_NONE;
+ }
+ 
+-static int ipw2100_tx(struct ieee80211_txb *txb, struct net_device *dev)
++static int ipw2100_tx(struct ieee80211_txb *txb, struct net_device *dev,
++		      int pri)
+ {
+ 	struct ipw2100_priv *priv = ieee80211_priv(dev);
+ 	struct list_head *element;
+---
+0.99.8.GIT


Index: 0163-ieee80211-Updated-ipw2200-to-be-compatible-with-ieee80211_hdr-changes.txt
===================================================================
RCS file: 0163-ieee80211-Updated-ipw2200-to-be-compatible-with-ieee80211_hdr-changes.txt
diff -N 0163-ieee80211-Updated-ipw2200-to-be-compatible-with-ieee80211_hdr-changes.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0163-ieee80211-Updated-ipw2200-to-be-compatible-with-ieee80211_hdr-changes.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,77 @@
+Subject: [PATCH] ieee80211: Updated ipw2200 to be compatible with ieee80211_hdr changes
+From: James Ketrenos <jketreno linux intel com>
+Date: 1127323421 -0500
+
+tree 9f86c7b4f59249c05c96c360dfaa817995e8a44f
+parent 9b09701b2c6254f2fddb009004a14eb5a908714f
+author James Ketrenos <jketreno linux intel com> 1126714305 -0500
+committer James Ketrenos <jketreno linux intel com> 1127316074 -0500
+
+Updated ipw2200 to be compatible with ieee80211_hdr changes.
+
+Signed-off-by: James Ketrenos <jketreno linux intel com>
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/ipw2200.c |    9 +++++----
+ drivers/net/wireless/ipw2200.h |    4 ++--
+ 2 files changed, 7 insertions(+), 6 deletions(-)
+
+applies-to: 0084320b04b04b2d61e4630505803104251205a6
+0dacca1f0a53938dd7d5ba35c692bd1a3356d504
+diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
+index 86feef7..34f0052 100644
+--- a/drivers/net/wireless/ipw2200.c
++++ b/drivers/net/wireless/ipw2200.c
+@@ -4904,7 +4904,7 @@ static void ipw_rx(struct ipw_priv *priv
+ {
+ 	struct ipw_rx_mem_buffer *rxb;
+ 	struct ipw_rx_packet *pkt;
+-	struct ieee80211_hdr *header;
++	struct ieee80211_hdr_4addr *header;
+ 	u32 r, w, i;
+ 	u8 network_packet;
+ 
+@@ -4967,8 +4967,9 @@ static void ipw_rx(struct ipw_priv *priv
+ #endif
+ 
+ 				header =
+-				    (struct ieee80211_hdr *)(rxb->skb->data +
+-							     IPW_RX_FRAME_SIZE);
++				    (struct ieee80211_hdr_4addr *)(rxb->skb->
++								   data +
++								   IPW_RX_FRAME_SIZE);
+ 				/* TODO: Check Ad-Hoc dest/source and make sure
+ 				 * that we are actually parsing these packets
+ 				 * correctly -- we should probably use the
+@@ -6325,7 +6326,7 @@ we need to heavily modify the ieee80211_
+ 
+ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb)
+ {
+-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)
++	struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)
+ 	    txb->fragments[0]->data;
+ 	int i = 0;
+ 	struct tfd_frame *tfd;
+diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h
+index 5b00882..e9cf32b 100644
+--- a/drivers/net/wireless/ipw2200.h
++++ b/drivers/net/wireless/ipw2200.h
+@@ -1654,12 +1654,12 @@ static const long ipw_frequencies[] = {
+ 
+ #define IPW_MAX_CONFIG_RETRIES 10
+ 
+-static inline u32 frame_hdr_len(struct ieee80211_hdr *hdr)
++static inline u32 frame_hdr_len(struct ieee80211_hdr_4addr *hdr)
+ {
+ 	u32 retval;
+ 	u16 fc;
+ 
+-	retval = sizeof(struct ieee80211_hdr);
++	retval = sizeof(struct ieee80211_hdr_3addr);
+ 	fc = le16_to_cpu(hdr->frame_ctl);
+ 
+ 	/*
+---
+0.99.8.GIT


Index: 0164-ieee80211-Updated-ipw2200-to-be-compatible-with-ieee80211-s-hard_start_xmit-change.txt
===================================================================
RCS file: 0164-ieee80211-Updated-ipw2200-to-be-compatible-with-ieee80211-s-hard_start_xmit-change.txt
diff -N 0164-ieee80211-Updated-ipw2200-to-be-compatible-with-ieee80211-s-hard_start_xmit-change.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0164-ieee80211-Updated-ipw2200-to-be-compatible-with-ieee80211-s-hard_start_xmit-change.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,36 @@
+Subject: [PATCH] ieee80211: Updated ipw2200 to be compatible with ieee80211's hard_start_xmit change.
+From: James Ketrenos <jketreno linux intel com>
+Date: 1127323423 -0500
+
+tree 713b6ff3311decfe42d5209f7b2508736d144b85
+parent 6465beff0e89779330450dffc2a5e6dc5154eebf
+author James Ketrenos <jketreno linux intel com> 1126716726 -0500
+committer James Ketrenos <jketreno linux intel com> 1127316162 -0500
+
+Updated ipw2200 to be compatible with ieee80211's hard_start_xmit change.
+
+Signed-off-by: James Ketrenos <jketreno linux intel com>
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/ipw2200.c |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+applies-to: 1c3e6ddedd1032ef26a4e0f45e8d3b1fa3fd8d96
+c8d42d1ae4518091a20f7212b0591a0f4b0e8ca0
+diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
+index 34f0052..7ea9bd5 100644
+--- a/drivers/net/wireless/ipw2200.c
++++ b/drivers/net/wireless/ipw2200.c
+@@ -6449,7 +6449,7 @@ static inline void ipw_tx_skb(struct ipw
+ }
+ 
+ static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb,
+-				   struct net_device *dev)
++				   struct net_device *dev, int pri)
+ {
+ 	struct ipw_priv *priv = ieee80211_priv(dev);
+ 	unsigned long flags;
+---
+0.99.8.GIT


Index: 0165-ieee80211-Updated-atmel-to-be-compatible-with-ieee80211_hdr-changes.txt
===================================================================
RCS file: 0165-ieee80211-Updated-atmel-to-be-compatible-with-ieee80211_hdr-changes.txt
diff -N 0165-ieee80211-Updated-atmel-to-be-compatible-with-ieee80211_hdr-changes.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0165-ieee80211-Updated-atmel-to-be-compatible-with-ieee80211_hdr-changes.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,141 @@
+Subject: [PATCH] ieee80211: Updated atmel to be compatible with ieee80211_hdr changes
+From: James Ketrenos <jketreno linux intel com>
+Date: 1127323426 -0500
+
+tree d7be83000b058b14450d76f99c432b1fb2a1c177
+parent 322201093e03830fceedfc24931420b1ea855a8c
+author James Ketrenos <jketreno linux intel com> 1127316330 -0500
+committer James Ketrenos <jketreno linux intel com> 1127316330 -0500
+
+Updated atmel to be compatible with ieee80211_hdr changes.
+
+Change accomplished via:
+
+sed -i -e "s:ieee80211_hdr\([^_]\):ieee80211_hdr_4addr\1:g" \
+	drivers/net/wireless/atmel.c
+
+Compile tested only.
+
+CC: simon thekelleys org uk
+
+Signed-off-by: James Ketrenos <jketreno linux intel com>
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/atmel.c |   24 ++++++++++++------------
+ 1 files changed, 12 insertions(+), 12 deletions(-)
+
+applies-to: c79676c91d5f8fc12b7ef54625e1bcff8bdab14f
+4ca5253d573d7b3785dbb2f123f948fdca6ee235
+diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
+index 587869d..d570110 100644
+--- a/drivers/net/wireless/atmel.c
++++ b/drivers/net/wireless/atmel.c
+@@ -618,12 +618,12 @@ static int atmel_lock_mac(struct atmel_p
+ static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data);
+ static void atmel_command_irq(struct atmel_private *priv);
+ static int atmel_validate_channel(struct atmel_private *priv, int channel);
+-static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr *header, 
++static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header, 
+ 				   u16 frame_len, u8 rssi);
+ static void atmel_management_timer(u_long a);
+ static void atmel_send_command(struct atmel_private *priv, int command, void *cmd, int cmd_size);
+ static int atmel_send_command_wait(struct atmel_private *priv, int command, void *cmd, int cmd_size);
+-static void atmel_transmit_management_frame(struct atmel_private *priv, struct ieee80211_hdr *header,
++static void atmel_transmit_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
+ 					    u8 *body, int body_len);
+ 
+ static u8 atmel_get_mib8(struct atmel_private *priv, u8 type, u8 index);
+@@ -827,7 +827,7 @@ static void tx_update_descriptor(struct 
+ static int start_tx (struct sk_buff *skb, struct net_device *dev)
+ {
+ 	struct atmel_private *priv = netdev_priv(dev);
+-	struct ieee80211_hdr header;
++	struct ieee80211_hdr_4addr header;
+ 	unsigned long flags;
+ 	u16 buff, frame_ctl, len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
+ 	u8 SNAP_RFC1024[6] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
+@@ -902,7 +902,7 @@ static int start_tx (struct sk_buff *skb
+ }
+ 
+ static void atmel_transmit_management_frame(struct atmel_private *priv, 
+-					    struct ieee80211_hdr *header,
++					    struct ieee80211_hdr_4addr *header,
+ 					    u8 *body, int body_len)
+ {
+ 	u16 buff;
+@@ -917,7 +917,7 @@ static void atmel_transmit_management_fr
+ 	tx_update_descriptor(priv, header->addr1[0] & 0x01, len, buff, TX_PACKET_TYPE_MGMT);
+ }
+ 	
+-static void fast_rx_path(struct atmel_private *priv, struct ieee80211_hdr *header, 
++static void fast_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr *header, 
+ 			 u16 msdu_size, u16 rx_packet_loc, u32 crc)
+ {
+ 	/* fast path: unfragmented packet copy directly into skbuf */
+@@ -990,7 +990,7 @@ static int probe_crc(struct atmel_privat
+ 	return (crc ^ 0xffffffff) == netcrc;
+ }
+ 
+-static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr *header, 
++static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr *header, 
+ 			 u16 msdu_size, u16 rx_packet_loc, u32 crc, u16 seq_no, u8 frag_no, int more_frags)
+ {
+ 	u8 mac4[6]; 
+@@ -1082,7 +1082,7 @@ static void frag_rx_path(struct atmel_pr
+ static void rx_done_irq(struct atmel_private *priv)
+ {
+ 	int i;
+-	struct ieee80211_hdr header;
++	struct ieee80211_hdr_4addr header;
+ 	
+ 	for (i = 0; 
+ 	     atmel_rmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head)) == RX_DESC_FLAG_VALID &&
+@@ -2650,7 +2650,7 @@ static void handle_beacon_probe(struct a
+  
+ static void send_authentication_request(struct atmel_private *priv, u8 *challenge, int challenge_len)
+ {
+-	struct ieee80211_hdr header;
++	struct ieee80211_hdr_4addr header;
+ 	struct auth_body auth;
+ 	
+ 	header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH); 
+@@ -2688,7 +2688,7 @@ static void send_association_request(str
+ {
+ 	u8 *ssid_el_p;
+ 	int bodysize;
+-	struct ieee80211_hdr header;
++	struct ieee80211_hdr_4addr header;
+ 	struct ass_req_format {
+ 		u16 capability;
+ 		u16 listen_interval; 
+@@ -2738,7 +2738,7 @@ static void send_association_request(str
+ 	atmel_transmit_management_frame(priv, &header, (void *)&body, bodysize);
+ }
+ 
+-static int is_frame_from_current_bss(struct atmel_private *priv, struct ieee80211_hdr *header)
++static int is_frame_from_current_bss(struct atmel_private *priv, struct ieee80211_hdr_4addr *header)
+ {
+ 	if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
+ 		return memcmp(header->addr3, priv->CurrentBSSID, 6) == 0;
+@@ -2788,7 +2788,7 @@ static int retrieve_bss(struct atmel_pri
+ }
+ 
+ 
+-static void store_bss_info(struct atmel_private *priv, struct ieee80211_hdr *header,
++static void store_bss_info(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
+ 			   u16 capability, u16 beacon_period, u8 channel, u8 rssi, 
+ 			   u8 ssid_len, u8 *ssid, int is_beacon)
+ {
+@@ -3072,7 +3072,7 @@ static void atmel_smooth_qual(struct atm
+ }
+ 
+ /* deals with incoming managment frames. */
+-static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr *header, 
++static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header, 
+ 		      u16 frame_len, u8 rssi)
+ {
+ 	u16 subtype;
+---
+0.99.8.GIT


--- NEW FILE 0166-ieee80211-Fixed-a-kernel-oops-on-module-unload.txt ---
Subject: [PATCH] ieee80211: Fixed a kernel oops on module unload
From: James Ketrenos <jketreno linux intel com>
Date: 1127321623 -0500

tree 367069f24fc38b4aa910e86ff40094d2078d8aa7
parent a33a1982012e9070736e3717231714dc9892303b
author James Ketrenos <jketreno linux intel com> 1124430800 -0500
committer James Ketrenos <jketreno linux intel com> 1127310571 -0500

Fixed a kernel oops on module unload by adding spin lock protection to
ieee80211's crypt handlers (thanks to Zhu Yi)

Modified scan result logic to report WPA and RSN IEs if set (vs.being
based on wpa_enabled)

Added ieee80211_device as the first parameter to the crypt init()
method.  TKIP modified to use that structure for determining whether to
countermeasures are active.

Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/net/ieee80211.h              |    1 +
 include/net/ieee80211_crypt.h        |    2 +-
 net/ieee80211/ieee80211_crypt.c      |    9 +++++----
 net/ieee80211/ieee80211_crypt_ccmp.c |    2 +-
 net/ieee80211/ieee80211_crypt_tkip.c |   31 ++++++++++++++++++++++++++++---
 net/ieee80211/ieee80211_crypt_wep.c  |    2 +-
 net/ieee80211/ieee80211_rx.c         |   11 -----------
 net/ieee80211/ieee80211_tx.c         |   14 --------------
 net/ieee80211/ieee80211_wx.c         |    6 +++---
 9 files changed, 40 insertions(+), 38 deletions(-)

applies-to: 51092301c2553b9c977cbb6d77e272750ccfd068
20d64713ae71c0b0aa06084acbef2244021baaca
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 2d9c679..ed06a94 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -434,6 +434,7 @@ struct ieee80211_device;
 #define SEC_KEY_2         (1<<1)
 #define SEC_KEY_3         (1<<2)
 #define SEC_KEY_4         (1<<3)
+#define SEC_KEY_MASK      (SEC_KEY_1 | SEC_KEY_2 | SEC_KEY_3 | SEC_KEY_4)
 #define SEC_ACTIVE_KEY    (1<<4)
 #define SEC_AUTH_MODE     (1<<5)
 #define SEC_UNICAST_GROUP (1<<6)
diff --git a/include/net/ieee80211_crypt.h b/include/net/ieee80211_crypt.h
index 93bf91f..e2064ed 100644
--- a/include/net/ieee80211_crypt.h
+++ b/include/net/ieee80211_crypt.h
@@ -31,7 +31,7 @@ struct ieee80211_crypto_ops {
 	/* init new crypto context (e.g., allocate private data space,
 	 * select IV, etc.); returns NULL on failure or pointer to allocated
 	 * private data on success */
-	void *(*init) (int keyidx);
+	void *(*init) (struct ieee80211_device * ieee, int keyidx);
 
 	/* deinitialize crypto context and free allocated private data */
 	void (*deinit) (void *priv);
diff --git a/net/ieee80211/ieee80211_crypt.c b/net/ieee80211/ieee80211_crypt.c
index dc835f6..0c36629 100644
--- a/net/ieee80211/ieee80211_crypt.c
+++ b/net/ieee80211/ieee80211_crypt.c
@@ -41,7 +41,9 @@ void ieee80211_crypt_deinit_entries(stru
 {
 	struct list_head *ptr, *n;
 	struct ieee80211_crypt_data *entry;
+	unsigned long flags;
 
+	spin_lock_irqsave(&ieee->lock, flags);
 	for (ptr = ieee->crypt_deinit_list.next, n = ptr->next;
 	     ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) {
 		entry = list_entry(ptr, struct ieee80211_crypt_data, list);
@@ -57,14 +59,13 @@ void ieee80211_crypt_deinit_entries(stru
 		}
 		kfree(entry);
 	}
+	spin_unlock_irqrestore(&ieee->lock, flags);
 }
 
 void ieee80211_crypt_deinit_handler(unsigned long data)
 {
 	struct ieee80211_device *ieee = (struct ieee80211_device *)data;
-	unsigned long flags;
 
-	spin_lock_irqsave(&ieee->lock, flags);
 	ieee80211_crypt_deinit_entries(ieee, 0);
 	if (!list_empty(&ieee->crypt_deinit_list)) {
 		printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
@@ -72,7 +73,6 @@ void ieee80211_crypt_deinit_handler(unsi
 		ieee->crypt_deinit_timer.expires = jiffies + HZ;
 		add_timer(&ieee->crypt_deinit_timer);
 	}
-	spin_unlock_irqrestore(&ieee->lock, flags);
 
 }
 
@@ -182,7 +182,8 @@ struct ieee80211_crypto_ops *ieee80211_g
 		return NULL;
 }
 
-static void *ieee80211_crypt_null_init(int keyidx)
+static void *ieee80211_crypt_null_init(struct ieee80211_device *ieee,
+				       int keyidx)
 {
 	return (void *)1;
 }
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c
index 7b62908..1e6644b 100644
--- a/net/ieee80211/ieee80211_crypt_ccmp.c
+++ b/net/ieee80211/ieee80211_crypt_ccmp.c
@@ -74,7 +74,7 @@ static void ieee80211_ccmp_aes_encrypt(s
 	crypto_cipher_encrypt(tfm, &dst, &src, AES_BLOCK_LEN);
 }
 
-static void *ieee80211_ccmp_init(int key_idx)
+static void *ieee80211_ccmp_init(struct ieee80211_device *ieee, int key_idx)
 {
 	struct ieee80211_ccmp_data *priv;
 
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c
index dca380e..0c495f0 100644
--- a/net/ieee80211/ieee80211_crypt_tkip.c
+++ b/net/ieee80211/ieee80211_crypt_tkip.c
@@ -59,9 +59,11 @@ struct ieee80211_tkip_data {
 
 	/* scratch buffers for virt_to_page() (crypto API) */
 	u8 rx_hdr[16], tx_hdr[16];
+
+	struct ieee80211_device *ieee;
 };
 
-static void *ieee80211_tkip_init(int key_idx)
+static void *ieee80211_tkip_init(struct ieee80211_device *ieee, int key_idx)
 {
 	struct ieee80211_tkip_data *priv;
 
@@ -69,6 +71,9 @@ static void *ieee80211_tkip_init(int key
 	if (priv == NULL)
 		goto fail;
 	memset(priv, 0, sizeof(*priv));
+
+	priv->ieee = ieee;
+
 	priv->key_idx = key_idx;
 
 	priv->tfm_arc4 = crypto_alloc_tfm("arc4", 0);
@@ -264,11 +269,21 @@ static int ieee80211_tkip_encrypt(struct
 	u32 crc;
 	struct scatterlist sg;
 
+	hdr = (struct ieee80211_hdr *)skb->data;
+
+	if (tkey->ieee->tkip_countermeasures) {
+		if (net_ratelimit()) {
+			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
+			       "TX packet to " MAC_FMT "\n",
+			       tkey->ieee->dev->name, MAC_ARG(hdr->addr1));
+		}
+		return -1;
+	}
+
 	if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 ||
 	    skb->len < hdr_len)
 		return -1;
 
-	hdr = (struct ieee80211_hdr *)skb->data;
 	if (!tkey->tx_phase1_done) {
 		tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
 				   tkey->tx_iv32);
@@ -325,10 +340,20 @@ static int ieee80211_tkip_decrypt(struct
 	struct scatterlist sg;
 	int plen;
 
+	hdr = (struct ieee80211_hdr *)skb->data;
+
+	if (tkey->ieee->tkip_countermeasures) {
+		if (net_ratelimit()) {
+			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
+			       "received packet from " MAC_FMT "\n",
+			       tkey->ieee->dev->name, MAC_ARG(hdr->addr2));
+		}
+		return -1;
+	}
+
 	if (skb->len < hdr_len + 8 + 4)
 		return -1;
 
-	hdr = (struct ieee80211_hdr *)skb->data;
 	pos = skb->data + hdr_len;
 	keyidx = pos[3];
 	if (!(keyidx & (1 << 5))) {
diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c
index ebe1615..63e783f 100644
--- a/net/ieee80211/ieee80211_crypt_wep.c
+++ b/net/ieee80211/ieee80211_crypt_wep.c
@@ -37,7 +37,7 @@ struct prism2_wep_data {
 	struct crypto_tfm *tfm;
 };
 
-static void *prism2_wep_init(int keyidx)
+static void *prism2_wep_init(struct ieee80211_device *ieee, int keyidx)
 {
 	struct prism2_wep_data *priv;
 
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index e0337c8..9a125d4 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -280,17 +280,6 @@ ieee80211_rx_frame_decrypt(struct ieee80
 	hdr = (struct ieee80211_hdr *)skb->data;
 	hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 
-#ifdef CONFIG_IEEE80211_CRYPT_TKIP
-	if (ieee->tkip_countermeasures && strcmp(crypt->ops->name, "TKIP") == 0) {
-		if (net_ratelimit()) {
-			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
-			       "received packet from " MAC_FMT "\n",
-			       ieee->dev->name, MAC_ARG(hdr->addr2));
-		}
-		return -1;
-	}
-#endif
-
 	atomic_inc(&crypt->refcnt);
 	res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
 	atomic_dec(&crypt->refcnt);
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index 1a09448..435ef5a 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -157,20 +157,6 @@ static inline int ieee80211_encrypt_frag
 	struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx];
 	int res;
 
-#ifdef CONFIG_IEEE80211_CRYPT_TKIP
-	struct ieee80211_hdr *header;
-
-	if (ieee->tkip_countermeasures &&
-	    crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
-		header = (struct ieee80211_hdr *)frag->data;
-		if (net_ratelimit()) {
-			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
-			       "TX packet to " MAC_FMT "\n",
-			       ieee->dev->name, MAC_ARG(header->addr1));
-		}
-		return -1;
-	}
-#endif
 	/* To encrypt, frame format is:
 	 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
 
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index 04f0897..fc4e137 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -182,7 +182,7 @@ static inline char *ipw2100_translate_sc
 	if (iwe.u.data.length)
 		start = iwe_stream_add_point(start, stop, &iwe, custom);
 
-	if (ieee->wpa_enabled && network->wpa_ie_len) {
+	if (network->wpa_ie_len) {
 		char buf[MAX_WPA_IE_LEN * 2 + 30];
 
 		u8 *p = buf;
@@ -197,7 +197,7 @@ static inline char *ipw2100_translate_sc
 		start = iwe_stream_add_point(start, stop, &iwe, buf);
 	}
 
-	if (ieee->wpa_enabled && network->rsn_ie_len) {
+	if (network->rsn_ie_len) {
 		char buf[MAX_WPA_IE_LEN * 2 + 30];
 
 		u8 *p = buf;
@@ -351,7 +351,7 @@ int ieee80211_wx_set_encode(struct ieee8
 		}
 
 		if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
-			new_crypt->priv = new_crypt->ops->init(key);
+			new_crypt->priv = new_crypt->ops->init(ieee, key);
 
 		if (!new_crypt->ops || !new_crypt->priv) {
 			kfree(new_crypt);
---
0.99.8.GIT


--- NEW FILE 0167-ieee80211-Hardware-crypto-and-fragmentation-offload-support.txt ---
Subject: [PATCH] ieee80211: Hardware crypto and fragmentation offload support
From: James Ketrenos <jketreno linux intel com>
Date: 1127321634 -0500

tree 5322d496af90d03ffbec27292dc1a6268a746ede
parent 6c9364386ccb786e4a84427ab3ad712f0b7b8904
author James Ketrenos <jketreno linux intel com> 1124432367 -0500
committer James Ketrenos <jketreno linux intel com> 1127311810 -0500

Hardware crypto and fragmentation offload support added (Zhu Yi)

Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/net/ieee80211.h      |   46 +++++++++++++++++++++------------------
 net/ieee80211/ieee80211_tx.c |   27 ++++++++++++++++++-----
 net/ieee80211/ieee80211_wx.c |   50 ++++++++++++++++++++++++------------------
 3 files changed, 75 insertions(+), 48 deletions(-)

applies-to: f9af562b0bc70f7f75d0195aacf155fd3ec6628a
f1bf6638af9e9bbbb6fb0b769054fb7db1ae652f
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index ed06a94..fa14360 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -430,31 +430,34 @@ struct ieee80211_device;
 
 #include "ieee80211_crypt.h"
 
-#define SEC_KEY_1         (1<<0)
-#define SEC_KEY_2         (1<<1)
-#define SEC_KEY_3         (1<<2)
-#define SEC_KEY_4         (1<<3)
-#define SEC_KEY_MASK      (SEC_KEY_1 | SEC_KEY_2 | SEC_KEY_3 | SEC_KEY_4)
-#define SEC_ACTIVE_KEY    (1<<4)
-#define SEC_AUTH_MODE     (1<<5)
-#define SEC_UNICAST_GROUP (1<<6)
-#define SEC_LEVEL         (1<<7)
-#define SEC_ENABLED       (1<<8)
-
-#define SEC_LEVEL_0      0	/* None */
-#define SEC_LEVEL_1      1	/* WEP 40 and 104 bit */
-#define SEC_LEVEL_2      2	/* Level 1 + TKIP */
-#define SEC_LEVEL_2_CKIP 3	/* Level 1 + CKIP */
-#define SEC_LEVEL_3      4	/* Level 2 + CCMP */
-
-#define WEP_KEYS 4
-#define WEP_KEY_LEN 13
+#define SEC_KEY_1		(1<<0)
+#define SEC_KEY_2		(1<<1)
+#define SEC_KEY_3		(1<<2)
+#define SEC_KEY_4		(1<<3)
+#define SEC_ACTIVE_KEY		(1<<4)
+#define SEC_AUTH_MODE		(1<<5)
+#define SEC_UNICAST_GROUP	(1<<6)
+#define SEC_LEVEL		(1<<7)
+#define SEC_ENABLED		(1<<8)
+#define SEC_TGI_KEY_RESET	(1<<9)
+
+#define SEC_LEVEL_0		0	/* None */
+#define SEC_LEVEL_1		1	/* WEP 40 and 104 bit */
+#define SEC_LEVEL_2		2	/* Level 1 + TKIP */
+#define SEC_LEVEL_2_CKIP	3	/* Level 1 + CKIP */
+#define SEC_LEVEL_3		4	/* Level 2 + CCMP */
+
+#define WEP_KEYS		4
+#define WEP_KEY_LEN		13
+#define SCM_KEY_LEN		32
+#define SCM_TEMPORAL_KEY_LENGTH	16
 
 struct ieee80211_security {
 	u16 active_key:2,
-	    enabled:1, auth_mode:2, auth_algo:4, unicast_uses_group:1;
+	    enabled:1,
+	    auth_mode:2, auth_algo:4, unicast_uses_group:1, encrypt:1;
 	u8 key_sizes[WEP_KEYS];
-	u8 keys[WEP_KEYS][WEP_KEY_LEN];
+	u8 keys[WEP_KEYS][SCM_KEY_LEN];
 	u8 level;
 	u16 flags;
 } __attribute__ ((packed));
@@ -636,6 +639,7 @@ enum ieee80211_state {
 
 struct ieee80211_device {
 	struct net_device *dev;
+	struct ieee80211_security sec;
 
 	/* Bookkeeping structures */
 	struct net_device_stats stats;
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index 435ef5a..785e76f 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -231,7 +231,7 @@ int ieee80211_xmit(struct sk_buff *skb, 
 	int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
 	unsigned long flags;
 	struct net_device_stats *stats = &ieee->stats;
-	int ether_type, encrypt;
+	int ether_type, encrypt, host_encrypt;
 	int bytes, fc, hdr_len;
 	struct sk_buff *skb_frag;
 	struct ieee80211_hdr header = {	/* Ensure zero initialized */
@@ -262,7 +262,8 @@ int ieee80211_xmit(struct sk_buff *skb, 
 	crypt = ieee->crypt[ieee->tx_keyidx];
 
 	encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
-	    ieee->host_encrypt && crypt && crypt->ops;
+	    ieee->sec.encrypt;
+	host_encrypt = ieee->host_encrypt && encrypt;
 
 	if (!encrypt && ieee->ieee802_1x &&
 	    ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
@@ -280,7 +281,7 @@ int ieee80211_xmit(struct sk_buff *skb, 
 	/* Determine total amount of storage required for TXB packets */
 	bytes = skb->len + SNAP_SIZE + sizeof(u16);
 
-	if (encrypt)
+	if (host_encrypt)
 		fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
 		    IEEE80211_FCTL_PROTECTED;
 	else
@@ -320,7 +321,7 @@ int ieee80211_xmit(struct sk_buff *skb, 
 		bytes_per_frag -= IEEE80211_FCS_LEN;
 
 	/* Each fragment may need to have room for encryptiong pre/postfix */
-	if (encrypt)
+	if (host_encrypt)
 		bytes_per_frag -= crypt->ops->extra_prefix_len +
 		    crypt->ops->extra_postfix_len;
 
@@ -348,7 +349,7 @@ int ieee80211_xmit(struct sk_buff *skb, 
 	for (i = 0; i < nr_frags; i++) {
 		skb_frag = txb->fragments[i];
 
-		if (encrypt)
+		if (host_encrypt)
 			skb_reserve(skb_frag, crypt->ops->extra_prefix_len);
 
 		frag_hdr = (struct ieee80211_hdr *)skb_put(skb_frag, hdr_len);
@@ -380,8 +381,22 @@ int ieee80211_xmit(struct sk_buff *skb, 
 
 		/* Encryption routine will move the header forward in order
 		 * to insert the IV between the header and the payload */
-		if (encrypt)
+		if (host_encrypt)
 			ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
+
+		/* ipw2200/2915 Hardware encryption doesn't support TKIP MIC */
+		if (!ieee->host_encrypt && encrypt &&
+		    (ieee->sec.level == SEC_LEVEL_2) &&
+		    crypt && crypt->ops && crypt->ops->encrypt_msdu) {
+			int res = 0;
+			res = crypt->ops->encrypt_msdu(skb_frag, hdr_len,
+						       crypt->priv);
+			if (res < 0) {
+				IEEE80211_ERROR("TKIP MIC encryption failed\n");
+				goto failed;
+			}
+		}
+
 		if (ieee->config &
 		    (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
 			skb_put(skb_frag, 4);
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index fc4e137..f88c811 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -278,6 +278,7 @@ int ieee80211_wx_set_encode(struct ieee8
 	};
 	int i, key, key_provided, len;
 	struct ieee80211_crypt_data **crypt;
+	int host_crypto = ieee->host_encrypt || ieee->host_decrypt;
 
 	IEEE80211_DEBUG_WX("SET_ENCODE\n");
 
@@ -318,6 +319,7 @@ int ieee80211_wx_set_encode(struct ieee8
 
 		if (i == WEP_KEYS) {
 			sec.enabled = 0;
+			sec.encrypt = 0;
 			sec.level = SEC_LEVEL_0;
 			sec.flags |= SEC_ENABLED | SEC_LEVEL;
 		}
@@ -326,6 +328,7 @@ int ieee80211_wx_set_encode(struct ieee8
 	}
 
 	sec.enabled = 1;
+	sec.encrypt = 1;
 	sec.flags |= SEC_ENABLED;
 
 	if (*crypt != NULL && (*crypt)->ops != NULL &&
@@ -335,7 +338,7 @@ int ieee80211_wx_set_encode(struct ieee8
 		ieee80211_crypt_delayed_deinit(ieee, crypt);
 	}
 
-	if (*crypt == NULL) {
+	if (*crypt == NULL && host_crypto) {
 		struct ieee80211_crypt_data *new_crypt;
 
 		/* take WEP into use */
@@ -375,31 +378,34 @@ int ieee80211_wx_set_encode(struct ieee8
 				   key, escape_essid(sec.keys[key], len),
 				   erq->length, len);
 		sec.key_sizes[key] = len;
-		(*crypt)->ops->set_key(sec.keys[key], len, NULL,
-				       (*crypt)->priv);
+		if (*crypt)
+			(*crypt)->ops->set_key(sec.keys[key], len, NULL,
+					       (*crypt)->priv);
 		sec.flags |= (1 << key);
 		/* This ensures a key will be activated if no key is
 		 * explicitely set */
 		if (key == sec.active_key)
 			sec.flags |= SEC_ACTIVE_KEY;
+
 	} else {
-		len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
-					     NULL, (*crypt)->priv);
-		if (len == 0) {
-			/* Set a default key of all 0 */
-			IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
-					   key);
-			memset(sec.keys[key], 0, 13);
-			(*crypt)->ops->set_key(sec.keys[key], 13, NULL,
-					       (*crypt)->priv);
-			sec.key_sizes[key] = 13;
-			sec.flags |= (1 << key);
+		if (host_crypto) {
+			len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
+						     NULL, (*crypt)->priv);
+			if (len == 0) {
+				/* Set a default key of all 0 */
+				IEEE80211_DEBUG_WX("Setting key %d to all "
+						   "zero.\n", key);
+				memset(sec.keys[key], 0, 13);
+				(*crypt)->ops->set_key(sec.keys[key], 13, NULL,
+						       (*crypt)->priv);
+				sec.key_sizes[key] = 13;
+				sec.flags |= (1 << key);
+			}
 		}
-
 		/* No key data - just set the default TX key index */
 		if (key_provided) {
-			IEEE80211_DEBUG_WX
-			    ("Setting key %d to default Tx key.\n", key);
+			IEEE80211_DEBUG_WX("Setting key %d to default Tx "
+					   "key.\n", key);
 			ieee->tx_keyidx = key;
 			sec.active_key = key;
 			sec.flags |= SEC_ACTIVE_KEY;
@@ -442,6 +448,7 @@ int ieee80211_wx_get_encode(struct ieee8
 	struct iw_point *erq = &(wrqu->encoding);
 	int len, key;
 	struct ieee80211_crypt_data *crypt;
+	struct ieee80211_security *sec = &ieee->sec;
 
 	IEEE80211_DEBUG_WX("GET_ENCODE\n");
 
@@ -456,13 +463,13 @@ int ieee80211_wx_get_encode(struct ieee8
 	crypt = ieee->crypt[key];
 	erq->flags = key + 1;
 
-	if (crypt == NULL || crypt->ops == NULL) {
+	if (!sec->enabled) {
 		erq->length = 0;
 		erq->flags |= IW_ENCODE_DISABLED;
 		return 0;
 	}
 
-	if (strcmp(crypt->ops->name, "WEP") != 0) {
+	if (sec->level != SEC_LEVEL_1) {
 		/* only WEP is supported with wireless extensions, so just
 		 * report that encryption is used */
 		erq->length = 0;
@@ -470,9 +477,10 @@ int ieee80211_wx_get_encode(struct ieee8
 		return 0;
 	}
 
-	len = crypt->ops->get_key(keybuf, WEP_KEY_LEN, NULL, crypt->priv);
-	erq->length = (len >= 0 ? len : 0);
+	len = sec->key_sizes[key];
+	memcpy(keybuf, sec->keys[key], len);
 
+	erq->length = (len >= 0 ? len : 0);
 	erq->flags |= IW_ENCODE_ENABLED;
 
 	if (ieee->open_wep)
---
0.99.8.GIT


--- NEW FILE 0168-ieee80211-Fix-time-calculation-switching-to-use-jiffies_to_msecs.txt ---
Subject: [PATCH] ieee80211: Fix time calculation, switching to use jiffies_to_msecs
From: James Ketrenos <jketreno linux intel com>
Date: 1127321647 -0500

tree b9cdd7058b787807655ea6f125e2adbf8d26c863
parent 85d9b2bddfcf3ed2eb4d061947c25c6a832891ab
author Zhu Yi <jketreno io (none)> 1124435212 -0500
committer James Ketrenos <jketreno linux intel com> 1127312152 -0500

Fix time calculation, switching to use jiffies_to_msecs.

Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 net/ieee80211/ieee80211_wx.c |   13 +++++++------
 1 files changed, 7 insertions(+), 6 deletions(-)

applies-to: 5cf2dca63f88c1709ae8ee9d913c7f819bfc6ce8
42e349fd10d471d9ae6955a7f12523291c0193e6
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index f88c811..df64bf3 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -32,6 +32,7 @@
 
 #include <linux/kmod.h>
 #include <linux/module.h>
+#include <linux/jiffies.h>
 
 #include <net/ieee80211.h>
 #include <linux/wireless.h>
@@ -217,8 +218,8 @@ static inline char *ipw2100_translate_sc
 	iwe.cmd = IWEVCUSTOM;
 	p = custom;
 	p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
-		      " Last beacon: %lums ago",
-		      (jiffies - network->last_scanned) / (HZ / 100));
+		      " Last beacon: %dms ago",
+		      jiffies_to_msecs(jiffies - network->last_scanned));
 	iwe.u.data.length = p - custom;
 	if (iwe.u.data.length)
 		start = iwe_stream_add_point(start, stop, &iwe, custom);
@@ -248,13 +249,13 @@ int ieee80211_wx_get_scan(struct ieee802
 			ev = ipw2100_translate_scan(ieee, ev, stop, network);
 		else
 			IEEE80211_DEBUG_SCAN("Not showing network '%s ("
-					     MAC_FMT ")' due to age (%lums).\n",
+					     MAC_FMT ")' due to age (%dms).\n",
 					     escape_essid(network->ssid,
 							  network->ssid_len),
 					     MAC_ARG(network->bssid),
-					     (jiffies -
-					      network->last_scanned) / (HZ /
-									100));
+					     jiffies_to_msecs(jiffies -
+							      network->
+							      last_scanned));
 	}
 
 	spin_unlock_irqrestore(&ieee->lock, flags);
---
0.99.8.GIT


--- NEW FILE 0169-ieee80211-Fix-kernel-Oops-when-module-unload.txt ---
Subject: [PATCH] ieee80211: Fix kernel Oops when module unload
From: James Ketrenos <jketreno linux intel com>
Date: 1127321655 -0500

tree b69e983266840983183a00f5ac02c66d5270ca47
parent cdd6372949b76694622ed74fe36e1dd17a92eb71
author Zhu Yi <jketreno io (none)> 1124435425 -0500
committer James Ketrenos <jketreno linux intel com> 1127312421 -0500

Fix kernel Oops when module unload.

Export a new function ieee80211_crypt_quiescing from ieee80211. Device
drivers call it to make the host crypto stack enter the quiescence
state, which means "process existing requests, but don't accept new
ones". This is usually called during a driver's host crypto data
structure free (module unload) path.

Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/net/ieee80211.h          |    1 +
 include/net/ieee80211_crypt.h    |    1 +
 net/ieee80211/ieee80211_crypt.c  |   33 +++++++++++++++++++++++++++------
 net/ieee80211/ieee80211_module.c |    2 ++
 4 files changed, 31 insertions(+), 6 deletions(-)

applies-to: 9c7ce6a08a8b237b3fb9c53b7ad506d0343f0a02
0ad0c3c64484b1458b51167bd3e614d8d9d070f8
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index fa14360..6cc0674 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -684,6 +684,7 @@ struct ieee80211_device {
 	struct ieee80211_crypt_data *crypt[WEP_KEYS];
 	int tx_keyidx;		/* default TX key index (crypt[tx_keyidx]) */
 	struct timer_list crypt_deinit_timer;
+	int crypt_quiesced;
 
 	int bcrx_sta_key;	/* use individual keys to override default keys even
 				 * with RX of broad/multicast frames */
diff --git a/include/net/ieee80211_crypt.h b/include/net/ieee80211_crypt.h
index e2064ed..536e9a9 100644
--- a/include/net/ieee80211_crypt.h
+++ b/include/net/ieee80211_crypt.h
@@ -82,5 +82,6 @@ void ieee80211_crypt_deinit_entries(stru
 void ieee80211_crypt_deinit_handler(unsigned long);
 void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
 				    struct ieee80211_crypt_data **crypt);
+void ieee80211_crypt_quiescing(struct ieee80211_device *ieee);
 
 #endif
diff --git a/net/ieee80211/ieee80211_crypt.c b/net/ieee80211/ieee80211_crypt.c
index 0c36629..60d3166 100644
--- a/net/ieee80211/ieee80211_crypt.c
+++ b/net/ieee80211/ieee80211_crypt.c
@@ -44,6 +44,10 @@ void ieee80211_crypt_deinit_entries(stru
 	unsigned long flags;
 
 	spin_lock_irqsave(&ieee->lock, flags);
+
+	if (list_empty(&ieee->crypt_deinit_list))
+		goto unlock;
+
 	for (ptr = ieee->crypt_deinit_list.next, n = ptr->next;
 	     ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) {
 		entry = list_entry(ptr, struct ieee80211_crypt_data, list);
@@ -59,21 +63,35 @@ void ieee80211_crypt_deinit_entries(stru
 		}
 		kfree(entry);
 	}
+      unlock:
+	spin_unlock_irqrestore(&ieee->lock, flags);
+}
+
+/* After this, crypt_deinit_list won't accept new members */
+void ieee80211_crypt_quiescing(struct ieee80211_device *ieee)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ieee->lock, flags);
+	ieee->crypt_quiesced = 1;
 	spin_unlock_irqrestore(&ieee->lock, flags);
 }
 
 void ieee80211_crypt_deinit_handler(unsigned long data)
 {
 	struct ieee80211_device *ieee = (struct ieee80211_device *)data;
+	unsigned long flags;
 
 	ieee80211_crypt_deinit_entries(ieee, 0);
-	if (!list_empty(&ieee->crypt_deinit_list)) {
+
+	spin_lock_irqsave(&ieee->lock, flags);
+	if (!list_empty(&ieee->crypt_deinit_list) && !ieee->crypt_quiesced) {
 		printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
 		       "deletion list\n", ieee->dev->name);
 		ieee->crypt_deinit_timer.expires = jiffies + HZ;
 		add_timer(&ieee->crypt_deinit_timer);
 	}
-
+	spin_unlock_irqrestore(&ieee->lock, flags);
 }
 
 void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
@@ -93,10 +111,12 @@ void ieee80211_crypt_delayed_deinit(stru
 	 * locking. */
 
 	spin_lock_irqsave(&ieee->lock, flags);
-	list_add(&tmp->list, &ieee->crypt_deinit_list);
-	if (!timer_pending(&ieee->crypt_deinit_timer)) {
-		ieee->crypt_deinit_timer.expires = jiffies + HZ;
-		add_timer(&ieee->crypt_deinit_timer);
+	if (!ieee->crypt_quiesced) {
+		list_add(&tmp->list, &ieee->crypt_deinit_list);
+		if (!timer_pending(&ieee->crypt_deinit_timer)) {
+			ieee->crypt_deinit_timer.expires = jiffies + HZ;
+			add_timer(&ieee->crypt_deinit_timer);
+		}
 	}
 	spin_unlock_irqrestore(&ieee->lock, flags);
 }
@@ -250,6 +270,7 @@ static void __exit ieee80211_crypto_dein
 EXPORT_SYMBOL(ieee80211_crypt_deinit_entries);
 EXPORT_SYMBOL(ieee80211_crypt_deinit_handler);
 EXPORT_SYMBOL(ieee80211_crypt_delayed_deinit);
+EXPORT_SYMBOL(ieee80211_crypt_quiescing);
 
 EXPORT_SYMBOL(ieee80211_register_crypto_ops);
 EXPORT_SYMBOL(ieee80211_unregister_crypto_ops);
diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c
index 4b43ae1..82a4fd7 100644
--- a/net/ieee80211/ieee80211_module.c
+++ b/net/ieee80211/ieee80211_module.c
@@ -138,6 +138,7 @@ struct net_device *alloc_ieee80211(int s
 	init_timer(&ieee->crypt_deinit_timer);
 	ieee->crypt_deinit_timer.data = (unsigned long)ieee;
 	ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;
+	ieee->crypt_quiesced = 0;
 
 	spin_lock_init(&ieee->lock);
 
@@ -161,6 +162,7 @@ void free_ieee80211(struct net_device *d
 
 	int i;
 
+	ieee80211_crypt_quiescing(ieee);
 	del_timer_sync(&ieee->crypt_deinit_timer);
 	ieee80211_crypt_deinit_entries(ieee, 1);
 
---
0.99.8.GIT


--- NEW FILE 0170-ieee80211-Allow-drivers-to-fix-an-issue-when-using-wpa_supplicant-with-WEP.txt ---
Subject: [PATCH] ieee80211: Allow drivers to fix an issue when using wpa_supplicant with WEP
From: James Ketrenos <jketreno linux intel com>
Date: 1127321662 -0500

tree 898fedef6ca1b5b58b8bdf7e6d8894a78bbde4cd
parent 8720fff53090ae428d2159332b6f4b2749dea10f
author Zhu Yi <jketreno io (none)> 1124435746 -0500
committer James Ketrenos <jketreno linux intel com> 1127312509 -0500

Allow drivers to fix an issue when using wpa_supplicant with WEP.

The problem is introduced by the hwcrypto patch. We changed indicator of
the encryption request from the upper layer (i.e. wpa_supplicant):

In the original host based crypto the driver could use: crypt &&
crypt->ops.

In the new hardware based crypto, the driver should use the flags
specified in ieee->sec.encrypt.

Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/net/ieee80211.h      |    2 +-
 net/ieee80211/ieee80211_wx.c |    7 +++----
 2 files changed, 4 insertions(+), 5 deletions(-)

applies-to: 4ff20e24d22523603c51d9cd876ae0e5b1714531
259bf1fd8a7cc0f6b47fd8a9ac5e2dfc33182a3d
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 6cc0674..c7ab7cd 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -439,7 +439,7 @@ struct ieee80211_device;
 #define SEC_UNICAST_GROUP	(1<<6)
 #define SEC_LEVEL		(1<<7)
 #define SEC_ENABLED		(1<<8)
-#define SEC_TGI_KEY_RESET	(1<<9)
+#define SEC_ENCRYPT		(1<<9)
 
 #define SEC_LEVEL_0		0	/* None */
 #define SEC_LEVEL_1		1	/* WEP 40 and 104 bit */
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index df64bf3..49afea7 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -322,7 +322,7 @@ int ieee80211_wx_set_encode(struct ieee8
 			sec.enabled = 0;
 			sec.encrypt = 0;
 			sec.level = SEC_LEVEL_0;
-			sec.flags |= SEC_ENABLED | SEC_LEVEL;
+			sec.flags |= SEC_ENABLED | SEC_LEVEL | SEC_ENCRYPT;
 		}
 
 		goto done;
@@ -330,7 +330,7 @@ int ieee80211_wx_set_encode(struct ieee8
 
 	sec.enabled = 1;
 	sec.encrypt = 1;
-	sec.flags |= SEC_ENABLED;
+	sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
 
 	if (*crypt != NULL && (*crypt)->ops != NULL &&
 	    strcmp((*crypt)->ops->name, "WEP") != 0) {
@@ -412,8 +412,6 @@ int ieee80211_wx_set_encode(struct ieee8
 			sec.flags |= SEC_ACTIVE_KEY;
 		}
 	}
-
-      done:
 	ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
 	sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
 	sec.flags |= SEC_AUTH_MODE;
@@ -425,6 +423,7 @@ int ieee80211_wx_set_encode(struct ieee8
 	sec.flags |= SEC_LEVEL;
 	sec.level = SEC_LEVEL_1;	/* 40 and 104 bit WEP */
 
+      done:
 	if (ieee->set_security)
 		ieee->set_security(dev, &sec);
 
---
0.99.8.GIT


--- NEW FILE 0171-ieee82011-Added-WE-18-support-to-default-wireless-extension-handler.txt ---
Subject: [PATCH] ieee82011: Added WE-18 support to default wireless extension handler
From: James Ketrenos <jketreno linux intel com>
Date: 1127321670 -0500

tree 1536f39c18756698d033da72c49300a561be1289
parent 07172d7c9f10ee3d05d6f6489ba6d6ee2628da06
author Liu Hong <hong liu intel com> 1124436225 -0500
committer James Ketrenos <jketreno linux intel com> 1127312664 -0500

Added WE-18 support to default wireless extension handler in ieee80211
subsystem.

Updated patch since last send to account for ieee80211_device parameter
being added to the crypto init method.

Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/net/ieee80211.h      |   14 ++
 net/ieee80211/ieee80211_wx.c |  238 +++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 244 insertions(+), 8 deletions(-)

applies-to: 6c59c778280f899929c3d09c7f5564d80da830c2
e0d369d1d969fc9e4fd08a20f6dad04d369aceea
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index c7ab7cd..dfc5d65 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -447,6 +447,11 @@ struct ieee80211_device;
 #define SEC_LEVEL_2_CKIP	3	/* Level 1 + CKIP */
 #define SEC_LEVEL_3		4	/* Level 2 + CCMP */
 
+#define SEC_ALG_NONE		0
+#define SEC_ALG_WEP		1
+#define SEC_ALG_TKIP		2
+#define SEC_ALG_CCMP		3
+
 #define WEP_KEYS		4
 #define WEP_KEY_LEN		13
 #define SCM_KEY_LEN		32
@@ -456,6 +461,7 @@ struct ieee80211_security {
 	u16 active_key:2,
 	    enabled:1,
 	    auth_mode:2, auth_algo:4, unicast_uses_group:1, encrypt:1;
+	u8 encode_alg[WEP_KEYS];
 	u8 key_sizes[WEP_KEYS];
 	u8 keys[WEP_KEYS][SCM_KEY_LEN];
 	u8 level;
@@ -824,6 +830,14 @@ extern int ieee80211_wx_set_encode(struc
 extern int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
 				   struct iw_request_info *info,
 				   union iwreq_data *wrqu, char *key);
+#if WIRELESS_EXT > 17
+extern int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
+				      struct iw_request_info *info,
+				      union iwreq_data *wrqu, char *extra);
+extern int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee,
+				      struct iw_request_info *info,
+				      union iwreq_data *wrqu, char *extra);
+#endif
 
 extern inline void ieee80211_increment_scans(struct ieee80211_device *ieee)
 {
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index 49afea7..db66217 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -422,6 +422,7 @@ int ieee80211_wx_set_encode(struct ieee8
 	 * TODO: When WPA is added this is one place that needs to change */
 	sec.flags |= SEC_LEVEL;
 	sec.level = SEC_LEVEL_1;	/* 40 and 104 bit WEP */
+	sec.encode_alg[key] = SEC_ALG_WEP;
 
       done:
 	if (ieee->set_security)
@@ -469,14 +470,6 @@ int ieee80211_wx_get_encode(struct ieee8
 		return 0;
 	}
 
-	if (sec->level != SEC_LEVEL_1) {
-		/* only WEP is supported with wireless extensions, so just
-		 * report that encryption is used */
-		erq->length = 0;
-		erq->flags |= IW_ENCODE_ENABLED;
-		return 0;
-	}
-
 	len = sec->key_sizes[key];
 	memcpy(keybuf, sec->keys[key], len);
 
@@ -491,6 +484,235 @@ int ieee80211_wx_get_encode(struct ieee8
 	return 0;
 }
 
+#if WIRELESS_EXT > 17
+int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
+			       struct iw_request_info *info,
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct net_device *dev = ieee->dev;
+	struct iw_point *encoding = &wrqu->encoding;
+	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+	int i, idx, ret = 0;
+	const char *alg, *module;
+	struct ieee80211_crypto_ops *ops;
+	struct ieee80211_crypt_data **crypt;
+
+	struct ieee80211_security sec = {
+		.flags = 0,
+	};
+
+	idx = encoding->flags & IW_ENCODE_INDEX;
+	if (idx) {
+		if (idx < 1 || idx > WEP_KEYS)
+			return -EINVAL;
+		idx--;
+	} else
+		idx = ieee->tx_keyidx;
+
+	if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
+		crypt = &ieee->crypt[idx];
+	else {
+		if (idx != 0)
+			return -EINVAL;
+		if (ieee->iw_mode == IW_MODE_INFRA)
+			crypt = &ieee->crypt[idx];
+		else
+			return -EINVAL;
+	}
+
+	sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
+	if ((encoding->flags & IW_ENCODE_DISABLED) ||
+	    ext->alg == IW_ENCODE_ALG_NONE) {
+		if (*crypt)
+			ieee80211_crypt_delayed_deinit(ieee, crypt);
+
+		for (i = 0; i < WEP_KEYS; i++)
+			if (ieee->crypt[i] != NULL)
+				break;
+
+		if (i == WEP_KEYS) {
+			sec.enabled = 0;
+			sec.encrypt = 0;
+			sec.level = SEC_LEVEL_0;
+			sec.flags |= SEC_LEVEL;
+		}
+		goto done;
+	}
+
+	sec.enabled = 1;
+	sec.encrypt = 1;
+
+	if (!(ieee->host_encrypt || ieee->host_decrypt))
+		goto skip_host_crypt;
+
+	switch (ext->alg) {
+	case IW_ENCODE_ALG_WEP:
+		alg = "WEP";
+		module = "ieee80211_crypt_wep";
+		break;
+	case IW_ENCODE_ALG_TKIP:
+		alg = "TKIP";
+		module = "ieee80211_crypt_tkip";
+		break;
+	case IW_ENCODE_ALG_CCMP:
+		alg = "CCMP";
+		module = "ieee80211_crypt_ccmp";
+		break;
+	default:
+		IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
+				   dev->name, ext->alg);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	ops = ieee80211_get_crypto_ops(alg);
+	if (ops == NULL) {
+		request_module(module);
+		ops = ieee80211_get_crypto_ops(alg);
+	}
+	if (ops == NULL) {
+		IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
+				   dev->name, ext->alg);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (*crypt == NULL || (*crypt)->ops != ops) {
+		struct ieee80211_crypt_data *new_crypt;
+
+		ieee80211_crypt_delayed_deinit(ieee, crypt);
+
+		new_crypt = (struct ieee80211_crypt_data *)
+		    kmalloc(sizeof(*new_crypt), GFP_KERNEL);
+		if (new_crypt == NULL) {
+			ret = -ENOMEM;
+			goto done;
+		}
+		memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
+		new_crypt->ops = ops;
+		if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+			new_crypt->priv = new_crypt->ops->init(ieee, idx);
+		if (new_crypt->priv == NULL) {
+			kfree(new_crypt);
+			ret = -EINVAL;
+			goto done;
+		}
+		*crypt = new_crypt;
+	}
+
+	if (ext->key_len > 0 && (*crypt)->ops->set_key &&
+	    (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
+				   (*crypt)->priv) < 0) {
+		IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
+		ret = -EINVAL;
+		goto done;
+	}
+
+      skip_host_crypt:
+	if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
+		ieee->tx_keyidx = idx;
+		sec.active_key = idx;
+		sec.flags |= SEC_ACTIVE_KEY;
+	}
+
+	if (ext->alg != IW_ENCODE_ALG_NONE) {
+		memcpy(sec.keys[idx], ext->key, ext->key_len);
+		sec.key_sizes[idx] = ext->key_len;
+		sec.flags |= (1 << idx);
+		if (ext->alg == IW_ENCODE_ALG_WEP) {
+			sec.encode_alg[idx] = SEC_ALG_WEP;
+			sec.flags |= SEC_LEVEL;
+			sec.level = SEC_LEVEL_1;
+		} else if (ext->alg == IW_ENCODE_ALG_TKIP) {
+			sec.encode_alg[idx] = SEC_ALG_TKIP;
+			sec.flags |= SEC_LEVEL;
+			sec.level = SEC_LEVEL_2;
+		} else if (ext->alg == IW_ENCODE_ALG_CCMP) {
+			sec.encode_alg[idx] = SEC_ALG_CCMP;
+			sec.flags |= SEC_LEVEL;
+			sec.level = SEC_LEVEL_3;
+		}
+	}
+      done:
+	if (ieee->set_security)
+		ieee->set_security(ieee->dev, &sec);
+
+	/*
+	 * Do not reset port if card is in Managed mode since resetting will
+	 * generate new IEEE 802.11 authentication which may end up in looping
+	 * with IEEE 802.1X. If your hardware requires a reset after WEP
+	 * configuration (for example... Prism2), implement the reset_port in
+	 * the callbacks structures used to initialize the 802.11 stack.
+	 */
+	if (ieee->reset_on_keychange &&
+	    ieee->iw_mode != IW_MODE_INFRA &&
+	    ieee->reset_port && ieee->reset_port(dev)) {
+		IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee,
+			       struct iw_request_info *info,
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct iw_point *encoding = &wrqu->encoding;
+	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+	struct ieee80211_security *sec = &ieee->sec;
+	int idx, max_key_len;
+
+	max_key_len = encoding->length - sizeof(*ext);
+	if (max_key_len < 0)
+		return -EINVAL;
+
+	idx = encoding->flags & IW_ENCODE_INDEX;
+	if (idx) {
+		if (idx < 1 || idx > WEP_KEYS)
+			return -EINVAL;
+		idx--;
+	} else
+		idx = ieee->tx_keyidx;
+
+	if (!ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
+		if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
+			return -EINVAL;
+
+	encoding->flags = idx + 1;
+	memset(ext, 0, sizeof(*ext));
+
+	if (!sec->enabled) {
+		ext->alg = IW_ENCODE_ALG_NONE;
+		ext->key_len = 0;
+		encoding->flags |= IW_ENCODE_DISABLED;
+	} else {
+		if (sec->encode_alg[idx] == SEC_ALG_WEP)
+			ext->alg = IW_ENCODE_ALG_WEP;
+		else if (sec->encode_alg[idx] == SEC_ALG_TKIP)
+			ext->alg = IW_ENCODE_ALG_TKIP;
+		else if (sec->encode_alg[idx] == SEC_ALG_CCMP)
+			ext->alg = IW_ENCODE_ALG_CCMP;
+		else
+			return -EINVAL;
+
+		ext->key_len = sec->key_sizes[idx];
+		memcpy(ext->key, sec->keys[idx], ext->key_len);
+		encoding->flags |= IW_ENCODE_ENABLED;
+		if (ext->key_len &&
+		    (ext->alg == IW_ENCODE_ALG_TKIP ||
+		     ext->alg == IW_ENCODE_ALG_CCMP))
+			ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
+
+	}
+
+	return 0;
+}
+
+EXPORT_SYMBOL(ieee80211_wx_set_encodeext);
+EXPORT_SYMBOL(ieee80211_wx_get_encodeext);
+#endif
+
 EXPORT_SYMBOL(ieee80211_wx_get_scan);
 EXPORT_SYMBOL(ieee80211_wx_set_encode);
 EXPORT_SYMBOL(ieee80211_wx_get_encode);
---
0.99.8.GIT


--- NEW FILE 0172-ieee80211-Renamed-ieee80211_hdr-to-ieee80211_hdr_3addr.txt ---
Subject: [PATCH] ieee80211: Renamed ieee80211_hdr to ieee80211_hdr_3addr
From: James Ketrenos <jketreno linux intel com>
Date: 1127321676 -0500

tree e9c18b2c8e5ad446a4d213243c2dcf9fd1652a7b
parent 4e97ad6ae7084a4f741e94e76c41c68bc7c5a76a
author James Ketrenos <jketreno linux intel com> 1124444315 -0500
committer James Ketrenos <jketreno linux intel com> 1127312922 -0500

Renamed ieee80211_hdr to ieee80211_hdr_3addr and modified ieee80211_hdr
to just contain the frame_ctrl and duration_id.

Changed uses of ieee80211_hdr to ieee80211_hdr_4addr or
ieee80211_hdr_3addr based on what was expected for that portion of code.

NOTE: This requires changes to ipw2100, ipw2200, hostap, and atmel
drivers.

Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/net/ieee80211.h              |  117 ++++++++++++++++++++++++++--------
 net/ieee80211/ieee80211_crypt_ccmp.c |   10 +--
 net/ieee80211/ieee80211_crypt_tkip.c |   27 ++++----
 net/ieee80211/ieee80211_rx.c         |   32 +++++----
 net/ieee80211/ieee80211_tx.c         |    7 +-
 5 files changed, 129 insertions(+), 64 deletions(-)

applies-to: 9ce4d6a3938960b35c3d7c7b3da4bb546f8b1d95
ee34af37c095482b9dba254b9cd7cb5e65e9a25e
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index dfc5d65..ebe7e41 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -33,33 +33,13 @@
    represents the 2304 bytes of real data, plus a possible 8 bytes of
    WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */
 
-#define IEEE80211_HLEN			30
-#define IEEE80211_FRAME_LEN		(IEEE80211_DATA_LEN + IEEE80211_HLEN)
-
-struct ieee80211_hdr {
-	__le16 frame_ctl;
-	__le16 duration_id;
-	u8 addr1[ETH_ALEN];
-	u8 addr2[ETH_ALEN];
-	u8 addr3[ETH_ALEN];
-	__le16 seq_ctl;
-	u8 addr4[ETH_ALEN];
-} __attribute__ ((packed));
-
-struct ieee80211_hdr_3addr {
-	__le16 frame_ctl;
-	__le16 duration_id;
-	u8 addr1[ETH_ALEN];
-	u8 addr2[ETH_ALEN];
-	u8 addr3[ETH_ALEN];
-	__le16 seq_ctl;
-} __attribute__ ((packed));
-
 #define IEEE80211_1ADDR_LEN 10
 #define IEEE80211_2ADDR_LEN 16
 #define IEEE80211_3ADDR_LEN 24
 #define IEEE80211_4ADDR_LEN 30
 #define IEEE80211_FCS_LEN    4
+#define IEEE80211_HLEN			(IEEE80211_4ADDR_LEN)
+#define IEEE80211_FRAME_LEN		(IEEE80211_DATA_LEN + IEEE80211_HLEN)
 
 #define MIN_FRAG_THRESHOLD     256U
 #define	MAX_FRAG_THRESHOLD     2346U
@@ -515,6 +495,51 @@ enum ieee80211_mfie {
 	MFIE_TYPE_GENERIC = 221,
 };
 
+/* Minimal header; can be used for passing 802.11 frames with sufficient
+ * information to determine what type of underlying data type is actually
+ * stored in the data. */
+struct ieee80211_hdr {
+	u16 frame_ctl;
+	u16 duration_id;
+	u8 payload[0];
+} __attribute__ ((packed));
+
+struct ieee80211_hdr_1addr {
+	u16 frame_ctl;
+	u16 duration_id;
+	u8 addr1[ETH_ALEN];
+	u8 payload[0];
+} __attribute__ ((packed));
+
+struct ieee80211_hdr_2addr {
+	u16 frame_ctl;
+	u16 duration_id;
+	u8 addr1[ETH_ALEN];
+	u8 addr2[ETH_ALEN];
+	u8 payload[0];
+} __attribute__ ((packed));
+
+struct ieee80211_hdr_3addr {
+	u16 frame_ctl;
+	u16 duration_id;
+	u8 addr1[ETH_ALEN];
+	u8 addr2[ETH_ALEN];
+	u8 addr3[ETH_ALEN];
+	u16 seq_ctl;
+	u8 payload[0];
+} __attribute__ ((packed));
+
+struct ieee80211_hdr_4addr {
+	u16 frame_ctl;
+	u16 duration_id;
+	u8 addr1[ETH_ALEN];
+	u8 addr2[ETH_ALEN];
+	u8 addr3[ETH_ALEN];
+	u16 seq_ctl;
+	u8 addr4[ETH_ALEN];
+	u8 payload[0];
+} __attribute__ ((packed));
+
 struct ieee80211_info_element {
 	u8 id;
 	u8 len;
@@ -538,7 +563,7 @@ struct ieee80211_info_element {
 	u16 status;
 */
 
-struct ieee80211_authentication {
+struct ieee80211_auth {
 	struct ieee80211_hdr_3addr header;
 	__le16 algorithm;
 	__le16 transaction;
@@ -546,6 +571,17 @@ struct ieee80211_authentication {
 	struct ieee80211_info_element info_element[0];
 } __attribute__ ((packed));
 
+struct ieee80211_disassoc {
+	struct ieee80211_hdr_3addr header;
+	u16 reason_code;
+	struct ieee80211_info_element info_element[0];
+} __attribute__ ((packed));
+
+struct ieee80211_probe_request {
+	struct ieee80211_hdr_3addr header;
+	struct ieee80211_info_element info_element[0];
+} __attribute__ ((packed));
+
 struct ieee80211_probe_response {
 	struct ieee80211_hdr_3addr header;
 	u32 time_stamp[2];
@@ -554,14 +590,25 @@ struct ieee80211_probe_response {
 	struct ieee80211_info_element info_element[0];
 } __attribute__ ((packed));
 
-struct ieee80211_assoc_request_frame {
+/* Alias beacon for probe_response */
+#define ieee80211_beacon ieee80211_probe_response
+
+struct ieee80211_assoc_request {
+	struct ieee80211_hdr_3addr header;
+	u16 capability;
+	u16 listen_interval;
+	struct ieee80211_info_element info_element[0];
+} __attribute__ ((packed));
+
+struct ieee80211_reassoc_request {
+	struct ieee80211_hdr_3addr header;
 	__le16 capability;
 	__le16 listen_interval;
 	u8 current_ap[ETH_ALEN];
 	struct ieee80211_info_element info_element[0];
 } __attribute__ ((packed));
 
-struct ieee80211_assoc_response_frame {
+struct ieee80211_assoc_response {
 	struct ieee80211_hdr_3addr header;
 	__le16 capability;
 	__le16 status;
@@ -572,7 +619,8 @@ struct ieee80211_assoc_response_frame {
 struct ieee80211_txb {
 	u8 nr_frags;
 	u8 encrypted;
-	u16 reserved;
+	u8 rts_included;
+	u8 reserved;
 	u16 frag_size;
 	u16 payload_size;
 	struct sk_buff *fragments[0];
@@ -803,6 +851,21 @@ extern inline int ieee80211_get_hdrlen(u
 	return hdrlen;
 }
 
+extern inline u8 *ieee80211_get_payload(struct ieee80211_hdr *hdr)
+{
+	switch (ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl))) {
+	case IEEE80211_1ADDR_LEN:
+		return ((struct ieee80211_hdr_1addr *)hdr)->payload;
+	case IEEE80211_2ADDR_LEN:
+		return ((struct ieee80211_hdr_2addr *)hdr)->payload;
+	case IEEE80211_3ADDR_LEN:
+		return ((struct ieee80211_hdr_3addr *)hdr)->payload;
+	case IEEE80211_4ADDR_LEN:
+		return ((struct ieee80211_hdr_4addr *)hdr)->payload;
+	}
+
+}
+
 /* ieee80211.c */
 extern void free_ieee80211(struct net_device *dev);
 extern struct net_device *alloc_ieee80211(int sizeof_priv);
@@ -817,7 +880,7 @@ extern void ieee80211_txb_free(struct ie
 extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 			struct ieee80211_rx_stats *rx_stats);
 extern void ieee80211_rx_mgt(struct ieee80211_device *ieee,
-			     struct ieee80211_hdr *header,
+			     struct ieee80211_hdr_4addr *header,
 			     struct ieee80211_rx_stats *stats);
 
 /* ieee80211_wx.c */
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c
index 1e6644b..d3b5cde 100644
--- a/net/ieee80211/ieee80211_crypt_ccmp.c
+++ b/net/ieee80211/ieee80211_crypt_ccmp.c
@@ -119,7 +119,7 @@ static inline void xor_block(u8 * b, u8 
 }
 
 static void ccmp_init_blocks(struct crypto_tfm *tfm,
-			     struct ieee80211_hdr *hdr,
+			     struct ieee80211_hdr_4addr *hdr,
 			     u8 * pn, size_t dlen, u8 * b0, u8 * auth, u8 * s0)
 {
 	u8 *pos, qc = 0;
@@ -196,7 +196,7 @@ static int ieee80211_ccmp_encrypt(struct
 	struct ieee80211_ccmp_data *key = priv;
 	int data_len, i, blocks, last, len;
 	u8 *pos, *mic;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 	u8 *b0 = key->tx_b0;
 	u8 *b = key->tx_b;
 	u8 *e = key->tx_e;
@@ -229,7 +229,7 @@ static int ieee80211_ccmp_encrypt(struct
 	*pos++ = key->tx_pn[1];
 	*pos++ = key->tx_pn[0];
 
-	hdr = (struct ieee80211_hdr *)skb->data;
+	hdr = (struct ieee80211_hdr_4addr *)skb->data;
 	ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
 
 	blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
@@ -258,7 +258,7 @@ static int ieee80211_ccmp_decrypt(struct
 {
 	struct ieee80211_ccmp_data *key = priv;
 	u8 keyidx, *pos;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 	u8 *b0 = key->rx_b0;
 	u8 *b = key->rx_b;
 	u8 *a = key->rx_a;
@@ -272,7 +272,7 @@ static int ieee80211_ccmp_decrypt(struct
 		return -1;
 	}
 
-	hdr = (struct ieee80211_hdr *)skb->data;
+	hdr = (struct ieee80211_hdr_4addr *)skb->data;
 	pos = skb->data + hdr_len;
 	keyidx = pos[3];
 	if (!(keyidx & (1 << 5))) {
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c
index 0c495f0..f091aac 100644
--- a/net/ieee80211/ieee80211_crypt_tkip.c
+++ b/net/ieee80211/ieee80211_crypt_tkip.c
@@ -265,11 +265,11 @@ static int ieee80211_tkip_encrypt(struct
 	struct ieee80211_tkip_data *tkey = priv;
 	int len;
 	u8 rc4key[16], *pos, *icv;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 	u32 crc;
 	struct scatterlist sg;
 
-	hdr = (struct ieee80211_hdr *)skb->data;
+	hdr = (struct ieee80211_hdr_4addr *)skb->data;
 
 	if (tkey->ieee->tkip_countermeasures) {
 		if (net_ratelimit()) {
@@ -334,13 +334,13 @@ static int ieee80211_tkip_decrypt(struct
 	u8 keyidx, *pos;
 	u32 iv32;
 	u16 iv16;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 	u8 icv[4];
 	u32 crc;
 	struct scatterlist sg;
 	int plen;
 
-	hdr = (struct ieee80211_hdr *)skb->data;
+	hdr = (struct ieee80211_hdr_4addr *)skb->data;
 
 	if (tkey->ieee->tkip_countermeasures) {
 		if (net_ratelimit()) {
@@ -466,9 +466,9 @@ static int michael_mic(struct ieee80211_
 
 static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
 {
-	struct ieee80211_hdr *hdr11;
+	struct ieee80211_hdr_4addr *hdr11;
 
-	hdr11 = (struct ieee80211_hdr *)skb->data;
+	hdr11 = (struct ieee80211_hdr_4addr *)skb->data;
 	switch (le16_to_cpu(hdr11->frame_ctl) &
 		(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
 	case IEEE80211_FCTL_TODS:
@@ -517,7 +517,8 @@ static int ieee80211_michael_mic_add(str
 
 #if WIRELESS_EXT >= 18
 static void ieee80211_michael_mic_failure(struct net_device *dev,
-					  struct ieee80211_hdr *hdr, int keyidx)
+					  struct ieee80211_hdr_4addr *hdr,
+					  int keyidx)
 {
 	union iwreq_data wrqu;
 	struct iw_michaelmicfailure ev;
@@ -537,7 +538,8 @@ static void ieee80211_michael_mic_failur
 }
 #elif WIRELESS_EXT >= 15
 static void ieee80211_michael_mic_failure(struct net_device *dev,
-					  struct ieee80211_hdr *hdr, int keyidx)
+					  struct ieee80211_hdr_4addr *hdr,
+					  int keyidx)
 {
 	union iwreq_data wrqu;
 	char buf[128];
@@ -551,9 +553,8 @@ static void ieee80211_michael_mic_failur
 	wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
 }
 #else				/* WIRELESS_EXT >= 15 */
-static inline void ieee80211_michael_mic_failure(struct net_device *dev,
-						 struct ieee80211_hdr *hdr,
-						 int keyidx)
+static inline void ieee80211_michael_mic_failure(struct net_device *dev, struct ieee80211_hdr_4addr
+						 *hdr, int keyidx)
 {
 }
 #endif				/* WIRELESS_EXT >= 15 */
@@ -572,8 +573,8 @@ static int ieee80211_michael_mic_verify(
 			skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
 		return -1;
 	if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
-		struct ieee80211_hdr *hdr;
-		hdr = (struct ieee80211_hdr *)skb->data;
+		struct ieee80211_hdr_4addr *hdr;
+		hdr = (struct ieee80211_hdr_4addr *)skb->data;
 		printk(KERN_DEBUG "%s: Michael MIC verification failed for "
 		       "MSDU from " MAC_FMT " keyidx=%d\n",
 		       skb->dev ? skb->dev->name : "N/A", MAC_ARG(hdr->addr2),
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 9a125d4..71d14c7 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -87,7 +87,7 @@ static struct ieee80211_frag_entry *ieee
 
 /* Called only as a tasklet (software IRQ) */
 static struct sk_buff *ieee80211_frag_cache_get(struct ieee80211_device *ieee,
-						struct ieee80211_hdr *hdr)
+						struct ieee80211_hdr_4addr *hdr)
 {
 	struct sk_buff *skb = NULL;
 	u16 sc;
@@ -101,7 +101,7 @@ static struct sk_buff *ieee80211_frag_ca
 	if (frag == 0) {
 		/* Reserve enough space to fit maximum frame length */
 		skb = dev_alloc_skb(ieee->dev->mtu +
-				    sizeof(struct ieee80211_hdr) +
+				    sizeof(struct ieee80211_hdr_4addr) +
 				    8 /* LLC */  +
 				    2 /* alignment */  +
 				    8 /* WEP */  + ETH_ALEN /* WDS */ );
@@ -138,7 +138,7 @@ static struct sk_buff *ieee80211_frag_ca
 
 /* Called only as a tasklet (software IRQ) */
 static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee,
-					   struct ieee80211_hdr *hdr)
+					   struct ieee80211_hdr_4addr *hdr)
 {
 	u16 sc;
 	unsigned int seq;
@@ -176,7 +176,7 @@ ieee80211_rx_frame_mgmt(struct ieee80211
 		       ieee->dev->name);
 		return 0;
 /*
-  hostap_update_sta_ps(ieee, (struct hostap_ieee80211_hdr *)
+  hostap_update_sta_ps(ieee, (struct hostap_ieee80211_hdr_4addr *)
   skb->data);*/
 	}
 
@@ -232,13 +232,13 @@ static int ieee80211_is_eapol_frame(stru
 {
 	struct net_device *dev = ieee->dev;
 	u16 fc, ethertype;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_3addr *hdr;
 	u8 *pos;
 
 	if (skb->len < 24)
 		return 0;
 
-	hdr = (struct ieee80211_hdr *)skb->data;
+	hdr = (struct ieee80211_hdr_3addr *)skb->data;
 	fc = le16_to_cpu(hdr->frame_ctl);
 
 	/* check that the frame is unicast frame to us */
@@ -271,13 +271,13 @@ static inline int
 ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb,
 			   struct ieee80211_crypt_data *crypt)
 {
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_3addr *hdr;
 	int res, hdrlen;
 
 	if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
 		return 0;
 
-	hdr = (struct ieee80211_hdr *)skb->data;
+	hdr = (struct ieee80211_hdr_3addr *)skb->data;
 	hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 
 	atomic_inc(&crypt->refcnt);
@@ -303,13 +303,13 @@ ieee80211_rx_frame_decrypt_msdu(struct i
 				struct sk_buff *skb, int keyidx,
 				struct ieee80211_crypt_data *crypt)
 {
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_3addr *hdr;
 	int res, hdrlen;
 
 	if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
 		return 0;
 
-	hdr = (struct ieee80211_hdr *)skb->data;
+	hdr = (struct ieee80211_hdr_3addr *)skb->data;
 	hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 
 	atomic_inc(&crypt->refcnt);
@@ -332,7 +332,7 @@ int ieee80211_rx(struct ieee80211_device
 		 struct ieee80211_rx_stats *rx_stats)
 {
 	struct net_device *dev = ieee->dev;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 	size_t hdrlen;
 	u16 fc, type, stype, sc;
 	struct net_device_stats *stats;
@@ -352,7 +352,7 @@ int ieee80211_rx(struct ieee80211_device
 	struct ieee80211_crypt_data *crypt = NULL;
 	int keyidx = 0;
 
-	hdr = (struct ieee80211_hdr *)skb->data;
+	hdr = (struct ieee80211_hdr_4addr *)skb->data;
 	stats = &ieee->stats;
 
 	if (skb->len < 10) {
@@ -552,7 +552,7 @@ int ieee80211_rx(struct ieee80211_device
 	    (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0)
 		goto rx_dropped;
 
-	hdr = (struct ieee80211_hdr *)skb->data;
+	hdr = (struct ieee80211_hdr_4addr *)skb->data;
 
 	/* skb: hdr + (possibly fragmented) plaintext payload */
 	// PR: FIXME: hostap has additional conditions in the "if" below:
@@ -606,7 +606,7 @@ int ieee80211_rx(struct ieee80211_device
 		/* this was the last fragment and the frame will be
 		 * delivered, so remove skb from fragment cache */
 		skb = frag_skb;
-		hdr = (struct ieee80211_hdr *)skb->data;
+		hdr = (struct ieee80211_hdr_4addr *)skb->data;
 		ieee80211_frag_cache_invalidate(ieee, hdr);
 	}
 
@@ -616,7 +616,7 @@ int ieee80211_rx(struct ieee80211_device
 	    ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt))
 		goto rx_dropped;
 
-	hdr = (struct ieee80211_hdr *)skb->data;
+	hdr = (struct ieee80211_hdr_4addr *)skb->data;
 	if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !ieee->open_wep) {
 		if (		/*ieee->ieee802_1x && */
 			   ieee80211_is_eapol_frame(ieee, skb)) {
@@ -1148,7 +1148,7 @@ static inline void ieee80211_process_pro
 }
 
 void ieee80211_rx_mgt(struct ieee80211_device *ieee,
-		      struct ieee80211_hdr *header,
+		      struct ieee80211_hdr_4addr *header,
 		      struct ieee80211_rx_stats *stats)
 {
 	switch (WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl))) {
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index 785e76f..29770cf 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -227,14 +227,14 @@ int ieee80211_xmit(struct sk_buff *skb, 
 {
 	struct ieee80211_device *ieee = netdev_priv(dev);
 	struct ieee80211_txb *txb = NULL;
-	struct ieee80211_hdr *frag_hdr;
+	struct ieee80211_hdr_3addr *frag_hdr;
 	int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
 	unsigned long flags;
 	struct net_device_stats *stats = &ieee->stats;
 	int ether_type, encrypt, host_encrypt;
 	int bytes, fc, hdr_len;
 	struct sk_buff *skb_frag;
-	struct ieee80211_hdr header = {	/* Ensure zero initialized */
+	struct ieee80211_hdr_3addr header = {	/* Ensure zero initialized */
 		.duration_id = 0,
 		.seq_ctl = 0
 	};
@@ -352,7 +352,8 @@ int ieee80211_xmit(struct sk_buff *skb, 
 		if (host_encrypt)
 			skb_reserve(skb_frag, crypt->ops->extra_prefix_len);
 
-		frag_hdr = (struct ieee80211_hdr *)skb_put(skb_frag, hdr_len);
+		frag_hdr =
+		    (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len);
 		memcpy(frag_hdr, &header, hdr_len);
 
 		/* If this is not the last fragment, then add the MOREFRAGS
---
0.99.8.GIT


--- NEW FILE 0173-ieee80211-adds-support-for-the-creation-of-RTS-packets.txt ---
Subject: [PATCH] ieee80211: adds support for the creation of RTS packets
From: James Ketrenos <jketreno linux intel com>
Date: 1127321683 -0500

tree b45c9c1017fd23216bfbe71e441aed9aa297fc84
parent 04aacdd71e904656a304d923bdcf57ad3bd2b254
author Ivo van Doorn <IvDoorn gmail com> 1124445405 -0500
committer James Ketrenos <jketreno linux intel com> 1127313029 -0500

This patch adds support for the creation of RTS packets when the
config flag CFG_IEEE80211_RTS has been set.

Signed-Off-By: Ivo van Doorn <IvDoorn gmail com>
Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/net/ieee80211.h          |    2 ++
 net/ieee80211/ieee80211_module.c |    1 +
 net/ieee80211/ieee80211_tx.c     |   41 +++++++++++++++++++++++++++++++++++---
 3 files changed, 41 insertions(+), 3 deletions(-)

applies-to: eed75aee11663053e658d839fb91bc8dfae56ecb
3cdd00c5827621cd0b1bb0665aa62ef9a724297d
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index ebe7e41..5e11ccf 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -690,6 +690,7 @@ enum ieee80211_state {
 
 #define CFG_IEEE80211_RESERVE_FCS (1<<0)
 #define CFG_IEEE80211_COMPUTE_FCS (1<<1)
+#define CFG_IEEE80211_RTS (1<<2)
 
 struct ieee80211_device {
 	struct net_device *dev;
@@ -747,6 +748,7 @@ struct ieee80211_device {
 	struct ieee80211_frag_entry frag_cache[IEEE80211_FRAG_CACHE_LEN];
 	unsigned int frag_next_idx;
 	u16 fts;		/* Fragmentation Threshold */
+	u16 rts;		/* RTS threshold */
 
 	/* Association info */
 	u8 bssid[ETH_ALEN];
diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c
index 82a4fd7..67d6bdd 100644
--- a/net/ieee80211/ieee80211_module.c
+++ b/net/ieee80211/ieee80211_module.c
@@ -126,6 +126,7 @@ struct net_device *alloc_ieee80211(int s
 
 	/* Default fragmentation threshold is maximum payload size */
 	ieee->fts = DEFAULT_FTS;
+	ieee->rts = DEFAULT_FTS;
 	ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
 	ieee->open_wep = 1;
 
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index 29770cf..cdee41c 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -222,13 +222,15 @@ static struct ieee80211_txb *ieee80211_a
 	return txb;
 }
 
-/* SKBs are added to the ieee->tx_queue. */
+/* Incoming skb is converted to a txb which consist of
+ * a block of 802.11 fragment packets (stored as skbs) */
 int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ieee80211_device *ieee = netdev_priv(dev);
 	struct ieee80211_txb *txb = NULL;
 	struct ieee80211_hdr_3addr *frag_hdr;
-	int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
+	int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size,
+	    rts_required;
 	unsigned long flags;
 	struct net_device_stats *stats = &ieee->stats;
 	int ether_type, encrypt, host_encrypt;
@@ -334,6 +336,13 @@ int ieee80211_xmit(struct sk_buff *skb, 
 	else
 		bytes_last_frag = bytes_per_frag;
 
+	rts_required = (frag_size > ieee->rts
+			&& ieee->config & CFG_IEEE80211_RTS);
+	if (rts_required)
+		nr_frags++;
+	else
+		bytes_last_frag = bytes_per_frag;
+
 	/* When we allocate the TXB we allocate enough space for the reserve
 	 * and full fragment bytes (bytes_per_frag doesn't include prefix,
 	 * postfix, header, FCS, etc.) */
@@ -346,7 +355,33 @@ int ieee80211_xmit(struct sk_buff *skb, 
 	txb->encrypted = encrypt;
 	txb->payload_size = bytes;
 
-	for (i = 0; i < nr_frags; i++) {
+	if (rts_required) {
+		skb_frag = txb->fragments[0];
+		frag_hdr =
+		    (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len);
+
+		/*
+		 * Set header frame_ctl to the RTS.
+		 */
+		header.frame_ctl =
+		    cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
+		memcpy(frag_hdr, &header, hdr_len);
+
+		/*
+		 * Restore header frame_ctl to the original data setting.
+		 */
+		header.frame_ctl = cpu_to_le16(fc);
+
+		if (ieee->config &
+		    (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
+			skb_put(skb_frag, 4);
+
+		txb->rts_included = 1;
+		i = 1;
+	} else
+		i = 0;
+
+	for (; i < nr_frags; i++) {
 		skb_frag = txb->fragments[i];
 
 		if (host_encrypt)
---
0.99.8.GIT


--- NEW FILE 0174-ieee82011-Added-ieee80211_tx_frame-to-convert-generic-802.11-data-frames-and-callbacks.txt ---
Subject: [PATCH] ieee82011: Added ieee80211_tx_frame to convert generic 802.11 data frames, and callbacks
From: James Ketrenos <jketreno linux intel com>
Date: 1127321687 -0500

tree 40adc78b623ae70d56074934ec6334eb4f0ae6a5
parent db43d847bcebaa3df6414e26d0008eb21690e8cf
author James Ketrenos <jketreno linux intel com> 1124445938 -0500
committer James Ketrenos <jketreno linux intel com> 1127313102 -0500

Added ieee80211_tx_frame to convert generic 802.11 data frames into
txbs for transmission.

Added several purpose specific callbacks (handle_assoc, handle_auth,
etc.) which the driver can register with for being notified on
reception of variouf frame elements.

Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/net/ieee80211.h      |   23 +++++++++++++++
 net/ieee80211/ieee80211_rx.c |   58 ++++++++++++++++++++++++++++----------
 net/ieee80211/ieee80211_tx.c |   64 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 130 insertions(+), 15 deletions(-)

applies-to: 03d3a7cfa9fb645b052bac748c5398430ab2c9ca
3f552bbf8614d2d26f488ca0d3e188bdec484bf4
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 5e11ccf..43cf2e5 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -769,6 +769,27 @@ struct ieee80211_device {
 	int (*hard_start_xmit) (struct ieee80211_txb * txb,
 				struct net_device * dev);
 	int (*reset_port) (struct net_device * dev);
+	int (*is_queue_full) (struct net_device * dev, int pri);
+
+	/* Typical STA methods */
+	int (*handle_auth) (struct net_device * dev,
+			    struct ieee80211_auth * auth);
+	int (*handle_disassoc) (struct net_device * dev,
+				struct ieee80211_disassoc * assoc);
+	int (*handle_beacon) (struct net_device * dev,
+			      struct ieee80211_beacon * beacon,
+			      struct ieee80211_network * network);
+	int (*handle_probe_response) (struct net_device * dev,
+				      struct ieee80211_probe_response * resp,
+				      struct ieee80211_network * network);
+	int (*handle_assoc_response) (struct net_device * dev,
+				      struct ieee80211_assoc_response * resp,
+				      struct ieee80211_network * network);
+
+	/* Typical AP methods */
+	int (*handle_assoc_request) (struct net_device * dev);
+	int (*handle_reassoc_request) (struct net_device * dev,
+				       struct ieee80211_reassoc_request * req);
 
 	/* This must be the last item so that it points to the data
 	 * allocated beyond this structure by alloc_ieee80211 */
@@ -877,6 +898,8 @@ extern int ieee80211_set_encryption(stru
 /* ieee80211_tx.c */
 extern int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev);
 extern void ieee80211_txb_free(struct ieee80211_txb *);
+extern int ieee80211_tx_frame(struct ieee80211_device *ieee,
+			      struct ieee80211_hdr *frame, int len);
 
 /* ieee80211_rx.c */
 extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 71d14c7..d1ae282 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -1029,12 +1029,18 @@ static inline void update_network(struct
 	/* dst->last_associate is not overwritten */
 }
 
+static inline int is_beacon(int fc)
+{
+	return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == IEEE80211_STYPE_BEACON);
+}
+
 static inline void ieee80211_process_probe_response(struct ieee80211_device
 						    *ieee, struct
 						    ieee80211_probe_response
 						    *beacon, struct ieee80211_rx_stats
 						    *stats)
 {
+	struct net_device *dev = ieee->dev;
 	struct ieee80211_network network;
 	struct ieee80211_network *target;
 	struct ieee80211_network *oldest = NULL;
@@ -1070,11 +1076,10 @@ static inline void ieee80211_process_pro
 				     escape_essid(info_element->data,
 						  info_element->len),
 				     MAC_ARG(beacon->header.addr3),
-				     WLAN_FC_GET_STYPE(le16_to_cpu
-						       (beacon->header.
-							frame_ctl)) ==
-				     IEEE80211_STYPE_PROBE_RESP ?
-				     "PROBE RESPONSE" : "BEACON");
+				     is_beacon(le16_to_cpu
+					       (beacon->header.
+						frame_ctl)) ?
+				     "BEACON" : "PROBE RESPONSE");
 		return;
 	}
 
@@ -1123,11 +1128,10 @@ static inline void ieee80211_process_pro
 				     escape_essid(network.ssid,
 						  network.ssid_len),
 				     MAC_ARG(network.bssid),
-				     WLAN_FC_GET_STYPE(le16_to_cpu
-						       (beacon->header.
-							frame_ctl)) ==
-				     IEEE80211_STYPE_PROBE_RESP ?
-				     "PROBE RESPONSE" : "BEACON");
+				     is_beacon(le16_to_cpu
+					       (beacon->header.
+						frame_ctl)) ?
+				     "BEACON" : "PROBE RESPONSE");
 #endif
 		memcpy(target, &network, sizeof(*target));
 		list_add_tail(&target->list, &ieee->network_list);
@@ -1136,15 +1140,22 @@ static inline void ieee80211_process_pro
 				     escape_essid(target->ssid,
 						  target->ssid_len),
 				     MAC_ARG(target->bssid),
-				     WLAN_FC_GET_STYPE(le16_to_cpu
-						       (beacon->header.
-							frame_ctl)) ==
-				     IEEE80211_STYPE_PROBE_RESP ?
-				     "PROBE RESPONSE" : "BEACON");
+				     is_beacon(le16_to_cpu
+					       (beacon->header.
+						frame_ctl)) ?
+				     "BEACON" : "PROBE RESPONSE");
 		update_network(target, &network);
 	}
 
 	spin_unlock_irqrestore(&ieee->lock, flags);
+
+	if (is_beacon(le16_to_cpu(beacon->header.frame_ctl))) {
+		if (ieee->handle_beacon != NULL)
+			ieee->handle_beacon(dev, beacon, &network);
+	} else {
+		if (ieee->handle_probe_response != NULL)
+			ieee->handle_probe_response(dev, beacon, &network);
+	}
 }
 
 void ieee80211_rx_mgt(struct ieee80211_device *ieee,
@@ -1185,6 +1196,23 @@ void ieee80211_rx_mgt(struct ieee80211_d
 						  ieee80211_probe_response *)
 						 header, stats);
 		break;
+	case IEEE80211_STYPE_AUTH:
+
+		IEEE80211_DEBUG_MGMT("recieved auth (%d)\n",
+				     WLAN_FC_GET_STYPE(le16_to_cpu
+						       (header->frame_ctl)));
+
+		if (ieee->handle_auth != NULL)
+			ieee->handle_auth(ieee->dev,
+					  (struct ieee80211_auth *)header);
+		break;
+
+	case IEEE80211_STYPE_DISASSOC:
+		if (ieee->handle_disassoc != NULL)
+			ieee->handle_disassoc(ieee->dev,
+					      (struct ieee80211_disassoc *)
+					      header);
+		break;
 
 	default:
 		IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n",
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index cdee41c..f505aa1 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -459,7 +459,71 @@ int ieee80211_xmit(struct sk_buff *skb, 
 	netif_stop_queue(dev);
 	stats->tx_errors++;
 	return 1;
+}
+
+/* Incoming 802.11 strucure is converted to a TXB
+ * a block of 802.11 fragment packets (stored as skbs) */
+int ieee80211_tx_frame(struct ieee80211_device *ieee,
+		       struct ieee80211_hdr *frame, int len)
+{
+	struct ieee80211_txb *txb = NULL;
+	unsigned long flags;
+	struct net_device_stats *stats = &ieee->stats;
+	struct sk_buff *skb_frag;
+
+	spin_lock_irqsave(&ieee->lock, flags);
+
+	/* If there is no driver handler to take the TXB, dont' bother
+	 * creating it... */
+	if (!ieee->hard_start_xmit) {
+		printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name);
+		goto success;
+	}
+
+	if (unlikely(len < 24)) {
+		printk(KERN_WARNING "%s: skb too small (%d).\n",
+		       ieee->dev->name, len);
+		goto success;
+	}
+
+	/* When we allocate the TXB we allocate enough space for the reserve
+	 * and full fragment bytes (bytes_per_frag doesn't include prefix,
+	 * postfix, header, FCS, etc.) */
+	txb = ieee80211_alloc_txb(1, len, GFP_ATOMIC);
+	if (unlikely(!txb)) {
+		printk(KERN_WARNING "%s: Could not allocate TXB\n",
+		       ieee->dev->name);
+		goto failed;
+	}
+	txb->encrypted = 0;
+	txb->payload_size = len;
+
+	skb_frag = txb->fragments[0];
 
+	memcpy(skb_put(skb_frag, len), frame, len);
+
+	if (ieee->config &
+	    (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
+		skb_put(skb_frag, 4);
+
+      success:
+	spin_unlock_irqrestore(&ieee->lock, flags);
+
+	if (txb) {
+		if ((*ieee->hard_start_xmit) (txb, ieee->dev) == 0) {
+			stats->tx_packets++;
+			stats->tx_bytes += txb->payload_size;
+			return 0;
+		}
+		ieee80211_txb_free(txb);
+	}
+	return 0;
+
+      failed:
+	spin_unlock_irqrestore(&ieee->lock, flags);
+	stats->tx_errors++;
+	return 1;
 }
 
+EXPORT_SYMBOL(ieee80211_tx_frame);
 EXPORT_SYMBOL(ieee80211_txb_free);
---
0.99.8.GIT


--- NEW FILE 0175-ieee80211-Fix-TKIP-repeated-fragmentation-problem-and-payload_size-reporting.txt ---
Subject: [PATCH] ieee80211: Fix TKIP, repeated fragmentation problem, and payload_size reporting
From: James Ketrenos <jketreno linux intel com>
Date: 1127321693 -0500

tree 8428e9f510e6ad6c77baec89cb57374842abf733
parent d78bfd3ddae9c422dd350159110f9c4d7cfc50de
author Liu Hong <hong liu intel com> 1124446520 -0500
committer James Ketrenos <jketreno linux intel com> 1127313183 -0500

Fix TKIP, repeated fragmentation problem, and payload_size reporting

1. TKIP encryption
    Originally, TKIP encryption issues msdu + mpdu encryption on every
    fragment. Change the behavior to msdu encryption on the whole
    packet, then mpdu encryption on every fragment.

2. Avoid repeated fragmentation when !host_encrypt.
    We only need do fragmentation when using host encryption. Otherwise
    we only need pass the whole packet to driver, letting driver do the
    fragmentation.

3. change the txb->payload_size to correct value
    FW will use this value to determine whether to do fragmentation. If
    we pass the wrong value, fw may cut on the wrong bound which will
    make decryption fail when we do host encryption.

NOTE:  This requires changing drivers (hostap) that have
extra_prefix_len used within them (structure member name change).

Signed-off-by: Hong Liu <liu hong intel com>
Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/net/ieee80211.h              |    2 
 include/net/ieee80211_crypt.h        |    3 -
 net/ieee80211/ieee80211_crypt.c      |    4 -
 net/ieee80211/ieee80211_crypt_ccmp.c |    4 -
 net/ieee80211/ieee80211_crypt_tkip.c |    5 +
 net/ieee80211/ieee80211_crypt_wep.c  |    4 -
 net/ieee80211/ieee80211_module.c     |    7 +-
 net/ieee80211/ieee80211_tx.c         |  148 +++++++++++++++++++---------------
 8 files changed, 102 insertions(+), 75 deletions(-)

applies-to: 9721d4dc2d53579d7c324fa0b98eddc964149ab4
1264fc0498e1e20f97b1ab690e523e7a7fc50eab
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 43cf2e5..46466f5 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -724,7 +724,9 @@ struct ieee80211_device {
 
 	/* If the host performs {en,de}cryption, then set to 1 */
 	int host_encrypt;
+	int host_encrypt_msdu;
 	int host_decrypt;
+	int host_open_frag;
 	int ieee802_1x;		/* is IEEE 802.1X used */
 
 	/* WPA data */
diff --git a/include/net/ieee80211_crypt.h b/include/net/ieee80211_crypt.h
index 536e9a9..24e4912 100644
--- a/include/net/ieee80211_crypt.h
+++ b/include/net/ieee80211_crypt.h
@@ -63,7 +63,8 @@ struct ieee80211_crypto_ops {
 	 * extra_postfix_len; encrypt need not use all this space, but
 	 * the result must start at the beginning of the buffer and correct
 	 * length must be returned */
-	int extra_prefix_len, extra_postfix_len;
+	int extra_mpdu_prefix_len, extra_mpdu_postfix_len;
+	int extra_msdu_prefix_len, extra_msdu_postfix_len;
 
 	struct module *owner;
 };
diff --git a/net/ieee80211/ieee80211_crypt.c b/net/ieee80211/ieee80211_crypt.c
index 60d3166..e26bcc9 100644
--- a/net/ieee80211/ieee80211_crypt.c
+++ b/net/ieee80211/ieee80211_crypt.c
@@ -221,8 +221,8 @@ static struct ieee80211_crypto_ops ieee8
 	.decrypt_msdu = NULL,
 	.set_key = NULL,
 	.get_key = NULL,
-	.extra_prefix_len = 0,
-	.extra_postfix_len = 0,
+	.extra_mpdu_prefix_len = 0,
+	.extra_mpdu_postfix_len = 0,
 	.owner = THIS_MODULE,
 };
 
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c
index d3b5cde..a3dc571 100644
--- a/net/ieee80211/ieee80211_crypt_ccmp.c
+++ b/net/ieee80211/ieee80211_crypt_ccmp.c
@@ -436,8 +436,8 @@ static struct ieee80211_crypto_ops ieee8
 	.set_key = ieee80211_ccmp_set_key,
 	.get_key = ieee80211_ccmp_get_key,
 	.print_stats = ieee80211_ccmp_print_stats,
-	.extra_prefix_len = CCMP_HDR_LEN,
-	.extra_postfix_len = CCMP_MIC_LEN,
+	.extra_mpdu_prefix_len = CCMP_HDR_LEN,
+	.extra_mpdu_postfix_len = CCMP_MIC_LEN,
 	.owner = THIS_MODULE,
 };
 
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c
index f091aac..f973d6c 100644
--- a/net/ieee80211/ieee80211_crypt_tkip.c
+++ b/net/ieee80211/ieee80211_crypt_tkip.c
@@ -690,8 +690,9 @@ static struct ieee80211_crypto_ops ieee8
 	.set_key = ieee80211_tkip_set_key,
 	.get_key = ieee80211_tkip_get_key,
 	.print_stats = ieee80211_tkip_print_stats,
-	.extra_prefix_len = 4 + 4,	/* IV + ExtIV */
-	.extra_postfix_len = 8 + 4,	/* MIC + ICV */
+	.extra_mpdu_prefix_len = 4 + 4,	/* IV + ExtIV */
+	.extra_mpdu_postfix_len = 4,	/* ICV */
+	.extra_msdu_postfix_len = 8,	/* MIC */
 	.owner = THIS_MODULE,
 };
 
diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c
index 63e783f..2aaeac1 100644
--- a/net/ieee80211/ieee80211_crypt_wep.c
+++ b/net/ieee80211/ieee80211_crypt_wep.c
@@ -239,8 +239,8 @@ static struct ieee80211_crypto_ops ieee8
 	.set_key = prism2_wep_set_key,
 	.get_key = prism2_wep_get_key,
 	.print_stats = prism2_wep_print_stats,
-	.extra_prefix_len = 4,	/* IV */
-	.extra_postfix_len = 4,	/* ICV */
+	.extra_mpdu_prefix_len = 4,	/* IV */
+	.extra_mpdu_postfix_len = 4,	/* ICV */
 	.owner = THIS_MODULE,
 };
 
diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c
index 67d6bdd..dddc616 100644
--- a/net/ieee80211/ieee80211_module.c
+++ b/net/ieee80211/ieee80211_module.c
@@ -133,6 +133,12 @@ struct net_device *alloc_ieee80211(int s
 	/* Default to enabling full open WEP with host based encrypt/decrypt */
 	ieee->host_encrypt = 1;
 	ieee->host_decrypt = 1;
+	/* Host fragementation in Open mode. Default is enabled.
+	 * Note: host fragmentation is always enabled if host encryption
+	 * is enabled. For cards can do hardware encryption, they must do
+	 * hardware fragmentation as well. So we don't need a variable
+	 * like host_enc_frag. */
+	ieee->host_open_frag = 1;
 	ieee->ieee802_1x = 1;	/* Default to supporting 802.1x */
 
 	INIT_LIST_HEAD(&ieee->crypt_deinit_list);
@@ -147,7 +153,6 @@ struct net_device *alloc_ieee80211(int s
 	ieee->tkip_countermeasures = 0;
 	ieee->drop_unencrypted = 0;
 	ieee->privacy_invoked = 0;
-	ieee->ieee802_1x = 1;
 
 	return dev;
 
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index f505aa1..23a1f88 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -128,7 +128,7 @@ payload of each frame is reduced to 492 
 static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
 static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
 
-static inline int ieee80211_put_snap(u8 * data, u16 h_proto)
+static inline int ieee80211_copy_snap(u8 * data, u16 h_proto)
 {
 	struct ieee80211_snap_hdr *snap;
 	u8 *oui;
@@ -159,15 +159,9 @@ static inline int ieee80211_encrypt_frag
 
 	/* To encrypt, frame format is:
 	 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
-
-	// PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU encryption.
-	/* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
-	 * call both MSDU and MPDU encryption functions from here. */
 	atomic_inc(&crypt->refcnt);
 	res = 0;
-	if (crypt->ops->encrypt_msdu)
-		res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
-	if (res == 0 && crypt->ops->encrypt_mpdu)
+	if (crypt->ops->encrypt_mpdu)
 		res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
 
 	atomic_dec(&crypt->refcnt);
@@ -222,7 +216,7 @@ static struct ieee80211_txb *ieee80211_a
 	return txb;
 }
 
-/* Incoming skb is converted to a txb which consist of
+/* Incoming skb is converted to a txb which consists of
  * a block of 802.11 fragment packets (stored as skbs) */
 int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
 {
@@ -233,7 +227,7 @@ int ieee80211_xmit(struct sk_buff *skb, 
 	    rts_required;
 	unsigned long flags;
 	struct net_device_stats *stats = &ieee->stats;
-	int ether_type, encrypt, host_encrypt;
+	int ether_type, encrypt, host_encrypt, host_encrypt_msdu;
 	int bytes, fc, hdr_len;
 	struct sk_buff *skb_frag;
 	struct ieee80211_hdr_3addr header = {	/* Ensure zero initialized */
@@ -241,8 +235,8 @@ int ieee80211_xmit(struct sk_buff *skb, 
 		.seq_ctl = 0
 	};
 	u8 dest[ETH_ALEN], src[ETH_ALEN];
-
 	struct ieee80211_crypt_data *crypt;
+	int snapped = 0;
 
 	spin_lock_irqsave(&ieee->lock, flags);
 
@@ -266,6 +260,7 @@ int ieee80211_xmit(struct sk_buff *skb, 
 	encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
 	    ieee->sec.encrypt;
 	host_encrypt = ieee->host_encrypt && encrypt;
+	host_encrypt_msdu = ieee->host_encrypt_msdu && encrypt;
 
 	if (!encrypt && ieee->ieee802_1x &&
 	    ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
@@ -291,14 +286,12 @@ int ieee80211_xmit(struct sk_buff *skb, 
 
 	if (ieee->iw_mode == IW_MODE_INFRA) {
 		fc |= IEEE80211_FCTL_TODS;
-		/* To DS: Addr1 = BSSID, Addr2 = SA,
-		   Addr3 = DA */
+		/* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */
 		memcpy(header.addr1, ieee->bssid, ETH_ALEN);
 		memcpy(header.addr2, src, ETH_ALEN);
 		memcpy(header.addr3, dest, ETH_ALEN);
 	} else if (ieee->iw_mode == IW_MODE_ADHOC) {
-		/* not From/To DS: Addr1 = DA, Addr2 = SA,
-		   Addr3 = BSSID */
+		/* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */
 		memcpy(header.addr1, dest, ETH_ALEN);
 		memcpy(header.addr2, src, ETH_ALEN);
 		memcpy(header.addr3, ieee->bssid, ETH_ALEN);
@@ -306,42 +299,75 @@ int ieee80211_xmit(struct sk_buff *skb, 
 	header.frame_ctl = cpu_to_le16(fc);
 	hdr_len = IEEE80211_3ADDR_LEN;
 
-	/* Determine fragmentation size based on destination (multicast
-	 * and broadcast are not fragmented) */
-	if (is_multicast_ether_addr(dest) || is_broadcast_ether_addr(dest))
-		frag_size = MAX_FRAG_THRESHOLD;
-	else
-		frag_size = ieee->fts;
-
-	/* Determine amount of payload per fragment.  Regardless of if
-	 * this stack is providing the full 802.11 header, one will
-	 * eventually be affixed to this fragment -- so we must account for
-	 * it when determining the amount of payload space. */
-	bytes_per_frag = frag_size - IEEE80211_3ADDR_LEN;
-	if (ieee->config &
-	    (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
-		bytes_per_frag -= IEEE80211_FCS_LEN;
+	/* Encrypt msdu first on the whole data packet. */
+	if ((host_encrypt || host_encrypt_msdu) &&
+	    crypt && crypt->ops && crypt->ops->encrypt_msdu) {
+		int res = 0;
+		int len = bytes + hdr_len + crypt->ops->extra_msdu_prefix_len +
+		    crypt->ops->extra_msdu_postfix_len;
+		struct sk_buff *skb_new = dev_alloc_skb(len);
+		if (unlikely(!skb_new))
+			goto failed;
+		skb_reserve(skb_new, crypt->ops->extra_msdu_prefix_len);
+		memcpy(skb_put(skb_new, hdr_len), &header, hdr_len);
+		snapped = 1;
+		ieee80211_copy_snap(skb_put(skb_new, SNAP_SIZE + sizeof(u16)),
+				    ether_type);
+		memcpy(skb_put(skb_new, skb->len), skb->data, skb->len);
+		res = crypt->ops->encrypt_msdu(skb_new, hdr_len, crypt->priv);
+		if (res < 0) {
+			IEEE80211_ERROR("msdu encryption failed\n");
+			dev_kfree_skb_any(skb_new);
+			goto failed;
+		}
+		dev_kfree_skb_any(skb);
+		skb = skb_new;
+		bytes += crypt->ops->extra_msdu_prefix_len +
+		    crypt->ops->extra_msdu_postfix_len;
+		skb_pull(skb, hdr_len);
+	}
+
+	if (host_encrypt || ieee->host_open_frag) {
+		/* Determine fragmentation size based on destination (multicast
+		 * and broadcast are not fragmented) */
+		if (is_multicast_ether_addr(dest))
+			frag_size = MAX_FRAG_THRESHOLD;
+		else
+			frag_size = ieee->fts;
+
+		/* Determine amount of payload per fragment.  Regardless of if
+		 * this stack is providing the full 802.11 header, one will
+		 * eventually be affixed to this fragment -- so we must account
+		 * for it when determining the amount of payload space. */
+		bytes_per_frag = frag_size - IEEE80211_3ADDR_LEN;
+		if (ieee->config &
+		    (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
+			bytes_per_frag -= IEEE80211_FCS_LEN;
 
-	/* Each fragment may need to have room for encryptiong pre/postfix */
-	if (host_encrypt)
-		bytes_per_frag -= crypt->ops->extra_prefix_len +
-		    crypt->ops->extra_postfix_len;
+		/* Each fragment may need to have room for encryptiong
+		 * pre/postfix */
+		if (host_encrypt)
+			bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len +
+			    crypt->ops->extra_mpdu_postfix_len;
 
-	/* Number of fragments is the total bytes_per_frag /
-	 * payload_per_fragment */
-	nr_frags = bytes / bytes_per_frag;
-	bytes_last_frag = bytes % bytes_per_frag;
-	if (bytes_last_frag)
-		nr_frags++;
-	else
-		bytes_last_frag = bytes_per_frag;
+		/* Number of fragments is the total
+		 * bytes_per_frag / payload_per_fragment */
+		nr_frags = bytes / bytes_per_frag;
+		bytes_last_frag = bytes % bytes_per_frag;
+		if (bytes_last_frag)
+			nr_frags++;
+		else
+			bytes_last_frag = bytes_per_frag;
+	} else {
+		nr_frags = 1;
+		bytes_per_frag = bytes_last_frag = bytes;
+		frag_size = bytes + IEEE80211_3ADDR_LEN;
+	}
 
 	rts_required = (frag_size > ieee->rts
 			&& ieee->config & CFG_IEEE80211_RTS);
 	if (rts_required)
 		nr_frags++;
-	else
-		bytes_last_frag = bytes_per_frag;
 
 	/* When we allocate the TXB we allocate enough space for the reserve
 	 * and full fragment bytes (bytes_per_frag doesn't include prefix,
@@ -353,7 +379,11 @@ int ieee80211_xmit(struct sk_buff *skb, 
 		goto failed;
 	}
 	txb->encrypted = encrypt;
-	txb->payload_size = bytes;
+	if (host_encrypt)
+		txb->payload_size = frag_size * (nr_frags - 1) +
+		    bytes_last_frag;
+	else
+		txb->payload_size = bytes;
 
 	if (rts_required) {
 		skb_frag = txb->fragments[0];
@@ -385,7 +415,8 @@ int ieee80211_xmit(struct sk_buff *skb, 
 		skb_frag = txb->fragments[i];
 
 		if (host_encrypt)
-			skb_reserve(skb_frag, crypt->ops->extra_prefix_len);
+			skb_reserve(skb_frag,
+				    crypt->ops->extra_mpdu_prefix_len);
 
 		frag_hdr =
 		    (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len);
@@ -402,11 +433,10 @@ int ieee80211_xmit(struct sk_buff *skb, 
 			bytes = bytes_last_frag;
 		}
 
-		/* Put a SNAP header on the first fragment */
-		if (i == 0) {
-			ieee80211_put_snap(skb_put
-					   (skb_frag, SNAP_SIZE + sizeof(u16)),
-					   ether_type);
+		if (i == 0 && !snapped) {
+			ieee80211_copy_snap(skb_put
+					    (skb_frag, SNAP_SIZE + sizeof(u16)),
+					    ether_type);
 			bytes -= SNAP_SIZE + sizeof(u16);
 		}
 
@@ -420,19 +450,6 @@ int ieee80211_xmit(struct sk_buff *skb, 
 		if (host_encrypt)
 			ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
 
-		/* ipw2200/2915 Hardware encryption doesn't support TKIP MIC */
-		if (!ieee->host_encrypt && encrypt &&
-		    (ieee->sec.level == SEC_LEVEL_2) &&
-		    crypt && crypt->ops && crypt->ops->encrypt_msdu) {
-			int res = 0;
-			res = crypt->ops->encrypt_msdu(skb_frag, hdr_len,
-						       crypt->priv);
-			if (res < 0) {
-				IEEE80211_ERROR("TKIP MIC encryption failed\n");
-				goto failed;
-			}
-		}
-
 		if (ieee->config &
 		    (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
 			skb_put(skb_frag, 4);
@@ -444,7 +461,8 @@ int ieee80211_xmit(struct sk_buff *skb, 
 	dev_kfree_skb_any(skb);
 
 	if (txb) {
-		if ((*ieee->hard_start_xmit) (txb, dev) == 0) {
+		int ret = (*ieee->hard_start_xmit) (txb, dev);
+		if (ret == 0) {
 			stats->tx_packets++;
 			stats->tx_bytes += txb->payload_size;
 			return 0;
---
0.99.8.GIT


--- NEW FILE 0176-ieee80211-Return-NETDEV_TX_BUSY-when-QoS-buffer-full.txt ---
Subject: [PATCH] ieee80211: Return NETDEV_TX_BUSY when QoS buffer full
From: James Ketrenos <jketreno linux intel com>
Date: 1127321787 -0500

tree ba6509c7cd1dd4244a2f285f2da5d632e7ffbb25
parent 7b5f9f2ddcabdaea214527a895e6e8445cafdd80
author James Ketrenos <jketreno linux intel com> 1124447000 -0500
committer James Ketrenos <jketreno linux intel com> 1127313383 -0500

Per the conversations with folks at OLS, the QoS layer in 802.11
drivers can now result in NETDEV_TX_BUSY being returned when the queue
a packet is targetted for is full.

To implement this, ieee80211_xmit will now call the driver's
is_queue_full to determine if the current priority queue is full.  If
so, NETDEV_TX_BUSY is returned to the kernel and no processing is done
on the frame.

Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 net/ieee80211/ieee80211_tx.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

applies-to: 000b8528685f3ca250d0581df88abef03417941d
2c0aa2a5c2dfa1293ae3a07517d0b7de149358a1
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index 23a1f88..e9efdd4 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -236,8 +236,12 @@ int ieee80211_xmit(struct sk_buff *skb, 
 	};
 	u8 dest[ETH_ALEN], src[ETH_ALEN];
 	struct ieee80211_crypt_data *crypt;
+	int priority = skb->priority;
 	int snapped = 0;
 
+	if (ieee->is_queue_full && (*ieee->is_queue_full) (dev, priority))
+		return NETDEV_TX_BUSY;
+
 	spin_lock_irqsave(&ieee->lock, flags);
 
 	/* If there is no driver handler to take the TXB, dont' bother
@@ -467,6 +471,14 @@ int ieee80211_xmit(struct sk_buff *skb, 
 			stats->tx_bytes += txb->payload_size;
 			return 0;
 		}
+
+		if (ret == NETDEV_TX_BUSY) {
+			printk(KERN_ERR "%s: NETDEV_TX_BUSY returned; "
+			       "driver should report queue full via "
+			       "ieee_device->is_queue_full.\n",
+			       ieee->dev->name);
+		}
+
 		ieee80211_txb_free(txb);
 	}
 
---
0.99.8.GIT


--- NEW FILE 0177-ieee80211-Add-QoS-WME-support-to-the-ieee80211-subsystem.txt ---
Subject: [PATCH] ieee80211: Add QoS (WME) support to the ieee80211 subsystem
From: James Ketrenos <jketreno linux intel com>
Date: 1127321793 -0500

tree a3ad796273e98036eb0e9fc063225070fa24508a
parent 1b9c0aeb377abf8e4a43a86cff42382f74ca0259
author Mohamed Abbas <mabbas linux intel com> 1124447069 -0500
committer James Ketrenos <jketreno linux intel com> 1127313435 -0500

Add QoS (WME) support to the ieee80211 subsystem.

NOTE: This requires drivers that use the ieee80211 hard_start_xmit
(ipw2100 and ipw2200) to add the priority parameter to their callback.

Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/net/ieee80211.h      |  103 ++++++++++++-
 net/ieee80211/ieee80211_rx.c |  334 ++++++++++++++++++++++++++++++++++++++++--
 net/ieee80211/ieee80211_tx.c |    5 -
 3 files changed, 417 insertions(+), 25 deletions(-)

applies-to: a9f949b6dc6a5e68086c06dfeb459a14608227a3
9e8571affd1c54b9638b4ff9844e47aae07310f6
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 46466f5..72bd2b1 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -92,6 +92,7 @@
 #define IEEE80211_STYPE_CFACK		0x0050
 #define IEEE80211_STYPE_CFPOLL		0x0060
 #define IEEE80211_STYPE_CFACKPOLL	0x0070
+#define IEEE80211_STYPE_QOS_DATA        0x0080
 
 #define IEEE80211_SCTL_FRAG		0x000F
 #define IEEE80211_SCTL_SEQ		0xFFF0
@@ -153,6 +154,7 @@ const char *escape_essid(const char *ess
 
 #define IEEE80211_DL_TX            (1<<8)
 #define IEEE80211_DL_RX            (1<<9)
+#define IEEE80211_DL_QOS           (1<<31)
 
 #define IEEE80211_ERROR(f, a...) printk(KERN_ERR "ieee80211: " f, ## a)
 #define IEEE80211_WARNING(f, a...) printk(KERN_WARNING "ieee80211: " f, ## a)
@@ -166,6 +168,7 @@ const char *escape_essid(const char *ess
 #define IEEE80211_DEBUG_DROP(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_DROP, f, ## a)
 #define IEEE80211_DEBUG_TX(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_TX, f, ## a)
 #define IEEE80211_DEBUG_RX(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a)
+#define IEEE80211_DEBUG_QOS(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_QOS, f, ## a)
 #include <linux/netdevice.h>
 #include <linux/wireless.h>
 #include <linux/if_arp.h>	/* ARPHRD_ETHER */
@@ -493,6 +496,7 @@ enum ieee80211_mfie {
 	MFIE_TYPE_RSN = 48,
 	MFIE_TYPE_RATES_EX = 50,
 	MFIE_TYPE_GENERIC = 221,
+	MFIE_TYPE_QOS_PARAMETER = 222,
 };
 
 /* Minimal header; can be used for passing 802.11 frames with sufficient
@@ -540,6 +544,29 @@ struct ieee80211_hdr_4addr {
 	u8 payload[0];
 } __attribute__ ((packed));
 
+struct ieee80211_hdr_3addrqos {
+	u16 frame_ctl;
+	u16 duration_id;
+	u8 addr1[ETH_ALEN];
+	u8 addr2[ETH_ALEN];
+	u8 addr3[ETH_ALEN];
+	u16 seq_ctl;
+	u8 payload[0];
+	u16 qos_ctl;
+} __attribute__ ((packed));
+
+struct ieee80211_hdr_4addrqos {
+	u16 frame_ctl;
+	u16 duration_id;
+	u8 addr1[ETH_ALEN];
+	u8 addr2[ETH_ALEN];
+	u8 addr3[ETH_ALEN];
+	u16 seq_ctl;
+	u8 addr4[ETH_ALEN];
+	u8 payload[0];
+	u16 qos_ctl;
+} __attribute__ ((packed));
+
 struct ieee80211_info_element {
 	u8 id;
 	u8 len;
@@ -641,9 +668,68 @@ struct ieee80211_txb {
 
 #define MAX_WPA_IE_LEN 64
 
-#define NETWORK_EMPTY_ESSID (1<<0)
-#define NETWORK_HAS_OFDM    (1<<1)
-#define NETWORK_HAS_CCK     (1<<2)
+#define NETWORK_EMPTY_ESSID    (1<<0)
+#define NETWORK_HAS_OFDM       (1<<1)
+#define NETWORK_HAS_CCK        (1<<2)
+
+/* QoS structure */
+#define NETWORK_HAS_QOS_PARAMETERS      (1<<3)
+#define NETWORK_HAS_QOS_INFORMATION     (1<<4)
+#define NETWORK_HAS_QOS_MASK            (NETWORK_HAS_QOS_PARAMETERS | NETWORK_HAS_QOS_INFORMATION)
+
+#define QOS_QUEUE_NUM                   4
+#define QOS_OUI_LEN                     3
+#define QOS_OUI_TYPE                    2
+#define QOS_ELEMENT_ID                  221
+#define QOS_OUI_INFO_SUB_TYPE           0
+#define QOS_OUI_PARAM_SUB_TYPE          1
+#define QOS_VERSION_1                   1
+#define QOS_AIFSN_MIN_VALUE             2
+
+struct ieee80211_qos_information_element {
+	u8 elementID;
+	u8 length;
+	u8 qui[QOS_OUI_LEN];
+	u8 qui_type;
+	u8 qui_subtype;
+	u8 version;
+	u8 ac_info;
+} __attribute__ ((packed));
+
+struct ieee80211_qos_ac_parameter {
+	u8 aci_aifsn;
+	u8 ecw_min_max;
+	u16 tx_op_limit;
+} __attribute__ ((packed));
+
+struct ieee80211_qos_parameter_info {
+	struct ieee80211_qos_information_element info_element;
+	u8 reserved;
+	struct ieee80211_qos_ac_parameter ac_params_record[QOS_QUEUE_NUM];
+} __attribute__ ((packed));
+
+struct ieee80211_qos_parameters {
+	u16 cw_min[QOS_QUEUE_NUM];
+	u16 cw_max[QOS_QUEUE_NUM];
+	u8 aifs[QOS_QUEUE_NUM];
+	u8 flag[QOS_QUEUE_NUM];
+	u16 tx_op_limit[QOS_QUEUE_NUM];
+} __attribute__ ((packed));
+
+struct ieee80211_qos_data {
+	struct ieee80211_qos_parameters parameters;
+	int active;
+	int supported;
+	u8 param_count;
+	u8 old_param_count;
+};
+
+struct ieee80211_tim_parameters {
+	u8 tim_count;
+	u8 tim_period;
+} __attribute__ ((packed));
+
+/*******************************************************/
 
 struct ieee80211_network {
 	/* These entries are used to identify a unique network */
@@ -653,6 +739,8 @@ struct ieee80211_network {
 	u8 ssid[IW_ESSID_MAX_SIZE + 1];
 	u8 ssid_len;
 
+	struct ieee80211_qos_data qos_data;
+
 	/* These are network statistics */
 	struct ieee80211_rx_stats stats;
 	u16 capability;
@@ -672,6 +760,7 @@ struct ieee80211_network {
 	size_t wpa_ie_len;
 	u8 rsn_ie[MAX_WPA_IE_LEN];
 	size_t rsn_ie_len;
+	struct ieee80211_tim_parameters tim;
 	struct list_head list;
 };
 
@@ -769,10 +858,13 @@ struct ieee80211_device {
 	void (*set_security) (struct net_device * dev,
 			      struct ieee80211_security * sec);
 	int (*hard_start_xmit) (struct ieee80211_txb * txb,
-				struct net_device * dev);
+				struct net_device * dev, int pri);
 	int (*reset_port) (struct net_device * dev);
 	int (*is_queue_full) (struct net_device * dev, int pri);
 
+	int (*handle_management) (struct net_device * dev,
+				  struct ieee80211_network * network, u16 type);
+
 	/* Typical STA methods */
 	int (*handle_auth) (struct net_device * dev,
 			    struct ieee80211_auth * auth);
@@ -854,11 +946,14 @@ extern inline int ieee80211_is_valid_mod
 extern inline int ieee80211_get_hdrlen(u16 fc)
 {
 	int hdrlen = IEEE80211_3ADDR_LEN;
+	u16 stype = WLAN_FC_GET_STYPE(fc);
 
 	switch (WLAN_FC_GET_TYPE(fc)) {
 	case IEEE80211_FTYPE_DATA:
 		if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS))
 			hdrlen = IEEE80211_4ADDR_LEN;
+		if (stype & IEEE80211_STYPE_QOS_DATA)
+			hdrlen += 2;
 		break;
 	case IEEE80211_FTYPE_CTL:
 		switch (WLAN_FC_GET_STYPE(fc)) {
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index d1ae282..2c46135 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -534,6 +534,9 @@ int ieee80211_rx(struct ieee80211_device
 
 	/* Nullfunc frames may have PS-bit set, so they must be passed to
 	 * hostap_handle_sta_rx() before being dropped here. */
+
+	stype &= ~IEEE80211_STYPE_QOS_DATA;
+
 	if (stype != IEEE80211_STYPE_DATA &&
 	    stype != IEEE80211_STYPE_DATA_CFACK &&
 	    stype != IEEE80211_STYPE_DATA_CFPOLL &&
@@ -758,6 +761,264 @@ int ieee80211_rx(struct ieee80211_device
 
 #define MGMT_FRAME_FIXED_PART_LENGTH		0x24
 
+static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };
+
+/*
+* Make ther structure we read from the beacon packet has
+* the right values
+*/
+static int ieee80211_verify_qos_info(struct ieee80211_qos_information_element
+				     *info_element, int sub_type)
+{
+
+	if (info_element->qui_subtype != sub_type)
+		return -1;
+	if (memcmp(info_element->qui, qos_oui, QOS_OUI_LEN))
+		return -1;
+	if (info_element->qui_type != QOS_OUI_TYPE)
+		return -1;
+	if (info_element->version != QOS_VERSION_1)
+		return -1;
+
+	return 0;
+}
+
+/*
+ * Parse a QoS parameter element
+ */
+static int ieee80211_read_qos_param_element(struct ieee80211_qos_parameter_info
+					    *element_param, struct ieee80211_info_element
+					    *info_element)
+{
+	int ret = 0;
+	u16 size = sizeof(struct ieee80211_qos_parameter_info) - 2;
+
+	if ((info_element == NULL) || (element_param == NULL))
+		return -1;
+
+	if (info_element->id == QOS_ELEMENT_ID && info_element->len == size) {
+		memcpy(element_param->info_element.qui, info_element->data,
+		       info_element->len);
+		element_param->info_element.elementID = info_element->id;
+		element_param->info_element.length = info_element->len;
+	} else
+		ret = -1;
+	if (ret == 0)
+		ret = ieee80211_verify_qos_info(&element_param->info_element,
+						QOS_OUI_PARAM_SUB_TYPE);
+	return ret;
+}
+
+/*
+ * Parse a QoS information element
+ */
+static int ieee80211_read_qos_info_element(struct
+					   ieee80211_qos_information_element
+					   *element_info, struct ieee80211_info_element
+					   *info_element)
+{
+	int ret = 0;
+	u16 size = sizeof(struct ieee80211_qos_information_element) - 2;
+
+	if (element_info == NULL)
+		return -1;
+	if (info_element == NULL)
+		return -1;
+
+	if ((info_element->id == QOS_ELEMENT_ID) && (info_element->len == size)) {
+		memcpy(element_info->qui, info_element->data,
+		       info_element->len);
+		element_info->elementID = info_element->id;
+		element_info->length = info_element->len;
+	} else
+		ret = -1;
+
+	if (ret == 0)
+		ret = ieee80211_verify_qos_info(element_info,
+						QOS_OUI_INFO_SUB_TYPE);
+	return ret;
+}
+
+/*
+ * Write QoS parameters from the ac parameters.
+ */
+static int ieee80211_qos_convert_ac_to_parameters(struct
+						  ieee80211_qos_parameter_info
+						  *param_elm, struct
+						  ieee80211_qos_parameters
+						  *qos_param)
+{
+	int rc = 0;
+	int i;
+	struct ieee80211_qos_ac_parameter *ac_params;
+	u32 txop;
+	u8 cw_min;
+	u8 cw_max;
+
+	for (i = 0; i < QOS_QUEUE_NUM; i++) {
+		ac_params = &(param_elm->ac_params_record[i]);
+
+		qos_param->aifs[i] = (ac_params->aci_aifsn) & 0x0F;
+		qos_param->aifs[i] -= (qos_param->aifs[i] < 2) ? 0 : 2;
+
+		cw_min = ac_params->ecw_min_max & 0x0F;
+		qos_param->cw_min[i] = (u16) ((1 << cw_min) - 1);
+
+		cw_max = (ac_params->ecw_min_max & 0xF0) >> 4;
+		qos_param->cw_max[i] = (u16) ((1 << cw_max) - 1);
+
+		qos_param->flag[i] =
+		    (ac_params->aci_aifsn & 0x10) ? 0x01 : 0x00;
+
+		txop = le16_to_cpu(ac_params->tx_op_limit) * 32;
+		qos_param->tx_op_limit[i] = (u16) txop;
+	}
+	return rc;
+}
+
+/*
+ * we have a generic data element which it may contain QoS information or
+ * parameters element. check the information element length to decide
+ * which type to read
+ */
+static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element
+					     *info_element,
+					     struct ieee80211_network *network)
+{
+	int rc = 0;
+	struct ieee80211_qos_parameters *qos_param = NULL;
+	struct ieee80211_qos_information_element qos_info_element;
+
+	rc = ieee80211_read_qos_info_element(&qos_info_element, info_element);
+
+	if (rc == 0) {
+		network->qos_data.param_count = qos_info_element.ac_info & 0x0F;
+		network->flags |= NETWORK_HAS_QOS_INFORMATION;
+	} else {
+		struct ieee80211_qos_parameter_info param_element;
+
+		rc = ieee80211_read_qos_param_element(&param_element,
+						      info_element);
+		if (rc == 0) {
+			qos_param = &(network->qos_data.parameters);
+			ieee80211_qos_convert_ac_to_parameters(&param_element,
+							       qos_param);
+			network->flags |= NETWORK_HAS_QOS_PARAMETERS;
+			network->qos_data.param_count =
+			    param_element.info_element.ac_info & 0x0F;
+		}
+	}
+
+	if (rc == 0) {
+		IEEE80211_DEBUG_QOS("QoS is supported\n");
+		network->qos_data.supported = 1;
+	}
+	return rc;
+}
+
+static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response
+				       *frame, struct ieee80211_rx_stats *stats)
+{
+	struct ieee80211_network network_resp;
+	struct ieee80211_network *network = &network_resp;
+	struct ieee80211_info_element *info_element;
+	struct net_device *dev = ieee->dev;
+	u16 left;
+
+	network->flags = 0;
+	network->qos_data.active = 0;
+	network->qos_data.supported = 0;
+	network->qos_data.param_count = 0;
+	network->qos_data.old_param_count = 0;
+
+	//network->atim_window = le16_to_cpu(frame->aid) & (0x3FFF);
+	network->atim_window = le16_to_cpu(frame->aid);
+	network->listen_interval = le16_to_cpu(frame->status);
+
+	info_element = frame->info_element;
+	left = stats->len - sizeof(*frame);
+
+	while (left >= sizeof(struct ieee80211_info_element)) {
+		if (sizeof(struct ieee80211_info_element) +
+		    info_element->len > left) {
+			IEEE80211_DEBUG_QOS("ASSOC RESP: parse failed: "
+					    "info_element->len + 2 > left : "
+					    "info_element->len+2=%zd left=%d, id=%d.\n",
+					    info_element->len +
+					    sizeof(struct
+						   ieee80211_info_element),
+					    left, info_element->id);
+			return 1;
+		}
+
+		switch (info_element->id) {
+		case MFIE_TYPE_SSID:
+			if (ieee80211_is_empty_essid(info_element->data,
+						     info_element->len)) {
+				network->flags |= NETWORK_EMPTY_ESSID;
+				break;
+			}
+
+			network->ssid_len = min(info_element->len,
+						(u8) IW_ESSID_MAX_SIZE);
+			memcpy(network->ssid, info_element->data,
+			       network->ssid_len);
+			if (network->ssid_len < IW_ESSID_MAX_SIZE)
+				memset(network->ssid + network->ssid_len, 0,
+				       IW_ESSID_MAX_SIZE - network->ssid_len);
+
+			IEEE80211_DEBUG_QOS("MFIE_TYPE_SSID: '%s' len=%d.\n",
+					    network->ssid, network->ssid_len);
+			break;
+
+		case MFIE_TYPE_TIM:
+			IEEE80211_DEBUG_QOS("MFIE_TYPE_TIM: ignored\n");
+			break;
+
+		case MFIE_TYPE_IBSS_SET:
+			IEEE80211_DEBUG_QOS("MFIE_TYPE_IBSS_SET: ignored\n");
+			break;
+
+		case MFIE_TYPE_CHALLENGE:
+			IEEE80211_DEBUG_QOS("MFIE_TYPE_CHALLENGE: ignored\n");
+			break;
+
+		case MFIE_TYPE_GENERIC:
+			IEEE80211_DEBUG_QOS("MFIE_TYPE_GENERIC: %d bytes\n",
+					    info_element->len);
+			ieee80211_parse_qos_info_param_IE(info_element,
+							  network);
+			break;
+
+		case MFIE_TYPE_RSN:
+			IEEE80211_DEBUG_QOS("MFIE_TYPE_RSN: %d bytes\n",
+					    info_element->len);
+			break;
+
+		case MFIE_TYPE_QOS_PARAMETER:
+			printk("QoS Error need to parse QOS_PARAMETER IE\n");
+			break;
+
+		default:
+			IEEE80211_DEBUG_QOS("unsupported IE %d\n",
+					    info_element->id);
+			break;
+		}
+
+		left -= sizeof(struct ieee80211_info_element) +
+		    info_element->len;
+		info_element = (struct ieee80211_info_element *)
+		    &info_element->data[info_element->len];
+	}
+
+	if (ieee->handle_assoc_response != NULL)
+		ieee->handle_assoc_response(dev, frame, network);
+
+	return 0;
+}
+
+/***************************************************/
+
 static inline int ieee80211_is_ofdm_rate(u8 rate)
 {
 	switch (rate & ~IEEE80211_BASIC_RATE_MASK) {
@@ -786,6 +1047,9 @@ static inline int ieee80211_network_init
 	struct ieee80211_info_element *info_element;
 	u16 left;
 	u8 i;
+	network->qos_data.active = 0;
+	network->qos_data.supported = 0;
+	network->qos_data.param_count = 0;
 
 	/* Pull out fixed field data */
 	memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
@@ -813,13 +1077,11 @@ static inline int ieee80211_network_init
 
 	info_element = beacon->info_element;
 	left = stats->len - sizeof(*beacon);
-	while (left >= sizeof(struct ieee80211_info_element)) {
-		if (sizeof(struct ieee80211_info_element) + info_element->len >
-		    left) {
+	while (left >= sizeof(*info_element)) {
+		if (sizeof(*info_element) + info_element->len > left) {
 			IEEE80211_DEBUG_SCAN
 			    ("SCAN: parse failed: info_element->len + 2 > left : info_element->len+2=%Zd left=%d.\n",
-			     info_element->len +
-			     sizeof(struct ieee80211_info_element), left);
+			     info_element->len + sizeof(*info_element), left);
 			return 1;
 		}
 
@@ -847,15 +1109,14 @@ static inline int ieee80211_network_init
 #ifdef CONFIG_IEEE80211_DEBUG
 			p = rates_str;
 #endif
-			network->rates_len =
-			    min(info_element->len, MAX_RATES_LENGTH);
+			network->rates_len = min(info_element->len,
+						 MAX_RATES_LENGTH);
 			for (i = 0; i < network->rates_len; i++) {
 				network->rates[i] = info_element->data[i];
 #ifdef CONFIG_IEEE80211_DEBUG
-				p += snprintf(p,
-					      sizeof(rates_str) - (p -
-								   rates_str),
-					      "%02X ", network->rates[i]);
+				p += snprintf(p, sizeof(rates_str) -
+					      (p - rates_str), "%02X ",
+					      network->rates[i]);
 #endif
 				if (ieee80211_is_ofdm_rate
 				    (info_element->data[i])) {
@@ -875,15 +1136,14 @@ static inline int ieee80211_network_init
 #ifdef CONFIG_IEEE80211_DEBUG
 			p = rates_str;
 #endif
-			network->rates_ex_len =
-			    min(info_element->len, MAX_RATES_EX_LENGTH);
+			network->rates_ex_len = min(info_element->len,
+						    MAX_RATES_EX_LENGTH);
 			for (i = 0; i < network->rates_ex_len; i++) {
 				network->rates_ex[i] = info_element->data[i];
 #ifdef CONFIG_IEEE80211_DEBUG
-				p += snprintf(p,
-					      sizeof(rates_str) - (p -
-								   rates_str),
-					      "%02X ", network->rates[i]);
+				p += snprintf(p, sizeof(rates_str) -
+					      (p - rates_str), "%02X ",
+					      network->rates[i]);
 #endif
 				if (ieee80211_is_ofdm_rate
 				    (info_element->data[i])) {
@@ -929,6 +1189,10 @@ static inline int ieee80211_network_init
 		case MFIE_TYPE_GENERIC:
 			IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n",
 					     info_element->len);
+			if (!ieee80211_parse_qos_info_param_IE(info_element,
+							       network))
+				break;
+
 			if (info_element->len >= 4 &&
 			    info_element->data[0] == 0x00 &&
 			    info_element->data[1] == 0x50 &&
@@ -950,14 +1214,18 @@ static inline int ieee80211_network_init
 			       network->rsn_ie_len);
 			break;
 
+		case MFIE_TYPE_QOS_PARAMETER:
+			printk(KERN_ERR
+			       "QoS Error need to parse QOS_PARAMETER IE\n");
+			break;
+
 		default:
 			IEEE80211_DEBUG_SCAN("unsupported IE %d\n",
 					     info_element->id);
 			break;
 		}
 
-		left -= sizeof(struct ieee80211_info_element) +
-		    info_element->len;
+		left -= sizeof(*info_element) + info_element->len;
 		info_element = (struct ieee80211_info_element *)
 		    &info_element->data[info_element->len];
 	}
@@ -1004,6 +1272,9 @@ static inline int is_same_network(struct
 static inline void update_network(struct ieee80211_network *dst,
 				  struct ieee80211_network *src)
 {
+	int qos_active;
+	u8 old_param;
+
 	memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats));
 	dst->capability = src->capability;
 	memcpy(dst->rates, src->rates, src->rates_len);
@@ -1026,6 +1297,28 @@ static inline void update_network(struct
 	dst->rsn_ie_len = src->rsn_ie_len;
 
 	dst->last_scanned = jiffies;
+	qos_active = src->qos_data.active;
+	old_param = dst->qos_data.old_param_count;
+	if (dst->flags & NETWORK_HAS_QOS_MASK)
+		memcpy(&dst->qos_data, &src->qos_data,
+		       sizeof(struct ieee80211_qos_data));
+	else {
+		dst->qos_data.supported = src->qos_data.supported;
+		dst->qos_data.param_count = src->qos_data.param_count;
+	}
+
+	if (dst->qos_data.supported == 1) {
+		if (dst->ssid_len)
+			IEEE80211_DEBUG_QOS
+			    ("QoS the network %s is QoS supported\n",
+			     dst->ssid);
+		else
+			IEEE80211_DEBUG_QOS
+			    ("QoS the network is QoS supported\n");
+	}
+	dst->qos_data.active = qos_active;
+	dst->qos_data.old_param_count = old_param;
+
 	/* dst->last_associate is not overwritten */
 }
 
@@ -1167,6 +1460,9 @@ void ieee80211_rx_mgt(struct ieee80211_d
 		IEEE80211_DEBUG_MGMT("received ASSOCIATION RESPONSE (%d)\n",
 				     WLAN_FC_GET_STYPE(le16_to_cpu
 						       (header->frame_ctl)));
+		ieee80211_handle_assoc_resp(ieee,
+					    (struct ieee80211_assoc_response *)
+					    header, stats);
 		break;
 
 	case IEEE80211_STYPE_REASSOC_RESP:
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index e9efdd4..aba72f9 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -465,7 +465,7 @@ int ieee80211_xmit(struct sk_buff *skb, 
 	dev_kfree_skb_any(skb);
 
 	if (txb) {
-		int ret = (*ieee->hard_start_xmit) (txb, dev);
+		int ret = (*ieee->hard_start_xmit) (txb, dev, priority);
 		if (ret == 0) {
 			stats->tx_packets++;
 			stats->tx_bytes += txb->payload_size;
@@ -500,6 +500,7 @@ int ieee80211_tx_frame(struct ieee80211_
 	unsigned long flags;
 	struct net_device_stats *stats = &ieee->stats;
 	struct sk_buff *skb_frag;
+	int priority = -1;
 
 	spin_lock_irqsave(&ieee->lock, flags);
 
@@ -540,7 +541,7 @@ int ieee80211_tx_frame(struct ieee80211_
 	spin_unlock_irqrestore(&ieee->lock, flags);
 
 	if (txb) {
-		if ((*ieee->hard_start_xmit) (txb, ieee->dev) == 0) {
+		if ((*ieee->hard_start_xmit) (txb, ieee->dev, priority) == 0) {
 			stats->tx_packets++;
 			stats->tx_bytes += txb->payload_size;
 			return 0;
---
0.99.8.GIT


--- NEW FILE 0178-ieee80211-Added-ieee80211_geo-to-provide-helper-functions.txt ---
Subject: [PATCH] ieee80211: Added ieee80211_geo to provide helper functions
From: James Ketrenos <jketreno linux intel com>
Date: 1127321798 -0500

tree 385b391fc0d7c124cd0547fdb6183e9a0c333391
parent 97d7a47f76e72bedde7f402785559ed4c7a8e8e8
author James Ketrenos <jketreno linux intel com> 1124447590 -0500
committer James Ketrenos <jketreno linux intel com> 1127313735 -0500

Added ieee80211_geo to provide helper functions to drivers for
implementing supported channel maps.

Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/net/ieee80211.h       |   46 +++++++++++++
 net/ieee80211/Makefile        |    3 +
 net/ieee80211/ieee80211_geo.c |  141 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 189 insertions(+), 1 deletions(-)
 create mode 100644 net/ieee80211/ieee80211_geo.c

applies-to: f6e568913c2d8aa1bf6bfedb3d90a78f2ade747b
02cda6ae01814f58422c45259fb48136fbd7bcc1
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 72bd2b1..b3815fd 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -781,6 +781,38 @@ enum ieee80211_state {
 #define CFG_IEEE80211_COMPUTE_FCS (1<<1)
 #define CFG_IEEE80211_RTS (1<<2)
 
+#define IEEE80211_24GHZ_MIN_CHANNEL 1
+#define IEEE80211_24GHZ_MAX_CHANNEL 14
+#define IEEE80211_24GHZ_CHANNELS    14
+
+#define IEEE80211_52GHZ_MIN_CHANNEL 36
+#define IEEE80211_52GHZ_MAX_CHANNEL 165
+#define IEEE80211_52GHZ_CHANNELS    32
+
+enum {
+	IEEE80211_CH_PASSIVE_ONLY = (1 << 0),
+	IEEE80211_CH_B_ONLY = (1 << 2),
+	IEEE80211_CH_NO_IBSS = (1 << 3),
+	IEEE80211_CH_UNIFORM_SPREADING = (1 << 4),
+	IEEE80211_CH_RADAR_DETECT = (1 << 5),
+	IEEE80211_CH_INVALID = (1 << 6),
+};
+
+struct ieee80211_channel {
+	u16 freq;
+	u8 channel;
+	u8 flags;
+	u8 max_power;
+};
+
+struct ieee80211_geo {
+	u8 name[4];
+	u8 bg_channels;
+	u8 a_channels;
+	struct ieee80211_channel bg[IEEE80211_24GHZ_CHANNELS];
+	struct ieee80211_channel a[IEEE80211_52GHZ_CHANNELS];
+};
+
 struct ieee80211_device {
 	struct net_device *dev;
 	struct ieee80211_security sec;
@@ -789,6 +821,8 @@ struct ieee80211_device {
 	struct net_device_stats stats;
 	struct ieee80211_stats ieee_stats;
 
+	struct ieee80211_geo geo;
+
 	/* Probe / Beacon management */
 	struct list_head network_free_list;
 	struct list_head network_list;
@@ -1005,6 +1039,18 @@ extern void ieee80211_rx_mgt(struct ieee
 			     struct ieee80211_hdr_4addr *header,
 			     struct ieee80211_rx_stats *stats);
 
+/* ieee80211_geo.c */
+extern const struct ieee80211_geo *ieee80211_get_geo(struct ieee80211_device
+						     *ieee);
+extern int ieee80211_set_geo(struct ieee80211_device *ieee,
+			     const struct ieee80211_geo *geo);
+
+extern int ieee80211_is_valid_channel(struct ieee80211_device *ieee,
+				      u8 channel);
+extern int ieee80211_channel_to_index(struct ieee80211_device *ieee,
+				      u8 channel);
+extern u8 ieee80211_freq_to_channel(struct ieee80211_device *ieee, u32 freq);
+
 /* ieee80211_wx.c */
 extern int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
 				 struct iw_request_info *info,
diff --git a/net/ieee80211/Makefile b/net/ieee80211/Makefile
index a6ccac5..f988417 100644
--- a/net/ieee80211/Makefile
+++ b/net/ieee80211/Makefile
@@ -7,5 +7,6 @@ ieee80211-objs := \
 	ieee80211_module.o \
 	ieee80211_tx.o \
 	ieee80211_rx.o \
-	ieee80211_wx.o
+	ieee80211_wx.o \
+	ieee80211_geo.o
 
diff --git a/net/ieee80211/ieee80211_geo.c b/net/ieee80211/ieee80211_geo.c
new file mode 100644
index 0000000..c4b54ef
--- /dev/null
+++ b/net/ieee80211/ieee80211_geo.c
@@ -0,0 +1,141 @@
+/******************************************************************************
+
+  Copyright(c) 2005 Intel Corporation. All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc., 59
+  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+
+  Contact Information:
+  James P. Ketrenos <ipw2100-admin linux intel com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+******************************************************************************/
+#include <linux/compiler.h>
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/if_arp.h>
+#include <linux/in6.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/tcp.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/wireless.h>
+#include <linux/etherdevice.h>
+#include <asm/uaccess.h>
+
+#include <net/ieee80211.h>
+
+int ieee80211_is_valid_channel(struct ieee80211_device *ieee, u8 channel)
+{
+	int i;
+
+	/* Driver needs to initialize the geography map before using
+	 * these helper functions */
+	BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
+
+	if (ieee->freq_band & IEEE80211_24GHZ_BAND)
+		for (i = 0; i < ieee->geo.bg_channels; i++)
+			/* NOTE: If G mode is currently supported but
+			 * this is a B only channel, we don't see it
+			 * as valid. */
+			if ((ieee->geo.bg[i].channel == channel) &&
+			    (!(ieee->mode & IEEE_G) ||
+			     !(ieee->geo.bg[i].flags & IEEE80211_CH_B_ONLY)))
+				return IEEE80211_24GHZ_BAND;
+
+	if (ieee->freq_band & IEEE80211_52GHZ_BAND)
+		for (i = 0; i < ieee->geo.a_channels; i++)
+			if (ieee->geo.a[i].channel == channel)
+				return IEEE80211_52GHZ_BAND;
+
+	return 0;
+}
+
+int ieee80211_channel_to_index(struct ieee80211_device *ieee, u8 channel)
+{
+	int i;
+
+	/* Driver needs to initialize the geography map before using
+	 * these helper functions */
+	BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
+
+	if (ieee->freq_band & IEEE80211_24GHZ_BAND)
+		for (i = 0; i < ieee->geo.bg_channels; i++)
+			if (ieee->geo.bg[i].channel == channel)
+				return i;
+
+	if (ieee->freq_band & IEEE80211_52GHZ_BAND)
+		for (i = 0; i < ieee->geo.a_channels; i++)
+			if (ieee->geo.a[i].channel == channel)
+				return i;
+
+	return -1;
+}
+
+u8 ieee80211_freq_to_channel(struct ieee80211_device * ieee, u32 freq)
+{
+	int i;
+
+	/* Driver needs to initialize the geography map before using
+	 * these helper functions */
+	BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
+
+	freq /= 100000;
+
+	if (ieee->freq_band & IEEE80211_24GHZ_BAND)
+		for (i = 0; i < ieee->geo.bg_channels; i++)
+			if (ieee->geo.bg[i].freq == freq)
+				return ieee->geo.bg[i].channel;
+
+	if (ieee->freq_band & IEEE80211_52GHZ_BAND)
+		for (i = 0; i < ieee->geo.a_channels; i++)
+			if (ieee->geo.a[i].freq == freq)
+				return ieee->geo.a[i].channel;
+
+	return 0;
+}
+
+int ieee80211_set_geo(struct ieee80211_device *ieee,
+		      const struct ieee80211_geo *geo)
+{
+	memcpy(ieee->geo.name, geo->name, 3);
+	ieee->geo.name[3] = '\0';
+	ieee->geo.bg_channels = geo->bg_channels;
+	ieee->geo.a_channels = geo->a_channels;
+	memcpy(ieee->geo.bg, geo->bg, geo->bg_channels *
+	       sizeof(struct ieee80211_channel));
+	memcpy(ieee->geo.a, geo->a, ieee->geo.a_channels *
+	       sizeof(struct ieee80211_channel));
+	return 0;
+}
+
+const struct ieee80211_geo *ieee80211_get_geo(struct ieee80211_device *ieee)
+{
+	return &ieee->geo;
+}
+
+EXPORT_SYMBOL(ieee80211_is_valid_channel);
+EXPORT_SYMBOL(ieee80211_freq_to_channel);
+EXPORT_SYMBOL(ieee80211_channel_to_index);
+EXPORT_SYMBOL(ieee80211_set_geo);
+EXPORT_SYMBOL(ieee80211_get_geo);
---
0.99.8.GIT


--- NEW FILE 0179-ieee80211-Added-ieee80211_radiotap.h.txt ---
Subject: [PATCH] ieee80211: Added ieee80211_radiotap.h
From: James Ketrenos <jketreno linux intel com>
Date: 1127321802 -0500

tree 383c59b2516a61f2683f02dfebbed0caf6ee5dc3
parent a04948f63fd96c4b875a43f78afad1a0874cc441
author Mike Kershaw <dragorn kismetwireless net> 1124447833 -0500
committer James Ketrenos <jketreno linux intel com> 1127313883 -0500

Added ieee80211_radiotap.h to enhance statistic reporting to user space
from wireless drivers.

Signed-off-by: Mike Kershaw <dragorn kismetwireless net>
Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/linux/if_arp.h           |    1 
 include/net/ieee80211_radiotap.h |  231 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 232 insertions(+), 0 deletions(-)
 create mode 100644 include/net/ieee80211_radiotap.h

applies-to: 3efdd946b19928c4dbe039f68ee1cfc65fe57355
3905ec4561b7b049e9c2e27311d072c356dbdee2
diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h
index 0856548..a8b1a20 100644
--- a/include/linux/if_arp.h
+++ b/include/linux/if_arp.h
@@ -84,6 +84,7 @@
 #define ARPHRD_IEEE802_TR 800		/* Magic type ident for TR	*/
 #define ARPHRD_IEEE80211 801		/* IEEE 802.11			*/
 #define ARPHRD_IEEE80211_PRISM 802	/* IEEE 802.11 + Prism2 header  */
+#define ARPHRD_IEEE80211_RADIOTAP 803	/* IEEE 802.11 + radiotap header */
 
 #define ARPHRD_VOID	  0xFFFF	/* Void type, nothing is known */
 #define ARPHRD_NONE	  0xFFFE	/* zero header length */
diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h
new file mode 100644
index 0000000..429b738
--- /dev/null
+++ b/include/net/ieee80211_radiotap.h
@@ -0,0 +1,231 @@
+/* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 20:12:05 sam Exp $ */
+/* $NetBSD: ieee80211_radiotap.h,v 1.11 2005/06/22 06:16:02 dyoung Exp $ */
+
+/*-
+ * Copyright (c) 2003, 2004 David Young.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of David Young may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DAVID
+ * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ */
+
+/*
+ * Modifications to fit into the linux IEEE 802.11 stack,
+ * Mike Kershaw (dragorn kismetwireless net)
+ */
+
+#ifndef IEEE80211RADIOTAP_H
+#define IEEE80211RADIOTAP_H
+
+#include <linux/if_ether.h>
+#include <linux/kernel.h>
+
+/* Radiotap header version (from official NetBSD feed) */
+#define IEEE80211RADIOTAP_VERSION	"1.5"
+/* Base version of the radiotap packet header data */
+#define PKTHDR_RADIOTAP_VERSION		0
+
+/* A generic radio capture format is desirable. There is one for
+ * Linux, but it is neither rigidly defined (there were not even
+ * units given for some fields) nor easily extensible.
+ *
+ * I suggest the following extensible radio capture format. It is
+ * based on a bitmap indicating which fields are present.
+ *
+ * I am trying to describe precisely what the application programmer
+ * should expect in the following, and for that reason I tell the
+ * units and origin of each measurement (where it applies), or else I
+ * use sufficiently weaselly language ("is a monotonically nondecreasing
+ * function of...") that I cannot set false expectations for lawyerly
+ * readers.
+ */
+
+/* XXX tcpdump/libpcap do not tolerate variable-length headers,
+ * yet, so we pad every radiotap header to 64 bytes. Ugh.
+ */
+#define IEEE80211_RADIOTAP_HDRLEN	64
+
+/* The radio capture header precedes the 802.11 header. */
+struct ieee80211_radiotap_header {
+	u8 it_version;		/* Version 0. Only increases
+				 * for drastic changes,
+				 * introduction of compatible
+				 * new fields does not count.
+				 */
+	u8 it_pad;
+	u16 it_len;		/* length of the whole
+				 * header in bytes, including
+				 * it_version, it_pad,
+				 * it_len, and data fields.
+				 */
+	u32 it_present;		/* A bitmap telling which
+				 * fields are present. Set bit 31
+				 * (0x80000000) to extend the
+				 * bitmap by another 32 bits.
+				 * Additional extensions are made
+				 * by setting bit 31.
+				 */
+};
+
+/* Name                                 Data type       Units
+ * ----                                 ---------       -----
+ *
+ * IEEE80211_RADIOTAP_TSFT              u64       microseconds
+ *
+ *      Value in microseconds of the MAC's 64-bit 802.11 Time
+ *      Synchronization Function timer when the first bit of the
+ *      MPDU arrived at the MAC. For received frames, only.
+ *
+ * IEEE80211_RADIOTAP_CHANNEL           2 x u16   MHz, bitmap
+ *
+ *      Tx/Rx frequency in MHz, followed by flags (see below).
+ *
+ * IEEE80211_RADIOTAP_FHSS              u16       see below
+ *
+ *      For frequency-hopping radios, the hop set (first byte)
+ *      and pattern (second byte).
+ *
+ * IEEE80211_RADIOTAP_RATE              u8        500kb/s
+ *
+ *      Tx/Rx data rate
+ *
+ * IEEE80211_RADIOTAP_DBM_ANTSIGNAL     int8_t          decibels from
+ *                                                      one milliwatt (dBm)
+ *
+ *      RF signal power at the antenna, decibel difference from
+ *      one milliwatt.
+ *
+ * IEEE80211_RADIOTAP_DBM_ANTNOISE      int8_t          decibels from
+ *                                                      one milliwatt (dBm)
+ *
+ *      RF noise power at the antenna, decibel difference from one
+ *      milliwatt.
+ *
+ * IEEE80211_RADIOTAP_DB_ANTSIGNAL      u8        decibel (dB)
+ *
+ *      RF signal power at the antenna, decibel difference from an
+ *      arbitrary, fixed reference.
+ *
+ * IEEE80211_RADIOTAP_DB_ANTNOISE       u8        decibel (dB)
+ *
+ *      RF noise power at the antenna, decibel difference from an
+ *      arbitrary, fixed reference point.
+ *
+ * IEEE80211_RADIOTAP_LOCK_QUALITY      u16       unitless
+ *
+ *      Quality of Barker code lock. Unitless. Monotonically
+ *      nondecreasing with "better" lock strength. Called "Signal
+ *      Quality" in datasheets.  (Is there a standard way to measure
+ *      this?)
+ *
+ * IEEE80211_RADIOTAP_TX_ATTENUATION    u16       unitless
+ *
+ *      Transmit power expressed as unitless distance from max
+ *      power set at factory calibration.  0 is max power.
+ *      Monotonically nondecreasing with lower power levels.
+ *
+ * IEEE80211_RADIOTAP_DB_TX_ATTENUATION u16       decibels (dB)
+ *
+ *      Transmit power expressed as decibel distance from max power
+ *      set at factory calibration.  0 is max power.  Monotonically
+ *      nondecreasing with lower power levels.
+ *
+ * IEEE80211_RADIOTAP_DBM_TX_POWER      int8_t          decibels from
+ *                                                      one milliwatt (dBm)
+ *
+ *      Transmit power expressed as dBm (decibels from a 1 milliwatt
+ *      reference). This is the absolute power level measured at
+ *      the antenna port.
+ *
+ * IEEE80211_RADIOTAP_FLAGS             u8        bitmap
+ *
+ *      Properties of transmitted and received frames. See flags
+ *      defined below.
+ *
+ * IEEE80211_RADIOTAP_ANTENNA           u8        antenna index
+ *
+ *      Unitless indication of the Rx/Tx antenna for this packet.
+ *      The first antenna is antenna 0.
+ *
+ * IEEE80211_RADIOTAP_FCS           	u32       data
+ *
+ *	FCS from frame in network byte order.
+ */
+enum ieee80211_radiotap_type {
+	IEEE80211_RADIOTAP_TSFT = 0,
+	IEEE80211_RADIOTAP_FLAGS = 1,
+	IEEE80211_RADIOTAP_RATE = 2,
+	IEEE80211_RADIOTAP_CHANNEL = 3,
+	IEEE80211_RADIOTAP_FHSS = 4,
+	IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
+	IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
+	IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
+	IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
+	IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
+	IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
+	IEEE80211_RADIOTAP_ANTENNA = 11,
+	IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
+	IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
+	IEEE80211_RADIOTAP_EXT = 31,
+};
+
+/* Channel flags. */
+#define	IEEE80211_CHAN_TURBO	0x0010	/* Turbo channel */
+#define	IEEE80211_CHAN_CCK	0x0020	/* CCK channel */
+#define	IEEE80211_CHAN_OFDM	0x0040	/* OFDM channel */
+#define	IEEE80211_CHAN_2GHZ	0x0080	/* 2 GHz spectrum channel. */
+#define	IEEE80211_CHAN_5GHZ	0x0100	/* 5 GHz spectrum channel */
+#define	IEEE80211_CHAN_PASSIVE	0x0200	/* Only passive scan allowed */
+#define	IEEE80211_CHAN_DYN	0x0400	/* Dynamic CCK-OFDM channel */
+#define	IEEE80211_CHAN_GFSK	0x0800	/* GFSK channel (FHSS PHY) */
+
+/* For IEEE80211_RADIOTAP_FLAGS */
+#define	IEEE80211_RADIOTAP_F_CFP	0x01	/* sent/received
+						 * during CFP
+						 */
+#define	IEEE80211_RADIOTAP_F_SHORTPRE	0x02	/* sent/received
+						 * with short
+						 * preamble
+						 */
+#define	IEEE80211_RADIOTAP_F_WEP	0x04	/* sent/received
+						 * with WEP encryption
+						 */
+#define	IEEE80211_RADIOTAP_F_FRAG	0x08	/* sent/received
+						 * with fragmentation
+						 */
+#define	IEEE80211_RADIOTAP_F_FCS	0x10	/* frame includes FCS */
+#define	IEEE80211_RADIOTAP_F_DATAPAD	0x20	/* frame has padding between
+						 * 802.11 header and payload
+						 * (to 32-bit boundary)
+						 */
+
+/* Ugly macro to convert literal channel numbers into their mhz equivalents
+ * There are certianly some conditions that will break this (like feeding it '30')
+ * but they shouldn't arise since nothing talks on channel 30. */
+#define ieee80211chan2mhz(x) \
+	(((x) <= 14) ? \
+	(((x) == 14) ? 2484 : ((x) * 5) + 2407) : \
+	((x) + 1000) * 5)
+
+#endif				/* IEEE80211_RADIOTAP_H */
---
0.99.8.GIT


--- NEW FILE 0180-ieee80211-Additional-fixes-for-endian-aware-types.txt ---
Subject: [PATCH] ieee80211: Additional fixes for endian-aware types
From: James Ketrenos <jketreno linux intel com>
Date: 1127321809 -0500

tree 589bbb92ce7cdf7c2ae820b0ebd3f8fbf1baeee9
parent c6ce9081e79e8836a11e86e3d38297521a2420be
author Jiri Benc <jbenc suse cz> 1125015310 -0400
committer James Ketrenos <jketreno linux intel com> 1127313914 -0500

Additional fixes for endian-aware types

Based on the application of __le16/__be16 changes already made w/ a
prior patch by Michael Wu <flamingice sourmilk net>

Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/net/ieee80211.h |   58 ++++++++++++++++++++++++-----------------------
 1 files changed, 29 insertions(+), 29 deletions(-)

applies-to: 81a34fc3ce8f5bf8aa937023e23f90c7e2ed6760
cdcfc210820b8e043cb606eddc145906185c6743
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index b3815fd..372a173 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -503,68 +503,68 @@ enum ieee80211_mfie {
  * information to determine what type of underlying data type is actually
  * stored in the data. */
 struct ieee80211_hdr {
-	u16 frame_ctl;
-	u16 duration_id;
+	__le16 frame_ctl;
+	__le16 duration_id;
 	u8 payload[0];
 } __attribute__ ((packed));
 
 struct ieee80211_hdr_1addr {
-	u16 frame_ctl;
-	u16 duration_id;
+	__le16 frame_ctl;
+	__le16 duration_id;
 	u8 addr1[ETH_ALEN];
 	u8 payload[0];
 } __attribute__ ((packed));
 
 struct ieee80211_hdr_2addr {
-	u16 frame_ctl;
-	u16 duration_id;
+	__le16 frame_ctl;
+	__le16 duration_id;
 	u8 addr1[ETH_ALEN];
 	u8 addr2[ETH_ALEN];
 	u8 payload[0];
 } __attribute__ ((packed));
 
 struct ieee80211_hdr_3addr {
-	u16 frame_ctl;
-	u16 duration_id;
+	__le16 frame_ctl;
+	__le16 duration_id;
 	u8 addr1[ETH_ALEN];
 	u8 addr2[ETH_ALEN];
 	u8 addr3[ETH_ALEN];
-	u16 seq_ctl;
+	__le16 seq_ctl;
 	u8 payload[0];
 } __attribute__ ((packed));
 
 struct ieee80211_hdr_4addr {
-	u16 frame_ctl;
-	u16 duration_id;
+	__le16 frame_ctl;
+	__le16 duration_id;
 	u8 addr1[ETH_ALEN];
 	u8 addr2[ETH_ALEN];
 	u8 addr3[ETH_ALEN];
-	u16 seq_ctl;
+	__le16 seq_ctl;
 	u8 addr4[ETH_ALEN];
 	u8 payload[0];
 } __attribute__ ((packed));
 
 struct ieee80211_hdr_3addrqos {
-	u16 frame_ctl;
-	u16 duration_id;
+	__le16 frame_ctl;
+	__le16 duration_id;
 	u8 addr1[ETH_ALEN];
 	u8 addr2[ETH_ALEN];
 	u8 addr3[ETH_ALEN];
-	u16 seq_ctl;
+	__le16 seq_ctl;
 	u8 payload[0];
-	u16 qos_ctl;
+	__le16 qos_ctl;
 } __attribute__ ((packed));
 
 struct ieee80211_hdr_4addrqos {
-	u16 frame_ctl;
-	u16 duration_id;
+	__le16 frame_ctl;
+	__le16 duration_id;
 	u8 addr1[ETH_ALEN];
 	u8 addr2[ETH_ALEN];
 	u8 addr3[ETH_ALEN];
-	u16 seq_ctl;
+	__le16 seq_ctl;
 	u8 addr4[ETH_ALEN];
 	u8 payload[0];
-	u16 qos_ctl;
+	__le16 qos_ctl;
 } __attribute__ ((packed));
 
 struct ieee80211_info_element {
@@ -600,7 +600,7 @@ struct ieee80211_auth {
 
 struct ieee80211_disassoc {
 	struct ieee80211_hdr_3addr header;
-	u16 reason_code;
+	__le16 reason_code;
 	struct ieee80211_info_element info_element[0];
 } __attribute__ ((packed));
 
@@ -622,8 +622,8 @@ struct ieee80211_probe_response {
 
 struct ieee80211_assoc_request {
 	struct ieee80211_hdr_3addr header;
-	u16 capability;
-	u16 listen_interval;
+	__le16 capability;
+	__le16 listen_interval;
 	struct ieee80211_info_element info_element[0];
 } __attribute__ ((packed));
 
@@ -648,8 +648,8 @@ struct ieee80211_txb {
 	u8 encrypted;
 	u8 rts_included;
 	u8 reserved;
-	u16 frag_size;
-	u16 payload_size;
+	__le16 frag_size;
+	__le16 payload_size;
 	struct sk_buff *fragments[0];
 };
 
@@ -699,7 +699,7 @@ struct ieee80211_qos_information_element
 struct ieee80211_qos_ac_parameter {
 	u8 aci_aifsn;
 	u8 ecw_min_max;
-	u16 tx_op_limit;
+	__le16 tx_op_limit;
 } __attribute__ ((packed));
 
 struct ieee80211_qos_parameter_info {
@@ -709,11 +709,11 @@ struct ieee80211_qos_parameter_info {
 } __attribute__ ((packed));
 
 struct ieee80211_qos_parameters {
-	u16 cw_min[QOS_QUEUE_NUM];
-	u16 cw_max[QOS_QUEUE_NUM];
+	__le16 cw_min[QOS_QUEUE_NUM];
+	__le16 cw_max[QOS_QUEUE_NUM];
 	u8 aifs[QOS_QUEUE_NUM];
 	u8 flag[QOS_QUEUE_NUM];
-	u16 tx_op_limit[QOS_QUEUE_NUM];
+	__le16 tx_op_limit[QOS_QUEUE_NUM];
 } __attribute__ ((packed));
 
 struct ieee80211_qos_data {
---
0.99.8.GIT


--- NEW FILE 0181-ieee80211-extern-inline-to-static-inline.txt ---
Subject: [PATCH] ieee80211: "extern inline" to "static inline"
From: James Ketrenos <jketreno linux intel com>
Date: 1127321904 -0500

tree bce04549ce0a8239d8083d8da5c3d12f7e1aecd9
parent b15a5153d5f1c75d9435d5ce19b52287059d5d54
author Adrian Bunk <bunk stusta de> 1125026386 -0500
committer James Ketrenos <jketreno linux intel com> 1127313953 -0500

"extern inline" doesn't make much sense.

Signed-off-by: Adrian Bunk <bunk stusta de>
Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/net/ieee80211.h |   14 +++++++-------
 1 files changed, 7 insertions(+), 7 deletions(-)

applies-to: 96765d7169945c83d8ace4db8d5bde187ec2d812
9ba7e0d1579485ce231594651b39c169029f5d67
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 372a173..9310b2e 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -929,12 +929,12 @@ struct ieee80211_device {
 #define IEEE_G            (1<<2)
 #define IEEE_MODE_MASK    (IEEE_A|IEEE_B|IEEE_G)
 
-extern inline void *ieee80211_priv(struct net_device *dev)
+static inline void *ieee80211_priv(struct net_device *dev)
 {
 	return ((struct ieee80211_device *)netdev_priv(dev))->priv;
 }
 
-extern inline int ieee80211_is_empty_essid(const char *essid, int essid_len)
+static inline int ieee80211_is_empty_essid(const char *essid, int essid_len)
 {
 	/* Single white space is for Linksys APs */
 	if (essid_len == 1 && essid[0] == ' ')
@@ -950,7 +950,7 @@ extern inline int ieee80211_is_empty_ess
 	return 1;
 }
 
-extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee,
+static inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee,
 					  int mode)
 {
 	/*
@@ -977,7 +977,7 @@ extern inline int ieee80211_is_valid_mod
 	return 0;
 }
 
-extern inline int ieee80211_get_hdrlen(u16 fc)
+static inline int ieee80211_get_hdrlen(u16 fc)
 {
 	int hdrlen = IEEE80211_3ADDR_LEN;
 	u16 stype = WLAN_FC_GET_STYPE(fc);
@@ -1005,7 +1005,7 @@ extern inline int ieee80211_get_hdrlen(u
 	return hdrlen;
 }
 
-extern inline u8 *ieee80211_get_payload(struct ieee80211_hdr *hdr)
+static inline u8 *ieee80211_get_payload(struct ieee80211_hdr *hdr)
 {
 	switch (ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl))) {
 	case IEEE80211_1ADDR_LEN:
@@ -1070,12 +1070,12 @@ extern int ieee80211_wx_get_encodeext(st
 				      union iwreq_data *wrqu, char *extra);
 #endif
 
-extern inline void ieee80211_increment_scans(struct ieee80211_device *ieee)
+static inline void ieee80211_increment_scans(struct ieee80211_device *ieee)
 {
 	ieee->scans++;
 }
 
-extern inline int ieee80211_get_scans(struct ieee80211_device *ieee)
+static inline int ieee80211_get_scans(struct ieee80211_device *ieee)
 {
 	return ieee->scans;
 }
---
0.99.8.GIT


--- NEW FILE 0182-ieee80211-Type-o-capbility-definition-for-QoS-and-ERP-parsing.txt ---
Subject: [PATCH] ieee80211: Type-o, capbility definition for QoS, and ERP parsing
From: James Ketrenos <jketreno linux intel com>
Date: 1127321909 -0500

tree 3ac0dd07b9972dfd68fee47ec2152d3d378de000
parent 9ada1d971d9829c34a14d98840080b7e69fdff6b
author Mohamed Abbad <mohamed abbas intel com> 1126054379 -0500
committer James Ketrenos <jketreno linux intel com> 1127314340 -0500

Type-o, capbility definition for QoS, and ERP parsing

Added WLAN_CAPABILITY_QOS
Fixed type-o WLAN_CAPABILITY_OSSS_OFDM -> WLAN_CAPABILITY_DSSS_OFDM
Added ERP IE parsing to ieee80211_rx
Added handle_probe_request callback.

Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/net/ieee80211.h      |    7 ++++++-
 net/ieee80211/ieee80211_rx.c |   25 ++++++++++++++++++++++++-
 2 files changed, 30 insertions(+), 2 deletions(-)

applies-to: a00b1757d7a2d548b0e3cd13589aaadeb88d1d3c
42c94e43be27f8b9be9b5be491bae8af05e54dbd
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 9310b2e..931737e 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -225,8 +225,9 @@ struct ieee80211_snap_hdr {
 #define WLAN_CAPABILITY_PBCC (1<<6)
 #define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7)
 #define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8)
+#define WLAN_CAPABILITY_QOS (1<<9)
 #define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10)
-#define WLAN_CAPABILITY_OSSS_OFDM (1<<13)
+#define WLAN_CAPABILITY_DSSS_OFDM (1<<13)
 
 /* Status codes */
 enum ieee80211_statuscode {
@@ -756,6 +757,7 @@ struct ieee80211_network {
 	u16 beacon_interval;
 	u16 listen_interval;
 	u16 atim_window;
+	u8 erp_value;
 	u8 wpa_ie[MAX_WPA_IE_LEN];
 	size_t wpa_ie_len;
 	u8 rsn_ie[MAX_WPA_IE_LEN];
@@ -910,6 +912,9 @@ struct ieee80211_device {
 	int (*handle_probe_response) (struct net_device * dev,
 				      struct ieee80211_probe_response * resp,
 				      struct ieee80211_network * network);
+	int (*handle_probe_request) (struct net_device * dev,
+				     struct ieee80211_probe_request * req,
+				     struct ieee80211_rx_stats * stats);
 	int (*handle_assoc_response) (struct net_device * dev,
 				      struct ieee80211_assoc_response * resp,
 				      struct ieee80211_network * network);
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 2c46135..8bcdbab 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -1065,6 +1065,8 @@ static inline int ieee80211_network_init
 	network->ssid_len = 0;
 	network->flags = 0;
 	network->atim_window = 0;
+	network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ?
+		0x3 : 0x0;
 
 	if (stats->freq == IEEE80211_52GHZ_BAND) {
 		/* for A band (No DS info) */
@@ -1178,8 +1180,16 @@ static inline int ieee80211_network_init
 			IEEE80211_DEBUG_SCAN("MFIE_TYPE_TIM: ignored\n");
 			break;
 
+		case MFIE_TYPE_ERP_INFO:
+			network->erp_value = info_element->data[0];
+			IEEE80211_DEBUG_SCAN("MFIE_TYPE_ERP_SET: %d\n",
+					     network->erp_value);
+			break;
+
 		case MFIE_TYPE_IBSS_SET:
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_IBSS_SET: ignored\n");
+			network->atim_window = info_element->data[0];
+			IEEE80211_DEBUG_SCAN("MFIE_TYPE_IBSS_SET: %d\n",
+					     network->atim_window);
 			break;
 
 		case MFIE_TYPE_CHALLENGE:
@@ -1290,6 +1300,7 @@ static inline void update_network(struct
 	dst->beacon_interval = src->beacon_interval;
 	dst->listen_interval = src->listen_interval;
 	dst->atim_window = src->atim_window;
+	dst->erp_value = src->erp_value;
 
 	memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
 	dst->wpa_ie_len = src->wpa_ie_len;
@@ -1471,6 +1482,18 @@ void ieee80211_rx_mgt(struct ieee80211_d
 						       (header->frame_ctl)));
 		break;
 
+	case IEEE80211_STYPE_PROBE_REQ:
+		IEEE80211_DEBUG_MGMT("recieved auth (%d)\n",
+				     WLAN_FC_GET_STYPE(le16_to_cpu
+						       (header->frame_ctl)));
+
+		if (ieee->handle_probe_request != NULL)
+			ieee->handle_probe_request(ieee->dev,
+						   (struct
+						    ieee80211_probe_request *)
+						   header, stats);
+		break;
+
 	case IEEE80211_STYPE_PROBE_RESP:
 		IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n",
 				     WLAN_FC_GET_STYPE(le16_to_cpu
---
0.99.8.GIT


--- NEW FILE 0183-ieee80211-Mixed-PTK-GTK-CCMP-TKIP-support.txt ---
Subject: [PATCH] ieee80211: Mixed PTK/GTK CCMP/TKIP support
From: James Ketrenos <jketreno linux intel com>
Date: 1127321912 -0500

tree 5c7559a1216ae1121487f6aed94a6017490729b3
parent c1ff4c22e5622c8987bf96c09158c4924cde98c2
author Hong Liu <hong liu intel com> 1125482767 +0800
committer James Ketrenos <jketreno linux intel com> 1127314427 -0500

Mixed PTK/GTK CCMP/TKIP support.

Signed-off-by: Hong Liu <hong liu intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/net/ieee80211.h          |    3 +++
 net/ieee80211/ieee80211_module.c |    2 ++
 net/ieee80211/ieee80211_rx.c     |    5 +++--
 net/ieee80211/ieee80211_wx.c     |   13 ++++++++++---
 4 files changed, 18 insertions(+), 5 deletions(-)

applies-to: 83ec8abd98a18e1539c6b99979f11b5d6c3341bc
ccd0fda3a6d9186d067893114f65b8df758d5a1f
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 931737e..ef85a96 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -851,6 +851,9 @@ struct ieee80211_device {
 	int host_encrypt;
 	int host_encrypt_msdu;
 	int host_decrypt;
+	/* host performs multicast decryption */
+	int host_mc_decrypt;
+
 	int host_open_frag;
 	int ieee802_1x;		/* is IEEE 802.1X used */
 
diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c
index dddc616..941f1a1 100644
--- a/net/ieee80211/ieee80211_module.c
+++ b/net/ieee80211/ieee80211_module.c
@@ -133,6 +133,8 @@ struct net_device *alloc_ieee80211(int s
 	/* Default to enabling full open WEP with host based encrypt/decrypt */
 	ieee->host_encrypt = 1;
 	ieee->host_decrypt = 1;
+	ieee->host_mc_decrypt = 1;
+
 	/* Host fragementation in Open mode. Default is enabled.
 	 * Note: host fragmentation is always enabled if host encryption
 	 * is enabled. For cards can do hardware encryption, they must do
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 8bcdbab..65315bc 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -409,7 +409,8 @@ int ieee80211_rx(struct ieee80211_device
 		return 1;
 	}
 
-	if (ieee->host_decrypt) {
+	if (is_multicast_ether_addr(hdr->addr1) ? ieee->host_mc_decrypt :
+	    ieee->host_decrypt) {
 		int idx = 0;
 		if (skb->len >= hdrlen + 3)
 			idx = skb->data[hdrlen + 3] >> 6;
@@ -1066,7 +1067,7 @@ static inline int ieee80211_network_init
 	network->flags = 0;
 	network->atim_window = 0;
 	network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ?
-		0x3 : 0x0;
+	    0x3 : 0x0;
 
 	if (stats->freq == IEEE80211_52GHZ_BAND) {
 		/* for A band (No DS info) */
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index db66217..d710f47 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -493,6 +493,7 @@ int ieee80211_wx_set_encodeext(struct ie
 	struct iw_point *encoding = &wrqu->encoding;
 	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
 	int i, idx, ret = 0;
+	int group_key = 0;
 	const char *alg, *module;
 	struct ieee80211_crypto_ops *ops;
 	struct ieee80211_crypt_data **crypt;
@@ -509,9 +510,10 @@ int ieee80211_wx_set_encodeext(struct ie
 	} else
 		idx = ieee->tx_keyidx;
 
-	if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
+	if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
 		crypt = &ieee->crypt[idx];
-	else {
+		group_key = 1;
+	} else {
 		if (idx != 0)
 			return -EINVAL;
 		if (ieee->iw_mode == IW_MODE_INFRA)
@@ -542,7 +544,9 @@ int ieee80211_wx_set_encodeext(struct ie
 	sec.enabled = 1;
 	sec.encrypt = 1;
 
-	if (!(ieee->host_encrypt || ieee->host_decrypt))
+	if (group_key ? !ieee->host_mc_decrypt :
+	    !(ieee->host_encrypt || ieee->host_decrypt ||
+	      ieee->host_encrypt_msdu))
 		goto skip_host_crypt;
 
 	switch (ext->alg) {
@@ -632,6 +636,9 @@ int ieee80211_wx_set_encodeext(struct ie
 			sec.flags |= SEC_LEVEL;
 			sec.level = SEC_LEVEL_3;
 		}
+		/* Don't set sec level for group keys. */
+		if (group_key)
+			sec.flags &= ~SEC_LEVEL;
 	}
       done:
 	if (ieee->set_security)
---
0.99.8.GIT


--- NEW FILE 0184-ieee80211-Keep-auth-mode-unchanged-after-iwconfig-key-off-on-cycle.txt ---
Subject: [PATCH] ieee80211: Keep auth mode unchanged after iwconfig key off/on cycle
From: James Ketrenos <jketreno linux intel com>
Date: 1127321918 -0500

tree 2e6f6e7dc4f4eeb8e3dc265020016dd53e40578a
parent ba2075794a089430b3dd7c90ff46ce1b67e9c7cc
author Zhu Yi <yi zhu intel com> 1125551043 +0800
committer James Ketrenos <jketreno linux intel com> 1127314475 -0500

[Bug 768] Keep auth mode unchanged after iwconfig key off/on cycle.

Signed-off-by: Zhu Yi <yi zhu intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 net/ieee80211/ieee80211_wx.c |   14 +++++++++-----
 1 files changed, 9 insertions(+), 5 deletions(-)

applies-to: 2a6301d4762851c7253a21b50e10818cc1bab5b3
7dc888fefc053996354ca40602159e0ce5669f86
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index d710f47..65aa96d 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -412,11 +412,15 @@ int ieee80211_wx_set_encode(struct ieee8
 			sec.flags |= SEC_ACTIVE_KEY;
 		}
 	}
-	ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
-	sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
-	sec.flags |= SEC_AUTH_MODE;
-	IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
-			   "OPEN" : "SHARED KEY");
+	if (erq->flags & (IW_ENCODE_OPEN | IW_ENCODE_RESTRICTED)) {
+		ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
+		sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN :
+		    WLAN_AUTH_SHARED_KEY;
+		sec.flags |= SEC_AUTH_MODE;
+		IEEE80211_DEBUG_WX("Auth: %s\n",
+				   sec.auth_mode == WLAN_AUTH_OPEN ?
+				   "OPEN" : "SHARED KEY");
+	}
 
 	/* For now we just support WEP, so only set that security level...
 	 * TODO: When WPA is added this is one place that needs to change */
---
0.99.8.GIT


--- NEW FILE 0185-ieee80211-Updated-copyright-dates.txt ---
Subject: [PATCH] ieee80211: Updated copyright dates
From: James Ketrenos <jketreno linux intel com>
Date: 1127321923 -0500

tree 0d3e41e574fcb41b9da7f0b7e1d27ec350726654
parent dbe2885fe2f454d538eaaabefc741ded1026f476
author James Ketrenos <jketreno linux intel com> 1126720499 -0500
committer James Ketrenos <jketreno linux intel com> 1127314531 -0500

Updated copyright dates.

NOTE:  This is a split out of just the copyright updates from patch
24/29 in the prior series.

Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/net/ieee80211.h          |    2 +-
 net/ieee80211/ieee80211_module.c |    2 +-
 net/ieee80211/ieee80211_rx.c     |    2 +-
 net/ieee80211/ieee80211_tx.c     |    2 +-
 net/ieee80211/ieee80211_wx.c     |    2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

applies-to: a92b0c4d487649958d908fbd2ce60425ca5ac8e8
ebeaddcc02fd47d1dbb7f25318d046461d90e4af
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index ef85a96..5380948 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -11,7 +11,7 @@
  *
  * Adaption to a generic IEEE 802.11 stack by James Ketrenos
  * <jketreno linux intel com>
- * Copyright (c) 2004, Intel Corporation
+ * Copyright (c) 2004-2005, Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c
index 941f1a1..0ae91c9 100644
--- a/net/ieee80211/ieee80211_module.c
+++ b/net/ieee80211/ieee80211_module.c
@@ -1,6 +1,6 @@
 /*******************************************************************************
 
-  Copyright(c) 2004 Intel Corporation. All rights reserved.
+  Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
 
   Portions of this file are based on the WEP enablement code provided by the
   Host AP project hostap-drivers v0.1.3
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 65315bc..256d552 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -5,7 +5,7 @@
  * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
  * <jkmaline cc hut fi>
  * Copyright (c) 2002-2003, Jouni Malinen <jkmaline cc hut fi>
- * Copyright (c) 2004, Intel Corporation
+ * Copyright (c) 2004-2005, Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index aba72f9..24ade5f 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
+  Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms of version 2 of the GNU General Public License as
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index 65aa96d..e28648e 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright(c) 2004 Intel Corporation. All rights reserved.
+  Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
 
   Portions of this file are based on the WEP enablement code provided by the
   Host AP project hostap-drivers v0.1.3
---
0.99.8.GIT


Index: 0186-ieee80211-Updated-hostap-to-be-compatible-with-ieee80211_hdr-changes.txt
===================================================================
RCS file: 0186-ieee80211-Updated-hostap-to-be-compatible-with-ieee80211_hdr-changes.txt
diff -N 0186-ieee80211-Updated-hostap-to-be-compatible-with-ieee80211_hdr-changes.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0186-ieee80211-Updated-hostap-to-be-compatible-with-ieee80211_hdr-changes.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,610 @@
+Subject: [PATCH] ieee80211: Updated hostap to be compatible with ieee80211_hdr changes
+From: James Ketrenos <jketreno linux intel com>
+Date: 1127323429 -0500
+
+tree 8ec97d9056ceaf0f845ed51175dd842b700baadd
+parent 329128457008ace3110c96971addf85a767dd5af
+author James Ketrenos <jketreno linux intel com> 1126714484 -0500
+committer James Ketrenos <jketreno linux intel com> 1127316636 -0500
+
+Updated hostap to be compatible with ieee80211_hdr changes.
+
+Change accomplished via:
+
+for i in hostap_ap.{c,h} hostap_80211_{t,r}x.c; do
+	sed -i -e "s:ieee80211_hdr\([^_]\):ieee80211_hdr_4addr\1:g" \
+		drivers/net/wireless/hostap/$i
+done
+
+CC: Jouni Malinen <jkmaline cc hut fi>
+
+Signed-off-by: James Ketrenos <jketreno linux intel com>
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/hostap/hostap_80211_rx.c |   40 ++++++++-------
+ drivers/net/wireless/hostap/hostap_80211_tx.c |   20 ++++----
+ drivers/net/wireless/hostap/hostap_ap.c       |   66 +++++++++++++------------
+ drivers/net/wireless/hostap/hostap_ap.h       |    6 +-
+ 4 files changed, 66 insertions(+), 66 deletions(-)
+
+applies-to: f623693884cb482dcbf3c5e3974442ddd31ca6de
+d041674d62e1ad565f2fb6d53ae80b31d6656033
+diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c
+index b050124..42e61c6 100644
+--- a/drivers/net/wireless/hostap/hostap_80211_rx.c
++++ b/drivers/net/wireless/hostap/hostap_80211_rx.c
+@@ -6,10 +6,10 @@
+ void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,
+ 			  struct hostap_80211_rx_status *rx_stats)
+ {
+-	struct ieee80211_hdr *hdr;
++	struct ieee80211_hdr_4addr *hdr;
+ 	u16 fc;
+ 
+-	hdr = (struct ieee80211_hdr *) skb->data;
++	hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ 
+ 	printk(KERN_DEBUG "%s: RX signal=%d noise=%d rate=%d len=%d "
+ 	       "jiffies=%ld\n",
+@@ -51,7 +51,7 @@ int prism2_rx_80211(struct net_device *d
+ 	int hdrlen, phdrlen, head_need, tail_need;
+ 	u16 fc;
+ 	int prism_header, ret;
+-	struct ieee80211_hdr *hdr;
++	struct ieee80211_hdr_4addr *hdr;
+ 
+ 	iface = netdev_priv(dev);
+ 	local = iface->local;
+@@ -70,7 +70,7 @@ int prism2_rx_80211(struct net_device *d
+ 		phdrlen = 0;
+ 	}
+ 
+-	hdr = (struct ieee80211_hdr *) skb->data;
++	hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ 	fc = le16_to_cpu(hdr->frame_ctl);
+ 
+ 	if (type == PRISM2_RX_MGMT && (fc & IEEE80211_FCTL_VERS)) {
+@@ -215,7 +215,7 @@ prism2_frag_cache_find(local_info_t *loc
+ 
+ /* Called only as a tasklet (software IRQ) */
+ static struct sk_buff *
+-prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr *hdr)
++prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr_4addr *hdr)
+ {
+ 	struct sk_buff *skb = NULL;
+ 	u16 sc;
+@@ -229,7 +229,7 @@ prism2_frag_cache_get(local_info_t *loca
+ 	if (frag == 0) {
+ 		/* Reserve enough space to fit maximum frame length */
+ 		skb = dev_alloc_skb(local->dev->mtu +
+-				    sizeof(struct ieee80211_hdr) +
++				    sizeof(struct ieee80211_hdr_4addr) +
+ 				    8 /* LLC */ +
+ 				    2 /* alignment */ +
+ 				    8 /* WEP */ + ETH_ALEN /* WDS */);
+@@ -267,7 +267,7 @@ prism2_frag_cache_get(local_info_t *loca
+ 
+ /* Called only as a tasklet (software IRQ) */
+ static int prism2_frag_cache_invalidate(local_info_t *local,
+-					struct ieee80211_hdr *hdr)
++					struct ieee80211_hdr_4addr *hdr)
+ {
+ 	u16 sc;
+ 	unsigned int seq;
+@@ -441,7 +441,7 @@ hostap_rx_frame_mgmt(local_info_t *local
+ 		     u16 stype)
+ {
+ 	if (local->iw_mode == IW_MODE_MASTER) {
+-		hostap_update_sta_ps(local, (struct ieee80211_hdr *)
++		hostap_update_sta_ps(local, (struct ieee80211_hdr_4addr *)
+ 				     skb->data);
+ 	}
+ 
+@@ -520,7 +520,7 @@ static inline struct net_device *prism2_
+ 
+ 
+ static inline int
+-hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr *hdr,
++hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
+ 		    u16 fc, struct net_device **wds)
+ {
+ 	/* FIX: is this really supposed to accept WDS frames only in Master
+@@ -579,13 +579,13 @@ static int hostap_is_eapol_frame(local_i
+ {
+ 	struct net_device *dev = local->dev;
+ 	u16 fc, ethertype;
+-	struct ieee80211_hdr *hdr;
++	struct ieee80211_hdr_4addr *hdr;
+ 	u8 *pos;
+ 
+ 	if (skb->len < 24)
+ 		return 0;
+ 
+-	hdr = (struct ieee80211_hdr *) skb->data;
++	hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ 	fc = le16_to_cpu(hdr->frame_ctl);
+ 
+ 	/* check that the frame is unicast frame to us */
+@@ -619,13 +619,13 @@ static inline int
+ hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
+ 			struct ieee80211_crypt_data *crypt)
+ {
+-	struct ieee80211_hdr *hdr;
++	struct ieee80211_hdr_4addr *hdr;
+ 	int res, hdrlen;
+ 
+ 	if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
+ 		return 0;
+ 
+-	hdr = (struct ieee80211_hdr *) skb->data;
++	hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ 	hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
+ 
+ 	if (local->tkip_countermeasures &&
+@@ -658,13 +658,13 @@ static inline int
+ hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb,
+ 			     int keyidx, struct ieee80211_crypt_data *crypt)
+ {
+-	struct ieee80211_hdr *hdr;
++	struct ieee80211_hdr_4addr *hdr;
+ 	int res, hdrlen;
+ 
+ 	if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
+ 		return 0;
+ 
+-	hdr = (struct ieee80211_hdr *) skb->data;
++	hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ 	hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
+ 
+ 	atomic_inc(&crypt->refcnt);
+@@ -689,7 +689,7 @@ void hostap_80211_rx(struct net_device *
+ {
+ 	struct hostap_interface *iface;
+ 	local_info_t *local;
+-	struct ieee80211_hdr *hdr;
++	struct ieee80211_hdr_4addr *hdr;
+ 	size_t hdrlen;
+ 	u16 fc, type, stype, sc;
+ 	struct net_device *wds = NULL;
+@@ -716,7 +716,7 @@ void hostap_80211_rx(struct net_device *
+ 	dev = local->ddev;
+ 	iface = netdev_priv(dev);
+ 
+-	hdr = (struct ieee80211_hdr *) skb->data;
++	hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ 	stats = hostap_get_stats(dev);
+ 
+ 	if (skb->len < 10)
+@@ -889,7 +889,7 @@ void hostap_80211_rx(struct net_device *
+ 	if (local->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
+ 	    (keyidx = hostap_rx_frame_decrypt(local, skb, crypt)) < 0)
+ 		goto rx_dropped;
+-	hdr = (struct ieee80211_hdr *) skb->data;
++	hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ 
+ 	/* skb: hdr + (possibly fragmented) plaintext payload */
+ 
+@@ -941,7 +941,7 @@ void hostap_80211_rx(struct net_device *
+ 		/* this was the last fragment and the frame will be
+ 		 * delivered, so remove skb from fragment cache */
+ 		skb = frag_skb;
+-		hdr = (struct ieee80211_hdr *) skb->data;
++		hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ 		prism2_frag_cache_invalidate(local, hdr);
+ 	}
+ 
+@@ -952,7 +952,7 @@ void hostap_80211_rx(struct net_device *
+ 	    hostap_rx_frame_decrypt_msdu(local, skb, keyidx, crypt))
+ 		goto rx_dropped;
+ 
+-	hdr = (struct ieee80211_hdr *) skb->data;
++	hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ 	if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !local->open_wep) {
+ 		if (local->ieee_802_1x &&
+ 		    hostap_is_eapol_frame(local, skb)) {
+diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c
+index 6358015..6db4543 100644
+--- a/drivers/net/wireless/hostap/hostap_80211_tx.c
++++ b/drivers/net/wireless/hostap/hostap_80211_tx.c
+@@ -1,9 +1,9 @@
+ void hostap_dump_tx_80211(const char *name, struct sk_buff *skb)
+ {
+-	struct ieee80211_hdr *hdr;
++	struct ieee80211_hdr_4addr *hdr;
+ 	u16 fc;
+ 
+-	hdr = (struct ieee80211_hdr *) skb->data;
++	hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ 
+ 	printk(KERN_DEBUG "%s: TX len=%d jiffies=%ld\n",
+ 	       name, skb->len, jiffies);
+@@ -41,7 +41,7 @@ int hostap_data_start_xmit(struct sk_buf
+ 	struct hostap_interface *iface;
+ 	local_info_t *local;
+ 	int need_headroom, need_tailroom = 0;
+-	struct ieee80211_hdr hdr;
++	struct ieee80211_hdr_4addr hdr;
+ 	u16 fc, ethertype = 0;
+ 	enum {
+ 		WDS_NO = 0, WDS_OWN_FRAME, WDS_COMPLIANT_FRAME
+@@ -244,7 +244,7 @@ int hostap_mgmt_start_xmit(struct sk_buf
+ 	struct hostap_interface *iface;
+ 	local_info_t *local;
+ 	struct hostap_skb_tx_data *meta;
+-	struct ieee80211_hdr *hdr;
++	struct ieee80211_hdr_4addr *hdr;
+ 	u16 fc;
+ 
+ 	iface = netdev_priv(dev);
+@@ -266,7 +266,7 @@ int hostap_mgmt_start_xmit(struct sk_buf
+ 	meta->iface = iface;
+ 
+ 	if (skb->len >= IEEE80211_DATA_HDR3_LEN + sizeof(rfc1042_header) + 2) {
+-		hdr = (struct ieee80211_hdr *) skb->data;
++		hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ 		fc = le16_to_cpu(hdr->frame_ctl);
+ 		if (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA &&
+ 		    WLAN_FC_GET_STYPE(fc) == IEEE80211_STYPE_DATA) {
+@@ -289,7 +289,7 @@ struct sk_buff * hostap_tx_encrypt(struc
+ {
+ 	struct hostap_interface *iface;
+ 	local_info_t *local;
+-	struct ieee80211_hdr *hdr;
++	struct ieee80211_hdr_4addr *hdr;
+ 	u16 fc;
+ 	int hdr_len, res;
+ 
+@@ -303,7 +303,7 @@ struct sk_buff * hostap_tx_encrypt(struc
+ 
+ 	if (local->tkip_countermeasures &&
+ 	    crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
+-		hdr = (struct ieee80211_hdr *) skb->data;
++		hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ 		if (net_ratelimit()) {
+ 			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
+ 			       "TX packet to " MACSTR "\n",
+@@ -325,7 +325,7 @@ struct sk_buff * hostap_tx_encrypt(struc
+ 		return NULL;
+ 	}
+ 
+-	hdr = (struct ieee80211_hdr *) skb->data;
++	hdr = (struct ieee80211_hdr_4addr *) skb->data;
+  	fc = le16_to_cpu(hdr->frame_ctl);
+ 	hdr_len = hostap_80211_get_hdrlen(fc);
+ 
+@@ -360,7 +360,7 @@ int hostap_master_start_xmit(struct sk_b
+ 	ap_tx_ret tx_ret;
+ 	struct hostap_skb_tx_data *meta;
+ 	int no_encrypt = 0;
+-	struct ieee80211_hdr *hdr;
++	struct ieee80211_hdr_4addr *hdr;
+ 
+ 	iface = netdev_priv(dev);
+ 	local = iface->local;
+@@ -403,7 +403,7 @@ int hostap_master_start_xmit(struct sk_b
+ 	tx_ret = hostap_handle_sta_tx(local, &tx);
+ 	skb = tx.skb;
+ 	meta = (struct hostap_skb_tx_data *) skb->cb;
+-	hdr = (struct ieee80211_hdr *) skb->data;
++	hdr = (struct ieee80211_hdr_4addr *) skb->data;
+  	fc = le16_to_cpu(hdr->frame_ctl);
+ 	switch (tx_ret) {
+ 	case AP_TX_CONTINUE:
+diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
+index 930cef8..070f703 100644
+--- a/drivers/net/wireless/hostap/hostap_ap.c
++++ b/drivers/net/wireless/hostap/hostap_ap.c
+@@ -591,14 +591,14 @@ static void hostap_ap_tx_cb(struct sk_bu
+ {
+ 	struct ap_data *ap = data;
+ 	u16 fc;
+-	struct ieee80211_hdr *hdr;
++	struct ieee80211_hdr_4addr *hdr;
+ 
+ 	if (!ap->local->hostapd || !ap->local->apdev) {
+ 		dev_kfree_skb(skb);
+ 		return;
+ 	}
+ 
+-	hdr = (struct ieee80211_hdr *) skb->data;
++	hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ 	fc = le16_to_cpu(hdr->frame_ctl);
+ 
+ 	/* Pass the TX callback frame to the hostapd; use 802.11 header version
+@@ -623,7 +623,7 @@ static void hostap_ap_tx_cb_auth(struct 
+ {
+ 	struct ap_data *ap = data;
+ 	struct net_device *dev = ap->local->dev;
+-	struct ieee80211_hdr *hdr;
++	struct ieee80211_hdr_4addr *hdr;
+ 	u16 fc, *pos, auth_alg, auth_transaction, status;
+ 	struct sta_info *sta = NULL;
+ 	char *txt = NULL;
+@@ -633,7 +633,7 @@ static void hostap_ap_tx_cb_auth(struct 
+ 		return;
+ 	}
+ 
+-	hdr = (struct ieee80211_hdr *) skb->data;
++	hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ 	fc = le16_to_cpu(hdr->frame_ctl);
+ 	if (WLAN_FC_GET_TYPE(fc) != IEEE80211_FTYPE_MGMT ||
+ 	    WLAN_FC_GET_STYPE(fc) != IEEE80211_STYPE_AUTH ||
+@@ -692,7 +692,7 @@ static void hostap_ap_tx_cb_assoc(struct
+ {
+ 	struct ap_data *ap = data;
+ 	struct net_device *dev = ap->local->dev;
+-	struct ieee80211_hdr *hdr;
++	struct ieee80211_hdr_4addr *hdr;
+ 	u16 fc, *pos, status;
+ 	struct sta_info *sta = NULL;
+ 	char *txt = NULL;
+@@ -702,7 +702,7 @@ static void hostap_ap_tx_cb_assoc(struct
+ 		return;
+ 	}
+ 
+-	hdr = (struct ieee80211_hdr *) skb->data;
++	hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ 	fc = le16_to_cpu(hdr->frame_ctl);
+ 	if (WLAN_FC_GET_TYPE(fc) != IEEE80211_FTYPE_MGMT ||
+ 	    (WLAN_FC_GET_STYPE(fc) != IEEE80211_STYPE_ASSOC_RESP &&
+@@ -757,12 +757,12 @@ static void hostap_ap_tx_cb_assoc(struct
+ static void hostap_ap_tx_cb_poll(struct sk_buff *skb, int ok, void *data)
+ {
+ 	struct ap_data *ap = data;
+-	struct ieee80211_hdr *hdr;
++	struct ieee80211_hdr_4addr *hdr;
+ 	struct sta_info *sta;
+ 
+ 	if (skb->len < 24)
+ 		goto fail;
+-	hdr = (struct ieee80211_hdr *) skb->data;
++	hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ 	if (ok) {
+ 		spin_lock(&ap->sta_table_lock);
+ 		sta = ap_get_sta(ap, hdr->addr1);
+@@ -918,7 +918,7 @@ static void prism2_send_mgmt(struct net_
+ {
+ 	struct hostap_interface *iface;
+ 	local_info_t *local;
+-	struct ieee80211_hdr *hdr;
++	struct ieee80211_hdr_4addr *hdr;
+ 	u16 fc;
+ 	struct sk_buff *skb;
+ 	struct hostap_skb_tx_data *meta;
+@@ -944,7 +944,7 @@ static void prism2_send_mgmt(struct net_
+ 
+ 	fc = type_subtype;
+ 	hdrlen = hostap_80211_get_hdrlen(fc);
+-	hdr = (struct ieee80211_hdr *) skb_put(skb, hdrlen);
++	hdr = (struct ieee80211_hdr_4addr *) skb_put(skb, hdrlen);
+ 	if (body)
+ 		memcpy(skb_put(skb, body_len), body, body_len);
+ 
+@@ -1285,7 +1285,7 @@ static void handle_authen(local_info_t *
+ 			  struct hostap_80211_rx_status *rx_stats)
+ {
+ 	struct net_device *dev = local->dev;
+-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
++	struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ 	size_t hdrlen;
+ 	struct ap_data *ap = local->ap;
+ 	char body[8 + WLAN_AUTH_CHALLENGE_LEN], *challenge = NULL;
+@@ -1498,7 +1498,7 @@ static void handle_assoc(local_info_t *l
+ 			 struct hostap_80211_rx_status *rx_stats, int reassoc)
+ {
+ 	struct net_device *dev = local->dev;
+-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
++	struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ 	char body[12], *p, *lpos;
+ 	int len, left;
+ 	u16 *pos;
+@@ -1705,7 +1705,7 @@ static void handle_deauth(local_info_t *
+ 			  struct hostap_80211_rx_status *rx_stats)
+ {
+ 	struct net_device *dev = local->dev;
+-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
++	struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ 	char *body = (char *) (skb->data + IEEE80211_MGMT_HDR_LEN);
+ 	int len;
+ 	u16 reason_code, *pos;
+@@ -1746,7 +1746,7 @@ static void handle_disassoc(local_info_t
+ 			    struct hostap_80211_rx_status *rx_stats)
+ {
+ 	struct net_device *dev = local->dev;
+-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
++	struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ 	char *body = skb->data + IEEE80211_MGMT_HDR_LEN;
+ 	int len;
+ 	u16 reason_code, *pos;
+@@ -1784,7 +1784,7 @@ static void handle_disassoc(local_info_t
+ 
+ /* Called only as a scheduled task for pending AP frames. */
+ static void ap_handle_data_nullfunc(local_info_t *local,
+-				    struct ieee80211_hdr *hdr)
++				    struct ieee80211_hdr_4addr *hdr)
+ {
+ 	struct net_device *dev = local->dev;
+ 
+@@ -1801,7 +1801,7 @@ static void ap_handle_data_nullfunc(loca
+ 
+ /* Called only as a scheduled task for pending AP frames. */
+ static void ap_handle_dropped_data(local_info_t *local,
+-				   struct ieee80211_hdr *hdr)
++				   struct ieee80211_hdr_4addr *hdr)
+ {
+ 	struct net_device *dev = local->dev;
+ 	struct sta_info *sta;
+@@ -1860,7 +1860,7 @@ static void pspoll_send_buffered(local_i
+ 
+ /* Called only as a scheduled task for pending AP frames. */
+ static void handle_pspoll(local_info_t *local,
+-			  struct ieee80211_hdr *hdr,
++			  struct ieee80211_hdr_4addr *hdr,
+ 			  struct hostap_80211_rx_status *rx_stats)
+ {
+ 	struct net_device *dev = local->dev;
+@@ -1979,7 +1979,7 @@ static void handle_wds_oper_queue(void *
+ static void handle_beacon(local_info_t *local, struct sk_buff *skb,
+ 			  struct hostap_80211_rx_status *rx_stats)
+ {
+-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
++	struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ 	char *body = skb->data + IEEE80211_MGMT_HDR_LEN;
+ 	int len, left;
+ 	u16 *pos, beacon_int, capability;
+@@ -2137,11 +2137,11 @@ static void handle_ap_item(local_info_t 
+ 	struct net_device *dev = local->dev;
+ #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+ 	u16 fc, type, stype;
+-	struct ieee80211_hdr *hdr;
++	struct ieee80211_hdr_4addr *hdr;
+ 
+ 	/* FIX: should give skb->len to handler functions and check that the
+ 	 * buffer is long enough */
+-	hdr = (struct ieee80211_hdr *) skb->data;
++	hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ 	fc = le16_to_cpu(hdr->frame_ctl);
+ 	type = WLAN_FC_GET_TYPE(fc);
+ 	stype = WLAN_FC_GET_STYPE(fc);
+@@ -2258,7 +2258,7 @@ void hostap_rx(struct net_device *dev, s
+ 	struct hostap_interface *iface;
+ 	local_info_t *local;
+ 	u16 fc;
+-	struct ieee80211_hdr *hdr;
++	struct ieee80211_hdr_4addr *hdr;
+ 
+ 	iface = netdev_priv(dev);
+ 	local = iface->local;
+@@ -2268,7 +2268,7 @@ void hostap_rx(struct net_device *dev, s
+ 
+ 	local->stats.rx_packets++;
+ 
+-	hdr = (struct ieee80211_hdr *) skb->data;
++	hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ 	fc = le16_to_cpu(hdr->frame_ctl);
+ 
+ 	if (local->ap->ap_policy == AP_OTHER_AP_SKIP_ALL &&
+@@ -2289,7 +2289,7 @@ void hostap_rx(struct net_device *dev, s
+ static void schedule_packet_send(local_info_t *local, struct sta_info *sta)
+ {
+ 	struct sk_buff *skb;
+-	struct ieee80211_hdr *hdr;
++	struct ieee80211_hdr_4addr *hdr;
+ 	struct hostap_80211_rx_status rx_stats;
+ 
+ 	if (skb_queue_empty(&sta->tx_buf))
+@@ -2302,7 +2302,7 @@ static void schedule_packet_send(local_i
+ 		return;
+ 	}
+ 
+-	hdr = (struct ieee80211_hdr *) skb_put(skb, 16);
++	hdr = (struct ieee80211_hdr_4addr *) skb_put(skb, 16);
+ 
+ 	/* Generate a fake pspoll frame to start packet delivery */
+ 	hdr->frame_ctl = __constant_cpu_to_le16(
+@@ -2685,7 +2685,7 @@ ap_tx_ret hostap_handle_sta_tx(local_inf
+ 	struct sta_info *sta = NULL;
+ 	struct sk_buff *skb = tx->skb;
+ 	int set_tim, ret;
+-	struct ieee80211_hdr *hdr;
++	struct ieee80211_hdr_4addr *hdr;
+ 	struct hostap_skb_tx_data *meta;
+ 
+ 	meta = (struct hostap_skb_tx_data *) skb->cb;
+@@ -2694,7 +2694,7 @@ ap_tx_ret hostap_handle_sta_tx(local_inf
+ 	    meta->iface->type == HOSTAP_INTERFACE_STA)
+ 		goto out;
+ 
+-	hdr = (struct ieee80211_hdr *) skb->data;
++	hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ 
+ 	if (hdr->addr1[0] & 0x01) {
+ 		/* broadcast/multicast frame - no AP related processing */
+@@ -2821,10 +2821,10 @@ void hostap_handle_sta_release(void *ptr
+ void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb)
+ {
+ 	struct sta_info *sta;
+-	struct ieee80211_hdr *hdr;
++	struct ieee80211_hdr_4addr *hdr;
+ 	struct hostap_skb_tx_data *meta;
+ 
+-	hdr = (struct ieee80211_hdr *) skb->data;
++	hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ 	meta = (struct hostap_skb_tx_data *) skb->cb;
+ 
+ 	spin_lock(&local->ap->sta_table_lock);
+@@ -2892,7 +2892,7 @@ static void hostap_update_sta_ps2(local_
+ 
+ /* Called only as a tasklet (software IRQ). Called for each RX frame to update
+  * STA power saving state. pwrmgt is a flag from 802.11 frame_ctl field. */
+-int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr *hdr)
++int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr_4addr *hdr)
+ {
+ 	struct sta_info *sta;
+ 	u16 fc;
+@@ -2925,12 +2925,12 @@ ap_rx_ret hostap_handle_sta_rx(local_inf
+ 	int ret;
+ 	struct sta_info *sta;
+ 	u16 fc, type, stype;
+-	struct ieee80211_hdr *hdr;
++	struct ieee80211_hdr_4addr *hdr;
+ 
+ 	if (local->ap == NULL)
+ 		return AP_RX_CONTINUE;
+ 
+-	hdr = (struct ieee80211_hdr *) skb->data;
++	hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ 
+ 	fc = le16_to_cpu(hdr->frame_ctl);
+ 	type = WLAN_FC_GET_TYPE(fc);
+@@ -3058,7 +3058,7 @@ ap_rx_ret hostap_handle_sta_rx(local_inf
+ 
+ /* Called only as a tasklet (software IRQ) */
+ int hostap_handle_sta_crypto(local_info_t *local,
+-			     struct ieee80211_hdr *hdr,
++			     struct ieee80211_hdr_4addr *hdr,
+ 			     struct ieee80211_crypt_data **crypt,
+ 			     void **sta_ptr)
+ {
+@@ -3160,7 +3160,7 @@ int hostap_add_sta(struct ap_data *ap, u
+ 
+ /* Called only as a tasklet (software IRQ) */
+ int hostap_update_rx_stats(struct ap_data *ap,
+-			   struct ieee80211_hdr *hdr,
++			   struct ieee80211_hdr_4addr *hdr,
+ 			   struct hostap_80211_rx_status *rx_stats)
+ {
+ 	struct sta_info *sta;
+diff --git a/drivers/net/wireless/hostap/hostap_ap.h b/drivers/net/wireless/hostap/hostap_ap.h
+index 816a52b..6d00df6 100644
+--- a/drivers/net/wireless/hostap/hostap_ap.h
++++ b/drivers/net/wireless/hostap/hostap_ap.h
+@@ -233,7 +233,7 @@ struct hostap_tx_data {
+ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx);
+ void hostap_handle_sta_release(void *ptr);
+ void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb);
+-int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr *hdr);
++int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr_4addr *hdr);
+ typedef enum {
+ 	AP_RX_CONTINUE, AP_RX_DROP, AP_RX_EXIT, AP_RX_CONTINUE_NOT_AUTHORIZED
+ } ap_rx_ret;
+@@ -241,13 +241,13 @@ ap_rx_ret hostap_handle_sta_rx(local_inf
+ 			       struct sk_buff *skb,
+ 			       struct hostap_80211_rx_status *rx_stats,
+ 			       int wds);
+-int hostap_handle_sta_crypto(local_info_t *local, struct ieee80211_hdr *hdr,
++int hostap_handle_sta_crypto(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
+ 			     struct ieee80211_crypt_data **crypt,
+ 			     void **sta_ptr);
+ int hostap_is_sta_assoc(struct ap_data *ap, u8 *sta_addr);
+ int hostap_is_sta_authorized(struct ap_data *ap, u8 *sta_addr);
+ int hostap_add_sta(struct ap_data *ap, u8 *sta_addr);
+-int hostap_update_rx_stats(struct ap_data *ap, struct ieee80211_hdr *hdr,
++int hostap_update_rx_stats(struct ap_data *ap, struct ieee80211_hdr_4addr *hdr,
+ 			   struct hostap_80211_rx_status *rx_stats);
+ void hostap_update_rates(local_info_t *local);
+ void hostap_add_wds_links(local_info_t *local);
+---
+0.99.8.GIT


Index: 0187-ieee80211-Updated-hostap-to-be-compatible-with-extra_prefix_len-changes.txt
===================================================================
RCS file: 0187-ieee80211-Updated-hostap-to-be-compatible-with-extra_prefix_len-changes.txt
diff -N 0187-ieee80211-Updated-hostap-to-be-compatible-with-extra_prefix_len-changes.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0187-ieee80211-Updated-hostap-to-be-compatible-with-extra_prefix_len-changes.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,84 @@
+Subject: [PATCH] ieee80211: Updated hostap to be compatible with extra_prefix_len changes
+From: James Ketrenos <jketreno linux intel com>
+Date: 1127323431 -0500
+
+tree 8c1676c8a15c08e6d4c718fc7cd42d9bf4cd8235
+parent 0ccc3dd6469ed492578c184f47dde2baccde3593
+author James Ketrenos <jketreno linux intel com> 1126715240 -0500
+committer James Ketrenos <jketreno linux intel com> 1127316717 -0500
+
+Updated hostap to be compatible with extra_prefix_len changes.
+
+Accomplished via:
+
+for i in hostap_ap.c hostap_80211_tx.c; do
+        sed -i -e "s:\([.>]\)extra_prefix_len:\1extra_mpdu_prefix_len:g" \
+                -e "s:\([.>]\)extra_postfix_len:\1extra_mpdu_postfix_len:g" \
+                drivers/net/wireless/hostap/$i
+done
+
+CC: Jouni Malinen <jkmaline cc hut fi>
+
+Signed-off-by: James Ketrenos <jketreno linux intel com>
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/hostap/hostap_80211_tx.c |    8 ++++----
+ drivers/net/wireless/hostap/hostap_ap.c       |    8 ++++----
+ 2 files changed, 8 insertions(+), 8 deletions(-)
+
+applies-to: fe63cb09606c2c23485092bac7298c85677fea92
+5bfc819b53ed67c76f33f969ab627070e85d87c1
+diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c
+index 6db4543..9d24f8a 100644
+--- a/drivers/net/wireless/hostap/hostap_80211_tx.c
++++ b/drivers/net/wireless/hostap/hostap_80211_tx.c
+@@ -317,10 +317,10 @@ struct sk_buff * hostap_tx_encrypt(struc
+ 	if (skb == NULL)
+ 		return NULL;
+ 
+-	if ((skb_headroom(skb) < crypt->ops->extra_prefix_len ||
+-	     skb_tailroom(skb) < crypt->ops->extra_postfix_len) &&
+-	    pskb_expand_head(skb, crypt->ops->extra_prefix_len,
+-			     crypt->ops->extra_postfix_len, GFP_ATOMIC)) {
++	if ((skb_headroom(skb) < crypt->ops->extra_mpdu_prefix_len ||
++	     skb_tailroom(skb) < crypt->ops->extra_mpdu_postfix_len) &&
++	    pskb_expand_head(skb, crypt->ops->extra_mpdu_prefix_len,
++			     crypt->ops->extra_mpdu_postfix_len, GFP_ATOMIC)) {
+ 		kfree_skb(skb);
+ 		return NULL;
+ 	}
+diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
+index 070f703..087d926 100644
+--- a/drivers/net/wireless/hostap/hostap_ap.c
++++ b/drivers/net/wireless/hostap/hostap_ap.c
+@@ -1256,14 +1256,14 @@ static char * ap_auth_make_challenge(str
+ 	}
+ 
+ 	skb = dev_alloc_skb(WLAN_AUTH_CHALLENGE_LEN +
+-			    ap->crypt->extra_prefix_len +
+-			    ap->crypt->extra_postfix_len);
++			    ap->crypt->extra_mpdu_prefix_len +
++			    ap->crypt->extra_mpdu_postfix_len);
+ 	if (skb == NULL) {
+ 		kfree(tmpbuf);
+ 		return NULL;
+ 	}
+ 
+-	skb_reserve(skb, ap->crypt->extra_prefix_len);
++	skb_reserve(skb, ap->crypt->extra_mpdu_prefix_len);
+ 	memset(skb_put(skb, WLAN_AUTH_CHALLENGE_LEN), 0,
+ 	       WLAN_AUTH_CHALLENGE_LEN);
+ 	if (ap->crypt->encrypt_mpdu(skb, 0, ap->crypt_priv)) {
+@@ -1272,7 +1272,7 @@ static char * ap_auth_make_challenge(str
+ 		return NULL;
+ 	}
+ 
+-	memcpy(tmpbuf, skb->data + ap->crypt->extra_prefix_len,
++	memcpy(tmpbuf, skb->data + ap->crypt->extra_mpdu_prefix_len,
+ 	       WLAN_AUTH_CHALLENGE_LEN);
+ 	dev_kfree_skb(skb);
+ 
+---
+0.99.8.GIT


--- NEW FILE 0188-ieee82011-Remove-WIRELESS_EXT-ifdefs.txt ---
Subject: [PATCH] ieee82011: Remove WIRELESS_EXT ifdefs
From: James Ketrenos <jketreno linux intel com>
Date: 1127331212 -0500

Remove old WIRELESS_EXT version compatibility

In-tree doesn't need to maintain backward compatibility.

Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/net/ieee80211.h              |    2 --
 net/ieee80211/ieee80211_crypt_tkip.c |   23 -----------------------
 net/ieee80211/ieee80211_wx.c         |    2 --
 3 files changed, 0 insertions(+), 27 deletions(-)

applies-to: a50aa1fd2c5cd51d934883b4f7cf559157c8f592
9a01c16bd49071b2e7904d222cae71d5f8bf6bb5
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 5380948..61a23d3 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -1069,14 +1069,12 @@ extern int ieee80211_wx_set_encode(struc
 extern int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
 				   struct iw_request_info *info,
 				   union iwreq_data *wrqu, char *key);
-#if WIRELESS_EXT > 17
 extern int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
 				      struct iw_request_info *info,
 				      union iwreq_data *wrqu, char *extra);
 extern int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee,
 				      struct iw_request_info *info,
 				      union iwreq_data *wrqu, char *extra);
-#endif
 
 static inline void ieee80211_increment_scans(struct ieee80211_device *ieee)
 {
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c
index f973d6c..21022f1 100644
--- a/net/ieee80211/ieee80211_crypt_tkip.c
+++ b/net/ieee80211/ieee80211_crypt_tkip.c
@@ -515,7 +515,6 @@ static int ieee80211_michael_mic_add(str
 	return 0;
 }
 
-#if WIRELESS_EXT >= 18
 static void ieee80211_michael_mic_failure(struct net_device *dev,
 					  struct ieee80211_hdr_4addr *hdr,
 					  int keyidx)
@@ -536,28 +535,6 @@ static void ieee80211_michael_mic_failur
 	wrqu.data.length = sizeof(ev);
 	wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev);
 }
-#elif WIRELESS_EXT >= 15
-static void ieee80211_michael_mic_failure(struct net_device *dev,
-					  struct ieee80211_hdr_4addr *hdr,
-					  int keyidx)
-{
-	union iwreq_data wrqu;
-	char buf[128];
-
-	/* TODO: needed parameters: count, keyid, key type, TSC */
-	sprintf(buf, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr="
-		MAC_FMT ")", keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni",
-		MAC_ARG(hdr->addr2));
-	memset(&wrqu, 0, sizeof(wrqu));
-	wrqu.data.length = strlen(buf);
-	wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
-}
-#else				/* WIRELESS_EXT >= 15 */
-static inline void ieee80211_michael_mic_failure(struct net_device *dev, struct ieee80211_hdr_4addr
-						 *hdr, int keyidx)
-{
-}
-#endif				/* WIRELESS_EXT >= 15 */
 
 static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
 					int hdr_len, void *priv)
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index e28648e..3dd2bba 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -488,7 +488,6 @@ int ieee80211_wx_get_encode(struct ieee8
 	return 0;
 }
 
-#if WIRELESS_EXT > 17
 int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
 			       struct iw_request_info *info,
 			       union iwreq_data *wrqu, char *extra)
@@ -722,7 +721,6 @@ int ieee80211_wx_get_encodeext(struct ie
 
 EXPORT_SYMBOL(ieee80211_wx_set_encodeext);
 EXPORT_SYMBOL(ieee80211_wx_get_encodeext);
-#endif
 
 EXPORT_SYMBOL(ieee80211_wx_get_scan);
 EXPORT_SYMBOL(ieee80211_wx_set_encode);
---
0.99.8.GIT


--- NEW FILE 0194-ieee80211-Added-subsystem-version-string-and-reporting-via-MODULE_VERSION.txt ---
Subject: [PATCH] ieee80211: Added subsystem version string and reporting via MODULE_VERSION
From: James Ketrenos <jketreno linux intel com>
Date: 1127321926 -0500

tree c1b50ac5d2d1f9b727c39c6bd86a7872f25a1127
parent 1bb997a3ac7dd1941e02426d2f70bd28993a82b7
author James Ketrenos <jketreno linux intel com> 1126720779 -0500
committer James Ketrenos <jketreno linux intel com> 1127314674 -0500

Added subsystem version string and reporting via MODULE_VERSION and
pritnk during load.

NOTE:  This is the version support split out from patch 24/29 of the
prior series.

Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/net/ieee80211.h          |    7 +++++++
 net/ieee80211/ieee80211_module.c |   24 ++++++++++++++++++------
 2 files changed, 25 insertions(+), 6 deletions(-)

applies-to: 560df923cbd6dcee66352e1d55c8b170ebd57b36
31696160c7415b5a7efa650c7f1ca5c9623f5d8f
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 61a23d3..4a1340b 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -17,6 +17,11 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation. See README and COPYING for
  * more details.
+ *
+ * API Version History
+ * 1.0.x -- Initial version
+ * 1.1.x -- Added radiotap, QoS, TIM, ieee80211_geo APIs,
+ *          various structure changes, and crypto API init method
  */
 #ifndef IEEE80211_H
 #define IEEE80211_H
@@ -24,6 +29,8 @@
 #include <linux/kernel.h>	/* ARRAY_SIZE */
 #include <linux/wireless.h>
 
+#define IEEE80211_VERSION "git-1.1.5"
+
 #define IEEE80211_DATA_LEN		2304
 /* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
    6.2.1.1.2.
diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c
index 0ae91c9..3193125 100644
--- a/net/ieee80211/ieee80211_module.c
+++ b/net/ieee80211/ieee80211_module.c
@@ -53,13 +53,16 @@
 
 #include <net/ieee80211.h>
 
-MODULE_DESCRIPTION("802.11 data/management/control stack");
-MODULE_AUTHOR
-    ("Copyright (C) 2004 Intel Corporation <jketreno linux intel com>");
+#define DRV_DESCRIPTION "802.11 data/management/control stack"
+#define DRV_NAME        "ieee80211"
+#define DRV_VERSION	IEEE80211_VERSION
+#define DRV_COPYRIGHT   "Copyright (C) 2004-2005 Intel Corporation <jketreno linux intel com>"
+
+MODULE_VERSION(DRV_VERSION);
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_AUTHOR(DRV_COPYRIGHT);
 MODULE_LICENSE("GPL");
 
-#define DRV_NAME "ieee80211"
-
 static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee)
 {
 	if (ieee->networks)
@@ -220,9 +223,11 @@ static int store_debug_level(struct file
 
 	return strnlen(buf, len);
 }
+#endif				/* CONFIG_IEEE80211_DEBUG */
 
 static int __init ieee80211_init(void)
 {
+#ifdef CONFIG_IEEE80211_DEBUG
 	struct proc_dir_entry *e;
 
 	ieee80211_debug_level = debug;
@@ -242,26 +247,33 @@ static int __init ieee80211_init(void)
 	e->read_proc = show_debug_level;
 	e->write_proc = store_debug_level;
 	e->data = NULL;
+#endif				/* CONFIG_IEEE80211_DEBUG */
+
+	printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
+	printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
 
 	return 0;
 }
 
 static void __exit ieee80211_exit(void)
 {
+#ifdef CONFIG_IEEE80211_DEBUG
 	if (ieee80211_proc) {
 		remove_proc_entry("debug_level", ieee80211_proc);
 		remove_proc_entry(DRV_NAME, proc_net);
 		ieee80211_proc = NULL;
 	}
+#endif				/* CONFIG_IEEE80211_DEBUG */
 }
 
+#ifdef CONFIG_IEEE80211_DEBUG
 #include <linux/moduleparam.h>
 module_param(debug, int, 0444);
 MODULE_PARM_DESC(debug, "debug output mask");
+#endif				/* CONFIG_IEEE80211_DEBUG */
 
 module_exit(ieee80211_exit);
 module_init(ieee80211_init);
-#endif
 
 const char *escape_essid(const char *essid, u8 essid_len)
 {
---
0.99.8.GIT


--- NEW FILE 0195-ieee80211-Added-handle_deauth-callback-enhanced-tkip-ccmp-support-of-varying-hw-sw-offload.txt ---
Subject: [PATCH] ieee80211: Added handle_deauth() callback, enhanced tkip/ccmp support of varying hw/sw offload
From: James Ketrenos <jketreno linux intel com>
Date: 1127321929 -0500

tree de81b55e78e85997642c651ea677078d0554a14f
parent c8030da8c159f8b82712172a6748a42523aea83a
author James Ketrenos <jketreno linux intel com> 1127104380 -0500
committer James Ketrenos <jketreno linux intel com> 1127315225 -0500

Added handle_deauth() callback.
Enhanced crypt_{tkip,ccmp} to support varying splits of HW/SW offload.
Changed channel freq to u32 from u16.
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/net/ieee80211.h              |    5 ++-
 include/net/ieee80211_crypt.h        |    2 +
 net/ieee80211/ieee80211_crypt_ccmp.c |   41 ++++++++++++++++-------
 net/ieee80211/ieee80211_crypt_tkip.c |   60 ++++++++++++++++++++++++----------
 net/ieee80211/ieee80211_rx.c         |    6 +++
 net/ieee80211/ieee80211_tx.c         |   18 +++++++++-
 6 files changed, 99 insertions(+), 33 deletions(-)

applies-to: 1f82e3a1e477374c78240ec2e95cece4859d9e81
31b59eaee8f8ec29d8cb6ac0c8eed086689d8030
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 4a1340b..220a9e3 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -808,7 +808,7 @@ enum {
 };
 
 struct ieee80211_channel {
-	u16 freq;
+	u32 freq;
 	u8 channel;
 	u8 flags;
 	u8 max_power;
@@ -862,6 +862,7 @@ struct ieee80211_device {
 	int host_mc_decrypt;
 
 	int host_open_frag;
+	int host_build_iv;
 	int ieee802_1x;		/* is IEEE 802.1X used */
 
 	/* WPA data */
@@ -914,6 +915,8 @@ struct ieee80211_device {
 	/* Typical STA methods */
 	int (*handle_auth) (struct net_device * dev,
 			    struct ieee80211_auth * auth);
+	int (*handle_deauth) (struct net_device * dev,
+			      struct ieee80211_auth * auth);
 	int (*handle_disassoc) (struct net_device * dev,
 				struct ieee80211_disassoc * assoc);
 	int (*handle_beacon) (struct net_device * dev,
diff --git a/include/net/ieee80211_crypt.h b/include/net/ieee80211_crypt.h
index 24e4912..daf3b2c 100644
--- a/include/net/ieee80211_crypt.h
+++ b/include/net/ieee80211_crypt.h
@@ -36,6 +36,8 @@ struct ieee80211_crypto_ops {
 	/* deinitialize crypto context and free allocated private data */
 	void (*deinit) (void *priv);
 
+	int (*build_iv) (struct sk_buff * skb, int hdr_len, void *priv);
+
 	/* encrypt/decrypt return < 0 on error or >= 0 on success. The return
 	 * value from decrypt_mpdu is passed as the keyidx value for
 	 * decrypt_msdu. skb must have enough head and tail room for the
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c
index a3dc571..081d857 100644
--- a/net/ieee80211/ieee80211_crypt_ccmp.c
+++ b/net/ieee80211/ieee80211_crypt_ccmp.c
@@ -191,26 +191,18 @@ static void ccmp_init_blocks(struct cryp
 	ieee80211_ccmp_aes_encrypt(tfm, b0, s0);
 }
 
-static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len, void *priv)
 {
 	struct ieee80211_ccmp_data *key = priv;
-	int data_len, i, blocks, last, len;
-	u8 *pos, *mic;
-	struct ieee80211_hdr_4addr *hdr;
-	u8 *b0 = key->tx_b0;
-	u8 *b = key->tx_b;
-	u8 *e = key->tx_e;
-	u8 *s0 = key->tx_s0;
+	int i;
+	u8 *pos;
 
-	if (skb_headroom(skb) < CCMP_HDR_LEN ||
-	    skb_tailroom(skb) < CCMP_MIC_LEN || skb->len < hdr_len)
+	if (skb_headroom(skb) < CCMP_HDR_LEN || skb->len < hdr_len)
 		return -1;
 
-	data_len = skb->len - hdr_len;
 	pos = skb_push(skb, CCMP_HDR_LEN);
 	memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
 	pos += hdr_len;
-	mic = skb_put(skb, CCMP_MIC_LEN);
 
 	i = CCMP_PN_LEN - 1;
 	while (i >= 0) {
@@ -229,6 +221,30 @@ static int ieee80211_ccmp_encrypt(struct
 	*pos++ = key->tx_pn[1];
 	*pos++ = key->tx_pn[0];
 
+	return CCMP_HDR_LEN;
+}
+
+static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+{
+	struct ieee80211_ccmp_data *key = priv;
+	int data_len, i, blocks, last, len;
+	u8 *pos, *mic;
+	struct ieee80211_hdr_4addr *hdr;
+	u8 *b0 = key->tx_b0;
+	u8 *b = key->tx_b;
+	u8 *e = key->tx_e;
+	u8 *s0 = key->tx_s0;
+
+	if (skb_tailroom(skb) < CCMP_MIC_LEN || skb->len < hdr_len)
+		return -1;
+
+	data_len = skb->len - hdr_len;
+	len = ieee80211_ccmp_hdr(skb, hdr_len, priv);
+	if (len < 0)
+		return -1;
+
+	pos = skb->data + hdr_len + CCMP_HDR_LEN;
+	mic = skb_put(skb, CCMP_MIC_LEN);
 	hdr = (struct ieee80211_hdr_4addr *)skb->data;
 	ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
 
@@ -429,6 +445,7 @@ static struct ieee80211_crypto_ops ieee8
 	.name = "CCMP",
 	.init = ieee80211_ccmp_init,
 	.deinit = ieee80211_ccmp_deinit,
+	.build_iv = ieee80211_ccmp_hdr,
 	.encrypt_mpdu = ieee80211_ccmp_encrypt,
 	.decrypt_mpdu = ieee80211_ccmp_decrypt,
 	.encrypt_msdu = NULL,
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c
index 21022f1..e073305 100644
--- a/net/ieee80211/ieee80211_crypt_tkip.c
+++ b/net/ieee80211/ieee80211_crypt_tkip.c
@@ -260,35 +260,27 @@ static void tkip_mixing_phase2(u8 * WEPS
 #endif
 }
 
-static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+static u8 *ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len, void *priv)
 {
 	struct ieee80211_tkip_data *tkey = priv;
 	int len;
-	u8 rc4key[16], *pos, *icv;
+	u8 *rc4key, *pos, *icv;
 	struct ieee80211_hdr_4addr *hdr;
 	u32 crc;
-	struct scatterlist sg;
 
 	hdr = (struct ieee80211_hdr_4addr *)skb->data;
 
-	if (tkey->ieee->tkip_countermeasures) {
-		if (net_ratelimit()) {
-			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
-			       "TX packet to " MAC_FMT "\n",
-			       tkey->ieee->dev->name, MAC_ARG(hdr->addr1));
-		}
-		return -1;
-	}
-
-	if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 ||
-	    skb->len < hdr_len)
-		return -1;
+	if (skb_headroom(skb) < 8 || skb->len < hdr_len)
+		return NULL;
 
 	if (!tkey->tx_phase1_done) {
 		tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
 				   tkey->tx_iv32);
 		tkey->tx_phase1_done = 1;
 	}
+	rc4key = kmalloc(16, GFP_ATOMIC);
+	if (!rc4key)
+		return NULL;
 	tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
 
 	len = skb->len - hdr_len;
@@ -297,9 +289,9 @@ static int ieee80211_tkip_encrypt(struct
 	pos += hdr_len;
 	icv = skb_put(skb, 4);
 
-	*pos++ = rc4key[0];
-	*pos++ = rc4key[1];
-	*pos++ = rc4key[2];
+	*pos++ = *rc4key;
+	*pos++ = *(rc4key + 1);
+	*pos++ = *(rc4key + 2);
 	*pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */ ;
 	*pos++ = tkey->tx_iv32 & 0xff;
 	*pos++ = (tkey->tx_iv32 >> 8) & 0xff;
@@ -312,6 +304,38 @@ static int ieee80211_tkip_encrypt(struct
 	icv[2] = crc >> 16;
 	icv[3] = crc >> 24;
 
+	return rc4key;
+}
+
+static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+{
+	struct ieee80211_tkip_data *tkey = priv;
+	int len;
+	const u8 *rc4key;
+	u8 *pos;
+	struct scatterlist sg;
+
+	if (tkey->ieee->tkip_countermeasures) {
+		if (net_ratelimit()) {
+			struct ieee80211_hdr_4addr *hdr =
+			    (struct ieee80211_hdr_4addr *)skb->data;
+			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
+			       "TX packet to " MAC_FMT "\n",
+			       tkey->ieee->dev->name, MAC_ARG(hdr->addr1));
+		}
+		return -1;
+	}
+
+	if (skb_tailroom(skb) < 4 || skb->len < hdr_len)
+		return -1;
+
+	len = skb->len - hdr_len;
+	pos = skb->data + hdr_len;
+
+	rc4key = ieee80211_tkip_hdr(skb, hdr_len, priv);
+	if (!rc4key)
+		return -1;
+
 	crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
 	sg.page = virt_to_page(pos);
 	sg.offset = offset_in_page(pos);
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 256d552..fcf05bf 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -1534,6 +1534,12 @@ void ieee80211_rx_mgt(struct ieee80211_d
 					      header);
 		break;
 
+	case IEEE80211_STYPE_DEAUTH:
+		printk("DEAUTH from AP\n");
+		if (ieee->handle_deauth != NULL)
+			ieee->handle_deauth(ieee->dev, (struct ieee80211_auth *)
+					    header);
+		break;
 	default:
 		IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n",
 				     WLAN_FC_GET_STYPE(le16_to_cpu
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index 24ade5f..8d87897 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -227,7 +227,7 @@ int ieee80211_xmit(struct sk_buff *skb, 
 	    rts_required;
 	unsigned long flags;
 	struct net_device_stats *stats = &ieee->stats;
-	int ether_type, encrypt, host_encrypt, host_encrypt_msdu;
+	int ether_type, encrypt, host_encrypt, host_encrypt_msdu, host_build_iv;
 	int bytes, fc, hdr_len;
 	struct sk_buff *skb_frag;
 	struct ieee80211_hdr_3addr header = {	/* Ensure zero initialized */
@@ -263,8 +263,10 @@ int ieee80211_xmit(struct sk_buff *skb, 
 
 	encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
 	    ieee->sec.encrypt;
+
 	host_encrypt = ieee->host_encrypt && encrypt;
 	host_encrypt_msdu = ieee->host_encrypt_msdu && encrypt;
+	host_build_iv = ieee->host_build_iv && encrypt;
 
 	if (!encrypt && ieee->ieee802_1x &&
 	    ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
@@ -310,8 +312,10 @@ int ieee80211_xmit(struct sk_buff *skb, 
 		int len = bytes + hdr_len + crypt->ops->extra_msdu_prefix_len +
 		    crypt->ops->extra_msdu_postfix_len;
 		struct sk_buff *skb_new = dev_alloc_skb(len);
+
 		if (unlikely(!skb_new))
 			goto failed;
+
 		skb_reserve(skb_new, crypt->ops->extra_msdu_prefix_len);
 		memcpy(skb_put(skb_new, hdr_len), &header, hdr_len);
 		snapped = 1;
@@ -418,7 +422,7 @@ int ieee80211_xmit(struct sk_buff *skb, 
 	for (; i < nr_frags; i++) {
 		skb_frag = txb->fragments[i];
 
-		if (host_encrypt)
+		if (host_encrypt || host_build_iv)
 			skb_reserve(skb_frag,
 				    crypt->ops->extra_mpdu_prefix_len);
 
@@ -453,6 +457,16 @@ int ieee80211_xmit(struct sk_buff *skb, 
 		 * to insert the IV between the header and the payload */
 		if (host_encrypt)
 			ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
+		else if (host_build_iv) {
+			struct ieee80211_crypt_data *crypt;
+
+			crypt = ieee->crypt[ieee->tx_keyidx];
+			atomic_inc(&crypt->refcnt);
+			if (crypt->ops->build_iv)
+				crypt->ops->build_iv(skb_frag, hdr_len,
+						     crypt->priv);
+			atomic_dec(&crypt->refcnt);
+		}
 
 		if (ieee->config &
 		    (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
---
0.99.8.GIT


--- NEW FILE 0196-ieee80211-added-IE-comments-reason_code-to-reason-removed-info_element-from-ieee80211_disassoc.txt ---
Subject: [PATCH] ieee80211: added IE comments, reason_code to reason, removed info_element from ieee80211_disassoc
From: James Ketrenos <jketreno linux intel com>
Date: 1127321936 -0500

tree 0254e7c97cece038cd11b47a16027c6379e464fe
parent a84f7713dc87ca1b51c6d53b391087663425a080
author James Ketrenos <jketreno linux intel com> 1126661324 -0500
committer James Ketrenos <jketreno linux intel com> 1127319069 -0500

Updated based on Michael Wu's patch and comments sent to netdev.

Added IE comments to ieee80211_* frame structures.
Changed reason_code to reason (consistency)
Removed info_element from ieee80211_disassoc

Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/net/ieee80211.h |   14 +++++++++++---
 1 files changed, 11 insertions(+), 3 deletions(-)

applies-to: 5ab119a07e98aaf623dc8ce6f04f7b3403b6b971
e5658d3e8a347f4393a9403b0cec8d43fa6214b1
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 220a9e3..4a381a0 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -603,17 +603,21 @@ struct ieee80211_auth {
 	__le16 algorithm;
 	__le16 transaction;
 	__le16 status;
+	/* challenge */
 	struct ieee80211_info_element info_element[0];
 } __attribute__ ((packed));
 
 struct ieee80211_disassoc {
 	struct ieee80211_hdr_3addr header;
-	__le16 reason_code;
-	struct ieee80211_info_element info_element[0];
+	__le16 reason;
 } __attribute__ ((packed));
 
+/* Alias deauth for disassoc */
+#define ieee82011_deauth ieee80211_disassoc
+
 struct ieee80211_probe_request {
 	struct ieee80211_hdr_3addr header;
+	/* SSID, supported rates */
 	struct ieee80211_info_element info_element[0];
 } __attribute__ ((packed));
 
@@ -622,6 +626,8 @@ struct ieee80211_probe_response {
 	u32 time_stamp[2];
 	__le16 beacon_interval;
 	__le16 capability;
+	/* SSID, supported rates, FH params, DS params,
+	 * CF params, IBSS params, TIM (if beacon), RSN */
 	struct ieee80211_info_element info_element[0];
 } __attribute__ ((packed));
 
@@ -632,6 +638,7 @@ struct ieee80211_assoc_request {
 	struct ieee80211_hdr_3addr header;
 	__le16 capability;
 	__le16 listen_interval;
+	/* SSID, supported rates, RSN */
 	struct ieee80211_info_element info_element[0];
 } __attribute__ ((packed));
 
@@ -648,7 +655,8 @@ struct ieee80211_assoc_response {
 	__le16 capability;
 	__le16 status;
 	__le16 aid;
-	struct ieee80211_info_element info_element[0];	/* supported rates */
+	/* supported rates */
+	struct ieee80211_info_element info_element[0];
 } __attribute__ ((packed));
 
 struct ieee80211_txb {
---
0.99.8.GIT


--- NEW FILE 0197-ieee80211-in-tree-driver-updates-to-sync-with-latest-ieee80211-series.txt ---
Subject: [PATCH] ieee80211: in-tree driver updates to sync with latest ieee80211 series
From: James Ketrenos <jketreno linux intel com>
Date: 1127385255 +0000

Changed crypto method from requiring a struct ieee80211_device reference
to the init handler.  Instead we now have a get/set flags method for
each crypto component.

Setting of TKIP countermeasures can now be done via
set_flags(IEEE80211_CRYPTO_TKIP_COUNTERMEASURES)

Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 include/net/ieee80211.h              |    1 -
 include/net/ieee80211_crypt.h        |   10 +++++++++-
 net/ieee80211/ieee80211_crypt.c      |    3 +--
 net/ieee80211/ieee80211_crypt_ccmp.c |    2 +-
 net/ieee80211/ieee80211_crypt_tkip.c |   34 ++++++++++++++++++++++++----------
 net/ieee80211/ieee80211_crypt_wep.c  |    2 +-
 net/ieee80211/ieee80211_module.c     |    1 -
 net/ieee80211/ieee80211_wx.c         |    4 ++--
 8 files changed, 38 insertions(+), 19 deletions(-)

applies-to: ae957738fa0a95a656e26b8ea48728b6c4267604
6eb6edf04acd09e3cea09456913e8da59323b89e
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 4a381a0..4851756 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -876,7 +876,6 @@ struct ieee80211_device {
 	/* WPA data */
 	int wpa_enabled;
 	int drop_unencrypted;
-	int tkip_countermeasures;
 	int privacy_invoked;
 	size_t wpa_ie_len;
 	u8 *wpa_ie;
diff --git a/include/net/ieee80211_crypt.h b/include/net/ieee80211_crypt.h
index daf3b2c..0c9d859 100644
--- a/include/net/ieee80211_crypt.h
+++ b/include/net/ieee80211_crypt.h
@@ -25,13 +25,17 @@
 
 #include <linux/skbuff.h>
 
+enum {
+	IEEE80211_CRYPTO_TKIP_COUNTERMEASURES = (1<<0),
+};
+
 struct ieee80211_crypto_ops {
 	const char *name;
 
 	/* init new crypto context (e.g., allocate private data space,
 	 * select IV, etc.); returns NULL on failure or pointer to allocated
 	 * private data on success */
-	void *(*init) (struct ieee80211_device * ieee, int keyidx);
+	void *(*init) (int keyidx);
 
 	/* deinitialize crypto context and free allocated private data */
 	void (*deinit) (void *priv);
@@ -60,6 +64,10 @@ struct ieee80211_crypto_ops {
 	 * statistics */
 	char *(*print_stats) (char *p, void *priv);
 
+	/* Crypto specific flag get/set for configuration settings */
+	unsigned long (*get_flags)(void *priv);
+	unsigned long (*set_flags)(unsigned long flags, void *priv);
+
 	/* maximum number of bytes added by encryption; encrypt buf is
 	 * allocated with extra_prefix_len bytes, copy of in_buf, and
 	 * extra_postfix_len; encrypt need not use all this space, but
diff --git a/net/ieee80211/ieee80211_crypt.c b/net/ieee80211/ieee80211_crypt.c
index e26bcc9..f3b6aa3 100644
--- a/net/ieee80211/ieee80211_crypt.c
+++ b/net/ieee80211/ieee80211_crypt.c
@@ -202,8 +202,7 @@ struct ieee80211_crypto_ops *ieee80211_g
 		return NULL;
 }
 
-static void *ieee80211_crypt_null_init(struct ieee80211_device *ieee,
-				       int keyidx)
+static void *ieee80211_crypt_null_init(int keyidx)
 {
 	return (void *)1;
 }
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c
index 081d857..05a853c 100644
--- a/net/ieee80211/ieee80211_crypt_ccmp.c
+++ b/net/ieee80211/ieee80211_crypt_ccmp.c
@@ -74,7 +74,7 @@ static void ieee80211_ccmp_aes_encrypt(s
 	crypto_cipher_encrypt(tfm, &dst, &src, AES_BLOCK_LEN);
 }
 
-static void *ieee80211_ccmp_init(struct ieee80211_device *ieee, int key_idx)
+static void *ieee80211_ccmp_init(int key_idx)
 {
 	struct ieee80211_ccmp_data *priv;
 
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c
index e073305..2e34f29 100644
--- a/net/ieee80211/ieee80211_crypt_tkip.c
+++ b/net/ieee80211/ieee80211_crypt_tkip.c
@@ -60,10 +60,24 @@ struct ieee80211_tkip_data {
 	/* scratch buffers for virt_to_page() (crypto API) */
 	u8 rx_hdr[16], tx_hdr[16];
 
-	struct ieee80211_device *ieee;
+	unsigned long flags;
 };
 
-static void *ieee80211_tkip_init(struct ieee80211_device *ieee, int key_idx)
+static unsigned long ieee80211_tkip_set_flags(unsigned long flags, void *priv)
+{
+	struct ieee80211_tkip_data *_priv = priv;
+	unsigned long old_flags = _priv->flags;
+	_priv->flags = flags;
+	return old_flags;
+}
+
+static unsigned long ieee80211_tkip_get_flags(void *priv)
+{
+	struct ieee80211_tkip_data *_priv = priv;
+	return _priv->flags;
+}
+
+static void *ieee80211_tkip_init(int key_idx)
 {
 	struct ieee80211_tkip_data *priv;
 
@@ -72,8 +86,6 @@ static void *ieee80211_tkip_init(struct 
 		goto fail;
 	memset(priv, 0, sizeof(*priv));
 
-	priv->ieee = ieee;
-
 	priv->key_idx = key_idx;
 
 	priv->tfm_arc4 = crypto_alloc_tfm("arc4", 0);
@@ -315,13 +327,13 @@ static int ieee80211_tkip_encrypt(struct
 	u8 *pos;
 	struct scatterlist sg;
 
-	if (tkey->ieee->tkip_countermeasures) {
+	if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
 		if (net_ratelimit()) {
 			struct ieee80211_hdr_4addr *hdr =
 			    (struct ieee80211_hdr_4addr *)skb->data;
-			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
+			printk(KERN_DEBUG "TKIP countermeasures: dropped "
 			       "TX packet to " MAC_FMT "\n",
-			       tkey->ieee->dev->name, MAC_ARG(hdr->addr1));
+			       MAC_ARG(hdr->addr1));
 		}
 		return -1;
 	}
@@ -366,11 +378,11 @@ static int ieee80211_tkip_decrypt(struct
 
 	hdr = (struct ieee80211_hdr_4addr *)skb->data;
 
-	if (tkey->ieee->tkip_countermeasures) {
+	if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
 		if (net_ratelimit()) {
-			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
+			printk(KERN_DEBUG "TKIP countermeasures: dropped "
 			       "received packet from " MAC_FMT "\n",
-			       tkey->ieee->dev->name, MAC_ARG(hdr->addr2));
+			       MAC_ARG(hdr->addr2));
 		}
 		return -1;
 	}
@@ -694,6 +706,8 @@ static struct ieee80211_crypto_ops ieee8
 	.extra_mpdu_prefix_len = 4 + 4,	/* IV + ExtIV */
 	.extra_mpdu_postfix_len = 4,	/* ICV */
 	.extra_msdu_postfix_len = 8,	/* MIC */
+	.get_flags = ieee80211_tkip_get_flags,
+	.set_flags = ieee80211_tkip_set_flags,
 	.owner = THIS_MODULE,
 };
 
diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c
index 2aaeac1..7c08ed2 100644
--- a/net/ieee80211/ieee80211_crypt_wep.c
+++ b/net/ieee80211/ieee80211_crypt_wep.c
@@ -37,7 +37,7 @@ struct prism2_wep_data {
 	struct crypto_tfm *tfm;
 };
 
-static void *prism2_wep_init(struct ieee80211_device *ieee, int keyidx)
+static void *prism2_wep_init(int keyidx)
 {
 	struct prism2_wep_data *priv;
 
diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c
index 3193125..5714692 100644
--- a/net/ieee80211/ieee80211_module.c
+++ b/net/ieee80211/ieee80211_module.c
@@ -155,7 +155,6 @@ struct net_device *alloc_ieee80211(int s
 	spin_lock_init(&ieee->lock);
 
 	ieee->wpa_enabled = 0;
-	ieee->tkip_countermeasures = 0;
 	ieee->drop_unencrypted = 0;
 	ieee->privacy_invoked = 0;
 
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index 3dd2bba..ee7a70a 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -355,7 +355,7 @@ int ieee80211_wx_set_encode(struct ieee8
 		}
 
 		if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
-			new_crypt->priv = new_crypt->ops->init(ieee, key);
+			new_crypt->priv = new_crypt->ops->init(key);
 
 		if (!new_crypt->ops || !new_crypt->priv) {
 			kfree(new_crypt);
@@ -598,7 +598,7 @@ int ieee80211_wx_set_encodeext(struct ie
 		memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
 		new_crypt->ops = ops;
 		if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
-			new_crypt->priv = new_crypt->ops->init(ieee, idx);
+			new_crypt->priv = new_crypt->ops->init(idx);
 		if (new_crypt->priv == NULL) {
 			kfree(new_crypt);
 			ret = -EINVAL;
---
0.99.8.GIT


Index: 0198-ieee80211-update-orinoco-wl3501-drivers-for-latest-struct-naming.txt
===================================================================
RCS file: 0198-ieee80211-update-orinoco-wl3501-drivers-for-latest-struct-naming.txt
diff -N 0198-ieee80211-update-orinoco-wl3501-drivers-for-latest-struct-naming.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0198-ieee80211-update-orinoco-wl3501-drivers-for-latest-struct-naming.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,40 @@
+Subject: [PATCH] ieee80211: update orinoco, wl3501 drivers for latest struct naming
+From: James Ketrenos <jketreno linux intel com>
+Date: 1127418187 -0400
+
+---
+
+ drivers/net/wireless/orinoco.c |    2 +-
+ drivers/net/wireless/wl3501.h  |    2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+applies-to: 7cf648aba7823b1b7cc9419f682a2dca60cc2e82
+af9288a707b609cdb1069cfe5bde0d6567c12c31
+diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
+index 77e93a2..fc2fa4d 100644
+--- a/drivers/net/wireless/orinoco.c
++++ b/drivers/net/wireless/orinoco.c
+@@ -636,7 +636,7 @@ static void __orinoco_ev_txexc(struct ne
+ 	/* Read the frame header */
+ 	err = hermes_bap_pread(hw, IRQ_BAP, &hdr,
+ 			       sizeof(struct hermes_tx_descriptor) +
+-			       sizeof(struct ieee80211_hdr),
++			       sizeof(struct ieee80211_hdr_4addr),
+ 			       fid, 0);
+ 
+ 	hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
+diff --git a/drivers/net/wireless/wl3501.h b/drivers/net/wireless/wl3501.h
+index 7fcbe58..4303c50 100644
+--- a/drivers/net/wireless/wl3501.h
++++ b/drivers/net/wireless/wl3501.h
+@@ -548,7 +548,7 @@ struct wl3501_80211_tx_plcp_hdr {
+ 
+ struct wl3501_80211_tx_hdr {
+ 	struct wl3501_80211_tx_plcp_hdr	pclp_hdr;
+-	struct ieee80211_hdr		mac_hdr;
++	struct ieee80211_hdr_4addr		mac_hdr;
+ } __attribute__ ((packed));
+ 
+ /*
+---
+0.99.8.GIT


Index: 0211-orinoco-Remove-inneeded-system-includes.txt
===================================================================
RCS file: 0211-orinoco-Remove-inneeded-system-includes.txt
diff -N 0211-orinoco-Remove-inneeded-system-includes.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0211-orinoco-Remove-inneeded-system-includes.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,365 @@
+Subject: [PATCH] orinoco: Remove inneeded system includes.
+From: Pavel Roskin <proski gnu org>
+Date: 1127463487 -0400
+
+Signed-off-by: Pavel Roskin <proski gnu org>
+
+Remove inneeded system includes.
+
+Most system includes are not needed.  In particular, the hardware
+backends don't need anything network related.  Some includes have been
+moved from local headers to the C files where they are actually used.
+Includes that have to be in the local headers are no longer from the C
+sources.
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/airport.c        |   19 +------------------
+ drivers/net/wireless/hermes.c         |   11 ++---------
+ drivers/net/wireless/hermes.h         |    3 +--
+ drivers/net/wireless/orinoco.c        |   12 ------------
+ drivers/net/wireless/orinoco.h        |    2 --
+ drivers/net/wireless/orinoco_cs.c     |   16 +---------------
+ drivers/net/wireless/orinoco_nortel.c |   18 +-----------------
+ drivers/net/wireless/orinoco_pci.c    |   18 +-----------------
+ drivers/net/wireless/orinoco_plx.c    |   18 +-----------------
+ drivers/net/wireless/orinoco_tmd.c    |   18 +-----------------
+ drivers/net/wireless/spectrum_cs.c    |   16 +---------------
+ 11 files changed, 10 insertions(+), 141 deletions(-)
+
+applies-to: 560986cb68a747de281f82ca605c7125ccc65c1c
+ef846bf04f4c9e1a68ab841e89931f8c26100874
+diff --git a/drivers/net/wireless/airport.c b/drivers/net/wireless/airport.c
+index 9d49670..7b321f7 100644
+--- a/drivers/net/wireless/airport.c
++++ b/drivers/net/wireless/airport.c
+@@ -15,28 +15,11 @@
+ #define PFX DRIVER_NAME ": "
+ 
+ #include <linux/config.h>
+-
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/ptrace.h>
+-#include <linux/slab.h>
+-#include <linux/string.h>
+-#include <linux/timer.h>
+-#include <linux/ioport.h>
+-#include <linux/netdevice.h>
+-#include <linux/if_arp.h>
+-#include <linux/etherdevice.h>
+-#include <linux/wireless.h>
+-
+-#include <asm/io.h>
+-#include <asm/system.h>
+-#include <asm/current.h>
+-#include <asm/prom.h>
+-#include <asm/machdep.h>
++#include <linux/delay.h>
+ #include <asm/pmac_feature.h>
+-#include <asm/irq.h>
+-#include <asm/uaccess.h>
+ 
+ #include "orinoco.h"
+ 
+diff --git a/drivers/net/wireless/hermes.c b/drivers/net/wireless/hermes.c
+index 21c3d0d..eba0d9d 100644
+--- a/drivers/net/wireless/hermes.c
++++ b/drivers/net/wireless/hermes.c
+@@ -39,17 +39,10 @@
+  */
+ 
+ #include <linux/config.h>
+-
+ #include <linux/module.h>
+-#include <linux/types.h>
+-#include <linux/threads.h>
+-#include <linux/smp.h>
+-#include <asm/io.h>
+-#include <linux/delay.h>
+-#include <linux/init.h>
+ #include <linux/kernel.h>
+-#include <linux/net.h>
+-#include <asm/errno.h>
++#include <linux/init.h>
++#include <linux/delay.h>
+ 
+ #include "hermes.h"
+ 
+diff --git a/drivers/net/wireless/hermes.h b/drivers/net/wireless/hermes.h
+index 8c9e874..786613a 100644
+--- a/drivers/net/wireless/hermes.h
++++ b/drivers/net/wireless/hermes.h
+@@ -30,9 +30,8 @@
+  * access to the hermes_t structure, and to the hardware
+ */
+ 
+-#include <linux/delay.h>
+ #include <linux/if_ether.h>
+-#include <asm/byteorder.h>
++#include <asm/io.h>
+ 
+ /*
+  * Limits and constants
+diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
+index fc2fa4d..f76fe3d 100644
+--- a/drivers/net/wireless/orinoco.c
++++ b/drivers/net/wireless/orinoco.c
+@@ -77,28 +77,16 @@
+ #define DRIVER_NAME "orinoco"
+ 
+ #include <linux/config.h>
+-
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/ptrace.h>
+-#include <linux/slab.h>
+-#include <linux/string.h>
+-#include <linux/timer.h>
+-#include <linux/ioport.h>
+ #include <linux/netdevice.h>
+-#include <linux/if_arp.h>
+ #include <linux/etherdevice.h>
+ #include <linux/ethtool.h>
+ #include <linux/wireless.h>
+ #include <net/iw_handler.h>
+ #include <net/ieee80211.h>
+ 
+-#include <asm/uaccess.h>
+-#include <asm/io.h>
+-#include <asm/system.h>
+-
+-#include "hermes.h"
+ #include "hermes_rid.h"
+ #include "orinoco.h"
+ 
+diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h
+index c800563..32530d4 100644
+--- a/drivers/net/wireless/orinoco.h
++++ b/drivers/net/wireless/orinoco.h
+@@ -9,8 +9,6 @@
+ 
+ #define DRIVER_VERSION "0.15rc2"
+ 
+-#include <linux/types.h>
+-#include <linux/spinlock.h>
+ #include <linux/netdevice.h>
+ #include <linux/wireless.h>
+ #include <net/iw_handler.h>
+diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
+index 80920b1..195c530 100644
+--- a/drivers/net/wireless/orinoco_cs.c
++++ b/drivers/net/wireless/orinoco_cs.c
+@@ -14,30 +14,16 @@
+ #define PFX DRIVER_NAME ": "
+ 
+ #include <linux/config.h>
+-
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/sched.h>
+-#include <linux/ptrace.h>
+-#include <linux/slab.h>
+-#include <linux/string.h>
+-#include <linux/ioport.h>
+-#include <linux/netdevice.h>
+-#include <linux/if_arp.h>
+-#include <linux/etherdevice.h>
+-#include <linux/wireless.h>
+-
++#include <linux/delay.h>
+ #include <pcmcia/cs_types.h>
+ #include <pcmcia/cs.h>
+ #include <pcmcia/cistpl.h>
+ #include <pcmcia/cisreg.h>
+ #include <pcmcia/ds.h>
+ 
+-#include <asm/uaccess.h>
+-#include <asm/io.h>
+-#include <asm/system.h>
+-
+ #include "orinoco.h"
+ 
+ /********************************************************************/
+diff --git a/drivers/net/wireless/orinoco_nortel.c b/drivers/net/wireless/orinoco_nortel.c
+index 86fa58e..d48ec24 100644
+--- a/drivers/net/wireless/orinoco_nortel.c
++++ b/drivers/net/wireless/orinoco_nortel.c
+@@ -40,29 +40,13 @@
+ #define PFX DRIVER_NAME ": "
+ 
+ #include <linux/config.h>
+-
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/sched.h>
+-#include <linux/ptrace.h>
+-#include <linux/slab.h>
+-#include <linux/string.h>
+-#include <linux/timer.h>
+-#include <linux/ioport.h>
+-#include <asm/uaccess.h>
+-#include <asm/io.h>
+-#include <asm/system.h>
+-#include <linux/netdevice.h>
+-#include <linux/if_arp.h>
+-#include <linux/etherdevice.h>
+-#include <linux/list.h>
++#include <linux/delay.h>
+ #include <linux/pci.h>
+-#include <linux/fcntl.h>
+-
+ #include <pcmcia/cisreg.h>
+ 
+-#include "hermes.h"
+ #include "orinoco.h"
+ 
+ #define COR_OFFSET    (0xe0)	/* COR attribute offset of Prism2 PC card */
+diff --git a/drivers/net/wireless/orinoco_pci.c b/drivers/net/wireless/orinoco_pci.c
+index 42e0343..5362c21 100644
+--- a/drivers/net/wireless/orinoco_pci.c
++++ b/drivers/net/wireless/orinoco_pci.c
+@@ -93,28 +93,12 @@
+ #define PFX DRIVER_NAME ": "
+ 
+ #include <linux/config.h>
+-
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/sched.h>
+-#include <linux/ptrace.h>
+-#include <linux/slab.h>
+-#include <linux/string.h>
+-#include <linux/timer.h>
+-#include <linux/ioport.h>
+-#include <linux/netdevice.h>
+-#include <linux/if_arp.h>
+-#include <linux/etherdevice.h>
+-#include <linux/list.h>
++#include <linux/delay.h>
+ #include <linux/pci.h>
+-#include <linux/fcntl.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/io.h>
+-#include <asm/system.h>
+ 
+-#include "hermes.h"
+ #include "orinoco.h"
+ 
+ /* All the magic there is from wlan-ng */
+diff --git a/drivers/net/wireless/orinoco_plx.c b/drivers/net/wireless/orinoco_plx.c
+index 7ab05b8..210e737 100644
+--- a/drivers/net/wireless/orinoco_plx.c
++++ b/drivers/net/wireless/orinoco_plx.c
+@@ -117,29 +117,13 @@
+ #define PFX DRIVER_NAME ": "
+ 
+ #include <linux/config.h>
+-
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/sched.h>
+-#include <linux/ptrace.h>
+-#include <linux/slab.h>
+-#include <linux/string.h>
+-#include <linux/timer.h>
+-#include <linux/ioport.h>
+-#include <asm/uaccess.h>
+-#include <asm/io.h>
+-#include <asm/system.h>
+-#include <linux/netdevice.h>
+-#include <linux/if_arp.h>
+-#include <linux/etherdevice.h>
+-#include <linux/list.h>
++#include <linux/delay.h>
+ #include <linux/pci.h>
+-#include <linux/fcntl.h>
+-
+ #include <pcmcia/cisreg.h>
+ 
+-#include "hermes.h"
+ #include "orinoco.h"
+ 
+ #define COR_OFFSET	(0x3e0)	/* COR attribute offset of Prism2 PC card */
+diff --git a/drivers/net/wireless/orinoco_tmd.c b/drivers/net/wireless/orinoco_tmd.c
+index 85893f4..5e68b70 100644
+--- a/drivers/net/wireless/orinoco_tmd.c
++++ b/drivers/net/wireless/orinoco_tmd.c
+@@ -53,29 +53,13 @@
+ #define PFX DRIVER_NAME ": "
+ 
+ #include <linux/config.h>
+-
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/sched.h>
+-#include <linux/ptrace.h>
+-#include <linux/slab.h>
+-#include <linux/string.h>
+-#include <linux/timer.h>
+-#include <linux/ioport.h>
+-#include <asm/uaccess.h>
+-#include <asm/io.h>
+-#include <asm/system.h>
+-#include <linux/netdevice.h>
+-#include <linux/if_arp.h>
+-#include <linux/etherdevice.h>
+-#include <linux/list.h>
++#include <linux/delay.h>
+ #include <linux/pci.h>
+-#include <linux/fcntl.h>
+-
+ #include <pcmcia/cisreg.h>
+ 
+-#include "hermes.h"
+ #include "orinoco.h"
+ 
+ #define COR_VALUE	(COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
+diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
+index 63e0042..6119954 100644
+--- a/drivers/net/wireless/spectrum_cs.c
++++ b/drivers/net/wireless/spectrum_cs.c
+@@ -22,31 +22,17 @@
+ #define PFX DRIVER_NAME ": "
+ 
+ #include <linux/config.h>
+-
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/sched.h>
+-#include <linux/ptrace.h>
+-#include <linux/slab.h>
+-#include <linux/string.h>
+-#include <linux/ioport.h>
+-#include <linux/netdevice.h>
+-#include <linux/if_arp.h>
+-#include <linux/etherdevice.h>
+-#include <linux/wireless.h>
++#include <linux/delay.h>
+ #include <linux/firmware.h>
+-
+ #include <pcmcia/cs_types.h>
+ #include <pcmcia/cs.h>
+ #include <pcmcia/cistpl.h>
+ #include <pcmcia/cisreg.h>
+ #include <pcmcia/ds.h>
+ 
+-#include <asm/uaccess.h>
+-#include <asm/io.h>
+-#include <asm/system.h>
+-
+ #include "orinoco.h"
+ 
+ static unsigned char *primsym;
+---
+0.99.8.GIT


Index: 0212-orinoco-Make-nortel_pci_hw_init-static.txt
===================================================================
RCS file: 0212-orinoco-Make-nortel_pci_hw_init-static.txt
diff -N 0212-orinoco-Make-nortel_pci_hw_init-static.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0212-orinoco-Make-nortel_pci_hw_init-static.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,33 @@
+Subject: [PATCH] orinoco: Make nortel_pci_hw_init() static.
+From: Pavel Roskin <proski gnu org>
+Date: 1127463486 -0400
+
+Signed-off-by: Pavel Roskin <proski gnu org>
+
+Make nortel_pci_hw_init() static.
+
+Found by sparse.
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/orinoco_nortel.c |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+applies-to: 20a1f3808166d65f98db97944870e20143c05067
+4c08202547111e503eca4031ae9443159a79e2b2
+diff --git a/drivers/net/wireless/orinoco_nortel.c b/drivers/net/wireless/orinoco_nortel.c
+index d48ec24..d8afd51 100644
+--- a/drivers/net/wireless/orinoco_nortel.c
++++ b/drivers/net/wireless/orinoco_nortel.c
+@@ -92,7 +92,7 @@ static int nortel_pci_cor_reset(struct o
+ 	return 0;
+ }
+ 
+-int nortel_pci_hw_init(struct nortel_pci_card *card)
++static int nortel_pci_hw_init(struct nortel_pci_card *card)
+ {
+ 	int i;
+ 	u32 reg;
+---
+0.99.8.GIT


Index: 0213-orinoco-Fix-memory-leak-and-unneeded-unlock-in-orinoco_join_ap.txt
===================================================================
RCS file: 0213-orinoco-Fix-memory-leak-and-unneeded-unlock-in-orinoco_join_ap.txt
diff -N 0213-orinoco-Fix-memory-leak-and-unneeded-unlock-in-orinoco_join_ap.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0213-orinoco-Fix-memory-leak-and-unneeded-unlock-in-orinoco_join_ap.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,46 @@
+Subject: [PATCH] orinoco: Fix memory leak and unneeded unlock in orinoco_join_ap()
+From: Pavel Roskin <proski gnu org>
+Date: 1127463486 -0400
+
+Signed-off-by: Pavel Roskin <proski gnu org>
+
+Fix memory leak and unneeded unlock in orinoco_join_ap()
+
+If orinoco_lock() fails, the code would still run orinoco_unlock(),
+instead of freeing the allocated memory.  Found by sparse.
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/orinoco.c |    6 ++++--
+ 1 files changed, 4 insertions(+), 2 deletions(-)
+
+applies-to: 16e191f069d0d722a61cbab76ab77fa587162386
+f3cb4cc120177090b0ccc9fb20a12010de39ac8a
+diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
+index f76fe3d..8b93b44 100644
+--- a/drivers/net/wireless/orinoco.c
++++ b/drivers/net/wireless/orinoco.c
+@@ -1046,7 +1046,7 @@ static void orinoco_join_ap(struct net_d
+ 		return;
+ 
+ 	if (orinoco_lock(priv, &flags) != 0)
+-		goto out;
++		goto fail_lock;
+ 
+ 	/* Sanity checks in case user changed something in the meantime */
+ 	if (! priv->bssid_fixed)
+@@ -1091,8 +1091,10 @@ static void orinoco_join_ap(struct net_d
+ 		printk(KERN_ERR "%s: Error issuing join request\n", dev->name);
+ 
+  out:
+-	kfree(buf);
+ 	orinoco_unlock(priv, &flags);
++
++ fail_lock:
++	kfree(buf);
+ }
+ 
+ /* Send new BSSID to userspace */
+---
+0.99.8.GIT


Index: 0214-orinoco-orinoco_send_wevents-could-return-without-unlocking.txt
===================================================================
RCS file: 0214-orinoco-orinoco_send_wevents-could-return-without-unlocking.txt
diff -N 0214-orinoco-orinoco_send_wevents-could-return-without-unlocking.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0214-orinoco-orinoco_send_wevents-could-return-without-unlocking.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,41 @@
+Subject: [PATCH] orinoco: orinoco_send_wevents() could return without unlocking.
+From: Pavel Roskin <proski gnu org>
+Date: 1127463486 -0400
+
+Signed-off-by: Pavel Roskin <proski gnu org>
+
+orinoco_send_wevents() could return without unlocking.
+
+Failure to read BSSID from the hardware would cause orinoco_send_wevents() to
+return with lock held.  Found by sparse.
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/orinoco.c |    4 +++-
+ 1 files changed, 3 insertions(+), 1 deletions(-)
+
+applies-to: 368c76f705f9512f5016288b607e3a0e4b36d54d
+8aeabc375041a5fe9c9be315472497b2e0547eed
+diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
+index 8b93b44..29cb5d8 100644
+--- a/drivers/net/wireless/orinoco.c
++++ b/drivers/net/wireless/orinoco.c
+@@ -1112,12 +1112,14 @@ static void orinoco_send_wevents(struct 
+ 	err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENTBSSID,
+ 			      ETH_ALEN, NULL, wrqu.ap_addr.sa_data);
+ 	if (err != 0)
+-		return;
++		goto out;
+ 
+ 	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ 
+ 	/* Send event to user space */
+ 	wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
++
++ out:
+ 	orinoco_unlock(priv, &flags);
+ }
+ 
+---
+0.99.8.GIT


Index: 0215-orinoco-Remove-unneeded-forward-declarations.txt
===================================================================
RCS file: 0215-orinoco-Remove-unneeded-forward-declarations.txt
diff -N 0215-orinoco-Remove-unneeded-forward-declarations.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0215-orinoco-Remove-unneeded-forward-declarations.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,90 @@
+Subject: [PATCH] orinoco: Remove unneeded forward declarations.
+From: Pavel Roskin <proski gnu org>
+Date: 1127463486 -0400
+
+Signed-off-by: Pavel Roskin <proski gnu org>
+
+Remove unneeded forward declarations.
+
+Also reorder struct pcmcia_driver initialization to keep attach and
+detach together.
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/orinoco_cs.c  |   15 +++------------
+ drivers/net/wireless/spectrum_cs.c |   15 +++------------
+ 2 files changed, 6 insertions(+), 24 deletions(-)
+
+applies-to: 27f79b27bc015596395c03ecd9c6ae72964fb322
+393da59834eef526fc6fd0df321e94344d7c49e3
+diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
+index 195c530..dc1128a 100644
+--- a/drivers/net/wireless/orinoco_cs.c
++++ b/drivers/net/wireless/orinoco_cs.c
+@@ -80,17 +80,8 @@ static dev_link_t *dev_list; /* = NULL *
+ /* Function prototypes						    */
+ /********************************************************************/
+ 
+-/* device methods */
+-static int orinoco_cs_hard_reset(struct orinoco_private *priv);
+-
+-/* PCMCIA gumpf */
+-static void orinoco_cs_config(dev_link_t * link);
+-static void orinoco_cs_release(dev_link_t * link);
+-static int orinoco_cs_event(event_t event, int priority,
+-			    event_callback_args_t * args);
+-
+-static dev_link_t *orinoco_cs_attach(void);
+-static void orinoco_cs_detach(dev_link_t *);
++static void orinoco_cs_release(dev_link_t *link);
++static void orinoco_cs_detach(dev_link_t *link);
+ 
+ /********************************************************************/
+ /* Device methods     						    */
+@@ -675,8 +666,8 @@ static struct pcmcia_driver orinoco_driv
+ 		.name	= DRIVER_NAME,
+ 	},
+ 	.attach		= orinoco_cs_attach,
+-	.event		= orinoco_cs_event,
+ 	.detach		= orinoco_cs_detach,
++	.event		= orinoco_cs_event,
+ 	.id_table       = orinoco_cs_ids,
+ };
+ 
+diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
+index 6119954..ceed024 100644
+--- a/drivers/net/wireless/spectrum_cs.c
++++ b/drivers/net/wireless/spectrum_cs.c
+@@ -89,17 +89,8 @@ static dev_link_t *dev_list; /* = NULL *
+ /* Function prototypes						    */
+ /********************************************************************/
+ 
+-/* device methods */
+-static int spectrum_cs_hard_reset(struct orinoco_private *priv);
+-
+-/* PCMCIA gumpf */
+-static void spectrum_cs_config(dev_link_t * link);
+-static void spectrum_cs_release(dev_link_t * link);
+-static int spectrum_cs_event(event_t event, int priority,
+-			    event_callback_args_t * args);
+-
+-static dev_link_t *spectrum_cs_attach(void);
+-static void spectrum_cs_detach(dev_link_t *);
++static void spectrum_cs_release(dev_link_t *link);
++static void spectrum_cs_detach(dev_link_t *link);
+ 
+ /********************************************************************/
+ /* Firmware downloader						    */
+@@ -1058,8 +1049,8 @@ static struct pcmcia_driver orinoco_driv
+ 		.name	= DRIVER_NAME,
+ 	},
+ 	.attach		= spectrum_cs_attach,
+-	.event		= spectrum_cs_event,
+ 	.detach		= spectrum_cs_detach,
++	.event		= spectrum_cs_event,
+ 	.id_table       = spectrum_cs_ids,
+ };
+ 
+---
+0.99.8.GIT


Index: 0216-orinoco-Annotate-endianess-of-variables-and-structure-members.txt
===================================================================
RCS file: 0216-orinoco-Annotate-endianess-of-variables-and-structure-members.txt
diff -N 0216-orinoco-Annotate-endianess-of-variables-and-structure-members.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0216-orinoco-Annotate-endianess-of-variables-and-structure-members.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,460 @@
+Subject: [PATCH] orinoco: Annotate endianess of variables and structure members.
+From: Pavel Roskin <proski gnu org>
+Date: 1127463486 -0400
+
+Signed-off-by: Pavel Roskin <proski gnu org>
+
+Annotate endianess of variables and structure members.
+
+Don't reuse variables for both host-endian and little-endian data.
+Minor comment changes in affected structures.
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/hermes.h      |  108 ++++++++++++++++++------------------
+ drivers/net/wireless/orinoco.c     |   62 +++++++++++----------
+ drivers/net/wireless/orinoco.h     |    6 +-
+ drivers/net/wireless/spectrum_cs.c |   20 +++----
+ 4 files changed, 99 insertions(+), 97 deletions(-)
+
+applies-to: bf4285c3f2064b56c2b188d4f24fe2b3d740290b
+d133ae4cd6a3c75c31b1630f906cc9979a11077f
+diff --git a/drivers/net/wireless/hermes.h b/drivers/net/wireless/hermes.h
+index 786613a..ad28e32 100644
+--- a/drivers/net/wireless/hermes.h
++++ b/drivers/net/wireless/hermes.h
+@@ -191,13 +191,13 @@
+ #define	HERMES_RXSTAT_WMP		(0x6000)	/* Wavelan-II Management Protocol frame */
+ 
+ struct hermes_tx_descriptor {
+-	u16 status;
+-	u16 reserved1;
+-	u16 reserved2;
+-	u32 sw_support;
++	__le16 status;
++	__le16 reserved1;
++	__le16 reserved2;
++	__le32 sw_support;
+ 	u8 retry_count;
+ 	u8 tx_rate;
+-	u16 tx_control;	
++	__le16 tx_control;	
+ } __attribute__ ((packed));
+ 
+ #define HERMES_TXSTAT_RETRYERR		(0x0001)
+@@ -221,60 +221,60 @@ struct hermes_tx_descriptor {
+ #define HERMES_INQ_SEC_STAT_AGERE	(0xF202)
+ 
+ struct hermes_tallies_frame {
+-	u16 TxUnicastFrames;
+-	u16 TxMulticastFrames;
+-	u16 TxFragments;
+-	u16 TxUnicastOctets;
+-	u16 TxMulticastOctets;
+-	u16 TxDeferredTransmissions;
+-	u16 TxSingleRetryFrames;
+-	u16 TxMultipleRetryFrames;
+-	u16 TxRetryLimitExceeded;
+-	u16 TxDiscards;
+-	u16 RxUnicastFrames;
+-	u16 RxMulticastFrames;
+-	u16 RxFragments;
+-	u16 RxUnicastOctets;
+-	u16 RxMulticastOctets;
+-	u16 RxFCSErrors;
+-	u16 RxDiscards_NoBuffer;
+-	u16 TxDiscardsWrongSA;
+-	u16 RxWEPUndecryptable;
+-	u16 RxMsgInMsgFragments;
+-	u16 RxMsgInBadMsgFragments;
++	__le16 TxUnicastFrames;
++	__le16 TxMulticastFrames;
++	__le16 TxFragments;
++	__le16 TxUnicastOctets;
++	__le16 TxMulticastOctets;
++	__le16 TxDeferredTransmissions;
++	__le16 TxSingleRetryFrames;
++	__le16 TxMultipleRetryFrames;
++	__le16 TxRetryLimitExceeded;
++	__le16 TxDiscards;
++	__le16 RxUnicastFrames;
++	__le16 RxMulticastFrames;
++	__le16 RxFragments;
++	__le16 RxUnicastOctets;
++	__le16 RxMulticastOctets;
++	__le16 RxFCSErrors;
++	__le16 RxDiscards_NoBuffer;
++	__le16 TxDiscardsWrongSA;
++	__le16 RxWEPUndecryptable;
++	__le16 RxMsgInMsgFragments;
++	__le16 RxMsgInBadMsgFragments;
+ 	/* Those last are probably not available in very old firmwares */
+-	u16 RxDiscards_WEPICVError;
+-	u16 RxDiscards_WEPExcluded;
++	__le16 RxDiscards_WEPICVError;
++	__le16 RxDiscards_WEPExcluded;
+ } __attribute__ ((packed));
+ 
+ /* Grabbed from wlan-ng - Thanks Mark... - Jean II
+  * This is the result of a scan inquiry command */
+ /* Structure describing info about an Access Point */
+ struct prism2_scan_apinfo {
+-	u16 channel;		/* Channel where the AP sits */
+-	u16 noise;		/* Noise level */
+-	u16 level;		/* Signal level */
++	__le16 channel;		/* Channel where the AP sits */
++	__le16 noise;		/* Noise level */
++	__le16 level;		/* Signal level */
+ 	u8 bssid[ETH_ALEN];	/* MAC address of the Access Point */
+-	u16 beacon_interv;	/* Beacon interval */
+-	u16 capabilities;	/* Capabilities */
+-	u16 essid_len;		/* ESSID length */
++	__le16 beacon_interv;	/* Beacon interval */
++	__le16 capabilities;	/* Capabilities */
++	__le16 essid_len;	/* ESSID length */
+ 	u8 essid[32];		/* ESSID of the network */
+ 	u8 rates[10];		/* Bit rate supported */
+-	u16 proberesp_rate;	/* Data rate of the response frame */
+-	u16 atim;		/* ATIM window time, Kus (hostscan only) */
++	__le16 proberesp_rate;	/* Data rate of the response frame */
++	__le16 atim;		/* ATIM window time, Kus (hostscan only) */
+ } __attribute__ ((packed));
+ 
+ /* Same stuff for the Lucent/Agere card.
+  * Thanks to h1kari <h1kari AT dachb0den.com> - Jean II */
+ struct agere_scan_apinfo {
+-	u16 channel;		/* Channel where the AP sits */
+-	u16 noise;		/* Noise level */
+-	u16 level;		/* Signal level */
++	__le16 channel;		/* Channel where the AP sits */
++	__le16 noise;		/* Noise level */
++	__le16 level;		/* Signal level */
+ 	u8 bssid[ETH_ALEN];	/* MAC address of the Access Point */
+-	u16 beacon_interv;	/* Beacon interval */
+-	u16 capabilities;	/* Capabilities */
++	__le16 beacon_interv;	/* Beacon interval */
++	__le16 capabilities;	/* Capabilities */
+ 	/* bits: 0-ess, 1-ibss, 4-privacy [wep] */
+-	u16 essid_len;		/* ESSID length */
++	__le16 essid_len;	/* ESSID length */
+ 	u8 essid[32];		/* ESSID of the network */
+ } __attribute__ ((packed));
+ 
+@@ -282,16 +282,16 @@ struct agere_scan_apinfo {
+ struct symbol_scan_apinfo {
+ 	u8 channel;		/* Channel where the AP sits */
+ 	u8 unknown1;		/* 8 in 2.9x and 3.9x f/w, 0 otherwise */
+-	u16 noise;		/* Noise level */
+-	u16 level;		/* Signal level */
++	__le16 noise;		/* Noise level */
++	__le16 level;		/* Signal level */
+ 	u8 bssid[ETH_ALEN];	/* MAC address of the Access Point */
+-	u16 beacon_interv;	/* Beacon interval */
+-	u16 capabilities;	/* Capabilities */
++	__le16 beacon_interv;	/* Beacon interval */
++	__le16 capabilities;	/* Capabilities */
+ 	/* bits: 0-ess, 1-ibss, 4-privacy [wep] */
+-	u16 essid_len;		/* ESSID length */
++	__le16 essid_len;	/* ESSID length */
+ 	u8 essid[32];		/* ESSID of the network */
+-    	u16 rates[5];		/* Bit rate supported */
+-	u16 basic_rates;	/* Basic rates bitmask */
++    	__le16 rates[5];	/* Bit rate supported */
++	__le16 basic_rates;	/* Basic rates bitmask */
+ 	u8 unknown2[6];		/* Always FF:FF:FF:FF:00:00 */
+ 	u8 unknown3[8];		/* Always 0, appeared in f/w 3.91-68 */
+ } __attribute__ ((packed));
+@@ -311,7 +311,7 @@ union hermes_scan_info {
+ #define HERMES_LINKSTATUS_ASSOC_FAILED    (0x0006)
+   
+ struct hermes_linkstatus {
+-	u16 linkstatus;         /* Link status */
++	__le16 linkstatus;         /* Link status */
+ } __attribute__ ((packed));
+ 
+ struct hermes_response {
+@@ -320,8 +320,8 @@ struct hermes_response {
+ 
+ /* "ID" structure - used for ESSID and station nickname */
+ struct hermes_idstring {
+-	u16 len;
+-	u16 val[16];
++	__le16 len;
++	__le16 val[16];
+ } __attribute__ ((packed));
+ 
+ struct hermes_multicast {
+@@ -446,7 +446,7 @@ static inline void hermes_clear_words(st
+ 
+ static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word)
+ {
+-	u16 rec;
++	__le16 rec;
+ 	int err;
+ 
+ 	err = HERMES_READ_RECORD(hw, bap, rid, &rec);
+@@ -456,7 +456,7 @@ static inline int hermes_read_wordrec(he
+ 
+ static inline int hermes_write_wordrec(hermes_t *hw, int bap, u16 rid, u16 word)
+ {
+-	u16 rec = cpu_to_le16(word);
++	__le16 rec = cpu_to_le16(word);
+ 	return HERMES_WRITE_RECORD(hw, bap, rid, &rec);
+ }
+ 
+diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
+index 29cb5d8..1ae301c 100644
+--- a/drivers/net/wireless/orinoco.c
++++ b/drivers/net/wireless/orinoco.c
+@@ -202,31 +202,32 @@ static struct {
+ /********************************************************************/
+ 
+ /* Used in Event handling.
+- * We avoid nested structres as they break on ARM -- Moustafa */
++ * We avoid nested structures as they break on ARM -- Moustafa */
+ struct hermes_tx_descriptor_802_11 {
+ 	/* hermes_tx_descriptor */
+-	u16 status;
+-	u16 reserved1;
+-	u16 reserved2;
+-	u32 sw_support;
++	__le16 status;
++	__le16 reserved1;
++	__le16 reserved2;
++	__le32 sw_support;
+ 	u8 retry_count;
+ 	u8 tx_rate;
+-	u16 tx_control;
++	__le16 tx_control;
+ 
+-	/* ieee802_11_hdr */
+-	u16 frame_ctl;
+-	u16 duration_id;
++	/* ieee80211_hdr */
++	__le16 frame_ctl;
++	__le16 duration_id;
+ 	u8 addr1[ETH_ALEN];
+ 	u8 addr2[ETH_ALEN];
+ 	u8 addr3[ETH_ALEN];
+-	u16 seq_ctl;
++	__le16 seq_ctl;
+ 	u8 addr4[ETH_ALEN];
+-	u16 data_len;
++
++	__le16 data_len;
+ 
+ 	/* ethhdr */
+-	unsigned char   h_dest[ETH_ALEN];       /* destination eth addr */
+-	unsigned char   h_source[ETH_ALEN];     /* source ether addr    */
+-	unsigned short  h_proto;                /* packet type ID field */
++	u8 h_dest[ETH_ALEN];	/* destination eth addr */
++	u8 h_source[ETH_ALEN];	/* source ether addr    */
++	__be16 h_proto;		/* packet type ID field */
+ 
+ 	/* p8022_hdr */
+ 	u8 dsap;
+@@ -234,31 +235,31 @@ struct hermes_tx_descriptor_802_11 {
+ 	u8 ctrl;
+ 	u8 oui[3];
+ 
+-	u16 ethertype;
++	__be16 ethertype;
+ } __attribute__ ((packed));
+ 
+ /* Rx frame header except compatibility 802.3 header */
+ struct hermes_rx_descriptor {
+ 	/* Control */
+-	u16 status;
+-	u32 time;
++	__le16 status;
++	__le32 time;
+ 	u8 silence;
+ 	u8 signal;
+ 	u8 rate;
+ 	u8 rxflow;
+-	u32 reserved;
++	__le32 reserved;
+ 
+ 	/* 802.11 header */
+-	u16 frame_ctl;
+-	u16 duration_id;
++	__le16 frame_ctl;
++	__le16 duration_id;
+ 	u8 addr1[ETH_ALEN];
+ 	u8 addr2[ETH_ALEN];
+ 	u8 addr3[ETH_ALEN];
+-	u16 seq_ctl;
++	__le16 seq_ctl;
+ 	u8 addr4[ETH_ALEN];
+ 
+ 	/* Data length */
+-	u16 data_len;
++	__le16 data_len;
+ } __attribute__ ((packed));
+ 
+ /********************************************************************/
+@@ -389,7 +390,7 @@ static struct iw_statistics *orinoco_get
+ 		}
+ 	} else {
+ 		struct {
+-			u16 qual, signal, noise;
++			__le16 qual, signal, noise;
+ 		} __attribute__ ((packed)) cq;
+ 
+ 		err = HERMES_READ_RECORD(hw, USER_BAP,
+@@ -615,6 +616,7 @@ static void __orinoco_ev_txexc(struct ne
+ 	struct orinoco_private *priv = netdev_priv(dev);
+ 	struct net_device_stats *stats = &priv->stats;
+ 	u16 fid = hermes_read_regn(hw, TXCOMPLFID);
++	u16 status;
+ 	struct hermes_tx_descriptor_802_11 hdr;
+ 	int err = 0;
+ 
+@@ -644,8 +646,8 @@ static void __orinoco_ev_txexc(struct ne
+ 	 * exceeded, because that's the only status that really mean
+ 	 * that this particular node went away.
+ 	 * Other errors means that *we* screwed up. - Jean II */
+-	hdr.status = le16_to_cpu(hdr.status);
+-	if (hdr.status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
++	status = le16_to_cpu(hdr.status);
++	if (status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
+ 		union iwreq_data	wrqu;
+ 
+ 		/* Copy 802.11 dest address.
+@@ -1031,7 +1033,7 @@ static void orinoco_join_ap(struct net_d
+ 	unsigned long flags;
+ 	struct join_req {
+ 		u8 bssid[ETH_ALEN];
+-		u16 channel;
++		__le16 channel;
+ 	} __attribute__ ((packed)) req;
+ 	const int atom_len = offsetof(struct prism2_scan_apinfo, atim);
+ 	struct prism2_scan_apinfo *atom = NULL;
+@@ -1128,8 +1130,8 @@ static void __orinoco_ev_info(struct net
+ 	struct orinoco_private *priv = netdev_priv(dev);
+ 	u16 infofid;
+ 	struct {
+-		u16 len;
+-		u16 type;
++		__le16 len;
++		__le16 type;
+ 	} __attribute__ ((packed)) info;
+ 	int len, type;
+ 	int err;
+@@ -3905,7 +3907,7 @@ static int orinoco_ioctl_setscan(struct 
+ 						   HERMES_HOSTSCAN_SYMBOL_BCAST);
+ 			break;
+ 		case FIRMWARE_TYPE_INTERSIL: {
+-			u16 req[3];
++			__le16 req[3];
+ 
+ 			req[0] = cpu_to_le16(0x3fff);	/* All channels */
+ 			req[1] = cpu_to_le16(0x0001);	/* rate 1 Mbps */
+@@ -3979,7 +3981,7 @@ static inline int orinoco_translate_scan
+ 	case FIRMWARE_TYPE_INTERSIL:
+ 		offset = 4;
+ 		if (priv->has_hostscan) {
+-			atom_len = le16_to_cpup((u16 *)scan);
++			atom_len = le16_to_cpup((__le16 *)scan);
+ 			/* Sanity check for atom_len */
+ 			if (atom_len < sizeof(struct prism2_scan_apinfo)) {
+ 				printk(KERN_ERR "%s: Invalid atom_len in scan data: %d\n",
+diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h
+index 32530d4..6920ead 100644
+--- a/drivers/net/wireless/orinoco.h
++++ b/drivers/net/wireless/orinoco.h
+@@ -27,7 +27,7 @@
+ #define ORINOCO_MAX_KEYS	4
+ 
+ struct orinoco_key {
+-	u16 len;	/* always stored as little-endian */
++	__le16 len;	/* always stored as little-endian */
+ 	char data[ORINOCO_MAX_KEY_SIZE];
+ } __attribute__ ((packed));
+ 
+@@ -35,14 +35,14 @@ struct header_struct {
+ 	/* 802.3 */
+ 	u8 dest[ETH_ALEN];
+ 	u8 src[ETH_ALEN];
+-	u16 len;
++	__be16 len;
+ 	/* 802.2 */
+ 	u8 dsap;
+ 	u8 ssap;
+ 	u8 ctrl;
+ 	/* SNAP */
+ 	u8 oui[3];
+-	u16 ethertype;
++	unsigned short ethertype;
+ } __attribute__ ((packed));
+ 
+ typedef enum {
+diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
+index ceed024..b1bbc8e 100644
+--- a/drivers/net/wireless/spectrum_cs.c
++++ b/drivers/net/wireless/spectrum_cs.c
+@@ -138,8 +138,8 @@ static void spectrum_cs_detach(dev_link_
+  * Each block has the following structure.
+  */
+ struct dblock {
+-	u32 _addr;		/* adapter address where to write the block */
+-	u16 _len;		/* length of the data only, in bytes */
++	__le32 _addr;		/* adapter address where to write the block */
++	__le16 _len;		/* length of the data only, in bytes */
+ 	char data[0];		/* data to be written */
+ } __attribute__ ((packed));
+ 
+@@ -149,9 +149,9 @@ struct dblock {
+  * items with matching ID should be written.
+  */
+ struct pdr {
+-	u32 _id;		/* record ID */
+-	u32 _addr;		/* adapter address where to write the data */
+-	u32 _len;		/* expected length of the data, in bytes */
++	__le32 _id;		/* record ID */
++	__le32 _addr;		/* adapter address where to write the data */
++	__le32 _len;		/* expected length of the data, in bytes */
+ 	char next[0];		/* next PDR starts here */
+ } __attribute__ ((packed));
+ 
+@@ -162,8 +162,8 @@ struct pdr {
+  * be plugged into the secondary firmware.
+  */
+ struct pdi {
+-	u16 _len;		/* length of ID and data, in words */
+-	u16 _id;		/* record ID */
++	__le16 _len;		/* length of ID and data, in words */
++	__le16 _id;		/* record ID */
+ 	char data[0];		/* plug data */
+ } __attribute__ ((packed));;
+ 
+@@ -370,7 +370,7 @@ spectrum_plug_pdi(hermes_t *hw, struct p
+ 
+ /* Read PDA from the adapter */
+ static int
+-spectrum_read_pda(hermes_t *hw, u16 *pda, int pda_len)
++spectrum_read_pda(hermes_t *hw, __le16 *pda, int pda_len)
+ {
+ 	int ret;
+ 	int pda_size;
+@@ -401,7 +401,7 @@ spectrum_read_pda(hermes_t *hw, u16 *pda
+ /* Parse PDA and write the records into the adapter */
+ static int
+ spectrum_apply_pda(hermes_t *hw, const struct dblock *first_block,
+-		   u16 *pda)
++		   __le16 *pda)
+ {
+ 	int ret;
+ 	struct pdi *pdi;
+@@ -467,7 +467,7 @@ spectrum_dl_image(hermes_t *hw, dev_link
+ 	const struct dblock *first_block;
+ 
+ 	/* Plug Data Area (PDA) */
+-	u16 pda[PDA_WORDS];
++	__le16 pda[PDA_WORDS];
+ 
+ 	/* Binary block begins after the 0x1A marker */
+ 	ptr = image;
+---
+0.99.8.GIT


Index: 0217-orinoco-Read-only-needed-data-in-__orinoco_ev_txexc.txt
===================================================================
RCS file: 0217-orinoco-Read-only-needed-data-in-__orinoco_ev_txexc.txt
diff -N 0217-orinoco-Read-only-needed-data-in-__orinoco_ev_txexc.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0217-orinoco-Read-only-needed-data-in-__orinoco_ev_txexc.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,39 @@
+Subject: [PATCH] orinoco: Read only needed data in __orinoco_ev_txexc().
+From: Pavel Roskin <proski gnu org>
+Date: 1127463486 -0400
+
+Signed-off-by: Pavel Roskin <proski gnu org>
+
+Read only needed data in __orinoco_ev_txexc().
+
+Don't read the 802.11 header beyond addr1.  The rest of the frame is not
+used currently.
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/orinoco.c |    6 +++---
+ 1 files changed, 3 insertions(+), 3 deletions(-)
+
+applies-to: 4b292054c342e6e8c5b2594c62cbf3534eea1edf
+48ca703807eba616ad5e384b40e27514bd341a3d
+diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
+index 1ae301c..78afbc7 100644
+--- a/drivers/net/wireless/orinoco.c
++++ b/drivers/net/wireless/orinoco.c
+@@ -623,10 +623,10 @@ static void __orinoco_ev_txexc(struct ne
+ 	if (fid == DUMMY_FID)
+ 		return; /* Nothing's really happened */
+ 
+-	/* Read the frame header */
++	/* Read part of the frame header - we need status and addr1 */
+ 	err = hermes_bap_pread(hw, IRQ_BAP, &hdr,
+-			       sizeof(struct hermes_tx_descriptor) +
+-			       sizeof(struct ieee80211_hdr_4addr),
++			       offsetof(struct hermes_tx_descriptor_802_11,
++					addr2),
+ 			       fid, 0);
+ 
+ 	hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
+---
+0.99.8.GIT


Index: 0218-orinoco-Bump-version-to-0.15rc3.txt
===================================================================
RCS file: 0218-orinoco-Bump-version-to-0.15rc3.txt
diff -N 0218-orinoco-Bump-version-to-0.15rc3.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0218-orinoco-Bump-version-to-0.15rc3.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,31 @@
+Subject: [PATCH] orinoco: Bump version to 0.15rc3.
+From: Pavel Roskin <proski gnu org>
+Date: 1127463486 -0400
+
+Signed-off-by: Pavel Roskin <proski gnu org>
+
+Bump version to 0.15rc3.
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/orinoco.h |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+applies-to: ca4a41c2a653ff89ff1e713109e9afe4978a12e6
+acc4b985a6f8f22a0e826692894a4af234764001
+diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h
+index 6920ead..7a17bb3 100644
+--- a/drivers/net/wireless/orinoco.h
++++ b/drivers/net/wireless/orinoco.h
+@@ -7,7 +7,7 @@
+ #ifndef _ORINOCO_H
+ #define _ORINOCO_H
+ 
+-#define DRIVER_VERSION "0.15rc2"
++#define DRIVER_VERSION "0.15rc3"
+ 
+ #include <linux/netdevice.h>
+ #include <linux/wireless.h>
+---
+0.99.8.GIT


--- NEW FILE 0222-RPC-Report-connection-errors-properly-when-mounting-with-soft.txt ---
Subject: [PATCH] RPC: Report connection errors properly when mounting with "soft"
From: Chuck Lever <cel citi umich edu>
Date: 1123791908 -0400

 Fix up xprt_connect_status: the soft timeout logic was clobbering tk_status,
 so TCP connect errors were not properly reported on soft mounts.

 Test-plan:
 Destructive testing (unplugging the network temporarily).  Connectathon
 with UDP and TCP.

 Version: Thu, 11 Aug 2005 16:01:28 -0400

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 net/sunrpc/xprt.c |   27 ++++++++++++++++++---------
 1 files changed, 18 insertions(+), 9 deletions(-)

applies-to: 788749de63303b280155cd84c5a47434f029d6e0
23475d66bd8600e0c5353f86c1b74f68df27bdb5
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 3c654e0..b28ea0c 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -592,24 +592,33 @@ xprt_connect_status(struct rpc_task *tas
 		return;
 	}
 
-	/* if soft mounted, just cause this RPC to fail */
-	if (RPC_IS_SOFT(task))
-		task->tk_status = -EIO;
-
 	switch (task->tk_status) {
 	case -ECONNREFUSED:
 	case -ECONNRESET:
+		dprintk("RPC: %4d xprt_connect_status: server %s refused connection\n",
+				task->tk_pid, task->tk_client->cl_server);
+		break;
 	case -ENOTCONN:
-		return;
+		dprintk("RPC: %4d xprt_connect_status: connection broken\n",
+				task->tk_pid);
+		break;
 	case -ETIMEDOUT:
-		dprintk("RPC: %4d xprt_connect_status: timed out\n",
+		dprintk("RPC: %4d xprt_connect_status: connect attempt timed out\n",
 				task->tk_pid);
 		break;
 	default:
-		printk(KERN_ERR "RPC: error %d connecting to server %s\n",
-				-task->tk_status, task->tk_client->cl_server);
+		dprintk("RPC: %4d xprt_connect_status: error %d connecting to server %s\n",
+				task->tk_pid, -task->tk_status, task->tk_client->cl_server);
+		xprt_release_write(xprt, task);
+		task->tk_status = -EIO;
+		return;
+	}
+
+	/* if soft mounted, just cause this RPC to fail */
+	if (RPC_IS_SOFT(task)) {
+		xprt_release_write(xprt, task);
+		task->tk_status = -EIO;
 	}
-	xprt_release_write(xprt, task);
 }
 
 /*
---
0.99.8.GIT


--- NEW FILE 0223-RPC-proper-soft-timeout-behavior-for-rpcbind.txt ---
Subject: [PATCH] RPC: proper soft timeout behavior for rpcbind
From: Chuck Lever <cel citi umich edu>
Date: 1123791911 -0400

 Implement a best practice:  for soft mounts, an rpcbind timeout should
 cause an RPC request to fail.

 This also provides an FSM hook for retrying an rpcbind with a different
 rpcbind protocol version.  We'll use this later to try multiple rpcbind
 protocol versions when binding.  To enable this, expose the RPC error
 code returned during a portmap request to the FSM so it can make some
 decision about how to report, retry, or fail the request.

 Test-plan:
 Hundreds of passes with connectathon NFSv3 locking suite, on the client
 and server.

 Version: Thu, 11 Aug 2005 16:01:53 -0400

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 net/sunrpc/clnt.c |   99 ++++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 78 insertions(+), 21 deletions(-)

applies-to: 040565dacc08e99a86e2dd716b348f74e12e08db
da35187801732397a7e05fb9e77f3700cc35f5db
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index f17e615..2d3cf0a 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -53,6 +53,7 @@ static void	call_allocate(struct rpc_tas
 static void	call_encode(struct rpc_task *task);
 static void	call_decode(struct rpc_task *task);
 static void	call_bind(struct rpc_task *task);
+static void	call_bind_status(struct rpc_task *task);
 static void	call_transmit(struct rpc_task *task);
 static void	call_status(struct rpc_task *task);
 static void	call_refresh(struct rpc_task *task);
@@ -734,43 +735,94 @@ static void
 call_bind(struct rpc_task *task)
 {
 	struct rpc_clnt	*clnt = task->tk_client;
-	struct rpc_xprt *xprt = clnt->cl_xprt;
-
-	dprintk("RPC: %4d call_bind xprt %p %s connected\n", task->tk_pid,
-			xprt, (xprt_connected(xprt) ? "is" : "is not"));
 
-	task->tk_action = (xprt_connected(xprt)) ? call_transmit : call_connect;
+	dprintk("RPC: %4d call_bind (status %d)\n",
+				task->tk_pid, task->tk_status);
 
+	task->tk_action = call_connect;
 	if (!clnt->cl_port) {
-		task->tk_action = call_connect;
+		task->tk_action = call_bind_status;
 		task->tk_timeout = RPC_CONNECT_TIMEOUT;
 		rpc_getport(task, clnt);
 	}
 }
 
 /*
- * 4a.	Connect to the RPC server (TCP case)
+ * 4a.	Sort out bind result
  */
 static void
-call_connect(struct rpc_task *task)
+call_bind_status(struct rpc_task *task)
 {
-	struct rpc_clnt *clnt = task->tk_client;
+	int status = -EACCES;
 
-	dprintk("RPC: %4d call_connect status %d\n",
-				task->tk_pid, task->tk_status);
-
-	if (xprt_connected(clnt->cl_xprt)) {
-		task->tk_action = call_transmit;
+	if (task->tk_status >= 0) {
+		dprintk("RPC: %4d call_bind_status (status %d)\n",
+					task->tk_pid, task->tk_status);
+		task->tk_status = 0;
+		task->tk_action = call_connect;
 		return;
 	}
-	task->tk_action = call_connect_status;
-	if (task->tk_status < 0)
-		return;
-	xprt_connect(task);
+
+	switch (task->tk_status) {
+	case -EACCES:
+		dprintk("RPC: %4d remote rpcbind: RPC program/version unavailable\n",
+				task->tk_pid);
+		break;
+	case -ETIMEDOUT:
+		dprintk("RPC: %4d rpcbind request timed out\n",
+				task->tk_pid);
+		if (RPC_IS_SOFT(task)) {
+			status = -EIO;
+			break;
+		}
+		goto retry_bind;
+	case -EPFNOSUPPORT:
+		dprintk("RPC: %4d remote rpcbind service unavailable\n",
+				task->tk_pid);
+		break;
+	case -EPROTONOSUPPORT:
+		dprintk("RPC: %4d remote rpcbind version 2 unavailable\n",
+				task->tk_pid);
+		break;
+	default:
+		dprintk("RPC: %4d unrecognized rpcbind error (%d)\n",
+				task->tk_pid, -task->tk_status);
+		status = -EIO;
+		break;
+	}
+
+	rpc_exit(task, status);
+	return;
+
+retry_bind:
+	task->tk_status = 0;
+	task->tk_action = call_bind;
+	return;
+}
+
+/*
+ * 4b.	Connect to the RPC server
+ */
+static void
+call_connect(struct rpc_task *task)
+{
+	struct rpc_xprt *xprt = task->tk_xprt;
+
+	dprintk("RPC: %4d call_connect xprt %p %s connected\n",
+			task->tk_pid, xprt,
+			(xprt_connected(xprt) ? "is" : "is not"));
+
+	task->tk_action = call_transmit;
+	if (!xprt_connected(xprt)) {
+		task->tk_action = call_connect_status;
+		if (task->tk_status < 0)
+			return;
+		xprt_connect(task);
+	}
 }
 
 /*
- * 4b. Sort out connect result
+ * 4c.	Sort out connect result
  */
 static void
 call_connect_status(struct rpc_task *task)
@@ -778,6 +830,9 @@ call_connect_status(struct rpc_task *tas
 	struct rpc_clnt *clnt = task->tk_client;
 	int status = task->tk_status;
 
+	dprintk("RPC: %5u call_connect_status (status %d)\n", 
+				task->tk_pid, task->tk_status);
+
 	task->tk_status = 0;
 	if (status >= 0) {
 		clnt->cl_stats->netreconn++;
@@ -785,17 +840,19 @@ call_connect_status(struct rpc_task *tas
 		return;
 	}
 
-	/* Something failed: we may have to rebind */
+	/* Something failed: remote service port may have changed */
 	if (clnt->cl_autobind)
 		clnt->cl_port = 0;
+
 	switch (status) {
 	case -ENOTCONN:
 	case -ETIMEDOUT:
 	case -EAGAIN:
-		task->tk_action = (clnt->cl_port == 0) ? call_bind : call_connect;
+		task->tk_action = call_bind;
 		break;
 	default:
 		rpc_exit(task, -EIO);
+		break;
 	}
 }
 
---
0.99.8.GIT


--- NEW FILE 0224-NFS-use-a-constant-value-for-TCP-retransmit-timeouts.txt ---
Subject: [PATCH] NFS: use a constant value for TCP retransmit timeouts
From: Chuck Lever <cel citi umich edu>
Date: 1123791914 -0400

 Implement a best practice: don't use exponential backoff when computing
 retransmit timeout values on TCP connections, but simply retransmit
 at regular intervals.

 This also fixes a bug introduced when xprt_reset_majortimeo() was added.

 Test-plan:
 Enable RPC debugging and watch timeout behavior on a NFS/TCP mount.

 Version: Thu, 11 Aug 2005 16:02:19 -0400

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 fs/nfs/inode.c    |   73 +++++++++++++++++++++++++----------------------------
 net/sunrpc/xprt.c |    4 +--
 2 files changed, 37 insertions(+), 40 deletions(-)

applies-to: 61307975e36112fd85b98d0df824386e209a5049
eab5c084b858fd95a873fc2b97de9a9ad937b4ed
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 6922469..b6a1ca5 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -358,6 +358,35 @@ out_no_root:
 	return no_root_error;
 }
 
+static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, unsigned int timeo, unsigned int retrans)
+{
+	to->to_initval = timeo * HZ / 10;
+	to->to_retries = retrans;
+	if (!to->to_retries)
+		to->to_retries = 2;
+
+	switch (proto) {
+	case IPPROTO_TCP:
+		if (!to->to_initval)
+			to->to_initval = 60 * HZ;
+		if (to->to_initval > RPC_MAX_TCP_TIMEOUT)
+			to->to_initval = RPC_MAX_TCP_TIMEOUT;
+		to->to_increment = to->to_initval;
+		to->to_maxval = to->to_initval + (to->to_increment * to->to_retries);
+		to->to_exponential = 0;
+		break;
+	case IPPROTO_UDP:
+	default:
+		if (!to->to_initval)
+			to->to_initval = 11 * HZ / 10;
+		if (to->to_initval > RPC_MAX_UDP_TIMEOUT)
+			to->to_initval = RPC_MAX_UDP_TIMEOUT;
+		to->to_maxval = RPC_MAX_UDP_TIMEOUT;
+		to->to_exponential = 1;
+		break;
+	}
+}
+
 /*
  * Create an RPC client handle.
  */
@@ -367,22 +396,12 @@ nfs_create_client(struct nfs_server *ser
 	struct rpc_timeout	timeparms;
 	struct rpc_xprt		*xprt = NULL;
 	struct rpc_clnt		*clnt = NULL;
-	int			tcp   = (data->flags & NFS_MOUNT_TCP);
+	int			proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP;
 
-	/* Initialize timeout values */
-	timeparms.to_initval = data->timeo * HZ / 10;
-	timeparms.to_retries = data->retrans;
-	timeparms.to_maxval  = tcp ? RPC_MAX_TCP_TIMEOUT : RPC_MAX_UDP_TIMEOUT;
-	timeparms.to_exponential = 1;
-
-	if (!timeparms.to_initval)
-		timeparms.to_initval = (tcp ? 600 : 11) * HZ / 10;
-	if (!timeparms.to_retries)
-		timeparms.to_retries = 5;
+	nfs_init_timeout_values(&timeparms, proto, data->timeo, data->retrans);
 
 	/* create transport and client */
-	xprt = xprt_create_proto(tcp ? IPPROTO_TCP : IPPROTO_UDP,
-				 &server->addr, &timeparms);
+	xprt = xprt_create_proto(proto, &server->addr, &timeparms);
 	if (IS_ERR(xprt)) {
 		dprintk("%s: cannot create RPC transport. Error = %ld\n",
 				__FUNCTION__, PTR_ERR(xprt));
@@ -1674,7 +1693,7 @@ static int nfs4_fill_super(struct super_
 	struct rpc_clnt *clnt = NULL;
 	struct rpc_timeout timeparms;
 	rpc_authflavor_t authflavour;
-	int proto, err = -EIO;
+	int err = -EIO;
 
 	sb->s_blocksize_bits = 0;
 	sb->s_blocksize = 0;
@@ -1692,30 +1711,8 @@ static int nfs4_fill_super(struct super_
 	server->acdirmax = data->acdirmax*HZ;
 
 	server->rpc_ops = &nfs_v4_clientops;
-	/* Initialize timeout values */
-
-	timeparms.to_initval = data->timeo * HZ / 10;
-	timeparms.to_retries = data->retrans;
-	timeparms.to_exponential = 1;
-	if (!timeparms.to_retries)
-		timeparms.to_retries = 5;
 
-	proto = data->proto;
-	/* Which IP protocol do we use? */
-	switch (proto) {
-	case IPPROTO_TCP:
-		timeparms.to_maxval  = RPC_MAX_TCP_TIMEOUT;
-		if (!timeparms.to_initval)
-			timeparms.to_initval = 600 * HZ / 10;
-		break;
-	case IPPROTO_UDP:
-		timeparms.to_maxval  = RPC_MAX_UDP_TIMEOUT;
-		if (!timeparms.to_initval)
-			timeparms.to_initval = 11 * HZ / 10;
-		break;
-	default:
-		return -EINVAL;
-	}
+	nfs_init_timeout_values(&timeparms, data->proto, data->timeo, data->retrans);
 
 	clp = nfs4_get_client(&server->addr.sin_addr);
 	if (!clp) {
@@ -1740,7 +1737,7 @@ static int nfs4_fill_super(struct super_
 
 	down_write(&clp->cl_sem);
 	if (IS_ERR(clp->cl_rpcclient)) {
-		xprt = xprt_create_proto(proto, &server->addr, &timeparms);
+		xprt = xprt_create_proto(data->proto, &server->addr, &timeparms);
 		if (IS_ERR(xprt)) {
 			up_write(&clp->cl_sem);
 			err = PTR_ERR(xprt);
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index b28ea0c..0e4ffda 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -1453,7 +1453,7 @@ xprt_default_timeout(struct rpc_timeout 
 	if (proto == IPPROTO_UDP)
 		xprt_set_timeout(to, 5,  5 * HZ);
 	else
-		xprt_set_timeout(to, 5, 60 * HZ);
+		xprt_set_timeout(to, 2, 60 * HZ);
 }
 
 /*
@@ -1464,7 +1464,7 @@ xprt_set_timeout(struct rpc_timeout *to,
 {
 	to->to_initval   = 
 	to->to_increment = incr;
-	to->to_maxval    = incr * retr;
+	to->to_maxval    = to->to_initval + (incr * retr);
 	to->to_retries   = retr;
 	to->to_exponential = 0;
 }
---
0.99.8.GIT


--- NEW FILE 0225-RPC-portmapper-doesn-t-need-a-reserved-port.txt ---
Subject: [PATCH] RPC: portmapper doesn't need a reserved port
From: Chuck Lever <cel citi umich edu>
Date: 1123791917 -0400

 The in-kernel portmapper does not require a reserved port for making
 bind queries.

 Test-plan:
 Tens of runs of the Connectathon locking suite with TCP and UDP
 against several other NFS server implementations using NFSv3,
 not NFSv4 (which doesn't require rpcbind).

 Version: Thu, 11 Aug 2005 16:02:43 -0400

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 net/sunrpc/pmap_clnt.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

applies-to: 6ba8287570ecc83fed1512bd4901df979221c2ab
602f83273c89fdd25f24757564d8001cf723e740
diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c
index 4e81f27..d8e3f22 100644
--- a/net/sunrpc/pmap_clnt.c
+++ b/net/sunrpc/pmap_clnt.c
@@ -208,6 +208,7 @@ pmap_create(char *hostname, struct socka
 	if (IS_ERR(xprt))
 		return (struct rpc_clnt *)xprt;
 	xprt->addr.sin_port = htons(RPC_PMAP_PORT);
+	xprt->resvport = 0;
 
 	/* printk("pmap: create clnt\n"); */
 	clnt = rpc_new_client(xprt, hostname,
---
0.99.8.GIT


--- NEW FILE 0226-RPC-extract-socket-logic-common-to-both-client-and-server.txt ---
Subject: [PATCH] RPC: extract socket logic common to both client and server
From: Chuck Lever <cel citi umich edu>
Date: 1123791920 -0400

 Clean-up: Move some code that is common to both RPC client- and server-side
 socket transports into its own source file, net/sunrpc/socklib.c.

 Test-plan:
 Compile kernel with CONFIG_NFS enabled.  Millions of fsx operations over
 UDP, client and server.  Connectathon over UDP.

 Version: Thu, 11 Aug 2005 16:03:09 -0400

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/xdr.h |    1 
 net/sunrpc/Makefile        |    2 -
 net/sunrpc/socklib.c       |  175 ++++++++++++++++++++++++++++++++++++++++++++
 net/sunrpc/svcsock.c       |    3 -
 net/sunrpc/xdr.c           |   75 -------------------
 net/sunrpc/xprt.c          |   64 ----------------
 6 files changed, 177 insertions(+), 143 deletions(-)
 create mode 100644 net/sunrpc/socklib.c

applies-to: 5268f27e143907ca08d265fdbc49e9c5c89e914d
094bb20b9fcab3a1652a77741caba6b78097d622
diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
index 23448d0..d8b7656 100644
--- a/include/linux/sunrpc/xdr.h
+++ b/include/linux/sunrpc/xdr.h
@@ -161,6 +161,7 @@ typedef struct {
 
 typedef size_t (*skb_read_actor_t)(skb_reader_t *desc, void *to, size_t len);
 
+extern int csum_partial_copy_to_xdr(struct xdr_buf *, struct sk_buff *);
 extern ssize_t xdr_partial_copy_from_skb(struct xdr_buf *, unsigned int,
 		skb_reader_t *, skb_read_actor_t);
 
diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile
index 46a2ce0..f0a9556 100644
--- a/net/sunrpc/Makefile
+++ b/net/sunrpc/Makefile
@@ -6,7 +6,7 @@
 obj-$(CONFIG_SUNRPC) += sunrpc.o
 obj-$(CONFIG_SUNRPC_GSS) += auth_gss/
 
-sunrpc-y := clnt.o xprt.o sched.o \
+sunrpc-y := clnt.o xprt.o socklib.o sched.o \
 	    auth.o auth_null.o auth_unix.o \
 	    svc.o svcsock.o svcauth.o svcauth_unix.o \
 	    pmap_clnt.o timer.o xdr.o \
diff --git a/net/sunrpc/socklib.c b/net/sunrpc/socklib.c
new file mode 100644
index 0000000..8f97e90
--- /dev/null
+++ b/net/sunrpc/socklib.c
@@ -0,0 +1,175 @@
+/*
+ * linux/net/sunrpc/socklib.c
+ *
+ * Common socket helper routines for RPC client and server
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir monad swb de>
+ */
+
+#include <linux/types.h>
+#include <linux/pagemap.h>
+#include <linux/udp.h>
+#include <linux/sunrpc/xdr.h>
+
+
+/**
+ * skb_read_bits - copy some data bits from skb to internal buffer
+ * @desc: sk_buff copy helper
+ * @to: copy destination
+ * @len: number of bytes to copy
+ *
+ * Possibly called several times to iterate over an sk_buff and copy
+ * data out of it.
+ */
+static size_t skb_read_bits(skb_reader_t *desc, void *to, size_t len)
+{
+	if (len > desc->count)
+		len = desc->count;
+	if (skb_copy_bits(desc->skb, desc->offset, to, len))
+		return 0;
+	desc->count -= len;
+	desc->offset += len;
+	return len;
+}
+
+/**
+ * skb_read_and_csum_bits - copy and checksum from skb to buffer
+ * @desc: sk_buff copy helper
+ * @to: copy destination
+ * @len: number of bytes to copy
+ *
+ * Same as skb_read_bits, but calculate a checksum at the same time.
+ */
+static size_t skb_read_and_csum_bits(skb_reader_t *desc, void *to, size_t len)
+{
+	unsigned int	csum2, pos;
+
+	if (len > desc->count)
+		len = desc->count;
+	pos = desc->offset;
+	csum2 = skb_copy_and_csum_bits(desc->skb, pos, to, len, 0);
+	desc->csum = csum_block_add(desc->csum, csum2, pos);
+	desc->count -= len;
+	desc->offset += len;
+	return len;
+}
+
+/**
+ * xdr_partial_copy_from_skb - copy data out of an skb
+ * @xdr: target XDR buffer
+ * @base: starting offset
+ * @desc: sk_buff copy helper
+ * @copy_actor: virtual method for copying data
+ *
+ */
+ssize_t xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base, skb_reader_t *desc, skb_read_actor_t copy_actor)
+{
+	struct page	**ppage = xdr->pages;
+	unsigned int	len, pglen = xdr->page_len;
+	ssize_t		copied = 0;
+	int		ret;
+
+	len = xdr->head[0].iov_len;
+	if (base < len) {
+		len -= base;
+		ret = copy_actor(desc, (char *)xdr->head[0].iov_base + base, len);
+		copied += ret;
+		if (ret != len || !desc->count)
+			goto out;
+		base = 0;
+	} else
+		base -= len;
+
+	if (unlikely(pglen == 0))
+		goto copy_tail;
+	if (unlikely(base >= pglen)) {
+		base -= pglen;
+		goto copy_tail;
+	}
+	if (base || xdr->page_base) {
+		pglen -= base;
+		base += xdr->page_base;
+		ppage += base >> PAGE_CACHE_SHIFT;
+		base &= ~PAGE_CACHE_MASK;
+	}
+	do {
+		char *kaddr;
+
+		/* ACL likes to be lazy in allocating pages - ACLs
+		 * are small by default but can get huge. */
+		if (unlikely(*ppage == NULL)) {
+			*ppage = alloc_page(GFP_ATOMIC);
+			if (unlikely(*ppage == NULL)) {
+				if (copied == 0)
+					copied = -ENOMEM;
+				goto out;
+			}
+		}
+
+		len = PAGE_CACHE_SIZE;
+		kaddr = kmap_atomic(*ppage, KM_SKB_SUNRPC_DATA);
+		if (base) {
+			len -= base;
+			if (pglen < len)
+				len = pglen;
+			ret = copy_actor(desc, kaddr + base, len);
+			base = 0;
+		} else {
+			if (pglen < len)
+				len = pglen;
+			ret = copy_actor(desc, kaddr, len);
+		}
+		flush_dcache_page(*ppage);
+		kunmap_atomic(kaddr, KM_SKB_SUNRPC_DATA);
+		copied += ret;
+		if (ret != len || !desc->count)
+			goto out;
+		ppage++;
+	} while ((pglen -= len) != 0);
+copy_tail:
+	len = xdr->tail[0].iov_len;
+	if (base < len)
+		copied += copy_actor(desc, (char *)xdr->tail[0].iov_base + base, len - base);
+out:
+	return copied;
+}
+
+/**
+ * csum_partial_copy_to_xdr - checksum and copy data
+ * @xdr: target XDR buffer
+ * @skb: source skb
+ *
+ * We have set things up such that we perform the checksum of the UDP
+ * packet in parallel with the copies into the RPC client iovec.  -DaveM
+ */
+int csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
+{
+	skb_reader_t	desc;
+
+	desc.skb = skb;
+	desc.offset = sizeof(struct udphdr);
+	desc.count = skb->len - desc.offset;
+
+	if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+		goto no_checksum;
+
+	desc.csum = csum_partial(skb->data, desc.offset, skb->csum);
+	if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_and_csum_bits) < 0)
+		return -1;
+	if (desc.offset != skb->len) {
+		unsigned int csum2;
+		csum2 = skb_checksum(skb, desc.offset, skb->len - desc.offset, 0);
+		desc.csum = csum_block_add(desc.csum, csum2, desc.offset);
+	}
+	if (desc.count)
+		return -1;
+	if ((unsigned short)csum_fold(desc.csum))
+		return -1;
+	return 0;
+no_checksum:
+	if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_bits) < 0)
+		return -1;
+	if (desc.count)
+		return -1;
+	return 0;
+}
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 30ec3ef..130f2b5 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -548,9 +548,6 @@ svc_write_space(struct sock *sk)
 /*
  * Receive a datagram from a UDP socket.
  */
-extern int
-csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb);
-
 static int
 svc_udp_recvfrom(struct svc_rqst *rqstp)
 {
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
index fde16f4..9cc12ae 100644
--- a/net/sunrpc/xdr.c
+++ b/net/sunrpc/xdr.c
@@ -176,81 +176,6 @@ xdr_inline_pages(struct xdr_buf *xdr, un
 	xdr->buflen += len;
 }
 
-ssize_t
-xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base,
-			  skb_reader_t *desc,
-			  skb_read_actor_t copy_actor)
-{
-	struct page	**ppage = xdr->pages;
-	unsigned int	len, pglen = xdr->page_len;
-	ssize_t		copied = 0;
-	int		ret;
-
-	len = xdr->head[0].iov_len;
-	if (base < len) {
-		len -= base;
-		ret = copy_actor(desc, (char *)xdr->head[0].iov_base + base, len);
-		copied += ret;
-		if (ret != len || !desc->count)
-			goto out;
-		base = 0;
-	} else
-		base -= len;
-
-	if (pglen == 0)
-		goto copy_tail;
-	if (base >= pglen) {
-		base -= pglen;
-		goto copy_tail;
-	}
-	if (base || xdr->page_base) {
-		pglen -= base;
-		base  += xdr->page_base;
-		ppage += base >> PAGE_CACHE_SHIFT;
-		base &= ~PAGE_CACHE_MASK;
-	}
-	do {
-		char *kaddr;
-
-		/* ACL likes to be lazy in allocating pages - ACLs
-		 * are small by default but can get huge. */
-		if (unlikely(*ppage == NULL)) {
-			*ppage = alloc_page(GFP_ATOMIC);
-			if (unlikely(*ppage == NULL)) {
-				if (copied == 0)
-					copied = -ENOMEM;
-				goto out;
-			}
-		}
-
-		len = PAGE_CACHE_SIZE;
-		kaddr = kmap_atomic(*ppage, KM_SKB_SUNRPC_DATA);
-		if (base) {
-			len -= base;
-			if (pglen < len)
-				len = pglen;
-			ret = copy_actor(desc, kaddr + base, len);
-			base = 0;
-		} else {
-			if (pglen < len)
-				len = pglen;
-			ret = copy_actor(desc, kaddr, len);
-		}
-		flush_dcache_page(*ppage);
-		kunmap_atomic(kaddr, KM_SKB_SUNRPC_DATA);
-		copied += ret;
-		if (ret != len || !desc->count)
-			goto out;
-		ppage++;
-	} while ((pglen -= len) != 0);
-copy_tail:
-	len = xdr->tail[0].iov_len;
-	if (base < len)
-		copied += copy_actor(desc, (char *)xdr->tail[0].iov_base + base, len - base);
-out:
-	return copied;
-}
-
 
 int
 xdr_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 0e4ffda..67444f4 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -691,70 +691,6 @@ xprt_complete_rqst(struct rpc_xprt *xprt
 	return;
 }
 
-static size_t
-skb_read_bits(skb_reader_t *desc, void *to, size_t len)
-{
-	if (len > desc->count)
-		len = desc->count;
-	if (skb_copy_bits(desc->skb, desc->offset, to, len))
-		return 0;
-	desc->count -= len;
-	desc->offset += len;
-	return len;
-}
-
-static size_t
-skb_read_and_csum_bits(skb_reader_t *desc, void *to, size_t len)
-{
-	unsigned int csum2, pos;
-
-	if (len > desc->count)
-		len = desc->count;
-	pos = desc->offset;
-	csum2 = skb_copy_and_csum_bits(desc->skb, pos, to, len, 0);
-	desc->csum = csum_block_add(desc->csum, csum2, pos);
-	desc->count -= len;
-	desc->offset += len;
-	return len;
-}
-
-/*
- * We have set things up such that we perform the checksum of the UDP
- * packet in parallel with the copies into the RPC client iovec.  -DaveM
- */
-int
-csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
-{
-	skb_reader_t desc;
-
-	desc.skb = skb;
-	desc.offset = sizeof(struct udphdr);
-	desc.count = skb->len - desc.offset;
-
-	if (skb->ip_summed == CHECKSUM_UNNECESSARY)
-		goto no_checksum;
-
-	desc.csum = csum_partial(skb->data, desc.offset, skb->csum);
-	if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_and_csum_bits) < 0)
-		return -1;
-	if (desc.offset != skb->len) {
-		unsigned int csum2;
-		csum2 = skb_checksum(skb, desc.offset, skb->len - desc.offset, 0);
-		desc.csum = csum_block_add(desc.csum, csum2, desc.offset);
-	}
-	if (desc.count)
-		return -1;
-	if ((unsigned short)csum_fold(desc.csum))
-		return -1;
-	return 0;
-no_checksum:
-	if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_bits) < 0)
-		return -1;
-	if (desc.count)
-		return -1;
-	return 0;
-}
-
 /*
  * Input handler for RPC replies. Called from a bottom half and hence
  * atomic.
---
0.99.8.GIT


--- NEW FILE 0227-RPC-introduce-client-side-transport-switch.txt ---
Subject: [PATCH] RPC: introduce client-side transport switch
From: Chuck Lever <cel citi umich edu>
Date: 1123791923 -0400

 Move the bulk of client-side socket-specific code into a separate source
 file, net/sunrpc/xprtsock.c.

 Test-plan:
 Millions of fsx operations.  Performance characterization such as "sio" or
 "iozone".  Destructive testing (unplugging the network temporarily, server
 reboots).  Connectathon with v2, v3, and v4.

 Version: Thu, 11 Aug 2005 16:03:38 -0400

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/xdr.h  |    5 
 include/linux/sunrpc/xprt.h |   38 +-
 net/sunrpc/Makefile         |    2 
 net/sunrpc/clnt.c           |    3 
 net/sunrpc/sysctl.c         |    3 
 net/sunrpc/xdr.c            |  102 ----
 net/sunrpc/xprt.c           |  918 ++-------------------------------------
 net/sunrpc/xprtsock.c       | 1021 +++++++++++++++++++++++++++++++++++++++++++
 8 files changed, 1102 insertions(+), 990 deletions(-)
 create mode 100644 net/sunrpc/xprtsock.c

applies-to: 85347e557be116ed1fa8bbf63555fcb83920baf5
a246b0105bbd9a70a698f69baae2042996f2a0e9
diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
index d8b7656..5da9687 100644
--- a/include/linux/sunrpc/xdr.h
+++ b/include/linux/sunrpc/xdr.h
@@ -165,11 +165,6 @@ extern int csum_partial_copy_to_xdr(stru
 extern ssize_t xdr_partial_copy_from_skb(struct xdr_buf *, unsigned int,
 		skb_reader_t *, skb_read_actor_t);
 
-struct socket;
-struct sockaddr;
-extern int xdr_sendpages(struct socket *, struct sockaddr *, int,
-		struct xdr_buf *, unsigned int, int);
-
 extern int xdr_encode_word(struct xdr_buf *, int, u32);
 extern int xdr_decode_word(struct xdr_buf *, int, u32 *);
 
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index e618c16..d82b47a 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -59,7 +59,13 @@ extern unsigned int xprt_tcp_slot_table_
  */
 #define RPC_REESTABLISH_TIMEOUT	(15*HZ)
 
-/* RPC call and reply header size as number of 32bit words (verifier
+/*
+ * RPC transport idle timeout.
+ */
+#define RPC_IDLE_DISCONNECT_TIMEOUT	(5*60*HZ)
+
+/*
+ * RPC call and reply header size as number of 32bit words (verifier
  * size computed separately)
  */
 #define RPC_CALLHDRSIZE		6
@@ -121,12 +127,19 @@ struct rpc_rqst {
 #define rq_svec			rq_snd_buf.head
 #define rq_slen			rq_snd_buf.len
 
-#define XPRT_LAST_FRAG		(1 << 0)
-#define XPRT_COPY_RECM		(1 << 1)
-#define XPRT_COPY_XID		(1 << 2)
-#define XPRT_COPY_DATA		(1 << 3)
+struct rpc_task;
+struct rpc_xprt;
+
+struct rpc_xprt_ops {
+	void		(*set_buffer_size)(struct rpc_xprt *xprt);
+	void		(*connect)(struct rpc_task *task);
+	int		(*send_request)(struct rpc_task *task);
+	void		(*close)(struct rpc_xprt *xprt);
+	void		(*destroy)(struct rpc_xprt *xprt);
+};
 
 struct rpc_xprt {
+	struct rpc_xprt_ops *	ops;		/* transport methods */
 	struct socket *		sock;		/* BSD socket layer */
 	struct sock *		inet;		/* INET layer */
 
@@ -199,14 +212,22 @@ struct rpc_xprt {
 	wait_queue_head_t	cong_wait;
 };
 
+#define XPRT_LAST_FRAG		(1 << 0)
+#define XPRT_COPY_RECM		(1 << 1)
+#define XPRT_COPY_XID		(1 << 2)
+#define XPRT_COPY_DATA		(1 << 3)
+
 #ifdef __KERNEL__
 
 struct rpc_xprt *	xprt_create_proto(int proto, struct sockaddr_in *addr,
 					struct rpc_timeout *toparms);
+void			xprt_disconnect(struct rpc_xprt *);
 int			xprt_destroy(struct rpc_xprt *);
 void			xprt_set_timeout(struct rpc_timeout *, unsigned int,
 					unsigned long);
-
+struct rpc_rqst *	xprt_lookup_rqst(struct rpc_xprt *, u32);
+void			xprt_complete_rqst(struct rpc_xprt *,
+					struct rpc_rqst *, int);
 void			xprt_reserve(struct rpc_task *);
 int			xprt_prepare_transmit(struct rpc_task *);
 void			xprt_transmit(struct rpc_task *);
@@ -214,7 +235,10 @@ void			xprt_receive(struct rpc_task *);
 int			xprt_adjust_timeout(struct rpc_rqst *req);
 void			xprt_release(struct rpc_task *);
 void			xprt_connect(struct rpc_task *);
-void			xprt_sock_setbufsize(struct rpc_xprt *);
+int			xs_setup_udp(struct rpc_xprt *,
+					struct rpc_timeout *);
+int			xs_setup_tcp(struct rpc_xprt *,
+					struct rpc_timeout *);
 
 #define XPRT_LOCKED	0
 #define XPRT_CONNECT	1
diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile
index f0a9556..cdcab9c 100644
--- a/net/sunrpc/Makefile
+++ b/net/sunrpc/Makefile
@@ -6,7 +6,7 @@
 obj-$(CONFIG_SUNRPC) += sunrpc.o
 obj-$(CONFIG_SUNRPC_GSS) += auth_gss/
 
-sunrpc-y := clnt.o xprt.o socklib.o sched.o \
+sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \
 	    auth.o auth_null.o auth_unix.o \
 	    svc.o svcsock.o svcauth.o svcauth_unix.o \
 	    pmap_clnt.o timer.o xdr.o \
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 2d3cf0a..ab50c3c 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -525,8 +525,7 @@ rpc_setbufsize(struct rpc_clnt *clnt, un
 	xprt->rcvsize = 0;
 	if (rcvsize)
 		xprt->rcvsize = rcvsize + RPC_SLACK_SPACE;
-	if (xprt_connected(xprt))
-		xprt_sock_setbufsize(xprt);
+	xprt->ops->set_buffer_size(xprt);
 }
 
 /*
diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c
index 1b9616a..ef48326 100644
--- a/net/sunrpc/sysctl.c
+++ b/net/sunrpc/sysctl.c
@@ -119,6 +119,9 @@ done:
 	return 0;
 }
 
+unsigned int xprt_udp_slot_table_entries = RPC_DEF_SLOT_TABLE;
+unsigned int xprt_tcp_slot_table_entries = RPC_DEF_SLOT_TABLE;
+
 static unsigned int min_slot_table_size = RPC_MIN_SLOT_TABLE;
 static unsigned int max_slot_table_size = RPC_MAX_SLOT_TABLE;
 
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
index 9cc12ae..32df433 100644
--- a/net/sunrpc/xdr.c
+++ b/net/sunrpc/xdr.c
@@ -6,15 +6,12 @@
  * Copyright (C) 1995, 1996 Olaf Kirch <okir monad swb de>
  */
 
+#include <linux/module.h>
 #include <linux/types.h>
-#include <linux/socket.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/pagemap.h>
 #include <linux/errno.h>
-#include <linux/in.h>
-#include <linux/net.h>
-#include <net/sock.h>
 #include <linux/sunrpc/xdr.h>
 #include <linux/sunrpc/msg_prot.h>
 
@@ -177,103 +174,6 @@ xdr_inline_pages(struct xdr_buf *xdr, un
 }
 
 
-int
-xdr_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
-		struct xdr_buf *xdr, unsigned int base, int msgflags)
-{
-	struct page **ppage = xdr->pages;
-	unsigned int len, pglen = xdr->page_len;
[...2045 lines suppressed...]
+
+	return;
+}
+
+/*
+ * Datastream sockets are created here, but xprt_connect will create
+ * and connect stream sockets.
+ */
+static struct socket * xprt_create_socket(struct rpc_xprt *xprt, int proto, int resvport)
+{
+	struct socket	*sock;
+	int		type, err;
+
+	dprintk("RPC:      xprt_create_socket(%s %d)\n",
+			   (proto == IPPROTO_UDP)? "udp" : "tcp", proto);
+
+	type = (proto == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
+
+	if ((err = sock_create_kern(PF_INET, type, proto, &sock)) < 0) {
+		printk("RPC: can't create socket (%d).\n", -err);
+		return NULL;
+	}
+
+	/* If the caller has the capability, bind to a reserved port */
+	if (resvport && xprt_bindresvport(xprt, sock) < 0) {
+		printk("RPC: can't bind to reserved port.\n");
+		goto failed;
+	}
+
+	return sock;
+
+failed:
+	sock_release(sock);
+	return NULL;
+}
+
+static void xprt_socket_connect(void *args)
+{
+	struct rpc_xprt *xprt = (struct rpc_xprt *)args;
+	struct socket *sock = xprt->sock;
+	int status = -EIO;
+
+	if (xprt->shutdown || xprt->addr.sin_port == 0)
+		goto out;
+
+	/*
+	 * Start by resetting any existing state
+	 */
+	xprt_close(xprt);
+	sock = xprt_create_socket(xprt, xprt->prot, xprt->resvport);
+	if (sock == NULL) {
+		/* couldn't create socket or bind to reserved port;
+		 * this is likely a permanent error, so cause an abort */
+		goto out;
+	}
+	xprt_bind_socket(xprt, sock);
+	xprt_sock_setbufsize(xprt);
+
+	status = 0;
+	if (!xprt->stream)
+		goto out;
+
+	/*
+	 * Tell the socket layer to start connecting...
+	 */
+	status = sock->ops->connect(sock, (struct sockaddr *) &xprt->addr,
+			sizeof(xprt->addr), O_NONBLOCK);
+	dprintk("RPC: %p  connect status %d connected %d sock state %d\n",
+			xprt, -status, xprt_connected(xprt), sock->sk->sk_state);
+	if (status < 0) {
+		switch (status) {
+			case -EINPROGRESS:
+			case -EALREADY:
+				goto out_clear;
+		}
+	}
+out:
+	if (status < 0)
+		rpc_wake_up_status(&xprt->pending, status);
+	else
+		rpc_wake_up(&xprt->pending);
+out_clear:
+	smp_mb__before_clear_bit();
+	clear_bit(XPRT_CONNECTING, &xprt->sockstate);
+	smp_mb__after_clear_bit();
+}
+
+static void
+xprt_connect_sock(struct rpc_task *task)
+{
+	struct rpc_xprt *xprt = task->tk_xprt;
+
+	if (!test_and_set_bit(XPRT_CONNECTING, &xprt->sockstate)) {
+		/* Note: if we are here due to a dropped connection
+		 * 	 we delay reconnecting by RPC_REESTABLISH_TIMEOUT/HZ
+		 * 	 seconds
+		 */
+		if (xprt->sock != NULL)
+			schedule_delayed_work(&xprt->sock_connect,
+					RPC_REESTABLISH_TIMEOUT);
+		else {
+			schedule_work(&xprt->sock_connect);
+			/* flush_scheduled_work can sleep... */
+			if (!RPC_IS_ASYNC(task))
+				flush_scheduled_work();
+		}
+	}
+}
+
+/*
+ * Set default timeout parameters
+ */
+static void
+xprt_default_timeout(struct rpc_timeout *to, int proto)
+{
+	if (proto == IPPROTO_UDP)
+		xprt_set_timeout(to, 5,  5 * HZ);
+	else
+		xprt_set_timeout(to, 2, 60 * HZ);
+}
+
+static struct rpc_xprt_ops xprt_socket_ops = {
+	.set_buffer_size	= xprt_sock_setbufsize,
+	.connect		= xprt_connect_sock,
+	.send_request		= xprt_send_request,
+	.close			= xprt_close,
+	.destroy		= xprt_socket_destroy,
+};
+
+extern unsigned int xprt_udp_slot_table_entries;
+extern unsigned int xprt_tcp_slot_table_entries;
+
+int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to)
+{
+	size_t slot_table_size;
+
+	dprintk("RPC:      setting up udp-ipv4 transport...\n");
+
+	xprt->max_reqs = xprt_udp_slot_table_entries;
+	slot_table_size = xprt->max_reqs * sizeof(xprt->slot[0]);
+	xprt->slot = kmalloc(slot_table_size, GFP_KERNEL);
+	if (xprt->slot == NULL)
+		return -ENOMEM;
+	memset(xprt->slot, 0, slot_table_size);
+
+	xprt->prot = IPPROTO_UDP;
+	xprt->port = XPRT_MAX_RESVPORT;
+	xprt->stream = 0;
+	xprt->nocong = 0;
+	xprt->cwnd = RPC_INITCWND;
+	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
+	/* XXX: header size can vary due to auth type, IPv6, etc. */
+	xprt->max_payload = (1U << 16) - (MAX_HEADER << 3);
+
+	INIT_WORK(&xprt->sock_connect, xprt_socket_connect, xprt);
+
+	xprt->ops = &xprt_socket_ops;
+
+	if (to)
+		xprt->timeout = *to;
+	else
+		xprt_default_timeout(to, xprt->prot);
+
+	return 0;
+}
+
+int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to)
+{
+	size_t slot_table_size;
+
+	dprintk("RPC:      setting up tcp-ipv4 transport...\n");
+
+	xprt->max_reqs = xprt_tcp_slot_table_entries;
+	slot_table_size = xprt->max_reqs * sizeof(xprt->slot[0]);
+	xprt->slot = kmalloc(slot_table_size, GFP_KERNEL);
+	if (xprt->slot == NULL)
+		return -ENOMEM;
+	memset(xprt->slot, 0, slot_table_size);
+
+	xprt->prot = IPPROTO_TCP;
+	xprt->port = XPRT_MAX_RESVPORT;
+	xprt->stream = 1;
+	xprt->nocong = 1;
+	xprt->cwnd = RPC_MAXCWND(xprt);
+	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
+	xprt->max_payload = (1U << 31) - 1;
+
+	INIT_WORK(&xprt->sock_connect, xprt_socket_connect, xprt);
+
+	xprt->ops = &xprt_socket_ops;
+
+	if (to)
+		xprt->timeout = *to;
+	else
+		xprt_default_timeout(to, xprt->prot);
+
+	return 0;
+}
---
0.99.8.GIT


--- NEW FILE 0228-RPC-transport-switch-function-naming.txt ---
Subject: [PATCH] RPC: transport switch function naming
From: Chuck Lever <cel citi umich edu>
Date: 1123791926 -0400

 Introduce block header comments and a function naming convention to the
 socket transport implementation.  Provide a debug setting for transports
 that is separate from RPCDBG_XPRT.  Eliminate xprt_default_timeout().

 Provide block comments for exposed interfaces in xprt.c, and eliminate
 the useless obvious comments.

 Convert printk's to dprintk's.

 Test-plan:
 Compile kernel with CONFIG_NFS enabled.

 Version: Thu, 11 Aug 2005 16:04:04 -0400

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/debug.h |    1 
 net/sunrpc/xprt.c            |  147 +++++++------
 net/sunrpc/xprtsock.c        |  464 ++++++++++++++++++++++--------------------
 3 files changed, 311 insertions(+), 301 deletions(-)

applies-to: 6c8831d8579a7fdc5201d3e9c20270cb1420eeda
9903cd1c27a1f30e8efea75e125be3b2002f7cb9
diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
index eadb31e..42d2997 100644
--- a/include/linux/sunrpc/debug.h
+++ b/include/linux/sunrpc/debug.h
@@ -32,6 +32,7 @@
 #define RPCDBG_AUTH		0x0010
 #define RPCDBG_PMAP		0x0020
 #define RPCDBG_SCHED		0x0040
+#define RPCDBG_TRANS		0x0080
 #define RPCDBG_SVCSOCK		0x0100
 #define RPCDBG_SVCDSP		0x0200
 #define RPCDBG_MISC		0x0400
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 4342acf..589195e 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -227,9 +227,6 @@ xprt_adjust_cwnd(struct rpc_xprt *xprt, 
 	xprt->cwnd = cwnd;
 }
 
-/*
- * Reset the major timeout value
- */
 static void xprt_reset_majortimeo(struct rpc_rqst *req)
 {
 	struct rpc_timeout *to = &req->rq_xprt->timeout;
@@ -244,8 +241,10 @@ static void xprt_reset_majortimeo(struct
 	req->rq_majortimeo += jiffies;
 }
 
-/*
- * Adjust timeout values etc for next retransmit
+/**
+ * xprt_adjust_timeout - adjust timeout values for next retransmit
+ * @req: RPC request containing parameters to use for the adjustment
+ *
  */
 int xprt_adjust_timeout(struct rpc_rqst *req)
 {
@@ -291,8 +290,10 @@ xprt_socket_autoclose(void *args)
 	xprt_release_write(xprt, NULL);
 }
 
-/*
- * Mark a transport as disconnected
+/**
+ * xprt_disconnect - mark a transport as disconnected
+ * @xprt: transport to flag for disconnect
+ *
  */
 void xprt_disconnect(struct rpc_xprt *xprt)
 {
@@ -303,9 +304,6 @@ void xprt_disconnect(struct rpc_xprt *xp
 	spin_unlock_bh(&xprt->sock_lock);
 }
 
-/*
- * Used to allow disconnection when we've been idle
- */
 static void
 xprt_init_autodisconnect(unsigned long data)
 {
@@ -327,8 +325,9 @@ out_abort:
 	spin_unlock(&xprt->sock_lock);
 }
 
-/*
- * Attempt to connect a TCP socket.
+/**
+ * xprt_connect - schedule a transport connect operation
+ * @task: RPC task that is requesting the connect
  *
  */
 void xprt_connect(struct rpc_task *task)
@@ -361,11 +360,7 @@ void xprt_connect(struct rpc_task *task)
 	return;
 }
 
-/*
- * We arrive here when awoken from waiting on connection establishment.
- */
-static void
-xprt_connect_status(struct rpc_task *task)
+static void xprt_connect_status(struct rpc_task *task)
 {
 	struct rpc_xprt	*xprt = task->tk_xprt;
 
@@ -404,8 +399,11 @@ xprt_connect_status(struct rpc_task *tas
 	}
 }
 
-/*
- * Look up the RPC request corresponding to a reply, and then lock it.
+/**
+ * xprt_lookup_rqst - find an RPC request corresponding to an XID
+ * @xprt: transport on which the original request was transmitted
+ * @xid: RPC XID of incoming reply
+ *
  */
 struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid)
 {
@@ -422,9 +420,12 @@ struct rpc_rqst *xprt_lookup_rqst(struct
 	return req;
 }
 
-/*
- * Complete reply received.
- * The TCP code relies on us to remove the request from xprt->pending.
+/**
+ * xprt_complete_rqst - called when reply processing is complete
+ * @xprt: controlling transport
+ * @req: RPC request that just completed
+ * @copied: actual number of bytes received from the transport
+ *
  */
 void xprt_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied)
 {
@@ -498,12 +499,12 @@ out:
 	spin_unlock(&xprt->sock_lock);
 }
 
-/*
- * Place the actual RPC call.
- * We have to copy the iovec because sendmsg fiddles with its contents.
+/**
+ * xprt_prepare_transmit - reserve the transport before sending a request
+ * @task: RPC task about to send a request
+ *
  */
-int
-xprt_prepare_transmit(struct rpc_task *task)
+int xprt_prepare_transmit(struct rpc_task *task)
 {
 	struct rpc_rqst	*req = task->tk_rqstp;
 	struct rpc_xprt	*xprt = req->rq_xprt;
@@ -533,8 +534,13 @@ out_unlock:
 	return err;
 }
 
-void
-xprt_transmit(struct rpc_task *task)
+/**
+ * xprt_transmit - send an RPC request on a transport
+ * @task: controlling RPC task
+ *
+ * We have to copy the iovec because sendmsg fiddles with its contents.
+ */
+void xprt_transmit(struct rpc_task *task)
 {
 	struct rpc_clnt *clnt = task->tk_client;
 	struct rpc_rqst	*req = task->tk_rqstp;
@@ -604,11 +610,7 @@ xprt_transmit(struct rpc_task *task)
 	spin_unlock_bh(&xprt->sock_lock);
 }
 
-/*
- * Reserve an RPC call slot.
- */
-static inline void
-do_xprt_reserve(struct rpc_task *task)
+static inline void do_xprt_reserve(struct rpc_task *task)
 {
 	struct rpc_xprt	*xprt = task->tk_xprt;
 
@@ -628,8 +630,14 @@ do_xprt_reserve(struct rpc_task *task)
 	rpc_sleep_on(&xprt->backlog, task, NULL, NULL);
 }
 
-void
-xprt_reserve(struct rpc_task *task)
+/**
+ * xprt_reserve - allocate an RPC request slot
+ * @task: RPC task requesting a slot allocation
+ *
+ * If no more slots are available, place the task on the transport's
+ * backlog queue.
+ */
+void xprt_reserve(struct rpc_task *task)
 {
 	struct rpc_xprt	*xprt = task->tk_xprt;
 
@@ -641,9 +649,6 @@ xprt_reserve(struct rpc_task *task)
 	}
 }
 
-/*
- * Allocate a 'unique' XID
- */
 static inline u32 xprt_alloc_xid(struct rpc_xprt *xprt)
 {
 	return xprt->xid++;
@@ -654,11 +659,7 @@ static inline void xprt_init_xid(struct 
 	get_random_bytes(&xprt->xid, sizeof(xprt->xid));
 }
 
-/*
- * Initialize RPC request
- */
-static void
-xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
+static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
 {
 	struct rpc_rqst	*req = task->tk_rqstp;
 
@@ -670,11 +671,12 @@ xprt_request_init(struct rpc_task *task,
 			req, ntohl(req->rq_xid));
 }
 
-/*
- * Release an RPC call slot
+/**
+ * xprt_release - release an RPC request slot
+ * @task: task which is finished with the slot
+ *
  */
-void
-xprt_release(struct rpc_task *task)
+void xprt_release(struct rpc_task *task)
 {
 	struct rpc_xprt	*xprt = task->tk_xprt;
 	struct rpc_rqst	*req;
@@ -702,11 +704,14 @@ xprt_release(struct rpc_task *task)
 	spin_unlock(&xprt->xprt_lock);
 }
 
-/*
- * Set constant timeout
+/**
+ * xprt_set_timeout - set constant RPC timeout
+ * @to: RPC timeout parameters to set up
+ * @retr: number of retries
+ * @incr: amount of increase after each retry
+ *
  */
-void
-xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr)
+void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr)
 {
 	to->to_initval   = 
 	to->to_increment = incr;
@@ -715,11 +720,7 @@ xprt_set_timeout(struct rpc_timeout *to,
 	to->to_exponential = 0;
 }
 
-/*
- * Initialize an RPC client
- */
-static struct rpc_xprt *
-xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to)
+static struct rpc_xprt *xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to)
 {
 	int result;
 	struct rpc_xprt	*xprt;
@@ -778,11 +779,14 @@ xprt_setup(int proto, struct sockaddr_in
 	return xprt;
 }
 
-/*
- * Create an RPC client transport given the protocol and peer address.
+/**
+ * xprt_create_proto - create an RPC client transport
+ * @proto: requested transport protocol
+ * @sap: remote peer's address
+ * @to: timeout parameters for new transport
+ *
  */
-struct rpc_xprt *
-xprt_create_proto(int proto, struct sockaddr_in *sap, struct rpc_timeout *to)
+struct rpc_xprt *xprt_create_proto(int proto, struct sockaddr_in *sap, struct rpc_timeout *to)
 {
 	struct rpc_xprt	*xprt;
 
@@ -794,11 +798,7 @@ xprt_create_proto(int proto, struct sock
 	return xprt;
 }
 
-/*
- * Prepare for transport shutdown.
- */
-static void
-xprt_shutdown(struct rpc_xprt *xprt)
+static void xprt_shutdown(struct rpc_xprt *xprt)
 {
 	xprt->shutdown = 1;
 	rpc_wake_up(&xprt->sending);
@@ -809,21 +809,18 @@ xprt_shutdown(struct rpc_xprt *xprt)
 	del_timer_sync(&xprt->timer);
 }
 
-/*
- * Clear the xprt backlog queue
- */
-static int
-xprt_clear_backlog(struct rpc_xprt *xprt) {
+static int xprt_clear_backlog(struct rpc_xprt *xprt) {
 	rpc_wake_up_next(&xprt->backlog);
 	wake_up(&xprt->cong_wait);
 	return 1;
 }
 
-/*
- * Destroy an RPC transport, killing off all requests.
+/**
+ * xprt_destroy - destroy an RPC transport, killing off all requests.
+ * @xprt: transport to destroy
+ *
  */
-int
-xprt_destroy(struct rpc_xprt *xprt)
+int xprt_destroy(struct rpc_xprt *xprt)
 {
 	dprintk("RPC:      destroying transport %p\n", xprt);
 	xprt_shutdown(xprt);
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index fa1180a..80222de 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -33,23 +33,21 @@
 #include <net/udp.h>
 #include <net/tcp.h>
 
+/*
+ * Maximum port number to use when requesting a reserved port.
+ */
+#define XS_MAX_RESVPORT		(800U)
+
 #ifdef RPC_DEBUG
 # undef  RPC_DEBUG_DATA
-# define RPCDBG_FACILITY	RPCDBG_XPRT
+# define RPCDBG_FACILITY	RPCDBG_TRANS
 #endif
 
-#define XPRT_MAX_RESVPORT	(800)
-
 #ifdef RPC_DEBUG_DATA
-/*
- * Print the buffer contents (first 128 bytes only--just enough for
- * diropres return).
- */
-static void
-xprt_pktdump(char *msg, u32 *packet, unsigned int count)
+static void xs_pktdump(char *msg, u32 *packet, unsigned int count)
 {
-	u8	*buf = (u8 *) packet;
-	int	j;
+	u8 *buf = (u8 *) packet;
+	int j;
 
 	dprintk("RPC:      %s\n", msg);
 	for (j = 0; j < count && j < 128; j += 4) {
@@ -64,25 +62,22 @@ xprt_pktdump(char *msg, u32 *packet, uns
 	dprintk("\n");
 }
 #else
-static inline void
-xprt_pktdump(char *msg, u32 *packet, unsigned int count)
+static inline void xs_pktdump(char *msg, u32 *packet, unsigned int count)
 {
 	/* NOP */
 }
 #endif
 
-/*
- * Look up RPC transport given an INET socket
+/**
+ * xs_sendpages - write pages directly to a socket
+ * @sock: socket to send on
+ * @addr: UDP only -- address of destination
+ * @addrlen: UDP only -- length of destination address
+ * @xdr: buffer containing this request
+ * @base: starting position in the buffer
+ *
  */
-static inline struct rpc_xprt *
-xprt_from_sock(struct sock *sk)
-{
-	return (struct rpc_xprt *) sk->sk_user_data;
-}
-
-static int
-xdr_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
-		struct xdr_buf *xdr, unsigned int base, int msgflags)
+static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, int msgflags)
 {
 	struct page **ppage = xdr->pages;
 	unsigned int len, pglen = xdr->page_len;
@@ -125,7 +120,7 @@ xdr_sendpages(struct socket *sock, struc
 	}
 	if (base || xdr->page_base) {
 		pglen -= base;
-		base  += xdr->page_base;
+		base += xdr->page_base;
 		ppage += base >> PAGE_CACHE_SHIFT;
 		base &= ~PAGE_CACHE_MASK;
 	}
@@ -176,23 +171,25 @@ out:
 	return ret;
 }
 
-/*
- * Write data to socket.
+/**
+ * xs_sendmsg - write an RPC request to a socket
+ * @xprt: generic transport
+ * @req: the RPC request to write
+ *
  */
-static inline int
-xprt_sendmsg(struct rpc_xprt *xprt, struct rpc_rqst *req)
+static int xs_sendmsg(struct rpc_xprt *xprt, struct rpc_rqst *req)
 {
-	struct socket	*sock = xprt->sock;
-	struct xdr_buf	*xdr = &req->rq_snd_buf;
+	struct socket *sock = xprt->sock;
+	struct xdr_buf *xdr = &req->rq_snd_buf;
 	struct sockaddr *addr = NULL;
 	int addrlen = 0;
-	unsigned int	skip;
-	int		result;
+	unsigned int skip;
+	int result;
 
 	if (!sock)
 		return -ENOTCONN;
 
-	xprt_pktdump("packet data:";,
+	xs_pktdump("packet data:";,
 				req->rq_svec->iov_base,
 				req->rq_svec->iov_len);
 
@@ -201,13 +198,13 @@ xprt_sendmsg(struct rpc_xprt *xprt, stru
 		addr = (struct sockaddr *) &xprt->addr;
 		addrlen = sizeof(xprt->addr);
 	}
-	/* Dont repeat bytes */
+	/* Don't repeat bytes */
 	skip = req->rq_bytes_sent;
 
 	clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
-	result = xdr_sendpages(sock, addr, addrlen, xdr, skip, MSG_DONTWAIT);
+	result = xs_sendpages(sock, addr, addrlen, xdr, skip, MSG_DONTWAIT);
 
-	dprintk("RPC:      xprt_sendmsg(%d) = %d\n", xdr->len - skip, result);
+	dprintk("RPC:      xs_sendmsg(%d) = %d\n", xdr->len - skip, result);
 
 	if (result >= 0)
 		return result;
@@ -215,8 +212,7 @@ xprt_sendmsg(struct rpc_xprt *xprt, stru
 	switch (result) {
 	case -ECONNREFUSED:
 		/* When the server has died, an ICMP port unreachable message
-		 * prompts ECONNREFUSED.
-		 */
+		 * prompts ECONNREFUSED. */
 	case -EAGAIN:
 		break;
 	case -ECONNRESET:
@@ -227,13 +223,25 @@ xprt_sendmsg(struct rpc_xprt *xprt, stru
 			result = -ENOTCONN;
 		break;
 	default:
-		printk(KERN_NOTICE "RPC: sendmsg returned error %d\n", -result);
+		break;
 	}
 	return result;
 }
 
-static int
-xprt_send_request(struct rpc_task *task)
+/**
+ * xs_send_request - write an RPC request to a socket
+ * @task: address of RPC task that manages the state of an RPC request
+ *
+ * Return values:
+ *      0:  The request has been sent
+ * EAGAIN:  The socket was blocked, please call again later to
+ *          complete the request
+ *  other:  Some other error occured, the request was not sent
+ *
+ * XXX: In the case of soft timeouts, should we eventually give up
+ *      if the socket is not able to make progress?
+ */
+static int xs_send_request(struct rpc_task *task)
 {
 	struct rpc_rqst *req = task->tk_rqstp;
 	struct rpc_xprt *xprt = req->rq_xprt;
@@ -242,18 +250,18 @@ xprt_send_request(struct rpc_task *task)
 	/* set up everything as needed. */
 	/* Write the record marker */
 	if (xprt->stream) {
-		u32	*marker = req->rq_svec[0].iov_base;
+		u32 *marker = req->rq_svec[0].iov_base;
 
 		*marker = htonl(0x80000000|(req->rq_slen-sizeof(*marker)));
 	}
 
 	/* Continue transmitting the packet/record. We must be careful
 	 * to cope with writespace callbacks arriving _after_ we have
-	 * called xprt_sendmsg().
+	 * called sendmsg().
 	 */
 	while (1) {
 		req->rq_xtime = jiffies;
-		status = xprt_sendmsg(xprt, req);
+		status = xs_sendmsg(xprt, req);
 
 		if (status < 0)
 			break;
@@ -285,7 +293,7 @@ xprt_send_request(struct rpc_task *task)
 
 	if (status == -EAGAIN) {
 		if (test_bit(SOCK_ASYNC_NOSPACE, &xprt->sock->flags)) {
-			/* Protect against races with xprt_write_space */
+			/* Protect against races with xs_write_space */
 			spin_lock_bh(&xprt->sock_lock);
 			/* Don't race with disconnect */
 			if (!xprt_connected(xprt))
@@ -303,65 +311,77 @@ xprt_send_request(struct rpc_task *task)
 	return status;
 }
 
-/*
- * Close down a transport socket
+/**
+ * xs_close - close a socket
+ * @xprt: transport
+ *
  */
-static void
-xprt_close(struct rpc_xprt *xprt)
+static void xs_close(struct rpc_xprt *xprt)
 {
-	struct socket	*sock = xprt->sock;
-	struct sock	*sk = xprt->inet;
+	struct socket *sock = xprt->sock;
+	struct sock *sk = xprt->inet;
 
 	if (!sk)
 		return;
 
+	dprintk("RPC:      xs_close xprt %p\n", xprt);
+
 	write_lock_bh(&sk->sk_callback_lock);
 	xprt->inet = NULL;
 	xprt->sock = NULL;
 
-	sk->sk_user_data    = NULL;
-	sk->sk_data_ready   = xprt->old_data_ready;
+	sk->sk_user_data = NULL;
+	sk->sk_data_ready = xprt->old_data_ready;
 	sk->sk_state_change = xprt->old_state_change;
-	sk->sk_write_space  = xprt->old_write_space;
+	sk->sk_write_space = xprt->old_write_space;
 	write_unlock_bh(&sk->sk_callback_lock);
 
-	sk->sk_no_check	 = 0;
+	sk->sk_no_check = 0;
 
 	sock_release(sock);
 }
 
-static void xprt_socket_destroy(struct rpc_xprt *xprt)
+/**
+ * xs_destroy - prepare to shutdown a transport
+ * @xprt: doomed transport
+ *
+ */
+static void xs_destroy(struct rpc_xprt *xprt)
 {
+	dprintk("RPC:      xs_destroy xprt %p\n", xprt);
+
 	cancel_delayed_work(&xprt->sock_connect);
 	flush_scheduled_work();
 
 	xprt_disconnect(xprt);
-	xprt_close(xprt);
+	xs_close(xprt);
 	kfree(xprt->slot);
 }
 
-/*
- * Input handler for RPC replies. Called from a bottom half and hence
- * atomic.
+static inline struct rpc_xprt *xprt_from_sock(struct sock *sk)
+{
+	return (struct rpc_xprt *) sk->sk_user_data;
+}
+
+/**
+ * xs_udp_data_ready - "data ready" callback for UDP sockets
+ * @sk: socket with data to read
+ * @len: how much data to read
+ *
  */
-static void
-udp_data_ready(struct sock *sk, int len)
+static void xs_udp_data_ready(struct sock *sk, int len)
 {
-	struct rpc_task	*task;
-	struct rpc_xprt	*xprt;
+	struct rpc_task *task;
+	struct rpc_xprt *xprt;
 	struct rpc_rqst *rovr;
-	struct sk_buff	*skb;
+	struct sk_buff *skb;
 	int err, repsize, copied;
 	u32 _xid, *xp;
 
 	read_lock(&sk->sk_callback_lock);
-	dprintk("RPC:      udp_data_ready...\n");
-	if (!(xprt = xprt_from_sock(sk))) {
-		printk("RPC:      udp_data_ready request not found!\n");
+	dprintk("RPC:      xs_udp_data_ready...\n");
+	if (!(xprt = xprt_from_sock(sk)))
 		goto out;
-	}
-
-	dprintk("RPC:      udp_data_ready client %p\n", xprt);
 
 	if ((skb = skb_recv_datagram(sk, 0, 1, &err)) == NULL)
 		goto out;
@@ -371,7 +391,7 @@ udp_data_ready(struct sock *sk, int len)
 
 	repsize = skb->len - sizeof(struct udphdr);
 	if (repsize < 4) {
-		printk("RPC: impossible RPC reply size %d!\n", repsize);
+		dprintk("RPC:      impossible RPC reply size %d!\n", repsize);
 		goto dropit;
 	}
 
@@ -410,11 +430,7 @@ udp_data_ready(struct sock *sk, int len)
 	read_unlock(&sk->sk_callback_lock);
 }
 
-/*
- * Copy from an skb into memory and shrink the skb.
- */
-static inline size_t
-tcp_copy_data(skb_reader_t *desc, void *p, size_t len)
+static inline size_t xs_tcp_copy_data(skb_reader_t *desc, void *p, size_t len)
 {
 	if (len > desc->count)
 		len = desc->count;
@@ -430,18 +446,14 @@ tcp_copy_data(skb_reader_t *desc, void *
 	return len;
 }
 
-/*
- * TCP read fragment marker
- */
-static inline void
-tcp_read_fraghdr(struct rpc_xprt *xprt, skb_reader_t *desc)
+static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, skb_reader_t *desc)
 {
 	size_t len, used;
 	char *p;
 
 	p = ((char *) &xprt->tcp_recm) + xprt->tcp_offset;
 	len = sizeof(xprt->tcp_recm) - xprt->tcp_offset;
-	used = tcp_copy_data(desc, p, len);
+	used = xs_tcp_copy_data(desc, p, len);
 	xprt->tcp_offset += used;
 	if (used != len)
 		return;
@@ -455,15 +467,15 @@ tcp_read_fraghdr(struct rpc_xprt *xprt, 
 	xprt->tcp_offset = 0;
 	/* Sanity check of the record length */
 	if (xprt->tcp_reclen < 4) {
-		printk(KERN_ERR "RPC: Invalid TCP record fragment length\n");
+		dprintk("RPC:      invalid TCP record fragment length\n");
 		xprt_disconnect(xprt);
+		return;
 	}
 	dprintk("RPC:      reading TCP record fragment of length %d\n",
 			xprt->tcp_reclen);
 }
 
-static void
-tcp_check_recm(struct rpc_xprt *xprt)
+static void xs_tcp_check_recm(struct rpc_xprt *xprt)
 {
 	dprintk("RPC:      xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u, tcp_flags = %lx\n",
 			xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen, xprt->tcp_flags);
@@ -478,11 +490,7 @@ tcp_check_recm(struct rpc_xprt *xprt)
 	}
 }
 
-/*
- * TCP read xid
- */
-static inline void
-tcp_read_xid(struct rpc_xprt *xprt, skb_reader_t *desc)
+static inline void xs_tcp_read_xid(struct rpc_xprt *xprt, skb_reader_t *desc)
 {
 	size_t len, used;
 	char *p;
@@ -490,7 +498,7 @@ tcp_read_xid(struct rpc_xprt *xprt, skb_
 	len = sizeof(xprt->tcp_xid) - xprt->tcp_offset;
 	dprintk("RPC:      reading XID (%Zu bytes)\n", len);
 	p = ((char *) &xprt->tcp_xid) + xprt->tcp_offset;
-	used = tcp_copy_data(desc, p, len);
+	used = xs_tcp_copy_data(desc, p, len);
 	xprt->tcp_offset += used;
 	if (used != len)
 		return;
@@ -499,14 +507,10 @@ tcp_read_xid(struct rpc_xprt *xprt, skb_
 	xprt->tcp_copied = 4;
 	dprintk("RPC:      reading reply for XID %08x\n",
 						ntohl(xprt->tcp_xid));
-	tcp_check_recm(xprt);
+	xs_tcp_check_recm(xprt);
 }
 
-/*
- * TCP read and complete request
- */
-static inline void
-tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc)
+static inline void xs_tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc)
 {
 	struct rpc_rqst *req;
 	struct xdr_buf *rcvbuf;
@@ -533,12 +537,12 @@ tcp_read_request(struct rpc_xprt *xprt, 
 		memcpy(&my_desc, desc, sizeof(my_desc));
 		my_desc.count = len;
 		r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
-					  &my_desc, tcp_copy_data);
+					  &my_desc, xs_tcp_copy_data);
 		desc->count -= r;
 		desc->offset += r;
 	} else
 		r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
-					  desc, tcp_copy_data);
+					  desc, xs_tcp_copy_data);
 
 	if (r > 0) {
 		xprt->tcp_copied += r;
@@ -581,14 +585,10 @@ out:
 		xprt_complete_rqst(xprt, req, xprt->tcp_copied);
 	}
 	spin_unlock(&xprt->sock_lock);
-	tcp_check_recm(xprt);
+	xs_tcp_check_recm(xprt);
 }
 
-/*
- * TCP discard extra bytes from a short read
- */
-static inline void
-tcp_read_discard(struct rpc_xprt *xprt, skb_reader_t *desc)
+static inline void xs_tcp_read_discard(struct rpc_xprt *xprt, skb_reader_t *desc)
 {
 	size_t len;
 
@@ -599,16 +599,10 @@ tcp_read_discard(struct rpc_xprt *xprt, 
 	desc->offset += len;
 	xprt->tcp_offset += len;
 	dprintk("RPC:      discarded %Zu bytes\n", len);
-	tcp_check_recm(xprt);
+	xs_tcp_check_recm(xprt);
 }
 
-/*
- * TCP record receive routine
- * We first have to grab the record marker, then the XID, then the data.
- */
-static int
-tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
-		unsigned int offset, size_t len)
+static int xs_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, unsigned int offset, size_t len)
 {
 	struct rpc_xprt *xprt = rd_desc->arg.data;
 	skb_reader_t desc = {
@@ -616,64 +610,72 @@ tcp_data_recv(read_descriptor_t *rd_desc
 		.offset	= offset,
 		.count	= len,
 		.csum	= 0
-       	};
+	};
 
-	dprintk("RPC:      tcp_data_recv\n");
+	dprintk("RPC:      xs_tcp_data_recv started\n");
 	do {
 		/* Read in a new fragment marker if necessary */
 		/* Can we ever really expect to get completely empty fragments? */
 		if (xprt->tcp_flags & XPRT_COPY_RECM) {
-			tcp_read_fraghdr(xprt, &desc);
+			xs_tcp_read_fraghdr(xprt, &desc);
 			continue;
 		}
 		/* Read in the xid if necessary */
 		if (xprt->tcp_flags & XPRT_COPY_XID) {
-			tcp_read_xid(xprt, &desc);
+			xs_tcp_read_xid(xprt, &desc);
 			continue;
 		}
 		/* Read in the request data */
 		if (xprt->tcp_flags & XPRT_COPY_DATA) {
-			tcp_read_request(xprt, &desc);
+			xs_tcp_read_request(xprt, &desc);
 			continue;
 		}
 		/* Skip over any trailing bytes on short reads */
-		tcp_read_discard(xprt, &desc);
+		xs_tcp_read_discard(xprt, &desc);
 	} while (desc.count);
-	dprintk("RPC:      tcp_data_recv done\n");
+	dprintk("RPC:      xs_tcp_data_recv done\n");
 	return len - desc.count;
 }
 
-static void tcp_data_ready(struct sock *sk, int bytes)
+/**
+ * xs_tcp_data_ready - "data ready" callback for TCP sockets
+ * @sk: socket with data to read
+ * @bytes: how much data to read
+ *
+ */
+static void xs_tcp_data_ready(struct sock *sk, int bytes)
 {
 	struct rpc_xprt *xprt;
 	read_descriptor_t rd_desc;
 
 	read_lock(&sk->sk_callback_lock);
-	dprintk("RPC:      tcp_data_ready...\n");
-	if (!(xprt = xprt_from_sock(sk))) {
-		printk("RPC:      tcp_data_ready socket info not found!\n");
+	dprintk("RPC:      xs_tcp_data_ready...\n");
+	if (!(xprt = xprt_from_sock(sk)))
 		goto out;
-	}
 	if (xprt->shutdown)
 		goto out;
 
-	/* We use rd_desc to pass struct xprt to tcp_data_recv */
+	/* We use rd_desc to pass struct xprt to xs_tcp_data_recv */
 	rd_desc.arg.data = xprt;
 	rd_desc.count = 65536;
-	tcp_read_sock(sk, &rd_desc, tcp_data_recv);
+	tcp_read_sock(sk, &rd_desc, xs_tcp_data_recv);
 out:
 	read_unlock(&sk->sk_callback_lock);
 }
 
-static void
-tcp_state_change(struct sock *sk)
+/**
+ * xs_tcp_state_change - callback to handle TCP socket state changes
+ * @sk: socket whose state has changed
+ *
+ */
+static void xs_tcp_state_change(struct sock *sk)
 {
-	struct rpc_xprt	*xprt;
+	struct rpc_xprt *xprt;
 
 	read_lock(&sk->sk_callback_lock);
 	if (!(xprt = xprt_from_sock(sk)))
 		goto out;
-	dprintk("RPC:      tcp_state_change client %p...\n", xprt);
+	dprintk("RPC:      xs_tcp_state_change client %p...\n", xprt);
 	dprintk("RPC:      state %x conn %d dead %d zapped %d\n",
 				sk->sk_state, xprt_connected(xprt),
 				sock_flag(sk, SOCK_DEAD),
@@ -703,17 +705,20 @@ tcp_state_change(struct sock *sk)
 	read_unlock(&sk->sk_callback_lock);
 }
 
-/*
+/**
+ * xs_write_space - callback invoked when socket buffer space becomes
+ *                         available
+ * @sk: socket whose state has changed
+ *
  * Called when more output buffer space is available for this socket.
  * We try not to wake our writers until they can make "significant"
  * progress, otherwise we'll waste resources thrashing sock_sendmsg
  * with a bunch of small requests.
  */
-static void
-xprt_write_space(struct sock *sk)
+static void xs_write_space(struct sock *sk)
 {
-	struct rpc_xprt	*xprt;
-	struct socket	*sock;
+	struct rpc_xprt *xprt;
+	struct socket *sock;
 
 	read_lock(&sk->sk_callback_lock);
 	if (!(xprt = xprt_from_sock(sk)) || !(sock = sk->sk_socket))
@@ -743,11 +748,15 @@ out:
 	read_unlock(&sk->sk_callback_lock);
 }
 
-/*
- * Set socket buffer length
+/**
+ * xs_set_buffer_size - set send and receive limits
+ * @xprt: generic transport
+ *
+ * Set socket send and receive limits based on the
+ * sndsize and rcvsize fields in the generic transport
+ * structure. This applies only to UDP sockets.
  */
-static void
-xprt_sock_setbufsize(struct rpc_xprt *xprt)
+static void xs_set_buffer_size(struct rpc_xprt *xprt)
 {
 	struct sock *sk = xprt->inet;
 
@@ -764,15 +773,12 @@ xprt_sock_setbufsize(struct rpc_xprt *xp
 	}
 }
 
-/*
- * Bind to a reserved port
- */
-static inline int xprt_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
+static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
 {
 	struct sockaddr_in myaddr = {
 		.sin_family = AF_INET,
 	};
-	int		err, port;
+	int err, port;
 
 	/* Were we already bound to a given port? Try to reuse it */
 	port = xprt->port;
@@ -782,20 +788,47 @@ static inline int xprt_bindresvport(stru
 						sizeof(myaddr));
 		if (err == 0) {
 			xprt->port = port;
+			dprintk("RPC:      xs_bindresvport bound to port %u\n",
+					port);
 			return 0;
 		}
 		if (--port == 0)
-			port = XPRT_MAX_RESVPORT;
+			port = XS_MAX_RESVPORT;
 	} while (err == -EADDRINUSE && port != xprt->port);
 
-	printk("RPC: Can't bind to reserved port (%d).\n", -err);
+	dprintk("RPC:      can't bind to reserved port (%d).\n", -err);
 	return err;
 }
 
-static void
-xprt_bind_socket(struct rpc_xprt *xprt, struct socket *sock)
+static struct socket *xs_create(struct rpc_xprt *xprt, int proto, int resvport)
 {
-	struct sock	*sk = sock->sk;
+	struct socket *sock;
+	int type, err;
+
+	dprintk("RPC:      xs_create(%s %d)\n",
+			   (proto == IPPROTO_UDP)? "udp" : "tcp", proto);
+
+	type = (proto == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
+
+	if ((err = sock_create_kern(PF_INET, type, proto, &sock)) < 0) {
+		dprintk("RPC:      can't create socket (%d).\n", -err);
+		return NULL;
+	}
+
+	/* If the caller has the capability, bind to a reserved port */
+	if (resvport && xs_bindresvport(xprt, sock) < 0)
+		goto failed;
+
+	return sock;
+
+failed:
+	sock_release(sock);
+	return NULL;
+}
+
+static void xs_bind(struct rpc_xprt *xprt, struct socket *sock)
+{
+	struct sock *sk = sock->sk;
 
 	if (xprt->inet)
 		return;
@@ -806,16 +839,16 @@ xprt_bind_socket(struct rpc_xprt *xprt, 
 	xprt->old_state_change = sk->sk_state_change;
 	xprt->old_write_space = sk->sk_write_space;
 	if (xprt->prot == IPPROTO_UDP) {
-		sk->sk_data_ready = udp_data_ready;
+		sk->sk_data_ready = xs_udp_data_ready;
 		sk->sk_no_check = UDP_CSUM_NORCV;
 		xprt_set_connected(xprt);
 	} else {
 		tcp_sk(sk)->nonagle = 1;	/* disable Nagle's algorithm */
-		sk->sk_data_ready = tcp_data_ready;
-		sk->sk_state_change = tcp_state_change;
+		sk->sk_data_ready = xs_tcp_data_ready;
+		sk->sk_state_change = xs_tcp_state_change;
 		xprt_clear_connected(xprt);
 	}
-	sk->sk_write_space = xprt_write_space;
+	sk->sk_write_space = xs_write_space;
 
 	/* Reset to new socket */
 	xprt->sock = sock;
@@ -825,39 +858,13 @@ xprt_bind_socket(struct rpc_xprt *xprt, 
 	return;
 }
 
-/*
- * Datastream sockets are created here, but xprt_connect will create
- * and connect stream sockets.
+/**
+ * xs_connect_worker - try to connect a socket to a remote endpoint
+ * @args: RPC transport to connect
+ *
+ * Invoked by a work queue tasklet.
  */
-static struct socket * xprt_create_socket(struct rpc_xprt *xprt, int proto, int resvport)
-{
-	struct socket	*sock;
-	int		type, err;
-
-	dprintk("RPC:      xprt_create_socket(%s %d)\n",
-			   (proto == IPPROTO_UDP)? "udp" : "tcp", proto);
-
-	type = (proto == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
-
-	if ((err = sock_create_kern(PF_INET, type, proto, &sock)) < 0) {
-		printk("RPC: can't create socket (%d).\n", -err);
-		return NULL;
-	}
-
-	/* If the caller has the capability, bind to a reserved port */
-	if (resvport && xprt_bindresvport(xprt, sock) < 0) {
-		printk("RPC: can't bind to reserved port.\n");
-		goto failed;
-	}
-
-	return sock;
-
-failed:
-	sock_release(sock);
-	return NULL;
-}
-
-static void xprt_socket_connect(void *args)
+static void xs_connect_worker(void *args)
 {
 	struct rpc_xprt *xprt = (struct rpc_xprt *)args;
 	struct socket *sock = xprt->sock;
@@ -866,18 +873,20 @@ static void xprt_socket_connect(void *ar
 	if (xprt->shutdown || xprt->addr.sin_port == 0)
 		goto out;
 
+	dprintk("RPC:      xs_connect_worker xprt %p\n", xprt);
+
 	/*
 	 * Start by resetting any existing state
 	 */
-	xprt_close(xprt);
-	sock = xprt_create_socket(xprt, xprt->prot, xprt->resvport);
+	xs_close(xprt);
+	sock = xs_create(xprt, xprt->prot, xprt->resvport);
 	if (sock == NULL) {
 		/* couldn't create socket or bind to reserved port;
 		 * this is likely a permanent error, so cause an abort */
 		goto out;
 	}
-	xprt_bind_socket(xprt, sock);
-	xprt_sock_setbufsize(xprt);
+	xs_bind(xprt, sock);
+	xs_set_buffer_size(xprt);
 
 	status = 0;
 	if (!xprt->stream)
@@ -908,20 +917,23 @@ out_clear:
 	smp_mb__after_clear_bit();
 }
 
-static void
-xprt_connect_sock(struct rpc_task *task)
+/**
+ * xs_connect - connect a socket to a remote endpoint
+ * @task: address of RPC task that manages state of connect request
+ *
+ * TCP: If the remote end dropped the connection, delay reconnecting.
+ */
+static void xs_connect(struct rpc_task *task)
 {
 	struct rpc_xprt *xprt = task->tk_xprt;
 
 	if (!test_and_set_bit(XPRT_CONNECTING, &xprt->sockstate)) {
-		/* Note: if we are here due to a dropped connection
-		 * 	 we delay reconnecting by RPC_REESTABLISH_TIMEOUT/HZ
-		 * 	 seconds
-		 */
-		if (xprt->sock != NULL)
+		if (xprt->sock != NULL) {
+			dprintk("RPC:      xs_connect delayed xprt %p\n", xprt);
 			schedule_delayed_work(&xprt->sock_connect,
 					RPC_REESTABLISH_TIMEOUT);
-		else {
+		} else {
+			dprintk("RPC:      xs_connect scheduled xprt %p\n", xprt);
 			schedule_work(&xprt->sock_connect);
 			/* flush_scheduled_work can sleep... */
 			if (!RPC_IS_ASYNC(task))
@@ -930,29 +942,23 @@ xprt_connect_sock(struct rpc_task *task)
 	}
 }
 
-/*
- * Set default timeout parameters
- */
-static void
-xprt_default_timeout(struct rpc_timeout *to, int proto)
-{
-	if (proto == IPPROTO_UDP)
-		xprt_set_timeout(to, 5,  5 * HZ);
-	else
-		xprt_set_timeout(to, 2, 60 * HZ);
-}
-
-static struct rpc_xprt_ops xprt_socket_ops = {
-	.set_buffer_size	= xprt_sock_setbufsize,
-	.connect		= xprt_connect_sock,
-	.send_request		= xprt_send_request,
-	.close			= xprt_close,
-	.destroy		= xprt_socket_destroy,
+static struct rpc_xprt_ops xs_ops = {
+	.set_buffer_size	= xs_set_buffer_size,
+	.connect		= xs_connect,
+	.send_request		= xs_send_request,
+	.close			= xs_close,
+	.destroy		= xs_destroy,
 };
 
 extern unsigned int xprt_udp_slot_table_entries;
 extern unsigned int xprt_tcp_slot_table_entries;
 
+/**
+ * xs_setup_udp - Set up transport to use a UDP socket
+ * @xprt: transport to set up
+ * @to:   timeout parameters
+ *
+ */
 int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to)
 {
 	size_t slot_table_size;
@@ -967,7 +973,7 @@ int xs_setup_udp(struct rpc_xprt *xprt, 
 	memset(xprt->slot, 0, slot_table_size);
 
 	xprt->prot = IPPROTO_UDP;
-	xprt->port = XPRT_MAX_RESVPORT;
+	xprt->port = XS_MAX_RESVPORT;
 	xprt->stream = 0;
 	xprt->nocong = 0;
 	xprt->cwnd = RPC_INITCWND;
@@ -975,18 +981,24 @@ int xs_setup_udp(struct rpc_xprt *xprt, 
 	/* XXX: header size can vary due to auth type, IPv6, etc. */
 	xprt->max_payload = (1U << 16) - (MAX_HEADER << 3);
 
-	INIT_WORK(&xprt->sock_connect, xprt_socket_connect, xprt);
+	INIT_WORK(&xprt->sock_connect, xs_connect_worker, xprt);
 
-	xprt->ops = &xprt_socket_ops;
+	xprt->ops = &xs_ops;
 
 	if (to)
 		xprt->timeout = *to;
 	else
-		xprt_default_timeout(to, xprt->prot);
+		xprt_set_timeout(&xprt->timeout, 5, 5 * HZ);
 
 	return 0;
 }
 
+/**
+ * xs_setup_tcp - Set up transport to use a TCP socket
+ * @xprt: transport to set up
+ * @to: timeout parameters
+ *
+ */
 int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to)
 {
 	size_t slot_table_size;
@@ -1001,21 +1013,21 @@ int xs_setup_tcp(struct rpc_xprt *xprt, 
 	memset(xprt->slot, 0, slot_table_size);
 
 	xprt->prot = IPPROTO_TCP;
-	xprt->port = XPRT_MAX_RESVPORT;
+	xprt->port = XS_MAX_RESVPORT;
 	xprt->stream = 1;
 	xprt->nocong = 1;
 	xprt->cwnd = RPC_MAXCWND(xprt);
 	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
 	xprt->max_payload = (1U << 31) - 1;
 
-	INIT_WORK(&xprt->sock_connect, xprt_socket_connect, xprt);
+	INIT_WORK(&xprt->sock_connect, xs_connect_worker, xprt);
 
-	xprt->ops = &xprt_socket_ops;
+	xprt->ops = &xs_ops;
 
 	if (to)
 		xprt->timeout = *to;
 	else
-		xprt_default_timeout(to, xprt->prot);
+		xprt_set_timeout(&xprt->timeout, 2, 60 * HZ);
 
 	return 0;
 }
---
0.99.8.GIT


--- NEW FILE 0229-RPC-Reduce-stack-utilization-in-xs_sendpages.txt ---
Subject: [PATCH] RPC: Reduce stack utilization in xs_sendpages
From: Chuck Lever <cel citi umich edu>
Date: 1123791929 -0400

 Reduce stack utilization of the RPC socket transport's send path.

 A couple of unlikely()s are added to ensure the compiler places the
 tail processing at the end of the csect.

 Test-plan:
 Millions of fsx operations.  Performance characterization such as "sio" or
 "iozone".

 Version: Thu, 11 Aug 2005 16:04:30 -0400

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 net/sunrpc/xprtsock.c |   73 +++++++++++++++++++++++++++++--------------------
 1 files changed, 43 insertions(+), 30 deletions(-)

applies-to: ad684d0ce47793f161839e2321f118206ef707f3
b4b5cc85ed4ecbe4adbfbc4df028850de67a9f09
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 80222de..a5a0420 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -68,6 +68,41 @@ static inline void xs_pktdump(char *msg,
 }
 #endif
 
+#define XS_SENDMSG_FLAGS	(MSG_DONTWAIT | MSG_NOSIGNAL)
+
+static inline int xs_send_head(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, unsigned int len)
+{
+	struct kvec iov = {
+		.iov_base	= xdr->head[0].iov_base + base,
+		.iov_len	= len - base,
+	};
+	struct msghdr msg = {
+		.msg_name	= addr,
+		.msg_namelen	= addrlen,
+		.msg_flags	= XS_SENDMSG_FLAGS,
+	};
+
+	if (xdr->len > len)
+		msg.msg_flags |= MSG_MORE;
+
+	if (likely(iov.iov_len))
+		return kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
+	return kernel_sendmsg(sock, &msg, NULL, 0, 0);
+}
+
+static int xs_send_tail(struct socket *sock, struct xdr_buf *xdr, unsigned int base, unsigned int len)
+{
+	struct kvec iov = {
+		.iov_base	= xdr->tail[0].iov_base + base,
+		.iov_len	= len - base,
+	};
+	struct msghdr msg = {
+		.msg_flags	= XS_SENDMSG_FLAGS,
+	};
+
+	return kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
+}
+
 /**
  * xs_sendpages - write pages directly to a socket
  * @sock: socket to send on
@@ -77,7 +112,7 @@ static inline void xs_pktdump(char *msg,
  * @base: starting position in the buffer
  *
  */
-static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, int msgflags)
+static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base)
 {
 	struct page **ppage = xdr->pages;
 	unsigned int len, pglen = xdr->page_len;
@@ -86,35 +121,20 @@ static int xs_sendpages(struct socket *s
 
 	len = xdr->head[0].iov_len;
 	if (base < len || (addr != NULL && base == 0)) {
-		struct kvec iov = {
-			.iov_base = xdr->head[0].iov_base + base,
-			.iov_len  = len - base,
-		};
-		struct msghdr msg = {
-			.msg_name    = addr,
-			.msg_namelen = addrlen,
-			.msg_flags   = msgflags,
-		};
-		if (xdr->len > len)
-			msg.msg_flags |= MSG_MORE;
-
-		if (iov.iov_len != 0)
-			err = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
-		else
-			err = kernel_sendmsg(sock, &msg, NULL, 0, 0);
+		err = xs_send_head(sock, addr, addrlen, xdr, base, len);
 		if (ret == 0)
 			ret = err;
 		else if (err > 0)
 			ret += err;
-		if (err != iov.iov_len)
+		if (err != (len - base))
 			goto out;
 		base = 0;
 	} else
 		base -= len;
 
-	if (pglen == 0)
+	if (unlikely(pglen == 0))
 		goto copy_tail;
-	if (base >= pglen) {
+	if (unlikely(base >= pglen)) {
 		base -= pglen;
 		goto copy_tail;
 	}
@@ -127,7 +147,7 @@ static int xs_sendpages(struct socket *s
 
 	sendpage = sock->ops->sendpage ? : sock_no_sendpage;
 	do {
-		int flags = msgflags;
+		int flags = XS_SENDMSG_FLAGS;
 
 		len = PAGE_CACHE_SIZE;
 		if (base)
@@ -154,14 +174,7 @@ static int xs_sendpages(struct socket *s
 copy_tail:
 	len = xdr->tail[0].iov_len;
 	if (base < len) {
-		struct kvec iov = {
-			.iov_base = xdr->tail[0].iov_base + base,
-			.iov_len  = len - base,
-		};
-		struct msghdr msg = {
-			.msg_flags   = msgflags,
-		};
-		err = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
+		err = xs_send_tail(sock, xdr, base, len);
 		if (ret == 0)
 			ret = err;
 		else if (err > 0)
@@ -202,7 +215,7 @@ static int xs_sendmsg(struct rpc_xprt *x
 	skip = req->rq_bytes_sent;
 
 	clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
-	result = xs_sendpages(sock, addr, addrlen, xdr, skip, MSG_DONTWAIT);
+	result = xs_sendpages(sock, addr, addrlen, xdr, skip);
 
 	dprintk("RPC:      xs_sendmsg(%d) = %d\n", xdr->len - skip, result);
 
---
0.99.8.GIT


--- NEW FILE 0230-RPC-Rename-sock_lock.txt ---
Subject: [PATCH] RPC: Rename sock_lock
From: Chuck Lever <cel citi umich edu>
Date: 1123791932 -0400

 Clean-up: replace a name reference to sockets in the generic parts of the RPC
 client by renaming sock_lock in the rpc_xprt structure.

 Test-plan:
 Compile kernel with CONFIG_NFS enabled.

 Version: Thu, 11 Aug 2005 16:05:00 -0400

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/xprt.h |    2 +-
 net/sunrpc/xprt.c           |   44 ++++++++++++++++++++++---------------------
 net/sunrpc/xprtsock.c       |   22 +++++++++++-----------
 3 files changed, 34 insertions(+), 34 deletions(-)

applies-to: 41b4a8d22847f816e555ad5e4566b9c33dea5c0f
4a0f8c04f2ece949d54a0c4fd7490259cf23a58a
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index d82b47a..c4f903f 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -198,7 +198,7 @@ struct rpc_xprt {
 	/*
 	 * Send stuff
 	 */
-	spinlock_t		sock_lock;	/* lock socket info */
+	spinlock_t		transport_lock;	/* lock transport info */
 	spinlock_t		xprt_lock;	/* lock xprt info */
 	struct rpc_task *	snd_task;	/* Task blocked in send */
 
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 589195e..1f0da8c 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -106,9 +106,9 @@ xprt_lock_write(struct rpc_xprt *xprt, s
 {
 	int retval;
 
-	spin_lock_bh(&xprt->sock_lock);
+	spin_lock_bh(&xprt->transport_lock);
 	retval = __xprt_lock_write(xprt, task);
-	spin_unlock_bh(&xprt->sock_lock);
+	spin_unlock_bh(&xprt->transport_lock);
 	return retval;
 }
 
@@ -161,9 +161,9 @@ __xprt_release_write(struct rpc_xprt *xp
 static inline void
 xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task)
 {
-	spin_lock_bh(&xprt->sock_lock);
+	spin_lock_bh(&xprt->transport_lock);
 	__xprt_release_write(xprt, task);
-	spin_unlock_bh(&xprt->sock_lock);
+	spin_unlock_bh(&xprt->transport_lock);
 }
 
 /*
@@ -266,9 +266,9 @@ int xprt_adjust_timeout(struct rpc_rqst 
 		req->rq_retries = 0;
 		xprt_reset_majortimeo(req);
 		/* Reset the RTT counters == "slow start" */
-		spin_lock_bh(&xprt->sock_lock);
+		spin_lock_bh(&xprt->transport_lock);
 		rpc_init_rtt(req->rq_task->tk_client->cl_rtt, to->to_initval);
-		spin_unlock_bh(&xprt->sock_lock);
+		spin_unlock_bh(&xprt->transport_lock);
 		pprintk("RPC: %lu timeout\n", jiffies);
 		status = -ETIMEDOUT;
 	}
@@ -298,10 +298,10 @@ xprt_socket_autoclose(void *args)
 void xprt_disconnect(struct rpc_xprt *xprt)
 {
 	dprintk("RPC:      disconnected transport %p\n", xprt);
-	spin_lock_bh(&xprt->sock_lock);
+	spin_lock_bh(&xprt->transport_lock);
 	xprt_clear_connected(xprt);
 	rpc_wake_up_status(&xprt->pending, -ENOTCONN);
-	spin_unlock_bh(&xprt->sock_lock);
+	spin_unlock_bh(&xprt->transport_lock);
 }
 
 static void
@@ -309,12 +309,12 @@ xprt_init_autodisconnect(unsigned long d
 {
 	struct rpc_xprt *xprt = (struct rpc_xprt *)data;
 
-	spin_lock(&xprt->sock_lock);
+	spin_lock(&xprt->transport_lock);
 	if (!list_empty(&xprt->recv) || xprt->shutdown)
 		goto out_abort;
 	if (test_and_set_bit(XPRT_LOCKED, &xprt->sockstate))
 		goto out_abort;
-	spin_unlock(&xprt->sock_lock);
+	spin_unlock(&xprt->transport_lock);
 	/* Let keventd close the socket */
 	if (test_bit(XPRT_CONNECTING, &xprt->sockstate) != 0)
 		xprt_release_write(xprt, NULL);
@@ -322,7 +322,7 @@ xprt_init_autodisconnect(unsigned long d
 		schedule_work(&xprt->task_cleanup);
 	return;
 out_abort:
-	spin_unlock(&xprt->sock_lock);
+	spin_unlock(&xprt->transport_lock);
 }
 
 /**
@@ -482,7 +482,7 @@ xprt_timer(struct rpc_task *task)
 	struct rpc_rqst	*req = task->tk_rqstp;
 	struct rpc_xprt *xprt = req->rq_xprt;
 
-	spin_lock(&xprt->sock_lock);
+	spin_lock(&xprt->transport_lock);
 	if (req->rq_received)
 		goto out;
 
@@ -496,7 +496,7 @@ xprt_timer(struct rpc_task *task)
 out:
 	task->tk_timeout = 0;
 	rpc_wake_up_task(task);
-	spin_unlock(&xprt->sock_lock);
+	spin_unlock(&xprt->transport_lock);
 }
 
 /**
@@ -515,7 +515,7 @@ int xprt_prepare_transmit(struct rpc_tas
 	if (xprt->shutdown)
 		return -EIO;
 
-	spin_lock_bh(&xprt->sock_lock);
+	spin_lock_bh(&xprt->transport_lock);
 	if (req->rq_received && !req->rq_bytes_sent) {
 		err = req->rq_received;
 		goto out_unlock;
@@ -530,7 +530,7 @@ int xprt_prepare_transmit(struct rpc_tas
 		goto out_unlock;
 	}
 out_unlock:
-	spin_unlock_bh(&xprt->sock_lock);
+	spin_unlock_bh(&xprt->transport_lock);
 	return err;
 }
 
@@ -552,13 +552,13 @@ void xprt_transmit(struct rpc_task *task
 	smp_rmb();
 	if (!req->rq_received) {
 		if (list_empty(&req->rq_list)) {
-			spin_lock_bh(&xprt->sock_lock);
+			spin_lock_bh(&xprt->transport_lock);
 			/* Update the softirq receive buffer */
 			memcpy(&req->rq_private_buf, &req->rq_rcv_buf,
 					sizeof(req->rq_private_buf));
 			/* Add request to the receive list */
 			list_add_tail(&req->rq_list, &xprt->recv);
-			spin_unlock_bh(&xprt->sock_lock);
+			spin_unlock_bh(&xprt->transport_lock);
 			xprt_reset_majortimeo(req);
 			/* Turn off autodisconnect */
 			del_singleshot_timer_sync(&xprt->timer);
@@ -592,7 +592,7 @@ void xprt_transmit(struct rpc_task *task
  out_receive:
 	dprintk("RPC: %4d xmit complete\n", task->tk_pid);
 	/* Set the task's receive timeout value */
-	spin_lock_bh(&xprt->sock_lock);
+	spin_lock_bh(&xprt->transport_lock);
 	if (!xprt->nocong) {
 		int timer = task->tk_msg.rpc_proc->p_timer;
 		task->tk_timeout = rpc_calc_rto(clnt->cl_rtt, timer);
@@ -607,7 +607,7 @@ void xprt_transmit(struct rpc_task *task
 	else if (!req->rq_received)
 		rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer);
 	__xprt_release_write(xprt, task);
-	spin_unlock_bh(&xprt->sock_lock);
+	spin_unlock_bh(&xprt->transport_lock);
 }
 
 static inline void do_xprt_reserve(struct rpc_task *task)
@@ -683,7 +683,7 @@ void xprt_release(struct rpc_task *task)
 
 	if (!(req = task->tk_rqstp))
 		return;
-	spin_lock_bh(&xprt->sock_lock);
+	spin_lock_bh(&xprt->transport_lock);
 	__xprt_release_write(xprt, task);
 	__xprt_put_cong(xprt, req);
 	if (!list_empty(&req->rq_list))
@@ -692,7 +692,7 @@ void xprt_release(struct rpc_task *task)
 	if (list_empty(&xprt->recv) && !xprt->shutdown)
 		mod_timer(&xprt->timer,
 				xprt->last_used + RPC_IDLE_DISCONNECT_TIMEOUT);
-	spin_unlock_bh(&xprt->sock_lock);
+	spin_unlock_bh(&xprt->transport_lock);
 	task->tk_rqstp = NULL;
 	memset(req, 0, sizeof(*req));	/* mark unused */
 
@@ -750,7 +750,7 @@ static struct rpc_xprt *xprt_setup(int p
 		return ERR_PTR(result);
 	}
 
-	spin_lock_init(&xprt->sock_lock);
+	spin_lock_init(&xprt->transport_lock);
 	spin_lock_init(&xprt->xprt_lock);
 	init_waitqueue_head(&xprt->cong_wait);
 
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index a5a0420..bc90caa 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -307,7 +307,7 @@ static int xs_send_request(struct rpc_ta
 	if (status == -EAGAIN) {
 		if (test_bit(SOCK_ASYNC_NOSPACE, &xprt->sock->flags)) {
 			/* Protect against races with xs_write_space */
-			spin_lock_bh(&xprt->sock_lock);
+			spin_lock_bh(&xprt->transport_lock);
 			/* Don't race with disconnect */
 			if (!xprt_connected(xprt))
 				task->tk_status = -ENOTCONN;
@@ -315,7 +315,7 @@ static int xs_send_request(struct rpc_ta
 				task->tk_timeout = req->rq_timeout;
 				rpc_sleep_on(&xprt->pending, task, NULL, NULL);
 			}
-			spin_unlock_bh(&xprt->sock_lock);
+			spin_unlock_bh(&xprt->transport_lock);
 			return status;
 		}
 		/* Keep holding the socket if it is blocked */
@@ -415,7 +415,7 @@ static void xs_udp_data_ready(struct soc
 		goto dropit;
 
 	/* Look up and lock the request corresponding to the given XID */
-	spin_lock(&xprt->sock_lock);
+	spin_lock(&xprt->transport_lock);
 	rovr = xprt_lookup_rqst(xprt, *xp);
 	if (!rovr)
 		goto out_unlock;
@@ -436,7 +436,7 @@ static void xs_udp_data_ready(struct soc
 	xprt_complete_rqst(xprt, rovr, copied);
 
  out_unlock:
-	spin_unlock(&xprt->sock_lock);
+	spin_unlock(&xprt->transport_lock);
  dropit:
 	skb_free_datagram(sk, skb);
  out:
@@ -531,13 +531,13 @@ static inline void xs_tcp_read_request(s
 	ssize_t r;
 
 	/* Find and lock the request corresponding to this xid */
-	spin_lock(&xprt->sock_lock);
+	spin_lock(&xprt->transport_lock);
 	req = xprt_lookup_rqst(xprt, xprt->tcp_xid);
 	if (!req) {
 		xprt->tcp_flags &= ~XPRT_COPY_DATA;
 		dprintk("RPC:      XID %08x request not found!\n",
 				ntohl(xprt->tcp_xid));
-		spin_unlock(&xprt->sock_lock);
+		spin_unlock(&xprt->transport_lock);
 		return;
 	}
 
@@ -597,7 +597,7 @@ out:
 				req->rq_task->tk_pid);
 		xprt_complete_rqst(xprt, req, xprt->tcp_copied);
 	}
-	spin_unlock(&xprt->sock_lock);
+	spin_unlock(&xprt->transport_lock);
 	xs_tcp_check_recm(xprt);
 }
 
@@ -696,7 +696,7 @@ static void xs_tcp_state_change(struct s
 
 	switch (sk->sk_state) {
 	case TCP_ESTABLISHED:
-		spin_lock_bh(&xprt->sock_lock);
+		spin_lock_bh(&xprt->transport_lock);
 		if (!xprt_test_and_set_connected(xprt)) {
 			/* Reset TCP record info */
 			xprt->tcp_offset = 0;
@@ -705,7 +705,7 @@ static void xs_tcp_state_change(struct s
 			xprt->tcp_flags = XPRT_COPY_RECM | XPRT_COPY_XID;
 			rpc_wake_up(&xprt->pending);
 		}
-		spin_unlock_bh(&xprt->sock_lock);
+		spin_unlock_bh(&xprt->transport_lock);
 		break;
 	case TCP_SYN_SENT:
 	case TCP_SYN_RECV:
@@ -753,10 +753,10 @@ static void xs_write_space(struct sock *
 	if (!test_and_clear_bit(SOCK_NOSPACE, &sock->flags))
 		goto out;
 
-	spin_lock_bh(&xprt->sock_lock);
+	spin_lock_bh(&xprt->transport_lock);
 	if (xprt->snd_task)
 		rpc_wake_up_task(xprt->snd_task);
-	spin_unlock_bh(&xprt->sock_lock);
+	spin_unlock_bh(&xprt->transport_lock);
 out:
 	read_unlock(&sk->sk_callback_lock);
 }
---
0.99.8.GIT


--- NEW FILE 0231-RPC-Rename-xprt_lock.txt ---
Subject: [PATCH] RPC: Rename xprt_lock
From: Chuck Lever <cel citi umich edu>
Date: 1123791935 -0400

 Clean-up: Replace the xprt_lock with something more aptly named.  This lock
 single-threads the XID and request slot reservation process.

 Test-plan:
 Compile kernel with CONFIG_NFS enabled.

 Version: Thu, 11 Aug 2005 16:05:26 -0400

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/xprt.h |    2 +-
 net/sunrpc/xprt.c           |   10 +++++-----
 2 files changed, 6 insertions(+), 6 deletions(-)

applies-to: 6c6e142cfa37b984dcba6f785a4f886374a307c6
5dc07727f86b25851e95193a0c484ea21b531c47
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index c4f903f..41ce296 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -199,7 +199,7 @@ struct rpc_xprt {
 	 * Send stuff
 	 */
 	spinlock_t		transport_lock;	/* lock transport info */
-	spinlock_t		xprt_lock;	/* lock xprt info */
+	spinlock_t		reserve_lock;	/* lock slot table */
 	struct rpc_task *	snd_task;	/* Task blocked in send */
 
 	struct list_head	recv;
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 1f0da8c..9c45c52 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -643,9 +643,9 @@ void xprt_reserve(struct rpc_task *task)
 
 	task->tk_status = -EIO;
 	if (!xprt->shutdown) {
-		spin_lock(&xprt->xprt_lock);
+		spin_lock(&xprt->reserve_lock);
 		do_xprt_reserve(task);
-		spin_unlock(&xprt->xprt_lock);
+		spin_unlock(&xprt->reserve_lock);
 	}
 }
 
@@ -698,10 +698,10 @@ void xprt_release(struct rpc_task *task)
 
 	dprintk("RPC: %4d release request %p\n", task->tk_pid, req);
 
-	spin_lock(&xprt->xprt_lock);
+	spin_lock(&xprt->reserve_lock);
 	list_add(&req->rq_list, &xprt->free);
 	xprt_clear_backlog(xprt);
-	spin_unlock(&xprt->xprt_lock);
+	spin_unlock(&xprt->reserve_lock);
 }
 
 /**
@@ -751,7 +751,7 @@ static struct rpc_xprt *xprt_setup(int p
 	}
 
 	spin_lock_init(&xprt->transport_lock);
-	spin_lock_init(&xprt->xprt_lock);
+	spin_lock_init(&xprt->reserve_lock);
 	init_waitqueue_head(&xprt->cong_wait);
 
 	INIT_LIST_HEAD(&xprt->free);
---
0.99.8.GIT


--- NEW FILE 0232-RPC-rename-the-sockstate-field.txt ---
Subject: [PATCH] RPC: rename the sockstate field
From: Chuck Lever <cel citi umich edu>
Date: 1123791938 -0400

 Clean-up: get rid of a name reference to sockets in the generic parts of the
 RPC client by renaming the sockstate field in the rpc_xprt structure.

 Test-plan:
 Compile kernel with CONFIG_NFS enabled.

 Version: Thu, 11 Aug 2005 16:05:53 -0400

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/xprt.h |   60 +++++++++++++++++++++++++++++++++++--------
 net/sunrpc/xprt.c           |   14 +++++-----
 net/sunrpc/xprtsock.c       |    6 +---
 3 files changed, 58 insertions(+), 22 deletions(-)

applies-to: 813a8cb359fef51172ff67d9da8efdfc5fee4a83
2226feb6bcd0e5e117a9be3ea3dd3ffc14f3e41e
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 41ce296..009a3bb 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -163,7 +163,7 @@ struct rpc_xprt {
 	struct list_head	free;		/* free slots */
 	struct rpc_rqst *	slot;		/* slot table storage */
 	unsigned int		max_reqs;	/* total slots */
-	unsigned long		sockstate;	/* Socket state */
+	unsigned long		state;		/* transport state */
 	unsigned char		shutdown   : 1,	/* being shut down */
 				nocong	   : 1,	/* no congestion control */
 				resvport   : 1, /* use a reserved port */
@@ -240,16 +240,54 @@ int			xs_setup_udp(struct rpc_xprt *,
 int			xs_setup_tcp(struct rpc_xprt *,
 					struct rpc_timeout *);
 
-#define XPRT_LOCKED	0
-#define XPRT_CONNECT	1
-#define XPRT_CONNECTING	2
-
-#define xprt_connected(xp)		(test_bit(XPRT_CONNECT, &(xp)->sockstate))
-#define xprt_set_connected(xp)		(set_bit(XPRT_CONNECT, &(xp)->sockstate))
-#define xprt_test_and_set_connected(xp)	(test_and_set_bit(XPRT_CONNECT, &(xp)->sockstate))
-#define xprt_test_and_clear_connected(xp) \
-					(test_and_clear_bit(XPRT_CONNECT, &(xp)->sockstate))
-#define xprt_clear_connected(xp)	(clear_bit(XPRT_CONNECT, &(xp)->sockstate))
+/*
+ * Reserved bit positions in xprt->state
+ */
+#define XPRT_LOCKED		(0)
+#define XPRT_CONNECTED		(1)
+#define XPRT_CONNECTING		(2)
+
+static inline void xprt_set_connected(struct rpc_xprt *xprt)
+{
+	set_bit(XPRT_CONNECTED, &xprt->state);
+}
+
+static inline void xprt_clear_connected(struct rpc_xprt *xprt)
+{
+	clear_bit(XPRT_CONNECTED, &xprt->state);
+}
+
+static inline int xprt_connected(struct rpc_xprt *xprt)
+{
+	return test_bit(XPRT_CONNECTED, &xprt->state);
+}
+
+static inline int xprt_test_and_set_connected(struct rpc_xprt *xprt)
+{
+	return test_and_set_bit(XPRT_CONNECTED, &xprt->state);
+}
+
+static inline int xprt_test_and_clear_connected(struct rpc_xprt *xprt)
+{
+	return test_and_clear_bit(XPRT_CONNECTED, &xprt->state);
+}
+
+static inline void xprt_clear_connecting(struct rpc_xprt *xprt)
+{
+	smp_mb__before_clear_bit();
+	clear_bit(XPRT_CONNECTING, &xprt->state);
+	smp_mb__after_clear_bit();
+}
+
+static inline int xprt_connecting(struct rpc_xprt *xprt)
+{
+	return test_bit(XPRT_CONNECTING, &xprt->state);
+}
+
+static inline int xprt_test_and_set_connecting(struct rpc_xprt *xprt)
+{
+	return test_and_set_bit(XPRT_CONNECTING, &xprt->state);
+}
 
 #endif /* __KERNEL__*/
 
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 9c45c52..57c5e77 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -74,7 +74,7 @@ __xprt_lock_write(struct rpc_xprt *xprt,
 {
 	struct rpc_rqst *req = task->tk_rqstp;
 
-	if (test_and_set_bit(XPRT_LOCKED, &xprt->sockstate)) {
+	if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) {
 		if (task == xprt->snd_task)
 			return 1;
 		goto out_sleep;
@@ -88,7 +88,7 @@ __xprt_lock_write(struct rpc_xprt *xprt,
 		return 1;
 	}
 	smp_mb__before_clear_bit();
-	clear_bit(XPRT_LOCKED, &xprt->sockstate);
+	clear_bit(XPRT_LOCKED, &xprt->state);
 	smp_mb__after_clear_bit();
 out_sleep:
 	dprintk("RPC: %4d failed to lock socket %p\n", task->tk_pid, xprt);
@@ -118,7 +118,7 @@ __xprt_lock_write_next(struct rpc_xprt *
 {
 	struct rpc_task *task;
 
-	if (test_and_set_bit(XPRT_LOCKED, &xprt->sockstate))
+	if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
 		return;
 	if (!xprt->nocong && RPCXPRT_CONGESTED(xprt))
 		goto out_unlock;
@@ -139,7 +139,7 @@ __xprt_lock_write_next(struct rpc_xprt *
 	}
 out_unlock:
 	smp_mb__before_clear_bit();
-	clear_bit(XPRT_LOCKED, &xprt->sockstate);
+	clear_bit(XPRT_LOCKED, &xprt->state);
 	smp_mb__after_clear_bit();
 }
 
@@ -152,7 +152,7 @@ __xprt_release_write(struct rpc_xprt *xp
 	if (xprt->snd_task == task) {
 		xprt->snd_task = NULL;
 		smp_mb__before_clear_bit();
-		clear_bit(XPRT_LOCKED, &xprt->sockstate);
+		clear_bit(XPRT_LOCKED, &xprt->state);
 		smp_mb__after_clear_bit();
 		__xprt_lock_write_next(xprt);
 	}
@@ -312,11 +312,11 @@ xprt_init_autodisconnect(unsigned long d
 	spin_lock(&xprt->transport_lock);
 	if (!list_empty(&xprt->recv) || xprt->shutdown)
 		goto out_abort;
-	if (test_and_set_bit(XPRT_LOCKED, &xprt->sockstate))
+	if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
 		goto out_abort;
 	spin_unlock(&xprt->transport_lock);
 	/* Let keventd close the socket */
-	if (test_bit(XPRT_CONNECTING, &xprt->sockstate) != 0)
+	if (xprt_connecting(xprt))
 		xprt_release_write(xprt, NULL);
 	else
 		schedule_work(&xprt->task_cleanup);
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index bc90caa..76a33b5 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -925,9 +925,7 @@ out:
 	else
 		rpc_wake_up(&xprt->pending);
 out_clear:
-	smp_mb__before_clear_bit();
-	clear_bit(XPRT_CONNECTING, &xprt->sockstate);
-	smp_mb__after_clear_bit();
+	xprt_clear_connecting(xprt);
 }
 
 /**
@@ -940,7 +938,7 @@ static void xs_connect(struct rpc_task *
 {
 	struct rpc_xprt *xprt = task->tk_xprt;
 
-	if (!test_and_set_bit(XPRT_CONNECTING, &xprt->sockstate)) {
+	if (!xprt_test_and_set_connecting(xprt)) {
 		if (xprt->sock != NULL) {
 			dprintk("RPC:      xs_connect delayed xprt %p\n", xprt);
 			schedule_delayed_work(&xprt->sock_connect,
---
0.99.8.GIT


--- NEW FILE 0233-RPC-Eliminate-socket.h-includes-in-RPC-client.txt ---
Subject: [PATCH] RPC: Eliminate socket.h includes in RPC client
From: Chuck Lever <cel citi umich edu>
Date: 1123791941 -0400

 Clean-up: get rid of unnecessary socket.h and in.h includes in the generic
 parts of the RPC client.

 Test-plan:
 Compile kernel with CONFIG_NFS enabled.

 Version: Thu, 11 Aug 2005 16:06:23 -0400

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 net/sunrpc/auth.c                     |    1 -
 net/sunrpc/auth_gss/auth_gss.c        |    2 --
 net/sunrpc/auth_gss/gss_krb5_mech.c   |    1 -
 net/sunrpc/auth_gss/gss_mech_switch.c |    1 -
 net/sunrpc/auth_null.c                |    2 --
 net/sunrpc/auth_unix.c                |    2 --
 net/sunrpc/clnt.c                     |    1 -
 net/sunrpc/sunrpc_syms.c              |    1 -
 8 files changed, 0 insertions(+), 11 deletions(-)

applies-to: 5ae6bde4dd66da8932c23c780745c72cf38de722
86b9f57dfdf455763d2be73a742a9a88bb664173
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 505e2d4..a415d99 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -11,7 +11,6 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
-#include <linux/socket.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/spinlock.h>
 
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 2f7b867..53a030a 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -42,8 +42,6 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/slab.h>
-#include <linux/socket.h>
-#include <linux/in.h>
 #include <linux/sched.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/auth.h>
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 606a8a8..462c5b8 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -39,7 +39,6 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/sunrpc/auth.h>
-#include <linux/in.h>
 #include <linux/sunrpc/gss_krb5.h>
 #include <linux/sunrpc/xdr.h>
 #include <linux/crypto.h>
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
index 9dfb683..58aeadd 100644
--- a/net/sunrpc/auth_gss/gss_mech_switch.c
+++ b/net/sunrpc/auth_gss/gss_mech_switch.c
@@ -35,7 +35,6 @@
 
 #include <linux/types.h>
 #include <linux/slab.h>
-#include <linux/socket.h>
 #include <linux/module.h>
 #include <linux/sunrpc/msg_prot.h>
 #include <linux/sunrpc/gss_asn1.h>
diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c
index 9b72d3a..f56767a 100644
--- a/net/sunrpc/auth_null.c
+++ b/net/sunrpc/auth_null.c
@@ -7,9 +7,7 @@
  */
 
 #include <linux/types.h>
-#include <linux/socket.h>
 #include <linux/module.h>
-#include <linux/in.h>
 #include <linux/utsname.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sched.h>
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c
index 4ff297a..890fb5e 100644
--- a/net/sunrpc/auth_unix.c
+++ b/net/sunrpc/auth_unix.c
@@ -9,8 +9,6 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/module.h>
-#include <linux/socket.h>
-#include <linux/in.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/auth.h>
 
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index ab50c3c..0d1b010 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -27,7 +27,6 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
-#include <linux/in.h>
 #include <linux/utsname.h>
 
 #include <linux/sunrpc/clnt.h>
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index ed48ff0..2387e7b 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -10,7 +10,6 @@
 #include <linux/module.h>
 
 #include <linux/types.h>
-#include <linux/socket.h>
 #include <linux/sched.h>
 #include <linux/uio.h>
 #include <linux/unistd.h>
---
0.99.8.GIT


--- NEW FILE 0234-RPC-Add-helper-for-waking-tasks-pending-on-a-transport.txt ---
Subject: [PATCH] RPC: Add helper for waking tasks pending on a transport
From: Chuck Lever <cel citi umich edu>
Date: 1123791944 -0400

 Clean-up: remove only reference to xprt->pending from the socket transport
 implementation.  This makes a cleaner interface for other transport
 implementations as well.

 Test-plan:
 Compile kernel with CONFIG_NFS enabled.

 Version: Thu, 11 Aug 2005 16:06:52 -0400

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/xprt.h |    1 +
 net/sunrpc/xprt.c           |   18 ++++++++++++++++--
 net/sunrpc/xprtsock.c       |    7 ++-----
 3 files changed, 19 insertions(+), 7 deletions(-)

applies-to: 4d153fb7e1452efcbfd170c8ce85f049257c558e
44fbac2288dfed6f1963ac00bf922c3bcd779cd1
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 009a3bb..d522399 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -232,6 +232,7 @@ void			xprt_reserve(struct rpc_task *);
 int			xprt_prepare_transmit(struct rpc_task *);
 void			xprt_transmit(struct rpc_task *);
 void			xprt_receive(struct rpc_task *);
+void			xprt_wake_pending_tasks(struct rpc_xprt *, int);
 int			xprt_adjust_timeout(struct rpc_rqst *req);
 void			xprt_release(struct rpc_task *);
 void			xprt_connect(struct rpc_task *);
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 57c5e77..2f9cd46 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -227,6 +227,20 @@ xprt_adjust_cwnd(struct rpc_xprt *xprt, 
 	xprt->cwnd = cwnd;
 }
 
+/**
+ * xprt_wake_pending_tasks - wake all tasks on a transport's pending queue
+ * @xprt: transport with waiting tasks
+ * @status: result code to plant in each task before waking it
+ *
+ */
+void xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status)
+{
+	if (status < 0)
+		rpc_wake_up_status(&xprt->pending, status);
+	else
+		rpc_wake_up(&xprt->pending);
+}
+
 static void xprt_reset_majortimeo(struct rpc_rqst *req)
 {
 	struct rpc_timeout *to = &req->rq_xprt->timeout;
@@ -300,7 +314,7 @@ void xprt_disconnect(struct rpc_xprt *xp
 	dprintk("RPC:      disconnected transport %p\n", xprt);
 	spin_lock_bh(&xprt->transport_lock);
 	xprt_clear_connected(xprt);
-	rpc_wake_up_status(&xprt->pending, -ENOTCONN);
+	xprt_wake_pending_tasks(xprt, -ENOTCONN);
 	spin_unlock_bh(&xprt->transport_lock);
 }
 
@@ -803,7 +817,7 @@ static void xprt_shutdown(struct rpc_xpr
 	xprt->shutdown = 1;
 	rpc_wake_up(&xprt->sending);
 	rpc_wake_up(&xprt->resend);
-	rpc_wake_up(&xprt->pending);
+	xprt_wake_pending_tasks(xprt, -EIO);
 	rpc_wake_up(&xprt->backlog);
 	wake_up(&xprt->cong_wait);
 	del_timer_sync(&xprt->timer);
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 76a33b5..182da2e 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -703,7 +703,7 @@ static void xs_tcp_state_change(struct s
 			xprt->tcp_reclen = 0;
 			xprt->tcp_copied = 0;
 			xprt->tcp_flags = XPRT_COPY_RECM | XPRT_COPY_XID;
-			rpc_wake_up(&xprt->pending);
+			xprt_wake_pending_tasks(xprt, 0);
 		}
 		spin_unlock_bh(&xprt->transport_lock);
 		break;
@@ -920,10 +920,7 @@ static void xs_connect_worker(void *args
 		}
 	}
 out:
-	if (status < 0)
-		rpc_wake_up_status(&xprt->pending, status);
-	else
-		rpc_wake_up(&xprt->pending);
+	xprt_wake_pending_tasks(xprt, status);
 out_clear:
 	xprt_clear_connecting(xprt);
 }
---
0.99.8.GIT


--- NEW FILE 0235-RPC-client-side-transport-switch-cleanup.txt ---
Subject: [PATCH] RPC: client-side transport switch cleanup
From: Chuck Lever <cel citi umich edu>
Date: 1123791947 -0400

 Clean-up: change some comments to reflect the realities of the new RPC
 transport switch mechanism.  Get rid of unused xprt_receive() prototype.

 Also, organize function prototypes in xprt.h by usage and scope.

 Test-plan:
 Compile kernel with CONFIG_NFS enabled.

 Version: Thu, 11 Aug 2005 16:07:21 -0400

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/xprt.h |   61 +++++++++++++++++++++++++------------------
 net/sunrpc/clnt.c           |    2 +
 net/sunrpc/xprt.c           |   26 ++++++++----------
 net/sunrpc/xprtsock.c       |   12 +++++---
 4 files changed, 55 insertions(+), 46 deletions(-)

applies-to: f256182f85b4fdf9185903d6f0531f877e311c8e
55aa4f58aa43dc9a51fb80010630d94b96053a2e
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index d522399..bfbc492 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -1,5 +1,5 @@
 /*
- *  linux/include/linux/sunrpc/clnt_xprt.h
+ *  linux/include/linux/sunrpc/xprt.h
  *
  *  Declarations for the RPC transport interface.
  *
@@ -150,8 +150,8 @@ struct rpc_xprt {
 	unsigned long		cong;		/* current congestion */
 	unsigned long		cwnd;		/* congestion window */
 
-	unsigned int		rcvsize,	/* socket receive buffer size */
-				sndsize;	/* socket send buffer size */
+	unsigned int		rcvsize,	/* transport rcv buffer size */
+				sndsize;	/* transport send buffer size */
 
 	size_t			max_payload;	/* largest RPC payload size,
 						   in bytes */
@@ -184,12 +184,12 @@ struct rpc_xprt {
 	unsigned long		tcp_copied,	/* copied to request */
 				tcp_flags;
 	/*
-	 * Connection of sockets
+	 * Connection of transports
 	 */
-	struct work_struct	sock_connect;
+	struct work_struct	connect_worker;
 	unsigned short		port;
 	/*
-	 * Disconnection of idle sockets
+	 * Disconnection of idle transports
 	 */
 	struct work_struct	task_cleanup;
 	struct timer_list	timer;
@@ -219,27 +219,36 @@ struct rpc_xprt {
 
 #ifdef __KERNEL__
 
-struct rpc_xprt *	xprt_create_proto(int proto, struct sockaddr_in *addr,
-					struct rpc_timeout *toparms);
-void			xprt_disconnect(struct rpc_xprt *);
-int			xprt_destroy(struct rpc_xprt *);
-void			xprt_set_timeout(struct rpc_timeout *, unsigned int,
-					unsigned long);
-struct rpc_rqst *	xprt_lookup_rqst(struct rpc_xprt *, u32);
-void			xprt_complete_rqst(struct rpc_xprt *,
-					struct rpc_rqst *, int);
-void			xprt_reserve(struct rpc_task *);
-int			xprt_prepare_transmit(struct rpc_task *);
-void			xprt_transmit(struct rpc_task *);
-void			xprt_receive(struct rpc_task *);
-void			xprt_wake_pending_tasks(struct rpc_xprt *, int);
+/*
+ * Transport operations used by ULPs
+ */
+struct rpc_xprt *	xprt_create_proto(int proto, struct sockaddr_in *addr, struct rpc_timeout *to);
+void			xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr);
+
+/*
+ * Generic internal transport functions
+ */
+void			xprt_connect(struct rpc_task *task);
+void			xprt_reserve(struct rpc_task *task);
+int			xprt_prepare_transmit(struct rpc_task *task);
+void			xprt_transmit(struct rpc_task *task);
 int			xprt_adjust_timeout(struct rpc_rqst *req);
-void			xprt_release(struct rpc_task *);
-void			xprt_connect(struct rpc_task *);
-int			xs_setup_udp(struct rpc_xprt *,
-					struct rpc_timeout *);
-int			xs_setup_tcp(struct rpc_xprt *,
-					struct rpc_timeout *);
+void			xprt_release(struct rpc_task *task);
+int			xprt_destroy(struct rpc_xprt *xprt);
+
+/*
+ * Transport switch helper functions
+ */
+void			xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status);
+struct rpc_rqst *	xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid);
+void			xprt_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied);
+void			xprt_disconnect(struct rpc_xprt *xprt);
+
+/*
+ * Socket transport setup operations
+ */
+int			xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to);
+int			xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to);
 
 /*
  * Reserved bit positions in xprt->state
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 0d1b010..4677959 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -1,5 +1,5 @@
 /*
- *  linux/net/sunrpc/rpcclnt.c
+ *  linux/net/sunrpc/clnt.c
  *
  *  This file contains the high-level RPC interface.
  *  It is modeled as a finite state machine to support both synchronous
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 2f9cd46..247fa1e 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -10,12 +10,12 @@
  *	one is available. Otherwise, it sleeps on the backlog queue
  *	(xprt_reserve).
  *  -	Next, the caller puts together the RPC message, stuffs it into
- *	the request struct, and calls xprt_call().
- *  -	xprt_call transmits the message and installs the caller on the
- *	socket's wait list. At the same time, it installs a timer that
+ *	the request struct, and calls xprt_transmit().
+ *  -	xprt_transmit sends the message and installs the caller on the
+ *	transport's wait list. At the same time, it installs a timer that
  *	is run after the packet's timeout has expired.
  *  -	When a packet arrives, the data_ready handler walks the list of
- *	pending requests for that socket. If a matching XID is found, the
+ *	pending requests for that transport. If a matching XID is found, the
  *	caller is woken up, and the timer removed.
  *  -	When no reply arrives within the timeout interval, the timer is
  *	fired by the kernel and runs xprt_timer(). It either adjusts the
@@ -32,6 +32,8 @@
  *  tasks that rely on callbacks.
  *
  *  Copyright (C) 1995-1997, Olaf Kirch <okir monad swb de>
+ *
+ *  Transport switch API copyright (C) 2005, Chuck Lever <cel netapp com>
  */
 
 #include <linux/module.h>
@@ -52,8 +54,6 @@
 # define RPCDBG_FACILITY	RPCDBG_XPRT
 #endif
 
-#define XPRT_MAX_BACKOFF	(8)
-
 /*
  * Local functions
  */
@@ -65,9 +65,9 @@ static int      __xprt_get_cong(struct r
 static int	xprt_clear_backlog(struct rpc_xprt *xprt);
 
 /*
- * Serialize write access to sockets, in order to prevent different
+ * Serialize write access to transports, in order to prevent different
  * requests from interfering with each other.
- * Also prevents TCP socket connects from colliding with writes.
+ * Also prevents transport connects from colliding with writes.
  */
 static int
 __xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
@@ -91,7 +91,7 @@ __xprt_lock_write(struct rpc_xprt *xprt,
 	clear_bit(XPRT_LOCKED, &xprt->state);
 	smp_mb__after_clear_bit();
 out_sleep:
-	dprintk("RPC: %4d failed to lock socket %p\n", task->tk_pid, xprt);
+	dprintk("RPC: %4d failed to lock transport %p\n", task->tk_pid, xprt);
 	task->tk_timeout = 0;
 	task->tk_status = -EAGAIN;
 	if (req && req->rq_ntrans)
@@ -144,7 +144,7 @@ out_unlock:
 }
 
 /*
- * Releases the socket for use by other requests.
+ * Releases the transport for use by other requests.
  */
 static void
 __xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task)
@@ -294,8 +294,7 @@ int xprt_adjust_timeout(struct rpc_rqst 
 	return status;
 }
 
-static void
-xprt_socket_autoclose(void *args)
+static void xprt_autoclose(void *args)
 {
 	struct rpc_xprt *xprt = (struct rpc_xprt *)args;
 
@@ -329,7 +328,6 @@ xprt_init_autodisconnect(unsigned long d
 	if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
 		goto out_abort;
 	spin_unlock(&xprt->transport_lock);
-	/* Let keventd close the socket */
 	if (xprt_connecting(xprt))
 		xprt_release_write(xprt, NULL);
 	else
@@ -770,7 +768,7 @@ static struct rpc_xprt *xprt_setup(int p
 
 	INIT_LIST_HEAD(&xprt->free);
 	INIT_LIST_HEAD(&xprt->recv);
-	INIT_WORK(&xprt->task_cleanup, xprt_socket_autoclose, xprt);
+	INIT_WORK(&xprt->task_cleanup, xprt_autoclose, xprt);
 	init_timer(&xprt->timer);
 	xprt->timer.function = xprt_init_autodisconnect;
 	xprt->timer.data = (unsigned long) xprt;
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 182da2e..7f0b9f7 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -11,6 +11,8 @@
  * Rewrite of larges part of the code in order to stabilize TCP stuff.
  * Fix behaviour when socket buffer is full.
  *  (C) 1999 Trond Myklebust <trond myklebust fys uio no>
+ *
+ * IP socket transport implementation, (C) 2005 Chuck Lever <cel netapp com>
  */
 
 #include <linux/types.h>
@@ -363,7 +365,7 @@ static void xs_destroy(struct rpc_xprt *
 {
 	dprintk("RPC:      xs_destroy xprt %p\n", xprt);
 
-	cancel_delayed_work(&xprt->sock_connect);
+	cancel_delayed_work(&xprt->connect_worker);
 	flush_scheduled_work();
 
 	xprt_disconnect(xprt);
@@ -938,11 +940,11 @@ static void xs_connect(struct rpc_task *
 	if (!xprt_test_and_set_connecting(xprt)) {
 		if (xprt->sock != NULL) {
 			dprintk("RPC:      xs_connect delayed xprt %p\n", xprt);
-			schedule_delayed_work(&xprt->sock_connect,
+			schedule_delayed_work(&xprt->connect_worker,
 					RPC_REESTABLISH_TIMEOUT);
 		} else {
 			dprintk("RPC:      xs_connect scheduled xprt %p\n", xprt);
-			schedule_work(&xprt->sock_connect);
+			schedule_work(&xprt->connect_worker);
 			/* flush_scheduled_work can sleep... */
 			if (!RPC_IS_ASYNC(task))
 				flush_scheduled_work();
@@ -989,7 +991,7 @@ int xs_setup_udp(struct rpc_xprt *xprt, 
 	/* XXX: header size can vary due to auth type, IPv6, etc. */
 	xprt->max_payload = (1U << 16) - (MAX_HEADER << 3);
 
-	INIT_WORK(&xprt->sock_connect, xs_connect_worker, xprt);
+	INIT_WORK(&xprt->connect_worker, xs_connect_worker, xprt);
 
 	xprt->ops = &xs_ops;
 
@@ -1028,7 +1030,7 @@ int xs_setup_tcp(struct rpc_xprt *xprt, 
 	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
 	xprt->max_payload = (1U << 31) - 1;
 
-	INIT_WORK(&xprt->sock_connect, xs_connect_worker, xprt);
+	INIT_WORK(&xprt->connect_worker, xs_connect_worker, xprt);
 
 	xprt->ops = &xs_ops;
 
---
0.99.8.GIT


--- NEW FILE 0236-RPC-separate-TCP-and-UDP-write-space-callbacks.txt ---
Subject: [PATCH] RPC: separate TCP and UDP write space callbacks
From: Chuck Lever <cel citi umich edu>
Date: 1123791950 -0400

 Split the socket write space callback function into a TCP version and UDP
 version, eliminating one dependence on the "xprt->stream" variable.

 Keep the common pieces of this path in xprt.c so other transports can use
 it too.

 Test-plan:
 Write-intensive workload on a single mount point.

 Version: Thu, 11 Aug 2005 16:07:51 -0400

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/xprt.h |    2 +
 net/sunrpc/xprt.c           |   34 +++++++++++++++++
 net/sunrpc/xprtsock.c       |   84 +++++++++++++++++++++++++++----------------
 3 files changed, 89 insertions(+), 31 deletions(-)

applies-to: 7b3d79bdc15c76c25d8a53437b9e4173ebc68f24
c7b2cae8a634015b72941ba2fc6c4bc9b8d3a129
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index bfbc492..e73174c 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -240,6 +240,8 @@ int			xprt_destroy(struct rpc_xprt *xprt
  * Transport switch helper functions
  */
 void			xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status);
+void			xprt_wait_for_buffer_space(struct rpc_task *task);
+void			xprt_write_space(struct rpc_xprt *xprt);
 struct rpc_rqst *	xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid);
 void			xprt_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied);
 void			xprt_disconnect(struct rpc_xprt *xprt);
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 247fa1e..31ef7dc 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -241,6 +241,40 @@ void xprt_wake_pending_tasks(struct rpc_
 		rpc_wake_up(&xprt->pending);
 }
 
+/**
+ * xprt_wait_for_buffer_space - wait for transport output buffer to clear
+ * @task: task to be put to sleep
+ *
+ */
+void xprt_wait_for_buffer_space(struct rpc_task *task)
+{
+	struct rpc_rqst *req = task->tk_rqstp;
+	struct rpc_xprt *xprt = req->rq_xprt;
+
+	task->tk_timeout = req->rq_timeout;
+	rpc_sleep_on(&xprt->pending, task, NULL, NULL);
+}
+
+/**
+ * xprt_write_space - wake the task waiting for transport output buffer space
+ * @xprt: transport with waiting tasks
+ *
+ * Can be called in a soft IRQ context, so xprt_write_space never sleeps.
+ */
+void xprt_write_space(struct rpc_xprt *xprt)
+{
+	if (unlikely(xprt->shutdown))
+		return;
+
+	spin_lock_bh(&xprt->transport_lock);
+	if (xprt->snd_task) {
+		dprintk("RPC:      write space: waking waiting task on xprt %p\n",
+				xprt);
+		rpc_wake_up_task(xprt->snd_task);
+	}
+	spin_unlock_bh(&xprt->transport_lock);
+}
+
 static void xprt_reset_majortimeo(struct rpc_rqst *req)
 {
 	struct rpc_timeout *to = &req->rq_xprt->timeout;
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 7f0b9f7..70a772d 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -308,15 +308,13 @@ static int xs_send_request(struct rpc_ta
 
 	if (status == -EAGAIN) {
 		if (test_bit(SOCK_ASYNC_NOSPACE, &xprt->sock->flags)) {
-			/* Protect against races with xs_write_space */
+			/* Protect against races with write_space */
 			spin_lock_bh(&xprt->transport_lock);
 			/* Don't race with disconnect */
 			if (!xprt_connected(xprt))
 				task->tk_status = -ENOTCONN;
-			else if (test_bit(SOCK_NOSPACE, &xprt->sock->flags)) {
-				task->tk_timeout = req->rq_timeout;
-				rpc_sleep_on(&xprt->pending, task, NULL, NULL);
-			}
+			else if (test_bit(SOCK_NOSPACE, &xprt->sock->flags))
+				xprt_wait_for_buffer_space(task);
 			spin_unlock_bh(&xprt->transport_lock);
 			return status;
 		}
@@ -721,45 +719,68 @@ static void xs_tcp_state_change(struct s
 }
 
 /**
- * xs_write_space - callback invoked when socket buffer space becomes
- *                         available
+ * xs_udp_write_space - callback invoked when socket buffer space
+ *                             becomes available
  * @sk: socket whose state has changed
  *
  * Called when more output buffer space is available for this socket.
  * We try not to wake our writers until they can make "significant"
- * progress, otherwise we'll waste resources thrashing sock_sendmsg
+ * progress, otherwise we'll waste resources thrashing kernel_sendmsg
  * with a bunch of small requests.
  */
-static void xs_write_space(struct sock *sk)
+static void xs_udp_write_space(struct sock *sk)
 {
-	struct rpc_xprt *xprt;
-	struct socket *sock;
-
 	read_lock(&sk->sk_callback_lock);
-	if (!(xprt = xprt_from_sock(sk)) || !(sock = sk->sk_socket))
-		goto out;
-	if (xprt->shutdown)
-		goto out;
 
-	/* Wait until we have enough socket memory */
-	if (xprt->stream) {
-		/* from net/core/stream.c:sk_stream_write_space */
-		if (sk_stream_wspace(sk) < sk_stream_min_wspace(sk))
+	/* from net/core/sock.c:sock_def_write_space */
+	if (sock_writeable(sk)) {
+		struct socket *sock;
+		struct rpc_xprt *xprt;
+
+		if (unlikely(!(sock = sk->sk_socket)))
 			goto out;
-	} else {
-		/* from net/core/sock.c:sock_def_write_space */
-		if (!sock_writeable(sk))
+		if (unlikely(!(xprt = xprt_from_sock(sk))))
+			goto out;
+		if (unlikely(!test_and_clear_bit(SOCK_NOSPACE, &sock->flags)))
 			goto out;
+
+		xprt_write_space(xprt);
 	}
 
-	if (!test_and_clear_bit(SOCK_NOSPACE, &sock->flags))
-		goto out;
+ out:
+	read_unlock(&sk->sk_callback_lock);
+}
 
-	spin_lock_bh(&xprt->transport_lock);
-	if (xprt->snd_task)
-		rpc_wake_up_task(xprt->snd_task);
-	spin_unlock_bh(&xprt->transport_lock);
-out:
+/**
+ * xs_tcp_write_space - callback invoked when socket buffer space
+ *                             becomes available
+ * @sk: socket whose state has changed
+ *
+ * Called when more output buffer space is available for this socket.
+ * We try not to wake our writers until they can make "significant"
+ * progress, otherwise we'll waste resources thrashing kernel_sendmsg
+ * with a bunch of small requests.
+ */
+static void xs_tcp_write_space(struct sock *sk)
+{
+	read_lock(&sk->sk_callback_lock);
+
+	/* from net/core/stream.c:sk_stream_write_space */
+	if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) {
+		struct socket *sock;
+		struct rpc_xprt *xprt;
+
+		if (unlikely(!(sock = sk->sk_socket)))
+			goto out;
+		if (unlikely(!(xprt = xprt_from_sock(sk))))
+			goto out;
+		if (unlikely(!test_and_clear_bit(SOCK_NOSPACE, &sock->flags)))
+			goto out;
+
+		xprt_write_space(xprt);
+	}
+
+ out:
 	read_unlock(&sk->sk_callback_lock);
 }
 
@@ -855,15 +876,16 @@ static void xs_bind(struct rpc_xprt *xpr
 	xprt->old_write_space = sk->sk_write_space;
 	if (xprt->prot == IPPROTO_UDP) {
 		sk->sk_data_ready = xs_udp_data_ready;
+		sk->sk_write_space = xs_udp_write_space;
 		sk->sk_no_check = UDP_CSUM_NORCV;
 		xprt_set_connected(xprt);
 	} else {
 		tcp_sk(sk)->nonagle = 1;	/* disable Nagle's algorithm */
 		sk->sk_data_ready = xs_tcp_data_ready;
 		sk->sk_state_change = xs_tcp_state_change;
+		sk->sk_write_space = xs_tcp_write_space;
 		xprt_clear_connected(xprt);
 	}
-	sk->sk_write_space = xs_write_space;
 
 	/* Reset to new socket */
 	xprt->sock = sock;
---
0.99.8.GIT


--- NEW FILE 0237-RPC-separate-TCP-and-UDP-transport-connection-logic.txt ---
Subject: [PATCH] RPC: separate TCP and UDP transport connection logic
From: Chuck Lever <cel citi umich edu>
Date: 1123791953 -0400

 Create separate connection worker functions for managing UDP and TCP
 transport sockets.  This eliminates several dependencies on "xprt->stream".

 Test-plan:
 Destructive testing (unplugging the network temporarily).  Connectathon with
 v2, v3, and v4.

 Version: Thu, 11 Aug 2005 16:08:18 -0400

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 net/sunrpc/xprtsock.c |  164 +++++++++++++++++++++++++++----------------------
 1 files changed, 91 insertions(+), 73 deletions(-)

applies-to: 95f561877d67eed80a823daa6ef0c00ad1c060eb
b0d93ad511ce2f37823a07c7a3258117a431f5fb
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 70a772d..f915297 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -836,102 +836,118 @@ static int xs_bindresvport(struct rpc_xp
 	return err;
 }
 
-static struct socket *xs_create(struct rpc_xprt *xprt, int proto, int resvport)
+/**
+ * xs_udp_connect_worker - set up a UDP socket
+ * @args: RPC transport to connect
+ *
+ * Invoked by a work queue tasklet.
+ */
+static void xs_udp_connect_worker(void *args)
 {
-	struct socket *sock;
-	int type, err;
-
-	dprintk("RPC:      xs_create(%s %d)\n",
-			   (proto == IPPROTO_UDP)? "udp" : "tcp", proto);
+	struct rpc_xprt *xprt = (struct rpc_xprt *) args;
+	struct socket *sock = xprt->sock;
+	int err, status = -EIO;
 
-	type = (proto == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
+	if (xprt->shutdown || xprt->addr.sin_port == 0)
+		goto out;
 
-	if ((err = sock_create_kern(PF_INET, type, proto, &sock)) < 0) {
-		dprintk("RPC:      can't create socket (%d).\n", -err);
-		return NULL;
-	}
+	dprintk("RPC:      xs_udp_connect_worker for xprt %p\n", xprt);
 
-	/* If the caller has the capability, bind to a reserved port */
-	if (resvport && xs_bindresvport(xprt, sock) < 0)
-		goto failed;
+	/* Start by resetting any existing state */
+	xs_close(xprt);
 
-	return sock;
+	if ((err = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock)) < 0) {
+		dprintk("RPC:      can't create UDP transport socket (%d).\n", -err);
+		goto out;
+	}
 
-failed:
-	sock_release(sock);
-	return NULL;
-}
+	if (xprt->resvport && xs_bindresvport(xprt, sock) < 0) {
+		sock_release(sock);
+		goto out;
+	}
 
-static void xs_bind(struct rpc_xprt *xprt, struct socket *sock)
-{
-	struct sock *sk = sock->sk;
+	if (!xprt->inet) {
+		struct sock *sk = sock->sk;
 
-	if (xprt->inet)
-		return;
+		write_lock_bh(&sk->sk_callback_lock);
 
-	write_lock_bh(&sk->sk_callback_lock);
-	sk->sk_user_data = xprt;
-	xprt->old_data_ready = sk->sk_data_ready;
-	xprt->old_state_change = sk->sk_state_change;
-	xprt->old_write_space = sk->sk_write_space;
-	if (xprt->prot == IPPROTO_UDP) {
+		sk->sk_user_data = xprt;
+		xprt->old_data_ready = sk->sk_data_ready;
+		xprt->old_state_change = sk->sk_state_change;
+		xprt->old_write_space = sk->sk_write_space;
 		sk->sk_data_ready = xs_udp_data_ready;
 		sk->sk_write_space = xs_udp_write_space;
 		sk->sk_no_check = UDP_CSUM_NORCV;
+
 		xprt_set_connected(xprt);
-	} else {
-		tcp_sk(sk)->nonagle = 1;	/* disable Nagle's algorithm */
-		sk->sk_data_ready = xs_tcp_data_ready;
-		sk->sk_state_change = xs_tcp_state_change;
-		sk->sk_write_space = xs_tcp_write_space;
-		xprt_clear_connected(xprt);
-	}
 
-	/* Reset to new socket */
-	xprt->sock = sock;
-	xprt->inet = sk;
-	write_unlock_bh(&sk->sk_callback_lock);
+		/* Reset to new socket */
+		xprt->sock = sock;
+		xprt->inet = sk;
 
-	return;
+		write_unlock_bh(&sk->sk_callback_lock);
+	}
+	xs_set_buffer_size(xprt);
+	status = 0;
+out:
+	xprt_wake_pending_tasks(xprt, status);
+	xprt_clear_connecting(xprt);
 }
 
 /**
- * xs_connect_worker - try to connect a socket to a remote endpoint
+ * xs_tcp_connect_worker - connect a TCP socket to a remote endpoint
  * @args: RPC transport to connect
  *
  * Invoked by a work queue tasklet.
  */
-static void xs_connect_worker(void *args)
+static void xs_tcp_connect_worker(void *args)
 {
 	struct rpc_xprt *xprt = (struct rpc_xprt *)args;
 	struct socket *sock = xprt->sock;
-	int status = -EIO;
+	int err, status = -EIO;
 
 	if (xprt->shutdown || xprt->addr.sin_port == 0)
 		goto out;
 
-	dprintk("RPC:      xs_connect_worker xprt %p\n", xprt);
+	dprintk("RPC:      xs_tcp_connect_worker for xprt %p\n", xprt);
 
-	/*
-	 * Start by resetting any existing state
-	 */
+	/* Start by resetting any existing socket state */
 	xs_close(xprt);
-	sock = xs_create(xprt, xprt->prot, xprt->resvport);
-	if (sock == NULL) {
-		/* couldn't create socket or bind to reserved port;
-		 * this is likely a permanent error, so cause an abort */
+
+	if ((err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) {
+		dprintk("RPC:      can't create TCP transport socket (%d).\n", -err);
 		goto out;
 	}
-	xs_bind(xprt, sock);
-	xs_set_buffer_size(xprt);
 
-	status = 0;
-	if (!xprt->stream)
+	if (xprt->resvport && xs_bindresvport(xprt, sock) < 0) {
+		sock_release(sock);
 		goto out;
+	}
+
+	if (!xprt->inet) {
+		struct sock *sk = sock->sk;
 
-	/*
-	 * Tell the socket layer to start connecting...
-	 */
+		write_lock_bh(&sk->sk_callback_lock);
+
+		sk->sk_user_data = xprt;
+		xprt->old_data_ready = sk->sk_data_ready;
+		xprt->old_state_change = sk->sk_state_change;
+		xprt->old_write_space = sk->sk_write_space;
+		sk->sk_data_ready = xs_tcp_data_ready;
+		sk->sk_state_change = xs_tcp_state_change;
+		sk->sk_write_space = xs_tcp_write_space;
+		tcp_sk(sk)->nonagle = 1;
+
+		xprt_clear_connected(xprt);
+
+		/* Reset to new socket */
+		xprt->sock = sock;
+		xprt->inet = sk;
+
+		write_unlock_bh(&sk->sk_callback_lock);
+	}
+
+	/* Tell the socket layer to start connecting... */
 	status = sock->ops->connect(sock, (struct sockaddr *) &xprt->addr,
 			sizeof(xprt->addr), O_NONBLOCK);
 	dprintk("RPC: %p  connect status %d connected %d sock state %d\n",
@@ -959,18 +975,20 @@ static void xs_connect(struct rpc_task *
 {
 	struct rpc_xprt *xprt = task->tk_xprt;
 
-	if (!xprt_test_and_set_connecting(xprt)) {
-		if (xprt->sock != NULL) {
-			dprintk("RPC:      xs_connect delayed xprt %p\n", xprt);
-			schedule_delayed_work(&xprt->connect_worker,
+	if (xprt_test_and_set_connecting(xprt))
+		return;
+
+	if (xprt->sock != NULL) {
+		dprintk("RPC:      xs_connect delayed xprt %p\n", xprt);
+		schedule_delayed_work(&xprt->connect_worker,
 					RPC_REESTABLISH_TIMEOUT);
-		} else {
-			dprintk("RPC:      xs_connect scheduled xprt %p\n", xprt);
-			schedule_work(&xprt->connect_worker);
-			/* flush_scheduled_work can sleep... */
-			if (!RPC_IS_ASYNC(task))
-				flush_scheduled_work();
-		}
+	} else {
+		dprintk("RPC:      xs_connect scheduled xprt %p\n", xprt);
+		schedule_work(&xprt->connect_worker);
+
+		/* flush_scheduled_work can sleep... */
+		if (!RPC_IS_ASYNC(task))
+			flush_scheduled_work();
 	}
 }
 
@@ -1013,7 +1031,7 @@ int xs_setup_udp(struct rpc_xprt *xprt, 
 	/* XXX: header size can vary due to auth type, IPv6, etc. */
 	xprt->max_payload = (1U << 16) - (MAX_HEADER << 3);
 
-	INIT_WORK(&xprt->connect_worker, xs_connect_worker, xprt);
+	INIT_WORK(&xprt->connect_worker, xs_udp_connect_worker, xprt);
 
 	xprt->ops = &xs_ops;
 
@@ -1052,7 +1070,7 @@ int xs_setup_tcp(struct rpc_xprt *xprt, 
 	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
 	xprt->max_payload = (1U << 31) - 1;
 
-	INIT_WORK(&xprt->connect_worker, xs_connect_worker, xprt);
+	INIT_WORK(&xprt->connect_worker, xs_tcp_connect_worker, xprt);
 
 	xprt->ops = &xs_ops;
 
---
0.99.8.GIT


--- NEW FILE 0238-RPC-separate-TCP-and-UDP-socket-write-paths.txt ---
Subject: [PATCH] RPC: separate TCP and UDP socket write paths
From: Chuck Lever <cel citi umich edu>
Date: 1123791956 -0400

 Split the RPC client's main socket write path into a TCP version and a UDP
 version to eliminate another dependency on the "xprt->stream" variable.

 Compiler optimization removes unneeded code from xs_sendpages, as this
 function is now called with some constant arguments.

 We can now cleanly perform transport protocol-specific return code testing
 and error recovery in each path.

 Test-plan:
 Millions of fsx operations.  Performance characterization such as
 "sio" or "iozone".  Examine oprofile results for any changes before and
 after this patch is applied.

 Version: Thu, 11 Aug 2005 16:08:46 -0400

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 net/sunrpc/xprtsock.c |  215 +++++++++++++++++++++++++++++--------------------
 1 files changed, 128 insertions(+), 87 deletions(-)

applies-to: a9fc753bf821d1d71c345f58e056511dfd0cf5ac
262965f53defd312a294b45366ea17907b6a616b
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index f915297..5798830 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -40,6 +40,12 @@
  */
 #define XS_MAX_RESVPORT		(800U)
 
+/*
+ * How many times to try sending a request on a socket before waiting
+ * for the socket buffer to clear.
+ */
+#define XS_SENDMSG_RETRY	(10U)
+
 #ifdef RPC_DEBUG
 # undef  RPC_DEBUG_DATA
 # define RPCDBG_FACILITY	RPCDBG_TRANS
@@ -114,13 +120,18 @@ static int xs_send_tail(struct socket *s
  * @base: starting position in the buffer
  *
  */
-static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base)
+static inline int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base)
 {
 	struct page **ppage = xdr->pages;
 	unsigned int len, pglen = xdr->page_len;
 	int err, ret = 0;
 	ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
 
+	if (unlikely(!sock))
+		return -ENOTCONN;
+
+	clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
+
 	len = xdr->head[0].iov_len;
 	if (base < len || (addr != NULL && base == 0)) {
 		err = xs_send_head(sock, addr, addrlen, xdr, base, len);
@@ -187,140 +198,162 @@ out:
 }
 
 /**
- * xs_sendmsg - write an RPC request to a socket
- * @xprt: generic transport
- * @req: the RPC request to write
+ * xs_nospace - place task on wait queue if transmit was incomplete
+ * @task: task to put to sleep
  *
  */
-static int xs_sendmsg(struct rpc_xprt *xprt, struct rpc_rqst *req)
+static void xs_nospace(struct rpc_task *task)
 {
-	struct socket *sock = xprt->sock;
-	struct xdr_buf *xdr = &req->rq_snd_buf;
-	struct sockaddr *addr = NULL;
-	int addrlen = 0;
-	unsigned int skip;
-	int result;
+	struct rpc_rqst *req = task->tk_rqstp;
+	struct rpc_xprt *xprt = req->rq_xprt;
 
-	if (!sock)
-		return -ENOTCONN;
+	dprintk("RPC: %4d xmit incomplete (%u left of %u)\n",
+			task->tk_pid, req->rq_slen - req->rq_bytes_sent,
+			req->rq_slen);
+
+	if (test_bit(SOCK_ASYNC_NOSPACE, &xprt->sock->flags)) {
+		/* Protect against races with write_space */
+		spin_lock_bh(&xprt->transport_lock);
+
+		/* Don't race with disconnect */
+		if (!xprt_connected(xprt))
+			task->tk_status = -ENOTCONN;
+		else if (test_bit(SOCK_NOSPACE, &xprt->sock->flags))
+			xprt_wait_for_buffer_space(task);
+
+		spin_unlock_bh(&xprt->transport_lock);
+	} else
+		/* Keep holding the socket if it is blocked */
+		rpc_delay(task, HZ>>4);
+}
+
+/**
+ * xs_udp_send_request - write an RPC request to a UDP socket
+ * @task: address of RPC task that manages the state of an RPC request
+ *
+ * Return values:
+ *        0:	The request has been sent
+ *   EAGAIN:	The socket was blocked, please call again later to
+ *		complete the request
+ * ENOTCONN:	Caller needs to invoke connect logic then call again
+ *    other:	Some other error occured, the request was not sent
+ */
+static int xs_udp_send_request(struct rpc_task *task)
+{
+	struct rpc_rqst *req = task->tk_rqstp;
+	struct rpc_xprt *xprt = req->rq_xprt;
+	struct xdr_buf *xdr = &req->rq_snd_buf;
+	int status;
 
 	xs_pktdump("packet data:";,
 				req->rq_svec->iov_base,
 				req->rq_svec->iov_len);
 
-	/* For UDP, we need to provide an address */
-	if (!xprt->stream) {
-		addr = (struct sockaddr *) &xprt->addr;
-		addrlen = sizeof(xprt->addr);
-	}
-	/* Don't repeat bytes */
-	skip = req->rq_bytes_sent;
+	req->rq_xtime = jiffies;
+	status = xs_sendpages(xprt->sock, (struct sockaddr *) &xprt->addr,
+				sizeof(xprt->addr), xdr, req->rq_bytes_sent);
 
-	clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
-	result = xs_sendpages(sock, addr, addrlen, xdr, skip);
+	dprintk("RPC:      xs_udp_send_request(%u) = %d\n",
+			xdr->len - req->rq_bytes_sent, status);
 
-	dprintk("RPC:      xs_sendmsg(%d) = %d\n", xdr->len - skip, result);
+	if (likely(status >= (int) req->rq_slen))
+		return 0;
 
-	if (result >= 0)
-		return result;
+	/* Still some bytes left; set up for a retry later. */
+	if (status > 0)
+		status = -EAGAIN;
 
-	switch (result) {
+	switch (status) {
+	case -ENETUNREACH:
+	case -EPIPE:
 	case -ECONNREFUSED:
 		/* When the server has died, an ICMP port unreachable message
 		 * prompts ECONNREFUSED. */
-	case -EAGAIN:
 		break;
-	case -ECONNRESET:
-	case -ENOTCONN:
-	case -EPIPE:
-		/* connection broken */
-		if (xprt->stream)
-			result = -ENOTCONN;
+	case -EAGAIN:
+		xs_nospace(task);
 		break;
 	default:
+		dprintk("RPC:      sendmsg returned unrecognized error %d\n",
+			-status);
 		break;
 	}
-	return result;
+
+	return status;
 }
 
 /**
- * xs_send_request - write an RPC request to a socket
+ * xs_tcp_send_request - write an RPC request to a TCP socket
  * @task: address of RPC task that manages the state of an RPC request
  *
  * Return values:
- *      0:  The request has been sent
- * EAGAIN:  The socket was blocked, please call again later to
- *          complete the request
- *  other:  Some other error occured, the request was not sent
+ *        0:	The request has been sent
+ *   EAGAIN:	The socket was blocked, please call again later to
+ *		complete the request
+ * ENOTCONN:	Caller needs to invoke connect logic then call again
+ *    other:	Some other error occured, the request was not sent
  *
  * XXX: In the case of soft timeouts, should we eventually give up
- *      if the socket is not able to make progress?
+ *	if sendmsg is not able to make progress?
  */
-static int xs_send_request(struct rpc_task *task)
+static int xs_tcp_send_request(struct rpc_task *task)
 {
 	struct rpc_rqst *req = task->tk_rqstp;
 	struct rpc_xprt *xprt = req->rq_xprt;
+	struct xdr_buf *xdr = &req->rq_snd_buf;
+	u32 *marker = req->rq_svec[0].iov_base;
 	int status, retry = 0;
 
-	/* set up everything as needed. */
 	/* Write the record marker */
-	if (xprt->stream) {
-		u32 *marker = req->rq_svec[0].iov_base;
+	*marker = htonl(0x80000000|(req->rq_slen-sizeof(*marker)));
 
-		*marker = htonl(0x80000000|(req->rq_slen-sizeof(*marker)));
-	}
+	xs_pktdump("packet data:";,
+				req->rq_svec->iov_base,
+				req->rq_svec->iov_len);
 
 	/* Continue transmitting the packet/record. We must be careful
 	 * to cope with writespace callbacks arriving _after_ we have
-	 * called sendmsg().
-	 */
+	 * called sendmsg(). */
 	while (1) {
 		req->rq_xtime = jiffies;
-		status = xs_sendmsg(xprt, req);
-
-		if (status < 0)
-			break;
+		status = xs_sendpages(xprt->sock, NULL, 0, xdr,
+						req->rq_bytes_sent);
 
-		if (xprt->stream) {
-			req->rq_bytes_sent += status;
+		dprintk("RPC:      xs_tcp_send_request(%u) = %d\n",
+				xdr->len - req->rq_bytes_sent, status);
 
-			/* If we've sent the entire packet, immediately
-			 * reset the count of bytes sent. */
-			if (req->rq_bytes_sent >= req->rq_slen) {
-				req->rq_bytes_sent = 0;
-				return 0;
-			}
-		} else {
-			if (status >= req->rq_slen)
-				return 0;
-			status = -EAGAIN;
+		if (unlikely(status < 0))
 			break;
-		}
 
-		dprintk("RPC: %4d xmit incomplete (%d left of %d)\n",
-				task->tk_pid, req->rq_slen - req->rq_bytes_sent,
-				req->rq_slen);
+		/* If we've sent the entire packet, immediately
+		 * reset the count of bytes sent. */
+		req->rq_bytes_sent += status;
+		if (likely(req->rq_bytes_sent >= req->rq_slen)) {
+			req->rq_bytes_sent = 0;
+			return 0;
+		}
 
 		status = -EAGAIN;
-		if (retry++ > 50)
+		if (retry++ > XS_SENDMSG_RETRY)
 			break;
 	}
 
-	if (status == -EAGAIN) {
-		if (test_bit(SOCK_ASYNC_NOSPACE, &xprt->sock->flags)) {
-			/* Protect against races with write_space */
-			spin_lock_bh(&xprt->transport_lock);
-			/* Don't race with disconnect */
-			if (!xprt_connected(xprt))
-				task->tk_status = -ENOTCONN;
-			else if (test_bit(SOCK_NOSPACE, &xprt->sock->flags))
-				xprt_wait_for_buffer_space(task);
-			spin_unlock_bh(&xprt->transport_lock);
-			return status;
-		}
-		/* Keep holding the socket if it is blocked */
-		rpc_delay(task, HZ>>4);
+	switch (status) {
+	case -EAGAIN:
+		xs_nospace(task);
+		break;
+	case -ECONNREFUSED:
+	case -ECONNRESET:
+	case -ENOTCONN:
+	case -EPIPE:
+		status = -ENOTCONN;
+		break;
+	default:
+		dprintk("RPC:      sendmsg returned unrecognized error %d\n",
+			-status);
+		break;
 	}
+
 	return status;
 }
 
@@ -992,10 +1025,18 @@ static void xs_connect(struct rpc_task *
 	}
 }
 
-static struct rpc_xprt_ops xs_ops = {
+static struct rpc_xprt_ops xs_udp_ops = {
+	.set_buffer_size	= xs_set_buffer_size,
+	.connect		= xs_connect,
+	.send_request		= xs_udp_send_request,
+	.close			= xs_close,
+	.destroy		= xs_destroy,
+};
+
+static struct rpc_xprt_ops xs_tcp_ops = {
 	.set_buffer_size	= xs_set_buffer_size,
 	.connect		= xs_connect,
-	.send_request		= xs_send_request,
+	.send_request		= xs_tcp_send_request,
 	.close			= xs_close,
 	.destroy		= xs_destroy,
 };
@@ -1033,7 +1074,7 @@ int xs_setup_udp(struct rpc_xprt *xprt, 
 
 	INIT_WORK(&xprt->connect_worker, xs_udp_connect_worker, xprt);
 
-	xprt->ops = &xs_ops;
+	xprt->ops = &xs_udp_ops;
 
 	if (to)
 		xprt->timeout = *to;
@@ -1072,7 +1113,7 @@ int xs_setup_tcp(struct rpc_xprt *xprt, 
 
 	INIT_WORK(&xprt->connect_worker, xs_tcp_connect_worker, xprt);
 
-	xprt->ops = &xs_ops;
+	xprt->ops = &xs_tcp_ops;
 
 	if (to)
 		xprt->timeout = *to;
---
0.99.8.GIT


--- NEW FILE 0239-RPC-skip-over-transport-specific-heads-automatically.txt ---
Subject: [PATCH] RPC: skip over transport-specific heads automatically
From: Chuck Lever <cel netapp com>
Date: 1125012349 -0700

 Add a generic mechanism for skipping over transport-specific headers
 when constructing an RPC request.  This removes another "xprt->stream"
 dependency.

 Test-plan:
 Write-intensive workload on a single mount point (try both UDP and
 TCP).

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/msg_prot.h |   25 +++++++++++++++++++++++++
 include/linux/sunrpc/xprt.h     |    7 +++++++
 net/sunrpc/auth_gss/auth_gss.c  |    6 ++----
 net/sunrpc/clnt.c               |    5 ++---
 net/sunrpc/xprtsock.c           |   24 +++++++++++++++++-------
 5 files changed, 53 insertions(+), 14 deletions(-)

applies-to: a5e0f194c02f230ff12d9d5b0933bad9eb8810ea
808012fbb23a52ec59352445d2076d175ad4ab26
diff --git a/include/linux/sunrpc/msg_prot.h b/include/linux/sunrpc/msg_prot.h
index 15f1153..f43f237 100644
--- a/include/linux/sunrpc/msg_prot.h
+++ b/include/linux/sunrpc/msg_prot.h
@@ -76,5 +76,30 @@ enum rpc_auth_stat {
 
 #define RPC_MAXNETNAMELEN	256
 
+/*
+ * From RFC 1831:
+ *
+ * "A record is composed of one or more record fragments.  A record
+ *  fragment is a four-byte header followed by 0 to (2**31) - 1 bytes of
+ *  fragment data.  The bytes encode an unsigned binary number; as with
+ *  XDR integers, the byte order is from highest to lowest.  The number
+ *  encodes two values -- a boolean which indicates whether the fragment
+ *  is the last fragment of the record (bit value 1 implies the fragment
+ *  is the last fragment) and a 31-bit unsigned binary value which is the
+ *  length in bytes of the fragment's data.  The boolean value is the
+ *  highest-order bit of the header; the length is the 31 low-order bits.
+ *  (Note that this record specification is NOT in XDR standard form!)"
+ *
+ * The Linux RPC client always sends its requests in a single record
+ * fragment, limiting the maximum payload size for stream transports to
+ * 2GB.
+ */
+
+typedef u32	rpc_fraghdr;
+
+#define	RPC_LAST_STREAM_FRAGMENT	(1U << 31)
+#define	RPC_FRAGMENT_SIZE_MASK		(~RPC_LAST_STREAM_FRAGMENT)
+#define	RPC_MAX_FRAGMENT_SIZE		((1U << 31) - 1)
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SUNRPC_MSGPROT_H_ */
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index e73174c..966c456 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -155,6 +155,8 @@ struct rpc_xprt {
 
 	size_t			max_payload;	/* largest RPC payload size,
 						   in bytes */
+	unsigned int		tsh_size;	/* size of transport specific
+						   header */
 
 	struct rpc_wait_queue	sending;	/* requests waiting to send */
 	struct rpc_wait_queue	resend;		/* requests waiting to resend */
@@ -236,6 +238,11 @@ int			xprt_adjust_timeout(struct rpc_rqs
 void			xprt_release(struct rpc_task *task);
 int			xprt_destroy(struct rpc_xprt *xprt);
 
+static inline u32 *xprt_skip_transport_header(struct rpc_xprt *xprt, u32 *p)
+{
+	return p + xprt->tsh_size;
+}
+
 /*
  * Transport switch helper functions
  */
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 53a030a..d2b08f1 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -844,10 +844,8 @@ gss_marshal(struct rpc_task *task, u32 *
 
 	/* We compute the checksum for the verifier over the xdr-encoded bytes
 	 * starting with the xid and ending at the end of the credential: */
-	iov.iov_base = req->rq_snd_buf.head[0].iov_base;
-	if (task->tk_client->cl_xprt->stream)
-		/* See clnt.c:call_header() */
-		iov.iov_base += 4;
+	iov.iov_base = xprt_skip_transport_header(task->tk_xprt,
+					req->rq_snd_buf.head[0].iov_base);
 	iov.iov_len = (u8 *)p - (u8 *)iov.iov_base;
 	xdr_buf_from_iov(&iov, &verf_buf);
 
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 4677959..cc1b773 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -1075,13 +1075,12 @@ static u32 *
 call_header(struct rpc_task *task)
 {
 	struct rpc_clnt *clnt = task->tk_client;
-	struct rpc_xprt *xprt = clnt->cl_xprt;
 	struct rpc_rqst	*req = task->tk_rqstp;
 	u32		*p = req->rq_svec[0].iov_base;
 
 	/* FIXME: check buffer size? */
-	if (xprt->stream)
-		*p++ = 0;		/* fill in later */
+
+	p = xprt_skip_transport_header(task->tk_xprt, p);
 	*p++ = req->rq_xid;		/* XID */
 	*p++ = htonl(RPC_CALL);		/* CALL */
 	*p++ = htonl(RPC_VERSION);	/* RPC version */
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 5798830..aaf053b 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -282,6 +282,13 @@ static int xs_udp_send_request(struct rp
 	return status;
 }
 
+static inline void xs_encode_tcp_record_marker(struct xdr_buf *buf)
+{
+	u32 reclen = buf->len - sizeof(rpc_fraghdr);
+	rpc_fraghdr *base = buf->head[0].iov_base;
+	*base = htonl(RPC_LAST_STREAM_FRAGMENT | reclen);
+}
+
 /**
  * xs_tcp_send_request - write an RPC request to a TCP socket
  * @task: address of RPC task that manages the state of an RPC request
@@ -301,11 +308,9 @@ static int xs_tcp_send_request(struct rp
 	struct rpc_rqst *req = task->tk_rqstp;
 	struct rpc_xprt *xprt = req->rq_xprt;
 	struct xdr_buf *xdr = &req->rq_snd_buf;
-	u32 *marker = req->rq_svec[0].iov_base;
 	int status, retry = 0;
 
-	/* Write the record marker */
-	*marker = htonl(0x80000000|(req->rq_slen-sizeof(*marker)));
+	xs_encode_tcp_record_marker(&req->rq_snd_buf);
 
 	xs_pktdump("packet data:";,
 				req->rq_svec->iov_base,
@@ -503,16 +508,19 @@ static inline void xs_tcp_read_fraghdr(s
 	xprt->tcp_offset += used;
 	if (used != len)
 		return;
+
 	xprt->tcp_reclen = ntohl(xprt->tcp_recm);
-	if (xprt->tcp_reclen & 0x80000000)
+	if (xprt->tcp_reclen & RPC_LAST_STREAM_FRAGMENT)
 		xprt->tcp_flags |= XPRT_LAST_FRAG;
 	else
 		xprt->tcp_flags &= ~XPRT_LAST_FRAG;
-	xprt->tcp_reclen &= 0x7fffffff;
+	xprt->tcp_reclen &= RPC_FRAGMENT_SIZE_MASK;
+
 	xprt->tcp_flags &= ~XPRT_COPY_RECM;
 	xprt->tcp_offset = 0;
+
 	/* Sanity check of the record length */
-	if (xprt->tcp_reclen < 4) {
+	if (unlikely(xprt->tcp_reclen < 4)) {
 		dprintk("RPC:      invalid TCP record fragment length\n");
 		xprt_disconnect(xprt);
 		return;
@@ -1065,6 +1073,7 @@ int xs_setup_udp(struct rpc_xprt *xprt, 
 
 	xprt->prot = IPPROTO_UDP;
 	xprt->port = XS_MAX_RESVPORT;
+	xprt->tsh_size = 0;
 	xprt->stream = 0;
 	xprt->nocong = 0;
 	xprt->cwnd = RPC_INITCWND;
@@ -1105,11 +1114,12 @@ int xs_setup_tcp(struct rpc_xprt *xprt, 
 
 	xprt->prot = IPPROTO_TCP;
 	xprt->port = XS_MAX_RESVPORT;
+	xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32);
 	xprt->stream = 1;
 	xprt->nocong = 1;
 	xprt->cwnd = RPC_MAXCWND(xprt);
 	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
-	xprt->max_payload = (1U << 31) - 1;
+	xprt->max_payload = RPC_MAX_FRAGMENT_SIZE;
 
 	INIT_WORK(&xprt->connect_worker, xs_tcp_connect_worker, xprt);
 
---
0.99.8.GIT


--- NEW FILE 0240-RPC-get-rid-of-xprt-stream.txt ---
Subject: [PATCH] RPC: get rid of xprt->stream
From: Chuck Lever <cel netapp com>
Date: 1125012349 -0700

 Now we can fix up the last few places that use the "xprt->stream"
 variable, and get rid of it from the rpc_xprt structure.

 Test-plan:
 Destructive testing (unplugging the network temporarily).  Connectathon
 with UDP and TCP.

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 fs/lockd/host.c             |    3 +--
 include/linux/sunrpc/xprt.h |    3 +--
 net/sunrpc/xprt.c           |    3 +--
 net/sunrpc/xprtsock.c       |   28 ++++++++++++++++++----------
 4 files changed, 21 insertions(+), 16 deletions(-)

applies-to: 7175edb3917bc35f7f5484f567e91d7303a17663
43118c29dea2b23798bd42a147015cceee7fa885
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 82c77df..7901f5b 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -173,11 +173,10 @@ nlm_bind_host(struct nlm_host *host)
 
 	/* If we've already created an RPC client, check whether
 	 * RPC rebind is required
-	 * Note: why keep rebinding if we're on a tcp connection?
 	 */
 	if ((clnt = host->h_rpcclnt) != NULL) {
 		xprt = clnt->cl_xprt;
-		if (!xprt->stream && time_after_eq(jiffies, host->h_nextrebind)) {
+		if (time_after_eq(jiffies, host->h_nextrebind)) {
 			clnt->cl_port = 0;
 			host->h_nextrebind = jiffies + NLM_HOST_REBIND;
 			dprintk("lockd: next rebind in %ld jiffies\n",
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 966c456..c9477f0 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -168,8 +168,7 @@ struct rpc_xprt {
 	unsigned long		state;		/* transport state */
 	unsigned char		shutdown   : 1,	/* being shut down */
 				nocong	   : 1,	/* no congestion control */
-				resvport   : 1, /* use a reserved port */
-				stream     : 1;	/* TCP */
+				resvport   : 1; /* use a reserved port */
 
 	/*
 	 * XID
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 31ef7dc..43fef76 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -630,8 +630,7 @@ void xprt_transmit(struct rpc_task *task
 	case -ENOTCONN:
 		return;
 	default:
-		if (xprt->stream)
-			xprt_disconnect(xprt);
+		break;
 	}
 	xprt_release_write(xprt, task);
 	return;
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index aaf053b..5bb6fed 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -356,6 +356,7 @@ static int xs_tcp_send_request(struct rp
 	default:
 		dprintk("RPC:      sendmsg returned unrecognized error %d\n",
 			-status);
+		xprt_disconnect(xprt);
 		break;
 	}
 
@@ -826,19 +827,17 @@ static void xs_tcp_write_space(struct so
 }
 
 /**
- * xs_set_buffer_size - set send and receive limits
+ * xs_udp_set_buffer_size - set send and receive limits
  * @xprt: generic transport
  *
  * Set socket send and receive limits based on the
  * sndsize and rcvsize fields in the generic transport
- * structure. This applies only to UDP sockets.
+ * structure.
  */
-static void xs_set_buffer_size(struct rpc_xprt *xprt)
+static void xs_udp_set_buffer_size(struct rpc_xprt *xprt)
 {
 	struct sock *sk = xprt->inet;
 
-	if (xprt->stream)
-		return;
 	if (xprt->rcvsize) {
 		sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
 		sk->sk_rcvbuf = xprt->rcvsize * xprt->max_reqs *  2;
@@ -850,6 +849,17 @@ static void xs_set_buffer_size(struct rp
 	}
 }
 
+/**
+ * xs_tcp_set_buffer_size - set send and receive limits
+ * @xprt: generic transport
+ *
+ * Nothing to do for TCP.
+ */
+static void xs_tcp_set_buffer_size(struct rpc_xprt *xprt)
+{
+	return;
+}
+
 static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
 {
 	struct sockaddr_in myaddr = {
@@ -928,7 +938,7 @@ static void xs_udp_connect_worker(void *
 
 		write_unlock_bh(&sk->sk_callback_lock);
 	}
-	xs_set_buffer_size(xprt);
+	xs_udp_set_buffer_size(xprt);
 	status = 0;
 out:
 	xprt_wake_pending_tasks(xprt, status);
@@ -1034,7 +1044,7 @@ static void xs_connect(struct rpc_task *
 }
 
 static struct rpc_xprt_ops xs_udp_ops = {
-	.set_buffer_size	= xs_set_buffer_size,
+	.set_buffer_size	= xs_udp_set_buffer_size,
 	.connect		= xs_connect,
 	.send_request		= xs_udp_send_request,
 	.close			= xs_close,
@@ -1042,7 +1052,7 @@ static struct rpc_xprt_ops xs_udp_ops = 
 };
 
 static struct rpc_xprt_ops xs_tcp_ops = {
-	.set_buffer_size	= xs_set_buffer_size,
+	.set_buffer_size	= xs_tcp_set_buffer_size,
 	.connect		= xs_connect,
 	.send_request		= xs_tcp_send_request,
 	.close			= xs_close,
@@ -1074,7 +1084,6 @@ int xs_setup_udp(struct rpc_xprt *xprt, 
 	xprt->prot = IPPROTO_UDP;
 	xprt->port = XS_MAX_RESVPORT;
 	xprt->tsh_size = 0;
-	xprt->stream = 0;
 	xprt->nocong = 0;
 	xprt->cwnd = RPC_INITCWND;
 	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
@@ -1115,7 +1124,6 @@ int xs_setup_tcp(struct rpc_xprt *xprt, 
 	xprt->prot = IPPROTO_TCP;
 	xprt->port = XS_MAX_RESVPORT;
 	xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32);
-	xprt->stream = 1;
 	xprt->nocong = 1;
 	xprt->cwnd = RPC_MAXCWND(xprt);
 	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
---
0.99.8.GIT


--- NEW FILE 0241-RPC-add-API-to-set-transport-specific-timeouts.txt ---
Subject: [PATCH] RPC: add API to set transport-specific timeouts
From: Chuck Lever <cel netapp com>
Date: 1125012350 -0700

 Prepare the way to remove the "xprt->nocong" variable by adding a callout
 to the RPC client transport switch API to handle setting RPC retransmit
 timeouts.

 Add a pair of generic helper functions that provide the ability to set a
 simple fixed timeout, or to set a timeout based on the state of a round-
 trip estimator.

 Test-plan:
 Use WAN simulation to cause sporadic bursty packet loss.  Look for significant
 regression in performance or client stability.

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/xprt.h |    3 ++
 net/sunrpc/xprt.c           |   67 +++++++++++++++++++++++++++++--------------
 net/sunrpc/xprtsock.c       |    2 +
 3 files changed, 50 insertions(+), 22 deletions(-)

applies-to: 4951a6777a3dc167d46c1373c02d21912b250e96
fe3aca290f17ae4978bd73d02aa4029f1c9c024c
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index c9477f0..ac08e99 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -134,6 +134,7 @@ struct rpc_xprt_ops {
 	void		(*set_buffer_size)(struct rpc_xprt *xprt);
 	void		(*connect)(struct rpc_task *task);
 	int		(*send_request)(struct rpc_task *task);
+	void		(*set_retrans_timeout)(struct rpc_task *task);
 	void		(*close)(struct rpc_xprt *xprt);
 	void		(*destroy)(struct rpc_xprt *xprt);
 };
@@ -245,6 +246,8 @@ static inline u32 *xprt_skip_transport_h
 /*
  * Transport switch helper functions
  */
+void			xprt_set_retrans_timeout_def(struct rpc_task *task);
+void			xprt_set_retrans_timeout_rtt(struct rpc_task *task);
 void			xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status);
 void			xprt_wait_for_buffer_space(struct rpc_task *task);
 void			xprt_write_space(struct rpc_xprt *xprt);
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 43fef76..1ac2fbe 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -275,6 +275,38 @@ void xprt_write_space(struct rpc_xprt *x
 	spin_unlock_bh(&xprt->transport_lock);
 }
 
+/**
+ * xprt_set_retrans_timeout_def - set a request's retransmit timeout
+ * @task: task whose timeout is to be set
+ *
+ * Set a request's retransmit timeout based on the transport's
+ * default timeout parameters.  Used by transports that don't adjust
+ * the retransmit timeout based on round-trip time estimation.
+ */
+void xprt_set_retrans_timeout_def(struct rpc_task *task)
+{
+	task->tk_timeout = task->tk_rqstp->rq_timeout;
+}
+
+/*
+ * xprt_set_retrans_timeout_rtt - set a request's retransmit timeout
+ * @task: task whose timeout is to be set
+ * 
+ * Set a request's retransmit timeout using the RTT estimator.
+ */
+void xprt_set_retrans_timeout_rtt(struct rpc_task *task)
+{
+	int timer = task->tk_msg.rpc_proc->p_timer;
+	struct rpc_rtt *rtt = task->tk_client->cl_rtt;
+	struct rpc_rqst *req = task->tk_rqstp;
+	unsigned long max_timeout = req->rq_xprt->timeout.to_maxval;
+
+	task->tk_timeout = rpc_calc_rto(rtt, timer);
+	task->tk_timeout <<= rpc_ntimeo(rtt, timer) + req->rq_retries;
+	if (task->tk_timeout > max_timeout || task->tk_timeout == 0)
+		task->tk_timeout = max_timeout;
+}
+
 static void xprt_reset_majortimeo(struct rpc_rqst *req)
 {
 	struct rpc_timeout *to = &req->rq_xprt->timeout;
@@ -588,7 +620,6 @@ out_unlock:
  */
 void xprt_transmit(struct rpc_task *task)
 {
-	struct rpc_clnt *clnt = task->tk_client;
 	struct rpc_rqst	*req = task->tk_rqstp;
 	struct rpc_xprt	*xprt = req->rq_xprt;
 	int status;
@@ -613,8 +644,19 @@ void xprt_transmit(struct rpc_task *task
 		return;
 
 	status = xprt->ops->send_request(task);
-	if (!status)
-		goto out_receive;
+	if (status == 0) {
+		dprintk("RPC: %4d xmit complete\n", task->tk_pid);
+		spin_lock_bh(&xprt->transport_lock);
+		xprt->ops->set_retrans_timeout(task);
+		/* Don't race with disconnect */
+		if (!xprt_connected(xprt))
+			task->tk_status = -ENOTCONN;
+		else if (!req->rq_received)
+			rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer);
+		__xprt_release_write(xprt, task);
+		spin_unlock_bh(&xprt->transport_lock);
+		return;
+	}
 
 	/* Note: at this point, task->tk_sleeping has not yet been set,
 	 *	 hence there is no danger of the waking up task being put on
@@ -634,25 +676,6 @@ void xprt_transmit(struct rpc_task *task
 	}
 	xprt_release_write(xprt, task);
 	return;
- out_receive:
-	dprintk("RPC: %4d xmit complete\n", task->tk_pid);
-	/* Set the task's receive timeout value */
-	spin_lock_bh(&xprt->transport_lock);
-	if (!xprt->nocong) {
-		int timer = task->tk_msg.rpc_proc->p_timer;
-		task->tk_timeout = rpc_calc_rto(clnt->cl_rtt, timer);
-		task->tk_timeout <<= rpc_ntimeo(clnt->cl_rtt, timer) + req->rq_retries;
-		if (task->tk_timeout > xprt->timeout.to_maxval || task->tk_timeout == 0)
-			task->tk_timeout = xprt->timeout.to_maxval;
-	} else
-		task->tk_timeout = req->rq_timeout;
-	/* Don't race with disconnect */
-	if (!xprt_connected(xprt))
-		task->tk_status = -ENOTCONN;
-	else if (!req->rq_received)
-		rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer);
-	__xprt_release_write(xprt, task);
-	spin_unlock_bh(&xprt->transport_lock);
 }
 
 static inline void do_xprt_reserve(struct rpc_task *task)
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 5bb6fed..79433ff 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -1047,6 +1047,7 @@ static struct rpc_xprt_ops xs_udp_ops = 
 	.set_buffer_size	= xs_udp_set_buffer_size,
 	.connect		= xs_connect,
 	.send_request		= xs_udp_send_request,
+	.set_retrans_timeout	= xprt_set_retrans_timeout_rtt,
 	.close			= xs_close,
 	.destroy		= xs_destroy,
 };
@@ -1055,6 +1056,7 @@ static struct rpc_xprt_ops xs_tcp_ops = 
 	.set_buffer_size	= xs_tcp_set_buffer_size,
 	.connect		= xs_connect,
 	.send_request		= xs_tcp_send_request,
+	.set_retrans_timeout	= xprt_set_retrans_timeout_def,
 	.close			= xs_close,
 	.destroy		= xs_destroy,
 };
---
0.99.8.GIT


--- NEW FILE 0242-RPC-expose-API-for-serializing-access-to-RPC-transports.txt ---
Subject: [PATCH] RPC: expose API for serializing access to RPC transports
From: Chuck Lever <cel netapp com>
Date: 1125012351 -0700

 The next several patches introduce an API that allows transports to
 choose whether the RPC client provides congestion control or whether
 the transport itself provides it.

 The first method we abstract is the one that serializes access to the
 RPC transport to prevent the bytes from different requests from mingling
 together.  This method provides proper request serialization and the
 opportunity to prevent new requests from being started because the
 transport is congested.

 The normal situation is for the transport to handle congestion control
 itself.  Although NFS over UDP was first, it has been recognized after
 years of experience that having the transport provide congestion control
 is much better than doing it in the RPC client.  Thus TCP, and probably
 every future transport implementation, will use the default method,
 xprt_lock_write, provided in xprt.c, which does not provide any kind
 of congestion control.  UDP can continue using the xprt.c-provided
 Van Jacobson congestion avoidance implementation.

 Test-plan:
 Use WAN simulation to cause sporadic bursty packet loss.  Look for significant
 regression in performance or client stability.

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/xprt.h |    3 ++
 net/sunrpc/xprt.c           |   64 +++++++++++++++++++++++++++++++++++--------
 net/sunrpc/xprtsock.c       |    2 +
 3 files changed, 57 insertions(+), 12 deletions(-)

applies-to: 4fbaa255e9e7a85f41eacb7cf1214dc44a90bcea
12a804698b29d040b7cdd92e8a44b0e75164dae9
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index ac08e99..eee1c68 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -132,6 +132,7 @@ struct rpc_xprt;
 
 struct rpc_xprt_ops {
 	void		(*set_buffer_size)(struct rpc_xprt *xprt);
+	int		(*reserve_xprt)(struct rpc_task *task);
 	void		(*connect)(struct rpc_task *task);
 	int		(*send_request)(struct rpc_task *task);
 	void		(*set_retrans_timeout)(struct rpc_task *task);
@@ -232,6 +233,8 @@ void			xprt_set_timeout(struct rpc_timeo
  */
 void			xprt_connect(struct rpc_task *task);
 void			xprt_reserve(struct rpc_task *task);
+int			xprt_reserve_xprt(struct rpc_task *task);
+int			xprt_reserve_xprt_cong(struct rpc_task *task);
 int			xprt_prepare_transmit(struct rpc_task *task);
 void			xprt_transmit(struct rpc_task *task);
 int			xprt_adjust_timeout(struct rpc_rqst *req);
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 1ac2fbe..2d1e8b8 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -64,14 +64,56 @@ static int      __xprt_get_cong(struct r
 
 static int	xprt_clear_backlog(struct rpc_xprt *xprt);
 
+/**
+ * xprt_reserve_xprt - serialize write access to transports
+ * @task: task that is requesting access to the transport
+ *
+ * This prevents mixing the payload of separate requests, and prevents
+ * transport connects from colliding with writes.  No congestion control
+ * is provided.
+ */
+int xprt_reserve_xprt(struct rpc_task *task)
+{
+	struct rpc_xprt	*xprt = task->tk_xprt;
+	struct rpc_rqst *req = task->tk_rqstp;
+
+	if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) {
+		if (task == xprt->snd_task)
+			return 1;
+		if (task == NULL)
+			return 0;
+		goto out_sleep;
+	}
+	xprt->snd_task = task;
+	if (req) {
+		req->rq_bytes_sent = 0;
+		req->rq_ntrans++;
+	}
+	return 1;
+
+out_sleep:
+	dprintk("RPC: %4d failed to lock transport %p\n",
+			task->tk_pid, xprt);
+	task->tk_timeout = 0;
+	task->tk_status = -EAGAIN;
+	if (req && req->rq_ntrans)
+		rpc_sleep_on(&xprt->resend, task, NULL, NULL);
+	else
+		rpc_sleep_on(&xprt->sending, task, NULL, NULL);
+	return 0;
+}
+
 /*
- * Serialize write access to transports, in order to prevent different
- * requests from interfering with each other.
- * Also prevents transport connects from colliding with writes.
+ * xprt_reserve_xprt_cong - serialize write access to transports
+ * @task: task that is requesting access to the transport
+ *
+ * Same as xprt_reserve_xprt, but Van Jacobson congestion control is
+ * integrated into the decision of whether a request is allowed to be
+ * woken up and given access to the transport.
  */
-static int
-__xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
+int xprt_reserve_xprt_cong(struct rpc_task *task)
 {
+	struct rpc_xprt	*xprt = task->tk_xprt;
 	struct rpc_rqst *req = task->tk_rqstp;
 
 	if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) {
@@ -79,7 +121,7 @@ __xprt_lock_write(struct rpc_xprt *xprt,
 			return 1;
 		goto out_sleep;
 	}
-	if (xprt->nocong || __xprt_get_cong(xprt, task)) {
+	if (__xprt_get_cong(xprt, task)) {
 		xprt->snd_task = task;
 		if (req) {
 			req->rq_bytes_sent = 0;
@@ -101,20 +143,18 @@ out_sleep:
 	return 0;
 }
 
-static inline int
-xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
+static inline int xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
 {
 	int retval;
 
 	spin_lock_bh(&xprt->transport_lock);
-	retval = __xprt_lock_write(xprt, task);
+	retval = xprt->ops->reserve_xprt(task);
 	spin_unlock_bh(&xprt->transport_lock);
 	return retval;
 }
 
 
-static void
-__xprt_lock_write_next(struct rpc_xprt *xprt)
+static void __xprt_lock_write_next(struct rpc_xprt *xprt)
 {
 	struct rpc_task *task;
 
@@ -598,7 +638,7 @@ int xprt_prepare_transmit(struct rpc_tas
 		err = req->rq_received;
 		goto out_unlock;
 	}
-	if (!__xprt_lock_write(xprt, task)) {
+	if (!xprt->ops->reserve_xprt(task)) {
 		err = -EAGAIN;
 		goto out_unlock;
 	}
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 79433ff..fc4fbe8 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -1045,6 +1045,7 @@ static void xs_connect(struct rpc_task *
 
 static struct rpc_xprt_ops xs_udp_ops = {
 	.set_buffer_size	= xs_udp_set_buffer_size,
+	.reserve_xprt		= xprt_reserve_xprt_cong,
 	.connect		= xs_connect,
 	.send_request		= xs_udp_send_request,
 	.set_retrans_timeout	= xprt_set_retrans_timeout_rtt,
@@ -1054,6 +1055,7 @@ static struct rpc_xprt_ops xs_udp_ops = 
 
 static struct rpc_xprt_ops xs_tcp_ops = {
 	.set_buffer_size	= xs_tcp_set_buffer_size,
+	.reserve_xprt		= xprt_reserve_xprt,
 	.connect		= xs_connect,
 	.send_request		= xs_tcp_send_request,
 	.set_retrans_timeout	= xprt_set_retrans_timeout_def,
---
0.99.8.GIT


--- NEW FILE 0243-RPC-expose-API-for-serializing-access-to-RPC-transports.txt ---
Subject: [PATCH] RPC: expose API for serializing access to RPC transports
From: Chuck Lever <cel netapp com>
Date: 1125012351 -0700

 The next method we abstract is the one that releases a transport,
 allowing another task to have access to the transport.

 Again, one generic version of this is provided for transports that
 don't need the RPC client to perform congestion control, and one
 version is for transports that can use the original Van Jacobson
 implementation in xprt.c.

 Test-plan:
 Use WAN simulation to cause sporadic bursty packet loss.  Look for
 significant regression in performance or client stability.

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/xprt.h |    3 ++
 net/sunrpc/xprt.c           |   77 +++++++++++++++++++++++++++++++++++--------
 net/sunrpc/xprtsock.c       |    2 +
 3 files changed, 68 insertions(+), 14 deletions(-)

applies-to: 9885cf95a0a2945ad8cd00de59633a0aa16a3599
49e9a89086b3cae784a4868ca852863e4f4ea3fe
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index eee1c68..86833b7 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -133,6 +133,7 @@ struct rpc_xprt;
 struct rpc_xprt_ops {
 	void		(*set_buffer_size)(struct rpc_xprt *xprt);
 	int		(*reserve_xprt)(struct rpc_task *task);
+	void		(*release_xprt)(struct rpc_xprt *xprt, struct rpc_task *task);
 	void		(*connect)(struct rpc_task *task);
 	int		(*send_request)(struct rpc_task *task);
 	void		(*set_retrans_timeout)(struct rpc_task *task);
@@ -238,6 +239,8 @@ int			xprt_reserve_xprt_cong(struct rpc_
 int			xprt_prepare_transmit(struct rpc_task *task);
 void			xprt_transmit(struct rpc_task *task);
 int			xprt_adjust_timeout(struct rpc_rqst *req);
+void			xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task);
+void			xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task);
 void			xprt_release(struct rpc_task *task);
 int			xprt_destroy(struct rpc_xprt *xprt);
 
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 2d1e8b8..e92ea99 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -153,14 +153,42 @@ static inline int xprt_lock_write(struct
 	return retval;
 }
 
-
 static void __xprt_lock_write_next(struct rpc_xprt *xprt)
 {
 	struct rpc_task *task;
+	struct rpc_rqst *req;
 
 	if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
 		return;
-	if (!xprt->nocong && RPCXPRT_CONGESTED(xprt))
+
+	task = rpc_wake_up_next(&xprt->resend);
+	if (!task) {
+		task = rpc_wake_up_next(&xprt->sending);
+		if (!task)
+			goto out_unlock;
+	}
+
+	req = task->tk_rqstp;
+	xprt->snd_task = task;
+	if (req) {
+		req->rq_bytes_sent = 0;
+		req->rq_ntrans++;
+	}
+	return;
+
+out_unlock:
+	smp_mb__before_clear_bit();
+	clear_bit(XPRT_LOCKED, &xprt->state);
+	smp_mb__after_clear_bit();
+}
+
+static void __xprt_lock_write_next_cong(struct rpc_xprt *xprt)
+{
+	struct rpc_task *task;
+
+	if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
+		return;
+	if (RPCXPRT_CONGESTED(xprt))
 		goto out_unlock;
 	task = rpc_wake_up_next(&xprt->resend);
 	if (!task) {
@@ -168,7 +196,7 @@ static void __xprt_lock_write_next(struc
 		if (!task)
 			goto out_unlock;
 	}
-	if (xprt->nocong || __xprt_get_cong(xprt, task)) {
+	if (__xprt_get_cong(xprt, task)) {
 		struct rpc_rqst *req = task->tk_rqstp;
 		xprt->snd_task = task;
 		if (req) {
@@ -183,11 +211,14 @@ out_unlock:
 	smp_mb__after_clear_bit();
 }
 
-/*
- * Releases the transport for use by other requests.
+/**
+ * xprt_release_xprt - allow other requests to use a transport
+ * @xprt: transport with other tasks potentially waiting
+ * @task: task that is releasing access to the transport
+ *
+ * Note that "task" can be NULL.  No congestion control is provided.
  */
-static void
-__xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task)
+void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task)
 {
 	if (xprt->snd_task == task) {
 		xprt->snd_task = NULL;
@@ -198,11 +229,29 @@ __xprt_release_write(struct rpc_xprt *xp
 	}
 }
 
-static inline void
-xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task)
+/**
+ * xprt_release_xprt_cong - allow other requests to use a transport
+ * @xprt: transport with other tasks potentially waiting
+ * @task: task that is releasing access to the transport
+ *
+ * Note that "task" can be NULL.  Another task is awoken to use the
+ * transport if the transport's congestion window allows it.
+ */
+void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task)
+{
+	if (xprt->snd_task == task) {
+		xprt->snd_task = NULL;
+		smp_mb__before_clear_bit();
+		clear_bit(XPRT_LOCKED, &xprt->state);
+		smp_mb__after_clear_bit();
+		__xprt_lock_write_next_cong(xprt);
+	}
+}
+
+static inline void xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task)
 {
 	spin_lock_bh(&xprt->transport_lock);
-	__xprt_release_write(xprt, task);
+	xprt->ops->release_xprt(xprt, task);
 	spin_unlock_bh(&xprt->transport_lock);
 }
 
@@ -237,7 +286,7 @@ __xprt_put_cong(struct rpc_xprt *xprt, s
 		return;
 	req->rq_cong = 0;
 	xprt->cong -= RPC_CWNDSCALE;
-	__xprt_lock_write_next(xprt);
+	__xprt_lock_write_next_cong(xprt);
 }
 
 /*
@@ -256,7 +305,7 @@ xprt_adjust_cwnd(struct rpc_xprt *xprt, 
 		cwnd += (RPC_CWNDSCALE * RPC_CWNDSCALE + (cwnd >> 1)) / cwnd;
 		if (cwnd > RPC_MAXCWND(xprt))
 			cwnd = RPC_MAXCWND(xprt);
-		__xprt_lock_write_next(xprt);
+		__xprt_lock_write_next_cong(xprt);
 	} else if (result == -ETIMEDOUT) {
 		cwnd >>= 1;
 		if (cwnd < RPC_CWNDSCALE)
@@ -693,7 +742,7 @@ void xprt_transmit(struct rpc_task *task
 			task->tk_status = -ENOTCONN;
 		else if (!req->rq_received)
 			rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer);
-		__xprt_release_write(xprt, task);
+		xprt->ops->release_xprt(xprt, task);
 		spin_unlock_bh(&xprt->transport_lock);
 		return;
 	}
@@ -792,7 +841,7 @@ void xprt_release(struct rpc_task *task)
 	if (!(req = task->tk_rqstp))
 		return;
 	spin_lock_bh(&xprt->transport_lock);
-	__xprt_release_write(xprt, task);
+	xprt->ops->release_xprt(xprt, task);
 	__xprt_put_cong(xprt, req);
 	if (!list_empty(&req->rq_list))
 		list_del(&req->rq_list);
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index fc4fbe8..8589c1a 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -1046,6 +1046,7 @@ static void xs_connect(struct rpc_task *
 static struct rpc_xprt_ops xs_udp_ops = {
 	.set_buffer_size	= xs_udp_set_buffer_size,
 	.reserve_xprt		= xprt_reserve_xprt_cong,
+	.release_xprt		= xprt_release_xprt_cong,
 	.connect		= xs_connect,
 	.send_request		= xs_udp_send_request,
 	.set_retrans_timeout	= xprt_set_retrans_timeout_rtt,
@@ -1056,6 +1057,7 @@ static struct rpc_xprt_ops xs_udp_ops = 
 static struct rpc_xprt_ops xs_tcp_ops = {
 	.set_buffer_size	= xs_tcp_set_buffer_size,
 	.reserve_xprt		= xprt_reserve_xprt,
+	.release_xprt		= xprt_release_xprt,
 	.connect		= xs_connect,
 	.send_request		= xs_tcp_send_request,
 	.set_retrans_timeout	= xprt_set_retrans_timeout_def,
---
0.99.8.GIT


--- NEW FILE 0244-RPC-separate-xprt_timer-implementations.txt ---
Subject: [PATCH] RPC: separate xprt_timer implementations
From: Chuck Lever <cel netapp com>
Date: 1125012352 -0700

 Allow transports to hook the retransmit timer interrupt.  Some transports
 calculate their congestion window here so that a retransmit timeout has
 immediate effect on the congestion window.

 Test-plan:
 Use WAN simulation to cause sporadic bursty packet loss.  Look for significant
 regression in performance or client stability.

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/xprt.h |    2 ++
 net/sunrpc/xprt.c           |   45 +++++++++++++++++++------------------------
 net/sunrpc/xprtsock.c       |   12 +++++++++++
 3 files changed, 34 insertions(+), 25 deletions(-)

applies-to: 5ba197fc1767fee5590b892b2f19aeb3583494c4
46c0ee8bc4ad3743de05e8b8b20201df44dcb6d3
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 86833b7..443c3f9 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -137,6 +137,7 @@ struct rpc_xprt_ops {
 	void		(*connect)(struct rpc_task *task);
 	int		(*send_request)(struct rpc_task *task);
 	void		(*set_retrans_timeout)(struct rpc_task *task);
+	void		(*timer)(struct rpc_task *task);
 	void		(*close)(struct rpc_xprt *xprt);
 	void		(*destroy)(struct rpc_xprt *xprt);
 };
@@ -257,6 +258,7 @@ void			xprt_set_retrans_timeout_rtt(stru
 void			xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status);
 void			xprt_wait_for_buffer_space(struct rpc_task *task);
 void			xprt_write_space(struct rpc_xprt *xprt);
+void			xprt_adjust_cwnd(struct rpc_task *task, int result);
 struct rpc_rqst *	xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid);
 void			xprt_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied);
 void			xprt_disconnect(struct rpc_xprt *xprt);
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index e92ea99..ffc5955 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -289,16 +289,19 @@ __xprt_put_cong(struct rpc_xprt *xprt, s
 	__xprt_lock_write_next_cong(xprt);
 }
 
-/*
- * Adjust RPC congestion window
+/**
+ * xprt_adjust_cwnd - adjust transport congestion window
+ * @task: recently completed RPC request used to adjust window
+ * @result: result code of completed RPC request
+ *
  * We use a time-smoothed congestion estimator to avoid heavy oscillation.
  */
-static void
-xprt_adjust_cwnd(struct rpc_xprt *xprt, int result)
+void xprt_adjust_cwnd(struct rpc_task *task, int result)
 {
-	unsigned long	cwnd;
+	struct rpc_rqst *req = task->tk_rqstp;
+	struct rpc_xprt *xprt = task->tk_xprt;
+	unsigned long cwnd = xprt->cwnd;
 
-	cwnd = xprt->cwnd;
 	if (result >= 0 && cwnd <= xprt->cong) {
 		/* The (cwnd >> 1) term makes sure
 		 * the result gets rounded properly. */
@@ -314,6 +317,7 @@ xprt_adjust_cwnd(struct rpc_xprt *xprt, 
 	dprintk("RPC:      cong %ld, cwnd was %ld, now %ld\n",
 			xprt->cong, xprt->cwnd, cwnd);
 	xprt->cwnd = cwnd;
+	__xprt_put_cong(xprt, req);
 }
 
 /**
@@ -602,8 +606,7 @@ void xprt_complete_rqst(struct rpc_xprt 
 	/* Adjust congestion window */
 	if (!xprt->nocong) {
 		unsigned timer = task->tk_msg.rpc_proc->p_timer;
-		xprt_adjust_cwnd(xprt, copied);
-		__xprt_put_cong(xprt, req);
+		xprt_adjust_cwnd(task, copied);
 		if (timer) {
 			if (req->rq_ntrans == 1)
 				rpc_update_rtt(clnt->cl_rtt, timer,
@@ -640,27 +643,19 @@ void xprt_complete_rqst(struct rpc_xprt 
 	return;
 }
 
-/*
- * RPC receive timeout handler.
- */
-static void
-xprt_timer(struct rpc_task *task)
+static void xprt_timer(struct rpc_task *task)
 {
-	struct rpc_rqst	*req = task->tk_rqstp;
+	struct rpc_rqst *req = task->tk_rqstp;
 	struct rpc_xprt *xprt = req->rq_xprt;
 
-	spin_lock(&xprt->transport_lock);
-	if (req->rq_received)
-		goto out;
-
-	xprt_adjust_cwnd(req->rq_xprt, -ETIMEDOUT);
-	__xprt_put_cong(xprt, req);
+	dprintk("RPC: %4d xprt_timer\n", task->tk_pid);
 
-	dprintk("RPC: %4d xprt_timer (%s request)\n",
-		task->tk_pid, req ? "pending" : "backlogged");
-
-	task->tk_status  = -ETIMEDOUT;
-out:
+	spin_lock(&xprt->transport_lock);
+	if (!req->rq_received) {
+		if (xprt->ops->timer)
+			xprt->ops->timer(task);
+		task->tk_status = -ETIMEDOUT;
+	}
 	task->tk_timeout = 0;
 	rpc_wake_up_task(task);
 	spin_unlock(&xprt->transport_lock);
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 8589c1a..c3658ff 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -860,6 +860,17 @@ static void xs_tcp_set_buffer_size(struc
 	return;
 }
 
+/**
+ * xs_udp_timer - called when a retransmit timeout occurs on a UDP transport
+ * @task: task that timed out
+ *
+ * Adjust the congestion window after a retransmit timeout has occurred.
+ */
+static void xs_udp_timer(struct rpc_task *task)
+{
+	xprt_adjust_cwnd(task, -ETIMEDOUT);
+}
+
 static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
 {
 	struct sockaddr_in myaddr = {
@@ -1050,6 +1061,7 @@ static struct rpc_xprt_ops xs_udp_ops = 
 	.connect		= xs_connect,
 	.send_request		= xs_udp_send_request,
 	.set_retrans_timeout	= xprt_set_retrans_timeout_rtt,
+	.timer			= xs_udp_timer,
 	.close			= xs_close,
 	.destroy		= xs_destroy,
 };
---
0.99.8.GIT


--- NEW FILE 0245-RPC-add-generic-interface-for-adjusting-the-congestion-window.txt ---
Subject: [PATCH] RPC: add generic interface for adjusting the congestion window
From: Chuck Lever <cel netapp com>
Date: 1125012352 -0700

 A new interface that allows transports to adjust their congestion window
 using the Van Jacobson implementation in xprt.c is provided.

 Test-plan:
 Use WAN simulation to cause sporadic bursty packet loss.  Look for
 significant regression in performance or client stability.

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/xprt.h |    3 +-
 net/sunrpc/xprt.c           |   64 +++++++++++++++++--------------------------
 net/sunrpc/xprtsock.c       |   13 +++------
 3 files changed, 32 insertions(+), 48 deletions(-)

applies-to: 6b2993ff1cefb69cc3cc40c3605d088ea2af3c98
1570c1e41eabf6b7031f3e4322a2cf1cbe319fee
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 443c3f9..2e48752 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -258,9 +258,10 @@ void			xprt_set_retrans_timeout_rtt(stru
 void			xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status);
 void			xprt_wait_for_buffer_space(struct rpc_task *task);
 void			xprt_write_space(struct rpc_xprt *xprt);
+void			xprt_update_rtt(struct rpc_task *task);
 void			xprt_adjust_cwnd(struct rpc_task *task, int result);
 struct rpc_rqst *	xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid);
-void			xprt_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied);
+void			xprt_complete_rqst(struct rpc_task *task, int copied);
 void			xprt_disconnect(struct rpc_xprt *xprt);
 
 /*
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index ffc5955..707806f 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -592,55 +592,41 @@ struct rpc_rqst *xprt_lookup_rqst(struct
 }
 
 /**
- * xprt_complete_rqst - called when reply processing is complete
- * @xprt: controlling transport
- * @req: RPC request that just completed
- * @copied: actual number of bytes received from the transport
+ * xprt_update_rtt - update an RPC client's RTT state after receiving a reply
+ * @task: RPC request that recently completed
  *
  */
-void xprt_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied)
+void xprt_update_rtt(struct rpc_task *task)
 {
-	struct rpc_task	*task = req->rq_task;
-	struct rpc_clnt *clnt = task->tk_client;
+	struct rpc_rqst *req = task->tk_rqstp;
+	struct rpc_rtt *rtt = task->tk_client->cl_rtt;
+	unsigned timer = task->tk_msg.rpc_proc->p_timer;
 
-	/* Adjust congestion window */
-	if (!xprt->nocong) {
-		unsigned timer = task->tk_msg.rpc_proc->p_timer;
-		xprt_adjust_cwnd(task, copied);
-		if (timer) {
-			if (req->rq_ntrans == 1)
-				rpc_update_rtt(clnt->cl_rtt, timer,
-						(long)jiffies - req->rq_xtime);
-			rpc_set_timeo(clnt->cl_rtt, timer, req->rq_ntrans - 1);
-		}
+	if (timer) {
+		if (req->rq_ntrans == 1)
+			rpc_update_rtt(rtt, timer,
+					(long)jiffies - req->rq_xtime);
+		rpc_set_timeo(rtt, timer, req->rq_ntrans - 1);
 	}
+}
 
-#ifdef RPC_PROFILE
-	/* Profile only reads for now */
-	if (copied > 1024) {
-		static unsigned long	nextstat;
-		static unsigned long	pkt_rtt, pkt_len, pkt_cnt;
-
-		pkt_cnt++;
-		pkt_len += req->rq_slen + copied;
-		pkt_rtt += jiffies - req->rq_xtime;
-		if (time_before(nextstat, jiffies)) {
-			printk("RPC: %lu %ld cwnd\n", jiffies, xprt->cwnd);
-			printk("RPC: %ld %ld %ld %ld stat\n",
-					jiffies, pkt_cnt, pkt_len, pkt_rtt);
-			pkt_rtt = pkt_len = pkt_cnt = 0;
-			nextstat = jiffies + 5 * HZ;
-		}
-	}
-#endif
+/**
+ * xprt_complete_rqst - called when reply processing is complete
+ * @task: RPC request that recently completed
+ * @copied: actual number of bytes received from the transport
+ *
+ * Caller holds transport lock.
+ */
+void xprt_complete_rqst(struct rpc_task *task, int copied)
+{
+	struct rpc_rqst *req = task->tk_rqstp;
+
+	dprintk("RPC: %5u xid %08x complete (%d bytes received)\n",
+			task->tk_pid, ntohl(req->rq_xid), copied);
 
-	dprintk("RPC: %4d has input (%d bytes)\n", task->tk_pid, copied);
 	list_del_init(&req->rq_list);
 	req->rq_received = req->rq_private_buf.len = copied;
-
-	/* ... and wake up the process. */
 	rpc_wake_up_task(task);
-	return;
 }
 
 static void xprt_timer(struct rpc_task *task)
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index c3658ff..980f265 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -460,8 +460,6 @@ static void xs_udp_data_ready(struct soc
 		goto out_unlock;
 	task = rovr->rq_task;
 
-	dprintk("RPC: %4d received reply\n", task->tk_pid);
-
 	if ((copied = rovr->rq_private_buf.buflen) > repsize)
 		copied = repsize;
 
@@ -472,7 +470,9 @@ static void xs_udp_data_ready(struct soc
 	/* Something worked... */
 	dst_confirm(skb->dst);
 
-	xprt_complete_rqst(xprt, rovr, copied);
+	xprt_adjust_cwnd(task, copied);
+	xprt_update_rtt(task);
+	xprt_complete_rqst(task, copied);
 
  out_unlock:
 	spin_unlock(&xprt->transport_lock);
@@ -634,11 +634,8 @@ static inline void xs_tcp_read_request(s
 	}
 
 out:
-	if (!(xprt->tcp_flags & XPRT_COPY_DATA)) {
-		dprintk("RPC: %4d received reply complete\n",
-				req->rq_task->tk_pid);
-		xprt_complete_rqst(xprt, req, xprt->tcp_copied);
-	}
+	if (!(xprt->tcp_flags & XPRT_COPY_DATA))
+		xprt_complete_rqst(req->rq_task, xprt->tcp_copied);
 	spin_unlock(&xprt->transport_lock);
 	xs_tcp_check_recm(xprt);
 }
---
0.99.8.GIT


--- NEW FILE 0246-RPC-add-a-release_rqst-callout-to-the-RPC-transport-switch.txt ---
Subject: [PATCH] RPC: add a release_rqst callout to the RPC transport switch
From: Chuck Lever <cel netapp com>
Date: 1125012353 -0700

 The final place where congestion control state is adjusted is in
 xprt_release, where each request is finally released.  Add a callout
 there to allow transports to perform additional processing when a
 request is about to be released.

 Test-plan:
 Use WAN simulation to cause sporadic bursty packet loss.  Look for significant
 regression in performance or client stability.

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/xprt.h |    2 ++
 net/sunrpc/xprt.c           |   14 +++++++++++++-
 net/sunrpc/xprtsock.c       |    1 +
 3 files changed, 16 insertions(+), 1 deletions(-)

applies-to: eee53757ac3e03d55b6c01bb0500996ba520a8bb
a58dd398f5db4f73d5c581069fd70a4304cc4f0a
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 2e48752..64e7765 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -138,6 +138,7 @@ struct rpc_xprt_ops {
 	int		(*send_request)(struct rpc_task *task);
 	void		(*set_retrans_timeout)(struct rpc_task *task);
 	void		(*timer)(struct rpc_task *task);
+	void		(*release_request)(struct rpc_task *task);
 	void		(*close)(struct rpc_xprt *xprt);
 	void		(*destroy)(struct rpc_xprt *xprt);
 };
@@ -262,6 +263,7 @@ void			xprt_update_rtt(struct rpc_task *
 void			xprt_adjust_cwnd(struct rpc_task *task, int result);
 struct rpc_rqst *	xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid);
 void			xprt_complete_rqst(struct rpc_task *task, int copied);
+void			xprt_release_rqst_cong(struct rpc_task *task);
 void			xprt_disconnect(struct rpc_xprt *xprt);
 
 /*
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 707806f..e8d11bd 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -290,6 +290,17 @@ __xprt_put_cong(struct rpc_xprt *xprt, s
 }
 
 /**
+ * xprt_release_rqst_cong - housekeeping when request is complete
+ * @task: RPC request that recently completed
+ *
+ * Useful for transports that require congestion control.
+ */
+void xprt_release_rqst_cong(struct rpc_task *task)
+{
+	__xprt_put_cong(task->tk_xprt, task->tk_rqstp);
+}
+
+/**
  * xprt_adjust_cwnd - adjust transport congestion window
  * @task: recently completed RPC request used to adjust window
  * @result: result code of completed RPC request
@@ -823,7 +834,8 @@ void xprt_release(struct rpc_task *task)
 		return;
 	spin_lock_bh(&xprt->transport_lock);
 	xprt->ops->release_xprt(xprt, task);
-	__xprt_put_cong(xprt, req);
+	if (xprt->ops->release_request)
+		xprt->ops->release_request(task);
 	if (!list_empty(&req->rq_list))
 		list_del(&req->rq_list);
 	xprt->last_used = jiffies;
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 980f265..6c2f5dc 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -1059,6 +1059,7 @@ static struct rpc_xprt_ops xs_udp_ops = 
 	.send_request		= xs_udp_send_request,
 	.set_retrans_timeout	= xprt_set_retrans_timeout_rtt,
 	.timer			= xs_udp_timer,
+	.release_request	= xprt_release_rqst_cong,
 	.close			= xs_close,
 	.destroy		= xs_destroy,
 };
---
0.99.8.GIT


--- NEW FILE 0247-RPC-remove-xprt-nocong.txt ---
Subject: [PATCH] RPC: remove xprt->nocong
From: Chuck Lever <cel netapp com>
Date: 1125012353 -0700

 Get rid of the "xprt->nocong" variable.

 Test-plan:
 Use WAN simulation to cause sporadic bursty packet loss with UDP mounts.
 Look for significant regression in performance or client stability.

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 fs/lockd/host.c             |    1 -
 include/linux/sunrpc/xprt.h |    1 -
 net/sunrpc/xprtsock.c       |    2 --
 3 files changed, 0 insertions(+), 4 deletions(-)

applies-to: 09e290d351c043392e7a2f8e0bc77aba90ff88ad
ed63c003701a314c4893c11eceb9d68f8f46c662
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 7901f5b..c4c8601 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -188,7 +188,6 @@ nlm_bind_host(struct nlm_host *host)
 			goto forgetit;
 
 		xprt_set_timeout(&xprt->timeout, 5, nlmsvc_timeout);
-		xprt->nocong = 1;	/* No congestion control for NLM */
 		xprt->resvport = 1;	/* NLM requires a reserved port */
 
 		/* Existing NLM servers accept AUTH_UNIX only */
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 64e7765..559fb47 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -172,7 +172,6 @@ struct rpc_xprt {
 	unsigned int		max_reqs;	/* total slots */
 	unsigned long		state;		/* transport state */
 	unsigned char		shutdown   : 1,	/* being shut down */
-				nocong	   : 1,	/* no congestion control */
 				resvport   : 1; /* use a reserved port */
 
 	/*
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 6c2f5dc..7e5e020 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -1100,7 +1100,6 @@ int xs_setup_udp(struct rpc_xprt *xprt, 
 	xprt->prot = IPPROTO_UDP;
 	xprt->port = XS_MAX_RESVPORT;
 	xprt->tsh_size = 0;
-	xprt->nocong = 0;
 	xprt->cwnd = RPC_INITCWND;
 	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
 	/* XXX: header size can vary due to auth type, IPv6, etc. */
@@ -1140,7 +1139,6 @@ int xs_setup_tcp(struct rpc_xprt *xprt, 
 	xprt->prot = IPPROTO_TCP;
 	xprt->port = XS_MAX_RESVPORT;
 	xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32);
-	xprt->nocong = 1;
 	xprt->cwnd = RPC_MAXCWND(xprt);
 	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
 	xprt->max_payload = RPC_MAX_FRAGMENT_SIZE;
---
0.99.8.GIT


--- NEW FILE 0248-RPC-clean-up-after-nocong-was-removed.txt ---
Subject: [PATCH] RPC: clean up after nocong was removed
From: Chuck Lever <cel netapp com>
Date: 1125012354 -0700

 Clean-up:  Move some macros that are specific to the Van Jacobson
 implementation into xprt.c.  Get rid of the cong_wait field in
 rpc_xprt, which is no longer used.  Get rid of xprt_clear_backlog.

 Test-plan:
 Compile with CONFIG_NFS enabled.

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/xprt.h |   22 ----------------------
 net/sunrpc/xprt.c           |   29 +++++++++++++++++++----------
 net/sunrpc/xprtsock.c       |    2 --
 3 files changed, 19 insertions(+), 34 deletions(-)

applies-to: c0567884d9cce53960061fece0ae9c2eabd0af77
555ee3af161b037865793bd4bebc06b58daafde6
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 559fb47..dcf0326 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -15,20 +15,6 @@
 #include <linux/sunrpc/sched.h>
 #include <linux/sunrpc/xdr.h>
 
-/*
- * The transport code maintains an estimate on the maximum number of out-
- * standing RPC requests, using a smoothed version of the congestion
- * avoidance implemented in 44BSD. This is basically the Van Jacobson
- * congestion algorithm: If a retransmit occurs, the congestion window is
- * halved; otherwise, it is incremented by 1/cwnd when
- *
- *	-	a reply is received and
- *	-	a full number of requests are outstanding and
- *	-	the congestion window hasn't been updated recently.
- *
- * Upper procedures may check whether a request would block waiting for
- * a free RPC slot by using the RPC_CONGESTED() macro.
- */
 extern unsigned int xprt_udp_slot_table_entries;
 extern unsigned int xprt_tcp_slot_table_entries;
 
@@ -36,12 +22,6 @@ extern unsigned int xprt_tcp_slot_table_
 #define RPC_DEF_SLOT_TABLE	(16U)
 #define RPC_MAX_SLOT_TABLE	(128U)
 
-#define RPC_CWNDSHIFT		(8U)
-#define RPC_CWNDSCALE		(1U << RPC_CWNDSHIFT)
-#define RPC_INITCWND		RPC_CWNDSCALE
-#define RPC_MAXCWND(xprt)	((xprt)->max_reqs << RPC_CWNDSHIFT)
-#define RPCXPRT_CONGESTED(xprt) ((xprt)->cong >= (xprt)->cwnd)
-
 /* Default timeout values */
 #define RPC_MAX_UDP_TIMEOUT	(60*HZ)
 #define RPC_MAX_TCP_TIMEOUT	(600*HZ)
@@ -213,8 +193,6 @@ struct rpc_xprt {
 	void			(*old_data_ready)(struct sock *, int);
 	void			(*old_state_change)(struct sock *);
 	void			(*old_write_space)(struct sock *);
-
-	wait_queue_head_t	cong_wait;
 };
 
 #define XPRT_LAST_FRAG		(1 << 0)
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index e8d11bd..0458319 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -62,7 +62,23 @@ static inline void	do_xprt_reserve(struc
 static void	xprt_connect_status(struct rpc_task *task);
 static int      __xprt_get_cong(struct rpc_xprt *, struct rpc_task *);
 
-static int	xprt_clear_backlog(struct rpc_xprt *xprt);
+/*
+ * The transport code maintains an estimate on the maximum number of out-
+ * standing RPC requests, using a smoothed version of the congestion
+ * avoidance implemented in 44BSD. This is basically the Van Jacobson
+ * congestion algorithm: If a retransmit occurs, the congestion window is
+ * halved; otherwise, it is incremented by 1/cwnd when
+ *
+ *	-	a reply is received and
+ *	-	a full number of requests are outstanding and
+ *	-	the congestion window hasn't been updated recently.
+ */
+#define RPC_CWNDSHIFT		(8U)
+#define RPC_CWNDSCALE		(1U << RPC_CWNDSHIFT)
+#define RPC_INITCWND		RPC_CWNDSCALE
+#define RPC_MAXCWND(xprt)	((xprt)->max_reqs << RPC_CWNDSHIFT)
+
+#define RPCXPRT_CONGESTED(xprt) ((xprt)->cong >= (xprt)->cwnd)
 
 /**
  * xprt_reserve_xprt - serialize write access to transports
@@ -850,7 +866,7 @@ void xprt_release(struct rpc_task *task)
 
 	spin_lock(&xprt->reserve_lock);
 	list_add(&req->rq_list, &xprt->free);
-	xprt_clear_backlog(xprt);
+	rpc_wake_up_next(&xprt->backlog);
 	spin_unlock(&xprt->reserve_lock);
 }
 
@@ -902,7 +918,6 @@ static struct rpc_xprt *xprt_setup(int p
 
 	spin_lock_init(&xprt->transport_lock);
 	spin_lock_init(&xprt->reserve_lock);
-	init_waitqueue_head(&xprt->cong_wait);
 
 	INIT_LIST_HEAD(&xprt->free);
 	INIT_LIST_HEAD(&xprt->recv);
@@ -911,6 +926,7 @@ static struct rpc_xprt *xprt_setup(int p
 	xprt->timer.function = xprt_init_autodisconnect;
 	xprt->timer.data = (unsigned long) xprt;
 	xprt->last_used = jiffies;
+	xprt->cwnd = RPC_INITCWND;
 
 	rpc_init_wait_queue(&xprt->pending, "xprt_pending");
 	rpc_init_wait_queue(&xprt->sending, "xprt_sending");
@@ -955,16 +971,9 @@ static void xprt_shutdown(struct rpc_xpr
 	rpc_wake_up(&xprt->resend);
 	xprt_wake_pending_tasks(xprt, -EIO);
 	rpc_wake_up(&xprt->backlog);
-	wake_up(&xprt->cong_wait);
 	del_timer_sync(&xprt->timer);
 }
 
-static int xprt_clear_backlog(struct rpc_xprt *xprt) {
-	rpc_wake_up_next(&xprt->backlog);
-	wake_up(&xprt->cong_wait);
-	return 1;
-}
-
 /**
  * xprt_destroy - destroy an RPC transport, killing off all requests.
  * @xprt: transport to destroy
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 7e5e020..26402c0 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -1100,7 +1100,6 @@ int xs_setup_udp(struct rpc_xprt *xprt, 
 	xprt->prot = IPPROTO_UDP;
 	xprt->port = XS_MAX_RESVPORT;
 	xprt->tsh_size = 0;
-	xprt->cwnd = RPC_INITCWND;
 	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
 	/* XXX: header size can vary due to auth type, IPv6, etc. */
 	xprt->max_payload = (1U << 16) - (MAX_HEADER << 3);
@@ -1139,7 +1138,6 @@ int xs_setup_tcp(struct rpc_xprt *xprt, 
 	xprt->prot = IPPROTO_TCP;
 	xprt->port = XS_MAX_RESVPORT;
 	xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32);
-	xprt->cwnd = RPC_MAXCWND(xprt);
 	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
 	xprt->max_payload = RPC_MAX_FRAGMENT_SIZE;
 
---
0.99.8.GIT


--- NEW FILE 0249-RPC-allow-RPC-client-s-port-range-to-be-adjustable.txt ---
Subject: [PATCH] RPC: allow RPC client's port range to be adjustable
From: Chuck Lever <cel netapp com>
Date: 1125012354 -0700

 Select an RPC client source port between 650 and 1023 instead of between
 1 and 800.  The old range conflicts with a number of network services.
 Provide sysctls to allow admins to select a different port range.

 Note that this doesn't affect user-level RPC library behavior, which
 still uses 1 to 800.

 Based on a suggestion by Olaf Kirch <okir suse de>.

 Test-plan:
 Repeated mount and unmount.  Destructive testing.  Idle timeouts.

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/debug.h |    2 ++
 include/linux/sunrpc/xprt.h  |   17 ++++++++++++++---
 net/sunrpc/sysctl.c          |   29 +++++++++++++++++++++++++++++
 net/sunrpc/xprtsock.c        |   23 ++++++++---------------
 4 files changed, 53 insertions(+), 18 deletions(-)

applies-to: 4c72474dabffab62234db158e5b6c86ace4f9d09
529b33c6db0120126b1381faa51406dc463acdc9
diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
index 42d2997..1a42d90 100644
--- a/include/linux/sunrpc/debug.h
+++ b/include/linux/sunrpc/debug.h
@@ -95,6 +95,8 @@ enum {
 	CTL_NLMDEBUG,
 	CTL_SLOTTABLE_UDP,
 	CTL_SLOTTABLE_TCP,
+	CTL_MIN_RESVPORT,
+	CTL_MAX_RESVPORT,
 };
 
 #endif /* _LINUX_SUNRPC_DEBUG_H_ */
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index dcf0326..9d9266c 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -52,6 +52,17 @@ extern unsigned int xprt_tcp_slot_table_
 #define RPC_REPHDRSIZE		4
 
 /*
+ * Parameters for choosing a free port
+ */
+extern unsigned int xprt_min_resvport;
+extern unsigned int xprt_max_resvport;
+
+#define RPC_MIN_RESVPORT	(1U)
+#define RPC_MAX_RESVPORT	(65535U)
+#define RPC_DEF_MIN_RESVPORT	(650U)
+#define RPC_DEF_MAX_RESVPORT	(1023U)
+
+/*
  * This describes a timeout strategy
  */
 struct rpc_timeout {
@@ -62,6 +73,9 @@ struct rpc_timeout {
 	unsigned char		to_exponential;
 };
 
+struct rpc_task;
+struct rpc_xprt;
+
 /*
  * This describes a complete RPC request
  */
@@ -107,9 +121,6 @@ struct rpc_rqst {
 #define rq_svec			rq_snd_buf.head
 #define rq_slen			rq_snd_buf.len
 
-struct rpc_task;
-struct rpc_xprt;
-
 struct rpc_xprt_ops {
 	void		(*set_buffer_size)(struct rpc_xprt *xprt);
 	int		(*reserve_xprt)(struct rpc_task *task);
diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c
index ef48326..d0c9f46 100644
--- a/net/sunrpc/sysctl.c
+++ b/net/sunrpc/sysctl.c
@@ -121,9 +121,16 @@ done:
 
 unsigned int xprt_udp_slot_table_entries = RPC_DEF_SLOT_TABLE;
 unsigned int xprt_tcp_slot_table_entries = RPC_DEF_SLOT_TABLE;
+unsigned int xprt_min_resvport = RPC_DEF_MIN_RESVPORT;
+EXPORT_SYMBOL(xprt_min_resvport);
+unsigned int xprt_max_resvport = RPC_DEF_MAX_RESVPORT;
+EXPORT_SYMBOL(xprt_max_resvport);
+
 
 static unsigned int min_slot_table_size = RPC_MIN_SLOT_TABLE;
 static unsigned int max_slot_table_size = RPC_MAX_SLOT_TABLE;
+static unsigned int xprt_min_resvport_limit = RPC_MIN_RESVPORT;
+static unsigned int xprt_max_resvport_limit = RPC_MAX_RESVPORT;
 
 static ctl_table debug_table[] = {
 	{
@@ -180,6 +187,28 @@ static ctl_table debug_table[] = {
 		.extra1		= &min_slot_table_size,
 		.extra2		= &max_slot_table_size
 	},
+	{
+		.ctl_name	= CTL_MIN_RESVPORT,
+		.procname	= "min_resvport",
+		.data		= &xprt_min_resvport,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &xprt_min_resvport_limit,
+		.extra2		= &xprt_max_resvport_limit
+	},
+	{
+		.ctl_name	= CTL_MAX_RESVPORT,
+		.procname	= "max_resvport",
+		.data		= &xprt_max_resvport,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &xprt_min_resvport_limit,
+		.extra2		= &xprt_max_resvport_limit
+	},
 	{ .ctl_name = 0 }
 };
 
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 26402c0..62c2e7c 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -36,11 +36,6 @@
 #include <net/tcp.h>
 
 /*
- * Maximum port number to use when requesting a reserved port.
- */
-#define XS_MAX_RESVPORT		(800U)
-
-/*
  * How many times to try sending a request on a socket before waiting
  * for the socket buffer to clear.
  */
@@ -873,10 +868,9 @@ static int xs_bindresvport(struct rpc_xp
 	struct sockaddr_in myaddr = {
 		.sin_family = AF_INET,
 	};
-	int err, port;
+	int err;
+	unsigned short port = xprt->port;
 
-	/* Were we already bound to a given port? Try to reuse it */
-	port = xprt->port;
 	do {
 		myaddr.sin_port = htons(port);
 		err = sock->ops->bind(sock, (struct sockaddr *) &myaddr,
@@ -887,8 +881,10 @@ static int xs_bindresvport(struct rpc_xp
 					port);
 			return 0;
 		}
-		if (--port == 0)
-			port = XS_MAX_RESVPORT;
+		if (port <= xprt_min_resvport)
+			port = xprt_max_resvport;
+		else
+			port--;
 	} while (err == -EADDRINUSE && port != xprt->port);
 
 	dprintk("RPC:      can't bind to reserved port (%d).\n", -err);
@@ -1075,9 +1071,6 @@ static struct rpc_xprt_ops xs_tcp_ops = 
 	.destroy		= xs_destroy,
 };
 
-extern unsigned int xprt_udp_slot_table_entries;
-extern unsigned int xprt_tcp_slot_table_entries;
-
 /**
  * xs_setup_udp - Set up transport to use a UDP socket
  * @xprt: transport to set up
@@ -1098,7 +1091,7 @@ int xs_setup_udp(struct rpc_xprt *xprt, 
 	memset(xprt->slot, 0, slot_table_size);
 
 	xprt->prot = IPPROTO_UDP;
-	xprt->port = XS_MAX_RESVPORT;
+	xprt->port = xprt_max_resvport;
 	xprt->tsh_size = 0;
 	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
 	/* XXX: header size can vary due to auth type, IPv6, etc. */
@@ -1136,7 +1129,7 @@ int xs_setup_tcp(struct rpc_xprt *xprt, 
 	memset(xprt->slot, 0, slot_table_size);
 
 	xprt->prot = IPPROTO_TCP;
-	xprt->port = XS_MAX_RESVPORT;
+	xprt->port = xprt_max_resvport;
 	xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32);
 	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
 	xprt->max_payload = RPC_MAX_FRAGMENT_SIZE;
---
0.99.8.GIT


--- NEW FILE 0250-RPC-make-sure-to-get-the-same-local-port-number-when-reconnecting.txt ---
Subject: [PATCH] RPC: make sure to get the same local port number when reconnecting
From: Chuck Lever <cel netapp com>
Date: 1125012355 -0700

 Implement a best practice: if the remote end drops our connection, try to
 reconnect using the same port number.  This is important because the NFS
 server's Duplicate Reply Cache often hashes on the source port number.
 If the client reuses the port number when it reconnects, the server's DRC
 will be more effective.

 Based on suggestions by Mike Eisler, Olaf Kirch, and Alexey Kuznetsky.

 Test-plan:
 Destructive testing.

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 net/sunrpc/xprtsock.c |   65 ++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 53 insertions(+), 12 deletions(-)

applies-to: 4856a23687aa891f6a5d1c45db80190b90b0fc68
3167e12c0c424f3c323944701615343022d86418
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 62c2e7c..88ac71f 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -362,6 +362,8 @@ static int xs_tcp_send_request(struct rp
  * xs_close - close a socket
  * @xprt: transport
  *
+ * This is used when all requests are complete; ie, no DRC state remains
+ * on the server we want to save.
  */
 static void xs_close(struct rpc_xprt *xprt)
 {
@@ -949,6 +951,30 @@ out:
 	xprt_clear_connecting(xprt);
 }
 
+/*
+ * We need to preserve the port number so the reply cache on the server can
+ * find our cached RPC replies when we get around to reconnecting.
+ */
+static void xs_tcp_reuse_connection(struct rpc_xprt *xprt)
+{
+	int result;
+	struct socket *sock = xprt->sock;
+	struct sockaddr any;
+
+	dprintk("RPC:      disconnecting xprt %p to reuse port\n", xprt);
+
+	/*
+	 * Disconnect the transport socket by doing a connect operation
+	 * with AF_UNSPEC.  This should return immediately...
+	 */
+	memset(&any, 0, sizeof(any));
+	any.sa_family = AF_UNSPEC;
+	result = sock->ops->connect(sock, &any, sizeof(any), 0);
+	if (result)
+		dprintk("RPC:      AF_UNSPEC connect return code %d\n",
+				result);
+}
+
 /**
  * xs_tcp_connect_worker - connect a TCP socket to a remote endpoint
  * @args: RPC transport to connect
@@ -966,18 +992,20 @@ static void xs_tcp_connect_worker(void *
 
 	dprintk("RPC:      xs_tcp_connect_worker for xprt %p\n", xprt);
 
-	/* Start by resetting any existing socket state */
-	xs_close(xprt);
-
-	if ((err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) {
-		dprintk("RPC:      can't create TCP transport socket (%d).\n", -err);
-		goto out;
-	}
+	if (!xprt->sock) {
+		/* start from scratch */
+		if ((err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) {
+			dprintk("RPC:      can't create TCP transport socket (%d).\n", -err);
+			goto out;
+		}
 
-	if (xprt->resvport && xs_bindresvport(xprt, sock) < 0) {
-		sock_release(sock);
-		goto out;
-	}
+		if (xprt->resvport && xs_bindresvport(xprt, sock) < 0) {
+			sock_release(sock);
+			goto out;
+		}
+	} else
+		/* "close" the socket, preserving the local port */
+		xs_tcp_reuse_connection(xprt);
 
 	if (!xprt->inet) {
 		struct sock *sk = sock->sk;
@@ -991,7 +1019,12 @@ static void xs_tcp_connect_worker(void *
 		sk->sk_data_ready = xs_tcp_data_ready;
 		sk->sk_state_change = xs_tcp_state_change;
 		sk->sk_write_space = xs_tcp_write_space;
-		tcp_sk(sk)->nonagle = 1;
+
+		/* socket options */
+		sk->sk_userlocks |= SOCK_BINDPORT_LOCK;
+		sock_reset_flag(sk, SOCK_LINGER);
+		tcp_sk(sk)->linger2 = 0;
+		tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF;
 
 		xprt_clear_connected(xprt);
 
@@ -1012,6 +1045,14 @@ static void xs_tcp_connect_worker(void *
 			case -EINPROGRESS:
 			case -EALREADY:
 				goto out_clear;
+			case -ECONNREFUSED:
+			case -ECONNRESET:
+				/* retry with existing socket, after a delay */
+				break;
+			default:
+				/* get rid of existing socket, and retry */
+				xs_close(xprt);
+				break;
 		}
 	}
 out:
---
0.99.8.GIT


--- NEW FILE 0251-RPC-parametrize-various-transport-connect-timeouts.txt ---
Subject: [PATCH] RPC: parametrize various transport connect timeouts
From: Chuck Lever <cel netapp com>
Date: 1125012355 -0700

 Each transport implementation can now set unique bind, connect,
 reestablishment, and idle timeout values.  These are variables,
 allowing the values to be modified dynamically.  This permits
 exponential backoff of any of these values, for instance.

 As an example, we implement exponential backoff for the connection
 reestablishment timeout.

 Test-plan:
 Destructive testing (unplugging the network temporarily).  Connectathon
 with UDP and TCP.

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 fs/nfs/inode.c              |   10 +++---
 include/linux/nfs_fs.h      |    4 +++
 include/linux/sunrpc/xprt.h |   29 ++++--------------
 net/sunrpc/clnt.c           |    2 +
 net/sunrpc/xprt.c           |    5 +--
 net/sunrpc/xprtsock.c       |   68 ++++++++++++++++++++++++++++++++++++++++++-
 6 files changed, 84 insertions(+), 34 deletions(-)

applies-to: 952961988fe19c19fc63f9cffb5edb4566f3527f
03bf4b707eee06706c9db343dd5c905b7ee47ed2
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index b6a1ca5..062911e 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -369,8 +369,8 @@ static void nfs_init_timeout_values(stru
 	case IPPROTO_TCP:
 		if (!to->to_initval)
 			to->to_initval = 60 * HZ;
-		if (to->to_initval > RPC_MAX_TCP_TIMEOUT)
-			to->to_initval = RPC_MAX_TCP_TIMEOUT;
+		if (to->to_initval > NFS_MAX_TCP_TIMEOUT)
+			to->to_initval = NFS_MAX_TCP_TIMEOUT;
 		to->to_increment = to->to_initval;
 		to->to_maxval = to->to_initval + (to->to_increment * to->to_retries);
 		to->to_exponential = 0;
@@ -379,9 +379,9 @@ static void nfs_init_timeout_values(stru
 	default:
 		if (!to->to_initval)
 			to->to_initval = 11 * HZ / 10;
-		if (to->to_initval > RPC_MAX_UDP_TIMEOUT)
-			to->to_initval = RPC_MAX_UDP_TIMEOUT;
-		to->to_maxval = RPC_MAX_UDP_TIMEOUT;
+		if (to->to_initval > NFS_MAX_UDP_TIMEOUT)
+			to->to_initval = NFS_MAX_UDP_TIMEOUT;
+		to->to_maxval = NFS_MAX_UDP_TIMEOUT;
 		to->to_exponential = 1;
 		break;
 	}
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 9a6047f..7bac278 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -41,6 +41,10 @@
 #define NFS_MAX_FILE_IO_BUFFER_SIZE	32768
 #define NFS_DEF_FILE_IO_BUFFER_SIZE	4096
 
+/* Default timeout values */
+#define NFS_MAX_UDP_TIMEOUT	(60*HZ)
+#define NFS_MAX_TCP_TIMEOUT	(600*HZ)
+
 /*
  * superblock magic number for NFS
  */
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 9d9266c..2543adf 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -22,28 +22,6 @@ extern unsigned int xprt_tcp_slot_table_
 #define RPC_DEF_SLOT_TABLE	(16U)
 #define RPC_MAX_SLOT_TABLE	(128U)
 
-/* Default timeout values */
-#define RPC_MAX_UDP_TIMEOUT	(60*HZ)
-#define RPC_MAX_TCP_TIMEOUT	(600*HZ)
-
-/*
- * Wait duration for an RPC TCP connection to be established.  Solaris
- * NFS over TCP uses 60 seconds, for example, which is in line with how
- * long a server takes to reboot.
- */
-#define RPC_CONNECT_TIMEOUT	(60*HZ)
-
-/*
- * Delay an arbitrary number of seconds before attempting to reconnect
- * after an error.
- */
-#define RPC_REESTABLISH_TIMEOUT	(15*HZ)
-
-/*
- * RPC transport idle timeout.
- */
-#define RPC_IDLE_DISCONNECT_TIMEOUT	(5*60*HZ)
-
 /*
  * RPC call and reply header size as number of 32bit words (verifier
  * size computed separately)
@@ -182,14 +160,19 @@ struct rpc_xprt {
 	/*
 	 * Connection of transports
 	 */
+	unsigned long		connect_timeout,
+				bind_timeout,
+				reestablish_timeout;
 	struct work_struct	connect_worker;
 	unsigned short		port;
+
 	/*
 	 * Disconnection of idle transports
 	 */
 	struct work_struct	task_cleanup;
 	struct timer_list	timer;
-	unsigned long		last_used;
+	unsigned long		last_used,
+				idle_timeout;
 
 	/*
 	 * Send stuff
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index cc1b773..24b44e7 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -740,7 +740,7 @@ call_bind(struct rpc_task *task)
 	task->tk_action = call_connect;
 	if (!clnt->cl_port) {
 		task->tk_action = call_bind_status;
-		task->tk_timeout = RPC_CONNECT_TIMEOUT;
+		task->tk_timeout = task->tk_xprt->bind_timeout;
 		rpc_getport(task, clnt);
 	}
 }
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 0458319..215be0d 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -551,7 +551,7 @@ void xprt_connect(struct rpc_task *task)
 		if (task->tk_rqstp)
 			task->tk_rqstp->rq_bytes_sent = 0;
 
-		task->tk_timeout = RPC_CONNECT_TIMEOUT;
+		task->tk_timeout = xprt->connect_timeout;
 		rpc_sleep_on(&xprt->pending, task, xprt_connect_status, NULL);
 		xprt->ops->connect(task);
 	}
@@ -763,7 +763,6 @@ void xprt_transmit(struct rpc_task *task
 
 	switch (status) {
 	case -ECONNREFUSED:
-		task->tk_timeout = RPC_REESTABLISH_TIMEOUT;
 		rpc_sleep_on(&xprt->sending, task, NULL, NULL);
 	case -EAGAIN:
 	case -ENOTCONN:
@@ -857,7 +856,7 @@ void xprt_release(struct rpc_task *task)
 	xprt->last_used = jiffies;
 	if (list_empty(&xprt->recv) && !xprt->shutdown)
 		mod_timer(&xprt->timer,
-				xprt->last_used + RPC_IDLE_DISCONNECT_TIMEOUT);
+				xprt->last_used + xprt->idle_timeout);
 	spin_unlock_bh(&xprt->transport_lock);
 	task->tk_rqstp = NULL;
 	memset(req, 0, sizeof(*req));	/* mark unused */
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 88ac71f..06c2d95 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -41,6 +41,50 @@
  */
 #define XS_SENDMSG_RETRY	(10U)
 
+/*
+ * Time out for an RPC UDP socket connect.  UDP socket connects are
+ * synchronous, but we set a timeout anyway in case of resource
+ * exhaustion on the local host.
+ */
+#define XS_UDP_CONN_TO		(5U * HZ)
+
+/*
+ * Wait duration for an RPC TCP connection to be established.  Solaris
+ * NFS over TCP uses 60 seconds, for example, which is in line with how
+ * long a server takes to reboot.
+ */
+#define XS_TCP_CONN_TO		(60U * HZ)
+
+/*
+ * Wait duration for a reply from the RPC portmapper.
+ */
+#define XS_BIND_TO		(60U * HZ)
+
+/*
+ * Delay if a UDP socket connect error occurs.  This is most likely some
+ * kind of resource problem on the local host.
+ */
+#define XS_UDP_REEST_TO		(2U * HZ)
+
+/*
+ * The reestablish timeout allows clients to delay for a bit before attempting
+ * to reconnect to a server that just dropped our connection.
+ *
+ * We implement an exponential backoff when trying to reestablish a TCP
+ * transport connection with the server.  Some servers like to drop a TCP
+ * connection when they are overworked, so we start with a short timeout and
+ * increase over time if the server is down or not responding.
+ */
+#define XS_TCP_INIT_REEST_TO	(3U * HZ)
+#define XS_TCP_MAX_REEST_TO	(5U * 60 * HZ)
+
+/*
+ * TCP idle timeout; client drops the transport socket if it is idle
+ * for this long.  Note that we also timeout UDP sockets to prevent
+ * holding port numbers when there is no RPC traffic.
+ */
+#define XS_IDLE_DISC_TO		(5U * 60 * HZ)
+
 #ifdef RPC_DEBUG
 # undef  RPC_DEBUG_DATA
 # define RPCDBG_FACILITY	RPCDBG_TRANS
@@ -739,6 +783,7 @@ static void xs_tcp_state_change(struct s
 			xprt->tcp_reclen = 0;
 			xprt->tcp_copied = 0;
 			xprt->tcp_flags = XPRT_COPY_RECM | XPRT_COPY_XID;
+			xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
 			xprt_wake_pending_tasks(xprt, 0);
 		}
 		spin_unlock_bh(&xprt->transport_lock);
@@ -1066,6 +1111,13 @@ out_clear:
  * @task: address of RPC task that manages state of connect request
  *
  * TCP: If the remote end dropped the connection, delay reconnecting.
+ *
+ * UDP socket connects are synchronous, but we use a work queue anyway
+ * to guarantee that even unprivileged user processes can set up a
+ * socket on a privileged port.
+ *
+ * If a UDP socket connect fails, the delay behavior here prevents
+ * retry floods (hard mounts).
  */
 static void xs_connect(struct rpc_task *task)
 {
@@ -1075,9 +1127,13 @@ static void xs_connect(struct rpc_task *
 		return;
 
 	if (xprt->sock != NULL) {
-		dprintk("RPC:      xs_connect delayed xprt %p\n", xprt);
+		dprintk("RPC:      xs_connect delayed xprt %p for %lu seconds\n",
+				xprt, xprt->reestablish_timeout / HZ);
 		schedule_delayed_work(&xprt->connect_worker,
-					RPC_REESTABLISH_TIMEOUT);
+					xprt->reestablish_timeout);
+		xprt->reestablish_timeout <<= 1;
+		if (xprt->reestablish_timeout > XS_TCP_MAX_REEST_TO)
+			xprt->reestablish_timeout = XS_TCP_MAX_REEST_TO;
 	} else {
 		dprintk("RPC:      xs_connect scheduled xprt %p\n", xprt);
 		schedule_work(&xprt->connect_worker);
@@ -1139,6 +1195,10 @@ int xs_setup_udp(struct rpc_xprt *xprt, 
 	xprt->max_payload = (1U << 16) - (MAX_HEADER << 3);
 
 	INIT_WORK(&xprt->connect_worker, xs_udp_connect_worker, xprt);
+	xprt->bind_timeout = XS_BIND_TO;
+	xprt->connect_timeout = XS_UDP_CONN_TO;
+	xprt->reestablish_timeout = XS_UDP_REEST_TO;
+	xprt->idle_timeout = XS_IDLE_DISC_TO;
 
 	xprt->ops = &xs_udp_ops;
 
@@ -1176,6 +1236,10 @@ int xs_setup_tcp(struct rpc_xprt *xprt, 
 	xprt->max_payload = RPC_MAX_FRAGMENT_SIZE;
 
 	INIT_WORK(&xprt->connect_worker, xs_tcp_connect_worker, xprt);
+	xprt->bind_timeout = XS_BIND_TO;
+	xprt->connect_timeout = XS_TCP_CONN_TO;
+	xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
+	xprt->idle_timeout = XS_IDLE_DISC_TO;
 
 	xprt->ops = &xs_tcp_ops;
 
---
0.99.8.GIT


--- NEW FILE 0252-RPC-rationalize-set_buffer_size.txt ---
Subject: [PATCH] RPC: rationalize set_buffer_size
From: Chuck Lever <cel netapp com>
Date: 1125012356 -0700

 In fact, ->set_buffer_size should be completely functionless for non-UDP.

 Test-plan:
 Check socket buffer size on UDP sockets over time.

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/xprt.h |    4 ++--
 net/sunrpc/clnt.c           |   10 ++--------
 net/sunrpc/xprtsock.c       |   30 +++++++++++++++---------------
 3 files changed, 19 insertions(+), 25 deletions(-)

applies-to: 54f89b578758e2bf2650b647ae1c7100c882a757
470056c288334eb0b37be26c9ff8aee37ed1cc7a
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 2543adf..99cad3e 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -100,7 +100,7 @@ struct rpc_rqst {
 #define rq_slen			rq_snd_buf.len
 
 struct rpc_xprt_ops {
-	void		(*set_buffer_size)(struct rpc_xprt *xprt);
+	void		(*set_buffer_size)(struct rpc_xprt *xprt, size_t sndsize, size_t rcvsize);
 	int		(*reserve_xprt)(struct rpc_task *task);
 	void		(*release_xprt)(struct rpc_xprt *xprt, struct rpc_task *task);
 	void		(*connect)(struct rpc_task *task);
@@ -124,7 +124,7 @@ struct rpc_xprt {
 	unsigned long		cong;		/* current congestion */
 	unsigned long		cwnd;		/* congestion window */
 
-	unsigned int		rcvsize,	/* transport rcv buffer size */
+	size_t			rcvsize,	/* transport rcv buffer size */
 				sndsize;	/* transport send buffer size */
 
 	size_t			max_payload;	/* largest RPC payload size,
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 24b44e7..5a8f01d 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -517,14 +517,8 @@ void
 rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize)
 {
 	struct rpc_xprt *xprt = clnt->cl_xprt;
-
-	xprt->sndsize = 0;
-	if (sndsize)
-		xprt->sndsize = sndsize + RPC_SLACK_SPACE;
-	xprt->rcvsize = 0;
-	if (rcvsize)
-		xprt->rcvsize = rcvsize + RPC_SLACK_SPACE;
-	xprt->ops->set_buffer_size(xprt);
+	if (xprt->ops->set_buffer_size)
+		xprt->ops->set_buffer_size(xprt, sndsize, rcvsize);
 }
 
 /*
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 06c2d95..2e15292 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -865,15 +865,7 @@ static void xs_tcp_write_space(struct so
 	read_unlock(&sk->sk_callback_lock);
 }
 
-/**
- * xs_udp_set_buffer_size - set send and receive limits
- * @xprt: generic transport
- *
- * Set socket send and receive limits based on the
- * sndsize and rcvsize fields in the generic transport
- * structure.
- */
-static void xs_udp_set_buffer_size(struct rpc_xprt *xprt)
+static void xs_udp_do_set_buffer_size(struct rpc_xprt *xprt)
 {
 	struct sock *sk = xprt->inet;
 
@@ -889,14 +881,23 @@ static void xs_udp_set_buffer_size(struc
 }
 
 /**
- * xs_tcp_set_buffer_size - set send and receive limits
+ * xs_udp_set_buffer_size - set send and receive limits
  * @xprt: generic transport
+ * @sndsize: requested size of send buffer, in bytes
+ * @rcvsize: requested size of receive buffer, in bytes
  *
- * Nothing to do for TCP.
+ * Set socket send and receive buffer size limits.
  */
-static void xs_tcp_set_buffer_size(struct rpc_xprt *xprt)
+static void xs_udp_set_buffer_size(struct rpc_xprt *xprt, size_t sndsize, size_t rcvsize)
 {
-	return;
+	xprt->sndsize = 0;
+	if (sndsize)
+		xprt->sndsize = sndsize + 1024;
+	xprt->rcvsize = 0;
+	if (rcvsize)
+		xprt->rcvsize = rcvsize + 1024;
+
+	xs_udp_do_set_buffer_size(xprt);
 }
 
 /**
@@ -989,7 +990,7 @@ static void xs_udp_connect_worker(void *
 
 		write_unlock_bh(&sk->sk_callback_lock);
 	}
-	xs_udp_set_buffer_size(xprt);
+	xs_udp_do_set_buffer_size(xprt);
 	status = 0;
 out:
 	xprt_wake_pending_tasks(xprt, status);
@@ -1158,7 +1159,6 @@ static struct rpc_xprt_ops xs_udp_ops = 
 };
 
 static struct rpc_xprt_ops xs_tcp_ops = {
-	.set_buffer_size	= xs_tcp_set_buffer_size,
 	.reserve_xprt		= xprt_reserve_xprt,
 	.release_xprt		= xprt_release_xprt,
 	.connect		= xs_connect,
---
0.99.8.GIT


--- NEW FILE 0253-RPC-NFS-new-rpc_pipefs-patch.txt ---
Subject: [PATCH] RPC,NFS: new rpc_pipefs patch
From: Christoph Hellwig <hch infradead org>
Date: 1122245581 +0100

 Currently rpc_mkdir/rpc_rmdir and rpc_mkpipe/mk_unlink have an API that's
 a little unfortunate.  They take a path relative to the rpc_pipefs root and
 thus need to perform a full lookup.  If you look at debugfs or usbfs they
 always store the dentry for directories they created and thus can pass in
 a dentry + single pathname component pair into their equivalents of the
 above functions.

 And in fact rpc_pipefs actually stores a dentry for all but one component so
 this change not only simplifies the core rpc_pipe code but also the callers.

 Unfortuntately this code path is only used by the NFS4 idmapper and
 AUTH_GSSAPI for which I don't have a test enviroment.  Could someone give
 it a spin?  It's the last bit needed before we can rework the
 lookup_hash API

 Signed-off-by: Christoph Hellwig <hch lst de>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 fs/nfs/idmap.c                     |   10 -
 include/linux/sunrpc/clnt.h        |    2 
 include/linux/sunrpc/rpc_pipe_fs.h |    9 +
 net/sunrpc/auth_gss/auth_gss.c     |    9 -
 net/sunrpc/clnt.c                  |   53 +++++--
 net/sunrpc/rpc_pipe.c              |  268 +++++++++++++-----------------------
 6 files changed, 142 insertions(+), 209 deletions(-)

applies-to: 8c76a17c31c5dadbd4438a11d64364cdbe164c40
278c995c8a153bb2a9bc427e931cfb9c8034c9d7
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
index ffb8df9..1d0a5bf 100644
--- a/fs/nfs/idmap.c
+++ b/fs/nfs/idmap.c
@@ -66,7 +66,6 @@ struct idmap_hashtable {
 };
 
 struct idmap {
-	char                  idmap_path[48];
 	struct dentry        *idmap_dentry;
 	wait_queue_head_t     idmap_wq;
 	struct idmap_msg      idmap_im;
@@ -102,11 +101,8 @@ nfs_idmap_new(struct nfs4_client *clp)
 
 	memset(idmap, 0, sizeof(*idmap));
 
-	snprintf(idmap->idmap_path, sizeof(idmap->idmap_path),
-	    "%s/idmap", clp->cl_rpcclient->cl_pathname);
-
-        idmap->idmap_dentry = rpc_mkpipe(idmap->idmap_path,
-	    idmap, &idmap_upcall_ops, 0);
+	idmap->idmap_dentry = rpc_mkpipe(clp->cl_rpcclient->cl_dentry,
+			"idmap", idmap, &idmap_upcall_ops, 0);
         if (IS_ERR(idmap->idmap_dentry)) {
 		kfree(idmap);
 		return;
@@ -128,7 +124,7 @@ nfs_idmap_delete(struct nfs4_client *clp
 
 	if (!idmap)
 		return;
-	rpc_unlink(idmap->idmap_path);
+	rpc_unlink(idmap->idmap_dentry);
 	clp->cl_idmap = NULL;
 	kfree(idmap);
 }
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index ab151bb..b5b51c1 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -59,7 +59,7 @@ struct rpc_clnt {
 
 	int			cl_nodelen;	/* nodename length */
 	char 			cl_nodename[UNX_MAXNODENAME];
-	char			cl_pathname[30];/* Path in rpc_pipe_fs */
+	struct dentry *		__cl_parent_dentry;
 	struct dentry *		cl_dentry;	/* inode */
 	struct rpc_clnt *	cl_parent;	/* Points to parent of clones */
 	struct rpc_rtt		cl_rtt_default;
diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h
index 6392934..63878d0 100644
--- a/include/linux/sunrpc/rpc_pipe_fs.h
+++ b/include/linux/sunrpc/rpc_pipe_fs.h
@@ -41,10 +41,11 @@ RPC_I(struct inode *inode)
 
 extern int rpc_queue_upcall(struct inode *, struct rpc_pipe_msg *);
 
-extern struct dentry *rpc_mkdir(char *, struct rpc_clnt *);
-extern int rpc_rmdir(char *);
-extern struct dentry *rpc_mkpipe(char *, void *, struct rpc_pipe_ops *, int flags);
-extern int rpc_unlink(char *);
+extern struct dentry *rpc_mkdir(struct dentry *, char *, struct rpc_clnt *);
+extern void rpc_rmdir(struct dentry *);
+extern struct dentry *rpc_mkpipe(struct dentry *, char *, void *,
+		struct rpc_pipe_ops *, int flags);
+extern void rpc_unlink(struct dentry *);
 
 #endif
 #endif
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index d2b08f1..bd25551 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -87,7 +87,6 @@ struct gss_auth {
 	struct list_head upcalls;
 	struct rpc_clnt *client;
 	struct dentry *dentry;
-	char path[48];
 	spinlock_t lock;
 };
 
@@ -690,10 +689,8 @@ gss_create(struct rpc_clnt *clnt, rpc_au
 	if (err)
 		goto err_put_mech;
 
-	snprintf(gss_auth->path, sizeof(gss_auth->path), "%s/%s",
-			clnt->cl_pathname,
-			gss_auth->mech->gm_name);
-	gss_auth->dentry = rpc_mkpipe(gss_auth->path, clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
+	gss_auth->dentry = rpc_mkpipe(clnt->cl_dentry, gss_auth->mech->gm_name,
+			clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
 	if (IS_ERR(gss_auth->dentry)) {
 		err = PTR_ERR(gss_auth->dentry);
 		goto err_put_mech;
@@ -718,7 +715,7 @@ gss_destroy(struct rpc_auth *auth)
 		auth, auth->au_flavor);
 
 	gss_auth = container_of(auth, struct gss_auth, rpc_auth);
-	rpc_unlink(gss_auth->path);
+	rpc_unlink(gss_auth->dentry);
 	gss_mech_put(gss_auth->mech);
 
 	rpcauth_free_credcache(auth);
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 5a8f01d..63bf591 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -67,26 +67,42 @@ static u32 *	call_verify(struct rpc_task
 static int
 rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
 {
-	static uint32_t clntid;
+	static unsigned int clntid;
+	char name[128];
 	int error;
 
 	if (dir_name == NULL)
 		return 0;
-	for (;;) {
-		snprintf(clnt->cl_pathname, sizeof(clnt->cl_pathname),
-				"%s/clnt%x", dir_name,
-				(unsigned int)clntid++);
-		clnt->cl_pathname[sizeof(clnt->cl_pathname) - 1] = '\0';
-		clnt->cl_dentry = rpc_mkdir(clnt->cl_pathname, clnt);
-		if (!IS_ERR(clnt->cl_dentry))
-			return 0;
+
+ retry_parent:
+	clnt->__cl_parent_dentry = rpc_mkdir(NULL, dir_name, NULL);
+	if (IS_ERR(clnt->__cl_parent_dentry)) {
+		error = PTR_ERR(clnt->__cl_parent_dentry);
+		if (error == -EEXIST)
+			goto retry_parent; /* XXX(hch): WTF? */
+	
+		printk(KERN_INFO "RPC: Couldn't create pipefs entry %s, error %d\n",
+				dir_name, error);
+		return error;
+	}
+
+
+ retry_child:
+	snprintf(name, sizeof(name), "clnt%x", clntid++);
+	name[sizeof(name) - 1] = '\0';
+
+	clnt->cl_dentry = rpc_mkdir(clnt->__cl_parent_dentry, name, clnt);
+	if (IS_ERR(clnt->cl_dentry)) {
 		error = PTR_ERR(clnt->cl_dentry);
-		if (error != -EEXIST) {
-			printk(KERN_INFO "RPC: Couldn't create pipefs entry %s, error %d\n",
-					clnt->cl_pathname, error);
-			return error;
-		}
+		if (error == -EEXIST)
+			goto retry_child;
+		printk(KERN_INFO "RPC: Couldn't create pipefs entry %s, error %d\n",
+				name, error);
+		rpc_rmdir(clnt->__cl_parent_dentry);
+		return error;
 	}
+
+	return 0;
 }
 
 /*
@@ -174,7 +190,8 @@ rpc_new_client(struct rpc_xprt *xprt, ch
 	return clnt;
 
 out_no_auth:
-	rpc_rmdir(clnt->cl_pathname);
+	rpc_rmdir(clnt->cl_dentry);
+	rpc_rmdir(clnt->__cl_parent_dentry);
 out_no_path:
 	if (clnt->cl_server != clnt->cl_inline_name)
 		kfree(clnt->cl_server);
@@ -302,8 +319,10 @@ rpc_destroy_client(struct rpc_clnt *clnt
 		rpc_destroy_client(clnt->cl_parent);
 		goto out_free;
 	}
-	if (clnt->cl_pathname[0])
-		rpc_rmdir(clnt->cl_pathname);
+	if (clnt->cl_dentry)
+		rpc_rmdir(clnt->cl_dentry);
+	if (clnt->__cl_parent_dentry)
+		rpc_rmdir(clnt->__cl_parent_dentry);
 	if (clnt->cl_xprt) {
 		xprt_destroy(clnt->cl_xprt);
 		clnt->cl_xprt = NULL;
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index ded6c63..b382809 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -414,38 +414,6 @@ rpc_put_mount(void)
 	simple_release_fs(&rpc_mount, &rpc_mount_count);
 }
 
-static int
-rpc_lookup_parent(char *path, struct nameidata *nd)
-{
-	if (path[0] == '\0')
-		return -ENOENT;
-	if (rpc_get_mount()) {
-		printk(KERN_WARNING "%s: %s failed to mount "
-			       "pseudofilesystem \n", __FILE__, __FUNCTION__);
-		return -ENODEV;
-	}
-	nd->mnt = mntget(rpc_mount);
-	nd->dentry = dget(rpc_mount->mnt_root);
-	nd->last_type = LAST_ROOT;
-	nd->flags = LOOKUP_PARENT;
-	nd->depth = 0;
-
-	if (path_walk(path, nd)) {
-		printk(KERN_WARNING "%s: %s failed to find path %s\n",
-				__FILE__, __FUNCTION__, path);
-		rpc_put_mount();
-		return -ENOENT;
-	}
-	return 0;
-}
-
-static void
-rpc_release_path(struct nameidata *nd)
-{
-	path_release(nd);
-	rpc_put_mount();
-}
-
 static struct inode *
 rpc_get_inode(struct super_block *sb, int mode)
 {
@@ -550,197 +518,149 @@ out_bad:
 	return -ENOMEM;
 }
 
-static int
-__rpc_mkdir(struct inode *dir, struct dentry *dentry)
+struct dentry *
+rpc_mkdir(struct dentry *parent, char *name, struct rpc_clnt *rpc_client)
 {
+	struct inode *dir;
+	struct dentry *dentry;
 	struct inode *inode;
-
-	inode = rpc_get_inode(dir->i_sb, S_IFDIR | S_IRUSR | S_IXUSR);
-	if (!inode)
-		goto out_err;
-	inode->i_ino = iunique(dir->i_sb, 100);
-	d_instantiate(dentry, inode);
-	dir->i_nlink++;
-	inode_dir_notify(dir, DN_CREATE);
-	rpc_get_mount();
-	return 0;
-out_err:
-	printk(KERN_WARNING "%s: %s failed to allocate inode for dentry %s\n",
-			__FILE__, __FUNCTION__, dentry->d_name.name);
-	return -ENOMEM;
-}
-
-static int
-__rpc_rmdir(struct inode *dir, struct dentry *dentry)
-{
 	int error;
 
-	shrink_dcache_parent(dentry);
-	if (dentry->d_inode) {
-		rpc_close_pipes(dentry->d_inode);
-		rpc_inode_setowner(dentry->d_inode, NULL);
-	}
-	if ((error = simple_rmdir(dir, dentry)) != 0)
-		return error;
-	if (!error) {
-		inode_dir_notify(dir, DN_DELETE);
-		d_drop(dentry);
-		rpc_put_mount();
-	}
-	return 0;
-}
-
-static struct dentry *
-rpc_lookup_negative(char *path, struct nameidata *nd)
-{
-	struct dentry *dentry;
-	struct inode *dir;
-	int error;
+	if (!parent)
+		parent = rpc_mount->mnt_root;
 
-	if ((error = rpc_lookup_parent(path, nd)) != 0)
+	dir = parent->d_inode;
+	
+	error = rpc_get_mount();
+	if (error)
 		return ERR_PTR(error);
-	dir = nd->dentry->d_inode;
+
 	down(&dir->i_sem);
-	dentry = lookup_hash(&nd->last, nd->dentry);
+	dentry = lookup_one_len(name, parent, strlen(name));
 	if (IS_ERR(dentry))
-		goto out_err;
+		goto out_unlock;
 	if (dentry->d_inode) {
-		dput(dentry);
 		dentry = ERR_PTR(-EEXIST);
-		goto out_err;
+		goto out_dput;
 	}
-	return dentry;
-out_err:
-	up(&dir->i_sem);
-	rpc_release_path(nd);
-	return dentry;
-}
 
+	inode = rpc_get_inode(dir->i_sb, S_IFDIR | S_IRUSR | S_IXUSR);
+	if (!inode)
+		goto out_dput;
+	inode->i_ino = iunique(dir->i_sb, 100);
+	dir->i_nlink++;
+	RPC_I(dentry->d_inode)->private = rpc_client;
 
-struct dentry *
-rpc_mkdir(char *path, struct rpc_clnt *rpc_client)
-{
-	struct nameidata nd;
-	struct dentry *dentry;
-	struct inode *dir;
-	int error;
+	d_instantiate(dentry, inode);
+	dget(dentry);
+	up(&dir->i_sem);
+
+	inode_dir_notify(dir, DN_CREATE);
 
-	dentry = rpc_lookup_negative(path, &nd);
-	if (IS_ERR(dentry))
-		return dentry;
-	dir = nd.dentry->d_inode;
-	if ((error = __rpc_mkdir(dir, dentry)) != 0)
-		goto err_dput;
-	RPC_I(dentry->d_inode)->private = rpc_client;
 	error = rpc_populate(dentry, authfiles,
 			RPCAUTH_info, RPCAUTH_EOF);
 	if (error)
-		goto err_depopulate;
-out:
-	up(&dir->i_sem);
-	rpc_release_path(&nd);
+		goto out_depopulate;
+
 	return dentry;
-err_depopulate:
-	rpc_depopulate(dentry);
-	__rpc_rmdir(dir, dentry);
-err_dput:
+
+ out_depopulate:
+	rpc_rmdir(dentry);
+ out_dput:
 	dput(dentry);
-	printk(KERN_WARNING "%s: %s() failed to create directory %s (errno = %d)\n",
-			__FILE__, __FUNCTION__, path, error);
-	dentry = ERR_PTR(error);
-	goto out;
+ out_unlock:
+	up(&dir->i_sem);
+	rpc_put_mount();
+	return dentry;
 }
 
-int
-rpc_rmdir(char *path)
+void
+rpc_rmdir(struct dentry *dentry)
 {
-	struct nameidata nd;
-	struct dentry *dentry;
-	struct inode *dir;
-	int error;
+	struct dentry *parent = dentry->d_parent;
 
-	if ((error = rpc_lookup_parent(path, &nd)) != 0)
-		return error;
-	dir = nd.dentry->d_inode;
-	down(&dir->i_sem);
-	dentry = lookup_hash(&nd.last, nd.dentry);
-	if (IS_ERR(dentry)) {
-		error = PTR_ERR(dentry);
-		goto out_release;
-	}
 	rpc_depopulate(dentry);
-	error = __rpc_rmdir(dir, dentry);
-	dput(dentry);
-out_release:
-	up(&dir->i_sem);
-	rpc_release_path(&nd);
-	return error;
+
+	down(&parent->d_inode->i_sem);
+	if (dentry->d_inode) {
+		rpc_close_pipes(dentry->d_inode);
+		rpc_inode_setowner(dentry->d_inode, NULL);
+		simple_rmdir(parent->d_inode, dentry);
+	}
+	up(&parent->d_inode->i_sem);
+
+	inode_dir_notify(parent->d_inode, DN_DELETE);
+	rpc_put_mount();
 }
 
 struct dentry *
-rpc_mkpipe(char *path, void *private, struct rpc_pipe_ops *ops, int flags)
+rpc_mkpipe(struct dentry *parent, char *name, void *private,
+	   struct rpc_pipe_ops *ops, int flags)
 {
-	struct nameidata nd;
+	struct inode *dir = parent->d_inode;
 	struct dentry *dentry;
-	struct inode *dir, *inode;
+	struct inode *inode;
 	struct rpc_inode *rpci;
+	int error;
 
-	dentry = rpc_lookup_negative(path, &nd);
+	error = rpc_get_mount();
+	if (error)
+		return ERR_PTR(error);
+
+	down(&parent->d_inode->i_sem);
+	dentry = lookup_one_len(name, parent, strlen(name));
 	if (IS_ERR(dentry))
-		return dentry;
-	dir = nd.dentry->d_inode;
-	inode = rpc_get_inode(dir->i_sb, S_IFSOCK | S_IRUSR | S_IWUSR);
-	if (!inode)
-		goto err_dput;
+		goto out_unlock;
+	if (dentry->d_inode) {
+		dentry = ERR_PTR(-EEXIST);
+		goto out_dput;
+	}
+
+	inode = rpc_get_inode(parent->d_inode->i_sb,
+			S_IFSOCK | S_IRUSR | S_IWUSR);
+	if (!inode) {
+		dentry = ERR_PTR(-ENOMEM);
+		goto out_dput;
+	}
+
 	inode->i_ino = iunique(dir->i_sb, 100);
 	inode->i_fop = &rpc_pipe_fops;
-	d_instantiate(dentry, inode);
+
 	rpci = RPC_I(inode);
 	rpci->private = private;
 	rpci->flags = flags;
 	rpci->ops = ops;
+
+	d_instantiate(dentry, inode);
+	dget(dentry);
+	up(&parent->d_inode->i_sem);
+
 	inode_dir_notify(dir, DN_CREATE);
-out:
-	up(&dir->i_sem);
-	rpc_release_path(&nd);
 	return dentry;
-err_dput:
+
+ out_dput:
 	dput(dentry);
-	dentry = ERR_PTR(-ENOMEM);
-	printk(KERN_WARNING "%s: %s() failed to create pipe %s (errno = %d)\n",
-			__FILE__, __FUNCTION__, path, -ENOMEM);
-	goto out;
+ out_unlock:
+	up(&parent->d_inode->i_sem);
+	rpc_put_mount();
+	return dentry;
 }
 
-int
-rpc_unlink(char *path)
+void
+rpc_unlink(struct dentry *dentry)
 {
-	struct nameidata nd;
-	struct dentry *dentry;
-	struct inode *dir;
-	int error;
+	struct dentry *parent = dentry->d_parent;
 
-	if ((error = rpc_lookup_parent(path, &nd)) != 0)
-		return error;
-	dir = nd.dentry->d_inode;
-	down(&dir->i_sem);
-	dentry = lookup_hash(&nd.last, nd.dentry);
-	if (IS_ERR(dentry)) {
-		error = PTR_ERR(dentry);
-		goto out_release;
-	}
-	d_drop(dentry);
+	down(&parent->d_inode->i_sem);
 	if (dentry->d_inode) {
 		rpc_close_pipes(dentry->d_inode);
 		rpc_inode_setowner(dentry->d_inode, NULL);
-		error = simple_unlink(dir, dentry);
+		simple_unlink(parent->d_inode, dentry);
 	}
-	dput(dentry);
-	inode_dir_notify(dir, DN_DELETE);
-out_release:
-	up(&dir->i_sem);
-	rpc_release_path(&nd);
-	return error;
+	up(&parent->d_inode->i_sem);
+
+	inode_dir_notify(parent->d_inode, DN_DELETE);
+	rpc_put_mount();
 }
 
 /*
---
0.99.8.GIT


--- NEW FILE 0255-Revert-PATCH-RPC-NFS-new-rpc_pipefs-patch.txt ---
Subject: [PATCH] Revert "[PATCH] RPC,NFS: new rpc_pipefs patch"
From: Trond Myklebust <Trond Myklebust netapp com>
Date: 1127488105 -0400

This reverts 17f4e6febca160a9f9dd4bdece9784577a2f4524 commit.

---

 fs/nfs/idmap.c                     |   10 +
 include/linux/sunrpc/clnt.h        |    2 
 include/linux/sunrpc/rpc_pipe_fs.h |    9 +
 net/sunrpc/auth_gss/auth_gss.c     |    9 +
 net/sunrpc/clnt.c                  |   53 ++-----
 net/sunrpc/rpc_pipe.c              |  268 +++++++++++++++++++++++-------------
 6 files changed, 209 insertions(+), 142 deletions(-)

applies-to: e44b1e23f7a7c642d9ef5040a2bc0b753e0fad99
f134585a7343d71f9be7f0cf97e2145f21dd10c6
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
index 1d0a5bf..ffb8df9 100644
--- a/fs/nfs/idmap.c
+++ b/fs/nfs/idmap.c
@@ -66,6 +66,7 @@ struct idmap_hashtable {
 };
 
 struct idmap {
+	char                  idmap_path[48];
 	struct dentry        *idmap_dentry;
 	wait_queue_head_t     idmap_wq;
 	struct idmap_msg      idmap_im;
@@ -101,8 +102,11 @@ nfs_idmap_new(struct nfs4_client *clp)
 
 	memset(idmap, 0, sizeof(*idmap));
 
-	idmap->idmap_dentry = rpc_mkpipe(clp->cl_rpcclient->cl_dentry,
-			"idmap", idmap, &idmap_upcall_ops, 0);
+	snprintf(idmap->idmap_path, sizeof(idmap->idmap_path),
+	    "%s/idmap", clp->cl_rpcclient->cl_pathname);
+
+        idmap->idmap_dentry = rpc_mkpipe(idmap->idmap_path,
+	    idmap, &idmap_upcall_ops, 0);
         if (IS_ERR(idmap->idmap_dentry)) {
 		kfree(idmap);
 		return;
@@ -124,7 +128,7 @@ nfs_idmap_delete(struct nfs4_client *clp
 
 	if (!idmap)
 		return;
-	rpc_unlink(idmap->idmap_dentry);
+	rpc_unlink(idmap->idmap_path);
 	clp->cl_idmap = NULL;
 	kfree(idmap);
 }
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index b5b51c1..ab151bb 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -59,7 +59,7 @@ struct rpc_clnt {
 
 	int			cl_nodelen;	/* nodename length */
 	char 			cl_nodename[UNX_MAXNODENAME];
-	struct dentry *		__cl_parent_dentry;
+	char			cl_pathname[30];/* Path in rpc_pipe_fs */
 	struct dentry *		cl_dentry;	/* inode */
 	struct rpc_clnt *	cl_parent;	/* Points to parent of clones */
 	struct rpc_rtt		cl_rtt_default;
diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h
index 63878d0..6392934 100644
--- a/include/linux/sunrpc/rpc_pipe_fs.h
+++ b/include/linux/sunrpc/rpc_pipe_fs.h
@@ -41,11 +41,10 @@ RPC_I(struct inode *inode)
 
 extern int rpc_queue_upcall(struct inode *, struct rpc_pipe_msg *);
 
-extern struct dentry *rpc_mkdir(struct dentry *, char *, struct rpc_clnt *);
-extern void rpc_rmdir(struct dentry *);
-extern struct dentry *rpc_mkpipe(struct dentry *, char *, void *,
-		struct rpc_pipe_ops *, int flags);
-extern void rpc_unlink(struct dentry *);
+extern struct dentry *rpc_mkdir(char *, struct rpc_clnt *);
+extern int rpc_rmdir(char *);
+extern struct dentry *rpc_mkpipe(char *, void *, struct rpc_pipe_ops *, int flags);
+extern int rpc_unlink(char *);
 
 #endif
 #endif
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index bd25551..d2b08f1 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -87,6 +87,7 @@ struct gss_auth {
 	struct list_head upcalls;
 	struct rpc_clnt *client;
 	struct dentry *dentry;
+	char path[48];
 	spinlock_t lock;
 };
 
@@ -689,8 +690,10 @@ gss_create(struct rpc_clnt *clnt, rpc_au
 	if (err)
 		goto err_put_mech;
 
-	gss_auth->dentry = rpc_mkpipe(clnt->cl_dentry, gss_auth->mech->gm_name,
-			clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
+	snprintf(gss_auth->path, sizeof(gss_auth->path), "%s/%s",
+			clnt->cl_pathname,
+			gss_auth->mech->gm_name);
+	gss_auth->dentry = rpc_mkpipe(gss_auth->path, clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
 	if (IS_ERR(gss_auth->dentry)) {
 		err = PTR_ERR(gss_auth->dentry);
 		goto err_put_mech;
@@ -715,7 +718,7 @@ gss_destroy(struct rpc_auth *auth)
 		auth, auth->au_flavor);
 
 	gss_auth = container_of(auth, struct gss_auth, rpc_auth);
-	rpc_unlink(gss_auth->dentry);
+	rpc_unlink(gss_auth->path);
 	gss_mech_put(gss_auth->mech);
 
 	rpcauth_free_credcache(auth);
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 63bf591..5a8f01d 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -67,42 +67,26 @@ static u32 *	call_verify(struct rpc_task
 static int
 rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
 {
-	static unsigned int clntid;
-	char name[128];
+	static uint32_t clntid;
 	int error;
 
 	if (dir_name == NULL)
 		return 0;
-
- retry_parent:
-	clnt->__cl_parent_dentry = rpc_mkdir(NULL, dir_name, NULL);
-	if (IS_ERR(clnt->__cl_parent_dentry)) {
-		error = PTR_ERR(clnt->__cl_parent_dentry);
-		if (error == -EEXIST)
-			goto retry_parent; /* XXX(hch): WTF? */
-	
-		printk(KERN_INFO "RPC: Couldn't create pipefs entry %s, error %d\n",
-				dir_name, error);
-		return error;
-	}
-
-
- retry_child:
-	snprintf(name, sizeof(name), "clnt%x", clntid++);
-	name[sizeof(name) - 1] = '\0';
-
-	clnt->cl_dentry = rpc_mkdir(clnt->__cl_parent_dentry, name, clnt);
-	if (IS_ERR(clnt->cl_dentry)) {
+	for (;;) {
+		snprintf(clnt->cl_pathname, sizeof(clnt->cl_pathname),
+				"%s/clnt%x", dir_name,
+				(unsigned int)clntid++);
+		clnt->cl_pathname[sizeof(clnt->cl_pathname) - 1] = '\0';
+		clnt->cl_dentry = rpc_mkdir(clnt->cl_pathname, clnt);
+		if (!IS_ERR(clnt->cl_dentry))
+			return 0;
 		error = PTR_ERR(clnt->cl_dentry);
-		if (error == -EEXIST)
-			goto retry_child;
-		printk(KERN_INFO "RPC: Couldn't create pipefs entry %s, error %d\n",
-				name, error);
-		rpc_rmdir(clnt->__cl_parent_dentry);
-		return error;
+		if (error != -EEXIST) {
+			printk(KERN_INFO "RPC: Couldn't create pipefs entry %s, error %d\n",
+					clnt->cl_pathname, error);
+			return error;
+		}
 	}
-
-	return 0;
 }
 
 /*
@@ -190,8 +174,7 @@ rpc_new_client(struct rpc_xprt *xprt, ch
 	return clnt;
 
 out_no_auth:
-	rpc_rmdir(clnt->cl_dentry);
-	rpc_rmdir(clnt->__cl_parent_dentry);
+	rpc_rmdir(clnt->cl_pathname);
 out_no_path:
 	if (clnt->cl_server != clnt->cl_inline_name)
 		kfree(clnt->cl_server);
@@ -319,10 +302,8 @@ rpc_destroy_client(struct rpc_clnt *clnt
 		rpc_destroy_client(clnt->cl_parent);
 		goto out_free;
 	}
-	if (clnt->cl_dentry)
-		rpc_rmdir(clnt->cl_dentry);
-	if (clnt->__cl_parent_dentry)
-		rpc_rmdir(clnt->__cl_parent_dentry);
+	if (clnt->cl_pathname[0])
+		rpc_rmdir(clnt->cl_pathname);
 	if (clnt->cl_xprt) {
 		xprt_destroy(clnt->cl_xprt);
 		clnt->cl_xprt = NULL;
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index b382809..ded6c63 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -414,6 +414,38 @@ rpc_put_mount(void)
 	simple_release_fs(&rpc_mount, &rpc_mount_count);
 }
 
+static int
+rpc_lookup_parent(char *path, struct nameidata *nd)
+{
+	if (path[0] == '\0')
+		return -ENOENT;
+	if (rpc_get_mount()) {
+		printk(KERN_WARNING "%s: %s failed to mount "
+			       "pseudofilesystem \n", __FILE__, __FUNCTION__);
+		return -ENODEV;
+	}
+	nd->mnt = mntget(rpc_mount);
+	nd->dentry = dget(rpc_mount->mnt_root);
+	nd->last_type = LAST_ROOT;
+	nd->flags = LOOKUP_PARENT;
+	nd->depth = 0;
+
+	if (path_walk(path, nd)) {
+		printk(KERN_WARNING "%s: %s failed to find path %s\n",
+				__FILE__, __FUNCTION__, path);
+		rpc_put_mount();
+		return -ENOENT;
+	}
+	return 0;
+}
+
+static void
+rpc_release_path(struct nameidata *nd)
+{
+	path_release(nd);
+	rpc_put_mount();
+}
+
 static struct inode *
 rpc_get_inode(struct super_block *sb, int mode)
 {
@@ -518,149 +550,197 @@ out_bad:
 	return -ENOMEM;
 }
 
-struct dentry *
-rpc_mkdir(struct dentry *parent, char *name, struct rpc_clnt *rpc_client)
+static int
+__rpc_mkdir(struct inode *dir, struct dentry *dentry)
 {
-	struct inode *dir;
-	struct dentry *dentry;
 	struct inode *inode;
+
+	inode = rpc_get_inode(dir->i_sb, S_IFDIR | S_IRUSR | S_IXUSR);
+	if (!inode)
+		goto out_err;
+	inode->i_ino = iunique(dir->i_sb, 100);
+	d_instantiate(dentry, inode);
+	dir->i_nlink++;
+	inode_dir_notify(dir, DN_CREATE);
+	rpc_get_mount();
+	return 0;
+out_err:
+	printk(KERN_WARNING "%s: %s failed to allocate inode for dentry %s\n",
+			__FILE__, __FUNCTION__, dentry->d_name.name);
+	return -ENOMEM;
+}
+
+static int
+__rpc_rmdir(struct inode *dir, struct dentry *dentry)
+{
 	int error;
 
-	if (!parent)
-		parent = rpc_mount->mnt_root;
+	shrink_dcache_parent(dentry);
+	if (dentry->d_inode) {
+		rpc_close_pipes(dentry->d_inode);
+		rpc_inode_setowner(dentry->d_inode, NULL);
+	}
+	if ((error = simple_rmdir(dir, dentry)) != 0)
+		return error;
+	if (!error) {
+		inode_dir_notify(dir, DN_DELETE);
+		d_drop(dentry);
+		rpc_put_mount();
+	}
+	return 0;
+}
+
+static struct dentry *
+rpc_lookup_negative(char *path, struct nameidata *nd)
+{
+	struct dentry *dentry;
+	struct inode *dir;
+	int error;
 
-	dir = parent->d_inode;
-	
-	error = rpc_get_mount();
-	if (error)
+	if ((error = rpc_lookup_parent(path, nd)) != 0)
 		return ERR_PTR(error);
-
+	dir = nd->dentry->d_inode;
 	down(&dir->i_sem);
-	dentry = lookup_one_len(name, parent, strlen(name));
+	dentry = lookup_hash(&nd->last, nd->dentry);
 	if (IS_ERR(dentry))
-		goto out_unlock;
+		goto out_err;
 	if (dentry->d_inode) {
+		dput(dentry);
 		dentry = ERR_PTR(-EEXIST);
-		goto out_dput;
+		goto out_err;
 	}
-
-	inode = rpc_get_inode(dir->i_sb, S_IFDIR | S_IRUSR | S_IXUSR);
-	if (!inode)
-		goto out_dput;
-	inode->i_ino = iunique(dir->i_sb, 100);
-	dir->i_nlink++;
-	RPC_I(dentry->d_inode)->private = rpc_client;
-
-	d_instantiate(dentry, inode);
-	dget(dentry);
+	return dentry;
+out_err:
 	up(&dir->i_sem);
+	rpc_release_path(nd);
+	return dentry;
+}
 
-	inode_dir_notify(dir, DN_CREATE);
 
+struct dentry *
+rpc_mkdir(char *path, struct rpc_clnt *rpc_client)
+{
+	struct nameidata nd;
+	struct dentry *dentry;
+	struct inode *dir;
+	int error;
+
+	dentry = rpc_lookup_negative(path, &nd);
+	if (IS_ERR(dentry))
+		return dentry;
+	dir = nd.dentry->d_inode;
+	if ((error = __rpc_mkdir(dir, dentry)) != 0)
+		goto err_dput;
+	RPC_I(dentry->d_inode)->private = rpc_client;
 	error = rpc_populate(dentry, authfiles,
 			RPCAUTH_info, RPCAUTH_EOF);
 	if (error)
-		goto out_depopulate;
-
-	return dentry;
-
- out_depopulate:
-	rpc_rmdir(dentry);
- out_dput:
-	dput(dentry);
- out_unlock:
+		goto err_depopulate;
+out:
 	up(&dir->i_sem);
-	rpc_put_mount();
+	rpc_release_path(&nd);
 	return dentry;
+err_depopulate:
+	rpc_depopulate(dentry);
+	__rpc_rmdir(dir, dentry);
+err_dput:
+	dput(dentry);
+	printk(KERN_WARNING "%s: %s() failed to create directory %s (errno = %d)\n",
+			__FILE__, __FUNCTION__, path, error);
+	dentry = ERR_PTR(error);
+	goto out;
 }
 
-void
-rpc_rmdir(struct dentry *dentry)
+int
+rpc_rmdir(char *path)
 {
-	struct dentry *parent = dentry->d_parent;
-
-	rpc_depopulate(dentry);
+	struct nameidata nd;
+	struct dentry *dentry;
+	struct inode *dir;
+	int error;
 
-	down(&parent->d_inode->i_sem);
-	if (dentry->d_inode) {
-		rpc_close_pipes(dentry->d_inode);
-		rpc_inode_setowner(dentry->d_inode, NULL);
-		simple_rmdir(parent->d_inode, dentry);
+	if ((error = rpc_lookup_parent(path, &nd)) != 0)
+		return error;
+	dir = nd.dentry->d_inode;
+	down(&dir->i_sem);
+	dentry = lookup_hash(&nd.last, nd.dentry);
+	if (IS_ERR(dentry)) {
+		error = PTR_ERR(dentry);
+		goto out_release;
 	}
-	up(&parent->d_inode->i_sem);
-
-	inode_dir_notify(parent->d_inode, DN_DELETE);
-	rpc_put_mount();
+	rpc_depopulate(dentry);
+	error = __rpc_rmdir(dir, dentry);
+	dput(dentry);
+out_release:
+	up(&dir->i_sem);
+	rpc_release_path(&nd);
+	return error;
 }
 
 struct dentry *
-rpc_mkpipe(struct dentry *parent, char *name, void *private,
-	   struct rpc_pipe_ops *ops, int flags)
+rpc_mkpipe(char *path, void *private, struct rpc_pipe_ops *ops, int flags)
 {
-	struct inode *dir = parent->d_inode;
+	struct nameidata nd;
 	struct dentry *dentry;
-	struct inode *inode;
+	struct inode *dir, *inode;
 	struct rpc_inode *rpci;
-	int error;
 
-	error = rpc_get_mount();
-	if (error)
-		return ERR_PTR(error);
-
-	down(&parent->d_inode->i_sem);
-	dentry = lookup_one_len(name, parent, strlen(name));
+	dentry = rpc_lookup_negative(path, &nd);
 	if (IS_ERR(dentry))
-		goto out_unlock;
-	if (dentry->d_inode) {
-		dentry = ERR_PTR(-EEXIST);
-		goto out_dput;
-	}
-
-	inode = rpc_get_inode(parent->d_inode->i_sb,
-			S_IFSOCK | S_IRUSR | S_IWUSR);
-	if (!inode) {
-		dentry = ERR_PTR(-ENOMEM);
-		goto out_dput;
-	}
-
+		return dentry;
+	dir = nd.dentry->d_inode;
+	inode = rpc_get_inode(dir->i_sb, S_IFSOCK | S_IRUSR | S_IWUSR);
+	if (!inode)
+		goto err_dput;
 	inode->i_ino = iunique(dir->i_sb, 100);
 	inode->i_fop = &rpc_pipe_fops;
-
+	d_instantiate(dentry, inode);
 	rpci = RPC_I(inode);
 	rpci->private = private;
 	rpci->flags = flags;
 	rpci->ops = ops;
-
-	d_instantiate(dentry, inode);
-	dget(dentry);
-	up(&parent->d_inode->i_sem);
-
 	inode_dir_notify(dir, DN_CREATE);
+out:
+	up(&dir->i_sem);
+	rpc_release_path(&nd);
 	return dentry;
-
- out_dput:
+err_dput:
 	dput(dentry);
- out_unlock:
-	up(&parent->d_inode->i_sem);
-	rpc_put_mount();
-	return dentry;
+	dentry = ERR_PTR(-ENOMEM);
+	printk(KERN_WARNING "%s: %s() failed to create pipe %s (errno = %d)\n",
+			__FILE__, __FUNCTION__, path, -ENOMEM);
+	goto out;
 }
 
-void
-rpc_unlink(struct dentry *dentry)
+int
+rpc_unlink(char *path)
 {
-	struct dentry *parent = dentry->d_parent;
+	struct nameidata nd;
+	struct dentry *dentry;
+	struct inode *dir;
+	int error;
 
-	down(&parent->d_inode->i_sem);
+	if ((error = rpc_lookup_parent(path, &nd)) != 0)
+		return error;
+	dir = nd.dentry->d_inode;
+	down(&dir->i_sem);
+	dentry = lookup_hash(&nd.last, nd.dentry);
+	if (IS_ERR(dentry)) {
+		error = PTR_ERR(dentry);
+		goto out_release;
+	}
+	d_drop(dentry);
 	if (dentry->d_inode) {
 		rpc_close_pipes(dentry->d_inode);
 		rpc_inode_setowner(dentry->d_inode, NULL);
-		simple_unlink(parent->d_inode, dentry);
+		error = simple_unlink(dir, dentry);
 	}
-	up(&parent->d_inode->i_sem);
-
-	inode_dir_notify(parent->d_inode, DN_DELETE);
-	rpc_put_mount();
+	dput(dentry);
+	inode_dir_notify(dir, DN_DELETE);
+out_release:
+	up(&dir->i_sem);
+	rpc_release_path(&nd);
+	return error;
 }
 
 /*
---
0.99.8.GIT


--- NEW FILE 0257-SUNRPC-fix-bug-in-patch-portmapper-doesn-t-need-a-reserved-port.txt ---
Subject: [PATCH] SUNRPC: fix bug in patch "portmapper doesn't need a reserved port"
From: Chuck Lever <cel citi umich edu>
Date: 1127438699 -0400

 The in-kernel portmapper does in fact need a reserved port when registering
 new services, but not when performing bind queries.

 Ensure that we distinguish between the two cases.

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 net/sunrpc/pmap_clnt.c |   13 +++++++------
 1 files changed, 7 insertions(+), 6 deletions(-)

applies-to: f1eae77a5063e3748cd8deba9a13794ae0a9439c
6cd7525a00f3b926e8bd2e402954ed3e09a8e924
diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c
index d8e3f22..a398575 100644
--- a/net/sunrpc/pmap_clnt.c
+++ b/net/sunrpc/pmap_clnt.c
@@ -26,7 +26,7 @@
 #define PMAP_GETPORT		3
 
 static struct rpc_procinfo	pmap_procedures[];
-static struct rpc_clnt *	pmap_create(char *, struct sockaddr_in *, int);
+static struct rpc_clnt *	pmap_create(char *, struct sockaddr_in *, int, int);
 static void			pmap_getport_done(struct rpc_task *);
 static struct rpc_program	pmap_program;
 static DEFINE_SPINLOCK(pmap_lock);
@@ -65,7 +65,7 @@ rpc_getport(struct rpc_task *task, struc
 	map->pm_binding = 1;
 	spin_unlock(&pmap_lock);
 
-	pmap_clnt = pmap_create(clnt->cl_server, sap, map->pm_prot);
+	pmap_clnt = pmap_create(clnt->cl_server, sap, map->pm_prot, 0);
 	if (IS_ERR(pmap_clnt)) {
 		task->tk_status = PTR_ERR(pmap_clnt);
 		goto bailout;
@@ -112,7 +112,7 @@ rpc_getport_external(struct sockaddr_in 
 			NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
 
 	sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr));
-	pmap_clnt = pmap_create(hostname, sin, prot);
+	pmap_clnt = pmap_create(hostname, sin, prot, 0);
 	if (IS_ERR(pmap_clnt))
 		return PTR_ERR(pmap_clnt);
 
@@ -171,7 +171,7 @@ rpc_register(u32 prog, u32 vers, int pro
 
 	sin.sin_family = AF_INET;
 	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-	pmap_clnt = pmap_create("localhost", &sin, IPPROTO_UDP);
+	pmap_clnt = pmap_create("localhost", &sin, IPPROTO_UDP, 1);
 	if (IS_ERR(pmap_clnt)) {
 		error = PTR_ERR(pmap_clnt);
 		dprintk("RPC: couldn't create pmap client. Error = %d\n", error);
@@ -198,7 +198,7 @@ rpc_register(u32 prog, u32 vers, int pro
 }
 
 static struct rpc_clnt *
-pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto)
+pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto, int privileged)
 {
 	struct rpc_xprt	*xprt;
 	struct rpc_clnt	*clnt;
@@ -208,7 +208,8 @@ pmap_create(char *hostname, struct socka
 	if (IS_ERR(xprt))
 		return (struct rpc_clnt *)xprt;
 	xprt->addr.sin_port = htons(RPC_PMAP_PORT);
-	xprt->resvport = 0;
+	if (!privileged)
+		xprt->resvport = 0;
 
 	/* printk("pmap: create clnt\n"); */
 	clnt = rpc_new_client(xprt, hostname,
---
0.99.8.GIT


--- NEW FILE 0261-netdrvr-gianfar-use-new-phy-layer.txt ---
Subject: [PATCH] [netdrvr gianfar] use new phy layer
From: Andy Fleming <afleming freescale com>
Date: 1127530461 -0400

Signed-off-by: Andy Fleming <afleming freescale com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 drivers/net/Kconfig           |    2 
 drivers/net/Makefile          |    2 
 drivers/net/gianfar.c         |  412 +++++---------------------
 drivers/net/gianfar.h         |   30 +-
 drivers/net/gianfar_ethtool.c |  100 ++++--
 drivers/net/gianfar_mii.c     |  219 ++++++++++++++
 drivers/net/gianfar_mii.h     |   45 +++
 drivers/net/gianfar_phy.c     |  661 -----------------------------------------
 drivers/net/gianfar_phy.h     |  213 -------------
 9 files changed, 433 insertions(+), 1251 deletions(-)
 create mode 100644 drivers/net/gianfar_mii.c
 create mode 100644 drivers/net/gianfar_mii.h
 delete mode 100644 drivers/net/gianfar_phy.c
 delete mode 100644 drivers/net/gianfar_phy.h

applies-to: 4615a3494ce14ed78d592599fd29605425b9c986
bb40dcbb0fcebe1df08ba261483fcc38b307d063
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index ff3fccd..4739a63 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2075,6 +2075,8 @@ config SPIDER_NET
 config GIANFAR
 	tristate "Gianfar Ethernet"
 	depends on 85xx || 83xx
+	select PHYLIB
+	select PHYCONTROL
 	help
 	  This driver supports the Gigabit TSEC on the MPC85xx 
 	  family of chips, and the FEC on the 8540
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index e6acba6..39b17cb 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -13,7 +13,7 @@ obj-$(CONFIG_CHELSIO_T1) += chelsio/
 obj-$(CONFIG_BONDING) += bonding/
 obj-$(CONFIG_GIANFAR) += gianfar_driver.o
 
-gianfar_driver-objs := gianfar.o gianfar_ethtool.o gianfar_phy.o
+gianfar_driver-objs := gianfar.o gianfar_ethtool.o gianfar_mii.o
 
 #
 # link order important here
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 6518334..ae5a2ed 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -29,12 +29,7 @@
  *  define the configuration needed by the board are defined in a
  *  board structure in arch/ppc/platforms (though I do not
  *  discount the possibility that other architectures could one
- *  day be supported.  One assumption the driver currently makes
- *  is that the PHY is configured in such a way to advertise all
- *  capabilities.  This is a sensible default, and on certain
- *  PHYs, changing this default encounters substantial errata
- *  issues.  Future versions may remove this requirement, but for
- *  now, it is best for the firmware to ensure this is the case.
+ *  day be supported.
  *
  *  The Gianfar Ethernet Controller uses a ring of buffer
  *  descriptors.  The beginning is indicated by a register
@@ -47,7 +42,7 @@
  *  corresponding bit in the IMASK register is also set (if
  *  interrupt coalescing is active, then the interrupt may not
  *  happen immediately, but will wait until either a set number
- *  of frames or amount of time have passed.).  In NAPI, the
+ *  of frames or amount of time have passed).  In NAPI, the
  *  interrupt handler will signal there is work to be done, and
  *  exit.  Without NAPI, the packet(s) will be handled
  *  immediately.  Both methods will start at the last known empty
@@ -75,6 +70,7 @@
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
+#include <linux/unistd.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -97,9 +93,11 @@
 #include <linux/version.h>
 #include <linux/dma-mapping.h>
 #include <linux/crc32.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
 
 #include "gianfar.h"
-#include "gianfar_phy.h"
+#include "gianfar_mii.h"
 
 #define TX_TIMEOUT      (1*HZ)
 #define SKB_ALLOC_TIMEOUT 1000000
@@ -113,9 +111,8 @@
 #endif
 
 const char gfar_driver_name[] = "Gianfar Ethernet";
-const char gfar_driver_version[] = "1.1";
+const char gfar_driver_version[] = "1.2";
 
-int startup_gfar(struct net_device *dev);
 static int gfar_enet_open(struct net_device *dev);
 static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void gfar_timeout(struct net_device *dev);
@@ -126,17 +123,13 @@ static int gfar_set_mac_address(struct n
 static int gfar_change_mtu(struct net_device *dev, int new_mtu);
 static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs);
 static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs);
-static irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs);
 static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void gfar_phy_change(void *data);
-static void gfar_phy_timer(unsigned long data);
 static void adjust_link(struct net_device *dev);
 static void init_registers(struct net_device *dev);
 static int init_phy(struct net_device *dev);
 static int gfar_probe(struct device *device);
 static int gfar_remove(struct device *device);
-void free_skb_resources(struct gfar_private *priv);
+static void free_skb_resources(struct gfar_private *priv);
 static void gfar_set_multi(struct net_device *dev);
 static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);
 #ifdef CONFIG_GFAR_NAPI
@@ -144,7 +137,6 @@ static int gfar_poll(struct net_device *
 #endif
 int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
 static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length);
-static void gfar_phy_startup_timer(unsigned long data);
 static void gfar_vlan_rx_register(struct net_device *netdev,
 		                struct vlan_group *grp);
 static void gfar_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
@@ -162,6 +154,9 @@ int gfar_uses_fcb(struct gfar_private *p
 	else
 		return 0;
 }
+
+/* Set up the ethernet device structure, private data,
+ * and anything else we need before we start */
 static int gfar_probe(struct device *device)
 {
 	u32 tempval;
@@ -175,7 +170,7 @@ static int gfar_probe(struct device *dev
 
 	einfo = (struct gianfar_platform_data *) pdev->dev.platform_data;
 
-	if (einfo == NULL) {
+	if (NULL == einfo) {
 		printk(KERN_ERR "gfar %d: Missing additional data!\n",
 		       pdev->id);
 
@@ -185,7 +180,7 @@ static int gfar_probe(struct device *dev
 	/* Create an ethernet device instance */
 	dev = alloc_etherdev(sizeof (*priv));
 
-	if (dev == NULL)
+	if (NULL == dev)
 		return -ENOMEM;
 
 	priv = netdev_priv(dev);
@@ -207,20 +202,11 @@ static int gfar_probe(struct device *dev
 	priv->regs = (struct gfar *)
 		ioremap(r->start, sizeof (struct gfar));
 
-	if (priv->regs == NULL) {
+	if (NULL == priv->regs) {
 		err = -ENOMEM;
 		goto regs_fail;
 	}
 
-	/* Set the PHY base address */
-	priv->phyregs = (struct gfar *)
-	    ioremap(einfo->phy_reg_addr, sizeof (struct gfar));
-
-	if (priv->phyregs == NULL) {
-		err = -ENOMEM;
-		goto phy_regs_fail;
-	}
-
 	spin_lock_init(&priv->lock);
 
 	dev_set_drvdata(device, dev);
@@ -386,12 +372,10 @@ static int gfar_probe(struct device *dev
 	return 0;
 
 register_fail:
-	iounmap((void *) priv->phyregs);
-phy_regs_fail:
 	iounmap((void *) priv->regs);
 regs_fail:
 	free_netdev(dev);
-	return -ENOMEM;
+	return err;
[...1773 lines suppressed...]
- * option) any later version.
- *
- */
-#ifndef __GIANFAR_PHY_H
-#define __GIANFAR_PHY_H
-
-#define MII_end ((u32)-2)
-#define MII_read ((u32)-1)
-
-#define MIIMIND_BUSY            0x00000001
-#define MIIMIND_NOTVALID        0x00000004
-
-#define GFAR_AN_TIMEOUT         2000
-
-/* 1000BT control (Marvell & BCM54xx at least) */
-#define MII_1000BASETCONTROL			0x09
-#define MII_1000BASETCONTROL_FULLDUPLEXCAP	0x0200
-#define MII_1000BASETCONTROL_HALFDUPLEXCAP	0x0100
-
-/* Cicada Extended Control Register 1 */
-#define MII_CIS8201_EXT_CON1           0x17
-#define MII_CIS8201_EXTCON1_INIT       0x0000
-
-/* Cicada Interrupt Mask Register */
-#define MII_CIS8201_IMASK		0x19
-#define MII_CIS8201_IMASK_IEN		0x8000
-#define MII_CIS8201_IMASK_SPEED	0x4000
-#define MII_CIS8201_IMASK_LINK		0x2000
-#define MII_CIS8201_IMASK_DUPLEX	0x1000
-#define MII_CIS8201_IMASK_MASK		0xf000
-
-/* Cicada Interrupt Status Register */
-#define MII_CIS8201_ISTAT		0x1a
-#define MII_CIS8201_ISTAT_STATUS	0x8000
-#define MII_CIS8201_ISTAT_SPEED	0x4000
-#define MII_CIS8201_ISTAT_LINK		0x2000
-#define MII_CIS8201_ISTAT_DUPLEX	0x1000
-
-/* Cicada Auxiliary Control/Status Register */
-#define MII_CIS8201_AUX_CONSTAT        0x1c
-#define MII_CIS8201_AUXCONSTAT_INIT    0x0004
-#define MII_CIS8201_AUXCONSTAT_DUPLEX  0x0020
-#define MII_CIS8201_AUXCONSTAT_SPEED   0x0018
-#define MII_CIS8201_AUXCONSTAT_GBIT    0x0010
-#define MII_CIS8201_AUXCONSTAT_100     0x0008
-                                                                                
-/* 88E1011 PHY Status Register */
-#define MII_M1011_PHY_SPEC_STATUS		0x11
-#define MII_M1011_PHY_SPEC_STATUS_1000		0x8000
-#define MII_M1011_PHY_SPEC_STATUS_100		0x4000
-#define MII_M1011_PHY_SPEC_STATUS_SPD_MASK	0xc000
-#define MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX	0x2000
-#define MII_M1011_PHY_SPEC_STATUS_RESOLVED	0x0800
-#define MII_M1011_PHY_SPEC_STATUS_LINK		0x0400
-
-#define MII_M1011_IEVENT		0x13
-#define MII_M1011_IEVENT_CLEAR		0x0000
-
-#define MII_M1011_IMASK			0x12
-#define MII_M1011_IMASK_INIT		0x6400
-#define MII_M1011_IMASK_CLEAR		0x0000
-
-#define MII_DM9161_SCR		0x10
-#define MII_DM9161_SCR_INIT	0x0610
-
-/* DM9161 Specified Configuration and Status Register */
-#define MII_DM9161_SCSR	0x11
-#define MII_DM9161_SCSR_100F	0x8000
-#define MII_DM9161_SCSR_100H	0x4000
-#define MII_DM9161_SCSR_10F	0x2000
-#define MII_DM9161_SCSR_10H	0x1000
-
-/* DM9161 Interrupt Register */
-#define MII_DM9161_INTR	0x15
-#define MII_DM9161_INTR_PEND		0x8000
-#define MII_DM9161_INTR_DPLX_MASK	0x0800
-#define MII_DM9161_INTR_SPD_MASK	0x0400
-#define MII_DM9161_INTR_LINK_MASK	0x0200
-#define MII_DM9161_INTR_MASK		0x0100
-#define MII_DM9161_INTR_DPLX_CHANGE	0x0010
-#define MII_DM9161_INTR_SPD_CHANGE	0x0008
-#define MII_DM9161_INTR_LINK_CHANGE	0x0004
-#define MII_DM9161_INTR_INIT 		0x0000
-#define MII_DM9161_INTR_STOP	\
-(MII_DM9161_INTR_DPLX_MASK | MII_DM9161_INTR_SPD_MASK \
- | MII_DM9161_INTR_LINK_MASK | MII_DM9161_INTR_MASK)
-
-/* DM9161 10BT Configuration/Status */
-#define MII_DM9161_10BTCSR	0x12
-#define MII_DM9161_10BTCSR_INIT	0x7800
-
-#define MII_BASIC_FEATURES	(SUPPORTED_10baseT_Half | \
-				 SUPPORTED_10baseT_Full | \
-				 SUPPORTED_100baseT_Half | \
-				 SUPPORTED_100baseT_Full | \
-				 SUPPORTED_Autoneg | \
-				 SUPPORTED_TP | \
-				 SUPPORTED_MII)
-
-#define MII_GBIT_FEATURES	(MII_BASIC_FEATURES | \
-				 SUPPORTED_1000baseT_Half | \
-				 SUPPORTED_1000baseT_Full)
-
-#define MII_READ_COMMAND       0x00000001
-
-#define MII_INTERRUPT_DISABLED 0x0
-#define MII_INTERRUPT_ENABLED 0x1
-/* Taken from mii_if_info and sungem_phy.h */
-struct gfar_mii_info {
-	/* Information about the PHY type */
-	/* And management functions */
-	struct phy_info *phyinfo;
-
-	/* forced speed & duplex (no autoneg)
-	 * partner speed & duplex & pause (autoneg)
-	 */
-	int speed;
-	int duplex;
-	int pause;
-
-	/* The most recently read link state */
-	int link;
-
-	/* Enabled Interrupts */
-	u32 interrupts;
-
-	u32 advertising;
-	int autoneg;
-	int mii_id;
-
-	/* private data pointer */
-	/* For use by PHYs to maintain extra state */
-	void *priv;
-
-	/* Provided by host chip */
-	struct net_device *dev;
-
-	/* A lock to ensure that only one thing can read/write
-	 * the MDIO bus at a time */
-	spinlock_t mdio_lock;
-
-	/* Provided by ethernet driver */
-	int (*mdio_read) (struct net_device *dev, int mii_id, int reg);
-	void (*mdio_write) (struct net_device *dev, int mii_id, int reg, int val);
-};
-
-/* struct phy_info: a structure which defines attributes for a PHY
- *
- * id will contain a number which represents the PHY.  During
- * startup, the driver will poll the PHY to find out what its
- * UID--as defined by registers 2 and 3--is.  The 32-bit result
- * gotten from the PHY will be ANDed with phy_id_mask to
- * discard any bits which may change based on revision numbers
- * unimportant to functionality
- *
- * There are 6 commands which take a gfar_mii_info structure.
- * Each PHY must declare config_aneg, and read_status.
- */
-struct phy_info {
-	u32 phy_id;
-	char *name;
-	unsigned int phy_id_mask;
-	u32 features;
-
-	/* Called to initialize the PHY */
-	int (*init)(struct gfar_mii_info *mii_info);
-
-	/* Called to suspend the PHY for power */
-	int (*suspend)(struct gfar_mii_info *mii_info);
-
-	/* Reconfigures autonegotiation (or disables it) */
-	int (*config_aneg)(struct gfar_mii_info *mii_info);
-
-	/* Determines the negotiated speed and duplex */
-	int (*read_status)(struct gfar_mii_info *mii_info);
-
-	/* Clears any pending interrupts */
-	int (*ack_interrupt)(struct gfar_mii_info *mii_info);
-
-	/* Enables or disables interrupts */
-	int (*config_intr)(struct gfar_mii_info *mii_info);
-
-	/* Clears up any memory if needed */
-	void (*close)(struct gfar_mii_info *mii_info);
-};
-
-struct phy_info *get_phy_info(struct gfar_mii_info *mii_info);
-int read_phy_reg(struct net_device *dev, int mii_id, int regnum);
-void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value);
-void mii_clear_phy_interrupt(struct gfar_mii_info *mii_info);
-void mii_configure_phy_interrupt(struct gfar_mii_info *mii_info, u32 interrupts);
-
-struct dm9161_private {
-	struct timer_list timer;
-	int resetdone;
-};
-
-#endif /* GIANFAR_PHY_H */
---
0.99.8.GIT


--- NEW FILE 0262-netdrvr-delete-CONFIG_PHYCONTROL.txt ---
Subject: [PATCH] [netdrvr] delete CONFIG_PHYCONTROL
From: Jeff Garzik <jgarzik pobox com>
Date: 1127530729 -0400

---

 drivers/net/Kconfig          |    1 -
 drivers/net/phy/Kconfig      |    8 --------
 drivers/net/phy/phy.c        |    8 --------
 drivers/net/phy/phy_device.c |    3 ---
 4 files changed, 0 insertions(+), 20 deletions(-)

applies-to: aefeb8db397de215cf1ff1c5ff7a581cee2b2b4b
8cee0cd5bec53b78dd3c43a73b27821a688133e6
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 4739a63..db88981 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2076,7 +2076,6 @@ config GIANFAR
 	tristate "Gianfar Ethernet"
 	depends on 85xx || 83xx
 	select PHYLIB
-	select PHYCONTROL
 	help
 	  This driver supports the Gigabit TSEC on the MPC85xx 
 	  family of chips, and the FEC on the 8540
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 14f4de1..c782a63 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -12,14 +12,6 @@ config PHYLIB
 	  devices.  This option provides infrastructure for
 	  managing PHY devices.
 
-config PHYCONTROL
-	bool "  Support for automatically handling PHY state changes"
-	depends on PHYLIB
-	help
-	  Adds code to perform all the work for keeping PHY link
-	  state (speed/duplex/etc) up-to-date.  Also handles
-	  interrupts.
-
 comment "MII PHY device drivers"
 	depends on PHYLIB
 
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index d9e11f9..9209da9 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -242,10 +242,6 @@ EXPORT_SYMBOL(phy_sanitize_settings);
  *   choose the next best ones from the ones selected, so we don't
  *   care if ethtool tries to give us bad values
  *
- * A note about the PHYCONTROL Layer.  If you turn off
- * CONFIG_PHYCONTROL, you will need to read the PHY status
- * registers after this function completes, and update your
- * controller manually.
  */
 int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd)
 {
@@ -380,7 +376,6 @@ int phy_start_aneg(struct phy_device *ph
 
 	err = phydev->drv->config_aneg(phydev);
 
-#ifdef CONFIG_PHYCONTROL
 	if (err < 0)
 		goto out_unlock;
 
@@ -395,14 +390,12 @@ int phy_start_aneg(struct phy_device *ph
 	}
 
 out_unlock:
-#endif
 	spin_unlock(&phydev->lock);
 	return err;
 }
 EXPORT_SYMBOL(phy_start_aneg);
 
 
-#ifdef CONFIG_PHYCONTROL
 static void phy_change(void *data);
 static void phy_timer(unsigned long data);
 
@@ -868,4 +861,3 @@ static void phy_timer(unsigned long data
 	mod_timer(&phydev->phy_timer, jiffies + PHY_STATE_TIME * HZ);
 }
 
-#endif /* CONFIG_PHYCONTROL */
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 33f7bdb..6da1aa0 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -101,7 +101,6 @@ struct phy_device * get_phy_device(struc
 	return dev;
 }
 
-#ifdef CONFIG_PHYCONTROL
 /* phy_prepare_link:
  *
  * description: Tells the PHY infrastructure to handle the
@@ -160,8 +159,6 @@ void phy_disconnect(struct phy_device *p
 }
 EXPORT_SYMBOL(phy_disconnect);
 
-#endif /* CONFIG_PHYCONTROL */
-
 /* phy_attach:
  *
  *   description: Called by drivers to attach to a particular PHY
---
0.99.8.GIT


Index: 0263-hostap-Fix-pci_driver-name-for-hostap_plx-and-hostap_pci.txt
===================================================================
RCS file: 0263-hostap-Fix-pci_driver-name-for-hostap_plx-and-hostap_pci.txt
diff -N 0263-hostap-Fix-pci_driver-name-for-hostap_plx-and-hostap_pci.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0263-hostap-Fix-pci_driver-name-for-hostap_plx-and-hostap_pci.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,53 @@
+Subject: [PATCH] hostap: Fix pci_driver name for hostap_plx and hostap_pci
+From: Pavel Roskin <proski gnu org>
+Date: 1127537938 -0700
+
+hostap_pci and hostap_plx drivers still use PCI driver names
+"prism2_pci" and "prism2_plx" respectively.  This is unfriendly to
+linux-wlan-ng, which uses the same names.  So, if e.g. hostap_pci and
+prism2_pci are loaded, they will "share" /sys/bus/pci/drivers/prism2_plx
+directory.
+
+Change PCI driver names of hostap_pci and hostap_plx to be equal to
+their module names.
+
+Signed-off-by: Pavel Roskin <proski gnu org>
+Signed-off-by: Jouni Malinen <jkmaline cc hut fi>
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/hostap/hostap_pci.c |    2 +-
+ drivers/net/wireless/hostap/hostap_plx.c |    2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+applies-to: 067920155bf3cf6896e88d1cff8c170d32768922
+7a716536c602be6050b4f3ece30f1fc3b64362b0
+diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
+index 025f8cd..b9254f7 100644
+--- a/drivers/net/wireless/hostap/hostap_pci.c
++++ b/drivers/net/wireless/hostap/hostap_pci.c
+@@ -441,7 +441,7 @@ static int prism2_pci_resume(struct pci_
+ MODULE_DEVICE_TABLE(pci, prism2_pci_id_table);
+ 
+ static struct pci_driver prism2_pci_drv_id = {
+-	.name		= "prism2_pci",
++	.name		= "hostap_pci",
+ 	.id_table	= prism2_pci_id_table,
+ 	.probe		= prism2_pci_probe,
+ 	.remove		= prism2_pci_remove,
+diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c
+index 474ef83..1abebdf 100644
+--- a/drivers/net/wireless/hostap/hostap_plx.c
++++ b/drivers/net/wireless/hostap/hostap_plx.c
+@@ -616,7 +616,7 @@ static void prism2_plx_remove(struct pci
+ MODULE_DEVICE_TABLE(pci, prism2_plx_id_table);
+ 
+ static struct pci_driver prism2_plx_drv_id = {
+-	.name		= "prism2_plx",
++	.name		= "hostap_plx",
+ 	.id_table	= prism2_plx_id_table,
+ 	.probe		= prism2_plx_probe,
+ 	.remove		= prism2_plx_remove,
+---
+0.99.8.GIT


Index: 0264-hostap-Add-support-for-WE-19.txt
===================================================================
RCS file: 0264-hostap-Add-support-for-WE-19.txt
diff -N 0264-hostap-Add-support-for-WE-19.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0264-hostap-Add-support-for-WE-19.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,101 @@
+Subject: [PATCH] hostap: Add support for WE-19
+From: Jean Tourrilhes <jt hpl hp com>
+Date: 1127537939 -0700
+
+This patch adds support for WE-19 to the HostAP driver. One of
+the major change is the use of an explicit flag to tell if iwstat is
+in dBm or not.
+
+Signed-off-by: Jouni Malinen <jkmaline cc hut fi>
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/hostap/hostap_80211_rx.c |    3 ++-
+ drivers/net/wireless/hostap/hostap_ap.c       |    6 +++---
+ drivers/net/wireless/hostap/hostap_ioctl.c    |    9 +++++++--
+ 3 files changed, 12 insertions(+), 6 deletions(-)
+
+applies-to: 58ed691a144e75b81b712ccdf5daccebbe58693a
+c28df16ed70d1b6cefd12135e3c68bfccd1bb635
+diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c
+index 42e61c6..ffac508 100644
+--- a/drivers/net/wireless/hostap/hostap_80211_rx.c
++++ b/drivers/net/wireless/hostap/hostap_80211_rx.c
+@@ -737,7 +737,8 @@ void hostap_80211_rx(struct net_device *
+ 		struct iw_quality wstats;
+ 		wstats.level = rx_stats->signal;
+ 		wstats.noise = rx_stats->noise;
+-		wstats.updated = 6;	/* No qual value */
++		wstats.updated = IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_UPDATED
++			| IW_QUAL_QUAL_INVALID | IW_QUAL_DBM;
+ 		/* Update spy records */
+ 		wireless_spy_update(dev, hdr->addr2, &wstats);
+ 	}
+diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
+index 087d926..9da94ab 100644
+--- a/drivers/net/wireless/hostap/hostap_ap.c
++++ b/drivers/net/wireless/hostap/hostap_ap.c
+@@ -2349,7 +2349,7 @@ static int prism2_ap_get_sta_qual(local_
+ 		qual[count].noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence);
+ 		qual[count].updated = sta->last_rx_updated;
+ 
+-		sta->last_rx_updated = 0;
++		sta->last_rx_updated = IW_QUAL_DBM;
+ 
+ 		count++;
+ 		if (count >= buf_size)
+@@ -2467,7 +2467,7 @@ static int prism2_ap_translate_scan(stru
+ 		}
+ #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+ 
+-		sta->last_rx_updated = 0;
++		sta->last_rx_updated = IW_QUAL_DBM;
+ 
+ 		/* To be continued, we should make good use of IWEVCUSTOM */
+ 	}
+@@ -3174,7 +3174,7 @@ int hostap_update_rx_stats(struct ap_dat
+ 		sta->last_rx_silence = rx_stats->noise;
+ 		sta->last_rx_signal = rx_stats->signal;
+ 		sta->last_rx_rate = rx_stats->rate;
+-		sta->last_rx_updated = 7;
++		sta->last_rx_updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+ 		if (rx_stats->rate == 10)
+ 			sta->rx_count[0]++;
+ 		else if (rx_stats->rate == 20)
+diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
+index e720369..dd98172 100644
+--- a/drivers/net/wireless/hostap/hostap_ioctl.c
++++ b/drivers/net/wireless/hostap/hostap_ioctl.c
+@@ -50,7 +50,8 @@ static struct iw_statistics *hostap_get_
+ #endif /* in_atomic */
+ 
+ 		if (update && prism2_update_comms_qual(dev) == 0)
+-			wstats->qual.updated = 7;
++			wstats->qual.updated = IW_QUAL_ALL_UPDATED |
++				IW_QUAL_DBM;
+ 
+ 		wstats->qual.qual = local->comms_qual;
+ 		wstats->qual.level = local->avg_signal;
+@@ -59,7 +60,7 @@ static struct iw_statistics *hostap_get_
+ 		wstats->qual.qual = 0;
+ 		wstats->qual.level = 0;
+ 		wstats->qual.noise = 0;
+-		wstats->qual.updated = 0;
++		wstats->qual.updated = IW_QUAL_ALL_INVALID;
+ 	}
+ 
+ 	return wstats;
+@@ -1894,6 +1895,10 @@ static char * __prism2_translate_scan(lo
+ 			iwe.u.qual.noise =
+ 				HFA384X_LEVEL_TO_dBm(le16_to_cpu(scan->anl));
+ 		}
++		iwe.u.qual.updated = IW_QUAL_LEVEL_UPDATED
++			| IW_QUAL_NOISE_UPDATED
++			| IW_QUAL_QUAL_INVALID
++			| IW_QUAL_DBM;
+ 		iwe.len = IW_EV_QUAL_LEN;
+ 		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+ 						  IW_EV_QUAL_LEN);
+---
+0.99.8.GIT


Index: 0265-hostap-Use-GFP_ATOMIC-to-get-rid-of-weird-might_sleep-issue.txt
===================================================================
RCS file: 0265-hostap-Use-GFP_ATOMIC-to-get-rid-of-weird-might_sleep-issue.txt
diff -N 0265-hostap-Use-GFP_ATOMIC-to-get-rid-of-weird-might_sleep-issue.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0265-hostap-Use-GFP_ATOMIC-to-get-rid-of-weird-might_sleep-issue.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,29 @@
+Subject: [PATCH] hostap: Use GFP_ATOMIC to get rid of weird might_sleep issue
+From: Jean Tourrilhes <jt hpl hp com>
+Date: 1127537940 -0700
+
+	This is the trace I got :
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/hostap/hostap_ioctl.c |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+applies-to: d1161f1c5523e9720f9bc58adf3b7495a5b1ac62
+a9d12b9a4afcfa2cb6f6e76beb4f185a9177c98e
+diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
+index dd98172..1764563 100644
+--- a/drivers/net/wireless/hostap/hostap_ioctl.c
++++ b/drivers/net/wireless/hostap/hostap_ioctl.c
+@@ -1935,7 +1935,7 @@ static char * __prism2_translate_scan(lo
+ 	}
+ 
+ 	/* TODO: add BeaconInt,resp_rate,atim into BSS table */
+-	buf = kmalloc(MAX_WPA_IE_LEN * 2 + 30, GFP_KERNEL);
++	buf = kmalloc(MAX_WPA_IE_LEN * 2 + 30, GFP_ATOMIC);
+ 	if (buf && scan) {
+ 		memset(&iwe, 0, sizeof(iwe));
+ 		iwe.cmd = IWEVCUSTOM;
+---
+0.99.8.GIT


Index: 0266-hostap-Remove-iwe_stream_add_event-kludge.txt
===================================================================
RCS file: 0266-hostap-Remove-iwe_stream_add_event-kludge.txt
diff -N 0266-hostap-Remove-iwe_stream_add_event-kludge.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0266-hostap-Remove-iwe_stream_add_event-kludge.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,78 @@
+Subject: [PATCH] hostap: Remove iwe_stream_add_event kludge
+From: Jean Tourrilhes <jt hpl hp com>
+Date: 1127537941 -0700
+
+Now that we are compiling with -fno-strict-aliasing (this is the
+kernel default), we can drop the following kludge for
+iwe_stream_add_event().
+
+Signed-off-by: Jouni Malinen <jkmaline cc hut fi>
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/hostap/hostap_ioctl.c |   12 ------------
+ 1 files changed, 0 insertions(+), 12 deletions(-)
+
+applies-to: ec30834a9f39a737d2f9d01d5c5b561015265ad1
+596ff2e7c8db39c700e277f0bc267244be253f5b
+diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
+index 1764563..53f5246 100644
+--- a/drivers/net/wireless/hostap/hostap_ioctl.c
++++ b/drivers/net/wireless/hostap/hostap_ioctl.c
+@@ -1828,13 +1828,6 @@ static char * __prism2_translate_scan(lo
+ 	iwe.cmd = SIOCGIWAP;
+ 	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+ 	memcpy(iwe.u.ap_addr.sa_data, bssid, ETH_ALEN);
+-	/* FIX:
+-	 * I do not know how this is possible, but iwe_stream_add_event
+-	 * seems to re-order memcpy execution so that len is set only
+-	 * after copying.. Pre-setting len here "fixes" this, but real
+-	 * problems should be solved (after which these iwe.len
+-	 * settings could be removed from this function). */
+-	iwe.len = IW_EV_ADDR_LEN;
+ 	current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+ 					  IW_EV_ADDR_LEN);
+ 
+@@ -1844,7 +1837,6 @@ static char * __prism2_translate_scan(lo
+ 	iwe.cmd = SIOCGIWESSID;
+ 	iwe.u.data.length = ssid_len;
+ 	iwe.u.data.flags = 1;
+-	iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
+ 	current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, ssid);
+ 
+ 	memset(&iwe, 0, sizeof(iwe));
+@@ -1860,7 +1852,6 @@ static char * __prism2_translate_scan(lo
+ 			iwe.u.mode = IW_MODE_MASTER;
+ 		else
+ 			iwe.u.mode = IW_MODE_ADHOC;
+-		iwe.len = IW_EV_UINT_LEN;
+ 		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+ 						  IW_EV_UINT_LEN);
+ 	}
+@@ -1878,7 +1869,6 @@ static char * __prism2_translate_scan(lo
+ 	if (chan > 0) {
+ 		iwe.u.freq.m = freq_list[le16_to_cpu(chan - 1)] * 100000;
+ 		iwe.u.freq.e = 1;
+-		iwe.len = IW_EV_FREQ_LEN;
+ 		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+ 						  IW_EV_FREQ_LEN);
+ 	}
+@@ -1899,7 +1889,6 @@ static char * __prism2_translate_scan(lo
+ 			| IW_QUAL_NOISE_UPDATED
+ 			| IW_QUAL_QUAL_INVALID
+ 			| IW_QUAL_DBM;
+-		iwe.len = IW_EV_QUAL_LEN;
+ 		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+ 						  IW_EV_QUAL_LEN);
+ 	}
+@@ -1911,7 +1900,6 @@ static char * __prism2_translate_scan(lo
+ 	else
+ 		iwe.u.data.flags = IW_ENCODE_DISABLED;
+ 	iwe.u.data.length = 0;
+-	iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
+ 	current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, "");
+ 
+ 	/* TODO: add SuppRates into BSS table */
+---
+0.99.8.GIT


Index: 0267-Remove-WIRELESS_EXT-ifdefs-from-several-wireless-drivers.txt
===================================================================
RCS file: 0267-Remove-WIRELESS_EXT-ifdefs-from-several-wireless-drivers.txt
diff -N 0267-Remove-WIRELESS_EXT-ifdefs-from-several-wireless-drivers.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0267-Remove-WIRELESS_EXT-ifdefs-from-several-wireless-drivers.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,715 @@
+Subject: [PATCH] Remove WIRELESS_EXT ifdefs from several wireless drivers.
+From: Jeff Garzik <jgarzik pobox com>
+Date: 1127549152 -0400
+
+---
+
+ drivers/net/wireless/airo.c               |   17 ---
+ drivers/net/wireless/netwave_cs.c         |  185 -----------------------------
+ drivers/net/wireless/prism54/isl_ioctl.c  |   10 --
+ drivers/net/wireless/prism54/islpci_dev.c |    4 -
+ drivers/net/wireless/prism54/islpci_dev.h |    2 
+ drivers/net/wireless/wavelan.c            |    8 -
+ drivers/net/wireless/wavelan.p.h          |    4 -
+ drivers/net/wireless/wavelan_cs.c         |    8 -
+ drivers/net/wireless/wavelan_cs.p.h       |    4 -
+ 9 files changed, 1 insertions(+), 241 deletions(-)
+
+applies-to: 9f0f0897c0ef74f8d44510c0cc868ee0e314cbdd
+e2e965072564e7aad8df963107677a6d22c41767
+diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
+index 06998c2..a619495 100644
+--- a/drivers/net/wireless/airo.c
++++ b/drivers/net/wireless/airo.c
+@@ -1046,7 +1046,6 @@ static WifiCtlHdr wifictlhdr8023 = {
+ 	}
+ };
+ 
+-#ifdef WIRELESS_EXT
+ // Frequency list (map channels to frequencies)
+ static const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
+ 				2447, 2452, 2457, 2462, 2467, 2472, 2484 };
+@@ -1067,7 +1066,6 @@ typedef struct wep_key_t {
+ 
+ /* List of Wireless Handlers (new API) */
+ static const struct iw_handler_def	airo_handler_def;
+-#endif /* WIRELESS_EXT */
+ 
+ static const char version[] = "airo.c 0.6 (Ben Reed & Javier Achirica)";
+ 
+@@ -1110,10 +1108,8 @@ static irqreturn_t airo_interrupt( int i
+ static int airo_thread(void *data);
+ static void timer_func( struct net_device *dev );
+ static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+-#ifdef WIRELESS_EXT
+ static struct iw_statistics *airo_get_wireless_stats (struct net_device *dev);
+ static void airo_read_wireless_stats (struct airo_info *local);
+-#endif /* WIRELESS_EXT */
+ #ifdef CISCO_EXT
+ static int readrids(struct net_device *dev, aironet_ioctl *comp);
+ static int writerids(struct net_device *dev, aironet_ioctl *comp);
+@@ -1187,12 +1183,10 @@ struct airo_info {
+ 		int fid;
+ 	} xmit, xmit11;
+ 	struct net_device *wifidev;
+-#ifdef WIRELESS_EXT
+ 	struct iw_statistics	wstats;		// wireless stats
+ 	unsigned long		scan_timestamp;	/* Time started to scan */
+ 	struct iw_spy_data	spy_data;
+ 	struct iw_public_data	wireless_data;
+-#endif /* WIRELESS_EXT */
+ #ifdef MICSUPPORT
+ 	/* MIC stuff */
+ 	struct crypto_tfm	*tfm;
+@@ -2647,9 +2641,7 @@ static void wifi_setup(struct net_device
+ 	dev->get_stats = &airo_get_stats;
+ 	dev->set_mac_address = &airo_set_mac_address;
+ 	dev->do_ioctl = &airo_ioctl;
+-#ifdef WIRELESS_EXT
+ 	dev->wireless_handlers = &airo_handler_def;
+-#endif /* WIRELESS_EXT */
+ 	dev->change_mtu = &airo_change_mtu;
+ 	dev->open = &airo_open;
+ 	dev->stop = &airo_close;
+@@ -2675,9 +2667,7 @@ static struct net_device *init_wifidev(s
+ 	dev->priv = ethdev->priv;
+ 	dev->irq = ethdev->irq;
+ 	dev->base_addr = ethdev->base_addr;
+-#ifdef WIRELESS_EXT
+ 	dev->wireless_data = ethdev->wireless_data;
+-#endif /* WIRELESS_EXT */
+ 	memcpy(dev->dev_addr, ethdev->dev_addr, dev->addr_len);
+ 	err = register_netdev(dev);
+ 	if (err<0) {
+@@ -2755,11 +2745,9 @@ static struct net_device *_init_airo_car
+ 	dev->set_multicast_list = &airo_set_multicast_list;
+ 	dev->set_mac_address = &airo_set_mac_address;
+ 	dev->do_ioctl = &airo_ioctl;
+-#ifdef WIRELESS_EXT
+ 	dev->wireless_handlers = &airo_handler_def;
+ 	ai->wireless_data.spy_data = &ai->spy_data;
+ 	dev->wireless_data = &ai->wireless_data;
+-#endif /* WIRELESS_EXT */
+ 	dev->change_mtu = &airo_change_mtu;
+ 	dev->open = &airo_open;
+ 	dev->stop = &airo_close;
+@@ -5598,7 +5586,6 @@ static void __exit airo_cleanup_module( 
+ 	remove_proc_entry("aironet", proc_root_driver);
+ }
+ 
+-#ifdef WIRELESS_EXT
+ /*
+  * Initial Wireless Extension code for Aironet driver by :
+  *	Jean Tourrilhes <jt hpl hp com> - HPL - 17 November 00
+@@ -7107,8 +7094,6 @@ static const struct iw_handler_def	airo_
+ 	.get_wireless_stats = airo_get_wireless_stats,
+ };
+ 
+-#endif /* WIRELESS_EXT */
+-
+ /*
+  * This defines the configuration part of the Wireless Extensions
+  * Note : irq and spinlock protection will occur in the subroutines
+@@ -7187,7 +7172,6 @@ static int airo_ioctl(struct net_device 
+ 	return rc;
+ }
+ 
+-#ifdef WIRELESS_EXT
+ /*
+  * Get the Wireless stats out of the driver
+  * Note : irq and spinlock protection will occur in the subroutines
+@@ -7260,7 +7244,6 @@ static struct iw_statistics *airo_get_wi
+ 
+ 	return &local->wstats;
+ }
+-#endif /* WIRELESS_EXT */
+ 
+ #ifdef CISCO_EXT
+ /*
+diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
+index ca6c03c..92793b9 100644
+--- a/drivers/net/wireless/netwave_cs.c
++++ b/drivers/net/wireless/netwave_cs.c
+@@ -57,9 +57,7 @@
+ #include <linux/bitops.h>
+ #ifdef CONFIG_NET_RADIO
+ #include <linux/wireless.h>
+-#if WIRELESS_EXT > 12
+ #include <net/iw_handler.h>
+-#endif	/* WIRELESS_EXT > 12 */
+ #endif
+ 
+ #include <pcmcia/cs_types.h>
+@@ -225,10 +223,7 @@ static void update_stats(struct net_devi
+ static struct net_device_stats *netwave_get_stats(struct net_device *dev);
+ 
+ /* Wireless extensions */
+-#ifdef WIRELESS_EXT
+ static struct iw_statistics* netwave_get_wireless_stats(struct net_device *dev);
+-#endif
+-static int netwave_ioctl(struct net_device *, struct ifreq *, int);
+ 
+ static void set_multicast_list(struct net_device *dev);
+ 
+@@ -260,26 +255,7 @@ static dev_link_t *dev_list;
+    because they generally can't be allocated dynamically.
+ */
+ 
+-#if WIRELESS_EXT <= 12
+-/* Wireless extensions backward compatibility */
+-
+-/* Part of iw_handler prototype we need */
+-struct iw_request_info
+-{
+-	__u16		cmd;		/* Wireless Extension command */
+-	__u16		flags;		/* More to come ;-) */
+-};
+-
+-/* Wireless Extension Backward compatibility - Jean II
+- * If the new wireless device private ioctl range is not defined,
+- * default to standard device private ioctl range */
+-#ifndef SIOCIWFIRSTPRIV
+-#define SIOCIWFIRSTPRIV	SIOCDEVPRIVATE
+-#endif /* SIOCIWFIRSTPRIV */
+-
+-#else	/* WIRELESS_EXT <= 12 */
+ static const struct iw_handler_def	netwave_handler_def;
+-#endif	/* WIRELESS_EXT <= 12 */
+ 
+ #define SIOCGIPSNAP	SIOCIWFIRSTPRIV	+ 1	/* Site Survey Snapshot */
+ 
+@@ -319,9 +295,7 @@ typedef struct netwave_private {
+     struct timer_list      watchdog;	/* To avoid blocking state */
+     struct site_survey     nss;
+     struct net_device_stats stats;
+-#ifdef WIRELESS_EXT
+     struct iw_statistics   iw_stats;    /* Wireless stats */
+-#endif
+ } netwave_private;
+ 
+ #ifdef NETWAVE_STATS
+@@ -353,7 +327,6 @@ static inline void wait_WOC(unsigned int
+     while ((inb(iobase + NETWAVE_REG_ASR) & 0x8) != 0x8) ; 
+ }
+ 
+-#ifdef WIRELESS_EXT
+ static void netwave_snapshot(netwave_private *priv, u_char __iomem *ramBase, 
+ 			     kio_addr_t iobase) {
+     u_short resultBuffer;
+@@ -376,9 +349,7 @@ static void netwave_snapshot(netwave_pri
+ 		      sizeof(struct site_survey)); 
+     } 
+ }
+-#endif
+ 
+-#ifdef WIRELESS_EXT
+ /*
+  * Function netwave_get_wireless_stats (dev)
+  *
+@@ -411,7 +382,6 @@ static struct iw_statistics *netwave_get
+     
+     return &priv->iw_stats;
+ }
+-#endif
+ 
+ /*
+  * Function netwave_attach (void)
+@@ -471,13 +441,7 @@ static dev_link_t *netwave_attach(void)
+     dev->get_stats  = &netwave_get_stats;
+     dev->set_multicast_list = &set_multicast_list;
+     /* wireless extensions */
+-#if WIRELESS_EXT <= 16
+-    dev->get_wireless_stats = &netwave_get_wireless_stats;
+-#endif /* WIRELESS_EXT <= 16 */
+-#if WIRELESS_EXT > 12
+     dev->wireless_handlers = (struct iw_handler_def *)&netwave_handler_def;
+-#endif /* WIRELESS_EXT > 12 */
+-    dev->do_ioctl = &netwave_ioctl;
+ 
+     dev->tx_timeout = &netwave_watchdog;
+     dev->watchdog_timeo = TX_TIMEOUT;
+@@ -576,13 +540,8 @@ static int netwave_set_nwid(struct net_d
+ 	/* Disable interrupts & save flags */
+ 	spin_lock_irqsave(&priv->spinlock, flags);
+ 
+-#if WIRELESS_EXT > 8
+ 	if(!wrqu->nwid.disabled) {
+ 	    domain = wrqu->nwid.value;
+-#else	/* WIRELESS_EXT > 8 */
+-	if(wrqu->nwid.on) {
+-	    domain = wrqu->nwid.nwid;
+-#endif	/* WIRELESS_EXT > 8 */
+ 	    printk( KERN_DEBUG "Setting domain to 0x%x%02x\n", 
+ 		    (domain >> 8) & 0x01, domain & 0xff);
+ 	    wait_WOC(iobase);
+@@ -606,15 +565,9 @@ static int netwave_get_nwid(struct net_d
+ 			    union iwreq_data *wrqu,
+ 			    char *extra)
+ {
+-#if WIRELESS_EXT > 8
+ 	wrqu->nwid.value = domain;
+ 	wrqu->nwid.disabled = 0;
+ 	wrqu->nwid.fixed = 1;
+-#else	/* WIRELESS_EXT > 8 */
+-	wrqu->nwid.nwid = domain;
+-	wrqu->nwid.on = 1;
+-#endif	/* WIRELESS_EXT > 8 */
+-
+ 	return 0;
+ }
+ 
+@@ -657,17 +610,11 @@ static int netwave_get_scramble(struct n
+ {
+ 	key[1] = scramble_key & 0xff;
+ 	key[0] = (scramble_key>>8) & 0xff;
+-#if WIRELESS_EXT > 8
+ 	wrqu->encoding.flags = IW_ENCODE_ENABLED;
+ 	wrqu->encoding.length = 2;
+-#else /* WIRELESS_EXT > 8 */
+-	wrqu->encoding.method = 1;
+-#endif	/* WIRELESS_EXT > 8 */
+-
+ 	return 0;
+ }
+ 
+-#if WIRELESS_EXT > 8
+ /*
+  * Wireless Handler : get mode
+  */
+@@ -683,7 +630,6 @@ static int netwave_get_mode(struct net_d
+ 
+ 	return 0;
+ }
+-#endif	/* WIRELESS_EXT > 8 */
+ 
+ /*
+  * Wireless Handler : get range info
+@@ -702,11 +648,9 @@ static int netwave_get_range(struct net_
+ 	/* Set all the info we don't care or don't know about to zero */
+ 	memset(range, 0, sizeof(struct iw_range));
+ 
+-#if WIRELESS_EXT > 10
+ 	/* Set the Wireless Extension versions */
+ 	range->we_version_compiled = WIRELESS_EXT;
+ 	range->we_version_source = 9;	/* Nothing for us in v10 and v11 */
+-#endif /* WIRELESS_EXT > 10 */
+ 		   
+ 	/* Set information in the range struct */
+ 	range->throughput = 450 * 1000;	/* don't argue on this ! */
+@@ -720,16 +664,12 @@ static int netwave_get_range(struct net_
+ 	range->max_qual.level = 255;
+ 	range->max_qual.noise = 0;
+ 		   
+-#if WIRELESS_EXT > 7
+ 	range->num_bitrates = 1;
+ 	range->bitrate[0] = 1000000;	/* 1 Mb/s */
+-#endif /* WIRELESS_EXT > 7 */
+ 
+-#if WIRELESS_EXT > 8
+ 	range->encoding_size[0] = 2;		/* 16 bits scrambling */
+ 	range->num_encoding_sizes = 1;
+ 	range->max_encoding_tokens = 1;	/* Only one key possible */
+-#endif /* WIRELESS_EXT > 8 */
+ 
+ 	return ret;
+ }
+@@ -775,8 +715,6 @@ static const struct iw_priv_args netwave
+     "getsitesurvey" },
+ };
+ 
+-#if WIRELESS_EXT > 12
+-
+ static const iw_handler		netwave_handler[] =
+ {
+ 	NULL,				/* SIOCSIWNAME */
+@@ -839,131 +777,8 @@ static const struct iw_handler_def	netwa
+ 	.standard	= (iw_handler *) netwave_handler,
+ 	.private	= (iw_handler *) netwave_private_handler,
+ 	.private_args	= (struct iw_priv_args *) netwave_private_args,
+-#if WIRELESS_EXT > 16
+ 	.get_wireless_stats = netwave_get_wireless_stats,
+-#endif /* WIRELESS_EXT > 16 */
+ };
+-#endif /* WIRELESS_EXT > 12 */
+-
+-/*
+- * Function netwave_ioctl (dev, rq, cmd)
+- *
+- *     Perform ioctl : config & info stuff
+- *     This is the stuff that are treated the wireless extensions (iwconfig)
+- *
+- */
+-static int netwave_ioctl(struct net_device *dev, /* ioctl device */
+-			 struct ifreq *rq,	 /* Data passed */
+-			 int	cmd)	     /* Ioctl number */
+-{
+-    int			ret = 0;
+-#ifdef WIRELESS_EXT
+-#if WIRELESS_EXT <= 12
+-    struct iwreq *wrq = (struct iwreq *) rq;
+-#endif
+-#endif
+-	
+-    DEBUG(0, "%s: ->netwave_ioctl(cmd=0x%X)\n", dev->name, cmd);
+-	
+-    /* Look what is the request */
+-    switch(cmd) {
+-	/* --------------- WIRELESS EXTENSIONS --------------- */
+-#ifdef WIRELESS_EXT
+-#if WIRELESS_EXT <= 12
+-    case SIOCGIWNAME:
+-	netwave_get_name(dev, NULL, &(wrq->u), NULL);
+-	break;
+-    case SIOCSIWNWID:
+-	ret = netwave_set_nwid(dev, NULL, &(wrq->u), NULL);
+-	break;
+-    case SIOCGIWNWID:
+-	ret = netwave_get_nwid(dev, NULL, &(wrq->u), NULL);
+-	break;
+-#if WIRELESS_EXT > 8	/* Note : The API did change... */
+-    case SIOCGIWENCODE:
+-	/* Get scramble key */
+-	if(wrq->u.encoding.pointer != (caddr_t) 0)
+-	  {
+-	    char	key[2];
+-	    ret = netwave_get_scramble(dev, NULL, &(wrq->u), key);
+-	    if(copy_to_user(wrq->u.encoding.pointer, key, 2))
+-	      ret = -EFAULT;
+-	  }
+-	break;
+-    case SIOCSIWENCODE:
+-	/* Set  scramble key */
+-	if(wrq->u.encoding.pointer != (caddr_t) 0)
+-	  {
+-	    char	key[2];
+-	    if(copy_from_user(key, wrq->u.encoding.pointer, 2))
+-	      {
+-		ret = -EFAULT;
+-		break;
+-	      }
+-	    ret = netwave_set_scramble(dev, NULL, &(wrq->u), key);
+-	  }
+-	break;
+-    case SIOCGIWMODE:
+-	/* Mode of operation */
+-	ret = netwave_get_mode(dev, NULL, &(wrq->u), NULL);
+-	break;
+-#else /* WIRELESS_EXT > 8 */
+-    case SIOCGIWENCODE:
+-	/* Get scramble key */
+-	ret = netwave_get_scramble(dev, NULL, &(wrq->u),
+-				   (char *) &wrq->u.encoding.code);
+-	break;
+-    case SIOCSIWENCODE:
+-	/* Set  scramble key */
+-	ret = netwave_set_scramble(dev, NULL, &(wrq->u),
+-				   (char *) &wrq->u.encoding.code);
+-	break;
+-#endif /* WIRELESS_EXT > 8 */
+-   case SIOCGIWRANGE:
+-       /* Basic checking... */
+-       if(wrq->u.data.pointer != (caddr_t) 0) {
+-           struct iw_range range;
+-	   ret = netwave_get_range(dev, NULL, &(wrq->u), (char *) &range);
+-	   if (copy_to_user(wrq->u.data.pointer, &range,
+-			    sizeof(struct iw_range)))
+-	       ret = -EFAULT;
+-       }
+-       break;
+-    case SIOCGIWPRIV:
+-	/* Basic checking... */
+-	if(wrq->u.data.pointer != (caddr_t) 0) {
+-	    /* Set the number of ioctl available */
+-	    wrq->u.data.length = sizeof(netwave_private_args) / sizeof(netwave_private_args[0]);
+-			
+-	    /* Copy structure to the user buffer */
+-	    if(copy_to_user(wrq->u.data.pointer,
+-			    (u_char *) netwave_private_args,
+-			    sizeof(netwave_private_args)))
+-	      ret = -EFAULT;
+-	} 
+-	break;
+-    case SIOCGIPSNAP:
+-	if(wrq->u.data.pointer != (caddr_t) 0) {
+-	    char buffer[sizeof( struct site_survey)];
+-	    ret = netwave_get_snap(dev, NULL, &(wrq->u), buffer);
+-	    /* Copy structure to the user buffer */
+-	    if(copy_to_user(wrq->u.data.pointer, 
+-			    buffer,
+-			    sizeof( struct site_survey)))
+-	      {
+-		printk(KERN_DEBUG "Bad buffer!\n");
+-		break;
+-	      }
+-	}
+-	break;
+-#endif /* WIRELESS_EXT <= 12 */
+-#endif /* WIRELESS_EXT */
+-    default:
+-	ret = -EOPNOTSUPP;
+-    }
+-	
+-    return ret;
+-}
+ 
+ /*
+  * Function netwave_pcmcia_config (link)
+diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
+index 9a8790e..5c1a1ad 100644
+--- a/drivers/net/wireless/prism54/isl_ioctl.c
++++ b/drivers/net/wireless/prism54/isl_ioctl.c
+@@ -462,14 +462,12 @@ prism54_get_range(struct net_device *nde
+ 	/* txpower is supported in dBm's */
+ 	range->txpower_capa = IW_TXPOW_DBM;
+ 
+-#if WIRELESS_EXT > 16
+ 	/* Event capability (kernel + driver) */
+ 	range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
+ 	IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) |
+ 	IW_EVENT_CAPA_MASK(SIOCGIWAP));
+ 	range->event_capa[1] = IW_EVENT_CAPA_K_1;
+ 	range->event_capa[4] = IW_EVENT_CAPA_MASK(IWEVCUSTOM);
+-#endif /* WIRELESS_EXT > 16 */
+ 
+ 	if (islpci_get_state(priv) < PRV_STATE_INIT)
+ 		return 0;
+@@ -693,14 +691,13 @@ prism54_get_scan(struct net_device *ndev
+ 						   extra + dwrq->length,
+ 						   &(bsslist->bsslist[i]),
+ 						   noise);
+-#if WIRELESS_EXT > 16
++
+ 		/* Check if there is space for one more entry */
+ 		if((extra + dwrq->length - current_ev) <= IW_EV_ADDR_LEN) {
+ 			/* Ask user space to try again with a bigger buffer */
+ 			rvalue = -E2BIG;
+ 			break;
+ 		}
+-#endif /* WIRELESS_EXT > 16 */
+ 	}
+ 
+ 	kfree(bsslist);
+@@ -2727,12 +2724,7 @@ const struct iw_handler_def prism54_hand
+ 	.standard = (iw_handler *) prism54_handler,
+ 	.private = (iw_handler *) prism54_private_handler,
+ 	.private_args = (struct iw_priv_args *) prism54_private_args,
+-#if WIRELESS_EXT > 16
+ 	.get_wireless_stats = prism54_get_wireless_stats,
+-#endif /* WIRELESS_EXT > 16 */
+-#if WIRELESS_EXT == 16
+-	.spy_offset = offsetof(islpci_private, spy_data),
+-#endif /* WIRELESS_EXT == 16 */
+ };
+ 
+ /* For wpa_supplicant */
+diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c
+index 10cce51..6c9584a 100644
+--- a/drivers/net/wireless/prism54/islpci_dev.c
++++ b/drivers/net/wireless/prism54/islpci_dev.c
+@@ -837,13 +837,9 @@ islpci_setup(struct pci_dev *pdev)
+ 	priv->ndev->type = (priv->iw_mode == IW_MODE_MONITOR) ?
+ 		priv->monitor_type : ARPHRD_ETHER;
+ 
+-#if WIRELESS_EXT > 16
+ 	/* Add pointers to enable iwspy support. */
+ 	priv->wireless_data.spy_data = &priv->spy_data;
+ 	ndev->wireless_data = &priv->wireless_data;
+-#else  /* WIRELESS_EXT > 16 */
+-	ndev->get_wireless_stats = &prism54_get_wireless_stats;
+-#endif /* WIRELESS_EXT > 16 */
+ 
+ 	/* save the start and end address of the PCI memory area */
+ 	ndev->mem_start = (unsigned long) priv->device_base;
+diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h
+index 32a1019..efbed43 100644
+--- a/drivers/net/wireless/prism54/islpci_dev.h
++++ b/drivers/net/wireless/prism54/islpci_dev.h
+@@ -100,9 +100,7 @@ typedef struct {
+ 
+ 	struct iw_spy_data spy_data; /* iwspy support */
+ 
+-#if WIRELESS_EXT > 16
+ 	struct iw_public_data wireless_data;
+-#endif /* WIRELESS_EXT > 16 */
+ 
+ 	int monitor_type; /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_PRISM */
+ 
+diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c
+index 7a5e20a..b0d8b5b 100644
+--- a/drivers/net/wireless/wavelan.c
++++ b/drivers/net/wireless/wavelan.c
+@@ -430,7 +430,6 @@ static void fee_read(unsigned long ioadd
+ 	}
+ }
+ 
+-#ifdef WIRELESS_EXT		/* if the wireless extension exists in the kernel */
+ 
+ /*------------------------------------------------------------------*/
+ /*
+@@ -514,7 +513,6 @@ static void fee_write(unsigned long ioad
+ 	fee_wait(ioaddr, 10, 100);
+ #endif				/* EEPROM_IS_PROTECTED */
+ }
+-#endif				/* WIRELESS_EXT */
+ 
+ /************************ I82586 SUBROUTINES *************************/
+ /*
+@@ -973,11 +971,9 @@ static void wv_mmc_show(struct net_devic
+ 	mmc_read(ioaddr, 0, (u8 *) & m, sizeof(m));
+ 	mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0);
+ 
+-#ifdef WIRELESS_EXT		/* if wireless extension exists in the kernel */
+ 	/* Don't forget to update statistics */
+ 	lp->wstats.discard.nwid +=
+ 	    (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l;
+-#endif				/* WIRELESS_EXT */
+ 
+ 	printk(KERN_DEBUG "##### WaveLAN modem status registers: #####\n");
+ #ifdef DEBUG_SHOW_UNUSED
+@@ -1499,7 +1495,6 @@ static int wavelan_set_mac_address(struc
+ }
+ #endif				/* SET_MAC_ADDRESS */
+ 
+-#ifdef WIRELESS_EXT		/* if wireless extensions exist in the kernel */
+ 
+ /*------------------------------------------------------------------*/
+ /*
+@@ -2473,7 +2468,6 @@ static iw_stats *wavelan_get_wireless_st
+ #endif
+ 	return &lp->wstats;
+ }
+-#endif				/* WIRELESS_EXT */
+ 
+ /************************* PACKET RECEPTION *************************/
+ /*
+@@ -4194,11 +4188,9 @@ static int __init wavelan_config(struct 
+ 	dev->set_mac_address = &wavelan_set_mac_address;
+ #endif				/* SET_MAC_ADDRESS */
+ 
+-#ifdef WIRELESS_EXT		/* if wireless extension exists in the kernel */
+ 	dev->wireless_handlers = &wavelan_handler_def;
+ 	lp->wireless_data.spy_data = &lp->spy_data;
+ 	dev->wireless_data = &lp->wireless_data;
+-#endif
+ 
+ 	dev->mtu = WAVELAN_MTU;
+ 
+diff --git a/drivers/net/wireless/wavelan.p.h b/drivers/net/wireless/wavelan.p.h
+index 509ff22..166e28b 100644
+--- a/drivers/net/wireless/wavelan.p.h
++++ b/drivers/net/wireless/wavelan.p.h
+@@ -409,11 +409,9 @@
+ #define MULTICAST_AVOID		/* Avoid extra multicast (I'm sceptical). */
+ #undef SET_MAC_ADDRESS		/* Experimental */
+ 
+-#ifdef WIRELESS_EXT	/* If wireless extensions exist in the kernel */
+ /* Warning:  this stuff will slow down the driver. */
+ #define WIRELESS_SPY		/* Enable spying addresses. */
+ #undef HISTOGRAM		/* Enable histogram of signal level. */
+-#endif
+ 
+ /****************************** DEBUG ******************************/
+ 
+@@ -506,12 +504,10 @@ struct net_local
+   u_short	tx_first_free;
+   u_short	tx_first_in_use;
+ 
+-#ifdef WIRELESS_EXT
+   iw_stats	wstats;		/* Wireless-specific statistics */
+ 
+   struct iw_spy_data	spy_data;
+   struct iw_public_data	wireless_data;
+-#endif
+ 
+ #ifdef HISTOGRAM
+   int		his_number;		/* number of intervals */
+diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
+index 183c473..4b3c98f 100644
+--- a/drivers/net/wireless/wavelan_cs.c
++++ b/drivers/net/wireless/wavelan_cs.c
+@@ -415,7 +415,6 @@ fee_read(u_long		base,	/* i/o port of th
+     }
+ }
+ 
+-#ifdef WIRELESS_EXT	/* If wireless extension exist in the kernel */
+ 
+ /*------------------------------------------------------------------*/
+ /*
+@@ -500,7 +499,6 @@ fee_write(u_long	base,	/* i/o port of th
+   fee_wait(base, 10, 100);
+ #endif	/* EEPROM_IS_PROTECTED */
+ }
+-#endif	/* WIRELESS_EXT */
+ 
+ /******************* WaveLAN Roaming routines... ********************/
+ 
+@@ -1161,10 +1159,8 @@ wv_mmc_show(struct net_device *	dev)
+   mmc_read(base, 0, (u_char *)&m, sizeof(m));
+   mmc_out(base, mmwoff(0, mmw_freeze), 0);
+ 
+-#ifdef WIRELESS_EXT	/* If wireless extension exist in the kernel */
+   /* Don't forget to update statistics */
+   lp->wstats.discard.nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l;
+-#endif	/* WIRELESS_EXT */
+ 
+   spin_unlock_irqrestore(&lp->spinlock, flags);
+ 
+@@ -1550,7 +1546,6 @@ wavelan_set_mac_address(struct net_devic
+ }
+ #endif	/* SET_MAC_ADDRESS */
+ 
+-#ifdef WIRELESS_EXT	/* If wireless extension exist in the kernel */
+ 
+ /*------------------------------------------------------------------*/
+ /*
+@@ -2793,7 +2788,6 @@ wavelan_get_wireless_stats(struct net_de
+ #endif
+   return &lp->wstats;
+ }
+-#endif	/* WIRELESS_EXT */
+ 
+ /************************* PACKET RECEPTION *************************/
+ /*
+@@ -4679,11 +4673,9 @@ wavelan_attach(void)
+   dev->watchdog_timeo	= WATCHDOG_JIFFIES;
+   SET_ETHTOOL_OPS(dev, &ops);
+ 
+-#ifdef WIRELESS_EXT	/* If wireless extension exist in the kernel */
+   dev->wireless_handlers = &wavelan_handler_def;
+   lp->wireless_data.spy_data = &lp->spy_data;
+   dev->wireless_data = &lp->wireless_data;
+-#endif
+ 
+   /* Other specific data */
+   dev->mtu = WAVELAN_MTU;
+diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h
+index 01d882b..724a715 100644
+--- a/drivers/net/wireless/wavelan_cs.p.h
++++ b/drivers/net/wireless/wavelan_cs.p.h
+@@ -472,11 +472,9 @@
+ #define MULTICAST_AVOID		/* Avoid extra multicast (I'm sceptical) */
+ #undef SET_MAC_ADDRESS		/* Experimental */
+ 
+-#ifdef WIRELESS_EXT	/* If wireless extension exist in the kernel */
+ /* Warning : these stuff will slow down the driver... */
+ #define WIRELESS_SPY		/* Enable spying addresses */
+ #undef HISTOGRAM		/* Enable histogram of sig level... */
+-#endif
+ 
+ /****************************** DEBUG ******************************/
+ 
+@@ -624,12 +622,10 @@ struct net_local
+   int   	rfp;		/* Last DMA machine receive pointer */
+   int		overrunning;	/* Receiver overrun flag */
+ 
+-#ifdef WIRELESS_EXT
+   iw_stats	wstats;		/* Wireless specific stats */
+ 
+   struct iw_spy_data	spy_data;
+   struct iw_public_data	wireless_data;
+-#endif
+ 
+ #ifdef HISTOGRAM
+   int		his_number;		/* Number of intervals */
+---
+0.99.8.GIT


Index: 0268-wireless-airo-remove-needed-dma_addr_t-obfuscation.txt
===================================================================
RCS file: 0268-wireless-airo-remove-needed-dma_addr_t-obfuscation.txt
diff -N 0268-wireless-airo-remove-needed-dma_addr_t-obfuscation.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0268-wireless-airo-remove-needed-dma_addr_t-obfuscation.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,67 @@
+Subject: [PATCH] [wireless airo] remove needed dma_addr_t obfuscation
+From: Jeff Garzik <jgarzik pobox com>
+Date: 1127549344 -0400
+
+Fixes bus address truncation bug for certain configs.
+
+---
+
+ drivers/net/wireless/airo.c |   13 +++++++------
+ 1 files changed, 7 insertions(+), 6 deletions(-)
+
+applies-to: 92667c7ec98f96308f4eefd4ec3c1bdfbb5acd93
+2759c8d536efe3b853867f345627d89fb64c37af
+diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
+index a619495..746456c 100644
+--- a/drivers/net/wireless/airo.c
++++ b/drivers/net/wireless/airo.c
+@@ -2521,7 +2521,8 @@ static int mpi_map_card(struct airo_info
+ 	unsigned long mem_start, mem_len, aux_start, aux_len;
+ 	int rc = -1;
+ 	int i;
+-	unsigned char *busaddroff,*vpackoff;
++	dma_addr_t busaddroff;
++	unsigned char *vpackoff;
+ 	unsigned char __iomem *pciaddroff;
+ 
+ 	mem_start = pci_resource_start(pci, 1);
+@@ -2564,7 +2565,7 @@ static int mpi_map_card(struct airo_info
+ 	/*
+ 	 * Setup descriptor RX, TX, CONFIG
+ 	 */
+-	busaddroff = (unsigned char *)ai->shared_dma;
++	busaddroff = ai->shared_dma;
+ 	pciaddroff = ai->pciaux + AUX_OFFSET;
+ 	vpackoff   = ai->shared;
+ 
+@@ -2573,7 +2574,7 @@ static int mpi_map_card(struct airo_info
+ 		ai->rxfids[i].pending = 0;
+ 		ai->rxfids[i].card_ram_off = pciaddroff;
+ 		ai->rxfids[i].virtual_host_addr = vpackoff;
+-		ai->rxfids[i].rx_desc.host_addr = (dma_addr_t) busaddroff;
++		ai->rxfids[i].rx_desc.host_addr = busaddroff;
+ 		ai->rxfids[i].rx_desc.valid = 1;
+ 		ai->rxfids[i].rx_desc.len = PKTSIZE;
+ 		ai->rxfids[i].rx_desc.rdy = 0;
+@@ -2588,7 +2589,7 @@ static int mpi_map_card(struct airo_info
+ 		ai->txfids[i].card_ram_off = pciaddroff;
+ 		ai->txfids[i].virtual_host_addr = vpackoff;
+ 		ai->txfids[i].tx_desc.valid = 1;
+-		ai->txfids[i].tx_desc.host_addr = (dma_addr_t) busaddroff;
++		ai->txfids[i].tx_desc.host_addr = busaddroff;
+ 		memcpy(ai->txfids[i].virtual_host_addr,
+ 			&wifictlhdr8023, sizeof(wifictlhdr8023));
+ 
+@@ -2601,8 +2602,8 @@ static int mpi_map_card(struct airo_info
+ 	/* Rid descriptor setup */
+ 	ai->config_desc.card_ram_off = pciaddroff;
+ 	ai->config_desc.virtual_host_addr = vpackoff;
+-	ai->config_desc.rid_desc.host_addr = (dma_addr_t) busaddroff;
+-	ai->ridbus = (dma_addr_t)busaddroff;
++	ai->config_desc.rid_desc.host_addr = busaddroff;
++	ai->ridbus = busaddroff;
+ 	ai->config_desc.rid_desc.rid = 0;
+ 	ai->config_desc.rid_desc.len = RIDSIZE;
+ 	ai->config_desc.rid_desc.valid = 1;
+---
+0.99.8.GIT


--- NEW FILE 0312-This-patch-fixes-a-typo-in-ieee80211.h-ieee82011_deauth-ieee80211_deauth.txt ---
Subject: [PATCH] This patch fixes a typo in ieee80211.h: ieee82011_deauth -> ieee80211_deauth
From: Michael Wu <flamingice sourmilk net>
Date: 1127938606 -0500

Signed-off-by: Michael Wu <flamingice sourmilk net>
Signed-off-by: James Ketrenos <jketreno linux intel com>

---

 include/net/ieee80211.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

applies-to: e8dc66c8c5e2e5dbea9629f1405cdf9bada79985
604116a32eaef4e10d05ae3361450b3f4a4e6a90
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 4851756..33b595e 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -613,7 +613,7 @@ struct ieee80211_disassoc {
 } __attribute__ ((packed));
 
 /* Alias deauth for disassoc */
-#define ieee82011_deauth ieee80211_disassoc
+#define ieee80211_deauth ieee80211_disassoc
 
 struct ieee80211_probe_request {
 	struct ieee80211_hdr_3addr header;
---
0.99.8.GIT


--- NEW FILE 0335-This-will-move-the-ieee80211_is_ofdm_rate-function-to-the-ieee80211.h.txt ---
Subject: [PATCH] This will move the ieee80211_is_ofdm_rate function to the ieee80211.h
From: Ivo van Doorn <IvDoorn gmail com>
Date: 1128351040 -0500
header, and I also added the ieee80211_is_cck_rate counterpart.

Various drivers currently create there own version of these functions,
but I guess the ieee80211 stack is the best place to provide such
routines.

Signed-off-by: Ivo van Doorn <IvDoorn gmail com>
Signed-off-by: James Ketrenos <jketreno linux intel com>

---

 include/net/ieee80211.h      |   28 ++++++++++++++++++++++++++++
 net/ieee80211/ieee80211_rx.c |   16 ----------------
 2 files changed, 28 insertions(+), 16 deletions(-)

applies-to: 6e5a0667172ddafd366b745a53b4ff392927176e
7c254d3dba0fae124b1d33f784ca23572ac386b0
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 33b595e..58f6222 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -1045,6 +1045,34 @@ static inline u8 *ieee80211_get_payload(
 
 }
 
+static inline int ieee80211_is_ofdm_rate(u8 rate)
+{
+	switch (rate & ~IEEE80211_BASIC_RATE_MASK) {
+	case IEEE80211_OFDM_RATE_6MB:
+	case IEEE80211_OFDM_RATE_9MB:
+	case IEEE80211_OFDM_RATE_12MB:
+	case IEEE80211_OFDM_RATE_18MB:
+	case IEEE80211_OFDM_RATE_24MB:
+	case IEEE80211_OFDM_RATE_36MB:
+	case IEEE80211_OFDM_RATE_48MB:
+	case IEEE80211_OFDM_RATE_54MB:
+		return 1;
+	}
+	return 0;
+}
+
+static inline int ieee80211_is_cck_rate(u8 rate)
+{
+	switch (rate & ~IEEE80211_BASIC_RATE_MASK) {
+	case IEEE80211_CCK_RATE_1MB:
+	case IEEE80211_CCK_RATE_2MB:
+	case IEEE80211_CCK_RATE_5MB:
+	case IEEE80211_CCK_RATE_11MB:
+		return 1;
+	}
+	return 0;
+}
+
 /* ieee80211.c */
 extern void free_ieee80211(struct net_device *dev);
 extern struct net_device *alloc_ieee80211(int sizeof_priv);
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index fcf05bf..2f4b16c 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -1020,22 +1020,6 @@ static int ieee80211_handle_assoc_resp(s
 
 /***************************************************/
 
-static inline int ieee80211_is_ofdm_rate(u8 rate)
-{
-	switch (rate & ~IEEE80211_BASIC_RATE_MASK) {
-	case IEEE80211_OFDM_RATE_6MB:
-	case IEEE80211_OFDM_RATE_9MB:
-	case IEEE80211_OFDM_RATE_12MB:
-	case IEEE80211_OFDM_RATE_18MB:
-	case IEEE80211_OFDM_RATE_24MB:
-	case IEEE80211_OFDM_RATE_36MB:
-	case IEEE80211_OFDM_RATE_48MB:
-	case IEEE80211_OFDM_RATE_54MB:
-		return 1;
-	}
-	return 0;
-}
-
 static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response
 					 *beacon,
 					 struct ieee80211_network *network,
---
0.99.8.GIT


--- NEW FILE 0337-Currently-the-info_element-is-parsed-by-2-seperate-functions-this.txt ---
Subject: [PATCH] Currently the info_element is parsed by 2 seperate functions, this
From: Ivo van Doorn <IvDoorn gmail com>
Date: 1128352765 -0500
results in a lot of duplicate code.

This will move the parsing stage into a seperate function.

Signed-off-by: Ivo van Doorn <IvDoorn gmail com>
Signed-off-by: James Ketrenos <jketreno linux intel com>

---

 net/ieee80211/ieee80211_rx.c |  267 ++++++++++++++++--------------------------
 1 files changed, 99 insertions(+), 168 deletions(-)

applies-to: 7cdeea0d54e1fcf13cd2d2d372749e6f1936e2de
ff9e00f1b09d594004f91700a371870f729ffc02
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 2f4b16c..3bf04d6 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -917,158 +917,23 @@ static int ieee80211_parse_qos_info_para
 	return rc;
 }
 
-static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response
-				       *frame, struct ieee80211_rx_stats *stats)
-{
-	struct ieee80211_network network_resp;
-	struct ieee80211_network *network = &network_resp;
-	struct ieee80211_info_element *info_element;
-	struct net_device *dev = ieee->dev;
-	u16 left;
-
-	network->flags = 0;
-	network->qos_data.active = 0;
-	network->qos_data.supported = 0;
-	network->qos_data.param_count = 0;
-	network->qos_data.old_param_count = 0;
-
-	//network->atim_window = le16_to_cpu(frame->aid) & (0x3FFF);
-	network->atim_window = le16_to_cpu(frame->aid);
-	network->listen_interval = le16_to_cpu(frame->status);
-
-	info_element = frame->info_element;
-	left = stats->len - sizeof(*frame);
-
-	while (left >= sizeof(struct ieee80211_info_element)) {
-		if (sizeof(struct ieee80211_info_element) +
-		    info_element->len > left) {
-			IEEE80211_DEBUG_QOS("ASSOC RESP: parse failed: "
-					    "info_element->len + 2 > left : "
-					    "info_element->len+2=%zd left=%d, id=%d.\n",
-					    info_element->len +
-					    sizeof(struct
-						   ieee80211_info_element),
-					    left, info_element->id);
-			return 1;
-		}
-
-		switch (info_element->id) {
-		case MFIE_TYPE_SSID:
-			if (ieee80211_is_empty_essid(info_element->data,
-						     info_element->len)) {
-				network->flags |= NETWORK_EMPTY_ESSID;
-				break;
-			}
-
-			network->ssid_len = min(info_element->len,
-						(u8) IW_ESSID_MAX_SIZE);
-			memcpy(network->ssid, info_element->data,
-			       network->ssid_len);
-			if (network->ssid_len < IW_ESSID_MAX_SIZE)
-				memset(network->ssid + network->ssid_len, 0,
-				       IW_ESSID_MAX_SIZE - network->ssid_len);
-
-			IEEE80211_DEBUG_QOS("MFIE_TYPE_SSID: '%s' len=%d.\n",
-					    network->ssid, network->ssid_len);
-			break;
-
-		case MFIE_TYPE_TIM:
-			IEEE80211_DEBUG_QOS("MFIE_TYPE_TIM: ignored\n");
-			break;
-
-		case MFIE_TYPE_IBSS_SET:
-			IEEE80211_DEBUG_QOS("MFIE_TYPE_IBSS_SET: ignored\n");
-			break;
-
-		case MFIE_TYPE_CHALLENGE:
-			IEEE80211_DEBUG_QOS("MFIE_TYPE_CHALLENGE: ignored\n");
-			break;
-
-		case MFIE_TYPE_GENERIC:
-			IEEE80211_DEBUG_QOS("MFIE_TYPE_GENERIC: %d bytes\n",
-					    info_element->len);
-			ieee80211_parse_qos_info_param_IE(info_element,
-							  network);
-			break;
-
-		case MFIE_TYPE_RSN:
-			IEEE80211_DEBUG_QOS("MFIE_TYPE_RSN: %d bytes\n",
-					    info_element->len);
-			break;
-
-		case MFIE_TYPE_QOS_PARAMETER:
-			printk("QoS Error need to parse QOS_PARAMETER IE\n");
-			break;
-
-		default:
-			IEEE80211_DEBUG_QOS("unsupported IE %d\n",
-					    info_element->id);
-			break;
-		}
-
-		left -= sizeof(struct ieee80211_info_element) +
-		    info_element->len;
-		info_element = (struct ieee80211_info_element *)
-		    &info_element->data[info_element->len];
-	}
-
-	if (ieee->handle_assoc_response != NULL)
-		ieee->handle_assoc_response(dev, frame, network);
-
-	return 0;
-}
-
-/***************************************************/
-
-static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response
-					 *beacon,
-					 struct ieee80211_network *network,
-					 struct ieee80211_rx_stats *stats)
+static int ieee80211_parse_info_param(struct ieee80211_info_element *info_element,
+					u16 length, struct ieee80211_network *network)
 {
+	u8 i;
 #ifdef CONFIG_IEEE80211_DEBUG
 	char rates_str[64];
 	char *p;
 #endif
-	struct ieee80211_info_element *info_element;
-	u16 left;
-	u8 i;
-	network->qos_data.active = 0;
-	network->qos_data.supported = 0;
-	network->qos_data.param_count = 0;
 
-	/* Pull out fixed field data */
-	memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
-	network->capability = le16_to_cpu(beacon->capability);
-	network->last_scanned = jiffies;
-	network->time_stamp[0] = le32_to_cpu(beacon->time_stamp[0]);
-	network->time_stamp[1] = le32_to_cpu(beacon->time_stamp[1]);
-	network->beacon_interval = le16_to_cpu(beacon->beacon_interval);
-	/* Where to pull this? beacon->listen_interval; */
-	network->listen_interval = 0x0A;
-	network->rates_len = network->rates_ex_len = 0;
-	network->last_associate = 0;
-	network->ssid_len = 0;
-	network->flags = 0;
-	network->atim_window = 0;
-	network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ?
-	    0x3 : 0x0;
-
-	if (stats->freq == IEEE80211_52GHZ_BAND) {
-		/* for A band (No DS info) */
-		network->channel = stats->received_channel;
-	} else
-		network->flags |= NETWORK_HAS_CCK;
-
-	network->wpa_ie_len = 0;
-	network->rsn_ie_len = 0;
-
-	info_element = beacon->info_element;
-	left = stats->len - sizeof(*beacon);
-	while (left >= sizeof(*info_element)) {
-		if (sizeof(*info_element) + info_element->len > left) {
-			IEEE80211_DEBUG_SCAN
-			    ("SCAN: parse failed: info_element->len + 2 > left : info_element->len+2=%Zd left=%d.\n",
-			     info_element->len + sizeof(*info_element), left);
+	while (length >= sizeof(*info_element)) {
+		if (sizeof(*info_element) + info_element->len > length) {
+			IEEE80211_DEBUG_MGMT("Info elem: parse failed: "
+					    "info_element->len + 2 > left : "
+					    "info_element->len+2=%zd left=%d, id=%d.\n",
+					    info_element->len +
+					    sizeof(*info_element),
+					    length, info_element->id);
 			return 1;
 		}
 
@@ -1088,8 +953,8 @@ static inline int ieee80211_network_init
 				memset(network->ssid + network->ssid_len, 0,
 				       IW_ESSID_MAX_SIZE - network->ssid_len);
 
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_SSID: '%s' len=%d.\n",
-					     network->ssid, network->ssid_len);
+			IEEE80211_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n",
+					    network->ssid, network->ssid_len);
 			break;
 
 		case MFIE_TYPE_RATES:
@@ -1115,7 +980,7 @@ static inline int ieee80211_network_init
 				}
 			}
 
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES: '%s' (%d)\n",
+			IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES: '%s' (%d)\n",
 					     rates_str, network->rates_len);
 			break;
 
@@ -1142,47 +1007,46 @@ static inline int ieee80211_network_init
 				}
 			}
 
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
+			IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
 					     rates_str, network->rates_ex_len);
 			break;
 
 		case MFIE_TYPE_DS_SET:
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_DS_SET: %d\n",
+			IEEE80211_DEBUG_MGMT("MFIE_TYPE_DS_SET: %d\n",
 					     info_element->data[0]);
-			if (stats->freq == IEEE80211_24GHZ_BAND)
-				network->channel = info_element->data[0];
+			network->channel = info_element->data[0];
 			break;
 
 		case MFIE_TYPE_FH_SET:
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_FH_SET: ignored\n");
+			IEEE80211_DEBUG_MGMT("MFIE_TYPE_FH_SET: ignored\n");
 			break;
 
 		case MFIE_TYPE_CF_SET:
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_CF_SET: ignored\n");
+			IEEE80211_DEBUG_MGMT("MFIE_TYPE_CF_SET: ignored\n");
 			break;
 
 		case MFIE_TYPE_TIM:
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_TIM: ignored\n");
+			IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: ignored\n");
 			break;
 
 		case MFIE_TYPE_ERP_INFO:
 			network->erp_value = info_element->data[0];
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_ERP_SET: %d\n",
+			IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n",
 					     network->erp_value);
 			break;
 
 		case MFIE_TYPE_IBSS_SET:
 			network->atim_window = info_element->data[0];
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_IBSS_SET: %d\n",
+			IEEE80211_DEBUG_MGMT("MFIE_TYPE_IBSS_SET: %d\n",
 					     network->atim_window);
 			break;
 
 		case MFIE_TYPE_CHALLENGE:
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_CHALLENGE: ignored\n");
+			IEEE80211_DEBUG_MGMT("MFIE_TYPE_CHALLENGE: ignored\n");
 			break;
 
 		case MFIE_TYPE_GENERIC:
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n",
+			IEEE80211_DEBUG_MGMT("MFIE_TYPE_GENERIC: %d bytes\n",
 					     info_element->len);
 			if (!ieee80211_parse_qos_info_param_IE(info_element,
 							       network))
@@ -1201,7 +1065,7 @@ static inline int ieee80211_network_init
 			break;
 
 		case MFIE_TYPE_RSN:
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_RSN: %d bytes\n",
+			IEEE80211_DEBUG_MGMT("MFIE_TYPE_RSN: %d bytes\n",
 					     info_element->len);
 			network->rsn_ie_len = min(info_element->len + 2,
 						  MAX_WPA_IE_LEN);
@@ -1210,21 +1074,88 @@ static inline int ieee80211_network_init
 			break;
 
 		case MFIE_TYPE_QOS_PARAMETER:
-			printk(KERN_ERR
-			       "QoS Error need to parse QOS_PARAMETER IE\n");
+			printk(KERN_ERR "QoS Error need to parse QOS_PARAMETER IE\n");
 			break;
 
 		default:
-			IEEE80211_DEBUG_SCAN("unsupported IE %d\n",
-					     info_element->id);
+			IEEE80211_DEBUG_MGMT("unsupported IE %d\n",
+					    info_element->id);
 			break;
 		}
 
-		left -= sizeof(*info_element) + info_element->len;
-		info_element = (struct ieee80211_info_element *)
-		    &info_element->data[info_element->len];
+		length -= sizeof(*info_element) + info_element->len;
+		info_element = (struct ieee80211_info_element *) &info_element->data[info_element->len];
 	}
 
+	return 0;
+}
+
+static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response
+				       *frame, struct ieee80211_rx_stats *stats)
+{
+	struct ieee80211_network network_resp;
+	struct ieee80211_network *network = &network_resp;
+	struct net_device *dev = ieee->dev;
+
+	network->flags = 0;
+	network->qos_data.active = 0;
+	network->qos_data.supported = 0;
+	network->qos_data.param_count = 0;
+	network->qos_data.old_param_count = 0;
+
+	//network->atim_window = le16_to_cpu(frame->aid) & (0x3FFF);
+	network->atim_window = le16_to_cpu(frame->aid);
+	network->listen_interval = le16_to_cpu(frame->status);
+
+	if(ieee80211_parse_info_param(frame->info_element, stats->len - sizeof(*frame), network))
+		return 1;
+
+	if (ieee->handle_assoc_response != NULL)
+		ieee->handle_assoc_response(dev, frame, network);
+
+	return 0;
+}
+
+/***************************************************/
+
+static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response
+					 *beacon,
+					 struct ieee80211_network *network,
+					 struct ieee80211_rx_stats *stats)
+{
+	network->qos_data.active = 0;
+	network->qos_data.supported = 0;
+	network->qos_data.param_count = 0;
+
+	/* Pull out fixed field data */
+	memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
+	network->capability = le16_to_cpu(beacon->capability);
+	network->last_scanned = jiffies;
+	network->time_stamp[0] = le32_to_cpu(beacon->time_stamp[0]);
+	network->time_stamp[1] = le32_to_cpu(beacon->time_stamp[1]);
+	network->beacon_interval = le16_to_cpu(beacon->beacon_interval);
+	/* Where to pull this? beacon->listen_interval; */
+	network->listen_interval = 0x0A;
+	network->rates_len = network->rates_ex_len = 0;
+	network->last_associate = 0;
+	network->ssid_len = 0;
+	network->flags = 0;
+	network->atim_window = 0;
+	network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ?
+	    0x3 : 0x0;
+
+	if (stats->freq == IEEE80211_52GHZ_BAND) {
+		/* for A band (No DS info) */
+		network->channel = stats->received_channel;
+	} else
+		network->flags |= NETWORK_HAS_CCK;
+
+	network->wpa_ie_len = 0;
+	network->rsn_ie_len = 0;
+
+	if(ieee80211_parse_info_param(beacon->info_element, stats->len - sizeof(*beacon), network))
+		return 1;
+
 	network->mode = 0;
 	if (stats->freq == IEEE80211_52GHZ_BAND)
 		network->mode = IEEE_A;
---
0.99.8.GIT


--- NEW FILE 0338-When-an-assoc_resp-is-received-the-network-structure-is-not-completely.txt ---
Subject: [PATCH] When an assoc_resp is received the network structure is not completely
From: Ivo van Doorn <IvDoorn gmail com>
Date: 1128352847 -0500
initialized which can cause problems for drivers that expect the network
structure to be completely filled in.

This patch will make sure the network is filled in as much as possible.

Signed-off-by: Ivo van Doorn <IvDoorn gmail com>
Signed-off-by: James Ketrenos <jketreno linux intel com>

---

 net/ieee80211/ieee80211_rx.c |   32 ++++++++++++++++++++++++++++++++
 1 files changed, 32 insertions(+), 0 deletions(-)

applies-to: 44977fc59711d89871d69e3169f8bc2b2cc2b55e
c1bda44a4aedf13251b2704e6e67afb4909195c8
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 3bf04d6..8d87d66 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -1106,10 +1106,41 @@ static int ieee80211_handle_assoc_resp(s
 	//network->atim_window = le16_to_cpu(frame->aid) & (0x3FFF);
 	network->atim_window = le16_to_cpu(frame->aid);
 	network->listen_interval = le16_to_cpu(frame->status);
+	memcpy(network->bssid, frame->header.addr3, ETH_ALEN);
+	network->capability = le16_to_cpu(frame->capability);
+	network->last_scanned = jiffies;
+	network->rates_len = network->rates_ex_len = 0;
+	network->last_associate = 0;
+	network->ssid_len = 0;
+	network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ? 0x3 : 0x0;
+
+	if (stats->freq == IEEE80211_52GHZ_BAND) {
+		/* for A band (No DS info) */
+		network->channel = stats->received_channel;
+	} else
+		network->flags |= NETWORK_HAS_CCK;
+
+	network->wpa_ie_len = 0;
+	network->rsn_ie_len = 0;
 
 	if(ieee80211_parse_info_param(frame->info_element, stats->len - sizeof(*frame), network))
 		return 1;
 
+	network->mode = 0;
+	if (stats->freq == IEEE80211_52GHZ_BAND)
+		network->mode = IEEE_A;
+	else {
+		if (network->flags & NETWORK_HAS_OFDM)
+			network->mode |= IEEE_G;
+		if (network->flags & NETWORK_HAS_CCK)
+			network->mode |= IEEE_B;
+	}
+
+	if (ieee80211_is_empty_essid(network->ssid, network->ssid_len))
+		network->flags |= NETWORK_EMPTY_ESSID;
+
+	memcpy(&network->stats, stats, sizeof(network->stats));
+
 	if (ieee->handle_assoc_response != NULL)
 		ieee->handle_assoc_response(dev, frame, network);
 
@@ -1126,6 +1157,7 @@ static inline int ieee80211_network_init
 	network->qos_data.active = 0;
 	network->qos_data.supported = 0;
 	network->qos_data.param_count = 0;
+	network->qos_data.old_param_count = 0;
 
 	/* Pull out fixed field data */
 	memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
---
0.99.8.GIT


--- NEW FILE 0339-Lindent-and-trailing-whitespace-script-executed-ieee80211-subsystem.txt ---
Subject: [PATCH] Lindent and trailing whitespace script executed ieee80211 subsystem
From: James Ketrenos <jketreno linux intel com>
Date: 1128353022 -0500

Signed-off-by: James Ketrenos <jketreno linux intel com>

---

 include/net/ieee80211_crypt.h |    6 +++---
 net/ieee80211/ieee80211_rx.c  |   35 +++++++++++++++++++++--------------
 2 files changed, 24 insertions(+), 17 deletions(-)

applies-to: ff5bd9d92894bf777183447df3fad5615da51db7
ff0037b259e8b47843176142131844bc80fd2887
diff --git a/include/net/ieee80211_crypt.h b/include/net/ieee80211_crypt.h
index 0c9d859..0a1c2d8 100644
--- a/include/net/ieee80211_crypt.h
+++ b/include/net/ieee80211_crypt.h
@@ -26,7 +26,7 @@
 #include <linux/skbuff.h>
 
 enum {
-	IEEE80211_CRYPTO_TKIP_COUNTERMEASURES = (1<<0),
+	IEEE80211_CRYPTO_TKIP_COUNTERMEASURES = (1 << 0),
 };
 
 struct ieee80211_crypto_ops {
@@ -65,8 +65,8 @@ struct ieee80211_crypto_ops {
 	char *(*print_stats) (char *p, void *priv);
 
 	/* Crypto specific flag get/set for configuration settings */
-	unsigned long (*get_flags)(void *priv);
-	unsigned long (*set_flags)(unsigned long flags, void *priv);
+	unsigned long (*get_flags) (void *priv);
+	unsigned long (*set_flags) (unsigned long flags, void *priv);
 
 	/* maximum number of bytes added by encryption; encrypt buf is
 	 * allocated with extra_prefix_len bytes, copy of in_buf, and
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 8d87d66..6b005cb 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -917,8 +917,9 @@ static int ieee80211_parse_qos_info_para
 	return rc;
 }
 
-static int ieee80211_parse_info_param(struct ieee80211_info_element *info_element,
-					u16 length, struct ieee80211_network *network)
+static int ieee80211_parse_info_param(struct ieee80211_info_element
+				      *info_element, u16 length,
+				      struct ieee80211_network *network)
 {
 	u8 i;
 #ifdef CONFIG_IEEE80211_DEBUG
@@ -929,11 +930,11 @@ static int ieee80211_parse_info_param(st
 	while (length >= sizeof(*info_element)) {
 		if (sizeof(*info_element) + info_element->len > length) {
 			IEEE80211_DEBUG_MGMT("Info elem: parse failed: "
-					    "info_element->len + 2 > left : "
-					    "info_element->len+2=%zd left=%d, id=%d.\n",
-					    info_element->len +
-					    sizeof(*info_element),
-					    length, info_element->id);
+					     "info_element->len + 2 > left : "
+					     "info_element->len+2=%zd left=%d, id=%d.\n",
+					     info_element->len +
+					     sizeof(*info_element),
+					     length, info_element->id);
 			return 1;
 		}
 
@@ -954,7 +955,7 @@ static int ieee80211_parse_info_param(st
 				       IW_ESSID_MAX_SIZE - network->ssid_len);
 
 			IEEE80211_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n",
-					    network->ssid, network->ssid_len);
+					     network->ssid, network->ssid_len);
 			break;
 
 		case MFIE_TYPE_RATES:
@@ -1074,17 +1075,20 @@ static int ieee80211_parse_info_param(st
 			break;
 
 		case MFIE_TYPE_QOS_PARAMETER:
-			printk(KERN_ERR "QoS Error need to parse QOS_PARAMETER IE\n");
+			printk(KERN_ERR
+			       "QoS Error need to parse QOS_PARAMETER IE\n");
 			break;
 
 		default:
 			IEEE80211_DEBUG_MGMT("unsupported IE %d\n",
-					    info_element->id);
+					     info_element->id);
 			break;
 		}
 
 		length -= sizeof(*info_element) + info_element->len;
-		info_element = (struct ieee80211_info_element *) &info_element->data[info_element->len];
+		info_element =
+		    (struct ieee80211_info_element *)&info_element->
+		    data[info_element->len];
 	}
 
 	return 0;
@@ -1112,7 +1116,8 @@ static int ieee80211_handle_assoc_resp(s
 	network->rates_len = network->rates_ex_len = 0;
 	network->last_associate = 0;
 	network->ssid_len = 0;
-	network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ? 0x3 : 0x0;
+	network->erp_value =
+	    (network->capability & WLAN_CAPABILITY_IBSS) ? 0x3 : 0x0;
 
 	if (stats->freq == IEEE80211_52GHZ_BAND) {
 		/* for A band (No DS info) */
@@ -1123,7 +1128,8 @@ static int ieee80211_handle_assoc_resp(s
 	network->wpa_ie_len = 0;
 	network->rsn_ie_len = 0;
 
-	if(ieee80211_parse_info_param(frame->info_element, stats->len - sizeof(*frame), network))
+	if (ieee80211_parse_info_param
+	    (frame->info_element, stats->len - sizeof(*frame), network))
 		return 1;
 
 	network->mode = 0;
@@ -1185,7 +1191,8 @@ static inline int ieee80211_network_init
 	network->wpa_ie_len = 0;
 	network->rsn_ie_len = 0;
 
-	if(ieee80211_parse_info_param(beacon->info_element, stats->len - sizeof(*beacon), network))
+	if (ieee80211_parse_info_param
+	    (beacon->info_element, stats->len - sizeof(*beacon), network))
 		return 1;
 
 	network->mode = 0;
---
0.99.8.GIT


Index: 0345-hostap-Remove-hw-specific-dev_open-close-handlers.txt
===================================================================
RCS file: 0345-hostap-Remove-hw-specific-dev_open-close-handlers.txt
diff -N 0345-hostap-Remove-hw-specific-dev_open-close-handlers.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0345-hostap-Remove-hw-specific-dev_open-close-handlers.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,176 @@
+Subject: [PATCH] hostap: Remove hw specific dev_open/close handlers
+From: Jouni Malinen <jkmaline cc hut fi>
+Date: 1128298738 -0700
+
+Host AP driver used hardware model specific dev_open/close handlers
+that were called on dev_open/close if the hardware driver had
+registered the handler. These were only used for hostap_cs and only
+for tracking whether any of the netdevs were UP. This information is
+already available from local->num_dev_open, so there is not need for
+the special open/close handler.
+
+Let's get rid of these handlers. In addition to cleaning up the code,
+this fixes a module refcounting issue for hostap_cs where ejecting the
+card while any of the netdevs were open did not decrement refcount
+properly.
+
+Signed-off-by: Jouni Malinen <jkmaline cc hut fi>
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/hostap/hostap.c      |    6 ----
+ drivers/net/wireless/hostap/hostap_cs.c   |   45 ++++++-----------------------
+ drivers/net/wireless/hostap/hostap_pci.c  |    2 -
+ drivers/net/wireless/hostap/hostap_plx.c  |    2 -
+ drivers/net/wireless/hostap/hostap_wlan.h |    2 -
+ 5 files changed, 10 insertions(+), 47 deletions(-)
+
+applies-to: e8dc66c8c5e2e5dbea9629f1405cdf9bada79985
+bab76198b3111bd0328be3c1fa208237eb12f86e
+diff --git a/drivers/net/wireless/hostap/hostap.c b/drivers/net/wireless/hostap/hostap.c
+index e7f5821..6a96cd9 100644
+--- a/drivers/net/wireless/hostap/hostap.c
++++ b/drivers/net/wireless/hostap/hostap.c
+@@ -716,9 +716,6 @@ static int prism2_close(struct net_devic
+ 		hostap_deauth_all_stas(dev, local->ap, 1);
+ #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+ 
+-	if (local->func->dev_close && local->func->dev_close(local))
+-		return 0;
+-
+ 	if (dev == local->dev) {
+ 		local->func->hw_shutdown(dev, HOSTAP_HW_ENABLE_CMDCOMPL);
+ 	}
+@@ -766,9 +763,6 @@ static int prism2_open(struct net_device
+ 	    local->hw_downloading)
+ 		return -ENODEV;
+ 
+-	if (local->func->dev_open && local->func->dev_open(local))
+-		return 1;
+-
+ 	if (!try_module_get(local->hw_module))
+ 		return -ENODEV;
+ 	local->num_dev_open++;
+diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
+index faa83ba..23bcc51 100644
+--- a/drivers/net/wireless/hostap/hostap_cs.c
++++ b/drivers/net/wireless/hostap/hostap_cs.c
+@@ -492,42 +492,10 @@ static void prism2_pccard_genesis_reset(
+ }
+ 
+ 
+-static int prism2_pccard_dev_open(local_info_t *local)
+-{
+-	struct hostap_cs_priv *hw_priv = local->hw_priv;
+-	hw_priv->link->open++;
+-	return 0;
+-}
+-
+-
+-static int prism2_pccard_dev_close(local_info_t *local)
+-{
+-	struct hostap_cs_priv *hw_priv;
+-
+-	if (local == NULL || local->hw_priv == NULL)
+-		return 1;
+-	hw_priv = local->hw_priv;
+-	if (hw_priv->link == NULL)
+-		return 1;
+-
+-	if (!hw_priv->link->open) {
+-		printk(KERN_WARNING "%s: prism2_pccard_dev_close(): "
+-		       "link not open?!\n", local->dev->name);
+-		return 1;
+-	}
+-
+-	hw_priv->link->open--;
+-
+-	return 0;
+-}
+-
+-
+ static struct prism2_helper_functions prism2_pccard_funcs =
+ {
+ 	.card_present	= prism2_pccard_card_present,
+ 	.cor_sreset	= prism2_pccard_cor_sreset,
+-	.dev_open	= prism2_pccard_dev_open,
+-	.dev_close	= prism2_pccard_dev_close,
+ 	.genesis_reset	= prism2_pccard_genesis_reset,
+ 	.hw_type	= HOSTAP_HW_PCCARD,
+ };
+@@ -883,6 +851,13 @@ static int prism2_event(event_t event, i
+ {
+ 	dev_link_t *link = args->client_data;
+ 	struct net_device *dev = (struct net_device *) link->priv;
++	int dev_open = 0;
++
++	if (link->state & DEV_CONFIG) {
++		struct hostap_interface *iface = netdev_priv(dev);
++		if (iface && iface->local)
++			dev_open = iface->local->num_dev_open > 0;
++	}
+ 
+ 	switch (event) {
+ 	case CS_EVENT_CARD_INSERTION:
+@@ -911,7 +886,7 @@ static int prism2_event(event_t event, i
+ 	case CS_EVENT_RESET_PHYSICAL:
+ 		PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_RESET_PHYSICAL\n", dev_info);
+ 		if (link->state & DEV_CONFIG) {
+-			if (link->open) {
++			if (dev_open) {
+ 				netif_stop_queue(dev);
+ 				netif_device_detach(dev);
+ 			}
+@@ -931,8 +906,8 @@ static int prism2_event(event_t event, i
+ 			pcmcia_request_configuration(link->handle,
+ 						     &link->conf);
+ 			prism2_hw_shutdown(dev, 1);
+-			prism2_hw_config(dev, link->open ? 0 : 1);
+-			if (link->open) {
++			prism2_hw_config(dev, dev_open ? 0 : 1);
++			if (dev_open) {
+ 				netif_device_attach(dev);
+ 				netif_start_queue(dev);
+ 			}
+diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
+index b9254f7..594cc29 100644
+--- a/drivers/net/wireless/hostap/hostap_pci.c
++++ b/drivers/net/wireless/hostap/hostap_pci.c
+@@ -277,8 +277,6 @@ static struct prism2_helper_functions pr
+ {
+ 	.card_present	= NULL,
+ 	.cor_sreset	= prism2_pci_cor_sreset,
+-	.dev_open	= NULL,
+-	.dev_close	= NULL,
+ 	.genesis_reset	= prism2_pci_genesis_reset,
+ 	.hw_type	= HOSTAP_HW_PCI,
+ };
+diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c
+index 1abebdf..85d3f8a 100644
+--- a/drivers/net/wireless/hostap/hostap_plx.c
++++ b/drivers/net/wireless/hostap/hostap_plx.c
+@@ -328,8 +328,6 @@ static struct prism2_helper_functions pr
+ {
+ 	.card_present	= NULL,
+ 	.cor_sreset	= prism2_plx_cor_sreset,
+-	.dev_open	= NULL,
+-	.dev_close	= NULL,
+ 	.genesis_reset	= prism2_plx_genesis_reset,
+ 	.hw_type	= HOSTAP_HW_PLX,
+ };
+diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h
+index cc061e1..cfd8015 100644
+--- a/drivers/net/wireless/hostap/hostap_wlan.h
++++ b/drivers/net/wireless/hostap/hostap_wlan.h
+@@ -552,8 +552,6 @@ struct prism2_helper_functions {
+ 	 * (hostap_{cs,plx,pci}.c */
+ 	int (*card_present)(local_info_t *local);
+ 	void (*cor_sreset)(local_info_t *local);
+-	int (*dev_open)(local_info_t *local);
+-	int (*dev_close)(local_info_t *local);
+ 	void (*genesis_reset)(local_info_t *local, int hcr);
+ 
+ 	/* the following functions are from hostap_hw.c, but they may have some
+---
+0.99.8.GIT


Index: 0346-hostap-Fix-hostap_pci-build-with-PRISM2_IO_DEBUG.txt
===================================================================
RCS file: 0346-hostap-Fix-hostap_pci-build-with-PRISM2_IO_DEBUG.txt
diff -N 0346-hostap-Fix-hostap_pci-build-with-PRISM2_IO_DEBUG.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0346-hostap-Fix-hostap_pci-build-with-PRISM2_IO_DEBUG.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,82 @@
+Subject: [PATCH] hostap: Fix hostap_pci build with PRISM2_IO_DEBUG
+From: Jouni Malinen <jkmaline cc hut fi>
+Date: 1128298739 -0700
+
+The debug version of I/O functions in hostap_pci had not survived the
+change to start using hw_priv pointer, so let's fix them to actually
+define the local hw_priv variable.
+
+Signed-off-by: Jouni Malinen <jkmaline cc hut fi>
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/hostap/hostap_pci.c |    8 ++++++++
+ 1 files changed, 8 insertions(+), 0 deletions(-)
+
+applies-to: 11f1e2ec911c48a1e74563979457e8d299e414e5
+f7a74447553d698795ba74b7e17e916000b0cb08
+diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
+index 594cc29..0d7305d 100644
+--- a/drivers/net/wireless/hostap/hostap_pci.c
++++ b/drivers/net/wireless/hostap/hostap_pci.c
+@@ -59,11 +59,13 @@ static struct pci_device_id prism2_pci_i
+ static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v)
+ {
+ 	struct hostap_interface *iface;
++	struct hostap_pci_priv *hw_priv;
+ 	local_info_t *local;
+ 	unsigned long flags;
+ 
+ 	iface = netdev_priv(dev);
+ 	local = iface->local;
++	hw_priv = local->hw_priv;
+ 
+ 	spin_lock_irqsave(&local->lock, flags);
+ 	prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTB, a, v);
+@@ -74,12 +76,14 @@ static inline void hfa384x_outb_debug(st
+ static inline u8 hfa384x_inb_debug(struct net_device *dev, int a)
+ {
+ 	struct hostap_interface *iface;
++	struct hostap_pci_priv *hw_priv;
+ 	local_info_t *local;
+ 	unsigned long flags;
+ 	u8 v;
+ 
+ 	iface = netdev_priv(dev);
+ 	local = iface->local;
++	hw_priv = local->hw_priv;
+ 
+ 	spin_lock_irqsave(&local->lock, flags);
+ 	v = readb(hw_priv->mem_start + a);
+@@ -91,11 +95,13 @@ static inline u8 hfa384x_inb_debug(struc
+ static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v)
+ {
+ 	struct hostap_interface *iface;
++	struct hostap_pci_priv *hw_priv;
+ 	local_info_t *local;
+ 	unsigned long flags;
+ 
+ 	iface = netdev_priv(dev);
+ 	local = iface->local;
++	hw_priv = local->hw_priv;
+ 
+ 	spin_lock_irqsave(&local->lock, flags);
+ 	prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTW, a, v);
+@@ -106,12 +112,14 @@ static inline void hfa384x_outw_debug(st
+ static inline u16 hfa384x_inw_debug(struct net_device *dev, int a)
+ {
+ 	struct hostap_interface *iface;
++	struct hostap_pci_priv *hw_priv;
+ 	local_info_t *local;
+ 	unsigned long flags;
+ 	u16 v;
+ 
+ 	iface = netdev_priv(dev);
+ 	local = iface->local;
++	hw_priv = local->hw_priv;
+ 
+ 	spin_lock_irqsave(&local->lock, flags);
+ 	v = readw(hw_priv->mem_start + a);
+---
+0.99.8.GIT


Index: 0347-hostap-Do-not-free-local-hw_priv-before-unregistering-netdev.txt
===================================================================
RCS file: 0347-hostap-Do-not-free-local-hw_priv-before-unregistering-netdev.txt
diff -N 0347-hostap-Do-not-free-local-hw_priv-before-unregistering-netdev.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0347-hostap-Do-not-free-local-hw_priv-before-unregistering-netdev.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,109 @@
+Subject: [PATCH] hostap: Do not free local->hw_priv before unregistering netdev
+From: Jouni Malinen <jkmaline cc hut fi>
+Date: 1128298740 -0700
+
+local->hw_priv was being freed and set to NULL just before calling
+prism2_free_local_data(). However, this may expose a race condition in
+which something ends up trying to use hw_priv during shutdown. I
+haven't noticed this happening, but better be safe than sorry, so
+let's postpone hw_priv freeing to happen only after
+prism2_free_local_data() has returned.
+
+Signed-off-by: Jouni Malinen <jkmaline cc hut fi>
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/hostap/hostap_cs.c  |    5 +++--
+ drivers/net/wireless/hostap/hostap_pci.c |    9 ++-------
+ drivers/net/wireless/hostap/hostap_plx.c |    7 ++-----
+ 3 files changed, 7 insertions(+), 14 deletions(-)
+
+applies-to: 02143425097ceec545e4de3795a44e12531e8b78
+c355184cd3cd58c9ffc78f2a17e0ac3563312ea7
+diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
+index 23bcc51..2643976 100644
+--- a/drivers/net/wireless/hostap/hostap_cs.c
++++ b/drivers/net/wireless/hostap/hostap_cs.c
+@@ -565,13 +565,14 @@ static void prism2_detach(dev_link_t *li
+ 	*linkp = link->next;
+ 	/* release net devices */
+ 	if (link->priv) {
++		struct hostap_cs_priv *hw_priv;
+ 		struct net_device *dev;
+ 		struct hostap_interface *iface;
+ 		dev = link->priv;
+ 		iface = netdev_priv(dev);
+-		kfree(iface->local->hw_priv);
+-		iface->local->hw_priv = NULL;
++		hw_priv = iface->local->hw_priv;
+ 		prism2_free_local_data(dev);
++		kfree(hw_priv);
+ 	}
+ 	kfree(link);
+ }
+diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
+index 0d7305d..da0c80f 100644
+--- a/drivers/net/wireless/hostap/hostap_pci.c
++++ b/drivers/net/wireless/hostap/hostap_pci.c
+@@ -358,8 +358,6 @@ static int prism2_pci_probe(struct pci_d
+ 	return hostap_hw_ready(dev);
+ 
+  fail:
+-	kfree(hw_priv);
+-
+ 	if (irq_registered && dev)
+ 		free_irq(dev->irq, dev);
+ 
+@@ -370,10 +368,8 @@ static int prism2_pci_probe(struct pci_d
+ 
+  err_out_disable:
+ 	pci_disable_device(pdev);
+-	kfree(hw_priv);
+-	if (local)
+-		local->hw_priv = NULL;
+ 	prism2_free_local_data(dev);
++	kfree(hw_priv);
+ 
+ 	return -ENODEV;
+ }
+@@ -398,9 +394,8 @@ static void prism2_pci_remove(struct pci
+ 		free_irq(dev->irq, dev);
+ 
+ 	mem_start = hw_priv->mem_start;
+-	kfree(hw_priv);
+-	iface->local->hw_priv = NULL;
+ 	prism2_free_local_data(dev);
++	kfree(hw_priv);
+ 
+ 	iounmap(mem_start);
+ 
+diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c
+index 85d3f8a..78d67b4 100644
+--- a/drivers/net/wireless/hostap/hostap_plx.c
++++ b/drivers/net/wireless/hostap/hostap_plx.c
+@@ -568,10 +568,8 @@ static int prism2_plx_probe(struct pci_d
+ 	return hostap_hw_ready(dev);
+ 
+  fail:
+-	kfree(hw_priv);
+-	if (local)
+-		local->hw_priv = NULL;
+ 	prism2_free_local_data(dev);
++	kfree(hw_priv);
+ 
+ 	if (irq_registered && dev)
+ 		free_irq(dev->irq, dev);
+@@ -604,9 +602,8 @@ static void prism2_plx_remove(struct pci
+ 	if (dev->irq)
+ 		free_irq(dev->irq, dev);
+ 
+-	kfree(iface->local->hw_priv);
+-	iface->local->hw_priv = NULL;
+ 	prism2_free_local_data(dev);
++	kfree(hw_priv);
+ 	pci_disable_device(pdev);
+ }
+ 
+---
+0.99.8.GIT


Index: 0348-hostap-Unregister-netdevs-before-freeing-local-data.txt
===================================================================
RCS file: 0348-hostap-Unregister-netdevs-before-freeing-local-data.txt
diff -N 0348-hostap-Unregister-netdevs-before-freeing-local-data.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0348-hostap-Unregister-netdevs-before-freeing-local-data.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,69 @@
+Subject: [PATCH] hostap: Unregister netdevs before freeing local data
+From: Jouni Malinen <jkmaline cc hut fi>
+Date: 1128298741 -0700
+
+Unregister all netdevs before freeing local data. I was unable to
+trigger any crashes without this change when running busy loops for
+driver operations when ejecting a Prism2 PC Card. Anyway, should there
+be a race condition with this, better make it less likely to happen by
+unregistering the netdevs first.
+
+Signed-off-by: Jouni Malinen <jkmaline cc hut fi>
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/hostap/hostap_hw.c |   22 ++++++++++++----------
+ 1 files changed, 12 insertions(+), 10 deletions(-)
+
+applies-to: f6de150b08f98540bf660cedffd77785ce75b479
+7cb3cd090c2725b80561958a362c2ba15a7a8c86
+diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
+index e533a66..59fc155 100644
+--- a/drivers/net/wireless/hostap/hostap_hw.c
++++ b/drivers/net/wireless/hostap/hostap_hw.c
+@@ -3322,6 +3322,18 @@ static void prism2_free_local_data(struc
+ 	iface = netdev_priv(dev);
+ 	local = iface->local;
+ 
++	/* Unregister all netdevs before freeing local data. */
++	list_for_each_safe(ptr, n, &local->hostap_interfaces) {
++		iface = list_entry(ptr, struct hostap_interface, list);
++		if (iface->type == HOSTAP_INTERFACE_MASTER) {
++			/* special handling for this interface below */
++			continue;
++		}
++		hostap_remove_interface(iface->dev, 0, 1);
++	}
++
++	unregister_netdev(local->dev);
++
+ 	flush_scheduled_work();
+ 
+ 	if (timer_pending(&local->crypt_deinit_timer))
+@@ -3382,15 +3394,6 @@ static void prism2_free_local_data(struc
+ 	prism2_download_free_data(local->dl_sec);
+ #endif /* PRISM2_DOWNLOAD_SUPPORT */
+ 
+-	list_for_each_safe(ptr, n, &local->hostap_interfaces) {
+-		iface = list_entry(ptr, struct hostap_interface, list);
+-		if (iface->type == HOSTAP_INTERFACE_MASTER) {
+-			/* special handling for this interface below */
+-			continue;
+-		}
+-		hostap_remove_interface(iface->dev, 0, 1);
+-	}
+-
+ 	prism2_clear_set_tim_queue(local);
+ 
+ 	list_for_each_safe(ptr, n, &local->bss_list) {
+@@ -3403,7 +3406,6 @@ static void prism2_free_local_data(struc
+ 	kfree(local->last_scan_results);
+ 	kfree(local->generic_elem);
+ 
+-	unregister_netdev(local->dev);
+ 	free_netdev(local->dev);
+ }
+ 
+---
+0.99.8.GIT


Index: 0366-airo-fix-resume.txt
===================================================================
RCS file: 0366-airo-fix-resume.txt
diff -N 0366-airo-fix-resume.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0366-airo-fix-resume.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,41 @@
+Subject: [PATCH] airo: fix resume
+From: Michal Schmidt <xschmi00 stud feec vutbr cz>
+Date: 1128426381 -0400
+
+Cisco Aironet doesn't resume properly from swsusp, because the resume
+method confuses a PM_EVENT_* for a PCI power state. It thinks that it is
+resuming from PCI_D1 and doesn't do the necessary initialization of the
+card.
+
+Signed-off-by: Michal Schmidt <xschmi00 stud feec vutbr cz>
+
+---
+
+ drivers/net/wireless/airo.c |    7 ++++---
+ 1 files changed, 4 insertions(+), 3 deletions(-)
+
+applies-to: b87f83c8215a65e1f1eb0b585d05afb21c15caaf
+53232803241ae0f26b39897a4d4b37775837de00
+diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
+index 746456c..cb429e7 100644
+--- a/drivers/net/wireless/airo.c
++++ b/drivers/net/wireless/airo.c
+@@ -5504,12 +5504,13 @@ static int airo_pci_resume(struct pci_de
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct airo_info *ai = dev->priv;
+ 	Resp rsp;
++	pci_power_t prev_state = pdev->current_state;
+ 
+-	pci_set_power_state(pdev, 0);
++	pci_set_power_state(pdev, PCI_D0);
+ 	pci_restore_state(pdev);
+-	pci_enable_wake(pdev, pci_choose_state(pdev, ai->power), 0);
++	pci_enable_wake(pdev, PCI_D0, 0);
+ 
+-	if (ai->power.event > 1) {
++	if (prev_state != PCI_D1) {
+ 		reset_card(dev, 0);
+ 		mpi_init_descriptors(ai);
+ 		setup_card(ai, dev->dev_addr, 0);
+---
+0.99.8.GIT


Index: 0371-wireless-ipw2200-remove-redundant-return-statement.txt
===================================================================
RCS file: 0371-wireless-ipw2200-remove-redundant-return-statement.txt
diff -N 0371-wireless-ipw2200-remove-redundant-return-statement.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0371-wireless-ipw2200-remove-redundant-return-statement.txt	11 Nov 2005 18:29:00 -0000	1.1.2.3
@@ -0,0 +1,26 @@
+Subject: [PATCH] [wireless ipw2200] remove redundant return statement
+From: Mateusz Berezecki <mateuszb gmail com>
+Date: 1128428040 -0400
+
+---
+
+ drivers/net/wireless/ipw2200.c |    2 --
+ 1 files changed, 0 insertions(+), 2 deletions(-)
+
+applies-to: a795da3ac5c888f16b96082ddbd3d01c8c05493d
+e2608361be343e6220e0a87e04ff224eb037df31
+diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
+index 7ea9bd5..de4e6c2 100644
+--- a/drivers/net/wireless/ipw2200.c
++++ b/drivers/net/wireless/ipw2200.c
+@@ -5318,8 +5318,6 @@ static int ipw_wx_set_freq(struct net_de
+ 
+ 	IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m);
+ 	return ipw_set_channel(priv, (u8) fwrq->m);
+-
+-	return 0;
+ }
+ 
+ static int ipw_wx_get_freq(struct net_device *dev,
+---
+0.99.8.GIT


--- NEW FILE 0543-SUNRPC-Retry-rpcbind-requests-if-the-server-s-portmapper-isn-t-up.txt ---
Subject: [PATCH] SUNRPC: Retry rpcbind requests if the server's portmapper isn't up
From: Chuck Lever <cel netapp com>
Date: 1128654778 -0400

 After a server crash/reboot, rebinding should always retry, otherwise
 requests on "hard" mounts will fail when they shouldn't.

 Test plan:
 Run a lock-intensive workload against a server while rebooting the server
 repeatedly.

 Signed-off-by: Chuck Lever <cel netapp com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 net/sunrpc/clnt.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

applies-to: 2791f2208b54ade86625af416ff5342f11282f0c
ea635a517e350eb03ab5f01618417f31b82a9a4d
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 5a8f01d..a5f7029 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -759,7 +759,8 @@ call_bind_status(struct rpc_task *task)
 	case -EACCES:
 		dprintk("RPC: %4d remote rpcbind: RPC program/version unavailable\n",
 				task->tk_pid);
-		break;
+		rpc_delay(task, 3*HZ);
+		goto retry_bind;
 	case -ETIMEDOUT:
 		dprintk("RPC: %4d rpcbind request timed out\n",
 				task->tk_pid);
---
0.99.8.GIT


--- NEW FILE 0544-RPC-allow-call_encode-to-delay-transmission-of-an-RPC-call.txt ---
Subject: [PATCH] RPC: allow call_encode() to delay transmission of an RPC call.
From: Trond Myklebust <Trond Myklebust netapp com>
Date: 1129670411 -0700

 Currently, call_encode will cause the entire RPC call to abort if it returns
 an error. This is unnecessarily rigid, and gets in the way of attempts
 to allow the NFSv4 layer to order RPC calls that carry sequence ids.

 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/xprt.h |    1 +
 net/sunrpc/clnt.c           |   23 ++++++++++++-----------
 net/sunrpc/xprt.c           |    8 ++++++++
 3 files changed, 21 insertions(+), 11 deletions(-)

applies-to: f2c506b1dec60259ab9d6cfd0b092433cf91774f
5e5ce5be6f0161d2a069a4f8a1154fe639c5c02f
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 99cad3e..068e1fb 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -211,6 +211,7 @@ int			xprt_reserve_xprt(struct rpc_task 
 int			xprt_reserve_xprt_cong(struct rpc_task *task);
 int			xprt_prepare_transmit(struct rpc_task *task);
 void			xprt_transmit(struct rpc_task *task);
+void			xprt_abort_transmit(struct rpc_task *task);
 int			xprt_adjust_timeout(struct rpc_rqst *req);
 void			xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task);
 void			xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task);
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index a5f7029..5342740 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -678,13 +678,11 @@ call_allocate(struct rpc_task *task)
 static void
 call_encode(struct rpc_task *task)
 {
-	struct rpc_clnt	*clnt = task->tk_client;
 	struct rpc_rqst	*req = task->tk_rqstp;
 	struct xdr_buf *sndbuf = &req->rq_snd_buf;
 	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
 	unsigned int	bufsiz;
 	kxdrproc_t	encode;
-	int		status;
 	u32		*p;
 
 	dprintk("RPC: %4d call_encode (status %d)\n", 
@@ -712,12 +710,9 @@ call_encode(struct rpc_task *task)
 		rpc_exit(task, -EIO);
 		return;
 	}
-	if (encode && (status = rpcauth_wrap_req(task, encode, req, p,
-						 task->tk_msg.rpc_argp)) < 0) {
-		printk(KERN_WARNING "%s: can't encode arguments: %d\n",
-				clnt->cl_protname, -status);
-		rpc_exit(task, status);
-	}
+	if (encode != NULL)
+		task->tk_status = rpcauth_wrap_req(task, encode, req, p,
+				task->tk_msg.rpc_argp);
 }
 
 /*
@@ -865,10 +860,12 @@ call_transmit(struct rpc_task *task)
 	if (task->tk_status != 0)
 		return;
 	/* Encode here so that rpcsec_gss can use correct sequence number. */
-	if (!task->tk_rqstp->rq_bytes_sent)
+	if (task->tk_rqstp->rq_bytes_sent == 0) {
 		call_encode(task);
-	if (task->tk_status < 0)
-		return;
+		/* Did the encode result in an error condition? */
+		if (task->tk_status != 0)
+			goto out_nosend;
+	}
 	xprt_transmit(task);
 	if (task->tk_status < 0)
 		return;
@@ -876,6 +873,10 @@ call_transmit(struct rpc_task *task)
 		task->tk_action = NULL;
 		rpc_wake_up_task(task);
 	}
+	return;
+out_nosend:
+	/* release socket write lock before attempting to handle error */
+	xprt_abort_transmit(task);
 }
 
 /*
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 215be0d..1ba55dc 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -709,6 +709,14 @@ out_unlock:
 	return err;
 }
 
+void
+xprt_abort_transmit(struct rpc_task *task)
+{
+	struct rpc_xprt	*xprt = task->tk_xprt;
+
+	xprt_release_write(xprt, task);
+}
+
 /**
  * xprt_transmit - send an RPC request on a transport
  * @task: controlling RPC task
---
0.99.8.GIT


--- NEW FILE 0563-ieee80211-division-by-zero-fix.txt ---
Subject: [PATCH] ieee80211: division by zero fix
From: Jiri Benc <jbenc suse cz>
Date: 1128964613 +0200

This fixes division by zero bug in ieee80211_wx_get_scan().

Signed-off-by: Jiri Benc <jbenc suse cz>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 net/ieee80211/ieee80211_wx.c |   21 ++++++++++++---------
 1 files changed, 12 insertions(+), 9 deletions(-)

applies-to: ea27df5ab7b728496a15602e0a7da74ff188378f
757d18faee58aa4c43bcaf9a44decf17fa68adeb
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index ee7a70a..1ce7af9 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -152,15 +152,18 @@ static inline char *ipw2100_translate_sc
 		iwe.u.qual.level = 0;
 	} else {
 		iwe.u.qual.level = network->stats.rssi;
-		iwe.u.qual.qual =
-		    (100 *
-		     (ieee->perfect_rssi - ieee->worst_rssi) *
-		     (ieee->perfect_rssi - ieee->worst_rssi) -
-		     (ieee->perfect_rssi - network->stats.rssi) *
-		     (15 * (ieee->perfect_rssi - ieee->worst_rssi) +
-		      62 * (ieee->perfect_rssi - network->stats.rssi))) /
-		    ((ieee->perfect_rssi - ieee->worst_rssi) *
-		     (ieee->perfect_rssi - ieee->worst_rssi));
+		if (ieee->perfect_rssi == ieee->worst_rssi)
+			iwe.u.qual.qual = 100;
+		else
+			iwe.u.qual.qual =
+			    (100 *
+			     (ieee->perfect_rssi - ieee->worst_rssi) *
+			     (ieee->perfect_rssi - ieee->worst_rssi) -
+			     (ieee->perfect_rssi - network->stats.rssi) *
+			     (15 * (ieee->perfect_rssi - ieee->worst_rssi) +
+			      62 * (ieee->perfect_rssi - network->stats.rssi))) /
+			    ((ieee->perfect_rssi - ieee->worst_rssi) *
+			     (ieee->perfect_rssi - ieee->worst_rssi));
 		if (iwe.u.qual.qual > 100)
 			iwe.u.qual.qual = 100;
 		else if (iwe.u.qual.qual < 1)
---
0.99.8.GIT


--- NEW FILE 0576-mipsnet-Virtual-ethernet-driver-for-MIPSsim.txt ---
Subject: [PATCH] mipsnet: Virtual ethernet driver for MIPSsim.
From: Ralf Baechle <ralf linux-mips org>
Date: 1128952287 +0100

Signed-off-by: Ralf Baechle <ralf linux-mips org>

 drivers/net/Kconfig   |    8 +
 drivers/net/Makefile  |    1
 drivers/net/mipsnet.c |  371 ++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/mipsnet.h |  127 +++++++++++++++++
 4 files changed, 507 insertions(+)
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 drivers/net/Kconfig   |    8 +
 drivers/net/Makefile  |    1 
 drivers/net/mipsnet.c |  371 +++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/mipsnet.h |  127 +++++++++++++++++
 4 files changed, 507 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/mipsnet.c
 create mode 100644 drivers/net/mipsnet.h

applies-to: 133c9a5830efd71f28c0e2ae544533e17e350624
dcbf8477567c312c9f0512545d07e05175d740a4
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 0a30368..5148d47 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -475,6 +475,14 @@ config SGI_IOC3_ETH_HW_TX_CSUM
 	  the moment only acceleration of IPv4 is supported.  This option
 	  enables offloading for checksums on transmit.  If unsure, say Y.
 
+config MIPS_SIM_NET
+	tristate "MIPS simulator Network device (EXPERIMENTAL)"
+	depends on NETDEVICES && MIPS_SIM && EXPERIMENTAL
+	help
+	  The MIPSNET device is a simple Ethernet network device which is
+	  emulated by the MIPS Simulator.
+	  If you are not using a MIPSsim or are unsure, say N.
+
 config SGI_O2MACE_ETH
 	tristate "SGI O2 MACE Fast Ethernet support"
 	depends on NET_ETHERNET && SGI_IP32=y
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 4c9477c..1a84e04 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -167,6 +167,7 @@ obj-$(CONFIG_EQUALIZER) += eql.o
 obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o
 obj-$(CONFIG_MIPS_GT96100ETH) += gt96100eth.o
 obj-$(CONFIG_MIPS_AU1X00_ENET) += au1000_eth.o
+obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o
 obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o
 obj-$(CONFIG_DECLANCE) += declance.o
 obj-$(CONFIG_ATARILANCE) += atarilance.o
diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c
new file mode 100644
index 0000000..f79f7ee
--- /dev/null
+++ b/drivers/net/mipsnet.c
@@ -0,0 +1,371 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#define DEBUG
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/sched.h>
+#include <linux/etherdevice.h>
+#include <linux/netdevice.h>
+#include <asm/io.h>
+#include <asm/mips-boards/simint.h>
+
+#include "mipsnet.h"		/* actual device IO mapping */
+
+#define MIPSNET_VERSION "2005-06-20"
+
+#define mipsnet_reg_address(dev, field) (dev->base_addr + field_offset(field))
+
+struct mipsnet_priv {
+	struct net_device_stats stats;
+};
+
+static struct platform_device *mips_plat_dev;
+
+static char mipsnet_string[] = "mipsnet";
+
+/*
+ * Copy data from the MIPSNET rx data port
+ */
+static int ioiocpy_frommipsnet(struct net_device *dev, unsigned char *kdata,
+			int len)
+{
+	uint32_t available_len = inl(mipsnet_reg_address(dev, rxDataCount));
+	if (available_len < len)
+		return -EFAULT;
+
+	for (; len > 0; len--, kdata++) {
+		*kdata = inb(mipsnet_reg_address(dev, rxDataBuffer));
+	}
+
+	return inl(mipsnet_reg_address(dev, rxDataCount));
+}
+
+static inline ssize_t mipsnet_put_todevice(struct net_device *dev,
+	struct sk_buff *skb)
+{
+	int count_to_go = skb->len;
+	char *buf_ptr = skb->data;
+	struct mipsnet_priv *mp = netdev_priv(dev);
+
+	pr_debug("%s: %s(): telling MIPSNET txDataCount(%d)\n",
+	         dev->name, __FUNCTION__, skb->len);
+
+	outl(skb->len, mipsnet_reg_address(dev, txDataCount));
+
+	pr_debug("%s: %s(): sending data to MIPSNET txDataBuffer(%d)\n",
+	         dev->name, __FUNCTION__, skb->len);
+
+	for (; count_to_go; buf_ptr++, count_to_go--) {
+		outb(*buf_ptr, mipsnet_reg_address(dev, txDataBuffer));
+	}
+
+	mp->stats.tx_packets++;
+	mp->stats.tx_bytes += skb->len;
+
+	return skb->len;
+}
+
+static int mipsnet_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	pr_debug("%s:%s(): transmitting %d bytes\n",
+	         dev->name, __FUNCTION__, skb->len);
+
+	/* Only one packet at a time. Once TXDONE interrupt is serviced, the
+	 * queue will be restarted.
+	 */
+	netif_stop_queue(dev);
+	mipsnet_put_todevice(dev, skb);
+
+	return 0;
+}
+
+static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t count)
+{
+	struct sk_buff *skb;
+	size_t len = count;
+	struct mipsnet_priv *mp = netdev_priv(dev);
+
+	if (!(skb = alloc_skb(len + 2, GFP_KERNEL))) {
+		mp->stats.rx_dropped++;
+		return -ENOMEM;
+	}
+
+	skb_reserve(skb, 2);
+	if (ioiocpy_frommipsnet(dev, skb_put(skb, len), len))
+		return -EFAULT;
+
+	skb->dev = dev;
+	skb->protocol = eth_type_trans(skb, dev);
+	skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+	pr_debug("%s:%s(): pushing RXed data to kernel\n",
+	         dev->name, __FUNCTION__);
+	netif_rx(skb);
+
+	mp->stats.rx_packets++;
+	mp->stats.rx_bytes += len;
+
+	return count;
+}
+
+static irqreturn_t
+mipsnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = dev_id;
+
+	irqreturn_t retval = IRQ_NONE;
+	uint64_t interruptFlags;
+
+	if (irq == dev->irq) {
+		pr_debug("%s:%s(): irq %d for device\n",
+		         dev->name, __FUNCTION__, irq);
+
+		retval = IRQ_HANDLED;
+
+		interruptFlags =
+		    inl(mipsnet_reg_address(dev, interruptControl));
+		pr_debug("%s:%s(): intCtl=0x%016llx\n", dev->name,
+		         __FUNCTION__, interruptFlags);
+
+		if (interruptFlags & MIPSNET_INTCTL_TXDONE) {
+			pr_debug("%s:%s(): got TXDone\n",
+			         dev->name, __FUNCTION__);
+			outl(MIPSNET_INTCTL_TXDONE,
+			     mipsnet_reg_address(dev, interruptControl));
+			// only one packet at a time, we are done.
+			netif_wake_queue(dev);
+		} else if (interruptFlags & MIPSNET_INTCTL_RXDONE) {
+			pr_debug("%s:%s(): got RX data\n",
+			         dev->name, __FUNCTION__);
+			mipsnet_get_fromdev(dev,
+			            inl(mipsnet_reg_address(dev, rxDataCount)));
+			pr_debug("%s:%s(): clearing RX int\n",
+			         dev->name, __FUNCTION__);
+			outl(MIPSNET_INTCTL_RXDONE,
+			     mipsnet_reg_address(dev, interruptControl));
+
+		} else if (interruptFlags & MIPSNET_INTCTL_TESTBIT) {
+			pr_debug("%s:%s(): got test interrupt\n",
+			         dev->name, __FUNCTION__);
+			// TESTBIT is cleared on read.
+			//    And takes effect after a write with 0
+			outl(0, mipsnet_reg_address(dev, interruptControl));
+		} else {
+			pr_debug("%s:%s(): no valid fags 0x%016llx\n",
+			         dev->name, __FUNCTION__, interruptFlags);
+			// Maybe shared IRQ, just ignore, no clearing.
+			retval = IRQ_NONE;
+		}
+
+	} else {
+		printk(KERN_INFO "%s: %s(): irq %d for unknown device\n",
+		       dev->name, __FUNCTION__, irq);
+		retval = IRQ_NONE;
+	}
+	return retval;
+}				//mipsnet_interrupt()
+
+static int mipsnet_open(struct net_device *dev)
+{
+	int err;
+	pr_debug("%s: mipsnet_open\n", dev->name);
+
+	err = request_irq(dev->irq, &mipsnet_interrupt,
+			  SA_SHIRQ, dev->name, (void *) dev);
+
+	if (err) {
+		pr_debug("%s: %s(): can't get irq %d\n",
+		         dev->name, __FUNCTION__, dev->irq);
+		release_region(dev->base_addr, MIPSNET_IO_EXTENT);
+		return err;
+	}
+
+	pr_debug("%s: %s(): got IO region at 0x%04lx and irq %d for dev.\n",
+	         dev->name, __FUNCTION__, dev->base_addr, dev->irq);
+
+
+	netif_start_queue(dev);
+
+	// test interrupt handler
+	outl(MIPSNET_INTCTL_TESTBIT,
+	     mipsnet_reg_address(dev, interruptControl));
+
+
+	return 0;
+}
+
+static int mipsnet_close(struct net_device *dev)
+{
+	pr_debug("%s: %s()\n", dev->name, __FUNCTION__);
+	netif_stop_queue(dev);
+	return 0;
+}
+
+static struct net_device_stats *mipsnet_get_stats(struct net_device *dev)
+{
+	struct mipsnet_priv *mp = netdev_priv(dev);
+
+	return &mp->stats;
+}
+
+static void mipsnet_set_mclist(struct net_device *dev)
+{
+	// we don't do anything
+	return;
+}
+
+static int __init mipsnet_probe(struct device *dev)
+{
+	struct net_device *netdev;
+	int err;
+
+	netdev = alloc_etherdev(sizeof(struct mipsnet_priv));
+	if (!netdev) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	dev_set_drvdata(dev, netdev);
+
+	netdev->open			= mipsnet_open;
+	netdev->stop			= mipsnet_close;
+	netdev->hard_start_xmit		= mipsnet_xmit;
+	netdev->get_stats		= mipsnet_get_stats;
+	netdev->set_multicast_list	= mipsnet_set_mclist;
+
+	/*
+	 * TODO: probe for these or load them from PARAM
+	 */
+	netdev->base_addr = 0x4200;
+	netdev->irq = MIPSCPU_INT_BASE + MIPSCPU_INT_MB0 +
+	              inl(mipsnet_reg_address(netdev, interruptInfo));
+
+	// Get the io region now, get irq on open()
+	if (!request_region(netdev->base_addr, MIPSNET_IO_EXTENT, "mipsnet")) {
+		pr_debug("%s: %s(): IO region {start: 0x%04lux, len: %d} "
+		         "for dev is not availble.\n", netdev->name,
+		         __FUNCTION__, netdev->base_addr, MIPSNET_IO_EXTENT);
+		err = -EBUSY;
+		goto out_free_netdev;
+	}
+
+	/*
+	 * Lacking any better mechanism to allocate a MAC address we use a
+	 * random one ...
+	 */
+	random_ether_addr(netdev->dev_addr);
+
+	err = register_netdev(netdev);
+	if (err) {
+		printk(KERN_ERR "MIPSNet: failed to register netdev.\n");
+		goto out_free_region;
+	}
+
+	return 0;
+
+out_free_region:
+	release_region(netdev->base_addr, MIPSNET_IO_EXTENT);
+
+out_free_netdev:
+	free_netdev(netdev);
+
+out:
+	return err;
+}
+
+static int __devexit mipsnet_device_remove(struct device *device)
+{
+	struct net_device *dev = dev_get_drvdata(device);
+
+	unregister_netdev(dev);
+	release_region(dev->base_addr, MIPSNET_IO_EXTENT);
+	free_netdev(dev);
+	dev_set_drvdata(device, NULL);
+
+	return 0;
+}
+
+static struct device_driver mipsnet_driver = {
+	.name	= mipsnet_string,
+	.bus	= &platform_bus_type,
+	.probe	= mipsnet_probe,
+	.remove	= __devexit_p(mipsnet_device_remove),
+};
+
+static void mipsnet_platform_release(struct device *device)
+{
+	struct platform_device *pldev;
+
+	/* free device */
+	pldev = to_platform_device(device);
+	kfree(pldev);
+}
+
+static int __init mipsnet_init_module(void)
+{
+	struct platform_device *pldev;
+	int err;
+
+	printk(KERN_INFO "MIPSNet Ethernet driver. Version: %s. "
+	       "(c)2005 MIPS Technologies, Inc.\n", MIPSNET_VERSION);
+
+	if (driver_register(&mipsnet_driver)) {
+		printk(KERN_ERR "Driver registration failed\n");
+		err = -ENODEV;
+		goto out;
+	}
+
+        if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto out_unregister_driver;
+	}
+
+	memset (pldev, 0, sizeof (*pldev));
+	pldev->name		= mipsnet_string;
+	pldev->id		= 0;
+	pldev->dev.release	= mipsnet_platform_release;
+
+	if (platform_device_register(pldev)) {
+		err = -ENODEV;
+		goto out_free_pldev;
+	}
+
+        if (!pldev->dev.driver) {
+		/*
+		 * The driver was not bound to this device, there was
+                 * no hardware at this address. Unregister it, as the
+		 * release fuction will take care of freeing the
+		 * allocated structure
+		 */
+		platform_device_unregister (pldev);
+	}
+
+	mips_plat_dev		= pldev;
+
+	return 0;
+
+out_free_pldev:
+	kfree(pldev);
+
+out_unregister_driver:
+	driver_unregister(&mipsnet_driver);
+out:
+	return err;
+}
+
+static void __exit mipsnet_exit_module(void)
+{
+	pr_debug("MIPSNet Ethernet driver exiting\n");
+
+	driver_unregister(&mipsnet_driver);
+}
+
+module_init(mipsnet_init_module);
+module_exit(mipsnet_exit_module);
diff --git a/drivers/net/mipsnet.h b/drivers/net/mipsnet.h
new file mode 100644
index 0000000..8785359
--- /dev/null
+++ b/drivers/net/mipsnet.h
@@ -0,0 +1,127 @@
+//
+// <COPYRIGHT CLASS="1B" YEAR="2005">
+// Unpublished work (c) MIPS Technologies, Inc.  All rights reserved.
+// Unpublished rights reserved under the copyright laws of the U.S.A. and
+//  other countries.
+//
+// PROPRIETARY / SECRET CONFIDENTIAL INFORMATION OF MIPS TECHNOLOGIES, INC.
+// FOR INTERNAL USE ONLY.
+//
+// Under no circumstances (contract or otherwise) may this information be
+// disclosed to, or copied, modified or used by anyone other than employees
+// or contractors of MIPS Technologies having a need to know.
+// </COPYRIGHT>
+//
+//++
+// File: MIPS_Net.h
+//
+// Description:
+//   The definition of the emulated MIPSNET device's interface.
+//
+// Notes: This include file needs to work from a Linux device drivers.
+//
+//--
+//
+
+#ifndef __MIPSNET_H
+#define __MIPSNET_H
+
+/*
+ *  Id of this Net device, as seen by the core.
+ */
+#define MIPS_NET_DEV_ID ((uint64_t)           \
+	                     ((uint64_t)'M'<< 0)| \
+	                     ((uint64_t)'I'<< 8)| \
+	                     ((uint64_t)'P'<<16)| \
+	                     ((uint64_t)'S'<<24)| \
+	                     ((uint64_t)'N'<<32)| \
+	                     ((uint64_t)'E'<<40)| \
+	                     ((uint64_t)'T'<<48)| \
+	                     ((uint64_t)'0'<<56))
+
+/*
+ * Net status/control block as seen by sw in the core.
+ * (Why not use bit fields? can't be bothered with cross-platform struct
+ *  packing.)
+ */
+typedef struct _net_control_block {
+	/// dev info for probing
+	///  reads as MIPSNET%d where %d is some form of version
+	uint64_t devId;		/*0x00 */
+
+	/*
+	 * read only busy flag.
+	 * Set and cleared by the Net Device to indicate that an rx or a tx
+	 * is in progress.
+	 */
+	uint32_t busy;		/*0x08 */
+
+	/*
+	 * Set by the Net Device.
+	 * The device will set it once data has been received.
+	 * The value is the number of bytes that should be read from
+	 * rxDataBuffer.  The value will decrease till 0 until all the data
+	 * from rxDataBuffer has been read.
+	 */
+	uint32_t rxDataCount;	/*0x0c */
+#define MIPSNET_MAX_RXTX_DATACOUNT (1<<16)
+
+	/*
+	 * Settable from the MIPS core, cleared by the Net Device.
+	 * The core should set the number of bytes it wants to send,
+	 *   then it should write those bytes of data to txDataBuffer.
+	 * The device will clear txDataCount has been processed (not necessarily sent).
+	 */
+	uint32_t txDataCount;	/*0x10 */
+
+	/*
+	 * Interrupt control
+	 *
+	 * Used to clear the interrupted generated by this dev.
+	 * Write a 1 to clear the interrupt. (except bit31).
+	 *
+	 * Bit0 is set if it was a tx-done interrupt.
+	 * Bit1 is set when new rx-data is available.
+	 *      Until this bit is cleared there will be no other RXs.
+	 *
+	 * Bit31 is used for testing, it clears after a read.
+	 *    Writing 1 to this bit will cause an interrupt to be generated.
+	 *    To clear the test interrupt, write 0 to this register.
+	 */
+	uint32_t interruptControl;	/*0x14 */
+#define MIPSNET_INTCTL_TXDONE     ((uint32_t)(1<< 0))
+#define MIPSNET_INTCTL_RXDONE     ((uint32_t)(1<< 1))
+#define MIPSNET_INTCTL_TESTBIT    ((uint32_t)(1<<31))
+#define MIPSNET_INTCTL_ALLSOURCES (MIPSNET_INTCTL_TXDONE|MIPSNET_INTCTL_RXDONE|MIPSNET_INTCTL_TESTBIT)
+
+	/*
+	 * Readonly core-specific interrupt info for the device to signal the core.
+	 * The meaning of the contents of this field might change.
+	 */
+	/*###\todo: the whole memIntf interrupt scheme is messy: the device should have
+	 *  no control what so ever of what VPE/register set is being used.
+	 *  The MemIntf should only expose interrupt lines, and something in the
+	 *  config should be responsible for the line<->core/vpe bindings.
+	 */
+	uint32_t interruptInfo;	/*0x18 */
+
+	/*
+	 *  This is where the received data is read out.
+	 *  There is more data to read until rxDataReady is 0.
+	 *  Only 1 byte at this regs offset is used.
+	 */
+	uint32_t rxDataBuffer;	/*0x1c */
+
+	/*
+	 * This is where the data to transmit is written.
+	 * Data should be written for the amount specified in the txDataCount register.
+	 *  Only 1 byte at this regs offset is used.
+	 */
+	uint32_t txDataBuffer;	/*0x20 */
+} MIPS_T_NetControl;
+
+#define MIPSNET_IO_EXTENT 0x40	/* being generous */
+
+#define field_offset(field) ((int)&((MIPS_T_NetControl*)(0))->field)
+
+#endif /* __MIPSNET_H */
---
0.99.8.GIT


--- NEW FILE 0584-bonding-cleanup-comment-for-mode-1-IGMP-xmit-hack.txt ---
Subject: [PATCH] bonding: cleanup comment for mode 1 IGMP xmit hack
From: John W. Linville <linville tuxdriver com>
Date: 1129685458 -0400

Expand comment explaining MAC address selection for replicated IGMP
frames transmitted in bonding mode 1 (active-backup).  Also, a small
whitespace cleanup.

Signed-off-by: John W. Linville <linville tuxdriver com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 drivers/net/bonding/bond_main.c |   10 +++++++---
 1 files changed, 7 insertions(+), 3 deletions(-)

applies-to: 03f977ac534403468a670140c0c05085fa95844f
df49898a47061e82219c991dfbe9ac6ddf7a866b
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 58c4e36..8032126 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -4242,8 +4242,8 @@ out:
 }
 
 static void bond_activebackup_xmit_copy(struct sk_buff *skb,
-                                         struct bonding *bond,
-                                         struct slave *slave)
+                                        struct bonding *bond,
+                                        struct slave *slave)
 {
 	struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
 	struct ethhdr *eth_data;
@@ -4259,7 +4259,11 @@ static void bond_activebackup_xmit_copy(
 	skb2->mac.raw = (unsigned char *)skb2->data;
 	eth_data = eth_hdr(skb2);
 
-	/* Pick an appropriate source MAC address */
+	/* Pick an appropriate source MAC address
+	 *	-- use slave's perm MAC addr, unless used by bond
+	 *	-- otherwise, borrow active slave's perm MAC addr
+	 *	   since that will not be used
+	 */
 	hwaddr = slave->perm_hwaddr;
 	if (!memcmp(eth_data->h_source, hwaddr, ETH_ALEN))
 		hwaddr = bond->curr_active_slave->perm_hwaddr;
---
0.99.8.GIT


Index: 0586-orinoco-remove-redundance-skb-length-check-before-padding.txt
===================================================================
RCS file: 0586-orinoco-remove-redundance-skb-length-check-before-padding.txt
diff -N 0586-orinoco-remove-redundance-skb-length-check-before-padding.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 0586-orinoco-remove-redundance-skb-length-check-before-padding.txt	11 Nov 2005 18:29:01 -0000	1.1.2.3
@@ -0,0 +1,37 @@
+Subject: [PATCH] orinoco: remove redundance skb length check before padding
+From: John W. Linville <linville tuxdriver com>
+Date: 1129685458 -0400
+
+Checking the skb->len value before calling skb_padto is redundant.
+
+Signed-off-by: John W. Linville <linville tuxdriver com>
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/orinoco.c |    8 +++-----
+ 1 files changed, 3 insertions(+), 5 deletions(-)
+
+applies-to: 52a0d64efd7a0f814dd327f2bd983a5c8260b1be
+36841c9d02870983c2b08c85d56572c1ff011997
+diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
+index da4c5e9..5db2bba 100644
+--- a/drivers/net/wireless/orinoco.c
++++ b/drivers/net/wireless/orinoco.c
+@@ -492,11 +492,9 @@ static int orinoco_xmit(struct sk_buff *
+ 
+ 	/* Check packet length, pad short packets, round up odd length */
+ 	len = max_t(int, ALIGN(skb->len, 2), ETH_ZLEN);
+-	if (skb->len < len) {
+-		skb = skb_padto(skb, len);
+-		if (skb == NULL)
+-			goto fail;
+-	}
++	skb = skb_padto(skb, len);
++	if (skb == NULL)
++		goto fail;
+ 	len -= ETH_HLEN;
+ 
+ 	eh = (struct ethhdr *)skb->data;
+---
+0.99.8.GIT


--- NEW FILE 0591-RPC-stops-the-release_pipe-funtion-from-being-called-twice.txt ---
Subject: [PATCH] RPC: stops the release_pipe() funtion from being called twice
From: Steve Dickson <steved redhat com>
Date: 1129702780 -0700

 This patch stops the release_pipe() funtion from being called
 twice by invalidating the ops pointer in the rpc_inode
 when rpc_pipe_release() is called.

 Signed-off-by: Steve Dickson <steved redhat com>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 net/sunrpc/rpc_pipe.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

applies-to: fde5f4b4918205ba4c547ecaac95acbc8a37caa0
747c5534c9a6da4aa87e7cdc2209ea98ea27f381
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index ded6c63..649d609 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -177,6 +177,8 @@ rpc_pipe_release(struct inode *inode, st
 		__rpc_purge_upcall(inode, -EPIPE);
 	if (rpci->ops->release_pipe)
 		rpci->ops->release_pipe(inode);
+	if (!rpci->nreaders && !rpci->nwriters)
+		rpci->ops = NULL;
 out:
 	up(&inode->i_sem);
 	return 0;
---
0.99.8.GIT


--- NEW FILE 0594-SUNRPC-Add-support-for-privacy-to-generic-gss-api-code.txt ---
Subject: [PATCH] SUNRPC: Add support for privacy to generic gss-api code.
From: J. Bruce Fields <bfields fieldses org>
Date: 1129236877 -0400

 Add support for privacy to generic gss-api code.  This is dead code until we
 have both a mechanism that supports privacy and code in the client or server
 that uses it.

 Signed-off-by: J. Bruce Fields <bfields citi umich edu>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/gss_api.h        |   22 ++++++++++++++++++++++
 net/sunrpc/auth_gss/gss_mech_switch.c |   22 ++++++++++++++++++++++
 2 files changed, 44 insertions(+), 0 deletions(-)

applies-to: b0b0a667cf9ecccabc26cd7afceed05815066aa6
293f1eb551a77fe5c8956a559a3c0baea95cd9bc
diff --git a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h
index 689262f..e896752 100644
--- a/include/linux/sunrpc/gss_api.h
+++ b/include/linux/sunrpc/gss_api.h
@@ -48,6 +48,17 @@ u32 gss_verify_mic(
 		struct xdr_buf		*message,
 		struct xdr_netobj	*mic_token,
 		u32			*qstate);
+u32 gss_wrap(
+		struct gss_ctx		*ctx_id,
+		u32			qop,
+		int			offset,
+		struct xdr_buf		*outbuf,
+		struct page		**inpages);
+u32 gss_unwrap(
+		struct gss_ctx		*ctx_id,
+		u32			*qop,
+		int			offset,
+		struct xdr_buf		*inbuf);
 u32 gss_delete_sec_context(
 		struct gss_ctx		**ctx_id);
 
@@ -93,6 +104,17 @@ struct gss_api_ops {
 			struct xdr_buf		*message,
 			struct xdr_netobj	*mic_token,
 			u32			*qstate);
+	u32 (*gss_wrap)(
+			struct gss_ctx		*ctx_id,
+			u32			qop,
+			int			offset,
+			struct xdr_buf		*outbuf,
+			struct page		**inpages);
+	u32 (*gss_unwrap)(
+			struct gss_ctx		*ctx_id,
+			u32			*qop,
+			int			offset,
+			struct xdr_buf		*buf);
 	void (*gss_delete_sec_context)(
 			void			*internal_ctx_id);
 };
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
index 58aeadd..06d97cb 100644
--- a/net/sunrpc/auth_gss/gss_mech_switch.c
+++ b/net/sunrpc/auth_gss/gss_mech_switch.c
@@ -276,6 +276,28 @@ gss_verify_mic(struct gss_ctx		*context_
 				 qstate);
 }
 
+u32
+gss_wrap(struct gss_ctx	*ctx_id,
+	 u32		qop,
+	 int		offset,
+	 struct xdr_buf	*buf,
+	 struct page	**inpages)
+{
+	return ctx_id->mech_type->gm_ops
+		->gss_wrap(ctx_id, qop, offset, buf, inpages);
+}
+
+u32
+gss_unwrap(struct gss_ctx	*ctx_id,
+	   u32			*qop,
+	   int			offset,
+	   struct xdr_buf	*buf)
+{
+	return ctx_id->mech_type->gm_ops
+		->gss_unwrap(ctx_id, qop, offset, buf);
+}
+
+
 /* gss_delete_sec_context: free all resources associated with context_handle.
  * Note this differs from the RFC 2744-specified prototype in that we don't
  * bother returning an output token, since it would never be used anyway. */
---
0.99.8.GIT


--- NEW FILE 0595-SUNRPC-Provide-a-callback-to-allow-free-pages-allocated-during-xdr-encoding.txt ---
Subject: [PATCH] SUNRPC: Provide a callback to allow free pages allocated during xdr encoding
From: J. Bruce Fields <bfields fieldses org>
Date: 1129236883 -0400

 For privacy, we need to allocate pages to store the encrypted data (passed
 in pages can't be used without the risk of corrupting data in the page cache).
 So we need a way to free that memory after the request has been transmitted.

 Signed-off-by: J. Bruce Fields <bfields citi umich edu>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/xprt.h |    5 ++++-
 net/sunrpc/xprt.c           |    3 +++
 2 files changed, 7 insertions(+), 1 deletions(-)

applies-to: 03c770935eb42f6deccb275be0326d2f4b17c80c
ead5e1c26fdcd969cf40c49cb0589d56879d240d
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 068e1fb..3b8b6e8 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -73,7 +73,10 @@ struct rpc_rqst {
 	int			rq_cong;	/* has incremented xprt->cong */
 	int			rq_received;	/* receive completed */
 	u32			rq_seqno;	/* gss seq no. used on req. */
-
+	int			rq_enc_pages_num;
+	struct page		**rq_enc_pages;	/* scratch pages for use by
+						   gss privacy code */
+	void (*rq_release_snd_buf)(struct rpc_rqst *); /* release rq_enc_pages */
 	struct list_head	rq_list;
 
 	struct xdr_buf		rq_private_buf;		/* The receive buffer
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 1ba55dc..6dda386 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -839,6 +839,7 @@ static void xprt_request_init(struct rpc
 	req->rq_task	= task;
 	req->rq_xprt    = xprt;
 	req->rq_xid     = xprt_alloc_xid(xprt);
+	req->rq_release_snd_buf = NULL;
 	dprintk("RPC: %4d reserved req %p xid %08x\n", task->tk_pid,
 			req, ntohl(req->rq_xid));
 }
@@ -867,6 +868,8 @@ void xprt_release(struct rpc_task *task)
 				xprt->last_used + xprt->idle_timeout);
 	spin_unlock_bh(&xprt->transport_lock);
 	task->tk_rqstp = NULL;
+	if (req->rq_release_snd_buf)
+		req->rq_release_snd_buf(req);
 	memset(req, 0, sizeof(*req));	/* mark unused */
 
 	dprintk("RPC: %4d release request %p\n", task->tk_pid, req);
---
0.99.8.GIT


--- NEW FILE 0596-SUNRPC-Retry-wrap-in-case-of-memory-allocation-failure.txt ---
Subject: [PATCH] SUNRPC: Retry wrap in case of memory allocation failure.
From: J. Bruce Fields <bfields fieldses org>
Date: 1129236888 -0400

 For privacy we need to allocate extra pages to hold encrypted page data when
 wrapping requests.  This allocation may fail, and we handle that case by
 waiting and retrying.

 Signed-off-by: J. Bruce Fields <bfields citi umich edu>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 net/sunrpc/clnt.c |   13 ++++++++++---
 1 files changed, 10 insertions(+), 3 deletions(-)

applies-to: af0e04aed32eac60b35c987b933dbc132f0e780b
f3680312a737355ddf35c1b68af25e384d7ef0a8
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 5342740..702ede3 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -710,9 +710,16 @@ call_encode(struct rpc_task *task)
 		rpc_exit(task, -EIO);
 		return;
 	}
-	if (encode != NULL)
-		task->tk_status = rpcauth_wrap_req(task, encode, req, p,
-				task->tk_msg.rpc_argp);
+	if (encode == NULL)
+		return;
+
+	task->tk_status = rpcauth_wrap_req(task, encode, req, p,
+			task->tk_msg.rpc_argp);
+	if (task->tk_status == -ENOMEM) {
+		/* XXX: Is this sane? */
+		rpc_delay(task, 3*HZ);
+		task->tk_status = -EAGAIN;
+	}
 }
 
 /*
---
0.99.8.GIT


--- NEW FILE 0597-RPCSEC_GSS-cleanup-au_rslack-calculation.txt ---
Subject: [PATCH] RPCSEC_GSS: cleanup au_rslack calculation
From: J. Bruce Fields <bfields fieldses org>
Date: 1129236893 -0400

 Various xdr encode routines use au_rslack to guess where the reply argument
 will end up, so we can set up the xdr_buf to recieve data into the right place
 for zero copy.

 Currently we calculate the au_rslack estimate when we check the verifier.
 Normally this only depends on the verifier size.  In the integrity case we add
 a few bytes to allow for a length and sequence number.

 It's a bit simpler to calculate only the verifier size when we check the
 verifier, and delay the full calculation till we unwrap.

 Signed-off-by: J. Bruce Fields <bfields citi umich edu>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/auth.h    |    7 ++++++-
 net/sunrpc/auth_gss/auth_gss.c |   20 ++++++--------------
 2 files changed, 12 insertions(+), 15 deletions(-)

applies-to: 6b447f0a58bf1c1acfa8b1731ef06580d275b983
24b2605becc10ca63c4c30808fa59a8abbf68727
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index 04ebc24..b68c11a 100644
--- a/include/linux/sunrpc/auth.h
+++ b/include/linux/sunrpc/auth.h
@@ -66,7 +66,12 @@ struct rpc_cred_cache {
 
 struct rpc_auth {
 	unsigned int		au_cslack;	/* call cred size estimate */
-	unsigned int		au_rslack;	/* reply verf size guess */
+				/* guess at number of u32's auth adds before
+				 * reply data; normally the verifier size: */
+	unsigned int		au_rslack;
+				/* for gss, used to calculate au_rslack: */
+	unsigned int		au_verfsize;
+
 	unsigned int		au_flags;	/* various flags */
 	struct rpc_authops *	au_ops;		/* operations */
 	rpc_authflavor_t	au_flavor;	/* pseudoflavor (note may
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index d2b08f1..dc95b79 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -886,8 +886,6 @@ static u32 *
 gss_validate(struct rpc_task *task, u32 *p)
 {
 	struct rpc_cred *cred = task->tk_msg.rpc_cred;
-	struct gss_cred	*gss_cred = container_of(cred, struct gss_cred,
-						gc_base);
 	struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
 	u32		seq, qop_state;
 	struct kvec	iov;
@@ -915,18 +913,9 @@ gss_validate(struct rpc_task *task, u32 
 		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
 	if (maj_stat)
 		goto out_bad;
-       switch (gss_cred->gc_service) {
-       case RPC_GSS_SVC_NONE:
-	       /* verifier data, flavor, length: */
-	       task->tk_auth->au_rslack = XDR_QUADLEN(len) + 2;
-	       break;
-       case RPC_GSS_SVC_INTEGRITY:
-	       /* verifier data, flavor, length, length, sequence number: */
-	       task->tk_auth->au_rslack = XDR_QUADLEN(len) + 4;
-	       break;
-       case RPC_GSS_SVC_PRIVACY:
-	       goto out_bad;
-       }
+	/* We leave it to unwrap to calculate au_rslack. For now we just
+	 * calculate the length of the verifier: */
+	task->tk_auth->au_verfsize = XDR_QUADLEN(len) + 2;
 	gss_put_ctx(ctx);
 	dprintk("RPC: %4u GSS gss_validate: gss_verify_mic succeeded.\n",
 			task->tk_pid);
@@ -1067,6 +1056,7 @@ gss_unwrap_resp(struct rpc_task *task,
 	struct gss_cred *gss_cred = container_of(cred, struct gss_cred,
 			gc_base);
 	struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
+	u32		*savedp = p;
 	int             status = -EIO;
 
 	if (ctx->gc_proc != RPC_GSS_PROC_DATA)
@@ -1082,6 +1072,8 @@ gss_unwrap_resp(struct rpc_task *task,
        		case RPC_GSS_SVC_PRIVACY:
 			break;
 	}
+	/* take into account extra slack for integrity and privacy cases: */
+	task->tk_auth->au_rslack = task->tk_auth->au_verfsize + (p - savedp);
 out_decode:
 	status = decode(rqstp, p, obj);
 out:
---
0.99.8.GIT


--- NEW FILE 0598-RPCSEC_GSS-client-side-privacy-support.txt ---
Subject: [PATCH] RPCSEC_GSS: client-side privacy support
From: J. Bruce Fields <bfields fieldses org>
Date: 1129236898 -0400

 Add the code to the client side to handle privacy.  This is dead code until
 we actually add privacy support to krb5.

 Signed-off-by: J. Bruce Fields <bfields citi umich edu>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 net/sunrpc/auth_gss/auth_gss.c |  149 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 148 insertions(+), 1 deletions(-)

applies-to: 64634bf6a5427f9a7253c9cb5b4d55550ef8b18d
2d2da60c63b67174add32f06e8d54c3a0c5cd9cf
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index dc95b79..5e48720 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -43,6 +43,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
+#include <linux/pagemap.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/auth.h>
 #include <linux/sunrpc/auth_gss.h>
@@ -975,6 +976,114 @@ gss_wrap_req_integ(struct rpc_cred *cred
 	return 0;
 }
 
+static void
+priv_release_snd_buf(struct rpc_rqst *rqstp)
+{
+	int i;
+
+	for (i=0; i < rqstp->rq_enc_pages_num; i++)
+		__free_page(rqstp->rq_enc_pages[i]);
+	kfree(rqstp->rq_enc_pages);
+}
+
+static int
+alloc_enc_pages(struct rpc_rqst *rqstp)
+{
+	struct xdr_buf *snd_buf = &rqstp->rq_snd_buf;
+	int first, last, i;
+
+	if (snd_buf->page_len == 0) {
+		rqstp->rq_enc_pages_num = 0;
+		return 0;
+	}
+
+	first = snd_buf->page_base >> PAGE_CACHE_SHIFT;
+	last = (snd_buf->page_base + snd_buf->page_len - 1) >> PAGE_CACHE_SHIFT;
+	rqstp->rq_enc_pages_num = last - first + 1 + 1;
+	rqstp->rq_enc_pages
+		= kmalloc(rqstp->rq_enc_pages_num * sizeof(struct page *),
+				GFP_NOFS);
+	if (!rqstp->rq_enc_pages)
+		goto out;
+	for (i=0; i < rqstp->rq_enc_pages_num; i++) {
+		rqstp->rq_enc_pages[i] = alloc_page(GFP_NOFS);
+		if (rqstp->rq_enc_pages[i] == NULL)
+			goto out_free;
+	}
+	rqstp->rq_release_snd_buf = priv_release_snd_buf;
+	return 0;
+out_free:
+	for (i--; i >= 0; i--) {
+		__free_page(rqstp->rq_enc_pages[i]);
+	}
+out:
+	return -EAGAIN;
+}
+
+static inline int
+gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
+		kxdrproc_t encode, struct rpc_rqst *rqstp, u32 *p, void *obj)
+{
+	struct xdr_buf	*snd_buf = &rqstp->rq_snd_buf;
+	u32		offset;
+	u32             maj_stat;
+	int		status;
+	u32		*opaque_len;
+	struct page	**inpages;
+	int		first;
+	int		pad;
+	struct kvec	*iov;
+	char		*tmp;
+
+	opaque_len = p++;
+	offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base;
+	*p++ = htonl(rqstp->rq_seqno);
+
+	status = encode(rqstp, p, obj);
+	if (status)
+		return status;
+
+	status = alloc_enc_pages(rqstp);
+	if (status)
+		return status;
+	first = snd_buf->page_base >> PAGE_CACHE_SHIFT;
+	inpages = snd_buf->pages + first;
+	snd_buf->pages = rqstp->rq_enc_pages;
+	snd_buf->page_base -= first << PAGE_CACHE_SHIFT;
+	/* Give the tail its own page, in case we need extra space in the
+	 * head when wrapping: */
+	if (snd_buf->page_len || snd_buf->tail[0].iov_len) {
+		tmp = page_address(rqstp->rq_enc_pages[rqstp->rq_enc_pages_num - 1]);
+		memcpy(tmp, snd_buf->tail[0].iov_base, snd_buf->tail[0].iov_len);
+		snd_buf->tail[0].iov_base = tmp;
+	}
+	maj_stat = gss_wrap(ctx->gc_gss_ctx, GSS_C_QOP_DEFAULT, offset,
+				snd_buf, inpages);
+	/* RPC_SLACK_SPACE should prevent this ever happening: */
+	BUG_ON(snd_buf->len > snd_buf->buflen);
+        status = -EIO;
+	/* We're assuming that when GSS_S_CONTEXT_EXPIRED, the encryption was
+	 * done anyway, so it's safe to put the request on the wire: */
+	if (maj_stat == GSS_S_CONTEXT_EXPIRED)
+		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+	else if (maj_stat)
+		return status;
+
+	*opaque_len = htonl(snd_buf->len - offset);
+	/* guess whether we're in the head or the tail: */
+	if (snd_buf->page_len || snd_buf->tail[0].iov_len)
+		iov = snd_buf->tail;
+	else
+		iov = snd_buf->head;
+	p = iov->iov_base + iov->iov_len;
+	pad = 3 - ((snd_buf->len - offset - 1) & 3);
+	memset(p, 0, pad);
+	iov->iov_len += pad;
+	snd_buf->len += pad;
+
+	return 0;
+}
+
 static int
 gss_wrap_req(struct rpc_task *task,
 	     kxdrproc_t encode, void *rqstp, u32 *p, void *obj)
@@ -1002,6 +1111,8 @@ gss_wrap_req(struct rpc_task *task,
 								rqstp, p, obj);
 			break;
        		case RPC_GSS_SVC_PRIVACY:
+			status = gss_wrap_req_priv(cred, ctx, encode,
+					rqstp, p, obj);
 			break;
 	}
 out:
@@ -1048,6 +1159,36 @@ gss_unwrap_resp_integ(struct rpc_cred *c
 	return 0;
 }
 
+static inline int
+gss_unwrap_resp_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
+		struct rpc_rqst *rqstp, u32 **p)
+{
+	struct xdr_buf  *rcv_buf = &rqstp->rq_rcv_buf;
+	u32 offset;
+	u32 opaque_len;
+	u32 maj_stat;
+	int status = -EIO;
+
+	opaque_len = ntohl(*(*p)++);
+	offset = (u8 *)(*p) - (u8 *)rcv_buf->head[0].iov_base;
+	if (offset + opaque_len > rcv_buf->len)
+		return status;
+	/* remove padding: */
+	rcv_buf->len = offset + opaque_len;
+
+	maj_stat = gss_unwrap(ctx->gc_gss_ctx, NULL,
+			offset, rcv_buf);
+	if (maj_stat == GSS_S_CONTEXT_EXPIRED)
+		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+	if (maj_stat != GSS_S_COMPLETE)
+		return status;
+	if (ntohl(*(*p)++) != rqstp->rq_seqno)
+		return status;
+
+	return 0;
+}
+
+
 static int
 gss_unwrap_resp(struct rpc_task *task,
 		kxdrproc_t decode, void *rqstp, u32 *p, void *obj)
@@ -1057,6 +1198,8 @@ gss_unwrap_resp(struct rpc_task *task,
 			gc_base);
 	struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
 	u32		*savedp = p;
+	struct kvec	*head = ((struct rpc_rqst *)rqstp)->rq_rcv_buf.head;
+	int		savedlen = head->iov_len;
 	int             status = -EIO;
 
 	if (ctx->gc_proc != RPC_GSS_PROC_DATA)
@@ -1070,10 +1213,14 @@ gss_unwrap_resp(struct rpc_task *task,
 				goto out;
 			break;
        		case RPC_GSS_SVC_PRIVACY:
+			status = gss_unwrap_resp_priv(cred, ctx, rqstp, &p);
+			if (status)
+				goto out;
 			break;
 	}
 	/* take into account extra slack for integrity and privacy cases: */
-	task->tk_auth->au_rslack = task->tk_auth->au_verfsize + (p - savedp);
+	task->tk_auth->au_rslack = task->tk_auth->au_verfsize + (p - savedp)
+						+ (savedlen - head->iov_len);
 out_decode:
 	status = decode(rqstp, p, obj);
 out:
---
0.99.8.GIT


--- NEW FILE 0599-RPCSEC_GSS-Simplify-rpcsec_gss-crypto-code.txt ---
Subject: [PATCH] RPCSEC_GSS: Simplify rpcsec_gss crypto code
From: J. Bruce Fields <bfields fieldses org>
Date: 1129236903 -0400

 Factor out some code that will be shared by privacy crypto routines

 Signed-off-by: J. Bruce Fields <bfields citi umich edu>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 net/sunrpc/auth_gss/gss_krb5_crypto.c |  106 ++++++++++++++++++++++++---------
 1 files changed, 77 insertions(+), 29 deletions(-)

applies-to: 4b9df421a02217e1cd23b601b6c05c592d0bdf02
f7b3af64c653c73feb060a9f94f2df9ab4bba4c3
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index ee6ae74..2baf93f 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -139,6 +139,82 @@ buf_to_sg(struct scatterlist *sg, char *
 	sg->length = len;
 }
 
+static int
+process_xdr_buf(struct xdr_buf *buf, int offset, int len,
+		int (*actor)(struct scatterlist *, void *), void *data)
+{
+	int i, page_len, thislen, page_offset, ret = 0;
+	struct scatterlist	sg[1];
+
+	if (offset >= buf->head[0].iov_len) {
+		offset -= buf->head[0].iov_len;
+	} else {
+		thislen = buf->head[0].iov_len - offset;
+		if (thislen > len)
+			thislen = len;
+		buf_to_sg(sg, buf->head[0].iov_base + offset, thislen);
+		ret = actor(sg, data);
+		if (ret)
+			goto out;
+		offset = 0;
+		len -= thislen;
+	}
+	if (len == 0)
+		goto out;
+
+	if (offset >= buf->page_len) {
+		offset -= buf->page_len;
+	} else {
+		page_len = buf->page_len - offset;
+		if (page_len > len)
+			page_len = len;
+		len -= page_len;
+		page_offset = (offset + buf->page_base) & (PAGE_CACHE_SIZE - 1);
+		i = (offset + buf->page_base) >> PAGE_CACHE_SHIFT;
+		thislen = PAGE_CACHE_SIZE - page_offset;
+		do {
+			if (thislen > page_len)
+				thislen = page_len;
+			sg->page = buf->pages[i];
+			sg->offset = page_offset;
+			sg->length = thislen;
+			ret = actor(sg, data);
+			if (ret)
+				goto out;
+			page_len -= thislen;
+			i++;
+			page_offset = 0;
+			thislen = PAGE_CACHE_SIZE;
+		} while (page_len != 0);
+		offset = 0;
+	}
+	if (len == 0)
+		goto out;
+
+	if (offset < buf->tail[0].iov_len) {
+		thislen = buf->tail[0].iov_len - offset;
+		if (thislen > len)
+			thislen = len;
+		buf_to_sg(sg, buf->tail[0].iov_base + offset, thislen);
+		ret = actor(sg, data);
+		len -= thislen;
+	}
+	if (len != 0)
+		ret = -EINVAL;
+out:
+	return ret;
+}
+
+static int
+checksummer(struct scatterlist *sg, void *data)
+{
+	struct crypto_tfm *tfm = (struct crypto_tfm *)data;
+
+	crypto_digest_update(tfm, sg, 1);
+
+	return 0;
+}
+
 /* checksum the plaintext data and hdrlen bytes of the token header */
 s32
 make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
@@ -148,8 +224,6 @@ make_checksum(s32 cksumtype, char *heade
 	struct crypto_tfm               *tfm = NULL; /* XXX add to ctx? */
 	struct scatterlist              sg[1];
 	u32                             code = GSS_S_FAILURE;
-	int				len, thislen, offset;
-	int				i;
 
 	switch (cksumtype) {
 		case CKSUMTYPE_RSA_MD5:
@@ -169,33 +243,7 @@ make_checksum(s32 cksumtype, char *heade
 	crypto_digest_init(tfm);
 	buf_to_sg(sg, header, hdrlen);
 	crypto_digest_update(tfm, sg, 1);
-	if (body->head[0].iov_len) {
-		buf_to_sg(sg, body->head[0].iov_base, body->head[0].iov_len);
-		crypto_digest_update(tfm, sg, 1);
-	}
-
-	len = body->page_len;
-	if (len != 0) {
-		offset = body->page_base & (PAGE_CACHE_SIZE - 1);
-		i = body->page_base >> PAGE_CACHE_SHIFT;
-		thislen = PAGE_CACHE_SIZE - offset;
-		do {
-			if (thislen > len)
-				thislen = len;
-			sg->page = body->pages[i];
-			sg->offset = offset;
-			sg->length = thislen;
-			crypto_digest_update(tfm, sg, 1);
-			len -= thislen;
-			i++;
-			offset = 0;
-			thislen = PAGE_CACHE_SIZE;
-		} while(len != 0);
-	}
-	if (body->tail[0].iov_len) {
-		buf_to_sg(sg, body->tail[0].iov_base, body->tail[0].iov_len);
-		crypto_digest_update(tfm, sg, 1);
-	}
+	process_xdr_buf(body, 0, body->len, checksummer, tfm);
 	crypto_digest_final(tfm, cksum->data);
 	code = 0;
 out:
---
0.99.8.GIT


--- NEW FILE 0600-RPCSEC_GSS-krb5-pre-privacy-cleanup.txt ---
Subject: [PATCH] RPCSEC_GSS: krb5 pre-privacy cleanup
From: J. Bruce Fields <bfields fieldses org>
Date: 1129236908 -0400

 The code this was originally derived from processed wrap and mic tokens using
 the same functions.  This required some contortions, and more would be required
 with the addition of xdr_buf's, so it's better to separate out the two code
 paths.

 In preparation for adding privacy support, remove the last vestiges of the
 old wrap token code.

 Signed-off-by: J. Bruce Fields <bfields citi umich edu>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/gss_krb5.h       |    5 ++--
 net/sunrpc/auth_gss/gss_krb5_mech.c   |    5 ++--
 net/sunrpc/auth_gss/gss_krb5_seal.c   |   38 +++++----------------------------
 net/sunrpc/auth_gss/gss_krb5_unseal.c |   30 +++++---------------------
 4 files changed, 16 insertions(+), 62 deletions(-)

applies-to: fee45429f16e5b548356f50dc64eb4e71bca1a9d
bfa91516b57483fc9c81d8d90325fd2c3c16ac48
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
index ffe31d2..cb35833 100644
--- a/include/linux/sunrpc/gss_krb5.h
+++ b/include/linux/sunrpc/gss_krb5.h
@@ -121,13 +121,12 @@ make_checksum(s32 cksumtype, char *heade
 u32
 krb5_make_token(struct krb5_ctx *context_handle, int qop_req,
 	struct xdr_buf *input_message_buffer,
-	struct xdr_netobj *output_message_buffer, int toktype);
+	struct xdr_netobj *output_message_buffer);
 
 u32
 krb5_read_token(struct krb5_ctx *context_handle,
 	  struct xdr_netobj *input_token_buffer,
-	  struct xdr_buf *message_buffer,
-	  int *qop_state, int toktype);
+	  struct xdr_buf *message_buffer, int *qop_state);
 
 u32
 krb5_encrypt(struct crypto_tfm * key,
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 462c5b8..8b9066f 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -199,8 +199,7 @@ gss_verify_mic_kerberos(struct gss_ctx		
 	int qop_state;
 	struct krb5_ctx *kctx = ctx->internal_ctx_id;
 
-	maj_stat = krb5_read_token(kctx, mic_token, message, &qop_state,
-				   KG_TOK_MIC_MSG);
+	maj_stat = krb5_read_token(kctx, mic_token, message, &qop_state);
 	if (!maj_stat && qop_state)
 	    *qstate = qop_state;
 
@@ -216,7 +215,7 @@ gss_get_mic_kerberos(struct gss_ctx	*ctx
 	u32 err = 0;
 	struct krb5_ctx *kctx = ctx->internal_ctx_id;
 
-	err = krb5_make_token(kctx, qop, message, mic_token, KG_TOK_MIC_MSG);
+	err = krb5_make_token(kctx, qop, message, mic_token);
 
 	dprintk("RPC:      gss_get_mic_kerberos returning %d\n",err);
 
diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
index afeeb87..2511834 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
@@ -70,22 +70,12 @@
 # define RPCDBG_FACILITY        RPCDBG_AUTH
 #endif
 
-static inline int
-gss_krb5_padding(int blocksize, int length) {
-	/* Most of the code is block-size independent but in practice we
-	 * use only 8: */
-	BUG_ON(blocksize != 8);
-	return 8 - (length & 7);
-}
-
 u32
 krb5_make_token(struct krb5_ctx *ctx, int qop_req,
-		   struct xdr_buf *text, struct xdr_netobj *token,
-		   int toktype)
+		   struct xdr_buf *text, struct xdr_netobj *token)
 {
 	s32			checksum_type;
 	struct xdr_netobj	md5cksum = {.len = 0, .data = NULL};
-	int			blocksize = 0, tmsglen;
 	unsigned char		*ptr, *krb5_hdr, *msg_start;
 	s32			now;
 
@@ -111,21 +101,13 @@ krb5_make_token(struct krb5_ctx *ctx, in
 		goto out_err;
 	}
 
-	if (toktype == KG_TOK_WRAP_MSG) {
-		blocksize = crypto_tfm_alg_blocksize(ctx->enc);
-		tmsglen = blocksize + text->len
-			+ gss_krb5_padding(blocksize, blocksize + text->len);
-	} else {
-		tmsglen = 0;
-	}
-
-	token->len = g_token_size(&ctx->mech_used, 22 + tmsglen);
+	token->len = g_token_size(&ctx->mech_used, 22);
 
 	ptr = token->data;
-	g_make_token_header(&ctx->mech_used, 22 + tmsglen, &ptr);
+	g_make_token_header(&ctx->mech_used, 22, &ptr);
 
-	*ptr++ = (unsigned char) ((toktype>>8)&0xff);
-	*ptr++ = (unsigned char) (toktype&0xff);
+	*ptr++ = (unsigned char) ((KG_TOK_MIC_MSG>>8)&0xff);
+	*ptr++ = (unsigned char) (KG_TOK_MIC_MSG&0xff);
 
 	/* ptr now at byte 2 of header described in rfc 1964, section 1.2.1: */
 	krb5_hdr = ptr - 2;
@@ -133,17 +115,9 @@ krb5_make_token(struct krb5_ctx *ctx, in
 
 	*(u16 *)(krb5_hdr + 2) = htons(ctx->signalg);
 	memset(krb5_hdr + 4, 0xff, 4);
-	if (toktype == KG_TOK_WRAP_MSG)
-		*(u16 *)(krb5_hdr + 4) = htons(ctx->sealalg);
 
-	if (toktype == KG_TOK_WRAP_MSG) {
-		/* XXX removing support for now */
+	if (make_checksum(checksum_type, krb5_hdr, 8, text, &md5cksum))
 		goto out_err;
-	} else { /* Sign only.  */
-		if (make_checksum(checksum_type, krb5_hdr, 8, text,
-				       &md5cksum))
-			goto out_err;
-	}
 
 	switch (ctx->signalg) {
 	case SGN_ALG_DES_MAC_MD5:
diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
index 8767fc5..19eba3d 100644
--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
@@ -68,20 +68,13 @@
 #endif
 
 
-/* message_buffer is an input if toktype is MIC and an output if it is WRAP:
- * If toktype is MIC: read_token is a mic token, and message_buffer is the
- *   data that the mic was supposedly taken over.
- * If toktype is WRAP: read_token is a wrap token, and message_buffer is used
- *   to return the decrypted data.
- */
+/* read_token is a mic token, and message_buffer is the data that the mic was
+ * supposedly taken over. */
 
-/* XXX will need to change prototype and/or just split into a separate function
- * when we add privacy (because read_token will be in pages too). */
 u32
 krb5_read_token(struct krb5_ctx *ctx,
 		struct xdr_netobj *read_token,
-		struct xdr_buf *message_buffer,
-		int *qop_state, int toktype)
+		struct xdr_buf *message_buffer, int *qop_state)
 {
 	int			signalg;
 	int			sealalg;
@@ -100,16 +93,12 @@ krb5_read_token(struct krb5_ctx *ctx,
 					read_token->len))
 		goto out;
 
-	if ((*ptr++ != ((toktype>>8)&0xff)) || (*ptr++ != (toktype&0xff)))
+	if ((*ptr++ != ((KG_TOK_MIC_MSG>>8)&0xff)) ||
+	    (*ptr++ != ( KG_TOK_MIC_MSG    &0xff))   )
 		goto out;
 
 	/* XXX sanity-check bodysize?? */
 
-	if (toktype == KG_TOK_WRAP_MSG) {
-		/* XXX gone */
-		goto out;
-	}
-
 	/* get the sign and seal algorithms */
 
 	signalg = ptr[0] + (ptr[1] << 8);
@@ -120,14 +109,7 @@ krb5_read_token(struct krb5_ctx *ctx,
 	if ((ptr[4] != 0xff) || (ptr[5] != 0xff))
 		goto out;
 
-	if (((toktype != KG_TOK_WRAP_MSG) && (sealalg != 0xffff)) ||
-	    ((toktype == KG_TOK_WRAP_MSG) && (sealalg == 0xffff)))
-		goto out;
-
-	/* in the current spec, there is only one valid seal algorithm per
-	   key type, so a simple comparison is ok */
-
-	if ((toktype == KG_TOK_WRAP_MSG) && !(sealalg == ctx->sealalg))
+	if (sealalg != 0xffff)
 		goto out;
 
 	/* there are several mappings of seal algorithms to sign algorithms,
---
0.99.8.GIT


--- NEW FILE 0601-RPCSEC_GSS-Add-support-for-privacy-to-krb5-rpcsec_gss-mechanism.txt ---
Subject: [PATCH] RPCSEC_GSS: Add support for privacy to krb5 rpcsec_gss mechanism.
From: J. Bruce Fields <bfields fieldses org>
Date: 1129236913 -0400

 Add support for privacy to the krb5 rpcsec_gss mechanism.

 Signed-off-by: J. Bruce Fields <bfields citi umich edu>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/gss_krb5.h       |   18 ++
 net/sunrpc/auth_gss/Makefile          |    2 
 net/sunrpc/auth_gss/gss_krb5_crypto.c |  156 ++++++++++++++
 net/sunrpc/auth_gss/gss_krb5_mech.c   |    7 +
 net/sunrpc/auth_gss/gss_krb5_seal.c   |    4 
 net/sunrpc/auth_gss/gss_krb5_unseal.c |    2 
 net/sunrpc/auth_gss/gss_krb5_wrap.c   |  370 +++++++++++++++++++++++++++++++++
 7 files changed, 552 insertions(+), 7 deletions(-)
 create mode 100644 net/sunrpc/auth_gss/gss_krb5_wrap.c

applies-to: ed5c63ec1aa88152b0991370f4a1dbcfff0cd15a
14ae162c24d985593d5b19437d7f3d8fd0062b59
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
index cb35833..7f93c2d 100644
--- a/include/linux/sunrpc/gss_krb5.h
+++ b/include/linux/sunrpc/gss_krb5.h
@@ -116,7 +116,7 @@ enum seal_alg {
 
 s32
 make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
-		   struct xdr_netobj *cksum);
+		   int body_offset, struct xdr_netobj *cksum);
 
 u32
 krb5_make_token(struct krb5_ctx *context_handle, int qop_req,
@@ -129,6 +129,15 @@ krb5_read_token(struct krb5_ctx *context
 	  struct xdr_buf *message_buffer, int *qop_state);
 
 u32
+gss_wrap_kerberos(struct gss_ctx *ctx_id, u32 qop, int offset,
+		struct xdr_buf *outbuf, struct page **pages);
+
+u32
+gss_unwrap_kerberos(struct gss_ctx *ctx_id, u32 *qop, int offset,
+		struct xdr_buf *buf);
+
+
+u32
 krb5_encrypt(struct crypto_tfm * key,
 	     void *iv, void *in, void *out, int length);
 
@@ -136,6 +145,13 @@ u32
 krb5_decrypt(struct crypto_tfm * key,
 	     void *iv, void *in, void *out, int length); 
 
+int
+gss_encrypt_xdr_buf(struct crypto_tfm *tfm, struct xdr_buf *outbuf, int offset,
+		struct page **pages);
+
+int
+gss_decrypt_xdr_buf(struct crypto_tfm *tfm, struct xdr_buf *inbuf, int offset);
+
 s32
 krb5_make_seq_num(struct crypto_tfm * key,
 		int direction,
diff --git a/net/sunrpc/auth_gss/Makefile b/net/sunrpc/auth_gss/Makefile
index fe1b874..f3431a7 100644
--- a/net/sunrpc/auth_gss/Makefile
+++ b/net/sunrpc/auth_gss/Makefile
@@ -10,7 +10,7 @@ auth_rpcgss-objs := auth_gss.o gss_gener
 obj-$(CONFIG_RPCSEC_GSS_KRB5) += rpcsec_gss_krb5.o
 
 rpcsec_gss_krb5-objs := gss_krb5_mech.o gss_krb5_seal.o gss_krb5_unseal.o \
-	gss_krb5_seqnum.o
+	gss_krb5_seqnum.o gss_krb5_wrap.o
 
 obj-$(CONFIG_RPCSEC_GSS_SPKM3) += rpcsec_gss_spkm3.o
 
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index 2baf93f..3f3d543 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -218,7 +218,7 @@ checksummer(struct scatterlist *sg, void
 /* checksum the plaintext data and hdrlen bytes of the token header */
 s32
 make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
-		   struct xdr_netobj *cksum)
+		   int body_offset, struct xdr_netobj *cksum)
 {
 	char                            *cksumname;
 	struct crypto_tfm               *tfm = NULL; /* XXX add to ctx? */
@@ -243,7 +243,8 @@ make_checksum(s32 cksumtype, char *heade
 	crypto_digest_init(tfm);
 	buf_to_sg(sg, header, hdrlen);
 	crypto_digest_update(tfm, sg, 1);
-	process_xdr_buf(body, 0, body->len, checksummer, tfm);
+	process_xdr_buf(body, body_offset, body->len - body_offset,
+			checksummer, tfm);
 	crypto_digest_final(tfm, cksum->data);
 	code = 0;
 out:
@@ -252,3 +253,154 @@ out:
 }
 
 EXPORT_SYMBOL(make_checksum);
+
+struct encryptor_desc {
+	u8 iv[8]; /* XXX hard-coded blocksize */
+	struct crypto_tfm *tfm;
+	int pos;
+	struct xdr_buf *outbuf;
+	struct page **pages;
+	struct scatterlist infrags[4];
+	struct scatterlist outfrags[4];
+	int fragno;
+	int fraglen;
+};
+
+static int
+encryptor(struct scatterlist *sg, void *data)
+{
+	struct encryptor_desc *desc = data;
+	struct xdr_buf *outbuf = desc->outbuf;
+	struct page *in_page;
+	int thislen = desc->fraglen + sg->length;
+	int fraglen, ret;
+	int page_pos;
+
+	/* Worst case is 4 fragments: head, end of page 1, start
+	 * of page 2, tail.  Anything more is a bug. */
+	BUG_ON(desc->fragno > 3);
+	desc->infrags[desc->fragno] = *sg;
+	desc->outfrags[desc->fragno] = *sg;
+
+	page_pos = desc->pos - outbuf->head[0].iov_len;
+	if (page_pos >= 0 && page_pos < outbuf->page_len) {
+		/* pages are not in place: */
+		int i = (page_pos + outbuf->page_base) >> PAGE_CACHE_SHIFT;
+		in_page = desc->pages[i];
+	} else {
+		in_page = sg->page;
+	}
+	desc->infrags[desc->fragno].page = in_page;
+	desc->fragno++;
+	desc->fraglen += sg->length;
+	desc->pos += sg->length;
+
+	fraglen = thislen & 7; /* XXX hardcoded blocksize */
+	thislen -= fraglen;
+
+	if (thislen == 0)
+		return 0;
+
+	ret = crypto_cipher_encrypt_iv(desc->tfm, desc->outfrags, desc->infrags,
+					thislen, desc->iv);
+	if (ret)
+		return ret;
+	if (fraglen) {
+		desc->outfrags[0].page = sg->page;
+		desc->outfrags[0].offset = sg->offset + sg->length - fraglen;
+		desc->outfrags[0].length = fraglen;
+		desc->infrags[0] = desc->outfrags[0];
+		desc->infrags[0].page = in_page;
+		desc->fragno = 1;
+		desc->fraglen = fraglen;
+	} else {
+		desc->fragno = 0;
+		desc->fraglen = 0;
+	}
+	return 0;
+}
+
+int
+gss_encrypt_xdr_buf(struct crypto_tfm *tfm, struct xdr_buf *buf, int offset,
+		struct page **pages)
+{
+	int ret;
+	struct encryptor_desc desc;
+
+	BUG_ON((buf->len - offset) % crypto_tfm_alg_blocksize(tfm) != 0);
+
+	memset(desc.iv, 0, sizeof(desc.iv));
+	desc.tfm = tfm;
+	desc.pos = offset;
+	desc.outbuf = buf;
+	desc.pages = pages;
+	desc.fragno = 0;
+	desc.fraglen = 0;
+
+	ret = process_xdr_buf(buf, offset, buf->len - offset, encryptor, &desc);
+	return ret;
+}
+
+EXPORT_SYMBOL(gss_encrypt_xdr_buf);
+
+struct decryptor_desc {
+	u8 iv[8]; /* XXX hard-coded blocksize */
+	struct crypto_tfm *tfm;
+	struct scatterlist frags[4];
+	int fragno;
+	int fraglen;
+};
+
+static int
+decryptor(struct scatterlist *sg, void *data)
+{
+	struct decryptor_desc *desc = data;
+	int thislen = desc->fraglen + sg->length;
+	int fraglen, ret;
+
+	/* Worst case is 4 fragments: head, end of page 1, start
+	 * of page 2, tail.  Anything more is a bug. */
+	BUG_ON(desc->fragno > 3);
+	desc->frags[desc->fragno] = *sg;
+	desc->fragno++;
+	desc->fraglen += sg->length;
+
+	fraglen = thislen & 7; /* XXX hardcoded blocksize */
+	thislen -= fraglen;
+
+	if (thislen == 0)
+		return 0;
+
+	ret = crypto_cipher_decrypt_iv(desc->tfm, desc->frags, desc->frags,
+					thislen, desc->iv);
+	if (ret)
+		return ret;
+	if (fraglen) {
+		desc->frags[0].page = sg->page;
+		desc->frags[0].offset = sg->offset + sg->length - fraglen;
+		desc->frags[0].length = fraglen;
+		desc->fragno = 1;
+		desc->fraglen = fraglen;
+	} else {
+		desc->fragno = 0;
+		desc->fraglen = 0;
+	}
+	return 0;
+}
+
+int
+gss_decrypt_xdr_buf(struct crypto_tfm *tfm, struct xdr_buf *buf, int offset)
+{
+	struct decryptor_desc desc;
+
+	/* XXXJBF: */
+	BUG_ON((buf->len - offset) % crypto_tfm_alg_blocksize(tfm) != 0);
+
+	memset(desc.iv, 0, sizeof(desc.iv));
+	desc.tfm = tfm;
+	desc.fragno = 0;
+	desc.fraglen = 0;
+	return process_xdr_buf(buf, offset, buf->len - offset, decryptor, &desc);
+}
+
+EXPORT_SYMBOL(gss_decrypt_xdr_buf);
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 8b9066f..37a9ad9 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -226,6 +226,8 @@ static struct gss_api_ops gss_kerberos_o
 	.gss_import_sec_context	= gss_import_sec_context_kerberos,
 	.gss_get_mic		= gss_get_mic_kerberos,
 	.gss_verify_mic		= gss_verify_mic_kerberos,
+	.gss_wrap		= gss_wrap_kerberos,
+	.gss_unwrap		= gss_unwrap_kerberos,
 	.gss_delete_sec_context	= gss_delete_sec_context_kerberos,
 };
 
@@ -240,6 +242,11 @@ static struct pf_desc gss_kerberos_pfs[]
 		.service = RPC_GSS_SVC_INTEGRITY,
 		.name = "krb5i",
 	},
+	[2] = {
+		.pseudoflavor = RPC_AUTH_GSS_KRB5P,
+		.service = RPC_GSS_SVC_PRIVACY,
+		.name = "krb5p",
+	},
 };
 
 static struct gss_api_mech gss_kerberos_mech = {
diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
index 2511834..fb852d9 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
@@ -116,8 +116,8 @@ krb5_make_token(struct krb5_ctx *ctx, in
 	*(u16 *)(krb5_hdr + 2) = htons(ctx->signalg);
 	memset(krb5_hdr + 4, 0xff, 4);
 
-	if (make_checksum(checksum_type, krb5_hdr, 8, text, &md5cksum))
-		goto out_err;
+	if (make_checksum(checksum_type, krb5_hdr, 8, text, 0, &md5cksum))
+			goto out_err;
 
 	switch (ctx->signalg) {
 	case SGN_ALG_DES_MAC_MD5:
diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
index 19eba3d..c3d6d1b 100644
--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
@@ -136,7 +136,7 @@ krb5_read_token(struct krb5_ctx *ctx,
 	switch (signalg) {
 	case SGN_ALG_DES_MAC_MD5:
 		ret = make_checksum(checksum_type, ptr - 2, 8,
-					 message_buffer, &md5cksum);
+					 message_buffer, 0, &md5cksum);
 		if (ret)
 			goto out;
 
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
new file mode 100644
index 0000000..ddcde6e
--- /dev/null
+++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
@@ -0,0 +1,370 @@
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/sunrpc/gss_krb5.h>
+#include <linux/random.h>
+#include <linux/pagemap.h>
+#include <asm/scatterlist.h>
+#include <linux/crypto.h>
+
+#ifdef RPC_DEBUG
+# define RPCDBG_FACILITY	RPCDBG_AUTH
+#endif
+
+static inline int
+gss_krb5_padding(int blocksize, int length)
+{
+	/* Most of the code is block-size independent but currently we
+	 * use only 8: */
+	BUG_ON(blocksize != 8);
+	return 8 - (length & 7);
+}
+
+static inline void
+gss_krb5_add_padding(struct xdr_buf *buf, int offset, int blocksize)
+{
+	int padding = gss_krb5_padding(blocksize, buf->len - offset);
+	char *p;
+	struct kvec *iov;
+
+	if (buf->page_len || buf->tail[0].iov_len)
+		iov = &buf->tail[0];
+	else
+		iov = &buf->head[0];
+	p = iov->iov_base + iov->iov_len;
+	iov->iov_len += padding;
+	buf->len += padding;
+	memset(p, padding, padding);
+}
+
+static inline int
+gss_krb5_remove_padding(struct xdr_buf *buf, int blocksize)
+{
+	u8 *ptr;
+	u8 pad;
+	int len = buf->len;
+
+	if (len <= buf->head[0].iov_len) {
+		pad = *(u8 *)(buf->head[0].iov_base + len - 1);
+		if (pad > buf->head[0].iov_len)
+			return -EINVAL;
+		buf->head[0].iov_len -= pad;
+		goto out;
+	} else
+		len -= buf->head[0].iov_len;
+	if (len <= buf->page_len) {
+		int last = (buf->page_base + len - 1)
+					>>PAGE_CACHE_SHIFT;
+		int offset = (buf->page_base + len - 1)
+					& (PAGE_CACHE_SIZE - 1);
+		ptr = kmap_atomic(buf->pages[last], KM_SKB_SUNRPC_DATA);
+		pad = *(ptr + offset);
+		kunmap_atomic(ptr, KM_SKB_SUNRPC_DATA);
+		goto out;
+	} else
+		len -= buf->page_len;
+	BUG_ON(len > buf->tail[0].iov_len);
+	pad = *(u8 *)(buf->tail[0].iov_base + len - 1);
+out:
+	/* XXX: NOTE: we do not adjust the page lengths--they represent
+	 * a range of data in the real filesystem page cache, and we need
+	 * to know that range so the xdr code can properly place read data.
+	 * However adjusting the head length, as we do above, is harmless.
+	 * In the case of a request that fits into a single page, the server
+	 * also uses length and head length together to determine the original
+	 * start of the request to copy the request for deferal; so it's
+	 * easier on the server if we adjust head and tail length in tandem.
+	 * It's not really a problem that we don't fool with the page and
+	 * tail lengths, though--at worst badly formed xdr might lead the
+	 * server to attempt to parse the padding.
+	 * XXX: Document all these weird requirements for gss mechanism
+	 * wrap/unwrap functions. */
+	if (pad > blocksize)
+		return -EINVAL;
+	if (buf->len > pad)
+		buf->len -= pad;
+	else
+		return -EINVAL;
+	return 0;
+}
+
+static inline void
+make_confounder(char *p, int blocksize)
+{
+	static u64 i = 0;
+	u64 *q = (u64 *)p;
+
+	/* rfc1964 claims this should be "random".  But all that's really
+	 * necessary is that it be unique.  And not even that is necessary in
+	 * our case since our "gssapi" implementation exists only to support
+	 * rpcsec_gss, so we know that the only buffers we will ever encrypt
+	 * already begin with a unique sequence number.  Just to hedge my bets
+	 * I'll make a half-hearted attempt at something unique, but ensuring
+	 * uniqueness would mean worrying about atomicity and rollover, and I
+	 * don't care enough. */
+
+	BUG_ON(blocksize != 8);
+	*q = i++;
+}
+
+/* Assumptions: the head and tail of inbuf are ours to play with.
+ * The pages, however, may be real pages in the page cache and we replace
+ * them with scratch pages from **pages before writing to them. */
+/* XXX: obviously the above should be documentation of wrap interface,
+ * and shouldn't be in this kerberos-specific file. */
+
+/* XXX factor out common code with seal/unseal. */
+
+u32
+gss_wrap_kerberos(struct gss_ctx *ctx, u32 qop, int offset,
+		struct xdr_buf *buf, struct page **pages)
+{
+	struct krb5_ctx		*kctx = ctx->internal_ctx_id;
+	s32			checksum_type;
+	struct xdr_netobj	md5cksum = {.len = 0, .data = NULL};
+	int			blocksize = 0, plainlen;
+	unsigned char		*ptr, *krb5_hdr, *msg_start;
+	s32			now;
+	int			headlen;
+	struct page		**tmp_pages;
+
+	dprintk("RPC:     gss_wrap_kerberos\n");
+
+	now = get_seconds();
+
+	if (qop != 0)
+		goto out_err;
+
+	switch (kctx->signalg) {
+		case SGN_ALG_DES_MAC_MD5:
+			checksum_type = CKSUMTYPE_RSA_MD5;
+			break;
+		default:
+			dprintk("RPC:      gss_krb5_seal: kctx->signalg %d not"
+				" supported\n", kctx->signalg);
+			goto out_err;
+	}
+	if (kctx->sealalg != SEAL_ALG_NONE && kctx->sealalg != SEAL_ALG_DES) {
+		dprintk("RPC:      gss_krb5_seal: kctx->sealalg %d not supported\n",
+			kctx->sealalg);
+		goto out_err;
+	}
+
+	blocksize = crypto_tfm_alg_blocksize(kctx->enc);
+	gss_krb5_add_padding(buf, offset, blocksize);
+	BUG_ON((buf->len - offset) % blocksize);
+	plainlen = blocksize + buf->len - offset;
+
+	headlen = g_token_size(&kctx->mech_used, 22 + plainlen) -
+						(buf->len - offset);
+
+	ptr = buf->head[0].iov_base + offset;
+	/* shift data to make room for header. */
+	/* XXX Would be cleverer to encrypt while copying. */
+	/* XXX bounds checking, slack, etc. */
+	memmove(ptr + headlen, ptr, buf->head[0].iov_len - offset);
+	buf->head[0].iov_len += headlen;
+	buf->len += headlen;
+	BUG_ON((buf->len - offset - headlen) % blocksize);
+
+	g_make_token_header(&kctx->mech_used, 22 + plainlen, &ptr);
+
+
+	*ptr++ = (unsigned char) ((KG_TOK_WRAP_MSG>>8)&0xff);
+	*ptr++ = (unsigned char) (KG_TOK_WRAP_MSG&0xff);
+
+	/* ptr now at byte 2 of header described in rfc 1964, section 1.2.1: */
+	krb5_hdr = ptr - 2;
+	msg_start = krb5_hdr + 24;
+	/* XXXJBF: */ BUG_ON(buf->head[0].iov_base + offset + headlen != msg_start + blocksize);
+
+	*(u16 *)(krb5_hdr + 2) = htons(kctx->signalg);
+	memset(krb5_hdr + 4, 0xff, 4);
+	*(u16 *)(krb5_hdr + 4) = htons(kctx->sealalg);
+
+	make_confounder(msg_start, blocksize);
+
+	/* XXXJBF: UGH!: */
+	tmp_pages = buf->pages;
+	buf->pages = pages;
+	if (make_checksum(checksum_type, krb5_hdr, 8, buf,
+				offset + headlen - blocksize, &md5cksum))
+		goto out_err;
+	buf->pages = tmp_pages;
+
+	switch (kctx->signalg) {
+	case SGN_ALG_DES_MAC_MD5:
+		if (krb5_encrypt(kctx->seq, NULL, md5cksum.data,
+				  md5cksum.data, md5cksum.len))
+			goto out_err;
+		memcpy(krb5_hdr + 16,
+		       md5cksum.data + md5cksum.len - KRB5_CKSUM_LENGTH,
+		       KRB5_CKSUM_LENGTH);
+
+		dprintk("RPC:      make_seal_token: cksum data: \n");
+		print_hexl((u32 *) (krb5_hdr + 16), KRB5_CKSUM_LENGTH, 0);
+		break;
+	default:
+		BUG();
+	}
+
+	kfree(md5cksum.data);
+
+	/* XXX would probably be more efficient to compute checksum
+	 * and encrypt at the same time: */
+	if ((krb5_make_seq_num(kctx->seq, kctx->initiate ? 0 : 0xff,
+			       kctx->seq_send, krb5_hdr + 16, krb5_hdr + 8)))
+		goto out_err;
+
+	if (gss_encrypt_xdr_buf(kctx->enc, buf, offset + headlen - blocksize,
+									pages))
+		goto out_err;
+
+	kctx->seq_send++;
+
+	return ((kctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE);
+out_err:
+	if (md5cksum.data) kfree(md5cksum.data);
+	return GSS_S_FAILURE;
+}
+
+u32
+gss_unwrap_kerberos(struct gss_ctx *ctx, u32 *qop, int offset,
+			struct xdr_buf *buf)
+{
+	struct krb5_ctx		*kctx = ctx->internal_ctx_id;
+	int			signalg;
+	int			sealalg;
+	s32			checksum_type;
+	struct xdr_netobj	md5cksum = {.len = 0, .data = NULL};
+	s32			now;
+	int			direction;
+	s32			seqnum;
+	unsigned char		*ptr;
+	int			bodysize;
+	u32			ret = GSS_S_DEFECTIVE_TOKEN;
+	void			*data_start, *orig_start;
+	int			data_len;
+	int			blocksize;
+
+	dprintk("RPC:      gss_unwrap_kerberos\n");
+
+	ptr = (u8 *)buf->head[0].iov_base + offset;
+	if (g_verify_token_header(&kctx->mech_used, &bodysize, &ptr,
+					buf->len - offset))
+		goto out;
+
+	if ((*ptr++ != ((KG_TOK_WRAP_MSG>>8)&0xff)) ||
+	    (*ptr++ !=  (KG_TOK_WRAP_MSG    &0xff))   )
+		goto out;
+
+	/* XXX sanity-check bodysize?? */
+
+	/* get the sign and seal algorithms */
+
+	signalg = ptr[0] + (ptr[1] << 8);
+	sealalg = ptr[2] + (ptr[3] << 8);
+
+	/* Sanity checks */
+
+	if ((ptr[4] != 0xff) || (ptr[5] != 0xff))
+		goto out;
+
+	if (sealalg == 0xffff)
+		goto out;
+
+	/* in the current spec, there is only one valid seal algorithm per
+	   key type, so a simple comparison is ok */
+
+	if (sealalg != kctx->sealalg)
+		goto out;
+
+	/* there are several mappings of seal algorithms to sign algorithms,
+	   but few enough that we can try them all. */
+
+	if ((kctx->sealalg == SEAL_ALG_NONE && signalg > 1) ||
+	    (kctx->sealalg == SEAL_ALG_1 && signalg != SGN_ALG_3) ||
+	    (kctx->sealalg == SEAL_ALG_DES3KD &&
+	     signalg != SGN_ALG_HMAC_SHA1_DES3_KD))
+		goto out;
+
+	if (gss_decrypt_xdr_buf(kctx->enc, buf,
+			ptr + 22 - (unsigned char *)buf->head[0].iov_base))
+		goto out;
+
+	/* compute the checksum of the message */
+
+	/* initialize the the cksum */
+	switch (signalg) {
+	case SGN_ALG_DES_MAC_MD5:
+		checksum_type = CKSUMTYPE_RSA_MD5;
+		break;
+	default:
+		ret = GSS_S_DEFECTIVE_TOKEN;
+		goto out;
+	}
+
+	switch (signalg) {
+	case SGN_ALG_DES_MAC_MD5:
+		ret = make_checksum(checksum_type, ptr - 2, 8, buf,
+			 ptr + 22 - (unsigned char *)buf->head[0].iov_base, &md5cksum);
+		if (ret)
+			goto out;
+
+		ret = krb5_encrypt(kctx->seq, NULL, md5cksum.data,
+				   md5cksum.data, md5cksum.len);
+		if (ret)
+			goto out;
+
+		if (memcmp(md5cksum.data + 8, ptr + 14, 8)) {
+			ret = GSS_S_BAD_SIG;
+			goto out;
+		}
+		break;
+	default:
+		ret = GSS_S_DEFECTIVE_TOKEN;
+		goto out;
+	}
+
+	/* it got through unscathed.  Make sure the context is unexpired */
+
+	if (qop)
+		*qop = GSS_C_QOP_DEFAULT;
+
+	now = get_seconds();
+
+	ret = GSS_S_CONTEXT_EXPIRED;
+	if (now > kctx->endtime)
+		goto out;
+
+	/* do sequencing checks */
+
+	ret = GSS_S_BAD_SIG;
+	if ((ret = krb5_get_seq_num(kctx->seq, ptr + 14, ptr + 6, &direction,
+				    &seqnum)))
+		goto out;
+
+	if ((kctx->initiate && direction != 0xff) ||
+	    (!kctx->initiate && direction != 0))
+		goto out;
+
+	/* Copy the data back to the right position.  XXX: Would probably be
+	 * better to copy and encrypt at the same time. */
+
+	blocksize = crypto_tfm_alg_blocksize(kctx->enc);
+	data_start = ptr + 22 + blocksize;
+	orig_start = buf->head[0].iov_base + offset;
+	data_len = (buf->head[0].iov_base + buf->head[0].iov_len) - data_start;
+	memmove(orig_start, data_start, data_len);
+	buf->head[0].iov_len -= (data_start - orig_start);
+	buf->len -= (data_start - orig_start);
+
+	ret = GSS_S_DEFECTIVE_TOKEN;
+	if (gss_krb5_remove_padding(buf, blocksize))
+		goto out;
+
+	ret = GSS_S_COMPLETE;
+out:
+	if (md5cksum.data) kfree(md5cksum.data);
+	return ret;
+}
---
0.99.8.GIT


--- NEW FILE 0602-RPCSEC_GSS-remove-all-qop-parameters.txt ---
Subject: [PATCH] RPCSEC_GSS remove all qop parameters
From: J. Bruce Fields <bfields fieldses org>
Date: 1129236918 -0400

 Not only are the qop parameters that are passed around throughout the gssapi
 unused by any currently implemented mechanism, but there appears to be some
 doubt as to whether they will ever be used.  Let's just kill them off for now.

 Signed-off-by: J. Bruce Fields <bfields citi umich edu>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/gss_api.h         |   13 ++-----------
 include/linux/sunrpc/gss_err.h         |   10 ----------
 include/linux/sunrpc/gss_krb5.h        |    8 ++++----
 include/linux/sunrpc/gss_spkm3.h       |    4 ++--
 net/sunrpc/auth_gss/auth_gss.c         |   20 +++++++-------------
 net/sunrpc/auth_gss/gss_krb5_mech.c    |   12 ++++--------
 net/sunrpc/auth_gss/gss_krb5_seal.c    |    5 +----
 net/sunrpc/auth_gss/gss_krb5_unseal.c  |    5 +----
 net/sunrpc/auth_gss/gss_krb5_wrap.c    |   11 ++---------
 net/sunrpc/auth_gss/gss_mech_switch.c  |   14 ++++----------
 net/sunrpc/auth_gss/gss_spkm3_mech.c   |   21 ++++++++-------------
 net/sunrpc/auth_gss/gss_spkm3_seal.c   |    4 +---
 net/sunrpc/auth_gss/gss_spkm3_unseal.c |    2 +-
 net/sunrpc/auth_gss/svcauth_gss.c      |    9 ++++-----
 14 files changed, 41 insertions(+), 97 deletions(-)

applies-to: 750fbc08e6a6e0cb00bfad7c871144a757ac43de
00fd6e14255fe7a249315746386d640bc4e9e758
diff --git a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h
index e896752..9b8bcf1 100644
--- a/include/linux/sunrpc/gss_api.h
+++ b/include/linux/sunrpc/gss_api.h
@@ -40,23 +40,19 @@ int gss_import_sec_context(
 		struct gss_ctx		**ctx_id);
 u32 gss_get_mic(
 		struct gss_ctx		*ctx_id,
-		u32			qop,
 		struct xdr_buf		*message,
 		struct xdr_netobj	*mic_token);
 u32 gss_verify_mic(
 		struct gss_ctx		*ctx_id,
 		struct xdr_buf		*message,
-		struct xdr_netobj	*mic_token,
-		u32			*qstate);
+		struct xdr_netobj	*mic_token);
 u32 gss_wrap(
 		struct gss_ctx		*ctx_id,
-		u32			qop,
 		int			offset,
 		struct xdr_buf		*outbuf,
 		struct page		**inpages);
 u32 gss_unwrap(
 		struct gss_ctx		*ctx_id,
-		u32			*qop,
 		int			offset,
 		struct xdr_buf		*inbuf);
 u32 gss_delete_sec_context(
@@ -67,7 +63,6 @@ char *gss_service_to_auth_domain_name(st
 
 struct pf_desc {
 	u32	pseudoflavor;
-	u32	qop;
 	u32	service;
 	char	*name;
 	char	*auth_domain_name;
@@ -96,23 +91,19 @@ struct gss_api_ops {
 			struct gss_ctx		*ctx_id);
 	u32 (*gss_get_mic)(
 			struct gss_ctx		*ctx_id,
-			u32			qop, 
 			struct xdr_buf		*message,
 			struct xdr_netobj	*mic_token);
 	u32 (*gss_verify_mic)(
 			struct gss_ctx		*ctx_id,
 			struct xdr_buf		*message,
-			struct xdr_netobj	*mic_token,
-			u32			*qstate);
+			struct xdr_netobj	*mic_token);
 	u32 (*gss_wrap)(
 			struct gss_ctx		*ctx_id,
-			u32			qop,
 			int			offset,
 			struct xdr_buf		*outbuf,
 			struct page		**inpages);
 	u32 (*gss_unwrap)(
 			struct gss_ctx		*ctx_id,
-			u32			*qop,
 			int			offset,
 			struct xdr_buf		*buf);
 	void (*gss_delete_sec_context)(
diff --git a/include/linux/sunrpc/gss_err.h b/include/linux/sunrpc/gss_err.h
index 92608a2..a680786 100644
--- a/include/linux/sunrpc/gss_err.h
+++ b/include/linux/sunrpc/gss_err.h
@@ -66,16 +66,6 @@ typedef unsigned int OM_uint32;
 
 
 /*
- * Define the default Quality of Protection for per-message services.  Note
- * that an implementation that offers multiple levels of QOP may either reserve
- * a value (for example zero, as assumed here) to mean "default protection", or
- * alternatively may simply equate GSS_C_QOP_DEFAULT to a specific explicit
- * QOP value.  However a value of 0 should always be interpreted by a GSSAPI
- * implementation as a request for the default protection level.
- */
-#define GSS_C_QOP_DEFAULT 0
-
-/*
  * Expiration time of 2^32-1 seconds means infinite lifetime for a
  * credential or security context
  */
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
index 7f93c2d..a7bda4e 100644
--- a/include/linux/sunrpc/gss_krb5.h
+++ b/include/linux/sunrpc/gss_krb5.h
@@ -119,21 +119,21 @@ make_checksum(s32 cksumtype, char *heade
 		   int body_offset, struct xdr_netobj *cksum);
 
 u32
-krb5_make_token(struct krb5_ctx *context_handle, int qop_req,
+krb5_make_token(struct krb5_ctx *context_handle,
 	struct xdr_buf *input_message_buffer,
 	struct xdr_netobj *output_message_buffer);
 
 u32
 krb5_read_token(struct krb5_ctx *context_handle,
 	  struct xdr_netobj *input_token_buffer,
-	  struct xdr_buf *message_buffer, int *qop_state);
+	  struct xdr_buf *message_buffer);
 
 u32
-gss_wrap_kerberos(struct gss_ctx *ctx_id, u32 qop, int offset,
+gss_wrap_kerberos(struct gss_ctx *ctx_id, int offset,
 		struct xdr_buf *outbuf, struct page **pages);
 
 u32
-gss_unwrap_kerberos(struct gss_ctx *ctx_id, u32 *qop, int offset,
+gss_unwrap_kerberos(struct gss_ctx *ctx_id, int offset,
 		struct xdr_buf *buf);
 
 
diff --git a/include/linux/sunrpc/gss_spkm3.h b/include/linux/sunrpc/gss_spkm3.h
index b5c9968..0beb2cf 100644
--- a/include/linux/sunrpc/gss_spkm3.h
+++ b/include/linux/sunrpc/gss_spkm3.h
@@ -41,9 +41,9 @@ struct spkm3_ctx {
 #define SPKM_WRAP_TOK	5
 #define SPKM_DEL_TOK	6
 
-u32 spkm3_make_token(struct spkm3_ctx *ctx, int qop_req, struct xdr_buf * text, struct xdr_netobj * token, int toktype);
+u32 spkm3_make_token(struct spkm3_ctx *ctx, struct xdr_buf * text, struct xdr_netobj * token, int toktype);
 
-u32 spkm3_read_token(struct spkm3_ctx *ctx, struct xdr_netobj *read_token, struct xdr_buf *message_buffer, int *qop_state, int toktype);
+u32 spkm3_read_token(struct spkm3_ctx *ctx, struct xdr_netobj *read_token, struct xdr_buf *message_buffer, int toktype);
 
 #define CKSUMTYPE_RSA_MD5            0x0007
 
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 5e48720..f44f46f 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -854,9 +854,7 @@ gss_marshal(struct rpc_task *task, u32 *
 	*p++ = htonl(RPC_AUTH_GSS);
 
 	mic.data = (u8 *)(p + 1);
-	maj_stat = gss_get_mic(ctx->gc_gss_ctx,
-			       GSS_C_QOP_DEFAULT, 
-			       &verf_buf, &mic);
+	maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
 	if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
 		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
 	} else if (maj_stat != 0) {
@@ -888,7 +886,7 @@ gss_validate(struct rpc_task *task, u32 
 {
 	struct rpc_cred *cred = task->tk_msg.rpc_cred;
 	struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
-	u32		seq, qop_state;
+	u32		seq;
 	struct kvec	iov;
 	struct xdr_buf	verf_buf;
 	struct xdr_netobj mic;
@@ -909,7 +907,7 @@ gss_validate(struct rpc_task *task, u32 
 	mic.data = (u8 *)p;
 	mic.len = len;
 
-	maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic, &qop_state);
+	maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
 	if (maj_stat == GSS_S_CONTEXT_EXPIRED)
 		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
 	if (maj_stat)
@@ -961,8 +959,7 @@ gss_wrap_req_integ(struct rpc_cred *cred
 	p = iov->iov_base + iov->iov_len;
 	mic.data = (u8 *)(p + 1);
 
-	maj_stat = gss_get_mic(ctx->gc_gss_ctx,
-			GSS_C_QOP_DEFAULT, &integ_buf, &mic);
+	maj_stat = gss_get_mic(ctx->gc_gss_ctx, &integ_buf, &mic);
 	status = -EIO; /* XXX? */
 	if (maj_stat == GSS_S_CONTEXT_EXPIRED)
 		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
@@ -1057,8 +1054,7 @@ gss_wrap_req_priv(struct rpc_cred *cred,
 		memcpy(tmp, snd_buf->tail[0].iov_base, snd_buf->tail[0].iov_len);
 		snd_buf->tail[0].iov_base = tmp;
 	}
-	maj_stat = gss_wrap(ctx->gc_gss_ctx, GSS_C_QOP_DEFAULT, offset,
-				snd_buf, inpages);
+	maj_stat = gss_wrap(ctx->gc_gss_ctx, offset, snd_buf, inpages);
 	/* RPC_SLACK_SPACE should prevent this ever happening: */
 	BUG_ON(snd_buf->len > snd_buf->buflen);
         status = -EIO;
@@ -1150,8 +1146,7 @@ gss_unwrap_resp_integ(struct rpc_cred *c
 	if (xdr_buf_read_netobj(rcv_buf, &mic, mic_offset))
 		return status;
 
-	maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf,
-			&mic, NULL);
+	maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf, &mic);
 	if (maj_stat == GSS_S_CONTEXT_EXPIRED)
 		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
 	if (maj_stat != GSS_S_COMPLETE)
@@ -1176,8 +1171,7 @@ gss_unwrap_resp_priv(struct rpc_cred *cr
 	/* remove padding: */
 	rcv_buf->len = offset + opaque_len;
 
-	maj_stat = gss_unwrap(ctx->gc_gss_ctx, NULL,
-			offset, rcv_buf);
+	maj_stat = gss_unwrap(ctx->gc_gss_ctx, offset, rcv_buf);
 	if (maj_stat == GSS_S_CONTEXT_EXPIRED)
 		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
 	if (maj_stat != GSS_S_COMPLETE)
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 37a9ad9..9ffac2c 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -193,15 +193,12 @@ gss_delete_sec_context_kerberos(void *in
 static u32
 gss_verify_mic_kerberos(struct gss_ctx		*ctx,
 			struct xdr_buf		*message,
-			struct xdr_netobj	*mic_token,
-			u32			*qstate) {
+			struct xdr_netobj	*mic_token)
+{
 	u32 maj_stat = 0;
-	int qop_state;
 	struct krb5_ctx *kctx = ctx->internal_ctx_id;
 
-	maj_stat = krb5_read_token(kctx, mic_token, message, &qop_state);
-	if (!maj_stat && qop_state)
-	    *qstate = qop_state;
+	maj_stat = krb5_read_token(kctx, mic_token, message);
 
 	dprintk("RPC:      gss_verify_mic_kerberos returning %d\n", maj_stat);
 	return maj_stat;
@@ -209,13 +206,12 @@ gss_verify_mic_kerberos(struct gss_ctx		
 
 static u32
 gss_get_mic_kerberos(struct gss_ctx	*ctx,
-		     u32		qop,
 		     struct xdr_buf 	*message,
 		     struct xdr_netobj	*mic_token) {
 	u32 err = 0;
 	struct krb5_ctx *kctx = ctx->internal_ctx_id;
 
-	err = krb5_make_token(kctx, qop, message, mic_token);
+	err = krb5_make_token(kctx, message, mic_token);
 
 	dprintk("RPC:      gss_get_mic_kerberos returning %d\n",err);
 
diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
index fb852d9..15227c7 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
@@ -71,7 +71,7 @@
 #endif
 
 u32
-krb5_make_token(struct krb5_ctx *ctx, int qop_req,
+krb5_make_token(struct krb5_ctx *ctx,
 		   struct xdr_buf *text, struct xdr_netobj *token)
 {
 	s32			checksum_type;
@@ -83,9 +83,6 @@ krb5_make_token(struct krb5_ctx *ctx, in
 
 	now = get_seconds();
 
-	if (qop_req != 0)
-		goto out_err;
-
 	switch (ctx->signalg) {
 		case SGN_ALG_DES_MAC_MD5:
 			checksum_type = CKSUMTYPE_RSA_MD5;
diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
index c3d6d1b..bcf9786 100644
--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
@@ -74,7 +74,7 @@
 u32
 krb5_read_token(struct krb5_ctx *ctx,
 		struct xdr_netobj *read_token,
-		struct xdr_buf *message_buffer, int *qop_state)
+		struct xdr_buf *message_buffer)
 {
 	int			signalg;
 	int			sealalg;
@@ -157,9 +157,6 @@ krb5_read_token(struct krb5_ctx *ctx,
 
 	/* it got through unscathed.  Make sure the context is unexpired */
 
-	if (qop_state)
-		*qop_state = GSS_C_QOP_DEFAULT;
-
 	now = get_seconds();
 
 	ret = GSS_S_CONTEXT_EXPIRED;
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
index ddcde6e..af777cf 100644
--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
+++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
@@ -116,7 +116,7 @@ make_confounder(char *p, int blocksize)
 /* XXX factor out common code with seal/unseal. */
 
 u32
-gss_wrap_kerberos(struct gss_ctx *ctx, u32 qop, int offset,
+gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
 		struct xdr_buf *buf, struct page **pages)
 {
 	struct krb5_ctx		*kctx = ctx->internal_ctx_id;
@@ -132,9 +132,6 @@ gss_wrap_kerberos(struct gss_ctx *ctx, u
 
 	now = get_seconds();
 
-	if (qop != 0)
-		goto out_err;
-
 	switch (kctx->signalg) {
 		case SGN_ALG_DES_MAC_MD5:
 			checksum_type = CKSUMTYPE_RSA_MD5;
@@ -229,8 +226,7 @@ out_err:
 }
 
 u32
-gss_unwrap_kerberos(struct gss_ctx *ctx, u32 *qop, int offset,
-			struct xdr_buf *buf)
+gss_unwrap_kerberos(struct gss_ctx *ctx, int offset, struct xdr_buf *buf)
 {
 	struct krb5_ctx		*kctx = ctx->internal_ctx_id;
 	int			signalg;
@@ -328,9 +324,6 @@ gss_unwrap_kerberos(struct gss_ctx *ctx,
 
 	/* it got through unscathed.  Make sure the context is unexpired */
 
-	if (qop)
-		*qop = GSS_C_QOP_DEFAULT;
-
 	now = get_seconds();
 
 	ret = GSS_S_CONTEXT_EXPIRED;
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
index 06d97cb..b048bf6 100644
--- a/net/sunrpc/auth_gss/gss_mech_switch.c
+++ b/net/sunrpc/auth_gss/gss_mech_switch.c
@@ -250,13 +250,11 @@ gss_import_sec_context(const void *input
 
 u32
 gss_get_mic(struct gss_ctx	*context_handle,
-	    u32			qop,
 	    struct xdr_buf	*message,
 	    struct xdr_netobj	*mic_token)
 {
 	 return context_handle->mech_type->gm_ops
 		->gss_get_mic(context_handle,
-			      qop,
 			      message,
 			      mic_token);
 }
@@ -266,35 +264,31 @@ gss_get_mic(struct gss_ctx	*context_hand
 u32
 gss_verify_mic(struct gss_ctx		*context_handle,
 	       struct xdr_buf		*message,
-	       struct xdr_netobj	*mic_token,
-	       u32			*qstate)
+	       struct xdr_netobj	*mic_token)
 {
 	return context_handle->mech_type->gm_ops
 		->gss_verify_mic(context_handle,
 				 message,
-				 mic_token,
-				 qstate);
+				 mic_token);
 }
 
 u32
 gss_wrap(struct gss_ctx	*ctx_id,
-	 u32		qop,
 	 int		offset,
 	 struct xdr_buf	*buf,
 	 struct page	**inpages)
 {
 	return ctx_id->mech_type->gm_ops
-		->gss_wrap(ctx_id, qop, offset, buf, inpages);
+		->gss_wrap(ctx_id, offset, buf, inpages);
 }
 
 u32
 gss_unwrap(struct gss_ctx	*ctx_id,
-	   u32			*qop,
 	   int			offset,
 	   struct xdr_buf	*buf)
 {
 	return ctx_id->mech_type->gm_ops
-		->gss_unwrap(ctx_id, qop, offset, buf);
+		->gss_unwrap(ctx_id, offset, buf);
 }
 
 
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c
index 6c97d61..39b3edc 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_mech.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c
@@ -224,18 +224,13 @@ gss_delete_sec_context_spkm3(void *inter
 static u32
 gss_verify_mic_spkm3(struct gss_ctx		*ctx,
 			struct xdr_buf		*signbuf,
-			struct xdr_netobj	*checksum,
-			u32		*qstate) {
+			struct xdr_netobj	*checksum)
+{
 	u32 maj_stat = 0;
-	int qop_state = 0;
 	struct spkm3_ctx *sctx = ctx->internal_ctx_id;
 
 	dprintk("RPC: gss_verify_mic_spkm3 calling spkm3_read_token\n");
-	maj_stat = spkm3_read_token(sctx, checksum, signbuf, &qop_state,
-				   SPKM_MIC_TOK);
-
-	if (!maj_stat && qop_state)
-	    *qstate = qop_state;
+	maj_stat = spkm3_read_token(sctx, checksum, signbuf, SPKM_MIC_TOK);
 
 	dprintk("RPC: gss_verify_mic_spkm3 returning %d\n", maj_stat);
 	return maj_stat;
@@ -243,15 +238,15 @@ gss_verify_mic_spkm3(struct gss_ctx		*ct
 
 static u32
 gss_get_mic_spkm3(struct gss_ctx	*ctx,
-		     u32		qop,
 		     struct xdr_buf	*message_buffer,
-		     struct xdr_netobj	*message_token) {
+		     struct xdr_netobj	*message_token)
+{
 	u32 err = 0;
 	struct spkm3_ctx *sctx = ctx->internal_ctx_id;
 
 	dprintk("RPC: gss_get_mic_spkm3\n");
 
-	err = spkm3_make_token(sctx, qop, message_buffer,
+	err = spkm3_make_token(sctx, message_buffer,
 			      message_token, SPKM_MIC_TOK);
 	return err;
 }
@@ -264,8 +259,8 @@ static struct gss_api_ops gss_spkm3_ops 
 };
 
 static struct pf_desc gss_spkm3_pfs[] = {
-	{RPC_AUTH_GSS_SPKM, 0, RPC_GSS_SVC_NONE, "spkm3"},
-	{RPC_AUTH_GSS_SPKMI, 0, RPC_GSS_SVC_INTEGRITY, "spkm3i"},
+	{RPC_AUTH_GSS_SPKM, RPC_GSS_SVC_NONE, "spkm3"},
+	{RPC_AUTH_GSS_SPKMI, RPC_GSS_SVC_INTEGRITY, "spkm3i"},
 };
 
 static struct gss_api_mech gss_spkm3_mech = {
diff --git a/net/sunrpc/auth_gss/gss_spkm3_seal.c b/net/sunrpc/auth_gss/gss_spkm3_seal.c
index 2533986..148201e 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_seal.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_seal.c
@@ -51,7 +51,7 @@
  */
 
 u32
-spkm3_make_token(struct spkm3_ctx *ctx, int qop_req,
+spkm3_make_token(struct spkm3_ctx *ctx,
 		   struct xdr_buf * text, struct xdr_netobj * token,
 		   int toktype)
 {
@@ -68,8 +68,6 @@ spkm3_make_token(struct spkm3_ctx *ctx, 
 	dprintk("RPC: spkm3_make_token\n");
 
 	now = jiffies;
-	if (qop_req != 0)
-		goto out_err;
 
 	if (ctx->ctx_id.len != 16) {
 		dprintk("RPC: spkm3_make_token BAD ctx_id.len %d\n",
diff --git a/net/sunrpc/auth_gss/gss_spkm3_unseal.c b/net/sunrpc/auth_gss/gss_spkm3_unseal.c
index 65ce81b..c3c0d95 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_unseal.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_unseal.c
@@ -52,7 +52,7 @@ u32
 spkm3_read_token(struct spkm3_ctx *ctx,
 		struct xdr_netobj *read_token,    /* checksum */
 		struct xdr_buf *message_buffer, /* signbuf */
-		int *qop_state, int toktype)
+		int toktype)
 {
 	s32			code;
 	struct xdr_netobj	wire_cksum = {.len =0, .data = NULL};
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index e330819..e4ada15 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -566,8 +566,7 @@ gss_verify_header(struct svc_rqst *rqstp
 
 	if (rqstp->rq_deferred) /* skip verification of revisited request */
 		return SVC_OK;
-	if (gss_verify_mic(ctx_id, &rpchdr, &checksum, NULL)
-							!= GSS_S_COMPLETE) {
+	if (gss_verify_mic(ctx_id, &rpchdr, &checksum) != GSS_S_COMPLETE) {
 		*authp = rpcsec_gsserr_credproblem;
 		return SVC_DENIED;
 	}
@@ -604,7 +603,7 @@ gss_write_verf(struct svc_rqst *rqstp, s
 	xdr_buf_from_iov(&iov, &verf_data);
 	p = rqstp->rq_res.head->iov_base + rqstp->rq_res.head->iov_len;
 	mic.data = (u8 *)(p + 1);
-	maj_stat = gss_get_mic(ctx_id, 0, &verf_data, &mic);
+	maj_stat = gss_get_mic(ctx_id, &verf_data, &mic);
 	if (maj_stat != GSS_S_COMPLETE)
 		return -1;
 	*p++ = htonl(mic.len);
@@ -710,7 +709,7 @@ unwrap_integ_data(struct xdr_buf *buf, u
 		goto out;
 	if (read_bytes_from_xdr_buf(buf, integ_len + 4, mic.data, mic.len))
 		goto out;
-	maj_stat = gss_verify_mic(ctx, &integ_buf, &mic, NULL);
+	maj_stat = gss_verify_mic(ctx, &integ_buf, &mic);
 	if (maj_stat != GSS_S_COMPLETE)
 		goto out;
 	if (ntohl(svc_getu32(&buf->head[0])) != seq)
@@ -1012,7 +1011,7 @@ svcauth_gss_release(struct svc_rqst *rqs
 			resv = &resbuf->tail[0];
 		}
 		mic.data = (u8 *)resv->iov_base + resv->iov_len + 4;
-		if (gss_get_mic(gsd->rsci->mechctx, 0, &integ_buf, &mic))
+		if (gss_get_mic(gsd->rsci->mechctx, &integ_buf, &mic))
 			goto out_err;
 		svc_putu32(resv, htonl(mic.len));
 		memset(mic.data + mic.len, 0,
---
0.99.8.GIT


--- NEW FILE 0603-RPCSEC_GSS-krb5-cleanup.txt ---
Subject: [PATCH] RPCSEC_GSS: krb5 cleanup
From: J. Bruce Fields <bfields fieldses org>
Date: 1129236923 -0400

 Remove some senseless wrappers.

 Signed-off-by: J. Bruce Fields <bfields citi umich edu>
 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 include/linux/sunrpc/gss_krb5.h       |   12 ++++--------
 net/sunrpc/auth_gss/gss_krb5_mech.c   |   28 ----------------------------
 net/sunrpc/auth_gss/gss_krb5_seal.c   |    5 +++--
 net/sunrpc/auth_gss/gss_krb5_unseal.c |    6 +++---
 4 files changed, 10 insertions(+), 41 deletions(-)

applies-to: 36d8fad57404c5ea96cdb6e5579f4241e2cd8188
a0857d03b21fa54653c9d2fe7a315381176015b4
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
index a7bda4e..2c3601d 100644
--- a/include/linux/sunrpc/gss_krb5.h
+++ b/include/linux/sunrpc/gss_krb5.h
@@ -118,15 +118,11 @@ s32
 make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
 		   int body_offset, struct xdr_netobj *cksum);
 
-u32
-krb5_make_token(struct krb5_ctx *context_handle,
-	struct xdr_buf *input_message_buffer,
-	struct xdr_netobj *output_message_buffer);
+u32 gss_get_mic_kerberos(struct gss_ctx *, struct xdr_buf *,
+		struct xdr_netobj *);
 
-u32
-krb5_read_token(struct krb5_ctx *context_handle,
-	  struct xdr_netobj *input_token_buffer,
-	  struct xdr_buf *message_buffer);
+u32 gss_verify_mic_kerberos(struct gss_ctx *, struct xdr_buf *,
+		struct xdr_netobj *);
 
 u32
 gss_wrap_kerberos(struct gss_ctx *ctx_id, int offset,
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 9ffac2c..5f1f806 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -190,34 +190,6 @@ gss_delete_sec_context_kerberos(void *in
 	kfree(kctx);
 }
 
-static u32
-gss_verify_mic_kerberos(struct gss_ctx		*ctx,
-			struct xdr_buf		*message,
-			struct xdr_netobj	*mic_token)
-{
-	u32 maj_stat = 0;
-	struct krb5_ctx *kctx = ctx->internal_ctx_id;
-
-	maj_stat = krb5_read_token(kctx, mic_token, message);
-
-	dprintk("RPC:      gss_verify_mic_kerberos returning %d\n", maj_stat);
-	return maj_stat;
-}
-
-static u32
-gss_get_mic_kerberos(struct gss_ctx	*ctx,
-		     struct xdr_buf 	*message,
-		     struct xdr_netobj	*mic_token) {
-	u32 err = 0;
-	struct krb5_ctx *kctx = ctx->internal_ctx_id;
-
-	err = krb5_make_token(kctx, message, mic_token);
-
-	dprintk("RPC:      gss_get_mic_kerberos returning %d\n",err);
-
-	return err;
-}
-
 static struct gss_api_ops gss_kerberos_ops = {
 	.gss_import_sec_context	= gss_import_sec_context_kerberos,
 	.gss_get_mic		= gss_get_mic_kerberos,
diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
index 15227c7..13f8ae9 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
@@ -71,9 +71,10 @@
 #endif
 
 u32
-krb5_make_token(struct krb5_ctx *ctx,
-		   struct xdr_buf *text, struct xdr_netobj *token)
+gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
+		struct xdr_netobj *token)
 {
+	struct krb5_ctx		*ctx = gss_ctx->internal_ctx_id;
 	s32			checksum_type;
 	struct xdr_netobj	md5cksum = {.len = 0, .data = NULL};
 	unsigned char		*ptr, *krb5_hdr, *msg_start;
diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
index bcf9786..2030475 100644
--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
@@ -72,10 +72,10 @@
  * supposedly taken over. */
 
 u32
-krb5_read_token(struct krb5_ctx *ctx,
-		struct xdr_netobj *read_token,
-		struct xdr_buf *message_buffer)
+gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
+		struct xdr_buf *message_buffer, struct xdr_netobj *read_token)
 {
+	struct krb5_ctx		*ctx = gss_ctx->internal_ctx_id;
 	int			signalg;
 	int			sealalg;
 	s32			checksum_type;
---
0.99.8.GIT


--- NEW FILE 0610-Fixed-problem-with-not-being-able-to-decrypt-encrypt-broadcast-packets.txt ---
Subject: [PATCH] Fixed problem with not being able to decrypt/encrypt broadcast packets.
From: Hong Liu <hong liu intel com>
Date: 1129757494 -0500

Signed-off-by: James Ketrenos <jketreno linux intel com>

---

 net/ieee80211/ieee80211_rx.c |    3 ++-
 net/ieee80211/ieee80211_tx.c |    3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

applies-to: aea6ab8810c74be573d4e5f032b6aac46e16dbd2
5b74eda78db410b979b7d450221c971fdebf5d29
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 6b005cb..ce694cf 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -409,7 +409,8 @@ int ieee80211_rx(struct ieee80211_device
 		return 1;
 	}
 
-	if (is_multicast_ether_addr(hdr->addr1) ? ieee->host_mc_decrypt :
+	if ((is_multicast_ether_addr(hdr->addr1) ||
+	     is_broadcast_ether_addr(hdr->addr2)) ? ieee->host_mc_decrypt :
 	    ieee->host_decrypt) {
 		int idx = 0;
 		if (skb->len >= hdrlen + 3)
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index 42c5061..2955b7a 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -338,7 +338,8 @@ int ieee80211_xmit(struct sk_buff *skb, 
 	if (host_encrypt || ieee->host_open_frag) {
 		/* Determine fragmentation size based on destination (multicast
 		 * and broadcast are not fragmented) */
-		if (is_multicast_ether_addr(dest))
+		if (is_multicast_ether_addr(dest) ||
+		    is_broadcast_ether_addr(dest))
 			frag_size = MAX_FRAG_THRESHOLD;
 		else
 			frag_size = ieee->fts;
---
0.99.8.GIT


--- NEW FILE 0635-Fixed-oops-if-an-uninitialized-key-is-used-for-encryption.txt ---
Subject: [PATCH] Fixed oops if an uninitialized key is used for encryption.
From: Hong Liu <hong liu intel com>
Date: 1129824396 -0500

Without this patch, if you try and use a key that has not been
configured, for example:

% iwconfig eth1 key deadbeef00 [2]

without having configured key [1], then the active key will still be
[1], but privacy will now be enabled.  Transmission of a packet in this
situation will result in a kernel oops.

Signed-off-by: James Ketrenos <jketreno linux intel com>

---

 net/ieee80211/ieee80211_tx.c |   11 +++++++----
 1 files changed, 7 insertions(+), 4 deletions(-)

applies-to: 4dd2ee158b10bf11e4f34ba00a28e09cdacbf272
f0f15ab5542f73d07e35eeee713df289599427b2
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index 2955b7a..f4f2a33 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -157,11 +157,14 @@ static inline int ieee80211_encrypt_frag
 	struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx];
 	int res;
 
+	if (crypt == NULL)
+		return -1;
+
 	/* To encrypt, frame format is:
 	 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
 	atomic_inc(&crypt->refcnt);
 	res = 0;
-	if (crypt->ops->encrypt_mpdu)
+	if (crypt->ops && crypt->ops->encrypt_mpdu)
 		res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
 
 	atomic_dec(&crypt->refcnt);
@@ -264,9 +267,9 @@ int ieee80211_xmit(struct sk_buff *skb, 
 	encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
 	    ieee->sec.encrypt;
 
-	host_encrypt = ieee->host_encrypt && encrypt;
-	host_encrypt_msdu = ieee->host_encrypt_msdu && encrypt;
-	host_build_iv = ieee->host_build_iv && encrypt;
+	host_encrypt = ieee->host_encrypt && encrypt && crypt;
+	host_encrypt_msdu = ieee->host_encrypt_msdu && encrypt && crypt;
+	host_build_iv = ieee->host_build_iv && encrypt && crypt;
 
 	if (!encrypt && ieee->ieee802_1x &&
 	    ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
---
0.99.8.GIT


--- NEW FILE 0658-ieee80211-subsystem.txt ---
Subject: [PATCH] ieee80211 subsystem:
From: Michael Buesch <mbuesch freenet de>
Date: 1129916392 -0500
* Use GFP mask on TX skb allocation.
* Use the tx_headroom and reserve requested space.

Signed-off-by: Michael Buesch <mbuesch freenet de>
Signed-off-by: James Ketrenos <jketreno linux intel com>

---

 net/ieee80211/ieee80211_tx.c |    9 ++++++---
 1 files changed, 6 insertions(+), 3 deletions(-)

applies-to: 4e511a4d571f5cf9838c99bd9bb5b6e06a06e263
d3f7bf4fa9626d371f26cd310477202628a8126a
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index f4f2a33..fb45090 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -190,7 +190,7 @@ void ieee80211_txb_free(struct ieee80211
 }
 
 static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
-						 gfp_t gfp_mask)
+						 int headroom, gfp_t gfp_mask)
 {
 	struct ieee80211_txb *txb;
 	int i;
@@ -204,11 +204,13 @@ static struct ieee80211_txb *ieee80211_a
 	txb->frag_size = txb_size;
 
 	for (i = 0; i < nr_frags; i++) {
-		txb->fragments[i] = dev_alloc_skb(txb_size);
+		txb->fragments[i] = __dev_alloc_skb(txb_size + headroom,
+						    gfp_mask);
 		if (unlikely(!txb->fragments[i])) {
 			i--;
 			break;
 		}
+		skb_reserve(txb->fragments[i], headroom);
 	}
 	if (unlikely(i != nr_frags)) {
 		while (i >= 0)
@@ -384,7 +386,8 @@ int ieee80211_xmit(struct sk_buff *skb, 
 	/* When we allocate the TXB we allocate enough space for the reserve
 	 * and full fragment bytes (bytes_per_frag doesn't include prefix,
 	 * postfix, header, FCS, etc.) */
-	txb = ieee80211_alloc_txb(nr_frags, frag_size, GFP_ATOMIC);
+	txb = ieee80211_alloc_txb(nr_frags, frag_size,
+				  ieee->tx_headroom, GFP_ATOMIC);
 	if (unlikely(!txb)) {
 		printk(KERN_WARNING "%s: Could not allocate TXB\n",
 		       ieee->dev->name);
---
0.99.8.GIT


--- NEW FILE 0659-Update-version-ieee80211-stamp-to-1.1.6.txt ---
Subject: [PATCH] Update version ieee80211 stamp to 1.1.6
From: James Ketrenos <jketreno linux intel com>
Date: 1129841823 -0500

---

 include/net/ieee80211.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

applies-to: 7b12b1ed327ff6f8e9820979e302e23e6a157223
519a62bb8a0b0b383e6022cad6242cf63efc015c
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 58f6222..5e38dca 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -29,7 +29,7 @@
 #include <linux/kernel.h>	/* ARRAY_SIZE */
 #include <linux/wireless.h>
 
-#define IEEE80211_VERSION "git-1.1.5"
+#define IEEE80211_VERSION "git-1.1.6"
 
 #define IEEE80211_DATA_LEN		2304
 /* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
---
0.99.8.GIT


--- NEW FILE 0759-DECNET-Remove-some-redundant-ifdeffed-code.txt ---
Subject: [PATCH] [DECNET]: Remove some redundant ifdeffed code
From: Patrick Caulfield <patrick tykepenguin com>
Date: 1129015353 +0100

Signed-off-by: Patrick Caulfield <patrick tykepenguin com>
Signed-off-by: Steven Whitehouse <steve chygwyn com>
Signed-off-by: David S. Miller <davem davemloft net>
Signed-off-by: Arnaldo Carvalho de Melo <acme mandriva com>

---

 net/decnet/af_decnet.c |   13 -------------
 1 files changed, 0 insertions(+), 13 deletions(-)

applies-to: 71b9717387e4b3ec8124ab23d53850b00e9be86f
900e0143a575406146ac531fcb91790f166ce52f
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index 1186dc4..3f25cad 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -719,22 +719,9 @@ static int dn_bind(struct socket *sock, 
 	if (saddr->sdn_flags & ~SDF_WILD)
 		return -EINVAL;
 
-#if 1
 	if (!capable(CAP_NET_BIND_SERVICE) && (saddr->sdn_objnum ||
 	    (saddr->sdn_flags & SDF_WILD)))
 		return -EACCES;
-#else
-	/*
-	 * Maybe put the default actions in the default security ops for
-	 * dn_prot_sock ? Would be nice if the capable call would go there
-	 * too.
-	 */
-	if (security_dn_prot_sock(saddr) &&
-	    !capable(CAP_NET_BIND_SERVICE) || 
-	    saddr->sdn_objnum || (saddr->sdn_flags & SDF_WILD))
-		return -EACCES;
-#endif
-
 
 	if (!(saddr->sdn_flags & SDF_WILD)) {
 		if (dn_ntohs(saddr->sdn_nodeaddrl)) {
---
0.99.8.GIT


--- NEW FILE 0760-NET-Wider-use-of-for_each_-cpu.txt ---
Subject: [PATCH] [NET]: Wider use of for_each_*cpu()
From: John Hawkes <hawkes sgi com>
Date: 1129221031 -0700

In 'net' change the explicit use of for-loops and NR_CPUS into the
general for_each_cpu() or for_each_online_cpu() constructs, as
appropriate.  This widens the scope of potential future optimizations
of the general constructs, as well as takes advantage of the existing
optimizations of first_cpu() and next_cpu(), which is advantageous
when the true CPU count is much smaller than NR_CPUS.

Signed-off-by: John Hawkes <hawkes sgi com>
Signed-off-by: David S. Miller <davem davemloft net>
Signed-off-by: Arnaldo Carvalho de Melo <acme mandriva com>

---

 net/core/neighbour.c |    5 +----
 net/core/pktgen.c    |    5 +----
 net/ipv4/icmp.c      |    5 +----
 net/ipv4/proc.c      |    4 +---
 net/ipv6/icmp.c      |    9 ++-------
 net/ipv6/proc.c      |    4 +---
 net/sctp/proc.c      |    4 +---
 7 files changed, 8 insertions(+), 28 deletions(-)

applies-to: d75e7e5cbf6303dddafe4f123a7f4bbba7146570
670c02c2bfd2c8a305a90f5285409a7b0a8fd630
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 1dcf7fa..e68700f 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1625,12 +1625,9 @@ static int neightbl_fill_info(struct nei
 
 		memset(&ndst, 0, sizeof(ndst));
 
-		for (cpu = 0; cpu < NR_CPUS; cpu++) {
+		for_each_cpu(cpu) {
 			struct neigh_statistics	*st;
 
-			if (!cpu_possible(cpu))
-				continue;
-
 			st = per_cpu_ptr(tbl->stats, cpu);
 			ndst.ndts_allocs		+= st->allocs;
 			ndst.ndts_destroys		+= st->destroys;
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 5f043d3..00116d8 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -3065,12 +3065,9 @@ static int __init pg_init(void) 
 	/* Register us to receive netdevice events */
 	register_netdevice_notifier(&pktgen_notifier_block);
         
-	for (cpu = 0; cpu < NR_CPUS ; cpu++) {
+	for_each_online_cpu(cpu) {
 		char buf[30];
 
-		if (!cpu_online(cpu))
-			continue;
-
                 sprintf(buf, "kpktgend_%i", cpu);
                 pktgen_create_thread(buf, cpu);
         }
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 90dca71..175e093 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -1108,12 +1108,9 @@ void __init icmp_init(struct net_proto_f
 	struct inet_sock *inet;
 	int i;
 
-	for (i = 0; i < NR_CPUS; i++) {
+	for_each_cpu(i) {
 		int err;
 
-		if (!cpu_possible(i))
-			continue;
-
 		err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_ICMP,
 				       &per_cpu(__icmp_socket, i));
 
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index f7943ba..a65e508 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -90,9 +90,7 @@ fold_field(void *mib[], int offt)
 	unsigned long res = 0;
 	int i;
 
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!cpu_possible(i))
-			continue;
+	for_each_cpu(i) {
 		res += *(((unsigned long *) per_cpu_ptr(mib[0], i)) + offt);
 		res += *(((unsigned long *) per_cpu_ptr(mib[1], i)) + offt);
 	}
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index b7185fb..23e5403 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -700,10 +700,7 @@ int __init icmpv6_init(struct net_proto_
 	struct sock *sk;
 	int err, i, j;
 
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!cpu_possible(i))
-			continue;
-
+	for_each_cpu(i) {
 		err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6,
 				       &per_cpu(__icmpv6_socket, i));
 		if (err < 0) {
@@ -749,9 +746,7 @@ void icmpv6_cleanup(void)
 {
 	int i;
 
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!cpu_possible(i))
-			continue;
+	for_each_cpu(i) {
 		sock_release(per_cpu(__icmpv6_socket, i));
 	}
 	inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6);
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 334a596..50a13e7 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -140,9 +140,7 @@ fold_field(void *mib[], int offt)
         unsigned long res = 0;
         int i;
  
-        for (i = 0; i < NR_CPUS; i++) {
-                if (!cpu_possible(i))
-                        continue;
+        for_each_cpu(i) {
                 res += *(((unsigned long *)per_cpu_ptr(mib[0], i)) + offt);
                 res += *(((unsigned long *)per_cpu_ptr(mib[1], i)) + offt);
         }
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index b74f777..6e4dc28 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -69,9 +69,7 @@ fold_field(void *mib[], int nr)
 	unsigned long res = 0;
 	int i;
 
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!cpu_possible(i))
-			continue;
+	for_each_cpu(i) {
 		res +=
 		    *((unsigned long *) (((void *) per_cpu_ptr(mib[0], i)) +
 					 sizeof (unsigned long) * nr));
---
0.99.8.GIT


--- NEW FILE 0761-PKTGEN-Sleeping-function-called-under-lock.txt ---
Subject: [PATCH] [PKTGEN]: Sleeping function called under lock
From: Stephen Hemminger <shemminger osdl org>
Date: 1129328794 -0700

pktgen is calling kmalloc GFP_KERNEL and vmalloc with lock held.
The simplest fix is to turn the lock into a semaphore, since the
thread lock is only used for admin control from user context.

Signed-off-by: Stephen Hemminger <shemminger osdl org>
Signed-off-by: Robert Olsson <robert olsson its uu se>
Signed-off-by: David S. Miller <davem davemloft net>
Signed-off-by: Arnaldo Carvalho de Melo <acme mandriva com>

---

 net/core/pktgen.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

applies-to: a6e7d773d72e2716bf675dbb2679e8ada21b4e21
b7c8921bf1a8a9c1907b1eeb029d3f167be226f3
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 00116d8..8a90bf7 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -177,8 +177,8 @@
 #define T_REMDEV      (1<<3)  /* Remove all devs */
 
 /* Locks */
-#define   thread_lock()        spin_lock(&_thread_lock)
-#define   thread_unlock()      spin_unlock(&_thread_lock)
+#define   thread_lock()        down(&pktgen_sem)
+#define   thread_unlock()      up(&pktgen_sem)
 
 /* If lock -- can be removed after some work */
 #define   if_lock(t)           spin_lock(&(t->if_lock));
@@ -503,7 +503,7 @@ static int pg_delay_d = 0;
 static int pg_clone_skb_d = 0;
 static int debug = 0;
 
-static DEFINE_SPINLOCK(_thread_lock);
+static DECLARE_MUTEX(pktgen_sem);
 static struct pktgen_thread *pktgen_threads = NULL;
 
 static char module_fname[128];
---
0.99.8.GIT


--- NEW FILE 0762-PKTGEN-Use-kzalloc.txt ---
Subject: [PATCH] [PKTGEN]: Use kzalloc
From: Stephen Hemminger <shemminger osdl org>
Date: 1129328988 -0700

These are cleanup patches for pktgen that can go in 2.6.15
Can use kzalloc in a couple of places.

Signed-off-by: Stephen Hemminger <shemminger osdl org>
Signed-off-by: Robert Olsson <robert olsson its uu se>
Signed-off-by: David S. Miller <davem davemloft net>
Signed-off-by: Arnaldo Carvalho de Melo <acme mandriva com>

---

 net/core/pktgen.c |    7 ++-----
 1 files changed, 2 insertions(+), 5 deletions(-)

applies-to: 8b3fcc1f10d297ddde054f8be887cd09129e0320
2845b63b504b051a9cb4d78bed8b3594451a1f6f
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 8a90bf7..b597ef1 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -2869,12 +2869,10 @@ static int pktgen_add_device(struct pktg
 
 	if( (pkt_dev = __pktgen_NN_threads(ifname, FIND)) == NULL) {
 						   
-		pkt_dev = kmalloc(sizeof(struct pktgen_dev), GFP_KERNEL);
+		pkt_dev = kzalloc(sizeof(struct pktgen_dev), GFP_KERNEL);
                 if (!pkt_dev) 
                         return -ENOMEM;
 
-                memset(pkt_dev, 0, sizeof(struct pktgen_dev));
-
 		pkt_dev->flows = vmalloc(MAX_CFLOWS*sizeof(struct flow_state));
 		if (pkt_dev->flows == NULL) {
 			kfree(pkt_dev);
@@ -2958,13 +2956,12 @@ static int pktgen_create_thread(const ch
                 return -EINVAL;
         }
 
-        t = (struct pktgen_thread*)(kmalloc(sizeof(struct pktgen_thread), GFP_KERNEL));
+        t = kzalloc(sizeof(struct pktgen_thread), GFP_KERNEL);
         if (!t) {
                 printk("pktgen: ERROR: out of memory, can't create new thread.\n");
                 return -ENOMEM;
         }
 
-        memset(t, 0, sizeof(struct pktgen_thread));
         strcpy(t->name, name);
         spin_lock_init(&t->if_lock);
 	t->cpu = cpu;
---
0.99.8.GIT


--- NEW FILE 0763-PKTGEN-Spelling-and-white-space.txt ---
Subject: [PATCH] [PKTGEN]: Spelling and white space
From: Stephen Hemminger <shemminger osdl org>
Date: 1129329142 -0700

Fix some cosmetic issues. Indentation, spelling errors, and some whitespace.

Signed-off-by: Stephen Hemminger <shemminger osdl org>
Signed-off-by: Robert Olsson <robert olsson its uu se>
Signed-off-by: David S. Miller <davem davemloft net>
Signed-off-by: Arnaldo Carvalho de Melo <acme mandriva com>

---

 net/core/pktgen.c |   24 ++++++++++++------------
 1 files changed, 12 insertions(+), 12 deletions(-)

applies-to: 6de91ce8e5c07ec3bfd670605e8de916eec3b9ad
b4099fab75d5e3eae8d207c0d7159e2f3348686e
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index b597ef1..ad053c8 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -75,7 +75,7 @@
  * By design there should only be *one* "controlling" process. In practice 
  * multiple write accesses gives unpredictable result. Understood by "write" 
  * to /proc gives result code thats should be read be the "writer".
- * For pratical use this should be no problem.
+ * For practical use this should be no problem.
  *
  * Note when adding devices to a specific CPU there good idea to also assign 
  * /proc/irq/XX/smp_affinity so TX-interrupts gets bound to the same CPU. 
@@ -96,7 +96,7 @@
  * New xmit() return, do_div and misc clean up by Stephen Hemminger 
  * <shemminger osdl org> 040923
  *
- * Rany Dunlap fixed u64 printk compiler waring 
+ * Randy Dunlap fixed u64 printk compiler waring 
  *
  * Remove FCS from BW calculation.  Lennert Buytenhek <buytenh wantstofly org>
  * New time handling. Lennert Buytenhek <buytenh wantstofly org> 041213
@@ -244,7 +244,7 @@ struct pktgen_dev {
         __u32 seq_num;
         
         int clone_skb; /* Use multiple SKBs during packet gen.  If this number
-                          * is greater than 1, then that many coppies of the same
+                          * is greater than 1, then that many copies of the same
                           * packet will be sent before a new packet is allocated.
                           * For instance, if you want to send 1024 identical packets
                           * before creating a new packet, set clone_skb to 1024.
@@ -396,7 +396,7 @@ static inline s64 divremdi3(s64 x, s64 y
 
 /* End of hacks to deal with 64-bit math on x86 */
 
-/** Convert to miliseconds */
+/** Convert to milliseconds */
 static inline __u64 tv_to_ms(const struct timeval* tv) 
 {
         __u64 ms = tv->tv_usec / 1000;
@@ -425,7 +425,7 @@ static inline __u64 pg_div64(__u64 n, __
 {
         __u64 tmp = n;
 /*
- * How do we know if the architectrure we are running on
+ * How do we know if the architecture we are running on
  * supports division with 64 bit base?
  * 
  */
@@ -544,12 +544,12 @@ static ssize_t proc_pgctrl_read(struct f
 	len = strlen(data);
 
 	if(len > count) {
-		len =-EFAULT;
+		len = -EFAULT;
 		goto out;
 	}  	
 
 	if (copy_to_user(buf, data, len)) {
-		len =-EFAULT;
+		len = -EFAULT;
 		goto out;
 	}  
 
@@ -578,7 +578,7 @@ static ssize_t proc_pgctrl_write(struct 
 		goto out;
 	}
 	if (copy_from_user(data, buf, count)) {
-		err =-EFAULT;
+		err = -EFAULT;
 		goto out_free;
 	}  
 	data[count-1] = 0; /* Make string */
@@ -1702,7 +1702,7 @@ static void spin(struct pktgen_dev *pkt_
 	start = now = getCurUs();
 	printk(KERN_INFO "sleeping for %d\n", (int)(spin_until_us - now));
 	while (now < spin_until_us) {
-		/* TODO: optimise sleeping behavior */
+		/* TODO: optimize sleeping behavior */
 		if (spin_until_us - now > jiffies_to_usecs(1)+1)
 			schedule_timeout_interruptible(1);
 		else if (spin_until_us - now > 100) {
@@ -2361,7 +2361,7 @@ static void pktgen_stop_all_threads_ifs(
 		pktgen_stop(t);
 		t = t->next;
 	}
-       thread_unlock();
+	thread_unlock();
 }
 
 static int thread_is_running(struct pktgen_thread *t )
@@ -2555,7 +2555,7 @@ static void pktgen_rem_thread(struct pkt
         if (strlen(t->fname))
                 remove_proc_entry(t->fname, NULL);
 
-       thread_lock();
+	thread_lock();
 
 	if (tmp == t)
 		pktgen_threads = tmp->next;
@@ -2929,7 +2929,7 @@ static struct pktgen_thread *pktgen_find
 {
         struct pktgen_thread *t = NULL;
 
-       thread_lock();
+	thread_lock();
 
         t = pktgen_threads;
         while (t) {
---
0.99.8.GIT


--- NEW FILE 0764-PKTGEN-proc-interface-revision.txt ---
Subject: [PATCH] [PKTGEN]: proc interface revision
From: Stephen Hemminger <shemminger osdl org>
Date: 1129329753 -0700

The code to handle the /proc interface can be cleaned up in several places:
* use seq_file for read
* don't need to remember all the filenames separately
* use for_online_cpu's
* don't vmalloc a buffer for small command from user.

Committer note:
This patch clashed with John Hawkes's "[NET]: Wider use of for_each_*cpu()",
so I fixed it up manually.

Signed-off-by: Stephen Hemminger <shemminger osdl org>
Signed-off-by: Robert Olsson <robert olsson its uu se>
Signed-off-by: David S. Miller <davem davemloft net>
Signed-off-by: Arnaldo Carvalho de Melo <acme mandriva com>

---

 net/core/pktgen.c |  476 ++++++++++++++++++++++++-----------------------------
 1 files changed, 217 insertions(+), 259 deletions(-)

applies-to: 62e1e42f5422c14491a5b7bd90d48da057912b17
d50a6b56f0f239cf061630c85add121dc3555339
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index ad053c8..7fc3e9e 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -137,6 +137,7 @@
 #include <linux/ipv6.h>
 #include <linux/udp.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/wait.h>
 #include <net/checksum.h>
 #include <net/ipv6.h>
@@ -151,7 +152,7 @@
 #include <asm/timex.h>
 
 
-#define VERSION  "pktgen v2.62: Packet Generator for packet performance testing.\n"
+#define VERSION  "pktgen v2.63: Packet Generator for packet performance testing.\n"
 
 /* #define PG_DEBUG(a) a */
 #define PG_DEBUG(a) 
@@ -186,7 +187,9 @@
 
 /* Used to help with determining the pkts on receive */
 #define PKTGEN_MAGIC 0xbe9be955
-#define PG_PROC_DIR "net/pktgen"
+#define PG_PROC_DIR "pktgen"
+#define PGCTRL	    "pgctrl"
+static struct proc_dir_entry *pg_proc_dir = NULL;
 
 #define MAX_CFLOWS  65536
 
@@ -202,11 +205,8 @@ struct pktgen_dev {
 	 * Try to keep frequent/infrequent used vars. separated.
 	 */
 
-        char ifname[32];
-        struct proc_dir_entry *proc_ent;
+        char ifname[IFNAMSIZ];
         char result[512];
-        /* proc file names */
-        char fname[80];
 
         struct pktgen_thread* pg_thread; /* the owner */
         struct pktgen_dev *next; /* Used for chaining in the thread's run-queue */
@@ -330,8 +330,6 @@ struct pktgen_thread {
         struct pktgen_dev *if_list;           /* All device here */
         struct pktgen_thread* next;
         char name[32];
-        char fname[128]; /* name of proc file */
-        struct proc_dir_entry *proc_ent;
         char result[512];
         u32 max_before_softirq; /* We'll call do_softirq to prevent starvation. */
         
@@ -473,16 +471,6 @@ static inline __u64 tv_diff(const struct
 
 static char version[] __initdata = VERSION;
 
-static ssize_t proc_pgctrl_read(struct file* file, char __user * buf, size_t count, loff_t *ppos);
-static ssize_t proc_pgctrl_write(struct file* file, const char __user * buf, size_t count, loff_t *ppos);
-static int proc_if_read(char *buf , char **start, off_t offset, int len, int *eof, void *data);
-
-static int proc_thread_read(char *buf , char **start, off_t offset, int len, int *eof, void *data);
-static int proc_if_write(struct file *file, const char __user *user_buffer, unsigned long count, void *data);
-static int proc_thread_write(struct file *file, const char __user *user_buffer, unsigned long count, void *data);
-static int create_proc_dir(void);
-static int remove_proc_dir(void);
-
 static int pktgen_remove_device(struct pktgen_thread* t, struct pktgen_dev *i);
 static int pktgen_add_device(struct pktgen_thread* t, const char* ifname);
 static struct pktgen_thread* pktgen_find_thread(const char* name);
@@ -506,80 +494,38 @@ static int debug = 0;
 static DECLARE_MUTEX(pktgen_sem);
 static struct pktgen_thread *pktgen_threads = NULL;
 
-static char module_fname[128];
-static struct proc_dir_entry *module_proc_ent = NULL;
-
 static struct notifier_block pktgen_notifier_block = {
 	.notifier_call = pktgen_device_event,
 };
 
-static struct file_operations pktgen_fops = {
-        .read     = proc_pgctrl_read,
-        .write    = proc_pgctrl_write,
-	/*  .ioctl    = pktgen_ioctl, later maybe */
-};
-
 /*
  * /proc handling functions 
  *
  */
 
-static struct proc_dir_entry *pg_proc_dir = NULL;
-static int proc_pgctrl_read_eof=0;
-
-static ssize_t proc_pgctrl_read(struct file* file, char __user * buf,
-                                 size_t count, loff_t *ppos)
+static int pgctrl_show(struct seq_file *seq, void *v)
 { 
-	char data[200];
-	int len = 0;
-
-	if(proc_pgctrl_read_eof) {
-		proc_pgctrl_read_eof=0;
-		len = 0;
-		goto out;
-	}
-
-	sprintf(data, "%s", VERSION); 
-
-	len = strlen(data);
-
-	if(len > count) {
-		len = -EFAULT;
-		goto out;
-	}  	
-
-	if (copy_to_user(buf, data, len)) {
-		len = -EFAULT;
-		goto out;
-	}  
-
-	*ppos += len;
-	proc_pgctrl_read_eof=1; /* EOF next call */
-
- out:
-	return len;
+	seq_puts(seq, VERSION);
+	return 0;
 }
 
-static ssize_t proc_pgctrl_write(struct file* file,const char __user * buf,
-				 size_t count, loff_t *ppos)
+static ssize_t pgctrl_write(struct file* file,const char __user * buf,
+			    size_t count, loff_t *ppos)
 {
-	char *data = NULL;
 	int err = 0;
+	char data[128];
 
         if (!capable(CAP_NET_ADMIN)){
                 err = -EPERM;
 		goto out;
         }
 
-	data = (void*)vmalloc ((unsigned int)count);
+	if (count > sizeof(data))
+		count = sizeof(data);
 
-	if(!data) {
-		err = -ENOMEM;
-		goto out;
-	}
 	if (copy_from_user(data, buf, count)) {
 		err = -EFAULT;
-		goto out_free;
+		goto out;
 	}  
 	data[count-1] = 0; /* Make string */
 
@@ -594,31 +540,40 @@ static ssize_t proc_pgctrl_write(struct 
 
 	err = count;
 
- out_free:
-	vfree (data);
  out:
         return err;
 }
 
-static int proc_if_read(char *buf , char **start, off_t offset,
-                           int len, int *eof, void *data)
+static int pgctrl_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, pgctrl_show, PDE(inode)->data);
+}
+
+static struct file_operations pktgen_fops = {
+	.owner	  = THIS_MODULE,
+	.open	  = pgctrl_open,
+        .read     = seq_read,
+	.llseek	  = seq_lseek,
+        .write    = pgctrl_write,
+	.release  = single_release,
+};
+
+static int pktgen_if_show(struct seq_file *seq, void *v)
 {
-	char *p;
 	int i;
-        struct pktgen_dev *pkt_dev = (struct pktgen_dev*)(data);
+        struct pktgen_dev *pkt_dev = seq->private;
         __u64 sa;
         __u64 stopped;
         __u64 now = getCurUs();
         
-	p = buf;
-	p += sprintf(p, "Params: count %llu  min_pkt_size: %u  max_pkt_size: %u\n",
-		     (unsigned long long) pkt_dev->count,
-		     pkt_dev->min_pkt_size, pkt_dev->max_pkt_size);
+	seq_printf(seq, "Params: count %llu  min_pkt_size: %u  max_pkt_size: %u\n",
+		   (unsigned long long) pkt_dev->count,
+		   pkt_dev->min_pkt_size, pkt_dev->max_pkt_size);
 
-	p += sprintf(p, "     frags: %d  delay: %u  clone_skb: %d  ifname: %s\n",
-                     pkt_dev->nfrags, 1000*pkt_dev->delay_us+pkt_dev->delay_ns, pkt_dev->clone_skb, pkt_dev->ifname);
+	seq_printf(seq, "     frags: %d  delay: %u  clone_skb: %d  ifname: %s\n",
+		   pkt_dev->nfrags, 1000*pkt_dev->delay_us+pkt_dev->delay_ns, pkt_dev->clone_skb, pkt_dev->ifname);
 
-	p += sprintf(p, "     flows: %u flowlen: %u\n", pkt_dev->cflows, pkt_dev->lflow);
+	seq_printf(seq, "     flows: %u flowlen: %u\n", pkt_dev->cflows, pkt_dev->lflow);
 
 
 	if(pkt_dev->flags & F_IPV6) {
@@ -626,19 +581,19 @@ static int proc_if_read(char *buf , char
 		fmt_ip6(b1,  pkt_dev->in6_saddr.s6_addr);
 		fmt_ip6(b2,  pkt_dev->min_in6_saddr.s6_addr);
 		fmt_ip6(b3,  pkt_dev->max_in6_saddr.s6_addr);
-		p += sprintf(p, "     saddr: %s  min_saddr: %s  max_saddr: %s\n", b1, b2, b3);
+		seq_printf(seq, "     saddr: %s  min_saddr: %s  max_saddr: %s\n", b1, b2, b3);
 
 		fmt_ip6(b1,  pkt_dev->in6_daddr.s6_addr);
 		fmt_ip6(b2,  pkt_dev->min_in6_daddr.s6_addr);
 		fmt_ip6(b3,  pkt_dev->max_in6_daddr.s6_addr);
-		p += sprintf(p, "     daddr: %s  min_daddr: %s  max_daddr: %s\n", b1, b2, b3);
+		seq_printf(seq, "     daddr: %s  min_daddr: %s  max_daddr: %s\n", b1, b2, b3);
 
 	} 
 	else 
-		p += sprintf(p, "     dst_min: %s  dst_max: %s\n     src_min: %s  src_max: %s\n",
-                     pkt_dev->dst_min, pkt_dev->dst_max, pkt_dev->src_min, pkt_dev->src_max);
+		seq_printf(seq,"     dst_min: %s  dst_max: %s\n     src_min: %s  src_max: %s\n",
+			   pkt_dev->dst_min, pkt_dev->dst_max, pkt_dev->src_min, pkt_dev->src_max);
 
-        p += sprintf(p, "     src_mac: ");
+	seq_puts(seq, "     src_mac: ");
 
 	if ((pkt_dev->src_mac[0] == 0) && 
 	    (pkt_dev->src_mac[1] == 0) && 
@@ -648,89 +603,89 @@ static int proc_if_read(char *buf , char
 	    (pkt_dev->src_mac[5] == 0)) 
 
 		for (i = 0; i < 6; i++) 
-			p += sprintf(p, "%02X%s", pkt_dev->odev->dev_addr[i], i == 5 ? "  " : ":");
+			seq_printf(seq,  "%02X%s", pkt_dev->odev->dev_addr[i], i == 5 ? "  " : ":");
 
 	else 
 		for (i = 0; i < 6; i++) 
-			p += sprintf(p, "%02X%s", pkt_dev->src_mac[i], i == 5 ? "  " : ":");
+			seq_printf(seq,  "%02X%s", pkt_dev->src_mac[i], i == 5 ? "  " : ":");
 
-        p += sprintf(p, "dst_mac: ");
+        seq_printf(seq,  "dst_mac: ");
 	for (i = 0; i < 6; i++) 
-		p += sprintf(p, "%02X%s", pkt_dev->dst_mac[i], i == 5 ? "\n" : ":");
+		seq_printf(seq,  "%02X%s", pkt_dev->dst_mac[i], i == 5 ? "\n" : ":");
 
-        p += sprintf(p, "     udp_src_min: %d  udp_src_max: %d  udp_dst_min: %d  udp_dst_max: %d\n",
-                     pkt_dev->udp_src_min, pkt_dev->udp_src_max, pkt_dev->udp_dst_min,
-                     pkt_dev->udp_dst_max);
+        seq_printf(seq,  "     udp_src_min: %d  udp_src_max: %d  udp_dst_min: %d  udp_dst_max: %d\n",
+		   pkt_dev->udp_src_min, pkt_dev->udp_src_max, pkt_dev->udp_dst_min,
+		   pkt_dev->udp_dst_max);
 
-        p += sprintf(p, "     src_mac_count: %d  dst_mac_count: %d \n     Flags: ",
-                     pkt_dev->src_mac_count, pkt_dev->dst_mac_count);
+        seq_printf(seq,  "     src_mac_count: %d  dst_mac_count: %d \n     Flags: ",
+		   pkt_dev->src_mac_count, pkt_dev->dst_mac_count);
 
 
         if (pkt_dev->flags &  F_IPV6) 
-                p += sprintf(p, "IPV6  ");
+                seq_printf(seq,  "IPV6  ");
 
         if (pkt_dev->flags &  F_IPSRC_RND) 
-                p += sprintf(p, "IPSRC_RND  ");
+                seq_printf(seq,  "IPSRC_RND  ");
 
         if (pkt_dev->flags & F_IPDST_RND) 
-                p += sprintf(p, "IPDST_RND  ");
+                seq_printf(seq,  "IPDST_RND  ");
         
         if (pkt_dev->flags & F_TXSIZE_RND) 
-                p += sprintf(p, "TXSIZE_RND  ");
+                seq_printf(seq,  "TXSIZE_RND  ");
         
         if (pkt_dev->flags & F_UDPSRC_RND) 
-                p += sprintf(p, "UDPSRC_RND  ");
+                seq_printf(seq,  "UDPSRC_RND  ");
         
         if (pkt_dev->flags & F_UDPDST_RND) 
-                p += sprintf(p, "UDPDST_RND  ");
+                seq_printf(seq,  "UDPDST_RND  ");
         
         if (pkt_dev->flags & F_MACSRC_RND) 
-                p += sprintf(p, "MACSRC_RND  ");
+                seq_printf(seq,  "MACSRC_RND  ");
         
         if (pkt_dev->flags & F_MACDST_RND) 
-                p += sprintf(p, "MACDST_RND  ");
+                seq_printf(seq,  "MACDST_RND  ");
 
         
-        p += sprintf(p, "\n");
+        seq_puts(seq,  "\n");
         
         sa = pkt_dev->started_at;
         stopped = pkt_dev->stopped_at;
         if (pkt_dev->running) 
                 stopped = now; /* not really stopped, more like last-running-at */
         
-        p += sprintf(p, "Current:\n     pkts-sofar: %llu  errors: %llu\n     started: %lluus  stopped: %lluus idle: %lluus\n",
-		     (unsigned long long) pkt_dev->sofar,
-		     (unsigned long long) pkt_dev->errors,
-		     (unsigned long long) sa,
-		     (unsigned long long) stopped, 
-		     (unsigned long long) pkt_dev->idle_acc);
-
-        p += sprintf(p, "     seq_num: %d  cur_dst_mac_offset: %d  cur_src_mac_offset: %d\n",
-                     pkt_dev->seq_num, pkt_dev->cur_dst_mac_offset, pkt_dev->cur_src_mac_offset);
+        seq_printf(seq,  "Current:\n     pkts-sofar: %llu  errors: %llu\n     started: %lluus  stopped: %lluus idle: %lluus\n",
+		   (unsigned long long) pkt_dev->sofar,
+		   (unsigned long long) pkt_dev->errors,
+		   (unsigned long long) sa,
+		   (unsigned long long) stopped,
+		   (unsigned long long) pkt_dev->idle_acc);
+
+        seq_printf(seq,  "     seq_num: %d  cur_dst_mac_offset: %d  cur_src_mac_offset: %d\n",
+		   pkt_dev->seq_num, pkt_dev->cur_dst_mac_offset,
+		   pkt_dev->cur_src_mac_offset);
 
 	if(pkt_dev->flags & F_IPV6) {
 		char b1[128], b2[128];
 		fmt_ip6(b1,  pkt_dev->cur_in6_daddr.s6_addr);
 		fmt_ip6(b2,  pkt_dev->cur_in6_saddr.s6_addr);
-		p += sprintf(p, "     cur_saddr: %s  cur_daddr: %s\n", b2, b1);
+		seq_printf(seq,  "     cur_saddr: %s  cur_daddr: %s\n", b2, b1);
 	} 
 	else 
-		p += sprintf(p, "     cur_saddr: 0x%x  cur_daddr: 0x%x\n",
-                     pkt_dev->cur_saddr, pkt_dev->cur_daddr);
+		seq_printf(seq,  "     cur_saddr: 0x%x  cur_daddr: 0x%x\n",
+			   pkt_dev->cur_saddr, pkt_dev->cur_daddr);
 
 
-	p += sprintf(p, "     cur_udp_dst: %d  cur_udp_src: %d\n",
-                     pkt_dev->cur_udp_dst, pkt_dev->cur_udp_src);
+	seq_printf(seq,  "     cur_udp_dst: %d  cur_udp_src: %d\n",
+		   pkt_dev->cur_udp_dst, pkt_dev->cur_udp_src);
 
-	p += sprintf(p, "     flows: %u\n", pkt_dev->nflows);
+	seq_printf(seq,  "     flows: %u\n", pkt_dev->nflows);
 
 	if (pkt_dev->result[0])
-		p += sprintf(p, "Result: %s\n", pkt_dev->result);
+		seq_printf(seq,  "Result: %s\n", pkt_dev->result);
 	else
-		p += sprintf(p, "Result: Idle\n");
-	*eof = 1;
+		seq_printf(seq,  "Result: Idle\n");
 
-	return p - buf;
+	return 0;
 }
 
 
@@ -802,13 +757,14 @@ done_str:
 	return i;
 }
 
-static int proc_if_write(struct file *file, const char __user *user_buffer,
-                            unsigned long count, void *data)
+static ssize_t pktgen_if_write(struct file *file, const char __user *user_buffer,
+			       size_t count, loff_t *offset)
 {
+	struct seq_file *seq = (struct seq_file *) file->private_data;
+        struct pktgen_dev *pkt_dev = seq->private;
 	int i = 0, max, len;
 	char name[16], valstr[32];
 	unsigned long value = 0;
-        struct pktgen_dev *pkt_dev = (struct pktgen_dev*)(data);
         char* pg_result = NULL;
         int tmp = 0;
 	char buf[128];
@@ -849,7 +805,8 @@ static int proc_if_write(struct file *fi
                 if (copy_from_user(tb, user_buffer, count))
 			return -EFAULT;
                 tb[count] = 0;
-		printk("pktgen: %s,%lu  buffer -:%s:-\n", name, count, tb);
+		printk("pktgen: %s,%lu  buffer -:%s:-\n", name,
+		       (unsigned long) count, tb);
         }
 
 	if (!strcmp(name, "min_pkt_size")) {
@@ -1335,92 +1292,98 @@ static int proc_if_write(struct file *fi
 	return -EINVAL;
 }
 
-static int proc_thread_read(char *buf , char **start, off_t offset,
-                               int len, int *eof, void *data)
+static int pktgen_if_open(struct inode *inode, struct file *file)
 {
-	char *p;
-        struct pktgen_thread *t = (struct pktgen_thread*)(data);
-        struct pktgen_dev *pkt_dev = NULL;
+	return single_open(file, pktgen_if_show, PDE(inode)->data);
+}
 
+static struct file_operations pktgen_if_fops = {
+	.owner	  = THIS_MODULE,
+	.open	  = pktgen_if_open,
+        .read     = seq_read,
+	.llseek	  = seq_lseek,
+        .write    = pktgen_if_write,
+	.release  = single_release,
+};
 
-        if (!t) {
-                printk("pktgen: ERROR: could not find thread in proc_thread_read\n");
-                return -EINVAL;
-        }
+static int pktgen_thread_show(struct seq_file *seq, void *v)
+{
+        struct pktgen_thread *t = seq->private;
+        struct pktgen_dev *pkt_dev = NULL;
+
+	BUG_ON(!t);
 
-	p = buf;
-	p += sprintf(p, "Name: %s  max_before_softirq: %d\n",
+	seq_printf(seq, "Name: %s  max_before_softirq: %d\n",
                      t->name, t->max_before_softirq);
 
-        p += sprintf(p, "Running: ");
+        seq_printf(seq, "Running: ");
         
         if_lock(t);
         for(pkt_dev = t->if_list;pkt_dev; pkt_dev = pkt_dev->next) 
 		if(pkt_dev->running)
-			p += sprintf(p, "%s ", pkt_dev->ifname);
+			seq_printf(seq, "%s ", pkt_dev->ifname);
         
-        p += sprintf(p, "\nStopped: ");
+        seq_printf(seq, "\nStopped: ");
 
         for(pkt_dev = t->if_list;pkt_dev; pkt_dev = pkt_dev->next) 
 		if(!pkt_dev->running)
-			p += sprintf(p, "%s ", pkt_dev->ifname);
+			seq_printf(seq, "%s ", pkt_dev->ifname);
 
 	if (t->result[0])
-		p += sprintf(p, "\nResult: %s\n", t->result);
+		seq_printf(seq, "\nResult: %s\n", t->result);
 	else
-		p += sprintf(p, "\nResult: NA\n");
-
-	*eof = 1;
+		seq_printf(seq, "\nResult: NA\n");
 
         if_unlock(t);
 
-	return p - buf;
+	return 0;
 }
 
-static int proc_thread_write(struct file *file, const char __user *user_buffer,
-                                unsigned long count, void *data)
+static ssize_t pktgen_thread_write(struct file *file,
+				   const char __user *user_buffer,
+				   size_t count, loff_t *offset)
 {
+	struct seq_file *seq = (struct seq_file *) file->private_data;
+        struct pktgen_thread *t = seq->private;
 	int i = 0, max, len, ret;
 	char name[40];
-        struct pktgen_thread *t;
         char *pg_result;
         unsigned long value = 0;
-        
+
 	if (count < 1) {
 		//	sprintf(pg_result, "Wrong command format");
 		return -EINVAL;
 	}
-  
+
 	max = count - i;
         len = count_trail_chars(&user_buffer[i], max);
-        if (len < 0) 
-		return len; 
-     
+        if (len < 0)
+		return len;
+
 	i += len;
-  
+
 	/* Read variable name */
 
 	len = strn_len(&user_buffer[i], sizeof(name) - 1);
-        if (len < 0)  
-		return len; 
+        if (len < 0)
+		return len;
 	
 	memset(name, 0, sizeof(name));
 	if (copy_from_user(name, &user_buffer[i], len))
 		return -EFAULT;
 	i += len;
-  
+
 	max = count -i;
 	len = count_trail_chars(&user_buffer[i], max);
-        if (len < 0)  
-		return len; 
-	
+        if (len < 0)
+		return len;
+
 	i += len;
 
-	if (debug) 
-		printk("pktgen: t=%s, count=%lu\n", name, count);
-        
+	if (debug)
+		printk("pktgen: t=%s, count=%lu\n", name,
+		       (unsigned long) count);
 
-        t = (struct pktgen_thread*)(data);
 	if(!t) {
 		printk("pktgen: ERROR: No thread\n");
 		ret = -EINVAL;
@@ -1474,21 +1437,19 @@ static int proc_thread_write(struct file
 	return ret;
 }
 
-static int create_proc_dir(void)
+static int pktgen_thread_open(struct inode *inode, struct file *file)
 {
-	pg_proc_dir = proc_mkdir(PG_PROC_DIR, NULL);
-        
-        if (!pg_proc_dir) 
-                return -ENODEV;
-        
-        return 0;
+	return single_open(file, pktgen_thread_show, PDE(inode)->data);
 }
 
-static int remove_proc_dir(void)
-{
-        remove_proc_entry(PG_PROC_DIR, NULL);
-        return 0;
-}
+static struct file_operations pktgen_thread_fops = {
+	.owner	  = THIS_MODULE,
+	.open	  = pktgen_thread_open,
+        .read     = seq_read,
+	.llseek	  = seq_lseek,
+        .write    = pktgen_thread_write,
+	.release  = single_release,
+};
 
 /* Think find or remove for NN */
 static struct pktgen_dev *__pktgen_NN_threads(const char* ifname, int remove) 
@@ -2552,8 +2513,7 @@ static void pktgen_rem_thread(struct pkt
 
 	struct pktgen_thread *tmp = pktgen_threads;
 
-        if (strlen(t->fname))
-                remove_proc_entry(t->fname, NULL);
+	remove_proc_entry(t->name, pg_proc_dir);
 
 	thread_lock();
 
@@ -2825,7 +2785,7 @@ static struct pktgen_dev *pktgen_find_de
         if_lock(t);
 
         for(pkt_dev=t->if_list; pkt_dev; pkt_dev = pkt_dev->next ) {
-                if (strcmp(pkt_dev->ifname, ifname) == 0) {
+                if (strncmp(pkt_dev->ifname, ifname, IFNAMSIZ) == 0) {
                         break;
                 }
         }
@@ -2864,65 +2824,63 @@ static int add_dev_to_thread(struct pktg
 static int pktgen_add_device(struct pktgen_thread *t, const char* ifname) 
 {
         struct pktgen_dev *pkt_dev;
+	struct proc_dir_entry *pe;
 	
 	/* We don't allow a device to be on several threads */
 
-	if( (pkt_dev = __pktgen_NN_threads(ifname, FIND)) == NULL) {
-						   
-		pkt_dev = kzalloc(sizeof(struct pktgen_dev), GFP_KERNEL);
-                if (!pkt_dev) 
-                        return -ENOMEM;
-
-		pkt_dev->flows = vmalloc(MAX_CFLOWS*sizeof(struct flow_state));
-		if (pkt_dev->flows == NULL) {
-			kfree(pkt_dev);
-			return -ENOMEM;
-		}
-		memset(pkt_dev->flows, 0, MAX_CFLOWS*sizeof(struct flow_state));
-
-		pkt_dev->min_pkt_size = ETH_ZLEN;
-                pkt_dev->max_pkt_size = ETH_ZLEN;
-                pkt_dev->nfrags = 0;
-                pkt_dev->clone_skb = pg_clone_skb_d;
-                pkt_dev->delay_us = pg_delay_d / 1000;
-                pkt_dev->delay_ns = pg_delay_d % 1000;
-                pkt_dev->count = pg_count_d;
-                pkt_dev->sofar = 0;
-                pkt_dev->udp_src_min = 9; /* sink port */
-                pkt_dev->udp_src_max = 9;
-                pkt_dev->udp_dst_min = 9;
-                pkt_dev->udp_dst_max = 9;
-
-                strncpy(pkt_dev->ifname, ifname, 31);
-                sprintf(pkt_dev->fname, "%s/%s", PG_PROC_DIR, ifname);
-
-                if (! pktgen_setup_dev(pkt_dev)) {
-                        printk("pktgen: ERROR: pktgen_setup_dev failed.\n");
-			if (pkt_dev->flows)
-				vfree(pkt_dev->flows);
-                        kfree(pkt_dev);
-                        return -ENODEV;
-                }
-
-                pkt_dev->proc_ent = create_proc_entry(pkt_dev->fname, 0600, NULL);
-                if (!pkt_dev->proc_ent) {
-                        printk("pktgen: cannot create %s procfs entry.\n", pkt_dev->fname);
-			if (pkt_dev->flows)
-				vfree(pkt_dev->flows);
-                        kfree(pkt_dev);
-                        return -EINVAL;
-                }
-                pkt_dev->proc_ent->read_proc = proc_if_read;
-                pkt_dev->proc_ent->write_proc = proc_if_write;
-                pkt_dev->proc_ent->data = (void*)(pkt_dev);
-		pkt_dev->proc_ent->owner = THIS_MODULE;
-
-                return add_dev_to_thread(t, pkt_dev);
-        }
-        else {
+	pkt_dev = __pktgen_NN_threads(ifname, FIND);
+	if (pkt_dev) {
                 printk("pktgen: ERROR: interface already used.\n");
                 return -EBUSY;
         }
+
+	pkt_dev = kzalloc(sizeof(struct pktgen_dev), GFP_KERNEL);
+	if (!pkt_dev)
+		return -ENOMEM;
+
+	pkt_dev->flows = vmalloc(MAX_CFLOWS*sizeof(struct flow_state));
+	if (pkt_dev->flows == NULL) {
+		kfree(pkt_dev);
+		return -ENOMEM;
+	}
+	memset(pkt_dev->flows, 0, MAX_CFLOWS*sizeof(struct flow_state));
+
+	pkt_dev->min_pkt_size = ETH_ZLEN;
+	pkt_dev->max_pkt_size = ETH_ZLEN;
+	pkt_dev->nfrags = 0;
+	pkt_dev->clone_skb = pg_clone_skb_d;
+	pkt_dev->delay_us = pg_delay_d / 1000;
+	pkt_dev->delay_ns = pg_delay_d % 1000;
+	pkt_dev->count = pg_count_d;
+	pkt_dev->sofar = 0;
+	pkt_dev->udp_src_min = 9; /* sink port */
+	pkt_dev->udp_src_max = 9;
+	pkt_dev->udp_dst_min = 9;
+	pkt_dev->udp_dst_max = 9;
+
+	strncpy(pkt_dev->ifname, ifname, IFNAMSIZ);
+
+	if (! pktgen_setup_dev(pkt_dev)) {
+		printk("pktgen: ERROR: pktgen_setup_dev failed.\n");
+		if (pkt_dev->flows)
+			vfree(pkt_dev->flows);
+		kfree(pkt_dev);
+		return -ENODEV;
+	}
+
+	pe = create_proc_entry(ifname, 0600, pg_proc_dir);
+	if (!pe) {
+		printk("pktgen: cannot create %s/%s procfs entry.\n",
+		       PG_PROC_DIR, ifname);
+		if (pkt_dev->flows)
+			vfree(pkt_dev->flows);
+		kfree(pkt_dev);
+		return -EINVAL;
+	}
+	pe->proc_fops = &pktgen_if_fops;
+	pe->data = pkt_dev;
+
+	return add_dev_to_thread(t, pkt_dev);
 }
 
 static struct pktgen_thread *pktgen_find_thread(const char* name) 
@@ -2945,6 +2903,7 @@ static struct pktgen_thread *pktgen_find
 static int pktgen_create_thread(const char* name, int cpu) 
 {
         struct pktgen_thread *t = NULL;
+	struct proc_dir_entry *pe;
 
         if (strlen(name) > 31) {
                 printk("pktgen: ERROR:  Thread name cannot be more than 31 characters.\n");
@@ -2966,17 +2925,16 @@ static int pktgen_create_thread(const ch
         spin_lock_init(&t->if_lock);
 	t->cpu = cpu;
         
-        sprintf(t->fname, "%s/%s", PG_PROC_DIR, t->name);
-        t->proc_ent = create_proc_entry(t->fname, 0600, NULL);
-        if (!t->proc_ent) {
-                printk("pktgen: cannot create %s procfs entry.\n", t->fname);
+        pe = create_proc_entry(t->name, 0600, pg_proc_dir);
+        if (!pe) {
+                printk("pktgen: cannot create %s/%s procfs entry.\n",
+		       PG_PROC_DIR, t->name);
                 kfree(t);
                 return -EINVAL;
         }
-        t->proc_ent->read_proc = proc_thread_read;
-        t->proc_ent->write_proc = proc_thread_write;
-        t->proc_ent->data = (void*)(t);
-        t->proc_ent->owner = THIS_MODULE;
+
+	pe->proc_fops = &pktgen_thread_fops;
+	pe->data = t;
 
         t->next = pktgen_threads;
         pktgen_threads = t;
@@ -3031,8 +2989,7 @@ static int pktgen_remove_device(struct p
 
         /* Clean up proc file system */
 
-        if (strlen(pkt_dev->fname)) 
-                remove_proc_entry(pkt_dev->fname, NULL);
+	remove_proc_entry(pkt_dev->ifname, pg_proc_dir);
 
 	if (pkt_dev->flows)
 		vfree(pkt_dev->flows);
@@ -3043,21 +3000,24 @@ static int pktgen_remove_device(struct p
 static int __init pg_init(void) 
 {
 	int cpu;
-	printk(version);
+	struct proc_dir_entry *pe;
 
-        module_fname[0] = 0;
-
-	create_proc_dir();
+	printk(version);
 
-        sprintf(module_fname, "%s/pgctrl", PG_PROC_DIR);
-        module_proc_ent = create_proc_entry(module_fname, 0600, NULL);
-        if (!module_proc_ent) {
-                printk("pktgen: ERROR: cannot create %s procfs entry.\n", module_fname);
+	pg_proc_dir = proc_mkdir(PG_PROC_DIR, proc_net);
+	if (!pg_proc_dir)
+		return -ENODEV;
+	pg_proc_dir->owner = THIS_MODULE;
+
+	pe = create_proc_entry(PGCTRL, 0600, pg_proc_dir);
+        if (pe == NULL) {
+		printk("pktgen: ERROR: cannot create %s procfs entry.\n", PGCTRL);
+		proc_net_remove(PG_PROC_DIR);
                 return -EINVAL;
         }
 
-        module_proc_ent->proc_fops =  &pktgen_fops;
-        module_proc_ent->data = NULL;
+        pe->proc_fops = &pktgen_fops;
+        pe->data      = NULL;
 
 	/* Register us to receive netdevice events */
 	register_netdevice_notifier(&pktgen_notifier_block);
@@ -3089,10 +3049,8 @@ static void __exit pg_cleanup(void)
 	unregister_netdevice_notifier(&pktgen_notifier_block);
 
         /* Clean up proc file system */
-
-        remove_proc_entry(module_fname, NULL);
-        
-	remove_proc_dir();
+	remove_proc_entry(PGCTRL, pg_proc_dir);
+	proc_net_remove(PG_PROC_DIR);
 }
 
 
---
0.99.8.GIT


--- NEW FILE 0765-NETFILTER-ip_conntrack-Make-hashsize-conntrack-parameter-writable.txt ---
Subject: [PATCH] [NETFILTER] ip_conntrack: Make "hashsize" conntrack parameter writable
From: Harald Welte <laforge netfilter org>
Date: 1129465379 +0200

It's fairly simple to resize the hash table, but currently you need to
remove and reinsert the module.  That's bad (we lose connection
state).  Harald has even offered to write a daemon which sets this
based on load.

Signed-off-by: Rusty Russell <rusty rustcorp com au>
Signed-off-by: Harald Welte <laforge netfilter org>
Signed-off-by: Arnaldo Carvalho de Melo <acme mandriva com>

---

 net/ipv4/netfilter/ip_conntrack_core.c |  132 +++++++++++++++++++++++---------
 1 files changed, 95 insertions(+), 37 deletions(-)

applies-to: 98012391b898e4ef4ccd59a41e75cdf65114353c
eed75f191d8318a2b144da8aae9774e1cfcae492
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index 07a80b5..422ab68 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -50,7 +50,7 @@
 #include <linux/netfilter_ipv4/ip_conntrack_core.h>
 #include <linux/netfilter_ipv4/listhelp.h>
 
-#define IP_CONNTRACK_VERSION	"2.3"
+#define IP_CONNTRACK_VERSION	"2.4"
 
 #if 0
 #define DEBUGP printk
@@ -148,16 +148,20 @@ DEFINE_PER_CPU(struct ip_conntrack_stat,
 static int ip_conntrack_hash_rnd_initted;
 static unsigned int ip_conntrack_hash_rnd;
 
-static u_int32_t
-hash_conntrack(const struct ip_conntrack_tuple *tuple)
+static u_int32_t __hash_conntrack(const struct ip_conntrack_tuple *tuple,
+			    unsigned int size, unsigned int rnd)
 {
-#if 0
-	dump_tuple(tuple);
-#endif
 	return (jhash_3words(tuple->src.ip,
 	                     (tuple->dst.ip ^ tuple->dst.protonum),
 	                     (tuple->src.u.all | (tuple->dst.u.all << 16)),
-	                     ip_conntrack_hash_rnd) % ip_conntrack_htable_size);
+	                     rnd) % size);
+}
+
+static u_int32_t
+hash_conntrack(const struct ip_conntrack_tuple *tuple)
+{
+	return __hash_conntrack(tuple, ip_conntrack_htable_size,
+				ip_conntrack_hash_rnd);
 }
 
 int
@@ -1341,14 +1345,13 @@ static int kill_all(struct ip_conntrack 
 	return 1;
 }
 
-static void free_conntrack_hash(void)
+static void free_conntrack_hash(struct list_head *hash, int vmalloced,int size)
 {
-	if (ip_conntrack_vmalloc)
-		vfree(ip_conntrack_hash);
+	if (vmalloced)
+		vfree(hash);
 	else
-		free_pages((unsigned long)ip_conntrack_hash, 
-			   get_order(sizeof(struct list_head)
-				     * ip_conntrack_htable_size));
+		free_pages((unsigned long)hash, 
+			   get_order(sizeof(struct list_head) * size));
 }
 
 void ip_conntrack_flush()
@@ -1378,12 +1381,83 @@ void ip_conntrack_cleanup(void)
 	ip_conntrack_flush();
 	kmem_cache_destroy(ip_conntrack_cachep);
 	kmem_cache_destroy(ip_conntrack_expect_cachep);
-	free_conntrack_hash();
+	free_conntrack_hash(ip_conntrack_hash, ip_conntrack_vmalloc,
+			    ip_conntrack_htable_size);
 	nf_unregister_sockopt(&so_getorigdst);
 }
 
-static int hashsize;
-module_param(hashsize, int, 0400);
+static struct list_head *alloc_hashtable(int size, int *vmalloced)
+{
+	struct list_head *hash;
+	unsigned int i;
+
+	*vmalloced = 0; 
+	hash = (void*)__get_free_pages(GFP_KERNEL, 
+				       get_order(sizeof(struct list_head)
+						 * size));
+	if (!hash) { 
+		*vmalloced = 1;
+		printk(KERN_WARNING"ip_conntrack: falling back to vmalloc.\n");
+		hash = vmalloc(sizeof(struct list_head) * size);
+	}
+
+	if (hash)
+		for (i = 0; i < size; i++)
+			INIT_LIST_HEAD(&hash[i]);
+
+	return hash;
+}
+
+int set_hashsize(const char *val, struct kernel_param *kp)
+{
+	int i, bucket, hashsize, vmalloced;
+	int old_vmalloced, old_size;
+	int rnd;
+	struct list_head *hash, *old_hash;
+	struct ip_conntrack_tuple_hash *h;
+
+	/* On boot, we can set this without any fancy locking. */
+	if (!ip_conntrack_htable_size)
+		return param_set_int(val, kp);
+
+	hashsize = simple_strtol(val, NULL, 0);
+	if (!hashsize)
+		return -EINVAL;
+
+	hash = alloc_hashtable(hashsize, &vmalloced);
+	if (!hash)
+		return -ENOMEM;
+
+	/* We have to rehash for the new table anyway, so we also can 
+	 * use a new random seed */
+	get_random_bytes(&rnd, 4);
+
+	write_lock_bh(&ip_conntrack_lock);
+	for (i = 0; i < ip_conntrack_htable_size; i++) {
+		while (!list_empty(&ip_conntrack_hash[i])) {
+			h = list_entry(ip_conntrack_hash[i].next,
+				       struct ip_conntrack_tuple_hash, list);
+			list_del(&h->list);
+			bucket = __hash_conntrack(&h->tuple, hashsize, rnd);
+			list_add_tail(&h->list, &hash[bucket]);
+		}
+	}
+	old_size = ip_conntrack_htable_size;
+	old_vmalloced = ip_conntrack_vmalloc;
+	old_hash = ip_conntrack_hash;
+
+	ip_conntrack_htable_size = hashsize;
+	ip_conntrack_vmalloc = vmalloced;
+	ip_conntrack_hash = hash;
+	ip_conntrack_hash_rnd = rnd;
+	write_unlock_bh(&ip_conntrack_lock);
+
+	free_conntrack_hash(old_hash, old_vmalloced, old_size);
+	return 0;
+}
+
+module_param_call(hashsize, set_hashsize, param_get_uint,
+		  &ip_conntrack_htable_size, 0600);
 
 int __init ip_conntrack_init(void)
 {
@@ -1392,9 +1466,7 @@ int __init ip_conntrack_init(void)
 
 	/* Idea from tcp.c: use 1/16384 of memory.  On i386: 32MB
 	 * machine has 256 buckets.  >= 1GB machines have 8192 buckets. */
- 	if (hashsize) {
- 		ip_conntrack_htable_size = hashsize;
- 	} else {
+ 	if (!ip_conntrack_htable_size) {
 		ip_conntrack_htable_size
 			= (((num_physpages << PAGE_SHIFT) / 16384)
 			   / sizeof(struct list_head));
@@ -1416,20 +1488,8 @@ int __init ip_conntrack_init(void)
 		return ret;
 	}
 
-	/* AK: the hash table is twice as big than needed because it
-	   uses list_head.  it would be much nicer to caches to use a
-	   single pointer list head here. */
-	ip_conntrack_vmalloc = 0; 
-	ip_conntrack_hash 
-		=(void*)__get_free_pages(GFP_KERNEL, 
-					 get_order(sizeof(struct list_head)
-						   *ip_conntrack_htable_size));
-	if (!ip_conntrack_hash) { 
-		ip_conntrack_vmalloc = 1;
-		printk(KERN_WARNING "ip_conntrack: falling back to vmalloc.\n");
-		ip_conntrack_hash = vmalloc(sizeof(struct list_head)
-					    * ip_conntrack_htable_size);
-	}
+	ip_conntrack_hash = alloc_hashtable(ip_conntrack_htable_size,
+					    &ip_conntrack_vmalloc);
 	if (!ip_conntrack_hash) {
 		printk(KERN_ERR "Unable to create ip_conntrack_hash\n");
 		goto err_unreg_sockopt;
@@ -1461,9 +1521,6 @@ int __init ip_conntrack_init(void)
 	ip_ct_protos[IPPROTO_ICMP] = &ip_conntrack_protocol_icmp;
 	write_unlock_bh(&ip_conntrack_lock);
 
-	for (i = 0; i < ip_conntrack_htable_size; i++)
-		INIT_LIST_HEAD(&ip_conntrack_hash[i]);
-
 	/* For use by ipt_REJECT */
 	ip_ct_attach = ip_conntrack_attach;
 
@@ -1478,7 +1535,8 @@ int __init ip_conntrack_init(void)
 err_free_conntrack_slab:
 	kmem_cache_destroy(ip_conntrack_cachep);
 err_free_hash:
-	free_conntrack_hash();
+	free_conntrack_hash(ip_conntrack_hash, ip_conntrack_vmalloc,
+			    ip_conntrack_htable_size);
 err_unreg_sockopt:
 	nf_unregister_sockopt(&so_getorigdst);
 
---
0.99.8.GIT


--- NEW FILE 0766-IPV4-Kill-redundant-rcu_dereference-on-fa_info.txt ---
Subject: [PATCH] [IPV4]: Kill redundant rcu_dereference on fa_info
From: Herbert Xu <herbert gondor apana org au>
Date: 1129333359 +1000

This patch kills a redundant rcu_dereference on fa->fa_info in fib_trie.c.
As this dereference directly follows a list_for_each_entry_rcu line, we
have already taken a read barrier with respect to getting an entry from
the list.

This read barrier guarantees that all values read out of fa are valid.
In particular, the contents of structure pointed to by fa->fa_info is
initialised before fa->fa_info is actually set (see fn_trie_insert);
the setting of fa->fa_info itself is further separated with a write
barrier from the insertion of fa into the list.

Therefore by taking a read barrier after obtaining fa from the list
(which is given by list_for_each_entry_rcu), we can be sure that
fa->fa_info contains a valid pointer, as well as the fact that the
data pointed to by fa->fa_info is itself valid.

Signed-off-by: Herbert Xu <herbert gondor apana org au>
Acked-by: Paul E. McKenney <paulmck us ibm com>
Signed-off-by: David S. Miller <davem davemloft net>
Signed-off-by: Arnaldo Carvalho de Melo <acme mandriva com>

---

 net/ipv4/fib_trie.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

applies-to: 512e66c1a83911c5944270a68bf950ddc1cbde0d
1371e37da299d4df6267ad0ddf010435782c28e9
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 0093ea0..66247f3 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -2404,7 +2404,7 @@ static int fib_route_seq_show(struct seq
 		prefix = htonl(l->key);
 
 		list_for_each_entry_rcu(fa, &li->falh, fa_list) {
-			const struct fib_info *fi = rcu_dereference(fa->fa_info);
+			const struct fib_info *fi = fa->fa_info;
 			unsigned flags = fib_flag_trans(fa->fa_type, mask, fi);
 
 			if (fa->fa_type == RTN_BROADCAST
---
0.99.8.GIT


--- NEW FILE 0767-IPSEC-Kill-obsolete-get_mss-function.txt ---
Subject: [PATCH] [IPSEC]: Kill obsolete get_mss function
From: Herbert Xu <herbert gondor apana org au>
Date: 1129337910 +1000

Now that we've switched over to storing MTUs in the xfrm_dst entries,
we no longer need the dst's get_mss methods.  This patch gets rid of
them.

It also documents the fact that our MTU calculation is not optimal
for ESP.

Signed-off-by: Herbert Xu <herbert gondor apana org au>
Signed-off-by: Arnaldo Carvalho de Melo <acme mandriva com>

---

 include/net/dst.h      |    1 -
 net/xfrm/xfrm_policy.c |   43 -------------------------------------------
 net/xfrm/xfrm_state.c  |    6 ++++++
 3 files changed, 6 insertions(+), 44 deletions(-)

applies-to: a8b1706d73d86e5f732b132d99b90e1107eafb68
80b30c1023dbd795faf948dee0cfb3b270b56d47
diff --git a/include/net/dst.h b/include/net/dst.h
index 4a056a6..6c196a5 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -94,7 +94,6 @@ struct dst_ops
 	struct dst_entry *	(*negative_advice)(struct dst_entry *);
 	void			(*link_failure)(struct sk_buff *);
 	void			(*update_pmtu)(struct dst_entry *dst, u32 mtu);
-	int			(*get_mss)(struct dst_entry *dst, u32 mtu);
 	int			entry_size;
 
 	atomic_t		entries;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index cbb0ba3..0db9e57 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1192,46 +1192,6 @@ int xfrm_bundle_ok(struct xfrm_dst *firs
 
 EXPORT_SYMBOL(xfrm_bundle_ok);
 
-/* Well... that's _TASK_. We need to scan through transformation
- * list and figure out what mss tcp should generate in order to
- * final datagram fit to mtu. Mama mia... :-)
- *
- * Apparently, some easy way exists, but we used to choose the most
- * bizarre ones. :-) So, raising Kalashnikov... tra-ta-ta.
- *
- * Consider this function as something like dark humour. :-)
- */
-static int xfrm_get_mss(struct dst_entry *dst, u32 mtu)
-{
-	int res = mtu - dst->header_len;
-
-	for (;;) {
-		struct dst_entry *d = dst;
-		int m = res;
-
-		do {
-			struct xfrm_state *x = d->xfrm;
-			if (x) {
-				spin_lock_bh(&x->lock);
-				if (x->km.state == XFRM_STATE_VALID &&
-				    x->type && x->type->get_max_size)
-					m = x->type->get_max_size(d->xfrm, m);
-				else
-					m += x->props.header_len;
-				spin_unlock_bh(&x->lock);
-			}
-		} while ((d = d->child) != NULL);
-
-		if (m <= mtu)
-			break;
-		res -= (m - mtu);
-		if (res < 88)
-			return mtu;
-	}
-
-	return res + dst->header_len;
-}
-
 int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
 {
 	int err = 0;
@@ -1252,8 +1212,6 @@ int xfrm_policy_register_afinfo(struct x
 			dst_ops->negative_advice = xfrm_negative_advice;
 		if (likely(dst_ops->link_failure == NULL))
 			dst_ops->link_failure = xfrm_link_failure;
-		if (likely(dst_ops->get_mss == NULL))
-			dst_ops->get_mss = xfrm_get_mss;
 		if (likely(afinfo->garbage_collect == NULL))
 			afinfo->garbage_collect = __xfrm_garbage_collect;
 		xfrm_policy_afinfo[afinfo->family] = afinfo;
@@ -1281,7 +1239,6 @@ int xfrm_policy_unregister_afinfo(struct
 			dst_ops->check = NULL;
 			dst_ops->negative_advice = NULL;
 			dst_ops->link_failure = NULL;
-			dst_ops->get_mss = NULL;
 			afinfo->garbage_collect = NULL;
 		}
 	}
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 9d206c2..8b9a474 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -1026,6 +1026,12 @@ void xfrm_state_delete_tunnel(struct xfr
 }
 EXPORT_SYMBOL(xfrm_state_delete_tunnel);
 
+/*
+ * This function is NOT optimal.  For example, with ESP it will give an
+ * MTU that's usually two bytes short of being optimal.  However, it will
+ * usually give an answer that's a multiple of 4 provided the input is
+ * also a multiple of 4.
+ */
 int xfrm_state_mtu(struct xfrm_state *x, int mtu)
 {
 	int res = mtu;
---
0.99.8.GIT


--- NEW FILE 0768-NETLINK-Remove-dead-code-in-af_netlink.c.txt ---
Subject: [PATCH] [NETLINK]: Remove dead code in af_netlink.c
From: Jayachandran C <jchandra digeo com>
Date: 1129228985 -0700

Remove the variable nlk & call to nlk_sk as it does not have any side effect.

Signed-off-by: Jayachandran C. <c.jayachandran at gmail.com>
Acked-by: James Morris <jmorris namei org>
Signed-off-by: Arnaldo Carvalho de Melo <acme mandriva com>

---

 net/netlink/af_netlink.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

applies-to: 18a6c4d4647e6b52ea9b53e1f938b5e7f7e97f8f
ea7ce406490cb248f44f510f7c0bcc357184640a
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 678c3f2..eab4942 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -740,11 +740,8 @@ int netlink_attachskb(struct sock *sk, s
 
 int netlink_sendskb(struct sock *sk, struct sk_buff *skb, int protocol)
 {
-	struct netlink_sock *nlk;
 	int len = skb->len;
 
-	nlk = nlk_sk(sk);
-
 	skb_queue_tail(&sk->sk_receive_queue, skb);
 	sk->sk_data_ready(sk, len);
 	sock_put(sk);
---
0.99.8.GIT


--- NEW FILE 0769-IPV4-Remove-dead-code-from-ip_output.c.txt ---
Subject: [PATCH] [IPV4]: Remove dead code from ip_output.c
From: Jayachandran C <jchandra digeo com>
Date: 1129228982 -0700

skb_prev is assigned from skb, which cannot be NULL. This patch removes the
unnecessary NULL check.

Signed-off-by: Jayachandran C. <c.jayachandran at gmail.com>
Acked-by: James Morris <jmorris namei org>
Signed-off-by: Arnaldo Carvalho de Melo <acme mandriva com>

---

 net/ipv4/ip_output.c |    5 +----
 1 files changed, 1 insertions(+), 4 deletions(-)

applies-to: 94865798286a5b9faeca5faa63885d9840c2d8ed
0d0d2bba97cb091218ea0bcb3d8debcc7bf48397
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 1ad5202..87e3500 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1023,10 +1023,7 @@ ssize_t	ip_append_page(struct sock *sk, 
 			int alloclen;
 
 			skb_prev = skb;
-			if (skb_prev)
-				fraggap = skb_prev->len - maxfraglen;
-			else
-				fraggap = 0;
+			fraggap = skb_prev->len - maxfraglen;
 
 			alloclen = fragheaderlen + hh_len + fraggap + 15;
 			skb = sock_wmalloc(sk, alloclen, 1, sk->sk_allocation);
---
0.99.8.GIT


--- NEW FILE 0770-SK_BUFF-kernel-doc-fix-skbuff-warnings.txt ---
Subject: [PATCH] [SK_BUFF] kernel-doc: fix skbuff warnings
From: Randy Dunlap <rdunlap xenotime net>
Date: 1129698461 -0700

Add kernel-doc to skbuff.h, skbuff.c to eliminate kernel-doc warnings.

Signed-off-by: Randy Dunlap <rdunlap xenotime net>
Signed-off-by: Arnaldo Carvalho de Melo <acme mandriva com>

---

 include/linux/skbuff.h |    3 ++-
 net/core/skbuff.c      |    2 ++
 2 files changed, 4 insertions(+), 1 deletions(-)

applies-to: 6f678dcabc60e41a07e1d6948d798e3b2644cea5
c83c24861882758b9731e8550225cd1e52a4cd1c
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 8f5d9e7..b756935 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -171,7 +171,6 @@ enum {
  *	struct sk_buff - socket buffer
  *	@next: Next buffer in list
  *	@prev: Previous buffer in list
- *	@list: List we are on
  *	@sk: Socket we are owned by
  *	@tstamp: Time we arrived
  *	@dev: Device we arrived on/are leaving by
@@ -190,6 +189,7 @@ enum {
  *	@cloned: Head may be cloned (check refcnt to be sure)
  *	@nohdr: Payload reference only, must not modify header
  *	@pkt_type: Packet class
+ *	@fclone: skbuff clone status
  *	@ip_summed: Driver fed us an IP checksum
  *	@priority: Packet queueing priority
  *	@users: User count - see {datagram,tcp}.c
@@ -202,6 +202,7 @@ enum {
  *	@destructor: Destruct function
  *	@nfmark: Can be used for communication between hooks
  *	@nfct: Associated connection, if any
+ *	@ipvs_property: skbuff is owned by ipvs
  *	@nfctinfo: Relationship of this skb to the connection
  *	@nf_bridge: Saved data about a bridged frame - see br_netfilter.c
  *	@tc_index: Traffic control index
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 02cd4cd..ef9d46b 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -122,6 +122,8 @@ void skb_under_panic(struct sk_buff *skb
  *	__alloc_skb	-	allocate a network buffer
  *	@size: size to allocate
  *	@gfp_mask: allocation mask
+ *	@fclone: allocate from fclone cache instead of head cache
+ *		and allocate a cloned (child) skb
  *
  *	Allocate a new &sk_buff. The returned buffer has no headroom and a
  *	tail room of size bytes. The object has a reference count of one.
---
0.99.8.GIT


--- NEW FILE 0771-AX.25-Use-constant-instead-of-magic-number.txt ---
Subject: [PATCH] [AX.25]: Use constant instead of magic number
From: Ralf Baechle <ralf linux-mips org>
Date: 1129667973 +0100

Signed-off-by: Ralf Baechle DL5RB <ralf linux-mips org>
Signed-off-by: Arnaldo Carvalho de Melo <acme mandriva com>

---

 net/rose/rose_route.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

applies-to: a6161031466786ec726532a822fdb63104613b5f
95df1c04ab3f7ca617774930df62c0893a188c2c
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index e556d92..b18fe50 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -727,7 +727,7 @@ int rose_rt_ioctl(unsigned int cmd, void
 		}
 		if (rose_route.mask > 10) /* Mask can't be more than 10 digits */
 			return -EINVAL;
-		if (rose_route.ndigis > 8) /* No more than 8 digipeats */
+		if (rose_route.ndigis > AX25_MAX_DIGIS)
 			return -EINVAL;
 		err = rose_add_node(&rose_route, dev);
 		dev_put(dev);
---
0.99.8.GIT


--- NEW FILE 0772-IPV4-Fix-setting-broadcast-for-SIOCSIFNETMASK.txt ---
Subject: [PATCH] [IPV4]: Fix setting broadcast for SIOCSIFNETMASK
From: David Engel <gigem comcast net>
Date: 1129950556 -0500

Fix setting of the broadcast address when the netmask is set via
SIOCSIFNETMASK in Linux 2.6.  The code wanted the old value of
ifa->ifa_mask but used it after it had already been overwritten with
the new value.

Signed-off-by: David Engel <gigem comcast net>
Signed-off-by: Arnaldo Carvalho de Melo <acme mandriva com>

---

 net/ipv4/devinet.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

applies-to: c37783ed5a57ebf90fb3645ed18b3b0005fe58ff
dcab5e1eeccf5e226c771ecc013631cde157435f
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 74f2207..4ec4b2c 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -715,6 +715,7 @@ int devinet_ioctl(unsigned int cmd, void
 			break;
 		ret = 0;
 		if (ifa->ifa_mask != sin->sin_addr.s_addr) {
+			u32 old_mask = ifa->ifa_mask;
 			inet_del_ifa(in_dev, ifap, 0);
 			ifa->ifa_mask = sin->sin_addr.s_addr;
 			ifa->ifa_prefixlen = inet_mask_len(ifa->ifa_mask);
@@ -728,7 +729,7 @@ int devinet_ioctl(unsigned int cmd, void
 			if ((dev->flags & IFF_BROADCAST) &&
 			    (ifa->ifa_prefixlen < 31) &&
 			    (ifa->ifa_broadcast ==
-			     (ifa->ifa_local|~ifa->ifa_mask))) {
+			     (ifa->ifa_local|~old_mask))) {
 				ifa->ifa_broadcast = (ifa->ifa_local |
 						      ~sin->sin_addr.s_addr);
 			}
---
0.99.8.GIT


--- NEW FILE 0774-ieee80211-build-fix.txt ---
Subject: [PATCH] ieee80211 build fix
From: James Ketrenos <jketreno linux intel com>
Date: 1130167666 -0500

James Ketrenos wrote:
> [3/4] Use the tx_headroom and reserve requested space.

This patch introduced a compile problem; patch below corrects this.

Fixed compilation error due to not passing tx_headroom in
ieee80211_tx_frame.

Signed-off-by: James Ketrenos <jketreno linux intel com>
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 net/ieee80211/ieee80211_tx.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

applies-to: 802058729c3d2401ec73c580c670d8b924b17954
077783f87708b24054452e5c07685ead2c28b1eb
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index fb45090..95ccbad 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -541,7 +541,7 @@ int ieee80211_tx_frame(struct ieee80211_
 	/* When we allocate the TXB we allocate enough space for the reserve
 	 * and full fragment bytes (bytes_per_frag doesn't include prefix,
 	 * postfix, header, FCS, etc.) */
-	txb = ieee80211_alloc_txb(1, len, GFP_ATOMIC);
+	txb = ieee80211_alloc_txb(1, len, ieee->tx_headroom, GFP_ATOMIC);
 	if (unlikely(!txb)) {
 		printk(KERN_WARNING "%s: Could not allocate TXB\n",
 		       ieee->dev->name);
---
0.99.8.GIT


--- NEW FILE 0822-Revert-RPC-stops-the-release_pipe-funtion-from-being-called-twice.txt ---
Subject: [PATCH] Revert "RPC: stops the release_pipe() funtion from being called twice"
From: Trond Myklebust <Trond Myklebust netapp com>
Date: 1130454498 -0400

This reverts 747c5534c9a6da4aa87e7cdc2209ea98ea27f381 commit.

---

 net/sunrpc/rpc_pipe.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

applies-to: afc2f191ef73e6eb1064de6358f44177d691aab0
6fa05b17367f04ada501e89d3b9cb56adec0d930
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 649d609..ded6c63 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -177,8 +177,6 @@ rpc_pipe_release(struct inode *inode, st
 		__rpc_purge_upcall(inode, -EPIPE);
 	if (rpci->ops->release_pipe)
 		rpci->ops->release_pipe(inode);
-	if (!rpci->nreaders && !rpci->nwriters)
-		rpci->ops = NULL;
 out:
 	up(&inode->i_sem);
 	return 0;
---
0.99.8.GIT


--- NEW FILE 0843-RPC-Ensure-that-nobody-can-queue-up-new-upcalls-after-rpc_close_pipes.txt ---
Subject: [PATCH] RPC: Ensure that nobody can queue up new upcalls after rpc_close_pipes()
From: Trond Myklebust <Trond Myklebust netapp com>
Date: 1130465566 -0400

 Signed-off-by: Trond Myklebust <Trond Myklebust netapp com>

---

 net/sunrpc/rpc_pipe.c |   29 +++++++++++++++--------------
 1 files changed, 15 insertions(+), 14 deletions(-)

applies-to: 76013e5926f02d476b47812eb4c49b5dff8264a3
6070fe6f82c67021367092855c0812a98becf0fa
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index ded6c63..4f188d0 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -76,25 +76,35 @@ int
 rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg)
 {
 	struct rpc_inode *rpci = RPC_I(inode);
-	int res = 0;
+	int res = -EPIPE;
 
 	down(&inode->i_sem);
+	if (rpci->ops == NULL)
+		goto out;
 	if (rpci->nreaders) {
 		list_add_tail(&msg->list, &rpci->pipe);
 		rpci->pipelen += msg->len;
+		res = 0;
 	} else if (rpci->flags & RPC_PIPE_WAIT_FOR_OPEN) {
 		if (list_empty(&rpci->pipe))
 			schedule_delayed_work(&rpci->queue_timeout,
 					RPC_UPCALL_TIMEOUT);
 		list_add_tail(&msg->list, &rpci->pipe);
 		rpci->pipelen += msg->len;
-	} else
-		res = -EPIPE;
+		res = 0;
+	}
+out:
 	up(&inode->i_sem);
 	wake_up(&rpci->waitq);
 	return res;
 }
 
+static inline void
+rpc_inode_setowner(struct inode *inode, void *private)
+{
+	RPC_I(inode)->private = private;
+}
+
 static void
 rpc_close_pipes(struct inode *inode)
 {
@@ -111,15 +121,10 @@ rpc_close_pipes(struct inode *inode)
 			rpci->ops->release_pipe(inode);
 		rpci->ops = NULL;
 	}
+	rpc_inode_setowner(inode, NULL);
 	up(&inode->i_sem);
 }
 
-static inline void
-rpc_inode_setowner(struct inode *inode, void *private)
-{
-	RPC_I(inode)->private = private;
-}
-
 static struct inode *
 rpc_alloc_inode(struct super_block *sb)
 {
@@ -501,7 +506,6 @@ repeat:
 			dentry = dvec[--n];
 			if (dentry->d_inode) {
 				rpc_close_pipes(dentry->d_inode);
-				rpc_inode_setowner(dentry->d_inode, NULL);
 				simple_unlink(dir, dentry);
 			}
 			dput(dentry);
@@ -576,10 +580,8 @@ __rpc_rmdir(struct inode *dir, struct de
 	int error;
 
 	shrink_dcache_parent(dentry);
-	if (dentry->d_inode) {
+	if (dentry->d_inode)
 		rpc_close_pipes(dentry->d_inode);
-		rpc_inode_setowner(dentry->d_inode, NULL);
-	}
 	if ((error = simple_rmdir(dir, dentry)) != 0)
 		return error;
 	if (!error) {
@@ -732,7 +734,6 @@ rpc_unlink(char *path)
 	d_drop(dentry);
 	if (dentry->d_inode) {
 		rpc_close_pipes(dentry->d_inode);
-		rpc_inode_setowner(dentry->d_inode, NULL);
 		error = simple_unlink(dir, dentry);
 	}
 	dput(dentry);
---
0.99.8.GIT


--- NEW FILE 0919-gfp_t-net.txt ---
Subject: [PATCH] gfp_t: net/*
From: Al Viro <viro zeniv linux org uk>
Date: 1129879243 -0400

Signed-off-by: Al Viro <viro zeniv linux org uk>
Signed-off-by: Linus Torvalds <torvalds osdl org>

---

 include/linux/security.h |    2 +-
 include/net/sock.h       |    2 +-
 net/core/sock.c          |    2 +-
 net/dccp/output.c        |    2 +-
 net/netlink/af_netlink.c |    2 +-
 security/dummy.c         |    2 +-
 security/selinux/hooks.c |    4 ++--
 7 files changed, 8 insertions(+), 8 deletions(-)

applies-to: f7e993817030747c5e1000d46685ebd2eef11085
7d877f3bda870ab5f001bd92528654471d5966b3
diff --git a/include/linux/security.h b/include/linux/security.h
index 627382e..dac956e 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1210,7 +1210,7 @@ struct security_operations {
 	int (*socket_shutdown) (struct socket * sock, int how);
 	int (*socket_sock_rcv_skb) (struct sock * sk, struct sk_buff * skb);
 	int (*socket_getpeersec) (struct socket *sock, char __user *optval, int __user *optlen, unsigned len);
-	int (*sk_alloc_security) (struct sock *sk, int family, int priority);
+	int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority);
 	void (*sk_free_security) (struct sock *sk);
 #endif	/* CONFIG_SECURITY_NETWORK */
 };
diff --git a/include/net/sock.h b/include/net/sock.h
index ecb7552..e0498bd 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -207,7 +207,7 @@ struct sock {
 	struct sk_buff_head	sk_write_queue;
 	int			sk_wmem_queued;
 	int			sk_forward_alloc;
-	unsigned int		sk_allocation;
+	gfp_t			sk_allocation;
 	int			sk_sndbuf;
 	int			sk_route_caps;
 	unsigned long 		sk_flags;
diff --git a/net/core/sock.c b/net/core/sock.c
index 1c52fe8..9602ceb 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -940,7 +940,7 @@ static struct sk_buff *sock_alloc_send_p
 					    int noblock, int *errcode)
 {
 	struct sk_buff *skb;
-	unsigned int gfp_mask;
+	gfp_t gfp_mask;
 	long timeo;
 	int err;
 
diff --git a/net/dccp/output.c b/net/dccp/output.c
index 2925074..d59f86f 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -495,7 +495,7 @@ void dccp_send_close(struct sock *sk, co
 {
 	struct dccp_sock *dp = dccp_sk(sk);
 	struct sk_buff *skb;
-	const unsigned int prio = active ? GFP_KERNEL : GFP_ATOMIC;
+	const gfp_t prio = active ? GFP_KERNEL : GFP_ATOMIC;
 
 	skb = alloc_skb(sk->sk_prot->max_header, prio);
 	if (skb == NULL)
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 678c3f2..291df2e 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -827,7 +827,7 @@ struct netlink_broadcast_data {
 	int failure;
 	int congested;
 	int delivered;
-	unsigned int allocation;
+	gfp_t allocation;
 	struct sk_buff *skb, *skb2;
 };
 
diff --git a/security/dummy.c b/security/dummy.c
index 9623a61..3d34f3d 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -768,7 +768,7 @@ static int dummy_socket_getpeersec(struc
 	return -ENOPROTOOPT;
 }
 
-static inline int dummy_sk_alloc_security (struct sock *sk, int family, int priority)
+static inline int dummy_sk_alloc_security (struct sock *sk, int family, gfp_t priority)
 {
 	return 0;
 }
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index b13be15..447a1e0 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -262,7 +262,7 @@ static void superblock_free_security(str
 }
 
 #ifdef CONFIG_SECURITY_NETWORK
-static int sk_alloc_security(struct sock *sk, int family, int priority)
+static int sk_alloc_security(struct sock *sk, int family, gfp_t priority)
 {
 	struct sk_security_struct *ssec;
 
@@ -3380,7 +3380,7 @@ out:	
 	return err;
 }
 
-static int selinux_sk_alloc_security(struct sock *sk, int family, int priority)
+static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
 {
 	return sk_alloc_security(sk, family, priority);
 }
---
0.99.8.GIT


--- NEW FILE 0951-ARM-2897-2-PXA2xx-IRDA-support.txt ---
Subject: [PATCH] [ARM] 2897/2: PXA2xx IRDA support
From: Nicolas Pitre <nico cam org>
Date: 1130513973 +0100

Patch from Nicolas Pitre

This is the PXA2xx common IRDA driver, plus platform support
for Lubbock and Mainstone.

Signed-off-by: Nicolas Pitre <nico cam org>
Acked-by: Jean Tourrilhes <jt hpl hp com>
Signed-off-by: Russell King <rmk+kernel arm linux org uk>

---

 arch/arm/mach-pxa/generic.c         |   18 +
 arch/arm/mach-pxa/lubbock.c         |   20 +
 arch/arm/mach-pxa/mainstone.c       |   25 +
 drivers/net/irda/Kconfig            |   10 
 drivers/net/irda/Makefile           |    1 
 drivers/net/irda/pxaficp_ir.c       |  871 +++++++++++++++++++++++++++++++++++
 include/asm-arm/arch-pxa/irda.h     |   17 +
 include/asm-arm/arch-pxa/pxa-regs.h |    2 
 8 files changed, 962 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/irda/pxaficp_ir.c
 create mode 100644 include/asm-arm/arch-pxa/irda.h

applies-to: 951b848e666ed00b90c2ac55bce1b2664dd51c27
6f475c0133eb91c7df3b056843dc33d2824368a2
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index 218eb96..3248bc9 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -34,6 +34,7 @@
 #include <asm/arch/udc.h>
 #include <asm/arch/pxafb.h>
 #include <asm/arch/mmc.h>
+#include <asm/arch/irda.h>
 #include <asm/arch/i2c.h>
 
 #include "generic.h"
@@ -301,6 +302,22 @@ static struct platform_device i2s_device
 	.num_resources	= ARRAY_SIZE(i2s_resources),
 };
 
+static u64 pxaficp_dmamask = ~(u32)0;
+
+static struct platform_device pxaficp_device = {
+	.name		= "pxa2xx-ir",
+	.id		= -1,
+	.dev		= {
+		.dma_mask = &pxaficp_dmamask,
+		.coherent_dma_mask = 0xffffffff,
+	},
+};
+
+void __init pxa_set_ficp_info(struct pxaficp_platform_data *info)
+{
+	pxaficp_device.dev.platform_data = info;
+}
+
 static struct platform_device *devices[] __initdata = {
 	&pxamci_device,
 	&udc_device,
@@ -308,6 +325,7 @@ static struct platform_device *devices[]
 	&ffuart_device,
 	&btuart_device,
 	&stuart_device,
+	&pxaficp_device,
 	&i2c_device,
 	&i2s_device,
 };
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index 69abc7f..beccf45 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -35,6 +35,7 @@
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/lubbock.h>
 #include <asm/arch/udc.h>
+#include <asm/arch/irda.h>
 #include <asm/arch/pxafb.h>
 #include <asm/arch/mmc.h>
 
@@ -237,11 +238,30 @@ static struct pxamci_platform_data lubbo
 	.init 		= lubbock_mci_init,
 };
 
+static void lubbock_irda_transceiver_mode(struct device *dev, int mode)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	if (mode & IR_SIRMODE) {
+		LUB_MISC_WR &= ~(1 << 4);
+	} else if (mode & IR_FIRMODE) {
+		LUB_MISC_WR |= 1 << 4;
+	}
+	local_irq_restore(flags);
+}
+
+static struct pxaficp_platform_data lubbock_ficp_platform_data = {
+	.transceiver_cap  = IR_SIRMODE | IR_FIRMODE,
+	.transceiver_mode = lubbock_irda_transceiver_mode,
+};
+
 static void __init lubbock_init(void)
 {
 	pxa_set_udc_info(&udc_info);
 	set_pxa_fb_info(&sharp_lm8v31);
 	pxa_set_mci_info(&lubbock_mci_platform_data);
+	pxa_set_ficp_info(&lubbock_ficp_platform_data);
 	(void) platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 8b4a216..a48c640 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -37,6 +37,7 @@
 #include <asm/arch/audio.h>
 #include <asm/arch/pxafb.h>
 #include <asm/arch/mmc.h>
+#include <asm/arch/irda.h>
 
 #include "generic.h"
 
@@ -294,6 +295,29 @@ static struct pxamci_platform_data mains
 	.exit		= mainstone_mci_exit,
 };
 
+static void mainstone_irda_transceiver_mode(struct device *dev, int mode)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	if (mode & IR_SIRMODE) {
+		MST_MSCWR1 &= ~MST_MSCWR1_IRDA_FIR;
+	} else if (mode & IR_FIRMODE) {
+		MST_MSCWR1 |= MST_MSCWR1_IRDA_FIR;
+	}
+	if (mode & IR_OFF) {
+		MST_MSCWR1 = (MST_MSCWR1 & ~MST_MSCWR1_IRDA_MASK) | MST_MSCWR1_IRDA_OFF;
+	} else {
+		MST_MSCWR1 = (MST_MSCWR1 & ~MST_MSCWR1_IRDA_MASK) | MST_MSCWR1_IRDA_FULL;
+	}
+	local_irq_restore(flags);
+}
+
+static struct pxaficp_platform_data mainstone_ficp_platform_data = {
+	.transceiver_cap  = IR_SIRMODE | IR_FIRMODE | IR_OFF,
+	.transceiver_mode = mainstone_irda_transceiver_mode,
+};
+
 static void __init mainstone_init(void)
 {
 	/*
@@ -313,6 +337,7 @@ static void __init mainstone_init(void)
 		set_pxa_fb_info(&toshiba_ltm035a776c);
 
 	pxa_set_mci_info(&mainstone_mci_platform_data);
+	pxa_set_ficp_info(&mainstone_ficp_platform_data);
 }
 
 
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index ca59140..d54156f 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -400,5 +400,15 @@ config VIA_FIR
 	  To compile it as a module, choose M here: the module will be called
 	  via-ircc.
 
+config PXA_FICP
+	tristate "Intel PXA2xx Internal FICP"
+	depends on ARCH_PXA && IRDA
+	help
+	  Say Y or M here if you want to build support for the PXA2xx
+	  built-in IRDA interface which can support both SIR and FIR.
+	  This driver relies on platform specific helper routines so
+	  available capabilities may vary from one PXA2xx target to
+	  another.
+
 endmenu
 
diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile
index 29a8bd8..e7a8b7f 100644
--- a/drivers/net/irda/Makefile
+++ b/drivers/net/irda/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_SMC_IRCC_FIR)	+= smsc-ircc2
 obj-$(CONFIG_ALI_FIR)		+= ali-ircc.o
 obj-$(CONFIG_VLSI_FIR)		+= vlsi_ir.o
 obj-$(CONFIG_VIA_FIR)		+= via-ircc.o
+obj-$(CONFIG_PXA_FICP)	        += pxaficp_ir.o
 # Old dongle drivers for old SIR drivers
 obj-$(CONFIG_ESI_DONGLE_OLD)		+= esi.o
 obj-$(CONFIG_TEKRAM_DONGLE_OLD)	+= tekram.o
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
new file mode 100644
index 0000000..aef80f5
--- /dev/null
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -0,0 +1,871 @@
+/*
+ * linux/drivers/net/irda/pxaficp_ir.c
+ *
+ * Based on sa1100_ir.c by Russell King
+ *
+ * Changes copyright (C) 2003-2005 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Infra-red driver (SIR/FIR) for the PXA2xx embedded microprocessor
+ *
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/slab.h>
+#include <linux/rtnetlink.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/pm.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/irda_device.h>
+
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <asm/delay.h>
+#include <asm/hardware.h>
+#include <asm/arch/irda.h>
+#include <asm/arch/pxa-regs.h>
+
+#ifdef CONFIG_MACH_MAINSTONE
+#include <asm/arch/mainstone.h>
+#endif
+
+#define IrSR_RXPL_NEG_IS_ZERO (1<<4)
+#define IrSR_RXPL_POS_IS_ZERO 0x0
+#define IrSR_TXPL_NEG_IS_ZERO (1<<3)
+#define IrSR_TXPL_POS_IS_ZERO 0x0
+#define IrSR_XMODE_PULSE_1_6  (1<<2)
+#define IrSR_XMODE_PULSE_3_16 0x0
+#define IrSR_RCVEIR_IR_MODE   (1<<1)
+#define IrSR_RCVEIR_UART_MODE 0x0
+#define IrSR_XMITIR_IR_MODE   (1<<0)
+#define IrSR_XMITIR_UART_MODE 0x0
+
+#define IrSR_IR_RECEIVE_ON (\
+                IrSR_RXPL_NEG_IS_ZERO | \
+                IrSR_TXPL_POS_IS_ZERO | \
+                IrSR_XMODE_PULSE_3_16 | \
+                IrSR_RCVEIR_IR_MODE   | \
+                IrSR_XMITIR_UART_MODE)
+
+#define IrSR_IR_TRANSMIT_ON (\
+                IrSR_RXPL_NEG_IS_ZERO | \
+                IrSR_TXPL_POS_IS_ZERO | \
+                IrSR_XMODE_PULSE_3_16 | \
+                IrSR_RCVEIR_UART_MODE | \
+                IrSR_XMITIR_IR_MODE)
+
+struct pxa_irda {
+	int			speed;
+	int			newspeed;
+	unsigned long		last_oscr;
+
+	unsigned char		*dma_rx_buff;
+	unsigned char		*dma_tx_buff;
+	dma_addr_t		dma_rx_buff_phy;
+	dma_addr_t		dma_tx_buff_phy;
+	unsigned int		dma_tx_buff_len;
+	int			txdma;
+	int			rxdma;
+
+	struct net_device_stats	stats;
+	struct irlap_cb		*irlap;
+	struct qos_info		qos;
+
+	iobuff_t		tx_buff;
+	iobuff_t		rx_buff;
+
+	struct device		*dev;
+	struct pxaficp_platform_data *pdata;
+};
+
+
+#define IS_FIR(si)		((si)->speed >= 4000000)
+#define IRDA_FRAME_SIZE_LIMIT	2047
+
+inline static void pxa_irda_fir_dma_rx_start(struct pxa_irda *si)
+{
+	DCSR(si->rxdma)  = DCSR_NODESC;
+	DSADR(si->rxdma) = __PREG(ICDR);
+	DTADR(si->rxdma) = si->dma_rx_buff_phy;
+	DCMD(si->rxdma) = DCMD_INCTRGADDR | DCMD_FLOWSRC |  DCMD_WIDTH1 | DCMD_BURST32 | IRDA_FRAME_SIZE_LIMIT;
+	DCSR(si->rxdma) |= DCSR_RUN;
+}
+
+inline static void pxa_irda_fir_dma_tx_start(struct pxa_irda *si)
+{
+	DCSR(si->txdma)  = DCSR_NODESC;
+	DSADR(si->txdma) = si->dma_tx_buff_phy;
+	DTADR(si->txdma) = __PREG(ICDR);
+	DCMD(si->txdma) = DCMD_INCSRCADDR | DCMD_FLOWTRG |  DCMD_ENDIRQEN | DCMD_WIDTH1 | DCMD_BURST32 | si->dma_tx_buff_len;
+	DCSR(si->txdma) |= DCSR_RUN;
+}
+
+/*
+ * Set the IrDA communications speed.
+ */
+static int pxa_irda_set_speed(struct pxa_irda *si, int speed)
+{
+	unsigned long flags;
+	unsigned int divisor;
+
+	switch (speed) {
+	case 9600:	case 19200:	case 38400:
+	case 57600:	case 115200:
+
+		/* refer to PXA250/210 Developer's Manual 10-7 */
+		/*  BaudRate = 14.7456 MHz / (16*Divisor) */
+		divisor = 14745600 / (16 * speed);
+
+		local_irq_save(flags);
+
+		if (IS_FIR(si)) {
+			/* stop RX DMA */
+			DCSR(si->rxdma) &= ~DCSR_RUN;
+			/* disable FICP */
+			ICCR0 = 0;
+			pxa_set_cken(CKEN13_FICP, 0);
+
+			/* set board transceiver to SIR mode */
+			si->pdata->transceiver_mode(si->dev, IR_SIRMODE);
+
+			/* configure GPIO46/47 */
+			pxa_gpio_mode(GPIO46_STRXD_MD);
+			pxa_gpio_mode(GPIO47_STTXD_MD);
+
+			/* enable the STUART clock */
+			pxa_set_cken(CKEN5_STUART, 1);
+		}
+
+		/* disable STUART first */
+		STIER = 0;
+
+		/* access DLL & DLH */
+		STLCR |= LCR_DLAB;
+		STDLL = divisor & 0xff;
+		STDLH = divisor >> 8;
+		STLCR &= ~LCR_DLAB;
+
+		si->speed = speed;
+		STISR = IrSR_IR_RECEIVE_ON | IrSR_XMODE_PULSE_1_6;
+		STIER = IER_UUE | IER_RLSE | IER_RAVIE | IER_RTIOE;
+
+		local_irq_restore(flags);
+		break;
+
+	case 4000000:
+		local_irq_save(flags);
+
+		/* disable STUART */
+		STIER = 0;
+		STISR = 0;
+		pxa_set_cken(CKEN5_STUART, 0);
+
+		/* disable FICP first */
+		ICCR0 = 0;
+
+		/* set board transceiver to FIR mode */
+		si->pdata->transceiver_mode(si->dev, IR_FIRMODE);
+
+		/* configure GPIO46/47 */
+		pxa_gpio_mode(GPIO46_ICPRXD_MD);
+		pxa_gpio_mode(GPIO47_ICPTXD_MD);
+
+		/* enable the FICP clock */
+		pxa_set_cken(CKEN13_FICP, 1);
+
+		si->speed = speed;
+		pxa_irda_fir_dma_rx_start(si);
+		ICCR0 = ICCR0_ITR | ICCR0_RXE;
+
+		local_irq_restore(flags);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* SIR interrupt service routine. */
+static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = dev_id;
+	struct pxa_irda *si = netdev_priv(dev);
+	int iir, lsr, data;
+
+	iir = STIIR;
+
+	switch  (iir & 0x0F) {
+	case 0x06: /* Receiver Line Status */
+	  	lsr = STLSR;
+		while (lsr & LSR_FIFOE) {
+			data = STRBR;
+			if (lsr & (LSR_OE | LSR_PE | LSR_FE | LSR_BI)) {
+				printk(KERN_DEBUG "pxa_ir: sir receiving error\n");
+				si->stats.rx_errors++;
+				if (lsr & LSR_FE)
+					si->stats.rx_frame_errors++;
+				if (lsr & LSR_OE)
+					si->stats.rx_fifo_errors++;
+			} else {
+				si->stats.rx_bytes++;
+				async_unwrap_char(dev, &si->stats, &si->rx_buff, data);
+			}
+			lsr = STLSR;
+		}
+		dev->last_rx = jiffies;
+		si->last_oscr = OSCR;
+		break;
+
+	case 0x04: /* Received Data Available */
+	  	   /* forth through */
+
+	case 0x0C: /* Character Timeout Indication */
+	  	do  {
+		    si->stats.rx_bytes++;
+	            async_unwrap_char(dev, &si->stats, &si->rx_buff, STRBR);
+	  	} while (STLSR & LSR_DR);
+	  	dev->last_rx = jiffies;
+		si->last_oscr = OSCR;
+	  	break;
+
+	case 0x02: /* Transmit FIFO Data Request */
+	    	while ((si->tx_buff.len) && (STLSR & LSR_TDRQ)) {
+	    		STTHR = *si->tx_buff.data++;
+			si->tx_buff.len -= 1;
+	    	}
+
+		if (si->tx_buff.len == 0) {
+			si->stats.tx_packets++;
+			si->stats.tx_bytes += si->tx_buff.data -
+					      si->tx_buff.head;
+
+                        /* We need to ensure that the transmitter has finished. */
+			while ((STLSR & LSR_TEMT) == 0)
+				cpu_relax();
+			si->last_oscr = OSCR;
+
+			/*
+		 	* Ok, we've finished transmitting.  Now enable
+		 	* the receiver.  Sometimes we get a receive IRQ
+		 	* immediately after a transmit...
+		 	*/
+			if (si->newspeed) {
+				pxa_irda_set_speed(si, si->newspeed);
+				si->newspeed = 0;
+			} else {
+				/* enable IR Receiver, disable IR Transmitter */
+				STISR = IrSR_IR_RECEIVE_ON | IrSR_XMODE_PULSE_1_6;
+				/* enable STUART and receive interrupts */
+				STIER = IER_UUE | IER_RLSE | IER_RAVIE | IER_RTIOE;
+			}
+			/* I'm hungry! */
+			netif_wake_queue(dev);
+		}
+		break;
+	}
+
+	return IRQ_HANDLED;
+}
+
+/* FIR Receive DMA interrupt handler */
+static void pxa_irda_fir_dma_rx_irq(int channel, void *data, struct pt_regs *regs)
+{
+	int dcsr = DCSR(channel);
+
+	DCSR(channel) = dcsr & ~DCSR_RUN;
+
+	printk(KERN_DEBUG "pxa_ir: fir rx dma bus error %#x\n", dcsr);
+}
+
+/* FIR Transmit DMA interrupt handler */
+static void pxa_irda_fir_dma_tx_irq(int channel, void *data, struct pt_regs *regs)
+{
+	struct net_device *dev = data;
+	struct pxa_irda *si = netdev_priv(dev);
+	int dcsr;
+
+	dcsr = DCSR(channel);
+	DCSR(channel) = dcsr & ~DCSR_RUN;
+
+	if (dcsr & DCSR_ENDINTR)  {
+		si->stats.tx_packets++;
+		si->stats.tx_bytes += si->dma_tx_buff_len;
+	} else {
+		si->stats.tx_errors++;
+	}
+
+	while (ICSR1 & ICSR1_TBY)
+		cpu_relax();
+	si->last_oscr = OSCR;
+
+	/*
+	 * HACK: It looks like the TBY bit is dropped too soon.
+	 * Without this delay things break.
+	 */
+	udelay(120);
+
+	if (si->newspeed) {
+		pxa_irda_set_speed(si, si->newspeed);
+		si->newspeed = 0;
+	} else {
+		ICCR0 = 0;
+		pxa_irda_fir_dma_rx_start(si);
+		ICCR0 = ICCR0_ITR | ICCR0_RXE;
+	}
+	netif_wake_queue(dev);
+}
+
+/* EIF(Error in FIFO/End in Frame) handler for FIR */
+static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev)
+{
+	unsigned int len, stat, data;
+
+	/* Get the current data position. */
+	len = DTADR(si->rxdma) - si->dma_rx_buff_phy;
+
+	do {
+		/* Read Status, and then Data. 	 */
+		stat = ICSR1;
+		rmb();
+		data = ICDR;
+
+		if (stat & (ICSR1_CRE | ICSR1_ROR)) {
+			si->stats.rx_errors++;
+			if (stat & ICSR1_CRE) {
+				printk(KERN_DEBUG "pxa_ir: fir receive CRC error\n");
+				si->stats.rx_crc_errors++;
+			}
+			if (stat & ICSR1_ROR) {
+				printk(KERN_DEBUG "pxa_ir: fir receive overrun\n");
+				si->stats.rx_frame_errors++;
+			}
+		} else	{
+			si->dma_rx_buff[len++] = data;
+		}
+		/* If we hit the end of frame, there's no point in continuing. */
+		if (stat & ICSR1_EOF)
+			break;
+	} while (ICSR0 & ICSR0_EIF);
+
+	if (stat & ICSR1_EOF) {
+		/* end of frame. */
+		struct sk_buff *skb = alloc_skb(len+1,GFP_ATOMIC);
+		if (!skb)  {
+			printk(KERN_ERR "pxa_ir: fir out of memory for receive skb\n");
+			si->stats.rx_dropped++;
+			return;
+		}
+
+		/* Align IP header to 20 bytes  */
+		skb_reserve(skb, 1);
+		memcpy(skb->data, si->dma_rx_buff, len);
+		skb_put(skb, len);
+
+		/* Feed it to IrLAP  */
+		skb->dev = dev;
+		skb->mac.raw  = skb->data;
+		skb->protocol = htons(ETH_P_IRDA);
+		netif_rx(skb);
+
+		si->stats.rx_packets++;
+		si->stats.rx_bytes += len;
+
+		dev->last_rx = jiffies;
+	}
+}
+
+/* FIR interrupt handler */
+static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = dev_id;
+	struct pxa_irda *si = netdev_priv(dev);
+	int icsr0;
+
+	/* stop RX DMA */
+	DCSR(si->rxdma) &= ~DCSR_RUN;
+	si->last_oscr = OSCR;
+	icsr0 = ICSR0;
+
+	if (icsr0 & (ICSR0_FRE | ICSR0_RAB)) {
+		if (icsr0 & ICSR0_FRE) {
+		        printk(KERN_DEBUG "pxa_ir: fir receive frame error\n");
+			si->stats.rx_frame_errors++;
+		} else {
+			printk(KERN_DEBUG "pxa_ir: fir receive abort\n");
+			si->stats.rx_errors++;
+		}
+		ICSR0 = icsr0 & (ICSR0_FRE | ICSR0_RAB);
+	}
+
+	if (icsr0 & ICSR0_EIF) {
+		/* An error in FIFO occured, or there is a end of frame */
+		pxa_irda_fir_irq_eif(si, dev);
+	}
+
+	ICCR0 = 0;
+	pxa_irda_fir_dma_rx_start(si);
+	ICCR0 = ICCR0_ITR | ICCR0_RXE;
+
+	return IRQ_HANDLED;
+}
+
+/* hard_xmit interface of irda device */
+static int pxa_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct pxa_irda *si = netdev_priv(dev);
+	int speed = irda_get_next_speed(skb);
+
+	/*
+	 * Does this packet contain a request to change the interface
+	 * speed?  If so, remember it until we complete the transmission
+	 * of this frame.
+	 */
+	if (speed != si->speed && speed != -1)
+		si->newspeed = speed;
+
+	/*
+	 * If this is an empty frame, we can bypass a lot.
+	 */
+	if (skb->len == 0) {
+		if (si->newspeed) {
+			si->newspeed = 0;
+			pxa_irda_set_speed(si, speed);
+		}
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+	netif_stop_queue(dev);
+
+	if (!IS_FIR(si)) {
+		si->tx_buff.data = si->tx_buff.head;
+		si->tx_buff.len  = async_wrap_skb(skb, si->tx_buff.data, si->tx_buff.truesize);
+
+		/* Disable STUART interrupts and switch to transmit mode. */
+		STIER = 0;
+		STISR = IrSR_IR_TRANSMIT_ON | IrSR_XMODE_PULSE_1_6;
+
+		/* enable STUART and transmit interrupts */
+		STIER = IER_UUE | IER_TIE;
+	} else {
+		unsigned long mtt = irda_get_mtt(skb);
+
+		si->dma_tx_buff_len = skb->len;
+		memcpy(si->dma_tx_buff, skb->data, skb->len);
+
+		if (mtt)
+			while ((unsigned)(OSCR - si->last_oscr)/4 < mtt)
+				cpu_relax();
+
+		/* stop RX DMA,  disable FICP */
+		DCSR(si->rxdma) &= ~DCSR_RUN;
+		ICCR0 = 0;
+
+		pxa_irda_fir_dma_tx_start(si);
+		ICCR0 = ICCR0_ITR | ICCR0_TXE;
+	}
+
+	dev_kfree_skb(skb);
+	dev->trans_start = jiffies;
+	return 0;
+}
+
+static int pxa_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
+{
+	struct if_irda_req *rq = (struct if_irda_req *)ifreq;
+	struct pxa_irda *si = netdev_priv(dev);
+	int ret;
+
+	switch (cmd) {
+	case SIOCSBANDWIDTH:
+		ret = -EPERM;
+		if (capable(CAP_NET_ADMIN)) {
+			/*
+			 * We are unable to set the speed if the
+			 * device is not running.
+			 */
+			if (netif_running(dev)) {
+				ret = pxa_irda_set_speed(si,
+						rq->ifr_baudrate);
+			} else {
+				printk(KERN_INFO "pxa_ir: SIOCSBANDWIDTH: !netif_running\n");
+				ret = 0;
+			}
+		}
+		break;
+
+	case SIOCSMEDIABUSY:
+		ret = -EPERM;
+		if (capable(CAP_NET_ADMIN)) {
+			irda_device_set_media_busy(dev, TRUE);
+			ret = 0;
+		}
+		break;
+
+	case SIOCGRECEIVING:
+		ret = 0;
+		rq->ifr_receiving = IS_FIR(si) ? 0
+					: si->rx_buff.state != OUTSIDE_FRAME;
+		break;
+
+	default:
+		ret = -EOPNOTSUPP;
+		break;
+	}
+
+	return ret;
+}
+
+static struct net_device_stats *pxa_irda_stats(struct net_device *dev)
+{
+	struct pxa_irda *si = netdev_priv(dev);
+	return &si->stats;
+}
+
+static void pxa_irda_startup(struct pxa_irda *si)
+{
+	/* Disable STUART interrupts */
+	STIER = 0;
+	/* enable STUART interrupt to the processor */
+	STMCR = MCR_OUT2;
+	/* configure SIR frame format: StartBit - Data 7 ... Data 0 - Stop Bit */
+	STLCR = LCR_WLS0 | LCR_WLS1;
+	/* enable FIFO, we use FIFO to improve performance */
+	STFCR = FCR_TRFIFOE | FCR_ITL_32;
+
+	/* disable FICP */
+	ICCR0 = 0;
+	/* configure FICP ICCR2 */
+	ICCR2 = ICCR2_TXP | ICCR2_TRIG_32;
+
+	/* configure DMAC */
+	DRCMR17 = si->rxdma | DRCMR_MAPVLD;
+	DRCMR18 = si->txdma | DRCMR_MAPVLD;
+
+	/* force SIR reinitialization */
+	si->speed = 4000000;
+	pxa_irda_set_speed(si, 9600);
+
+	printk(KERN_DEBUG "pxa_ir: irda startup\n");
+}
+
+static void pxa_irda_shutdown(struct pxa_irda *si)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	/* disable STUART and interrupt */
+	STIER = 0;
+	/* disable STUART SIR mode */
+	STISR = 0;
+	/* disable the STUART clock */
+	pxa_set_cken(CKEN5_STUART, 0);
+
+	/* disable DMA */
+	DCSR(si->txdma) &= ~DCSR_RUN;
+	DCSR(si->rxdma) &= ~DCSR_RUN;
+	/* disable FICP */
+	ICCR0 = 0;
+	/* disable the FICP clock */
+	pxa_set_cken(CKEN13_FICP, 0);
+
+	DRCMR17 = 0;
+	DRCMR18 = 0;
+
+	local_irq_restore(flags);
+
+	/* power off board transceiver */
+	si->pdata->transceiver_mode(si->dev, IR_OFF);
+
+	printk(KERN_DEBUG "pxa_ir: irda shutdown\n");
+}
+
+static int pxa_irda_start(struct net_device *dev)
+{
+	struct pxa_irda *si = netdev_priv(dev);
+	int err;
+
+	si->speed = 9600;
+
+	err = request_irq(IRQ_STUART, pxa_irda_sir_irq, 0, dev->name, dev);
+	if (err)
+		goto err_irq1;
+
+	err = request_irq(IRQ_ICP, pxa_irda_fir_irq, 0, dev->name, dev);
+	if (err)
+		goto err_irq2;
+
+	/*
+	 * The interrupt must remain disabled for now.
+	 */
+	disable_irq(IRQ_STUART);
+	disable_irq(IRQ_ICP);
+
+	err = -EBUSY;
+	si->rxdma = pxa_request_dma("FICP_RX",DMA_PRIO_LOW, pxa_irda_fir_dma_rx_irq, dev);
+	if (si->rxdma < 0)
+		goto err_rx_dma;
+
+	si->txdma = pxa_request_dma("FICP_TX",DMA_PRIO_LOW, pxa_irda_fir_dma_tx_irq, dev);
+	if (si->txdma < 0)
+		goto err_tx_dma;
+
+	err = -ENOMEM;
+	si->dma_rx_buff = dma_alloc_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT,
+					     &si->dma_rx_buff_phy, GFP_KERNEL );
+	if (!si->dma_rx_buff)
+		goto err_dma_rx_buff;
+
+	si->dma_tx_buff = dma_alloc_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT,
+					     &si->dma_tx_buff_phy, GFP_KERNEL );
+	if (!si->dma_tx_buff)
+		goto err_dma_tx_buff;
+
+	/* Setup the serial port for the initial speed. */
+	pxa_irda_startup(si);
+
+	/*
+	 * Open a new IrLAP layer instance.
+	 */
+	si->irlap = irlap_open(dev, &si->qos, "pxa");
+	err = -ENOMEM;
+	if (!si->irlap)
+		goto err_irlap;
+
+	/*
+	 * Now enable the interrupt and start the queue
+	 */
+	enable_irq(IRQ_STUART);
+	enable_irq(IRQ_ICP);
+	netif_start_queue(dev);
+
+	printk(KERN_DEBUG "pxa_ir: irda driver opened\n");
+
+	return 0;
+
+err_irlap:
+	pxa_irda_shutdown(si);
+	dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_tx_buff, si->dma_tx_buff_phy);
+err_dma_tx_buff:
+	dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_rx_buff, si->dma_rx_buff_phy);
+err_dma_rx_buff:
+	pxa_free_dma(si->txdma);
+err_tx_dma:
+	pxa_free_dma(si->rxdma);
+err_rx_dma:
+	free_irq(IRQ_ICP, dev);
+err_irq2:
+	free_irq(IRQ_STUART, dev);
+err_irq1:
+
+	return err;
+}
+
+static int pxa_irda_stop(struct net_device *dev)
+{
+	struct pxa_irda *si = netdev_priv(dev);
+
+	netif_stop_queue(dev);
+
+	pxa_irda_shutdown(si);
+
+	/* Stop IrLAP */
+	if (si->irlap) {
+		irlap_close(si->irlap);
+		si->irlap = NULL;
+	}
+
+	free_irq(IRQ_STUART, dev);
+	free_irq(IRQ_ICP, dev);
+
+	pxa_free_dma(si->rxdma);
+	pxa_free_dma(si->txdma);
+
+	if (si->dma_rx_buff)
+		dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_tx_buff, si->dma_tx_buff_phy);
+	if (si->dma_tx_buff)
+		dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_rx_buff, si->dma_rx_buff_phy);
+
+	printk(KERN_DEBUG "pxa_ir: irda driver closed\n");
+	return 0;
+}
+
+static int pxa_irda_suspend(struct device *_dev, pm_message_t state, u32 level)
+{
+	struct net_device *dev = dev_get_drvdata(_dev);
+	struct pxa_irda *si;
+
+	if (!dev || level != SUSPEND_DISABLE)
+		return 0;
+
+	if (netif_running(dev)) {
+		si = netdev_priv(dev);
+		netif_device_detach(dev);
+		pxa_irda_shutdown(si);
+	}
+
+	return 0;
+}
+
+static int pxa_irda_resume(struct device *_dev, u32 level)
+{
+	struct net_device *dev = dev_get_drvdata(_dev);
+	struct pxa_irda *si;
+
+	if (!dev || level != RESUME_ENABLE)
+		return 0;
+
+	if (netif_running(dev)) {
+		si = netdev_priv(dev);
+		pxa_irda_startup(si);
+		netif_device_attach(dev);
+		netif_wake_queue(dev);
+	}
+
+	return 0;
+}
+
+
+static int pxa_irda_init_iobuf(iobuff_t *io, int size)
+{
+	io->head = kmalloc(size, GFP_KERNEL | GFP_DMA);
+	if (io->head != NULL) {
+		io->truesize = size;
+		io->in_frame = FALSE;
+		io->state    = OUTSIDE_FRAME;
+		io->data     = io->head;
+	}
+	return io->head ? 0 : -ENOMEM;
+}
+
+static int pxa_irda_probe(struct device *_dev)
+{
+	struct platform_device *pdev = to_platform_device(_dev);
+	struct net_device *dev;
+	struct pxa_irda *si;
+	unsigned int baudrate_mask;
+	int err;
+
+	if (!pdev->dev.platform_data)
+		return -ENODEV;
+
+	err = request_mem_region(__PREG(STUART), 0x24, "IrDA") ? 0 : -EBUSY;
+	if (err)
+		goto err_mem_1;
+
+	err = request_mem_region(__PREG(FICP), 0x1c, "IrDA") ? 0 : -EBUSY;
+	if (err)
+		goto err_mem_2;
+
+	dev = alloc_irdadev(sizeof(struct pxa_irda));
+	if (!dev)
+		goto err_mem_3;
+
+	si = netdev_priv(dev);
+	si->dev = &pdev->dev;
+	si->pdata = pdev->dev.platform_data;
+
+	/*
+	 * Initialise the SIR buffers
+	 */
+	err = pxa_irda_init_iobuf(&si->rx_buff, 14384);
+	if (err)
+		goto err_mem_4;
+	err = pxa_irda_init_iobuf(&si->tx_buff, 4000);
+	if (err)
+		goto err_mem_5;
+
+	dev->hard_start_xmit	= pxa_irda_hard_xmit;
+	dev->open		= pxa_irda_start;
+	dev->stop		= pxa_irda_stop;
+	dev->do_ioctl		= pxa_irda_ioctl;
+	dev->get_stats		= pxa_irda_stats;
+
+	irda_init_max_qos_capabilies(&si->qos);
+
+	baudrate_mask = 0;
+	if (si->pdata->transceiver_cap & IR_SIRMODE)
+		baudrate_mask |= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+	if (si->pdata->transceiver_cap & IR_FIRMODE)
+		baudrate_mask |= IR_4000000 << 8;
+
+	si->qos.baud_rate.bits &= baudrate_mask;
+	si->qos.min_turn_time.bits = 7;  /* 1ms or more */
+
+	irda_qos_bits_to_value(&si->qos);
+
+	err = register_netdev(dev);
+
+	if (err == 0)
+		dev_set_drvdata(&pdev->dev, dev);
+
+	if (err) {
+		kfree(si->tx_buff.head);
+err_mem_5:
+		kfree(si->rx_buff.head);
+err_mem_4:
+		free_netdev(dev);
+err_mem_3:
+		release_mem_region(__PREG(FICP), 0x1c);
+err_mem_2:
+		release_mem_region(__PREG(STUART), 0x24);
+	}
+err_mem_1:
+	return err;
+}
+
+static int pxa_irda_remove(struct device *_dev)
+{
+	struct net_device *dev = dev_get_drvdata(_dev);
+
+	if (dev) {
+		struct pxa_irda *si = netdev_priv(dev);
+		unregister_netdev(dev);
+		kfree(si->tx_buff.head);
+		kfree(si->rx_buff.head);
+		free_netdev(dev);
+	}
+
+	release_mem_region(__PREG(STUART), 0x24);
+	release_mem_region(__PREG(FICP), 0x1c);
+
+	return 0;
+}
+
+static struct device_driver pxa_ir_driver = {
+	.name		= "pxa2xx-ir",
+	.bus		= &platform_bus_type,
+	.probe		= pxa_irda_probe,
+	.remove		= pxa_irda_remove,
+	.suspend	= pxa_irda_suspend,
+	.resume		= pxa_irda_resume,
+};
+
+static int __init pxa_irda_init(void)
+{
+	return driver_register(&pxa_ir_driver);
+}
+
+static void __exit pxa_irda_exit(void)
+{
+	driver_unregister(&pxa_ir_driver);
+}
+
+module_init(pxa_irda_init);
+module_exit(pxa_irda_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/include/asm-arm/arch-pxa/irda.h b/include/asm-arm/arch-pxa/irda.h
new file mode 100644
index 0000000..748406f
--- /dev/null
+++ b/include/asm-arm/arch-pxa/irda.h
@@ -0,0 +1,17 @@
+#ifndef ASMARM_ARCH_IRDA_H
+#define ASMARM_ARCH_IRDA_H
+
+/* board specific transceiver capabilities */
+
+#define IR_OFF		1
+#define IR_SIRMODE	2
+#define IR_FIRMODE	4
+
+struct pxaficp_platform_data {
+	int transceiver_cap;
+	void (*transceiver_mode)(struct device *dev, int mode);
+};
+
+extern void pxa_set_ficp_info(struct pxaficp_platform_data *info);
+
+#endif
diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
index 75f085d..a75a247 100644
--- a/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/include/asm-arm/arch-pxa/pxa-regs.h
@@ -1032,14 +1032,12 @@
 #define ICCR0_LBM	(1 << 1)	/* Loopback mode */
 #define ICCR0_ITR	(1 << 0)	/* IrDA transmission */
 
-#ifdef CONFIG_PXA27x
 #define ICCR2_RXP       (1 << 3)	/* Receive Pin Polarity select */
 #define ICCR2_TXP       (1 << 2)	/* Transmit Pin Polarity select */
 #define ICCR2_TRIG	(3 << 0)	/* Receive FIFO Trigger threshold */
 #define ICCR2_TRIG_8    (0 << 0)	/* 	>= 8 bytes */
 #define ICCR2_TRIG_16   (1 << 0)	/*	>= 16 bytes */
 #define ICCR2_TRIG_32   (2 << 0)	/*	>= 32 bytes */
-#endif
 
 #ifdef CONFIG_PXA27x
 #define ICSR0_EOC	(1 << 6)	/* DMA End of Descriptor Chain */
---
0.99.8.GIT


--- NEW FILE 0997-Input-convert-net-bluetooth-to-dynamic-input_dev-allocation.txt ---
Subject: [PATCH] Input: convert net/bluetooth to dynamic input_dev allocation
From: Dmitry Torokhov <dtor_core ameritech net>
Date: 1126767700 -0500

Input: convert net/bluetooth to dynamic input_dev allocation

This is required for input_dev sysfs integration

Signed-off-by: Dmitry Torokhov <dtor mail ru>
Signed-off-by: Greg Kroah-Hartman <gregkh suse de>

---

 net/bluetooth/hidp/core.c |   13 ++++++++-----
 1 files changed, 8 insertions(+), 5 deletions(-)

applies-to: 261580f0229e6365f044cd26925dfb2735e0754d
34abf91f4036c01669e298e649b7ba85cadf82eb
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index de8af5f..860444a 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -520,7 +520,7 @@ static int hidp_session(void *arg)
 
 	if (session->input) {
 		input_unregister_device(session->input);
-		kfree(session->input);
+		session->input = NULL;
 	}
 
 	up_write(&hidp_session_sem);
@@ -536,6 +536,8 @@ static inline void hidp_setup_input(stru
 
 	input->private = session;
 
+	input->name = "Bluetooth HID Boot Protocol Device";
+
 	input->id.bustype = BUS_BLUETOOTH;
 	input->id.vendor  = req->vendor;
 	input->id.product = req->product;
@@ -582,16 +584,15 @@ int hidp_add_connection(struct hidp_conn
 		return -ENOTUNIQ;
 
 	session = kmalloc(sizeof(struct hidp_session), GFP_KERNEL);
-	if (!session) 
+	if (!session)
 		return -ENOMEM;
 	memset(session, 0, sizeof(struct hidp_session));
 
-	session->input = kmalloc(sizeof(struct input_dev), GFP_KERNEL);
+	session->input = input_allocate_device();
 	if (!session->input) {
 		kfree(session);
 		return -ENOMEM;
 	}
-	memset(session->input, 0, sizeof(struct input_dev));
 
 	down_write(&hidp_session_sem);
 
@@ -651,8 +652,10 @@ unlink:
 
 	__hidp_unlink_session(session);
 
-	if (session->input)
+	if (session->input) {
 		input_unregister_device(session->input);
+		session->input = NULL; /* don't try to free it here */
+	}
 
 failed:
 	up_write(&hidp_session_sem);
---
0.99.8.GIT


***** Error reading new file: [Errno 2] No such file or directory: '1017-Bluetooth-Move-CRC-table-into-RFCOMM-core.txt'

--- NEW FILE 1020-Bluetooth-Make-more-functions-static.txt ---
Subject: [PATCH] [Bluetooth] Make more functions static
From: Marcel Holtmann <marcel holtmann org>
Date: 1130520048 +0200

This patch makes another bunch of functions static.

Signed-off-by: Marcel Holtmann <marcel holtmann org>

---

 include/net/bluetooth/bluetooth.h |    6 ++++++
 net/bluetooth/af_bluetooth.c      |    6 ------
 net/bluetooth/hci_core.c          |    4 ++--
 3 files changed, 8 insertions(+), 8 deletions(-)

applies-to: 8e2d141927ac8d63663d8c88a6a0eb7e096d8a8b
6516455d3b42b33759a33a8102c1b8b48af4d9c9
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 2104586..e42d728 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -171,4 +171,10 @@ static inline int skb_frags_no(struct sk
 
 int bt_err(__u16 code);
 
+extern int hci_sock_init(void);
+extern int hci_sock_cleanup(void);
+
+extern int bt_sysfs_init(void);
+extern void bt_sysfs_cleanup(void);
+
 #endif /* __BLUETOOTH_H */
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 12b4334..0353206 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -308,12 +308,6 @@ static struct net_proto_family bt_sock_f
 	.create	= bt_sock_create,
 };
 
-extern int hci_sock_init(void);
-extern int hci_sock_cleanup(void);
-
-extern int bt_sysfs_init(void);
-extern int bt_sysfs_cleanup(void);
-
 static int __init bt_init(void)
 {
 	BT_INFO("Core ver %s", VERSION);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 55dc42e..cf0df1c 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -87,7 +87,7 @@ int hci_unregister_notifier(struct notif
 	return notifier_chain_unregister(&hci_notifier, nb);
 }
 
-void hci_notify(struct hci_dev *hdev, int event)
+static void hci_notify(struct hci_dev *hdev, int event)
 {
 	notifier_call_chain(&hci_notifier, event, hdev);
 }
@@ -1347,7 +1347,7 @@ static inline void hci_scodata_packet(st
 	kfree_skb(skb);
 }
 
-void hci_rx_task(unsigned long arg)
+static void hci_rx_task(unsigned long arg)
 {
 	struct hci_dev *hdev = (struct hci_dev *) arg;
 	struct sk_buff *skb;
---
0.99.8.GIT


--- NEW FILE 1021-Bluetooth-Update-security-filter-for-Extended-Inquiry-Response.txt ---
Subject: [PATCH] [Bluetooth] Update security filter for Extended Inquiry Response
From: Marcel Holtmann <marcel holtmann org>
Date: 1130520053 +0200

This patch updates the HCI security filter with support for the Extended
Inquiry Response (EIR) feature.

Signed-off-by: Marcel Holtmann <marcel holtmann org>

---

 net/bluetooth/hci_sock.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

applies-to: e7395ebcfa68c4a5aa25d80e4b279313f3fdea3e
dd7f5527b3e68a7b2f715ae1a21164383f418013
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 32ef797..799e448 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -66,20 +66,20 @@ static struct hci_sec_filter hci_sec_fil
 	/* Packet types */
 	0x10,
 	/* Events */
-	{ 0x1000d9fe, 0x0000300c },
+	{ 0x1000d9fe, 0x0000b00c },
 	/* Commands */
 	{
 		{ 0x0 },
 		/* OGF_LINK_CTL */
-		{ 0xbe000006, 0x00000001, 0x0000, 0x00 },
+		{ 0xbe000006, 0x00000001, 0x000000, 0x00 },
 		/* OGF_LINK_POLICY */
-		{ 0x00005200, 0x00000000, 0x0000, 0x00 },
+		{ 0x00005200, 0x00000000, 0x000000, 0x00 },
 		/* OGF_HOST_CTL */
-		{ 0xaab00200, 0x2b402aaa, 0x0154, 0x00 },
+		{ 0xaab00200, 0x2b402aaa, 0x020154, 0x00 },
 		/* OGF_INFO_PARAM */
-		{ 0x000002be, 0x00000000, 0x0000, 0x00 },
+		{ 0x000002be, 0x00000000, 0x000000, 0x00 },
 		/* OGF_STATUS_PARAM */
-		{ 0x000000ea, 0x00000000, 0x0000, 0x00 }
+		{ 0x000000ea, 0x00000000, 0x000000, 0x00 }
 	}
 };
 
---
0.99.8.GIT


--- NEW FILE 1026-IPv4-IPv6-UFO-Scatter-gather-approach.txt ---
Subject: [PATCH] [IPv4/IPv6]: UFO Scatter-gather approach
From: Ananda Raju <ananda raju neterion com>
Date: 1129675601 -0700

Attached is kernel patch for UDP Fragmentation Offload (UFO) feature.

1. This patch incorporate the review comments by Jeff Garzik.
2. Renamed USO as UFO (UDP Fragmentation Offload)
3. udp sendfile support with UFO

This patches uses scatter-gather feature of skb to generate large UDP
datagram. Below is a "how-to" on changes required in network device
driver to use the UFO interface.

UDP Fragmentation Offload (UFO) Interface:
-------------------------------------------
UFO is a feature wherein the Linux kernel network stack will offload the
IP fragmentation functionality of large UDP datagram to hardware. This
will reduce the overhead of stack in fragmenting the large UDP datagram to
MTU sized packets

1) Drivers indicate their capability of UFO using
dev->features |= NETIF_F_UFO | NETIF_F_HW_CSUM | NETIF_F_SG

NETIF_F_HW_CSUM is required for UFO over ipv6.

2) UFO packet will be submitted for transmission using driver xmit routine.
UFO packet will have a non-zero value for

"skb_shinfo(skb)->ufo_size"

skb_shinfo(skb)->ufo_size will indicate the length of data part in each IP
fragment going out of the adapter after IP fragmentation by hardware.

skb->data will contain MAC/IP/UDP header and skb_shinfo(skb)->frags[]
contains the data payload. The skb->ip_summed will be set to CHECKSUM_HW
indicating that hardware has to do checksum calculation. Hardware should
compute the UDP checksum of complete datagram and also ip header checksum of
each fragmented IP packet.

For IPV6 the UFO provides the fragment identification-id in
skb_shinfo(skb)->ip6_frag_id. The adapter should use this ID for generating
IPv6 fragments.

Signed-off-by: Ananda Raju <ananda raju neterion com>
Signed-off-by: Rusty Russell <rusty rustcorp com au> (forwarded)
Signed-off-by: Arnaldo Carvalho de Melo <acme mandriva com>

---

 include/linux/ethtool.h   |    8 ++++
 include/linux/netdevice.h |    1 +
 include/linux/skbuff.h    |    7 ++++
 net/core/dev.c            |   14 ++++++++
 net/core/ethtool.c        |   53 +++++++++++++++++++++++++++++
 net/core/skbuff.c         |   75 +++++++++++++++++++++++++++++++++++++++++
 net/ipv4/ip_output.c      |   83 ++++++++++++++++++++++++++++++++++++++++++---
 net/ipv6/ip6_output.c     |   71 ++++++++++++++++++++++++++++++++++++++
 8 files changed, 306 insertions(+), 6 deletions(-)

applies-to: 56ea0f4e21ca74b14e1546e70ac92617dfb27dd1
e89e9cf539a28df7d0eb1d0a545368e9920b34ac
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index ed1440e..d2c390e 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -269,6 +269,8 @@ u32 ethtool_op_get_tso(struct net_device
 int ethtool_op_set_tso(struct net_device *dev, u32 data);
 int ethtool_op_get_perm_addr(struct net_device *dev, 
 			     struct ethtool_perm_addr *addr, u8 *data);
+u32 ethtool_op_get_ufo(struct net_device *dev);
+int ethtool_op_set_ufo(struct net_device *dev, u32 data);
 
 /**
  * &ethtool_ops - Alter and report network device settings
@@ -298,6 +300,8 @@ int ethtool_op_get_perm_addr(struct net_
  * set_sg: Turn scatter-gather on or off
  * get_tso: Report whether TCP segmentation offload is enabled
  * set_tso: Turn TCP segmentation offload on or off
+ * get_ufo: Report whether UDP fragmentation offload is enabled
+ * set_ufo: Turn UDP fragmentation offload on or off
  * self_test: Run specified self-tests
  * get_strings: Return a set of strings that describe the requested objects 
  * phys_id: Identify the device
@@ -364,6 +368,8 @@ struct ethtool_ops {
 	int	(*get_perm_addr)(struct net_device *, struct ethtool_perm_addr *, u8 *);
 	int	(*begin)(struct net_device *);
 	void	(*complete)(struct net_device *);
+	u32     (*get_ufo)(struct net_device *);
+	int     (*set_ufo)(struct net_device *, u32);
 };
 
 /* CMDs currently supported */
@@ -400,6 +406,8 @@ struct ethtool_ops {
 #define ETHTOOL_GTSO		0x0000001e /* Get TSO enable (ethtool_value) */
 #define ETHTOOL_STSO		0x0000001f /* Set TSO enable (ethtool_value) */
 #define ETHTOOL_GPERMADDR	0x00000020 /* Get permanent hardware address */
+#define ETHTOOL_GUFO		0x00000021 /* Get UFO enable (ethtool_value) */
+#define ETHTOOL_SUFO		0x00000022 /* Set UFO enable (ethtool_value) */
 
 /* compatibility with older code */
 #define SPARC_ETH_GSET		ETHTOOL_GSET
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index a9281b2..c6efce4 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -308,6 +308,7 @@ struct net_device
 #define NETIF_F_VLAN_CHALLENGED	1024	/* Device cannot handle VLAN packets */
 #define NETIF_F_TSO		2048	/* Can offload TCP/IP segmentation */
 #define NETIF_F_LLTX		4096	/* LockLess TX */
+#define NETIF_F_UFO             8192    /* Can offload UDP Large Send*/
 
 	struct net_device	*next_sched;
 
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index b756935..4286d83 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -137,6 +137,8 @@ struct skb_shared_info {
 	unsigned int	nr_frags;
 	unsigned short	tso_size;
 	unsigned short	tso_segs;
+	unsigned short  ufo_size;
+	unsigned int    ip6_frag_id;
 	struct sk_buff	*frag_list;
 	skb_frag_t	frags[MAX_SKB_FRAGS];
 };
@@ -341,6 +343,11 @@ extern void	      skb_over_panic(struct 
 extern void	      skb_under_panic(struct sk_buff *skb, int len,
 				      void *here);
 
+extern int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
+			int getfrag(void *from, char *to, int offset,
+			int len,int odd, struct sk_buff *skb),
+			void *from, int length);
+
 struct skb_seq_state
 {
 	__u32		lower_offset;
diff --git a/net/core/dev.c b/net/core/dev.c
index a44eeef..8d15415 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2717,6 +2717,20 @@ int register_netdevice(struct net_device
 		       dev->name);
 		dev->features &= ~NETIF_F_TSO;
 	}
+	if (dev->features & NETIF_F_UFO) {
+		if (!(dev->features & NETIF_F_HW_CSUM)) {
+			printk(KERN_ERR "%s: Dropping NETIF_F_UFO since no "
+					"NETIF_F_HW_CSUM feature.\n",
+							dev->name);
+			dev->features &= ~NETIF_F_UFO;
+		}
+		if (!(dev->features & NETIF_F_SG)) {
+			printk(KERN_ERR "%s: Dropping NETIF_F_UFO since no "
+					"NETIF_F_SG feature.\n",
+					dev->name);
+			dev->features &= ~NETIF_F_UFO;
+		}
+	}
 
 	/*
 	 *	nil rebuild_header routine,
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 404b761..0350586 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -93,6 +93,20 @@ int ethtool_op_get_perm_addr(struct net_
 }
  
 
+u32 ethtool_op_get_ufo(struct net_device *dev)
+{
+	return (dev->features & NETIF_F_UFO) != 0;
+}
+
+int ethtool_op_set_ufo(struct net_device *dev, u32 data)
+{
+	if (data)
+		dev->features |= NETIF_F_UFO;
+	else
+		dev->features &= ~NETIF_F_UFO;
+	return 0;
+}
+
 /* Handlers for each ethtool command */
 
 static int ethtool_get_settings(struct net_device *dev, void __user *useraddr)
@@ -483,6 +497,11 @@ static int __ethtool_set_sg(struct net_d
 			return err;
 	}
 
+	if (!data && dev->ethtool_ops->set_ufo) {
+		err = dev->ethtool_ops->set_ufo(dev, 0);
+		if (err)
+			return err;
+	}
 	return dev->ethtool_ops->set_sg(dev, data);
 }
 
@@ -569,6 +588,32 @@ static int ethtool_set_tso(struct net_de
 	return dev->ethtool_ops->set_tso(dev, edata.data);
 }
 
+static int ethtool_get_ufo(struct net_device *dev, char __user *useraddr)
+{
+	struct ethtool_value edata = { ETHTOOL_GTSO };
+
+	if (!dev->ethtool_ops->get_ufo)
+		return -EOPNOTSUPP;
+	edata.data = dev->ethtool_ops->get_ufo(dev);
+	if (copy_to_user(useraddr, &edata, sizeof(edata)))
+		 return -EFAULT;
+	return 0;
+}
+static int ethtool_set_ufo(struct net_device *dev, char __user *useraddr)
+{
+	struct ethtool_value edata;
+
+	if (!dev->ethtool_ops->set_ufo)
+		return -EOPNOTSUPP;
+	if (copy_from_user(&edata, useraddr, sizeof(edata)))
+		return -EFAULT;
+	if (edata.data && !(dev->features & NETIF_F_SG))
+		return -EINVAL;
+	if (edata.data && !(dev->features & NETIF_F_HW_CSUM))
+		return -EINVAL;
+	return dev->ethtool_ops->set_ufo(dev, edata.data);
+}
+
 static int ethtool_self_test(struct net_device *dev, char __user *useraddr)
 {
 	struct ethtool_test test;
@@ -854,6 +899,12 @@ int dev_ethtool(struct ifreq *ifr)
 	case ETHTOOL_GPERMADDR:
 		rc = ethtool_get_perm_addr(dev, useraddr);
 		break;
+	case ETHTOOL_GUFO:
+		rc = ethtool_get_ufo(dev, useraddr);
+		break;
+	case ETHTOOL_SUFO:
+		rc = ethtool_set_ufo(dev, useraddr);
+		break;
 	default:
 		rc =  -EOPNOTSUPP;
 	}
@@ -882,3 +933,5 @@ EXPORT_SYMBOL(ethtool_op_set_sg);
 EXPORT_SYMBOL(ethtool_op_set_tso);
 EXPORT_SYMBOL(ethtool_op_set_tx_csum);
 EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum);
+EXPORT_SYMBOL(ethtool_op_set_ufo);
+EXPORT_SYMBOL(ethtool_op_get_ufo);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index ef9d46b..95501e4 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -176,6 +176,8 @@ struct sk_buff *__alloc_skb(unsigned int
 	skb_shinfo(skb)->tso_size = 0;
 	skb_shinfo(skb)->tso_segs = 0;
 	skb_shinfo(skb)->frag_list = NULL;
+	skb_shinfo(skb)->ufo_size = 0;
+	skb_shinfo(skb)->ip6_frag_id = 0;
 out:
 	return skb;
 nodata:
@@ -1696,6 +1698,78 @@ unsigned int skb_find_text(struct sk_buf
 	return textsearch_find(config, state);
 }
 
+/**
+ * skb_append_datato_frags: - append the user data to a skb
+ * @sk: sock  structure
+ * @skb: skb structure to be appened with user data.
+ * @getfrag: call back function to be used for getting the user data
+ * @from: pointer to user message iov
+ * @length: length of the iov message
+ *
+ * Description: This procedure append the user data in the fragment part
+ * of the skb if any page alloc fails user this procedure returns  -ENOMEM
+ */
+int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
+			int getfrag(void *from, char *to, int offset,
+					int len, int odd, struct sk_buff *skb),
+			void *from, int length)
+{
+	int frg_cnt = 0;
+	skb_frag_t *frag = NULL;
+	struct page *page = NULL;
+	int copy, left;
+	int offset = 0;
+	int ret;
+
+	do {
+		/* Return error if we don't have space for new frag */
+		frg_cnt = skb_shinfo(skb)->nr_frags;
+		if (frg_cnt >= MAX_SKB_FRAGS)
+			return -EFAULT;
+
+		/* allocate a new page for next frag */
+		page = alloc_pages(sk->sk_allocation, 0);
+
+		/* If alloc_page fails just return failure and caller will
+		 * free previous allocated pages by doing kfree_skb()
+		 */
+		if (page == NULL)
+			return -ENOMEM;
+
+		/* initialize the next frag */
+		sk->sk_sndmsg_page = page;
+		sk->sk_sndmsg_off = 0;
+		skb_fill_page_desc(skb, frg_cnt, page, 0, 0);
+		skb->truesize += PAGE_SIZE;
+		atomic_add(PAGE_SIZE, &sk->sk_wmem_alloc);
+
+		/* get the new initialized frag */
+		frg_cnt = skb_shinfo(skb)->nr_frags;
+		frag = &skb_shinfo(skb)->frags[frg_cnt - 1];
+
+		/* copy the user data to page */
+		left = PAGE_SIZE - frag->page_offset;
+		copy = (length > left)? left : length;
+
+		ret = getfrag(from, (page_address(frag->page) +
+			    frag->page_offset + frag->size),
+			    offset, copy, 0, skb);
+		if (ret < 0)
+			return -EFAULT;
+
+		/* copy was successful so update the size parameters */
+		sk->sk_sndmsg_off += copy;
+		frag->size += copy;
+		skb->len += copy;
+		skb->data_len += copy;
+		offset += copy;
+		length -= copy;
+
+	} while (length > 0);
+
+	return 0;
+}
+
 void __init skb_init(void)
 {
 	skbuff_head_cache = kmem_cache_create("skbuff_head_cache",
@@ -1747,3 +1821,4 @@ EXPORT_SYMBOL(skb_prepare_seq_read);
 EXPORT_SYMBOL(skb_seq_read);
 EXPORT_SYMBOL(skb_abort_seq_read);
 EXPORT_SYMBOL(skb_find_text);
+EXPORT_SYMBOL(skb_append_datato_frags);
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 87e3500..1775823 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -275,7 +275,8 @@ int ip_output(struct sk_buff *skb)
 {
 	IP_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
 
-	if (skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->tso_size)
+	if (skb->len > dst_mtu(skb->dst) &&
+		!(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
 		return ip_fragment(skb, ip_finish_output);
 	else
 		return ip_finish_output(skb);
@@ -688,6 +689,60 @@ csum_page(struct page *page, int offset,
 	return csum;
 }
 
+inline int ip_ufo_append_data(struct sock *sk,
+			int getfrag(void *from, char *to, int offset, int len,
+			       int odd, struct sk_buff *skb),
+			void *from, int length, int hh_len, int fragheaderlen,
+			int transhdrlen, int mtu,unsigned int flags)
+{
+	struct sk_buff *skb;
+	int err;
+
+	/* There is support for UDP fragmentation offload by network
+	 * device, so create one single skb packet containing complete
+	 * udp datagram
+	 */
+	if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) {
+		skb = sock_alloc_send_skb(sk,
+			hh_len + fragheaderlen + transhdrlen + 20,
+			(flags & MSG_DONTWAIT), &err);
+
+		if (skb == NULL)
+			return err;
+
+		/* reserve space for Hardware header */
+		skb_reserve(skb, hh_len);
+
+		/* create space for UDP/IP header */
+		skb_put(skb,fragheaderlen + transhdrlen);
+
+		/* initialize network header pointer */
+		skb->nh.raw = skb->data;
+
+		/* initialize protocol header pointer */
+		skb->h.raw = skb->data + fragheaderlen;
+
+		skb->ip_summed = CHECKSUM_HW;
+		skb->csum = 0;
+		sk->sk_sndmsg_off = 0;
+	}
+
+	err = skb_append_datato_frags(sk,skb, getfrag, from,
+			       (length - transhdrlen));
+	if (!err) {
+		/* specify the length of each IP datagram fragment*/
+		skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen);
+		__skb_queue_tail(&sk->sk_write_queue, skb);
+
+		return 0;
+	}
+	/* There is not enough support do UFO ,
+	 * so follow normal path
+	 */
+	kfree_skb(skb);
+	return err;
+}
+
 /*
  *	ip_append_data() and ip_append_page() can make one large IP datagram
  *	from many pieces of data. Each pieces will be holded on the socket
@@ -777,6 +832,15 @@ int ip_append_data(struct sock *sk,
 		csummode = CHECKSUM_HW;
 
 	inet->cork.length += length;
+	if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) &&
+			(rt->u.dst.dev->features & NETIF_F_UFO)) {
+
+		if(ip_ufo_append_data(sk, getfrag, from, length, hh_len,
+			       fragheaderlen, transhdrlen, mtu, flags))
+			goto error;
+
+		return 0;
+	}
 
 	/* So, what's going on in the loop below?
 	 *
@@ -1008,14 +1072,23 @@ ssize_t	ip_append_page(struct sock *sk, 
 		return -EINVAL;
 
 	inet->cork.length += size;
+	if ((sk->sk_protocol == IPPROTO_UDP) &&
+	    (rt->u.dst.dev->features & NETIF_F_UFO))
+		skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen);
+
 
 	while (size > 0) {
 		int i;
 
-		/* Check if the remaining data fits into current packet. */
-		len = mtu - skb->len;
-		if (len < size)
-			len = maxfraglen - skb->len;
+		if (skb_shinfo(skb)->ufo_size)
+			len = size;
+		else {
+
+			/* Check if the remaining data fits into current packet. */
+			len = mtu - skb->len;
+			if (len < size)
+				len = maxfraglen - skb->len;
+		}
 		if (len <= 0) {
 			struct sk_buff *skb_prev;
 			char *data;
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 563b442..614296a 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -147,7 +147,8 @@ static int ip6_output2(struct sk_buff *s
 
 int ip6_output(struct sk_buff *skb)
 {
-	if (skb->len > dst_mtu(skb->dst) || dst_allfrag(skb->dst))
+	if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->ufo_size) ||
+				dst_allfrag(skb->dst))
 		return ip6_fragment(skb, ip6_output2);
 	else
 		return ip6_output2(skb);
@@ -768,6 +769,65 @@ out_err_release:
 	*dst = NULL;
 	return err;
 }
+inline int ip6_ufo_append_data(struct sock *sk,
+			int getfrag(void *from, char *to, int offset, int len,
+			int odd, struct sk_buff *skb),
+			void *from, int length, int hh_len, int fragheaderlen,
+			int transhdrlen, int mtu,unsigned int flags)
+
+{
+	struct sk_buff *skb;
+	int err;
+
+	/* There is support for UDP large send offload by network
+	 * device, so create one single skb packet containing complete
+	 * udp datagram
+	 */
+	if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) {
+		skb = sock_alloc_send_skb(sk,
+			hh_len + fragheaderlen + transhdrlen + 20,
+			(flags & MSG_DONTWAIT), &err);
+		if (skb == NULL)
+			return -ENOMEM;
+
+		/* reserve space for Hardware header */
+		skb_reserve(skb, hh_len);
+
+		/* create space for UDP/IP header */
+		skb_put(skb,fragheaderlen + transhdrlen);
+
+		/* initialize network header pointer */
+		skb->nh.raw = skb->data;
+
+		/* initialize protocol header pointer */
+		skb->h.raw = skb->data + fragheaderlen;
+
+		skb->ip_summed = CHECKSUM_HW;
+		skb->csum = 0;
+		sk->sk_sndmsg_off = 0;
+	}
+
+	err = skb_append_datato_frags(sk,skb, getfrag, from,
+				      (length - transhdrlen));
+	if (!err) {
+		struct frag_hdr fhdr;
+
+		/* specify the length of each IP datagram fragment*/
+		skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen) - 
+						sizeof(struct frag_hdr);
+		ipv6_select_ident(skb, &fhdr);
+		skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
+		__skb_queue_tail(&sk->sk_write_queue, skb);
+
+		return 0;
+	}
+	/* There is not enough support do UPD LSO,
+	 * so follow normal path
+	 */
+	kfree_skb(skb);
+
+	return err;
+}
 
 int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
 	int offset, int len, int odd, struct sk_buff *skb),
@@ -860,6 +920,15 @@ int ip6_append_data(struct sock *sk, int
 	 */
 
 	inet->cork.length += length;
+	if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) &&
+	    (rt->u.dst.dev->features & NETIF_F_UFO)) {
+
+		if(ip6_ufo_append_data(sk, getfrag, from, length, hh_len,
+				fragheaderlen, transhdrlen, mtu, flags))
+			goto error;
+
+		return 0;
+	}
 
 	if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL)
 		goto alloc_new_skb;
---
0.99.8.GIT


--- NEW FILE 1027-MCAST-IPv6-Fix-algorithm-to-compute-Querier-s-Query-Interval.txt ---
Subject: [PATCH] [MCAST] IPv6: Fix algorithm to compute Querier's Query Interval
From: Yan Zheng <yanzheng 21cn com>
Date: 1130515352 +0800

5.1.3.  Maximum Response Code

   The Maximum Response Code field specifies the maximum time allowed
   before sending a responding Report.  The actual time allowed, called
   the Maximum Response Delay, is represented in units of milliseconds,
   and is derived from the Maximum Response Code as follows:

   If Maximum Response Code < 32768,
      Maximum Response Delay = Maximum Response Code

   If Maximum Response Code >=32768, Maximum Response Code represents a
   floating-point value as follows:

       0 1 2 3 4 5 6 7 8 9 A B C D E F
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |1| exp |          mant         |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

   Maximum Response Delay = (mant | 0x1000) << (exp+3)

5.1.9.  QQIC (Querier's Query Interval Code)

   The Querier's Query Interval Code field specifies the [Query
   Interval] used by the Querier.  The actual interval, called the
   Querier's Query Interval (QQI), is represented in units of seconds,
   and is derived from the Querier's Query Interval Code as follows:

   If QQIC < 128, QQI = QQIC

   If QQIC >= 128, QQIC represents a floating-point value as follows:

       0 1 2 3 4 5 6 7
      +-+-+-+-+-+-+-+-+
      |1| exp | mant  |
      +-+-+-+-+-+-+-+-+

   QQI = (mant | 0x10) << (exp + 3)

                                                -- rfc3810

#define MLDV2_QQIC(value) MLDV2_EXP(0x80, 4, 3, value)
#define MLDV2_MRC(value) MLDV2_EXP(0x8000, 12, 3, value)

Above macro are defined in mcast.c. but 1 << 4 == 0x10 and 1 << 12 == 0x1000.
So the result computed by original Macro is larger.

Signed-off-by: Yan Zheng <yanzheng 21cn com>
Acked-by: David L Stevens <dlstevens us ibm com>
Signed-off-by: Arnaldo Carvalho de Melo <acme mandriva com>

---

 net/ipv6/mcast.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

applies-to: aae6a825f351ce931fcd30f1a865ebe65227c4b8
f12baeab9d65e2fe1b43b09b666f5efcb81b9369
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 39a96c7..c4f2a0e 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -164,7 +164,7 @@ static int ip6_mc_leave_src(struct sock 
 #define MLDV2_MASK(value, nb) ((nb)>=32 ? (value) : ((1<<(nb))-1) & (value))
 #define MLDV2_EXP(thresh, nbmant, nbexp, value) \
 	((value) < (thresh) ? (value) : \
-	((MLDV2_MASK(value, nbmant) | (1<<(nbmant+nbexp))) << \
+	((MLDV2_MASK(value, nbmant) | (1<<(nbmant))) << \
 	(MLDV2_MASK((value) >> (nbmant), nbexp) + (nbexp))))
 
 #define MLDV2_QQIC(value) MLDV2_EXP(0x80, 4, 3, value)
---
0.99.8.GIT


--- NEW FILE 1058-New-PowerPC-4xx-on-chip-ethernet-controller-driver.txt ---
Subject: [PATCH] New PowerPC 4xx on-chip ethernet controller driver
From: Eugene Surovegin <ebs ebshome net>
Date: 1128988694 -0700

This patch replaces current PowerPC 4xx EMAC driver with
new, re-written from the scratch version. This patch is quite big
(~234K) because there is virtualy 0% of common code between old and
new version.

New driver uses NAPI, it solves stability problems under heavy packet
load and low memory, corrects chip register access and fixes numerous
small bugs I don't even remember now.

This patch has been tested on all supported in 2.6 PPC 4xx boards.
It's been used in production for almost a year now on custom
4xx hardware. PPC32 specific parts are already upstream.

Patch was acked by the current EMAC driver maintainer (Matt Porter). I
will be maintaining this new version.

Signed-off-by: Eugene Surovegin <ebs ebshome net>
--

 Kconfig                   |   72
 ibm_emac/Makefile         |   13
 ibm_emac/ibm_emac.h       |  418 +++--
 ibm_emac/ibm_emac_core.c  | 3414 ++++++++++++++++++++++++----------------------
 ibm_emac/ibm_emac_core.h  |  313 ++--
 ibm_emac/ibm_emac_debug.c |  377 ++---
 ibm_emac/ibm_emac_debug.h |   63
 ibm_emac/ibm_emac_mal.c   |  674 +++++----
 ibm_emac/ibm_emac_mal.h   |  336 +++-
 ibm_emac/ibm_emac_phy.c   |  335 ++--
 ibm_emac/ibm_emac_phy.h   |  105 -
 ibm_emac/ibm_emac_rgmii.c |  201 ++
 ibm_emac/ibm_emac_rgmii.h |   68
 ibm_emac/ibm_emac_tah.c   |  111 +
 ibm_emac/ibm_emac_tah.h   |   96 -
 ibm_emac/ibm_emac_zmii.c  |  255 +++
 ibm_emac/ibm_emac_zmii.h  |  114 -
 17 files changed, 4114 insertions(+), 2851 deletions(-)
Signed-off-by: Jeff Garzik <jgarzik pobox com>

---

 drivers/net/Kconfig                   |   72 +
 drivers/net/ibm_emac/Makefile         |   13 
 drivers/net/ibm_emac/ibm_emac.h       |  418 ++--
 drivers/net/ibm_emac/ibm_emac_core.c  | 3414 +++++++++++++++++----------------
 drivers/net/ibm_emac/ibm_emac_core.h  |  313 ++-
 drivers/net/ibm_emac/ibm_emac_debug.c |  377 ++--
 drivers/net/ibm_emac/ibm_emac_debug.h |   63 +
 drivers/net/ibm_emac/ibm_emac_mal.c   |  674 ++++---
 drivers/net/ibm_emac/ibm_emac_mal.h   |  336 ++-
 drivers/net/ibm_emac/ibm_emac_phy.c   |  335 ++-
 drivers/net/ibm_emac/ibm_emac_phy.h   |  105 -
 drivers/net/ibm_emac/ibm_emac_rgmii.c |  201 ++
 drivers/net/ibm_emac/ibm_emac_rgmii.h |   68 -
 drivers/net/ibm_emac/ibm_emac_tah.c   |  111 +
 drivers/net/ibm_emac/ibm_emac_tah.h   |   96 +
 drivers/net/ibm_emac/ibm_emac_zmii.c  |  255 ++
 drivers/net/ibm_emac/ibm_emac_zmii.h  |  114 +
 17 files changed, 4114 insertions(+), 2851 deletions(-)
 create mode 100644 drivers/net/ibm_emac/ibm_emac_debug.h
 create mode 100644 drivers/net/ibm_emac/ibm_emac_rgmii.c
 create mode 100644 drivers/net/ibm_emac/ibm_emac_tah.c
 create mode 100644 drivers/net/ibm_emac/ibm_emac_zmii.c

applies-to: e6b22bf428cc83cd54f10e9ea6551c4cea09fdb8
37448f7d39717db7c1098c1a88b9074694c69797
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 27732fd..54ab70e 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1163,38 +1163,74 @@ config IBMVETH
 	  be called ibmveth.
 
 config IBM_EMAC
-	bool "IBM PPC4xx EMAC driver support"
+	tristate "PowerPC 4xx on-chip Ethernet support"
 	depends on 4xx
-	select CRC32
-	---help---
-	  This driver supports the IBM PPC4xx EMAC family of on-chip
-	  Ethernet controllers.
-
-config IBM_EMAC_ERRMSG
-	bool "Verbose error messages"
-	depends on IBM_EMAC && BROKEN
+	help
+	  This driver supports the PowerPC 4xx EMAC family of on-chip
+          Ethernet controllers.
 
 config IBM_EMAC_RXB
 	int "Number of receive buffers"
 	depends on IBM_EMAC
-	default "128" if IBM_EMAC4
-	default "64"
+	default "128"
 
 config IBM_EMAC_TXB
 	int "Number of transmit buffers"
 	depends on IBM_EMAC
-	default "128" if IBM_EMAC4
-	default "8"
+	default "64"
+
+config IBM_EMAC_POLL_WEIGHT
+	int "MAL NAPI polling weight"
+	depends on IBM_EMAC
+	default "32"
 
-config IBM_EMAC_FGAP
-	int "Frame gap"
+config IBM_EMAC_RX_COPY_THRESHOLD
+	int "RX skb copy threshold (bytes)"
 	depends on IBM_EMAC
-	default "8"
+	default "256"
 
-config IBM_EMAC_SKBRES
-	int "Skb reserve amount"
+config IBM_EMAC_RX_SKB_HEADROOM
+	int "Additional RX skb headroom (bytes)"
 	depends on IBM_EMAC
 	default "0"
+	help
+	  Additional receive skb headroom. Note, that driver
+	  will always reserve at least 2 bytes to make IP header
+	  aligned, so usualy there is no need to add any additional
+	  headroom.
+	  
+	  If unsure, set to 0.
+
+config IBM_EMAC_PHY_RX_CLK_FIX
+	bool "PHY Rx clock workaround"
+	depends on IBM_EMAC && (405EP || 440GX || 440EP)
+	help
+	  Enable this if EMAC attached to a PHY which doesn't generate
+	  RX clock if there is no link, if this is the case, you will 
+	  see "TX disable timeout" or "RX disable timeout" in the system
+	  log.
+	  
+	  If unsure, say N.
+
+config IBM_EMAC_DEBUG
+	bool "Debugging"
+	depends on IBM_EMAC
+	default n
+
+config IBM_EMAC_ZMII
+	bool
+	depends on IBM_EMAC && (NP405H || NP405L || 44x)
+	default y
+
+config IBM_EMAC_RGMII
+	bool
+	depends on IBM_EMAC && 440GX
+	default y
+		
+config IBM_EMAC_TAH
+	bool
+	depends on IBM_EMAC && 440GX
+	default y
 
 config NET_PCI
 	bool "EISA, VLB, PCI and on board controllers"
diff --git a/drivers/net/ibm_emac/Makefile b/drivers/net/ibm_emac/Makefile
index 7f583a3..f98ddf0 100644
--- a/drivers/net/ibm_emac/Makefile
+++ b/drivers/net/ibm_emac/Makefile
@@ -1,12 +1,11 @@
 #
-# Makefile for the IBM PPC4xx EMAC controllers
+# Makefile for the PowerPC 4xx on-chip ethernet driver
 #
 
 obj-$(CONFIG_IBM_EMAC) += ibm_emac.o
 
-ibm_emac-objs := ibm_emac_mal.o ibm_emac_core.o ibm_emac_phy.o
-
-# Only need this if you want to see additional debug messages
-ifeq ($(CONFIG_IBM_EMAC_ERRMSG), y)
-ibm_emac-objs += ibm_emac_debug.o
-endif
+ibm_emac-objs := ibm_emac_mal.o ibm_emac_core.o ibm_emac_phy.o 
+ibm_emac-$(CONFIG_IBM_EMAC_ZMII) += ibm_emac_zmii.o
+ibm_emac-$(CONFIG_IBM_EMAC_RGMII) += ibm_emac_rgmii.o
+ibm_emac-$(CONFIG_IBM_EMAC_TAH) += ibm_emac_tah.o
+ibm_emac-$(CONFIG_IBM_EMAC_DEBUG) += ibm_emac_debug.o
diff --git a/drivers/net/ibm_emac/ibm_emac.h b/drivers/net/ibm_emac/ibm_emac.h
index 15d5a0e..28c476f 100644
--- a/drivers/net/ibm_emac/ibm_emac.h
+++ b/drivers/net/ibm_emac/ibm_emac.h
@@ -1,110 +1,142 @@
 /*
- * ibm_emac.h
+ * drivers/net/ibm_emac/ibm_emac.h
  *
[...7788 lines suppressed...]
+	struct ibm_ocp_zmii *dev = ocp_get_drvdata(ocpdev);
+	u32 ssr = in_be32(&dev->base->ssr);
+
+	ZMII_DBG("%d: speed(%d, %d)" NL, ocpdev->def->index, input, speed);
+
+	if (speed == SPEED_100)
+		ssr |= ZMII_SSR_SP(input);
+	else
+		ssr &= ~ZMII_SSR_SP(input);
+
+	out_be32(&dev->base->ssr, ssr);
+}
+
+void __exit __zmii_fini(struct ocp_device *ocpdev, int input)
+{
+	struct ibm_ocp_zmii *dev = ocp_get_drvdata(ocpdev);
+	BUG_ON(!dev || dev->users == 0);
+
+	ZMII_DBG("%d: fini(%d)" NL, ocpdev->def->index, input);
+
+	/* Disable this input */
+	out_be32(&dev->base->fer,
+		 in_be32(&dev->base->fer) & ~zmii_mode_mask(dev->mode, input));
+
+	if (!--dev->users) {
+		/* Free everything if this is the last user */
+		ocp_set_drvdata(ocpdev, NULL);
+		iounmap((void *)dev->base);
+		kfree(dev);
+	}
+}
+
+int __zmii_get_regs_len(struct ocp_device *ocpdev)
+{
+	return sizeof(struct emac_ethtool_regs_subhdr) +
+	    sizeof(struct zmii_regs);
+}
+
+void *zmii_dump_regs(struct ocp_device *ocpdev, void *buf)
+{
+	struct ibm_ocp_zmii *dev = ocp_get_drvdata(ocpdev);
+	struct emac_ethtool_regs_subhdr *hdr = buf;
+	struct zmii_regs *regs = (struct zmii_regs *)(hdr + 1);
+
+	hdr->version = 0;
+	hdr->index = ocpdev->def->index;
+	memcpy_fromio(regs, dev->base, sizeof(struct zmii_regs));
+	return regs + 1;
+}
diff --git a/drivers/net/ibm_emac/ibm_emac_zmii.h b/drivers/net/ibm_emac/ibm_emac_zmii.h
index 6f6cd2a..0bb2606 100644
--- a/drivers/net/ibm_emac/ibm_emac_zmii.h
+++ b/drivers/net/ibm_emac/ibm_emac_zmii.h
@@ -1,23 +1,27 @@
 /*
- * ocp_zmii.h
+ * drivers/net/ibm_emac/ibm_emac_zmii.h
  *
- * Defines for the IBM ZMII bridge
+ * Driver for PowerPC 4xx on-chip ethernet controller, ZMII bridge support.
  *
- *      Armin Kuster akuster mvista com
- *      Dec, 2001
+ * Copyright (c) 2004, 2005 Zultys Technologies.
+ * Eugene Surovegin <eugene surovegin zultys com> or <ebs ebshome net>
  *
- * Copyright 2001 MontaVista Softare Inc.
+ * Based on original work by
+ *      Armin Kuster <akuster mvista com>
+ * 	Copyright 2001 MontaVista Softare Inc.
  *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
+ *
  */
-
 #ifndef _IBM_EMAC_ZMII_H_
 #define _IBM_EMAC_ZMII_H_
 
 #include <linux/config.h>
+#include <linux/init.h>
+#include <asm/ocp.h>
 
 /* ZMII bridge registers */
 struct zmii_regs {
@@ -26,68 +30,54 @@ struct zmii_regs {
 	u32 smiirs;		/* SMII status reg */
 };
 
-#define ZMII_INPUTS	4
-
 /* ZMII device */
 struct ibm_ocp_zmii {
 	struct zmii_regs *base;
-	int mode[ZMII_INPUTS];
+	int mode;		/* subset of PHY_MODE_XXXX */
 	int users;		/* number of EMACs using this ZMII bridge */
+	u32 fer_save;		/* FER value left by firmware */
 };
 
-/* Fuctional Enable Reg */
-
-#define ZMII_FER_MASK(x)	(0xf0000000 >> (4*x))
+#ifdef CONFIG_IBM_EMAC_ZMII
+int zmii_attach(void *emac) __init;
 
-#define ZMII_MDI0	0x80000000
-#define ZMII_SMII0	0x40000000
-#define ZMII_RMII0	0x20000000
-#define ZMII_MII0	0x10000000
-#define ZMII_MDI1	0x08000000
-#define ZMII_SMII1	0x04000000
-#define ZMII_RMII1	0x02000000
-#define ZMII_MII1	0x01000000
-#define ZMII_MDI2	0x00800000
-#define ZMII_SMII2	0x00400000
-#define ZMII_RMII2	0x00200000
-#define ZMII_MII2	0x00100000
-#define ZMII_MDI3	0x00080000
-#define ZMII_SMII3	0x00040000
-#define ZMII_RMII3	0x00020000
-#define ZMII_MII3	0x00010000
-
-/* Speed Selection reg */
-
-#define ZMII_SCI0	0x40000000
-#define ZMII_FSS0	0x20000000
-#define ZMII_SP0	0x10000000
-#define ZMII_SCI1	0x04000000
-#define ZMII_FSS1	0x02000000
-#define ZMII_SP1	0x01000000
-#define ZMII_SCI2	0x00400000
-#define ZMII_FSS2	0x00200000
-#define ZMII_SP2	0x00100000
-#define ZMII_SCI3	0x00040000
-#define ZMII_FSS3	0x00020000
-#define ZMII_SP3	0x00010000
-
-#define ZMII_MII0_100MB	ZMII_SP0
-#define ZMII_MII0_10MB	~ZMII_SP0
-#define ZMII_MII1_100MB	ZMII_SP1
-#define ZMII_MII1_10MB	~ZMII_SP1
-#define ZMII_MII2_100MB	ZMII_SP2
-#define ZMII_MII2_10MB	~ZMII_SP2
-#define ZMII_MII3_100MB	ZMII_SP3
-#define ZMII_MII3_10MB	~ZMII_SP3
-
-/* SMII Status reg */
-
-#define ZMII_STS0 0xFF000000	/* EMAC0 smii status mask */
-#define ZMII_STS1 0x00FF0000	/* EMAC1 smii status mask */
-
-#define SMII	0
-#define RMII	1
-#define MII	2
-#define MDI	3
+void __zmii_fini(struct ocp_device *ocpdev, int input) __exit;
+static inline void zmii_fini(struct ocp_device *ocpdev, int input)
+{
+	if (ocpdev)
+		__zmii_fini(ocpdev, input);
+}
+
+void __zmii_enable_mdio(struct ocp_device *ocpdev, int input);
+static inline void zmii_enable_mdio(struct ocp_device *ocpdev, int input)
+{
+	if (ocpdev)
+		__zmii_enable_mdio(ocpdev, input);
+}
+
+void __zmii_set_speed(struct ocp_device *ocpdev, int input, int speed);
+static inline void zmii_set_speed(struct ocp_device *ocpdev, int input,
+				  int speed)
+{
+	if (ocpdev)
+		__zmii_set_speed(ocpdev, input, speed);
+}
+
+int __zmii_get_regs_len(struct ocp_device *ocpdev);
+static inline int zmii_get_regs_len(struct ocp_device *ocpdev)
+{
+	return ocpdev ? __zmii_get_regs_len(ocpdev) : 0;
+}
+
+void *zmii_dump_regs(struct ocp_device *ocpdev, void *buf);
+
+#else
+# define zmii_attach(x)		0
+# define zmii_fini(x,y)		((void)0)
+# define zmii_enable_mdio(x,y)	((void)0)
+# define zmii_set_speed(x,y,z)	((void)0)
+# define zmii_get_regs_len(x)	0
+# define zmii_dump_regs(x,buf)	(buf)
+#endif				/* !CONFIG_IBM_EMAC_ZMII */
 
 #endif				/* _IBM_EMAC_ZMII_H_ */
---
0.99.8.GIT


Index: 1062-drivers-net-Remove-pointless-checks-for-NULL-prior-to-calling-kfree.txt
===================================================================
RCS file: 1062-drivers-net-Remove-pointless-checks-for-NULL-prior-to-calling-kfree.txt
diff -N 1062-drivers-net-Remove-pointless-checks-for-NULL-prior-to-calling-kfree.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 1062-drivers-net-Remove-pointless-checks-for-NULL-prior-to-calling-kfree.txt	11 Nov 2005 18:29:01 -0000	1.1.2.3
@@ -0,0 +1,767 @@
+Subject: [PATCH] drivers/net: Remove pointless checks for NULL prior to calling kfree()
+From: Jesper Juhl <jesper juhl gmail com>
+Date: 1130532793 -0400
+
+---
+
+ drivers/net/acenic.c                       |    6 +---
+ drivers/net/au1000_eth.c                   |    6 +---
+ drivers/net/b44.c                          |   12 ++-----
+ drivers/net/bmac.c                         |    6 +---
+ drivers/net/bnx2.c                         |   12 ++-----
+ drivers/net/e1000/e1000_ethtool.c          |    7 +---
+ drivers/net/hamradio/mkiss.c               |    6 +---
+ drivers/net/ibmveth.c                      |    6 +---
+ drivers/net/irda/donauboe.c                |    6 +---
+ drivers/net/irda/irda-usb.c                |    6 +---
+ drivers/net/irda/irport.c                  |    3 +-
+ drivers/net/irda/sir_dev.c                 |    3 +-
+ drivers/net/irda/vlsi_ir.c                 |    3 +-
+ drivers/net/mace.c                         |    6 +---
+ drivers/net/ni65.c                         |    9 ++---
+ drivers/net/rrunner.c                      |    6 +---
+ drivers/net/s2io.c                         |    3 +-
+ drivers/net/saa9730.c                      |    8 +----
+ drivers/net/tg3.c                          |    6 +---
+ drivers/net/tulip/de2104x.c                |    6 +---
+ drivers/net/tulip/tulip_core.c             |    6 +---
+ drivers/net/via-velocity.c                 |    6 +---
+ drivers/net/wireless/airo.c                |   48 +++++++++++-----------------
+ drivers/net/wireless/airo_cs.c             |    4 +-
+ drivers/net/wireless/atmel.c               |    6 +---
+ drivers/net/wireless/atmel_cs.c            |    3 +-
+ drivers/net/wireless/hostap/hostap_ioctl.c |    9 +----
+ drivers/net/wireless/prism54/islpci_dev.c  |    3 +-
+ drivers/net/wireless/prism54/oid_mgt.c     |    9 ++---
+ drivers/net/wireless/strip.c               |   38 ++++++++--------------
+ include/net/ax25.h                         |    3 +-
+ include/net/netrom.h                       |    3 +-
+ 32 files changed, 90 insertions(+), 174 deletions(-)
+
+applies-to: fb64f857892546a441b27af54921e1669aa30610
+b4558ea93d66a43f7990d26f145fd4c54a01c9bf
+diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
+index dbecc6b..b8953de 100644
+--- a/drivers/net/acenic.c
++++ b/drivers/net/acenic.c
+@@ -871,10 +871,8 @@ static void ace_init_cleanup(struct net_
+ 	if (ap->info)
+ 		pci_free_consistent(ap->pdev, sizeof(struct ace_info),
+ 				    ap->info, ap->info_dma);
+-	if (ap->skb)
+-		kfree(ap->skb);
+-	if (ap->trace_buf)
+-		kfree(ap->trace_buf);
++	kfree(ap->skb);
++	kfree(ap->trace_buf);
+ 
+ 	if (dev->irq)
+ 		free_irq(dev->irq, dev);
+diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
+index 7850691..332e995 100644
+--- a/drivers/net/au1000_eth.c
++++ b/drivers/net/au1000_eth.c
+@@ -1606,8 +1606,7 @@ err_out:
+ 	/* here we should have a valid dev plus aup-> register addresses
+ 	 * so we can reset the mac properly.*/
+ 	reset_mac(dev);
+-	if (aup->mii)
+-		kfree(aup->mii);
++	kfree(aup->mii);
+ 	for (i = 0; i < NUM_RX_DMA; i++) {
+ 		if (aup->rx_db_inuse[i])
+ 			ReleaseDB(aup, aup->rx_db_inuse[i]);
+@@ -1806,8 +1805,7 @@ static void __exit au1000_cleanup_module
+ 		if (dev) {
+ 			aup = (struct au1000_private *) dev->priv;
+ 			unregister_netdev(dev);
+-			if (aup->mii)
+-				kfree(aup->mii);
++			kfree(aup->mii);
+ 			for (j = 0; j < NUM_RX_DMA; j++) {
+ 				if (aup->rx_db_inuse[j])
+ 					ReleaseDB(aup, aup->rx_db_inuse[j]);
+diff --git a/drivers/net/b44.c b/drivers/net/b44.c
+index ab84507..5485e3b 100644
+--- a/drivers/net/b44.c
++++ b/drivers/net/b44.c
+@@ -1131,14 +1131,10 @@ static void b44_init_rings(struct b44 *b
+  */
+ static void b44_free_consistent(struct b44 *bp)
+ {
+-	if (bp->rx_buffers) {
+-		kfree(bp->rx_buffers);
+-		bp->rx_buffers = NULL;
+-	}
+-	if (bp->tx_buffers) {
+-		kfree(bp->tx_buffers);
+-		bp->tx_buffers = NULL;
+-	}
++	kfree(bp->rx_buffers);
++	bp->rx_buffers = NULL;
++	kfree(bp->tx_buffers);
++	bp->tx_buffers = NULL;
+ 	if (bp->rx_ring) {
+ 		if (bp->flags & B44_FLAG_RX_RING_HACK) {
+ 			dma_unmap_single(&bp->pdev->dev, bp->rx_ring_dma,
+diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c
+index 60dba4a..73f2fcf 100644
+--- a/drivers/net/bmac.c
++++ b/drivers/net/bmac.c
+@@ -1689,10 +1689,8 @@ static void __exit bmac_exit(void)
+ {
+ 	macio_unregister_driver(&bmac_driver);
+ 
+-	if (bmac_emergency_rxbuf != NULL) {
+-		kfree(bmac_emergency_rxbuf);
+-		bmac_emergency_rxbuf = NULL;
+-	}
++	kfree(bmac_emergency_rxbuf);
++	bmac_emergency_rxbuf = NULL;
+ }
+ 
+ MODULE_AUTHOR("Randy Gobbel/Paul Mackerras");
+diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
+index 3a2ace0..11d2523 100644
+--- a/drivers/net/bnx2.c
++++ b/drivers/net/bnx2.c
+@@ -314,20 +314,16 @@ bnx2_free_mem(struct bnx2 *bp)
+ 				    bp->tx_desc_ring, bp->tx_desc_mapping);
+ 		bp->tx_desc_ring = NULL;
+ 	}
+-	if (bp->tx_buf_ring) {
+-		kfree(bp->tx_buf_ring);
+-		bp->tx_buf_ring = NULL;
+-	}
++	kfree(bp->tx_buf_ring);
++	bp->tx_buf_ring = NULL;
+ 	if (bp->rx_desc_ring) {
+ 		pci_free_consistent(bp->pdev,
+ 				    sizeof(struct rx_bd) * RX_DESC_CNT,
+ 				    bp->rx_desc_ring, bp->rx_desc_mapping);
+ 		bp->rx_desc_ring = NULL;
+ 	}
+-	if (bp->rx_buf_ring) {
+-		kfree(bp->rx_buf_ring);
+-		bp->rx_buf_ring = NULL;
+-	}
++	kfree(bp->rx_buf_ring);
++	bp->rx_buf_ring = NULL;
+ }
+ 
+ static int
+diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
+index 6b9acc7..9c7feae 100644
+--- a/drivers/net/e1000/e1000_ethtool.c
++++ b/drivers/net/e1000/e1000_ethtool.c
+@@ -965,11 +965,8 @@ e1000_free_desc_rings(struct e1000_adapt
+ 	if(rxdr->desc)
+ 		pci_free_consistent(pdev, rxdr->size, rxdr->desc, rxdr->dma);
+ 
+-	if(txdr->buffer_info)
+-		kfree(txdr->buffer_info);
+-	if(rxdr->buffer_info)
+-		kfree(rxdr->buffer_info);
+-
++	kfree(txdr->buffer_info);
++	kfree(rxdr->buffer_info);
+ 	return;
+ }
+ 
+diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
+index 85d6dc0..3e9accf 100644
+--- a/drivers/net/hamradio/mkiss.c
++++ b/drivers/net/hamradio/mkiss.c
+@@ -390,10 +390,8 @@ static void ax_changedmtu(struct mkiss *
+ 		       "MTU change cancelled.\n",
+ 		       ax->dev->name);
+ 		dev->mtu = ax->mtu;
+-		if (xbuff != NULL)
+-			kfree(xbuff);
+-		if (rbuff != NULL)
+-			kfree(rbuff);
++		kfree(xbuff);
++		kfree(rbuff);
+ 		return;
+ 	}
+ 
+diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
+index f581952..36da54a 100644
+--- a/drivers/net/ibmveth.c
++++ b/drivers/net/ibmveth.c
+@@ -276,10 +276,8 @@ static void ibmveth_free_buffer_pool(str
+ {
+ 	int i;
+ 
+-	if(pool->free_map) {
+-		kfree(pool->free_map);
+-		pool->free_map  = NULL;
+-	}
++	kfree(pool->free_map);
++	pool->free_map = NULL;
+ 
+ 	if(pool->skbuff && pool->dma_addr) {
+ 		for(i = 0; i < pool->size; ++i) {
+diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c
+index 0a08c53..0282771 100644
+--- a/drivers/net/irda/donauboe.c
++++ b/drivers/net/irda/donauboe.c
+@@ -1695,11 +1695,9 @@ toshoboe_open (struct pci_dev *pci_dev, 
+ 
+ freebufs:
+   for (i = 0; i < TX_SLOTS; ++i)
+-    if (self->tx_bufs[i])
+-      kfree (self->tx_bufs[i]);
++    kfree (self->tx_bufs[i]);
+   for (i = 0; i < RX_SLOTS; ++i)
+-    if (self->rx_bufs[i])
+-      kfree (self->rx_bufs[i]);
++    kfree (self->rx_bufs[i]);
+   kfree(self->ringbuf);
+ 
+ freeregion:
+diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
+index 6c766fd..c22c051 100644
+--- a/drivers/net/irda/irda-usb.c
++++ b/drivers/net/irda/irda-usb.c
+@@ -1168,10 +1168,8 @@ static inline void irda_usb_close(struct
+ 	unregister_netdev(self->netdev);
+ 
+ 	/* Remove the speed buffer */
+-	if (self->speed_buff != NULL) {
+-		kfree(self->speed_buff);
+-		self->speed_buff = NULL;
+-	}
++	kfree(self->speed_buff);
++	self->speed_buff = NULL;
+ }
+ 
+ /********************** USB CONFIG SUBROUTINES **********************/
+diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c
+index 5971315..3d016a4 100644
+--- a/drivers/net/irda/irport.c
++++ b/drivers/net/irda/irport.c
+@@ -235,8 +235,7 @@ static int irport_close(struct irport_cb
+ 		   __FUNCTION__, self->io.sir_base);
+ 	release_region(self->io.sir_base, self->io.sir_ext);
+ 
+-	if (self->tx_buff.head)
+-		kfree(self->tx_buff.head);
++	kfree(self->tx_buff.head);
+ 	
+ 	if (self->rx_buff.skb)
+ 		kfree_skb(self->rx_buff.skb);
+diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c
+index efc5a88..df22b8b 100644
+--- a/drivers/net/irda/sir_dev.c
++++ b/drivers/net/irda/sir_dev.c
+@@ -490,8 +490,7 @@ static void sirdev_free_buffers(struct s
+ {
+ 	if (dev->rx_buff.skb)
+ 		kfree_skb(dev->rx_buff.skb);
+-	if (dev->tx_buff.head)
+-		kfree(dev->tx_buff.head);
++	kfree(dev->tx_buff.head);
+ 	dev->rx_buff.head = dev->tx_buff.head = NULL;
+ 	dev->rx_buff.skb = NULL;
+ }
+diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
+index 651c5a6..a9f49f0 100644
+--- a/drivers/net/irda/vlsi_ir.c
++++ b/drivers/net/irda/vlsi_ir.c
+@@ -473,8 +473,7 @@ static int vlsi_free_ring(struct vlsi_ri
+ 		rd_set_addr_status(rd, 0, 0);
+ 		if (busaddr)
+ 			pci_unmap_single(r->pdev, busaddr, r->len, r->dir);
+-		if (rd->buf)
+-			kfree(rd->buf);
++		kfree(rd->buf);
+ 	}
+ 	kfree(r);
+ 	return 0;
+diff --git a/drivers/net/mace.c b/drivers/net/mace.c
+index 81d0a26..09b1e7b 100644
+--- a/drivers/net/mace.c
++++ b/drivers/net/mace.c
+@@ -1035,10 +1035,8 @@ static void __exit mace_cleanup(void)
+ {
+ 	macio_unregister_driver(&mace_driver);
+ 
+-	if (dummy_buf) {
+-		kfree(dummy_buf);
+-		dummy_buf = NULL;
+-	}
++	kfree(dummy_buf);
++	dummy_buf = NULL;
+ }
+ 
+ MODULE_AUTHOR("Paul Mackerras");
+diff --git a/drivers/net/ni65.c b/drivers/net/ni65.c
+index 925d1df..bb42ff2 100644
+--- a/drivers/net/ni65.c
++++ b/drivers/net/ni65.c
+@@ -696,8 +696,7 @@ static void ni65_free_buffer(struct priv
+ 		return;
+ 
+ 	for(i=0;i<TMDNUM;i++) {
+-		if(p->tmdbounce[i])
+-			kfree(p->tmdbounce[i]);
++		kfree(p->tmdbounce[i]);
+ #ifdef XMT_VIA_SKB
+ 		if(p->tmd_skb[i])
+ 			dev_kfree_skb(p->tmd_skb[i]);
+@@ -710,12 +709,10 @@ static void ni65_free_buffer(struct priv
+ 		if(p->recv_skb[i])
+ 			dev_kfree_skb(p->recv_skb[i]);
+ #else
+-		if(p->recvbounce[i])
+-			kfree(p->recvbounce[i]);
++		kfree(p->recvbounce[i]);
+ #endif
+ 	}
+-	if(p->self)
+-		kfree(p->self);
++	kfree(p->self);
+ }
+ 
+ 
+diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c
+index ec1a18d..19c2df9 100644
+--- a/drivers/net/rrunner.c
++++ b/drivers/net/rrunner.c
+@@ -1710,10 +1710,8 @@ static int rr_ioctl(struct net_device *d
+ 			error = -EFAULT;
+ 		}
+ 	wf_out:
+-		if (oldimage)
+-			kfree(oldimage);
+-		if (image)
+-			kfree(image);
++		kfree(oldimage);
++		kfree(image);
+ 		return error;
+ 		
+ 	case SIOCRRID:
+diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
+index d303d16..5ea8977 100644
+--- a/drivers/net/s2io.c
++++ b/drivers/net/s2io.c
+@@ -705,8 +705,7 @@ static void free_shared_mem(struct s2io_
+ 			}
+ 			kfree(mac_control->rings[i].ba[j]);
+ 		}
+-		if (mac_control->rings[i].ba)
+-			kfree(mac_control->rings[i].ba);
++		kfree(mac_control->rings[i].ba);
+ 	}
+ #endif
+ 
+diff --git a/drivers/net/saa9730.c b/drivers/net/saa9730.c
+index fd01670..110e777 100644
+--- a/drivers/net/saa9730.c
++++ b/drivers/net/saa9730.c
+@@ -997,10 +997,7 @@ static void __devexit saa9730_remove_one
+ 
+         if (dev) {
+                 unregister_netdev(dev);
+-
+-		if (dev->priv)
+-			kfree(dev->priv);
+-
++		kfree(dev->priv);
+                 free_netdev(dev);
+                 pci_release_regions(pdev);
+                 pci_disable_device(pdev);
+@@ -1096,8 +1093,7 @@ static int lan_saa9730_init(struct net_d
+ 	return 0;
+ 
+  out:
+-	if (dev->priv)
+-		kfree(dev->priv);
++	kfree(dev->priv);
+ 	return ret;
+ }
+ 
+diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
+index 551c944..b547233 100644
+--- a/drivers/net/tg3.c
++++ b/drivers/net/tg3.c
+@@ -3918,10 +3918,8 @@ static void tg3_init_rings(struct tg3 *t
+  */
+ static void tg3_free_consistent(struct tg3 *tp)
+ {
+-	if (tp->rx_std_buffers) {
+-		kfree(tp->rx_std_buffers);
+-		tp->rx_std_buffers = NULL;
+-	}
++	kfree(tp->rx_std_buffers);
++	tp->rx_std_buffers = NULL;
+ 	if (tp->rx_std) {
+ 		pci_free_consistent(tp->pdev, TG3_RX_RING_BYTES,
+ 				    tp->rx_std, tp->rx_std_mapping);
+diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
+index 6b8eee8..d7fb3ff 100644
+--- a/drivers/net/tulip/de2104x.c
++++ b/drivers/net/tulip/de2104x.c
+@@ -2076,8 +2076,7 @@ static int __init de_init_one (struct pc
+ 	return 0;
+ 
+ err_out_iomap:
+-	if (de->ee_data)
+-		kfree(de->ee_data);
++	kfree(de->ee_data);
+ 	iounmap(regs);
+ err_out_res:
+ 	pci_release_regions(pdev);
+@@ -2096,8 +2095,7 @@ static void __exit de_remove_one (struct
+ 	if (!dev)
+ 		BUG();
+ 	unregister_netdev(dev);
+-	if (de->ee_data)
+-		kfree(de->ee_data);
++	kfree(de->ee_data);
+ 	iounmap(de->regs);
+ 	pci_release_regions(pdev);
+ 	pci_disable_device(pdev);
+diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
+index 6266a9a..125ed00 100644
+--- a/drivers/net/tulip/tulip_core.c
++++ b/drivers/net/tulip/tulip_core.c
+@@ -1727,8 +1727,7 @@ err_out_free_ring:
+ 			     tp->rx_ring, tp->rx_ring_dma);
+ 
+ err_out_mtable:
+-	if (tp->mtable)
+-		kfree (tp->mtable);
++	kfree (tp->mtable);
+ 	pci_iounmap(pdev, ioaddr);
+ 
+ err_out_free_res:
+@@ -1806,8 +1805,7 @@ static void __devexit tulip_remove_one (
+ 			     sizeof (struct tulip_rx_desc) * RX_RING_SIZE +
+ 			     sizeof (struct tulip_tx_desc) * TX_RING_SIZE,
+ 			     tp->rx_ring, tp->rx_ring_dma);
+-	if (tp->mtable)
+-		kfree (tp->mtable);
++	kfree (tp->mtable);
+ 	pci_iounmap(pdev, tp->base_addr);
+ 	free_netdev (dev);
+ 	pci_release_regions (pdev);
+diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
+index abc5cee..a368d08 100644
+--- a/drivers/net/via-velocity.c
++++ b/drivers/net/via-velocity.c
+@@ -1212,10 +1212,8 @@ static void velocity_free_td_ring(struct
+ 			velocity_free_td_ring_entry(vptr, j, i);
+ 
+ 		}
+-		if (vptr->td_infos[j]) {
+-			kfree(vptr->td_infos[j]);
+-			vptr->td_infos[j] = NULL;
+-		}
++		kfree(vptr->td_infos[j]);
++		vptr->td_infos[j] = NULL;
+ 	}
+ }
+ 
+diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
+index cb429e7..4c11699 100644
+--- a/drivers/net/wireless/airo.c
++++ b/drivers/net/wireless/airo.c
+@@ -2381,14 +2381,10 @@ void stop_airo_card( struct net_device *
+ 			dev_kfree_skb(skb);
+ 	}
+ 
+-	if (ai->flash)
+-		kfree(ai->flash);
+-	if (ai->rssi)
+-		kfree(ai->rssi);
+-	if (ai->APList)
+-		kfree(ai->APList);
+-	if (ai->SSID)
+-		kfree(ai->SSID);
++	kfree(ai->flash);
++	kfree(ai->rssi);
++	kfree(ai->APList);
++	kfree(ai->SSID);
+ 	if (freeres) {
+ 		/* PCMCIA frees this stuff, so only for PCI and ISA */
+ 	        release_region( dev->base_addr, 64 );
+@@ -3626,10 +3622,8 @@ static u16 setup_card(struct airo_info *
+ 	int rc;
+ 
+ 	memset( &mySsid, 0, sizeof( mySsid ) );
+-	if (ai->flash) {
+-		kfree (ai->flash);
+-		ai->flash = NULL;
+-	}
++	kfree (ai->flash);
++	ai->flash = NULL;
+ 
+ 	/* The NOP is the first step in getting the card going */
+ 	cmd.cmd = NOP;
+@@ -3666,14 +3660,10 @@ static u16 setup_card(struct airo_info *
+ 		tdsRssiRid rssi_rid;
+ 		CapabilityRid cap_rid;
+ 
+-		if (ai->APList) {
+-			kfree(ai->APList);
+-			ai->APList = NULL;
+-		}
+-		if (ai->SSID) {
+-			kfree(ai->SSID);
+-			ai->SSID = NULL;
+-		}
++		kfree(ai->APList);
++		ai->APList = NULL;
++		kfree(ai->SSID);
++		ai->SSID = NULL;
+ 		// general configuration (read/modify/write)
+ 		status = readConfigRid(ai, lock);
+ 		if ( status != SUCCESS ) return ERROR;
+@@ -3687,10 +3677,8 @@ static u16 setup_card(struct airo_info *
+ 				memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512); /* Skip RID length member */
+ 		}
+ 		else {
+-			if (ai->rssi) {
+-				kfree(ai->rssi);
+-				ai->rssi = NULL;
+-			}
++			kfree(ai->rssi);
++			ai->rssi = NULL;
+ 			if (cap_rid.softCap & 8)
+ 				ai->config.rmode |= RXMODE_NORMALIZED_RSSI;
+ 			else
+@@ -5369,11 +5357,13 @@ static int proc_BSSList_open( struct ino
+ 
+ static int proc_close( struct inode *inode, struct file *file )
+ {
+-	struct proc_data *data = (struct proc_data *)file->private_data;
+-	if ( data->on_close != NULL ) data->on_close( inode, file );
+-	if ( data->rbuffer ) kfree( data->rbuffer );
+-	if ( data->wbuffer ) kfree( data->wbuffer );
+-	kfree( data );
++	struct proc_data *data = file->private_data;
++
++	if (data->on_close != NULL)
++		data->on_close(inode, file);
++	kfree(data->rbuffer);
++	kfree(data->wbuffer);
++	kfree(data);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
+index bf25584..784de91 100644
+--- a/drivers/net/wireless/airo_cs.c
++++ b/drivers/net/wireless/airo_cs.c
+@@ -258,9 +258,7 @@ static void airo_detach(dev_link_t *link
+ 	
+ 	/* Unlink device structure, free pieces */
+ 	*linkp = link->next;
+-	if (link->priv) {
+-		kfree(link->priv);
+-	}
++	kfree(link->priv);
+ 	kfree(link);
+ 	
+ } /* airo_detach */
+diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
+index d570110..1fbe027 100644
+--- a/drivers/net/wireless/atmel.c
++++ b/drivers/net/wireless/atmel.c
+@@ -1653,8 +1653,7 @@ void stop_atmel_card(struct net_device *
+ 	unregister_netdev(dev);
+ 	remove_proc_entry("driver/atmel", NULL);
+ 	free_irq(dev->irq, dev);
+-	if (priv->firmware)
+-		kfree(priv->firmware);
++	kfree(priv->firmware);
+ 	if (freeres) {
+ 		/* PCMCIA frees this stuff, so only for PCI */
+ 	        release_region(dev->base_addr, 64);
+@@ -2450,8 +2449,7 @@ static int atmel_ioctl(struct net_device
+ 			break;
+ 		}
+ 
+-		if (priv->firmware)
+-			kfree(priv->firmware);
++		kfree(priv->firmware);
+ 		
+ 		priv->firmware = new_firmware;
+ 		priv->firmware_length = com.len;
+diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
+index ff031a3..195cb36 100644
+--- a/drivers/net/wireless/atmel_cs.c
++++ b/drivers/net/wireless/atmel_cs.c
+@@ -259,8 +259,7 @@ static void atmel_detach(dev_link_t *lin
+ 
+ 	/* Unlink device structure, free pieces */
+ 	*linkp = link->next;
+-	if (link->priv)
+-		kfree(link->priv);
++	kfree(link->priv);
+ 	kfree(link);
+ }
+ 
+diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
+index 53f5246..2617d70 100644
+--- a/drivers/net/wireless/hostap/hostap_ioctl.c
++++ b/drivers/net/wireless/hostap/hostap_ioctl.c
+@@ -552,7 +552,6 @@ static int prism2_ioctl_giwaplist(struct
+ 
+ 	kfree(addr);
+ 	kfree(qual);
+-
+ 	return 0;
+ }
+ 
+@@ -3081,9 +3080,7 @@ static int prism2_ioctl_priv_download(lo
+ 	ret = local->func->download(local, param);
+ 
+  out:
+-	if (param != NULL)
+-		kfree(param);
+-
++	kfree(param);
+ 	return ret;
+ }
+ #endif /* PRISM2_DOWNLOAD_SUPPORT */
+@@ -3890,9 +3887,7 @@ static int prism2_ioctl_priv_hostapd(loc
+ 	}
+ 
+  out:
+-	if (param != NULL)
+-		kfree(param);
+-
++	kfree(param);
+ 	return ret;
+ }
+ 
+diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c
+index 6c9584a..78bdb35 100644
+--- a/drivers/net/wireless/prism54/islpci_dev.c
++++ b/drivers/net/wireless/prism54/islpci_dev.c
+@@ -754,8 +754,7 @@ islpci_free_memory(islpci_private *priv)
+ 			pci_unmap_single(priv->pdev, buf->pci_addr,
+ 					 buf->size, PCI_DMA_FROMDEVICE);
+ 		buf->pci_addr = 0;
+-		if (buf->mem)
+-			kfree(buf->mem);
++		kfree(buf->mem);
+ 		buf->size = 0;
+ 		buf->mem = NULL;
+         }
+diff --git a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c
+index 12123e2..eea2f04 100644
+--- a/drivers/net/wireless/prism54/oid_mgt.c
++++ b/drivers/net/wireless/prism54/oid_mgt.c
+@@ -268,11 +268,10 @@ mgt_clean(islpci_private *priv)
+ 
+ 	if (!priv->mib)
+ 		return;
+-	for (i = 0; i < OID_NUM_LAST; i++)
+-		if (priv->mib[i]) {
+-			kfree(priv->mib[i]);
+-			priv->mib[i] = NULL;
+-		}
++	for (i = 0; i < OID_NUM_LAST; i++) {
++		kfree(priv->mib[i]);
++		priv->mib[i] = NULL;
++	}
+ 	kfree(priv->mib);
+ 	priv->mib = NULL;
+ }
+diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
+index 7bc7fc8..d25264b 100644
+--- a/drivers/net/wireless/strip.c
++++ b/drivers/net/wireless/strip.c
+@@ -860,12 +860,9 @@ static int allocate_buffers(struct strip
+ 		strip_info->mtu = dev->mtu = mtu;
+ 		return (1);
+ 	}
+-	if (r)
+-		kfree(r);
+-	if (s)
+-		kfree(s);
+-	if (t)
+-		kfree(t);
++	kfree(r);
++	kfree(s);
++	kfree(t);
+ 	return (0);
+ }
+ 
+@@ -922,13 +919,9 @@ static int strip_change_mtu(struct net_d
+ 	printk(KERN_NOTICE "%s: strip MTU changed fom %d to %d.\n",
+ 	       strip_info->dev->name, old_mtu, strip_info->mtu);
+ 
+-	if (orbuff)
+-		kfree(orbuff);
+-	if (osbuff)
+-		kfree(osbuff);
+-	if (otbuff)
+-		kfree(otbuff);
+-
++	kfree(orbuff);
++	kfree(osbuff);
++	kfree(otbuff);
+ 	return 0;
+ }
+ 
+@@ -2498,18 +2491,13 @@ static int strip_close_low(struct net_de
+ 	/*
+ 	 * Free all STRIP frame buffers.
+ 	 */
+-	if (strip_info->rx_buff) {
+-		kfree(strip_info->rx_buff);
+-		strip_info->rx_buff = NULL;
+-	}
+-	if (strip_info->sx_buff) {
+-		kfree(strip_info->sx_buff);
+-		strip_info->sx_buff = NULL;
+-	}
+-	if (strip_info->tx_buff) {
+-		kfree(strip_info->tx_buff);
+-		strip_info->tx_buff = NULL;
+-	}
++	kfree(strip_info->rx_buff);
++	strip_info->rx_buff = NULL;
++	kfree(strip_info->sx_buff);
++	strip_info->sx_buff = NULL;
++	kfree(strip_info->tx_buff);
++	strip_info->tx_buff = NULL;
++
+ 	del_timer(&strip_info->idle_timer);
+ 	return 0;
+ }
+diff --git a/include/net/ax25.h b/include/net/ax25.h
+index 30bb4a8..2250a18 100644
+--- a/include/net/ax25.h
++++ b/include/net/ax25.h
+@@ -237,8 +237,7 @@ typedef struct ax25_cb {
+ static __inline__ void ax25_cb_put(ax25_cb *ax25)
+ {
+ 	if (atomic_dec_and_test(&ax25->refcount)) {
+-		if (ax25->digipeat)
+-			kfree(ax25->digipeat);
++		kfree(ax25->digipeat);
+ 		kfree(ax25);
+ 	}
+ }
+diff --git a/include/net/netrom.h b/include/net/netrom.h
+index a6bf6e0..a5ee53b 100644
+--- a/include/net/netrom.h
++++ b/include/net/netrom.h
+@@ -136,8 +136,7 @@ static __inline__ void nr_node_put(struc
+ static __inline__ void nr_neigh_put(struct nr_neigh *nr_neigh)
+ {
+ 	if (atomic_dec_and_test(&nr_neigh->refcount)) {
+-		if (nr_neigh->digipeat != NULL)
+-			kfree(nr_neigh->digipeat);
++		kfree(nr_neigh->digipeat);
+ 		kfree(nr_neigh);
+ 	}
+ }
+---
+0.99.8.GIT


Index: 1065-ipw2200-Missing-kmalloc-check.txt
===================================================================
RCS file: 1065-ipw2200-Missing-kmalloc-check.txt
diff -N 1065-ipw2200-Missing-kmalloc-check.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 1065-ipw2200-Missing-kmalloc-check.txt	11 Nov 2005 18:29:01 -0000	1.1.2.3
@@ -0,0 +1,34 @@
+Subject: [PATCH] ipw2200: Missing kmalloc check
+From: Panagiotis Issaris <panagiotis issaris gmail com>
+Date: 1125886450 +0200
+
+The ipw2200 driver code in current GIT contains a kmalloc() followed by
+a memset() without handling a possible memory allocation failure.
+
+Signed-off-by: Panagiotis Issaris <panagiotis issaris gmail com>
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/ipw2200.c |    4 ++++
+ 1 files changed, 4 insertions(+), 0 deletions(-)
+
+applies-to: a18032b80383ba651236b7000028e2e1022ff0a2
+ad18b0ea089928367185e13d11424aea91d4b41f
+diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
+index de4e6c2..3db0c32 100644
+--- a/drivers/net/wireless/ipw2200.c
++++ b/drivers/net/wireless/ipw2200.c
+@@ -4030,6 +4030,10 @@ static struct ipw_rx_queue *ipw_rx_queue
+ 	int i;
+ 
+ 	rxq = (struct ipw_rx_queue *)kmalloc(sizeof(*rxq), GFP_KERNEL);
++	if (unlikely(!rxq)) {
++		IPW_ERROR("memory allocation failed\n");
++		return NULL;
++	}
+ 	memset(rxq, 0, sizeof(*rxq));
+ 	spin_lock_init(&rxq->lock);
+ 	INIT_LIST_HEAD(&rxq->rx_free);
+---
+0.99.8.GIT


--- NEW FILE 1141-SCTP-Rename-SCTP-specific-control-message-flags.txt ---
Subject: [PATCH] [SCTP] Rename SCTP specific control message flags.
From: Ivan Skytte Jorgensen <isj-sctp i1 dk>
Date: 1130537400 -0700

Rename SCTP specific control message flags to use SCTP_ prefix rather than
MSG_ prefix as per the latest sctp sockets API draft.

Signed-off-by: Ivan Skytte Jorgensen <isj-sctp i1 dk>
Signed-off-by: Sridhar Samudrala <sri us ibm com>

---

 include/net/sctp/user.h  |    8 ++++----
 net/sctp/sm_make_chunk.c |    2 +-
 net/sctp/socket.c        |   32 ++++++++++++++++----------------
 net/sctp/ulpevent.c      |    6 +++---
 4 files changed, 24 insertions(+), 24 deletions(-)

applies-to: 69ebfee77c8a174c87ea8ed31e023c94b09a9d6e
eaa5c54dbec70e2a93d6ed412bb589bbf9c90a17
diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h
index 1c5f19f..f1c3bc5 100644
--- a/include/net/sctp/user.h
+++ b/include/net/sctp/user.h
@@ -171,10 +171,10 @@ struct sctp_sndrcvinfo {
  */
 
 enum sctp_sinfo_flags {
-	MSG_UNORDERED = 1,  /* Send/receive message unordered. */
-	MSG_ADDR_OVER = 2,  /* Override the primary destination. */
-	MSG_ABORT=4,        /* Send an ABORT message to the peer. */
-	/* MSG_EOF is already defined per socket.h */
+	SCTP_UNORDERED = 1,  /* Send/receive message unordered. */
+	SCTP_ADDR_OVER = 2,  /* Override the primary destination. */
+	SCTP_ABORT=4,        /* Send an ABORT message to the peer. */
+	SCTP_EOF=MSG_FIN,    /* Initiate graceful shutdown process. */	
 };
 
 
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 10e82ec..660c61b 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -554,7 +554,7 @@ struct sctp_chunk *sctp_make_datafrag_em
 	dp.ppid   = sinfo->sinfo_ppid;
 
 	/* Set the flags for an unordered send.  */
-	if (sinfo->sinfo_flags & MSG_UNORDERED) {
+	if (sinfo->sinfo_flags & SCTP_UNORDERED) {
 		flags |= SCTP_DATA_UNORDERED;
 		dp.ssn = 0;
 	} else
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 02e068d..170045b 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1389,27 +1389,27 @@ SCTP_STATIC int sctp_sendmsg(struct kioc
 	SCTP_DEBUG_PRINTK("msg_len: %zu, sinfo_flags: 0x%x\n",
 			  msg_len, sinfo_flags);
 
-	/* MSG_EOF or MSG_ABORT cannot be set on a TCP-style socket. */
-	if (sctp_style(sk, TCP) && (sinfo_flags & (MSG_EOF | MSG_ABORT))) {
+	/* SCTP_EOF or SCTP_ABORT cannot be set on a TCP-style socket. */
+	if (sctp_style(sk, TCP) && (sinfo_flags & (SCTP_EOF | SCTP_ABORT))) {
 		err = -EINVAL;
 		goto out_nounlock;
 	}
 
-	/* If MSG_EOF is set, no data can be sent. Disallow sending zero
-	 * length messages when MSG_EOF|MSG_ABORT is not set.
-	 * If MSG_ABORT is set, the message length could be non zero with
+	/* If SCTP_EOF is set, no data can be sent. Disallow sending zero
+	 * length messages when SCTP_EOF|SCTP_ABORT is not set.
+	 * If SCTP_ABORT is set, the message length could be non zero with
 	 * the msg_iov set to the user abort reason.
  	 */
-	if (((sinfo_flags & MSG_EOF) && (msg_len > 0)) ||
-	    (!(sinfo_flags & (MSG_EOF|MSG_ABORT)) && (msg_len == 0))) {
+	if (((sinfo_flags & SCTP_EOF) && (msg_len > 0)) ||
+	    (!(sinfo_flags & (SCTP_EOF|SCTP_ABORT)) && (msg_len == 0))) {
 		err = -EINVAL;
 		goto out_nounlock;
 	}
 
-	/* If MSG_ADDR_OVER is set, there must be an address
+	/* If SCTP_ADDR_OVER is set, there must be an address
 	 * specified in msg_name.
 	 */
-	if ((sinfo_flags & MSG_ADDR_OVER) && (!msg->msg_name)) {
+	if ((sinfo_flags & SCTP_ADDR_OVER) && (!msg->msg_name)) {
 		err = -EINVAL;
 		goto out_nounlock;
 	}
@@ -1458,14 +1458,14 @@ SCTP_STATIC int sctp_sendmsg(struct kioc
 			goto out_unlock;
 		}
 
-		if (sinfo_flags & MSG_EOF) {
+		if (sinfo_flags & SCTP_EOF) {
 			SCTP_DEBUG_PRINTK("Shutting down association: %p\n",
 					  asoc);
 			sctp_primitive_SHUTDOWN(asoc, NULL);
 			err = 0;
 			goto out_unlock;
 		}
-		if (sinfo_flags & MSG_ABORT) {
+		if (sinfo_flags & SCTP_ABORT) {
 			SCTP_DEBUG_PRINTK("Aborting association: %p\n", asoc);
 			sctp_primitive_ABORT(asoc, msg);
 			err = 0;
@@ -1477,7 +1477,7 @@ SCTP_STATIC int sctp_sendmsg(struct kioc
 	if (!asoc) {
 		SCTP_DEBUG_PRINTK("There is no association yet.\n");
 
-		if (sinfo_flags & (MSG_EOF | MSG_ABORT)) {
+		if (sinfo_flags & (SCTP_EOF | SCTP_ABORT)) {
 			err = -EINVAL;
 			goto out_unlock;
 		}
@@ -1611,10 +1611,10 @@ SCTP_STATIC int sctp_sendmsg(struct kioc
 
 	/* If an address is passed with the sendto/sendmsg call, it is used
 	 * to override the primary destination address in the TCP model, or
-	 * when MSG_ADDR_OVER flag is set in the UDP model.
+	 * when SCTP_ADDR_OVER flag is set in the UDP model.
 	 */
 	if ((sctp_style(sk, TCP) && msg_name) ||
-	    (sinfo_flags & MSG_ADDR_OVER)) {
+	    (sinfo_flags & SCTP_ADDR_OVER)) {
 		chunk_tp = sctp_assoc_lookup_paddr(asoc, &to);
 		if (!chunk_tp) {
 			err = -EINVAL;
@@ -4640,8 +4640,8 @@ SCTP_STATIC int sctp_msghdr_parse(const 
 
 			/* Minimally, validate the sinfo_flags. */
 			if (cmsgs->info->sinfo_flags &
-			    ~(MSG_UNORDERED | MSG_ADDR_OVER |
-			      MSG_ABORT | MSG_EOF))
+			    ~(SCTP_UNORDERED | SCTP_ADDR_OVER |
+			      SCTP_ABORT | SCTP_EOF))
 				return -EINVAL;
 			break;
 
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index 057e7fa..e049f41 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -698,7 +698,7 @@ struct sctp_ulpevent *sctp_ulpevent_make
 	event->ssn = ntohs(chunk->subh.data_hdr->ssn);
 	event->ppid = chunk->subh.data_hdr->ppid;
 	if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) {
-		event->flags |= MSG_UNORDERED;
+		event->flags |= SCTP_UNORDERED;
 		event->cumtsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map);
 	}
 	event->tsn = ntohl(chunk->subh.data_hdr->tsn);
@@ -824,7 +824,7 @@ void sctp_ulpevent_read_sndrcvinfo(const
 	 *
 	 * recvmsg() flags:
 	 *
-	 * MSG_UNORDERED - This flag is present when the message was sent
+	 * SCTP_UNORDERED - This flag is present when the message was sent
 	 *                 non-ordered.
 	 */
 	sinfo.sinfo_flags = event->flags;
@@ -839,7 +839,7 @@ void sctp_ulpevent_read_sndrcvinfo(const
 	 * This field will hold the current cumulative TSN as
 	 * known by the underlying SCTP layer.  Note this field is
 	 * ignored when sending and only valid for a receive
-	 * operation when sinfo_flags are set to MSG_UNORDERED.
+	 * operation when sinfo_flags are set to SCTP_UNORDERED.
 	 */
 	sinfo.sinfo_cumtsn = event->cumtsn;
 	/* sinfo_assoc_id: sizeof (sctp_assoc_t)
---
0.99.8.GIT


--- NEW FILE 1145-SCTP-Fix-SCTP_SETADAPTION-sockopt-to-use-the-correct-structure.txt ---
Subject: [PATCH] [SCTP] Fix SCTP_SETADAPTION sockopt to use the correct structure.
From: Ivan Skytte Jorgensen <isj-sctp i1 dk>
Date: 1130538804 -0700

Signed-off-by: Ivan Skytte Jorgensen <isj-sctp i1 dk>
Signed-off-by: Sridhar Samudrala <sri us ibm com>

---

 net/sctp/socket.c |   20 +++++++++-----------
 1 files changed, 9 insertions(+), 11 deletions(-)

applies-to: 4047a75f7f74d978bad9c4862afbd47c8cda595a
a1ab3582699def352dab1355adcadd3d47f79f0f
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 170045b..c66c161 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -2384,14 +2384,14 @@ static int sctp_setsockopt_peer_primary_
 static int sctp_setsockopt_adaption_layer(struct sock *sk, char __user *optval,
 					  int optlen)
 {
-	__u32 val;
+	struct sctp_setadaption adaption;
 
-	if (optlen < sizeof(__u32))
+	if (optlen != sizeof(struct sctp_setadaption))
 		return -EINVAL;
-	if (copy_from_user(&val, optval, sizeof(__u32)))
+	if (copy_from_user(&adaption, optval, optlen)) 
 		return -EFAULT;
 
-	sctp_sk(sk)->adaption_ind = val;
+	sctp_sk(sk)->adaption_ind = adaption.ssb_adaption_ind;
 
 	return 0;
 }
@@ -3672,17 +3672,15 @@ static int sctp_getsockopt_primary_addr(
 static int sctp_getsockopt_adaption_layer(struct sock *sk, int len,
 				  char __user *optval, int __user *optlen)
 {
-	__u32 val;
+	struct sctp_setadaption adaption;
 
-	if (len < sizeof(__u32))
+	if (len != sizeof(struct sctp_setadaption))
 		return -EINVAL;
 
-	len = sizeof(__u32);
-	val = sctp_sk(sk)->adaption_ind;
-	if (put_user(len, optlen))
-		return -EFAULT;
-	if (copy_to_user(optval, &val, len))
+	adaption.ssb_adaption_ind = sctp_sk(sk)->adaption_ind;
+	if (copy_to_user(optval, &adaption, len))
 		return -EFAULT;
+
 	return 0;
 }
 
---
0.99.8.GIT


--- NEW FILE 1146-SCTP-Allow-SCTP_MAXSEG-to-revert-to-default-frag-point-with-a-0-value.txt ---
Subject: [PATCH] [SCTP] Allow SCTP_MAXSEG to revert to default frag point with a '0' value.
From: Ivan Skytte Jorgensen <isj-sctp i1 dk>
Date: 1130538972 -0700

Signed-off-by: Ivan Skytte Jorgensen <isj-sctp i1 dk>
Signed-off-by: Sridhar Samudrala <sri us ibm com>

---

 net/sctp/socket.c |   12 +++++-------
 1 files changed, 5 insertions(+), 7 deletions(-)

applies-to: 48faf33fae1b82f15df770e6340f58a858393e43
96a339985d4c6874d32909e8f1903e6e6c141399
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index c66c161..97b556c 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -2306,16 +2306,14 @@ static int sctp_setsockopt_maxseg(struct
 		return -EINVAL;
 	if (get_user(val, (int __user *)optval))
 		return -EFAULT;
-	if ((val < 8) || (val > SCTP_MAX_CHUNK_LEN))
+	if ((val != 0) && ((val < 8) || (val > SCTP_MAX_CHUNK_LEN)))
 		return -EINVAL;
 	sp->user_frag = val;
 
-	if (val) {
-		/* Update the frag_point of the existing associations. */
-		list_for_each(pos, &(sp->ep->asocs)) {
-			asoc = list_entry(pos, struct sctp_association, asocs);
-			asoc->frag_point = sctp_frag_point(sp, asoc->pmtu); 
-		}
+	/* Update the frag_point of the existing associations. */
+	list_for_each(pos, &(sp->ep->asocs)) {
+		asoc = list_entry(pos, struct sctp_association, asocs);
+		asoc->frag_point = sctp_frag_point(sp, asoc->pmtu); 
 	}
 
 	return 0;
---
0.99.8.GIT


--- NEW FILE 1178-SCTP-Do-not-allow-unprivileged-programs-initiating-new-associations-on.txt ---
Subject: [PATCH] [SCTP] Do not allow unprivileged programs initiating new associations on
From: Ivan Skytte Jorgensen <isj-sctp i1 dk>
Date: 1130539142 -0700
privileged ports.

Signed-off-by: Ivan Skytte Jorgensen <isj-sctp i1 dk>
Signed-off-by: Sridhar Samudrala <sri us ibm com>

---

 net/sctp/socket.c |   26 ++++++++++++++++++++++++++
 1 files changed, 26 insertions(+), 0 deletions(-)

applies-to: d3eb8006efa5e03bb0ef875bf8dc2ed1d90ecb21
64a0c1c81e300f0f56f26604c81040784e3717f0
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 97b556c..b529af5 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1010,6 +1010,19 @@ static int __sctp_connect(struct sock* s
 					err = -EAGAIN;
 					goto out_free;
 				}
+			} else {
+				/*
+				 * If an unprivileged user inherits a 1-many 
+				 * style socket with open associations on a 
+				 * privileged port, it MAY be permitted to 
+				 * accept new associations, but it SHOULD NOT 
+				 * be permitted to open new associations.
+				 */
+				if (ep->base.bind_addr.port < PROT_SOCK &&
+				    !capable(CAP_NET_BIND_SERVICE)) {
+					err = -EACCES;
+					goto out_free;
+				}
 			}
 
 			scope = sctp_scope(&to);
@@ -1515,6 +1528,19 @@ SCTP_STATIC int sctp_sendmsg(struct kioc
 				err = -EAGAIN;
 				goto out_unlock;
 			}
+		} else {
+			/*
+			 * If an unprivileged user inherits a one-to-many
+			 * style socket with open associations on a privileged
+			 * port, it MAY be permitted to accept new associations,
+			 * but it SHOULD NOT be permitted to open new
+			 * associations.
+			 */
+			if (ep->base.bind_addr.port < PROT_SOCK &&
+			    !capable(CAP_NET_BIND_SERVICE)) {
+				err = -EACCES;
+				goto out_unlock;
+			}
 		}
 
 		scope = sctp_scope(&to);
---
0.99.8.GIT


Index: 1186-revert-orinoco-Information-leakage-due-to-incorrect-padding.txt
===================================================================
RCS file: 1186-revert-orinoco-Information-leakage-due-to-incorrect-padding.txt
diff -N 1186-revert-orinoco-Information-leakage-due-to-incorrect-padding.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 1186-revert-orinoco-Information-leakage-due-to-incorrect-padding.txt	11 Nov 2005 18:29:01 -0000	1.1.2.3
@@ -0,0 +1,41 @@
+Subject: [PATCH] revert "orinoco: Information leakage due to incorrect padding"
+From: Andrew Morton <akpm osdl org>
+Date: 1130537691 -0700
+
+Cc: Alan Cox <alan redhat com>
+Signed-off-by: Andrew Morton <akpm osdl org>
+Signed-off-by: Jeff Garzik <jgarzik pobox com>
+
+---
+
+ drivers/net/wireless/orinoco.c |    6 ++++--
+ 1 files changed, 4 insertions(+), 2 deletions(-)
+
+applies-to: 05cb18e46286e5343a795c71890115a59e8c30bf
+63f57fb69b017230c77c40f1713e40885ae6d159
+diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
+index d3d4ec9..70a3477 100644
+--- a/drivers/net/wireless/orinoco.c
++++ b/drivers/net/wireless/orinoco.c
+@@ -490,7 +490,8 @@ static int orinoco_xmit(struct sk_buff *
+ 		return 0;
+ 	}
+ 
+-	/* Check packet length, pad short packets, round up odd length */
++	/* Length of the packet body */
++	/* FIXME: what if the skb is smaller than this? */
+ 	len = max_t(int, ALIGN(skb->len, 2), ETH_ZLEN);
+ 	skb = skb_padto(skb, len);
+ 	if (skb == NULL)
+@@ -547,7 +548,8 @@ static int orinoco_xmit(struct sk_buff *
+ 		p = skb->data;
+ 	}
+ 
+-	err = hermes_bap_pwrite(hw, USER_BAP, p, data_len,
++	/* Round up for odd length packets */
++	err = hermes_bap_pwrite(hw, USER_BAP, p, ALIGN(data_len, 2),
+ 				txfid, data_off);
+ 	if (err) {
+ 		printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
+---
+0.99.8.GIT


Index: 1187-Better-fixup-for-the-orinoco-driver.txt
===================================================================
RCS file: 1187-Better-fixup-for-the-orinoco-driver.txt
diff -N 1187-Better-fixup-for-the-orinoco-driver.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 1187-Better-fixup-for-the-orinoco-driver.txt	11 Nov 2005 18:29:01 -0000	1.1.2.3
@@ -0,0 +1,128 @@
+Subj