aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-04-24 14:34:17 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-04-24 14:34:17 -0400
commit8e500ff8df1223dfb42d6c39d3de1fc216fba1a2 (patch)
tree8fa65946dd64af4d1b120ff0a96567bbcb0db2f5 /drivers
parent383bee6b54a1eeac3a286812be8a5c3f122fd834 (diff)
parent7ce97d4f78b62e3af24cdd4df953d777e7efb2f6 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (22 commits) gianfar: Fix potential oops during OF address translation fsl_pq_mdio: Fix kernel oops during OF address translation tcp: bind() fix when many ports are bound rdma: potential ERR_PTR dereference rtnetlink: potential ERR_PTR dereference net: ipv6 bind to device issue ipv6: allow to send packet after receiving ICMPv6 Too Big message with MTU field less than IPV6_MIN_MTU drivers/net/usb: Add new driver ipheth cxgb3: fix linkup issue X25 fix dead unaccepted sockets KS8851: NULL pointer dereference if list is empty net: 3c574_cs fix stats.tx_bytes counter xfrm6: ensure to use the same dev when building a bundle can: Fix possible NULL pointer dereference in ems_usb.c net: Fix an RCU warning in dev_pick_tx() ipv6: Fix tcp_v6_send_response transport header setting. bridge: add a missing ntohs() 8139too: Fix a typo in the function name. mac80211: pass HT changes to driver when off channel mac80211: remove bogus TX agg state assignment ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/8139too.c2
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/can/usb/ems_usb.c8
-rw-r--r--drivers/net/cxgb3/ael1002.c2
-rw-r--r--drivers/net/fsl_pq_mdio.c20
-rw-r--r--drivers/net/gianfar.c6
-rw-r--r--drivers/net/ks8851.c12
-rw-r--r--drivers/net/pcmcia/3c574_cs.c7
-rw-r--r--drivers/net/usb/Kconfig12
-rw-r--r--drivers/net/usb/Makefile1
-rw-r--r--drivers/net/usb/ipheth.c568
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c31
18 files changed, 644 insertions, 39 deletions
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index a03d291de854..f0d23de32967 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -1944,7 +1944,7 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
1944 netif_dbg(tp, rx_status, dev, "%s() status %04x, size %04x, cur %04x\n", 1944 netif_dbg(tp, rx_status, dev, "%s() status %04x, size %04x, cur %04x\n",
1945 __func__, rx_status, rx_size, cur_rx); 1945 __func__, rx_status, rx_size, cur_rx);
1946#if RTL8139_DEBUG > 2 1946#if RTL8139_DEBUG > 2
1947 print_dump_hex(KERN_DEBUG, "Frame contents: ", 1947 print_hex_dump(KERN_DEBUG, "Frame contents: ",
1948 DUMP_PREFIX_OFFSET, 16, 1, 1948 DUMP_PREFIX_OFFSET, 16, 1,
1949 &rx_ring[ring_offset], 70, true); 1949 &rx_ring[ring_offset], 70, true);
1950#endif 1950#endif
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index a583b50d9de8..12b280afdd51 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -273,6 +273,7 @@ obj-$(CONFIG_USB_RTL8150) += usb/
273obj-$(CONFIG_USB_HSO) += usb/ 273obj-$(CONFIG_USB_HSO) += usb/
274obj-$(CONFIG_USB_USBNET) += usb/ 274obj-$(CONFIG_USB_USBNET) += usb/
275obj-$(CONFIG_USB_ZD1201) += usb/ 275obj-$(CONFIG_USB_ZD1201) += usb/
276obj-$(CONFIG_USB_IPHETH) += usb/
276 277
277obj-y += wireless/ 278obj-y += wireless/
278obj-$(CONFIG_NET_TULIP) += tulip/ 279obj-$(CONFIG_NET_TULIP) += tulip/
diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
index 33451092b8e8..d800b598ae3d 100644
--- a/drivers/net/can/usb/ems_usb.c
+++ b/drivers/net/can/usb/ems_usb.c
@@ -1006,7 +1006,7 @@ static int ems_usb_probe(struct usb_interface *intf,
1006 1006
1007 netdev = alloc_candev(sizeof(struct ems_usb), MAX_TX_URBS); 1007 netdev = alloc_candev(sizeof(struct ems_usb), MAX_TX_URBS);
1008 if (!netdev) { 1008 if (!netdev) {
1009 dev_err(netdev->dev.parent, "Couldn't alloc candev\n"); 1009 dev_err(&intf->dev, "ems_usb: Couldn't alloc candev\n");
1010 return -ENOMEM; 1010 return -ENOMEM;
1011 } 1011 }
1012 1012
@@ -1036,20 +1036,20 @@ static int ems_usb_probe(struct usb_interface *intf,
1036 1036
1037 dev->intr_urb = usb_alloc_urb(0, GFP_KERNEL); 1037 dev->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
1038 if (!dev->intr_urb) { 1038 if (!dev->intr_urb) {
1039 dev_err(netdev->dev.parent, "Couldn't alloc intr URB\n"); 1039 dev_err(&intf->dev, "Couldn't alloc intr URB\n");
1040 goto cleanup_candev; 1040 goto cleanup_candev;
1041 } 1041 }
1042 1042
1043 dev->intr_in_buffer = kzalloc(INTR_IN_BUFFER_SIZE, GFP_KERNEL); 1043 dev->intr_in_buffer = kzalloc(INTR_IN_BUFFER_SIZE, GFP_KERNEL);
1044 if (!dev->intr_in_buffer) { 1044 if (!dev->intr_in_buffer) {
1045 dev_err(netdev->dev.parent, "Couldn't alloc Intr buffer\n"); 1045 dev_err(&intf->dev, "Couldn't alloc Intr buffer\n");
1046 goto cleanup_intr_urb; 1046 goto cleanup_intr_urb;
1047 } 1047 }
1048 1048
1049 dev->tx_msg_buffer = kzalloc(CPC_HEADER_SIZE + 1049 dev->tx_msg_buffer = kzalloc(CPC_HEADER_SIZE +
1050 sizeof(struct ems_cpc_msg), GFP_KERNEL); 1050 sizeof(struct ems_cpc_msg), GFP_KERNEL);
1051 if (!dev->tx_msg_buffer) { 1051 if (!dev->tx_msg_buffer) {
1052 dev_err(netdev->dev.parent, "Couldn't alloc Tx buffer\n"); 1052 dev_err(&intf->dev, "Couldn't alloc Tx buffer\n");
1053 goto cleanup_intr_in_buffer; 1053 goto cleanup_intr_in_buffer;
1054 } 1054 }
1055 1055
diff --git a/drivers/net/cxgb3/ael1002.c b/drivers/net/cxgb3/ael1002.c
index 5248f9e0b2f4..35cd36729155 100644
--- a/drivers/net/cxgb3/ael1002.c
+++ b/drivers/net/cxgb3/ael1002.c
@@ -934,7 +934,7 @@ static struct cphy_ops xaui_direct_ops = {
934int t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter, 934int t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter,
935 int phy_addr, const struct mdio_ops *mdio_ops) 935 int phy_addr, const struct mdio_ops *mdio_ops)
936{ 936{
937 cphy_init(phy, adapter, MDIO_PRTAD_NONE, &xaui_direct_ops, mdio_ops, 937 cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops,
938 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP, 938 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
939 "10GBASE-CX4"); 939 "10GBASE-CX4");
940 return 0; 940 return 0;
diff --git a/drivers/net/fsl_pq_mdio.c b/drivers/net/fsl_pq_mdio.c
index d5160edf2fcf..3acac5f930c8 100644
--- a/drivers/net/fsl_pq_mdio.c
+++ b/drivers/net/fsl_pq_mdio.c
@@ -205,8 +205,6 @@ static int fsl_pq_mdio_find_free(struct mii_bus *new_bus)
205static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs, struct device_node *np) 205static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs, struct device_node *np)
206{ 206{
207 struct gfar __iomem *enet_regs; 207 struct gfar __iomem *enet_regs;
208 u32 __iomem *ioremap_tbipa;
209 u64 addr, size;
210 208
211 /* 209 /*
212 * This is mildly evil, but so is our hardware for doing this. 210 * This is mildly evil, but so is our hardware for doing this.
@@ -220,9 +218,7 @@ static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs, struct devi
220 return &enet_regs->tbipa; 218 return &enet_regs->tbipa;
221 } else if (of_device_is_compatible(np, "fsl,etsec2-mdio") || 219 } else if (of_device_is_compatible(np, "fsl,etsec2-mdio") ||
222 of_device_is_compatible(np, "fsl,etsec2-tbi")) { 220 of_device_is_compatible(np, "fsl,etsec2-tbi")) {
223 addr = of_translate_address(np, of_get_address(np, 1, &size, NULL)); 221 return of_iomap(np, 1);
224 ioremap_tbipa = ioremap(addr, size);
225 return ioremap_tbipa;
226 } else 222 } else
227 return NULL; 223 return NULL;
228} 224}
@@ -279,6 +275,7 @@ static int fsl_pq_mdio_probe(struct of_device *ofdev,
279 u32 __iomem *tbipa; 275 u32 __iomem *tbipa;
280 struct mii_bus *new_bus; 276 struct mii_bus *new_bus;
281 int tbiaddr = -1; 277 int tbiaddr = -1;
278 const u32 *addrp;
282 u64 addr = 0, size = 0; 279 u64 addr = 0, size = 0;
283 int err = 0; 280 int err = 0;
284 281
@@ -297,8 +294,19 @@ static int fsl_pq_mdio_probe(struct of_device *ofdev,
297 new_bus->priv = priv; 294 new_bus->priv = priv;
298 fsl_pq_mdio_bus_name(new_bus->id, np); 295 fsl_pq_mdio_bus_name(new_bus->id, np);
299 296
297 addrp = of_get_address(np, 0, &size, NULL);
298 if (!addrp) {
299 err = -EINVAL;
300 goto err_free_bus;
301 }
302
300 /* Set the PHY base address */ 303 /* Set the PHY base address */
301 addr = of_translate_address(np, of_get_address(np, 0, &size, NULL)); 304 addr = of_translate_address(np, addrp);
305 if (addr == OF_BAD_ADDR) {
306 err = -EINVAL;
307 goto err_free_bus;
308 }
309
302 map = ioremap(addr, size); 310 map = ioremap(addr, size);
303 if (!map) { 311 if (!map) {
304 err = -ENOMEM; 312 err = -ENOMEM;
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 080d1cea5b26..df49af382159 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -549,12 +549,8 @@ static int gfar_parse_group(struct device_node *np,
549 struct gfar_private *priv, const char *model) 549 struct gfar_private *priv, const char *model)
550{ 550{
551 u32 *queue_mask; 551 u32 *queue_mask;
552 u64 addr, size;
553
554 addr = of_translate_address(np,
555 of_get_address(np, 0, &size, NULL));
556 priv->gfargrp[priv->num_grps].regs = ioremap(addr, size);
557 552
553 priv->gfargrp[priv->num_grps].regs = of_iomap(np, 0);
558 if (!priv->gfargrp[priv->num_grps].regs) 554 if (!priv->gfargrp[priv->num_grps].regs)
559 return -ENOMEM; 555 return -ENOMEM;
560 556
diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c
index 13cc1ca261d9..9e9f9b349766 100644
--- a/drivers/net/ks8851.c
+++ b/drivers/net/ks8851.c
@@ -722,12 +722,14 @@ static void ks8851_tx_work(struct work_struct *work)
722 txb = skb_dequeue(&ks->txq); 722 txb = skb_dequeue(&ks->txq);
723 last = skb_queue_empty(&ks->txq); 723 last = skb_queue_empty(&ks->txq);
724 724
725 ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_SDA); 725 if (txb != NULL) {
726 ks8851_wrpkt(ks, txb, last); 726 ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_SDA);
727 ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr); 727 ks8851_wrpkt(ks, txb, last);
728 ks8851_wrreg16(ks, KS_TXQCR, TXQCR_METFE); 728 ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr);
729 ks8851_wrreg16(ks, KS_TXQCR, TXQCR_METFE);
729 730
730 ks8851_done_tx(ks, txb); 731 ks8851_done_tx(ks, txb);
732 }
731 } 733 }
732 734
733 mutex_unlock(&ks->lock); 735 mutex_unlock(&ks->lock);
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index 3d1d3a7b7ed3..757f87bb1db3 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -781,8 +781,13 @@ static netdev_tx_t el3_start_xmit(struct sk_buff *skb,
781 inw(ioaddr + EL3_STATUS)); 781 inw(ioaddr + EL3_STATUS));
782 782
783 spin_lock_irqsave(&lp->window_lock, flags); 783 spin_lock_irqsave(&lp->window_lock, flags);
784
785 dev->stats.tx_bytes += skb->len;
786
787 /* Put out the doubleword header... */
784 outw(skb->len, ioaddr + TX_FIFO); 788 outw(skb->len, ioaddr + TX_FIFO);
785 outw(0, ioaddr + TX_FIFO); 789 outw(0, ioaddr + TX_FIFO);
790 /* ... and the packet rounded to a doubleword. */
786 outsl(ioaddr + TX_FIFO, skb->data, (skb->len+3)>>2); 791 outsl(ioaddr + TX_FIFO, skb->data, (skb->len+3)>>2);
787 792
788 dev->trans_start = jiffies; 793 dev->trans_start = jiffies;
@@ -1021,8 +1026,6 @@ static void update_stats(struct net_device *dev)
1021 /* BadSSD */ inb(ioaddr + 12); 1026 /* BadSSD */ inb(ioaddr + 12);
1022 up = inb(ioaddr + 13); 1027 up = inb(ioaddr + 13);
1023 1028
1024 dev->stats.tx_bytes += tx + ((up & 0xf0) << 12);
1025
1026 EL3WINDOW(1); 1029 EL3WINDOW(1);
1027} 1030}
1028 1031
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index ba56ce4382d9..63be4caec70e 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -385,4 +385,16 @@ config USB_CDC_PHONET
385 cellular modem, as found on most Nokia handsets with the 385 cellular modem, as found on most Nokia handsets with the
386 "PC suite" USB profile. 386 "PC suite" USB profile.
387 387
388config USB_IPHETH
389 tristate "Apple iPhone USB Ethernet driver"
390 default n
391 ---help---
392 Module used to share Internet connection (tethering) from your
393 iPhone (Original, 3G and 3GS) to your system.
394 Note that you need userspace libraries and programs that are needed
395 to pair your device with your system and that understand the iPhone
396 protocol.
397
398 For more information: http://giagio.com/wiki/moin.cgi/iPhoneEthernetDriver
399
388endmenu 400endmenu
diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile
index 82ea62955b56..edb09c0ddf8e 100644
--- a/drivers/net/usb/Makefile
+++ b/drivers/net/usb/Makefile
@@ -23,4 +23,5 @@ obj-$(CONFIG_USB_NET_MCS7830) += mcs7830.o
23obj-$(CONFIG_USB_USBNET) += usbnet.o 23obj-$(CONFIG_USB_USBNET) += usbnet.o
24obj-$(CONFIG_USB_NET_INT51X1) += int51x1.o 24obj-$(CONFIG_USB_NET_INT51X1) += int51x1.o
25obj-$(CONFIG_USB_CDC_PHONET) += cdc-phonet.o 25obj-$(CONFIG_USB_CDC_PHONET) += cdc-phonet.o
26obj-$(CONFIG_USB_IPHETH) += ipheth.o
26 27
diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c
new file mode 100644
index 000000000000..fd1033130a81
--- /dev/null
+++ b/drivers/net/usb/ipheth.c
@@ -0,0 +1,568 @@
1/*
2 * ipheth.c - Apple iPhone USB Ethernet driver
3 *
4 * Copyright (c) 2009 Diego Giagio <diego@giagio.com>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of GIAGIO.COM nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * Alternatively, provided that this notice is retained in full, this
20 * software may be distributed under the terms of the GNU General
21 * Public License ("GPL") version 2, in which case the provisions of the
22 * GPL apply INSTEAD OF those given above.
23 *
24 * The provided data structures and external interfaces from this code
25 * are not restricted to be used by modules with a GPL compatible license.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
38 * DAMAGE.
39 *
40 *
41 * Attention: iPhone device must be paired, otherwise it won't respond to our
42 * driver. For more info: http://giagio.com/wiki/moin.cgi/iPhoneEthernetDriver
43 *
44 */
45
46#include <linux/kernel.h>
47#include <linux/errno.h>
48#include <linux/init.h>
49#include <linux/slab.h>
50#include <linux/module.h>
51#include <linux/netdevice.h>
52#include <linux/etherdevice.h>
53#include <linux/ethtool.h>
54#include <linux/usb.h>
55#include <linux/workqueue.h>
56
57#define USB_VENDOR_APPLE 0x05ac
58#define USB_PRODUCT_IPHONE 0x1290
59#define USB_PRODUCT_IPHONE_3G 0x1292
60#define USB_PRODUCT_IPHONE_3GS 0x1294
61
62#define IPHETH_USBINTF_CLASS 255
63#define IPHETH_USBINTF_SUBCLASS 253
64#define IPHETH_USBINTF_PROTO 1
65
66#define IPHETH_BUF_SIZE 1516
67#define IPHETH_TX_TIMEOUT (5 * HZ)
68
69#define IPHETH_INTFNUM 2
70#define IPHETH_ALT_INTFNUM 1
71
72#define IPHETH_CTRL_ENDP 0x00
73#define IPHETH_CTRL_BUF_SIZE 0x40
74#define IPHETH_CTRL_TIMEOUT (5 * HZ)
75
76#define IPHETH_CMD_GET_MACADDR 0x00
77#define IPHETH_CMD_CARRIER_CHECK 0x45
78
79#define IPHETH_CARRIER_CHECK_TIMEOUT round_jiffies_relative(1 * HZ)
80#define IPHETH_CARRIER_ON 0x04
81
82static struct usb_device_id ipheth_table[] = {
83 { USB_DEVICE_AND_INTERFACE_INFO(
84 USB_VENDOR_APPLE, USB_PRODUCT_IPHONE,
85 IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
86 IPHETH_USBINTF_PROTO) },
87 { USB_DEVICE_AND_INTERFACE_INFO(
88 USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_3G,
89 IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
90 IPHETH_USBINTF_PROTO) },
91 { USB_DEVICE_AND_INTERFACE_INFO(
92 USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_3GS,
93 IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
94 IPHETH_USBINTF_PROTO) },
95 { }
96};
97MODULE_DEVICE_TABLE(usb, ipheth_table);
98
99struct ipheth_device {
100 struct usb_device *udev;
101 struct usb_interface *intf;
102 struct net_device *net;
103 struct sk_buff *tx_skb;
104 struct urb *tx_urb;
105 struct urb *rx_urb;
106 unsigned char *tx_buf;
107 unsigned char *rx_buf;
108 unsigned char *ctrl_buf;
109 u8 bulk_in;
110 u8 bulk_out;
111 struct delayed_work carrier_work;
112};
113
114static int ipheth_rx_submit(struct ipheth_device *dev, gfp_t mem_flags);
115
116static int ipheth_alloc_urbs(struct ipheth_device *iphone)
117{
118 struct urb *tx_urb = NULL;
119 struct urb *rx_urb = NULL;
120 u8 *tx_buf = NULL;
121 u8 *rx_buf = NULL;
122
123 tx_urb = usb_alloc_urb(0, GFP_KERNEL);
124 if (tx_urb == NULL)
125 goto error;
126
127 rx_urb = usb_alloc_urb(0, GFP_KERNEL);
128 if (rx_urb == NULL)
129 goto error;
130
131 tx_buf = usb_buffer_alloc(iphone->udev,
132 IPHETH_BUF_SIZE,
133 GFP_KERNEL,
134 &tx_urb->transfer_dma);
135 if (tx_buf == NULL)
136 goto error;
137
138 rx_buf = usb_buffer_alloc(iphone->udev,
139 IPHETH_BUF_SIZE,
140 GFP_KERNEL,
141 &rx_urb->transfer_dma);
142 if (rx_buf == NULL)
143 goto error;
144
145
146 iphone->tx_urb = tx_urb;
147 iphone->rx_urb = rx_urb;
148 iphone->tx_buf = tx_buf;
149 iphone->rx_buf = rx_buf;
150 return 0;
151
152error:
153 usb_buffer_free(iphone->udev, IPHETH_BUF_SIZE, rx_buf,
154 rx_urb->transfer_dma);
155 usb_buffer_free(iphone->udev, IPHETH_BUF_SIZE, tx_buf,
156 tx_urb->transfer_dma);
157 usb_free_urb(rx_urb);
158 usb_free_urb(tx_urb);
159 return -ENOMEM;
160}
161
162static void ipheth_free_urbs(struct ipheth_device *iphone)
163{
164 usb_buffer_free(iphone->udev, IPHETH_BUF_SIZE, iphone->rx_buf,
165 iphone->rx_urb->transfer_dma);
166 usb_buffer_free(iphone->udev, IPHETH_BUF_SIZE, iphone->tx_buf,
167 iphone->tx_urb->transfer_dma);
168 usb_free_urb(iphone->rx_urb);
169 usb_free_urb(iphone->tx_urb);
170}
171
172static void ipheth_kill_urbs(struct ipheth_device *dev)
173{
174 usb_kill_urb(dev->tx_urb);
175 usb_kill_urb(dev->rx_urb);
176}
177
178static void ipheth_rcvbulk_callback(struct urb *urb)
179{
180 struct ipheth_device *dev;
181 struct sk_buff *skb;
182 int status;
183 char *buf;
184 int len;
185
186 dev = urb->context;
187 if (dev == NULL)
188 return;
189
190 status = urb->status;
191 switch (status) {
192 case -ENOENT:
193 case -ECONNRESET:
194 case -ESHUTDOWN:
195 return;
196 case 0:
197 break;
198 default:
199 err("%s: urb status: %d", __func__, urb->status);
200 return;
201 }
202
203 len = urb->actual_length;
204 buf = urb->transfer_buffer;
205
206 skb = dev_alloc_skb(NET_IP_ALIGN + len);
207 if (!skb) {
208 err("%s: dev_alloc_skb: -ENOMEM", __func__);
209 dev->net->stats.rx_dropped++;
210 return;
211 }
212
213 skb_reserve(skb, NET_IP_ALIGN);
214 memcpy(skb_put(skb, len), buf + NET_IP_ALIGN, len - NET_IP_ALIGN);
215 skb->dev = dev->net;
216 skb->protocol = eth_type_trans(skb, dev->net);
217
218 dev->net->stats.rx_packets++;
219 dev->net->stats.rx_bytes += len;
220
221 netif_rx(skb);
222 ipheth_rx_submit(dev, GFP_ATOMIC);
223}
224
225static void ipheth_sndbulk_callback(struct urb *urb)
226{
227 struct ipheth_device *dev;
228
229 dev = urb->context;
230 if (dev == NULL)
231 return;
232
233 if (urb->status != 0 &&
234 urb->status != -ENOENT &&
235 urb->status != -ECONNRESET &&
236 urb->status != -ESHUTDOWN)
237 err("%s: urb status: %d", __func__, urb->status);
238
239 dev_kfree_skb_irq(dev->tx_skb);
240 netif_wake_queue(dev->net);
241}
242
243static int ipheth_carrier_set(struct ipheth_device *dev)
244{
245 struct usb_device *udev = dev->udev;
246 int retval;
247
248 retval = usb_control_msg(udev,
249 usb_rcvctrlpipe(udev, IPHETH_CTRL_ENDP),
250 IPHETH_CMD_CARRIER_CHECK, /* request */
251 0xc0, /* request type */
252 0x00, /* value */
253 0x02, /* index */
254 dev->ctrl_buf, IPHETH_CTRL_BUF_SIZE,
255 IPHETH_CTRL_TIMEOUT);
256 if (retval < 0) {
257 err("%s: usb_control_msg: %d", __func__, retval);
258 return retval;
259 }
260
261 if (dev->ctrl_buf[0] == IPHETH_CARRIER_ON)
262 netif_carrier_on(dev->net);
263 else
264 netif_carrier_off(dev->net);
265
266 return 0;
267}
268
269static void ipheth_carrier_check_work(struct work_struct *work)
270{
271 struct ipheth_device *dev = container_of(work, struct ipheth_device,
272 carrier_work.work);
273
274 ipheth_carrier_set(dev);
275 schedule_delayed_work(&dev->carrier_work, IPHETH_CARRIER_CHECK_TIMEOUT);
276}
277
278static int ipheth_get_macaddr(struct ipheth_device *dev)
279{
280 struct usb_device *udev = dev->udev;
281 struct net_device *net = dev->net;
282 int retval;
283
284 retval = usb_control_msg(udev,
285 usb_rcvctrlpipe(udev, IPHETH_CTRL_ENDP),
286 IPHETH_CMD_GET_MACADDR, /* request */
287 0xc0, /* request type */
288 0x00, /* value */
289 0x02, /* index */
290 dev->ctrl_buf,
291 IPHETH_CTRL_BUF_SIZE,
292 IPHETH_CTRL_TIMEOUT);
293 if (retval < 0) {
294 err("%s: usb_control_msg: %d", __func__, retval);
295 } else if (retval < ETH_ALEN) {
296 err("%s: usb_control_msg: short packet: %d bytes",
297 __func__, retval);
298 retval = -EINVAL;
299 } else {
300 memcpy(net->dev_addr, dev->ctrl_buf, ETH_ALEN);
301 retval = 0;
302 }
303
304 return retval;
305}
306
307static int ipheth_rx_submit(struct ipheth_device *dev, gfp_t mem_flags)
308{
309 struct usb_device *udev = dev->udev;
310 int retval;
311
312 usb_fill_bulk_urb(dev->rx_urb, udev,
313 usb_rcvbulkpipe(udev, dev->bulk_in),
314 dev->rx_buf, IPHETH_BUF_SIZE,
315 ipheth_rcvbulk_callback,
316 dev);
317 dev->rx_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
318
319 retval = usb_submit_urb(dev->rx_urb, mem_flags);
320 if (retval)
321 err("%s: usb_submit_urb: %d", __func__, retval);
322 return retval;
323}
324
325static int ipheth_open(struct net_device *net)
326{
327 struct ipheth_device *dev = netdev_priv(net);
328 struct usb_device *udev = dev->udev;
329 int retval = 0;
330
331 usb_set_interface(udev, IPHETH_INTFNUM, IPHETH_ALT_INTFNUM);
332
333 retval = ipheth_carrier_set(dev);
334 if (retval)
335 return retval;
336
337 retval = ipheth_rx_submit(dev, GFP_KERNEL);
338 if (retval)
339 return retval;
340
341 schedule_delayed_work(&dev->carrier_work, IPHETH_CARRIER_CHECK_TIMEOUT);
342 netif_start_queue(net);
343 return retval;
344}
345
346static int ipheth_close(struct net_device *net)
347{
348 struct ipheth_device *dev = netdev_priv(net);
349
350 cancel_delayed_work_sync(&dev->carrier_work);
351 netif_stop_queue(net);
352 return 0;
353}
354
355static int ipheth_tx(struct sk_buff *skb, struct net_device *net)
356{
357 struct ipheth_device *dev = netdev_priv(net);
358 struct usb_device *udev = dev->udev;
359 int retval;
360
361 /* Paranoid */
362 if (skb->len > IPHETH_BUF_SIZE) {
363 WARN(1, "%s: skb too large: %d bytes", __func__, skb->len);
364 dev->net->stats.tx_dropped++;
365 dev_kfree_skb_irq(skb);
366 return NETDEV_TX_OK;
367 }
368
369 memcpy(dev->tx_buf, skb->data, skb->len);
370 if (skb->len < IPHETH_BUF_SIZE)
371 memset(dev->tx_buf + skb->len, 0, IPHETH_BUF_SIZE - skb->len);
372
373 usb_fill_bulk_urb(dev->tx_urb, udev,
374 usb_sndbulkpipe(udev, dev->bulk_out),
375 dev->tx_buf, IPHETH_BUF_SIZE,
376 ipheth_sndbulk_callback,
377 dev);
378 dev->tx_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
379
380 retval = usb_submit_urb(dev->tx_urb, GFP_ATOMIC);
381 if (retval) {
382 err("%s: usb_submit_urb: %d", __func__, retval);
383 dev->net->stats.tx_errors++;
384 dev_kfree_skb_irq(skb);
385 } else {
386 dev->tx_skb = skb;
387
388 dev->net->stats.tx_packets++;
389 dev->net->stats.tx_bytes += skb->len;
390 netif_stop_queue(net);
391 }
392
393 return NETDEV_TX_OK;
394}
395
396static void ipheth_tx_timeout(struct net_device *net)
397{
398 struct ipheth_device *dev = netdev_priv(net);
399
400 err("%s: TX timeout", __func__);
401 dev->net->stats.tx_errors++;
402 usb_unlink_urb(dev->tx_urb);
403}
404
405static struct net_device_stats *ipheth_stats(struct net_device *net)
406{
407 struct ipheth_device *dev = netdev_priv(net);
408 return &dev->net->stats;
409}
410
411static u32 ipheth_ethtool_op_get_link(struct net_device *net)
412{
413 struct ipheth_device *dev = netdev_priv(net);
414 return netif_carrier_ok(dev->net);
415}
416
417static struct ethtool_ops ops = {
418 .get_link = ipheth_ethtool_op_get_link
419};
420
421static const struct net_device_ops ipheth_netdev_ops = {
422 .ndo_open = &ipheth_open,
423 .ndo_stop = &ipheth_close,
424 .ndo_start_xmit = &ipheth_tx,
425 .ndo_tx_timeout = &ipheth_tx_timeout,
426 .ndo_get_stats = &ipheth_stats,
427};
428
429static struct device_type ipheth_type = {
430 .name = "wwan",
431};
432
433static int ipheth_probe(struct usb_interface *intf,
434 const struct usb_device_id *id)
435{
436 struct usb_device *udev = interface_to_usbdev(intf);
437 struct usb_host_interface *hintf;
438 struct usb_endpoint_descriptor *endp;
439 struct ipheth_device *dev;
440 struct net_device *netdev;
441 int i;
442 int retval;
443
444 netdev = alloc_etherdev(sizeof(struct ipheth_device));
445 if (!netdev)
446 return -ENOMEM;
447
448 netdev->netdev_ops = &ipheth_netdev_ops;
449 netdev->watchdog_timeo = IPHETH_TX_TIMEOUT;
450 strcpy(netdev->name, "wwan%d");
451
452 dev = netdev_priv(netdev);
453 dev->udev = udev;
454 dev->net = netdev;
455 dev->intf = intf;
456
457 /* Set up endpoints */
458 hintf = usb_altnum_to_altsetting(intf, IPHETH_ALT_INTFNUM);
459 if (hintf == NULL) {
460 retval = -ENODEV;
461 err("Unable to find alternate settings interface");
462 goto err_endpoints;
463 }
464
465 for (i = 0; i < hintf->desc.bNumEndpoints; i++) {
466 endp = &hintf->endpoint[i].desc;
467 if (usb_endpoint_is_bulk_in(endp))
468 dev->bulk_in = endp->bEndpointAddress;
469 else if (usb_endpoint_is_bulk_out(endp))
470 dev->bulk_out = endp->bEndpointAddress;
471 }
472 if (!(dev->bulk_in && dev->bulk_out)) {
473 retval = -ENODEV;
474 err("Unable to find endpoints");
475 goto err_endpoints;
476 }
477
478 dev->ctrl_buf = kmalloc(IPHETH_CTRL_BUF_SIZE, GFP_KERNEL);
479 if (dev->ctrl_buf == NULL) {
480 retval = -ENOMEM;
481 goto err_alloc_ctrl_buf;
482 }
483
484 retval = ipheth_get_macaddr(dev);
485 if (retval)
486 goto err_get_macaddr;
487
488 INIT_DELAYED_WORK(&dev->carrier_work, ipheth_carrier_check_work);
489
490 retval = ipheth_alloc_urbs(dev);
491 if (retval) {
492 err("error allocating urbs: %d", retval);
493 goto err_alloc_urbs;
494 }
495
496 usb_set_intfdata(intf, dev);
497
498 SET_NETDEV_DEV(netdev, &intf->dev);
499 SET_ETHTOOL_OPS(netdev, &ops);
500 SET_NETDEV_DEVTYPE(netdev, &ipheth_type);
501
502 retval = register_netdev(netdev);
503 if (retval) {
504 err("error registering netdev: %d", retval);
505 retval = -EIO;
506 goto err_register_netdev;
507 }
508
509 dev_info(&intf->dev, "Apple iPhone USB Ethernet device attached\n");
510 return 0;
511
512err_register_netdev:
513 ipheth_free_urbs(dev);
514err_alloc_urbs:
515err_get_macaddr:
516err_alloc_ctrl_buf:
517 kfree(dev->ctrl_buf);
518err_endpoints:
519 free_netdev(netdev);
520 return retval;
521}
522
523static void ipheth_disconnect(struct usb_interface *intf)
524{
525 struct ipheth_device *dev;
526
527 dev = usb_get_intfdata(intf);
528 if (dev != NULL) {
529 unregister_netdev(dev->net);
530 ipheth_kill_urbs(dev);
531 ipheth_free_urbs(dev);
532 kfree(dev->ctrl_buf);
533 free_netdev(dev->net);
534 }
535 usb_set_intfdata(intf, NULL);
536 dev_info(&intf->dev, "Apple iPhone USB Ethernet now disconnected\n");
537}
538
539static struct usb_driver ipheth_driver = {
540 .name = "ipheth",
541 .probe = ipheth_probe,
542 .disconnect = ipheth_disconnect,
543 .id_table = ipheth_table,
544};
545
546static int __init ipheth_init(void)
547{
548 int retval;
549
550 retval = usb_register(&ipheth_driver);
551 if (retval) {
552 err("usb_register failed: %d", retval);
553 return retval;
554 }
555 return 0;
556}
557
558static void __exit ipheth_exit(void)
559{
560 usb_deregister(&ipheth_driver);
561}
562
563module_init(ipheth_init);
564module_exit(ipheth_exit);
565
566MODULE_AUTHOR("Diego Giagio <diego@giagio.com>");
567MODULE_DESCRIPTION("Apple iPhone USB Ethernet driver");
568MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index c4844adff92a..92b3e64fc14d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -259,7 +259,7 @@ static struct iwl_lib_ops iwl6000_lib = {
259 EEPROM_5000_REG_BAND_3_CHANNELS, 259 EEPROM_5000_REG_BAND_3_CHANNELS,
260 EEPROM_5000_REG_BAND_4_CHANNELS, 260 EEPROM_5000_REG_BAND_4_CHANNELS,
261 EEPROM_5000_REG_BAND_5_CHANNELS, 261 EEPROM_5000_REG_BAND_5_CHANNELS,
262 EEPROM_5000_REG_BAND_24_HT40_CHANNELS, 262 EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
263 EEPROM_5000_REG_BAND_52_HT40_CHANNELS 263 EEPROM_5000_REG_BAND_52_HT40_CHANNELS
264 }, 264 },
265 .verify_signature = iwlcore_eeprom_verify_signature, 265 .verify_signature = iwlcore_eeprom_verify_signature,
@@ -323,7 +323,7 @@ static struct iwl_lib_ops iwl6050_lib = {
323 EEPROM_5000_REG_BAND_3_CHANNELS, 323 EEPROM_5000_REG_BAND_3_CHANNELS,
324 EEPROM_5000_REG_BAND_4_CHANNELS, 324 EEPROM_5000_REG_BAND_4_CHANNELS,
325 EEPROM_5000_REG_BAND_5_CHANNELS, 325 EEPROM_5000_REG_BAND_5_CHANNELS,
326 EEPROM_5000_REG_BAND_24_HT40_CHANNELS, 326 EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
327 EEPROM_5000_REG_BAND_52_HT40_CHANNELS 327 EEPROM_5000_REG_BAND_52_HT40_CHANNELS
328 }, 328 },
329 .verify_signature = iwlcore_eeprom_verify_signature, 329 .verify_signature = iwlcore_eeprom_verify_signature,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 8b8e3e1cbb44..bdff56583e11 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -3331,6 +3331,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
3331 3331
3332 cancel_delayed_work_sync(&priv->init_alive_start); 3332 cancel_delayed_work_sync(&priv->init_alive_start);
3333 cancel_delayed_work(&priv->scan_check); 3333 cancel_delayed_work(&priv->scan_check);
3334 cancel_work_sync(&priv->start_internal_scan);
3334 cancel_delayed_work(&priv->alive_start); 3335 cancel_delayed_work(&priv->alive_start);
3335 cancel_work_sync(&priv->beacon_update); 3336 cancel_work_sync(&priv->beacon_update);
3336 del_timer_sync(&priv->statistics_periodic); 3337 del_timer_sync(&priv->statistics_periodic);
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 3352f7086632..049b652bcb5e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -3358,7 +3358,6 @@ static void iwl_force_rf_reset(struct iwl_priv *priv)
3358 */ 3358 */
3359 IWL_DEBUG_INFO(priv, "perform radio reset.\n"); 3359 IWL_DEBUG_INFO(priv, "perform radio reset.\n");
3360 iwl_internal_short_hw_scan(priv); 3360 iwl_internal_short_hw_scan(priv);
3361 return;
3362} 3361}
3363 3362
3364 3363
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 732590f5fe30..36940a9ec6b9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -506,7 +506,7 @@ void iwl_init_scan_params(struct iwl_priv *priv);
506int iwl_scan_cancel(struct iwl_priv *priv); 506int iwl_scan_cancel(struct iwl_priv *priv);
507int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); 507int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
508int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req); 508int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req);
509int iwl_internal_short_hw_scan(struct iwl_priv *priv); 509void iwl_internal_short_hw_scan(struct iwl_priv *priv);
510int iwl_force_reset(struct iwl_priv *priv, int mode); 510int iwl_force_reset(struct iwl_priv *priv, int mode);
511u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, 511u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
512 const u8 *ie, int ie_len, int left); 512 const u8 *ie, int ie_len, int left);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 6054c5fba0c1..ef1720a852e9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1296,6 +1296,7 @@ struct iwl_priv {
1296 struct work_struct tt_work; 1296 struct work_struct tt_work;
1297 struct work_struct ct_enter; 1297 struct work_struct ct_enter;
1298 struct work_struct ct_exit; 1298 struct work_struct ct_exit;
1299 struct work_struct start_internal_scan;
1299 1300
1300 struct tasklet_struct irq_tasklet; 1301 struct tasklet_struct irq_tasklet;
1301 1302
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index 4e1ba824dc50..8171c701e4e1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -203,6 +203,10 @@ struct iwl_eeprom_enhanced_txpwr {
203#define EEPROM_5000_REG_BAND_52_HT40_CHANNELS ((0x92)\ 203#define EEPROM_5000_REG_BAND_52_HT40_CHANNELS ((0x92)\
204 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ 204 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */
205 205
206/* 6000 regulatory - indirect access */
207#define EEPROM_6000_REG_BAND_24_HT40_CHANNELS ((0x80)\
208 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 14 bytes */
209
206/* 6000 and up regulatory tx power - indirect access */ 210/* 6000 and up regulatory tx power - indirect access */
207/* max. elements per section */ 211/* max. elements per section */
208#define EEPROM_MAX_TXPOWER_SECTION_ELEMENTS (8) 212#define EEPROM_MAX_TXPOWER_SECTION_ELEMENTS (8)
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 9ab0e412bf10..12e455a4b90e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -470,6 +470,8 @@ EXPORT_SYMBOL(iwl_init_scan_params);
470 470
471static int iwl_scan_initiate(struct iwl_priv *priv) 471static int iwl_scan_initiate(struct iwl_priv *priv)
472{ 472{
473 WARN_ON(!mutex_is_locked(&priv->mutex));
474
473 IWL_DEBUG_INFO(priv, "Starting scan...\n"); 475 IWL_DEBUG_INFO(priv, "Starting scan...\n");
474 set_bit(STATUS_SCANNING, &priv->status); 476 set_bit(STATUS_SCANNING, &priv->status);
475 priv->is_internal_short_scan = false; 477 priv->is_internal_short_scan = false;
@@ -547,24 +549,31 @@ EXPORT_SYMBOL(iwl_mac_hw_scan);
547 * internal short scan, this function should only been called while associated. 549 * internal short scan, this function should only been called while associated.
548 * It will reset and tune the radio to prevent possible RF related problem 550 * It will reset and tune the radio to prevent possible RF related problem
549 */ 551 */
550int iwl_internal_short_hw_scan(struct iwl_priv *priv) 552void iwl_internal_short_hw_scan(struct iwl_priv *priv)
551{ 553{
552 int ret = 0; 554 queue_work(priv->workqueue, &priv->start_internal_scan);
555}
556
557static void iwl_bg_start_internal_scan(struct work_struct *work)
558{
559 struct iwl_priv *priv =
560 container_of(work, struct iwl_priv, start_internal_scan);
561
562 mutex_lock(&priv->mutex);
553 563
554 if (!iwl_is_ready_rf(priv)) { 564 if (!iwl_is_ready_rf(priv)) {
555 ret = -EIO;
556 IWL_DEBUG_SCAN(priv, "not ready or exit pending\n"); 565 IWL_DEBUG_SCAN(priv, "not ready or exit pending\n");
557 goto out; 566 goto unlock;
558 } 567 }
568
559 if (test_bit(STATUS_SCANNING, &priv->status)) { 569 if (test_bit(STATUS_SCANNING, &priv->status)) {
560 IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); 570 IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
561 ret = -EAGAIN; 571 goto unlock;
562 goto out;
563 } 572 }
573
564 if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { 574 if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
565 IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n"); 575 IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n");
566 ret = -EAGAIN; 576 goto unlock;
567 goto out;
568 } 577 }
569 578
570 priv->scan_bands = 0; 579 priv->scan_bands = 0;
@@ -577,9 +586,8 @@ int iwl_internal_short_hw_scan(struct iwl_priv *priv)
577 set_bit(STATUS_SCANNING, &priv->status); 586 set_bit(STATUS_SCANNING, &priv->status);
578 priv->is_internal_short_scan = true; 587 priv->is_internal_short_scan = true;
579 queue_work(priv->workqueue, &priv->request_scan); 588 queue_work(priv->workqueue, &priv->request_scan);
580 589 unlock:
581out: 590 mutex_unlock(&priv->mutex);
582 return ret;
583} 591}
584EXPORT_SYMBOL(iwl_internal_short_hw_scan); 592EXPORT_SYMBOL(iwl_internal_short_hw_scan);
585 593
@@ -965,6 +973,7 @@ void iwl_setup_scan_deferred_work(struct iwl_priv *priv)
965 INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); 973 INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed);
966 INIT_WORK(&priv->request_scan, iwl_bg_request_scan); 974 INIT_WORK(&priv->request_scan, iwl_bg_request_scan);
967 INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); 975 INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);
976 INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan);
968 INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); 977 INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
969} 978}
970EXPORT_SYMBOL(iwl_setup_scan_deferred_work); 979EXPORT_SYMBOL(iwl_setup_scan_deferred_work);