diff options
Diffstat (limited to 'drivers/net/wimax')
23 files changed, 222 insertions, 1796 deletions
diff --git a/drivers/net/wimax/i2400m/Kconfig b/drivers/net/wimax/i2400m/Kconfig index 3f703384295..71453db1425 100644 --- a/drivers/net/wimax/i2400m/Kconfig +++ b/drivers/net/wimax/i2400m/Kconfig @@ -7,9 +7,6 @@ config WIMAX_I2400M  comment "Enable USB support to see WiMAX USB drivers"  	depends on USB = n -comment "Enable MMC support to see WiMAX SDIO drivers" -	depends on MMC = n -  config WIMAX_I2400M_USB  	tristate "Intel Wireless WiMAX Connection 2400 over USB (including 5x50)"  	depends on WIMAX && USB @@ -21,24 +18,6 @@ config WIMAX_I2400M_USB  	  If unsure, it is safe to select M (module). -config WIMAX_I2400M_SDIO -	tristate "Intel Wireless WiMAX Connection 2400 over SDIO" -	depends on WIMAX && MMC -	select WIMAX_I2400M -	help -	  Select if you have a device based on the Intel WiMAX -	  Connection 2400 over SDIO. - -	  If unsure, it is safe to select M (module). - -config WIMAX_IWMC3200_SDIO -	bool "Intel Wireless Multicom WiMAX Connection 3200 over SDIO" -	depends on WIMAX_I2400M_SDIO -	select IWMC3200TOP -	help -	  Select if you have a device based on the Intel Multicom WiMAX -          Connection 3200 over SDIO. -  config WIMAX_I2400M_DEBUG_LEVEL  	int "WiMAX i2400m debug level"  	depends on WIMAX_I2400M diff --git a/drivers/net/wimax/i2400m/Makefile b/drivers/net/wimax/i2400m/Makefile index 5d9e018d31a..f6d19c34808 100644 --- a/drivers/net/wimax/i2400m/Makefile +++ b/drivers/net/wimax/i2400m/Makefile @@ -1,7 +1,6 @@  obj-$(CONFIG_WIMAX_I2400M) += i2400m.o  obj-$(CONFIG_WIMAX_I2400M_USB) += i2400m-usb.o -obj-$(CONFIG_WIMAX_I2400M_SDIO) += i2400m-sdio.o  i2400m-y :=		\  	control.o	\ @@ -21,10 +20,3 @@ i2400m-usb-y :=			\  	usb-tx.o		\  	usb-rx.o		\  	usb.o - - -i2400m-sdio-y := 		\ -	sdio.o      		\ -	sdio-tx.o   		\ -	sdio-fw.o	 	\ -	sdio-rx.o diff --git a/drivers/net/wimax/i2400m/control.c b/drivers/net/wimax/i2400m/control.c index 12b84ed0e38..4c417903e9b 100644 --- a/drivers/net/wimax/i2400m/control.c +++ b/drivers/net/wimax/i2400m/control.c @@ -78,6 +78,8 @@  #include <linux/kernel.h>  #include <linux/slab.h>  #include <linux/wimax/i2400m.h> +#include <linux/export.h> +#include <linux/moduleparam.h>  #define D_SUBMODULE control @@ -128,7 +130,7 @@ ssize_t i2400m_tlv_match(const struct i2400m_tlv_hdr *tlv,  	    && le16_to_cpu(tlv->length) + sizeof(*tlv) != tlv_size) {  		size_t size = le16_to_cpu(tlv->length) + sizeof(*tlv);  		printk(KERN_WARNING "W: tlv type 0x%x mismatched because of " -		       "size (got %zu vs %zu expected)\n", +		       "size (got %zu vs %zd expected)\n",  		       tlv_type, size, tlv_size);  		return size;  	} @@ -233,7 +235,7 @@ const struct i2400m_tlv_hdr *i2400m_tlv_find(  			break;  		if (match > 0)  			dev_warn(dev, "TLV type 0x%04x found with size " -				 "mismatch (%zu vs %zu needed)\n", +				 "mismatch (%zu vs %zd needed)\n",  				 tlv_type, match, tlv_size);  	}  	return tlv; @@ -378,7 +380,7 @@ void i2400m_report_tlv_system_state(struct i2400m *i2400m,   * the device's state as sometimes we need to do a link-renew (the BS   * wants us to renew a DHCP lease, for example).   * - * In fact, doc says that everytime we get a link-up, we should do a + * In fact, doc says that every time we get a link-up, we should do a   * DHCP negotiation...   */  static @@ -675,7 +677,7 @@ void i2400m_msg_to_dev_cancel_wait(struct i2400m *i2400m, int code)   *  - the ack message wasn't formatted correctly   *   * The returned skb has been allocated with wimax_msg_to_user_alloc(), - * it contains the reponse in a netlink attribute and is ready to be + * it contains the response in a netlink attribute and is ready to be   * passed up to user space with wimax_msg_to_user_send(). To access   * the payload and its length, use wimax_msg_{data,len}() on the skb.   * @@ -1059,7 +1061,7 @@ int i2400m_firmware_check(struct i2400m *i2400m)  		goto error_bad_major;  	}  	result = 0; -	if (minor < I2400M_HDIv_MINOR_2 && minor > I2400M_HDIv_MINOR) +	if (minor > I2400M_HDIv_MINOR_2 || minor < I2400M_HDIv_MINOR)  		dev_warn(dev, "untested minor fw version %u.%u.%u\n",  			 major, minor, branch);  	/* Yes, we ignore the branch -- we don't have to track it */ diff --git a/drivers/net/wimax/i2400m/debugfs.c b/drivers/net/wimax/i2400m/debugfs.c index 9c70b5fa3f5..6702da838b0 100644 --- a/drivers/net/wimax/i2400m/debugfs.c +++ b/drivers/net/wimax/i2400m/debugfs.c @@ -26,6 +26,7 @@  #include <linux/etherdevice.h>  #include <linux/spinlock.h>  #include <linux/device.h> +#include <linux/export.h>  #include "i2400m.h" @@ -52,17 +53,6 @@ struct dentry *debugfs_create_netdev_queue_stopped(  				   &fops_netdev_queue_stopped);  } - -/* - * inode->i_private has the @data argument to debugfs_create_file() - */ -static -int i2400m_stats_open(struct inode *inode, struct file *filp) -{ -	filp->private_data = inode->i_private; -	return 0; -} -  /*   * We don't allow partial reads of this file, as then the reader would   * get weirdly confused data as it is updated. @@ -116,7 +106,7 @@ ssize_t i2400m_rx_stats_write(struct file *filp, const char __user *buffer,  static  const struct file_operations i2400m_rx_stats_fops = {  	.owner =	THIS_MODULE, -	.open =		i2400m_stats_open, +	.open =		simple_open,  	.read =		i2400m_rx_stats_read,  	.write =	i2400m_rx_stats_write,  	.llseek =	default_llseek, @@ -169,7 +159,7 @@ ssize_t i2400m_tx_stats_write(struct file *filp, const char __user *buffer,  static  const struct file_operations i2400m_tx_stats_fops = {  	.owner =	THIS_MODULE, -	.open =		i2400m_stats_open, +	.open =		simple_open,  	.read =		i2400m_tx_stats_read,  	.write =	i2400m_tx_stats_write,  	.llseek =	default_llseek, @@ -219,6 +209,7 @@ int debugfs_i2400m_reset_set(void *data, u64 val)  		result = i2400m_reset(i2400m, rt);  		if (result >= 0)  			result = 0; +		break;  	default:  		result = -EINVAL;  	} diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c index cdedab46ba2..9c78090e72f 100644 --- a/drivers/net/wimax/i2400m/driver.c +++ b/drivers/net/wimax/i2400m/driver.c @@ -92,54 +92,6 @@ MODULE_PARM_DESC(barkers,  		 "signal; values are appended to a list--setting one value "  		 "as zero cleans the existing list and starts a new one."); -static -struct i2400m_work *__i2400m_work_setup( -	struct i2400m *i2400m, void (*fn)(struct work_struct *), -	gfp_t gfp_flags, const void *pl, size_t pl_size) -{ -	struct i2400m_work *iw; - -	iw = kzalloc(sizeof(*iw) + pl_size, gfp_flags); -	if (iw == NULL) -		return NULL; -	iw->i2400m = i2400m_get(i2400m); -	iw->pl_size = pl_size; -	memcpy(iw->pl, pl, pl_size); -	INIT_WORK(&iw->ws, fn); -	return iw; -} - - -/* - * Schedule i2400m's specific work on the system's queue. - * - * Used for a few cases where we really need it; otherwise, identical - * to i2400m_queue_work(). - * - * Returns < 0 errno code on error, 1 if ok. - * - * If it returns zero, something really bad happened, as it means the - * works struct was already queued, but we have just allocated it, so - * it should not happen. - */ -static int i2400m_schedule_work(struct i2400m *i2400m, -			 void (*fn)(struct work_struct *), gfp_t gfp_flags, -			 const void *pl, size_t pl_size) -{ -	int result; -	struct i2400m_work *iw; - -	result = -ENOMEM; -	iw = __i2400m_work_setup(i2400m, fn, gfp_flags, pl, pl_size); -	if (iw != NULL) { -		result = schedule_work(&iw->ws); -		if (WARN_ON(result == 0)) -			result = -ENXIO; -	} -	return result; -} - -  /*   * WiMAX stack operation: relay a message from user space   * @@ -270,7 +222,6 @@ int i2400m_check_mac_addr(struct i2400m *i2400m)  	struct sk_buff *skb;  	const struct i2400m_tlv_detailed_device_info *ddi;  	struct net_device *net_dev = i2400m->wimax_dev.net_dev; -	const unsigned char zeromac[ETH_ALEN] = { 0 };  	d_fnstart(3, dev, "(i2400m %p)\n", i2400m);  	skb = i2400m_get_device_info(i2400m); @@ -280,7 +231,7 @@ int i2400m_check_mac_addr(struct i2400m *i2400m)  			result);  		goto error;  	} -	/* Extract MAC addresss */ +	/* Extract MAC address */  	ddi = (void *) skb->data;  	BUILD_BUG_ON(ETH_ALEN != sizeof(ddi->mac_address));  	d_printf(2, dev, "GET DEVICE INFO: mac addr %pM\n", @@ -292,7 +243,7 @@ int i2400m_check_mac_addr(struct i2400m *i2400m)  		 "to that of boot mode's\n");  	dev_warn(dev, "device reports     %pM\n", ddi->mac_address);  	dev_warn(dev, "boot mode reported %pM\n", net_dev->perm_addr); -	if (!memcmp(zeromac, ddi->mac_address, sizeof(zeromac))) +	if (is_zero_ether_addr(ddi->mac_address))  		dev_err(dev, "device reports an invalid MAC address, "  			"not updating\n");  	else { @@ -549,26 +500,23 @@ int i2400m_pm_notifier(struct notifier_block *notifier,   */  int i2400m_pre_reset(struct i2400m *i2400m)  { -	int result;  	struct device *dev = i2400m_dev(i2400m);  	d_fnstart(3, dev, "(i2400m %p)\n", i2400m);  	d_printf(1, dev, "pre-reset shut down\n"); -	result = 0;  	mutex_lock(&i2400m->init_mutex);  	if (i2400m->updown) {  		netif_tx_disable(i2400m->wimax_dev.net_dev);  		__i2400m_dev_stop(i2400m); -		result = 0;  		/* down't set updown to zero -- this way  		 * post_reset can restore properly */  	}  	mutex_unlock(&i2400m->init_mutex);  	if (i2400m->bus_release)  		i2400m->bus_release(i2400m); -	d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result); -	return result; +	d_fnend(3, dev, "(i2400m %p) = 0\n", i2400m); +	return 0;  }  EXPORT_SYMBOL_GPL(i2400m_pre_reset); @@ -648,17 +596,11 @@ EXPORT_SYMBOL_GPL(i2400m_post_reset);  static  void __i2400m_dev_reset_handle(struct work_struct *ws)  { -	int result; -	struct i2400m_work *iw = container_of(ws, struct i2400m_work, ws); -	const char *reason; -	struct i2400m *i2400m = iw->i2400m; +	struct i2400m *i2400m = container_of(ws, struct i2400m, reset_ws); +	const char *reason = i2400m->reset_reason;  	struct device *dev = i2400m_dev(i2400m);  	struct i2400m_reset_ctx *ctx = i2400m->reset_ctx; - -	if (WARN_ON(iw->pl_size != sizeof(reason))) -		reason = "SW BUG: reason n/a"; -	else -		memcpy(&reason, iw->pl, sizeof(reason)); +	int result;  	d_fnstart(3, dev, "(ws %p i2400m %p reason %s)\n", ws, i2400m, reason); @@ -708,7 +650,7 @@ void __i2400m_dev_reset_handle(struct work_struct *ws)  	if (result == -EUCLEAN) {  		/*  		 * We come here because the reset during operational mode -		 * wasn't successully done and need to proceed to a bus +		 * wasn't successfully done and need to proceed to a bus  		 * reset. For the dev_reset_handle() to be able to handle  		 * the reset event later properly, we restore boot_mode back  		 * to the state before previous reset. ie: just like we are @@ -733,8 +675,6 @@ void __i2400m_dev_reset_handle(struct work_struct *ws)  		}  	}  out: -	i2400m_put(i2400m); -	kfree(iw);  	d_fnend(3, dev, "(ws %p i2400m %p reason %s) = void\n",  		ws, i2400m, reason);  } @@ -754,8 +694,8 @@ out:   */  int i2400m_dev_reset_handle(struct i2400m *i2400m, const char *reason)  { -	return i2400m_schedule_work(i2400m, __i2400m_dev_reset_handle, -				    GFP_ATOMIC, &reason, sizeof(reason)); +	i2400m->reset_reason = reason; +	return schedule_work(&i2400m->reset_ws);  }  EXPORT_SYMBOL_GPL(i2400m_dev_reset_handle); @@ -768,14 +708,9 @@ EXPORT_SYMBOL_GPL(i2400m_dev_reset_handle);  static  void __i2400m_error_recovery(struct work_struct *ws)  { -	struct i2400m_work *iw = container_of(ws, struct i2400m_work, ws); -	struct i2400m *i2400m = iw->i2400m; +	struct i2400m *i2400m = container_of(ws, struct i2400m, recovery_ws);  	i2400m_reset(i2400m, I2400M_RT_BUS); - -	i2400m_put(i2400m); -	kfree(iw); -	return;  }  /* @@ -805,26 +740,17 @@ void __i2400m_error_recovery(struct work_struct *ws)   */  void i2400m_error_recovery(struct i2400m *i2400m)  { -	struct device *dev = i2400m_dev(i2400m); - -	if (atomic_add_return(1, &i2400m->error_recovery) == 1) { -		if (i2400m_schedule_work(i2400m, __i2400m_error_recovery, -			GFP_ATOMIC, NULL, 0) < 0) { -			dev_err(dev, "run out of memory for " -				"scheduling an error recovery ?\n"); -			atomic_dec(&i2400m->error_recovery); -		} -	} else +	if (atomic_add_return(1, &i2400m->error_recovery) == 1) +		schedule_work(&i2400m->recovery_ws); +	else  		atomic_dec(&i2400m->error_recovery); -	return;  }  EXPORT_SYMBOL_GPL(i2400m_error_recovery);  /*   * Alloc the command and ack buffers for boot mode   * - * Get the buffers needed to deal with boot mode messages.  These - * buffers need to be allocated before the sdio recieve irq is setup. + * Get the buffers needed to deal with boot mode messages.   */  static  int i2400m_bm_buf_alloc(struct i2400m *i2400m) @@ -886,6 +812,10 @@ void i2400m_init(struct i2400m *i2400m)  	mutex_init(&i2400m->init_mutex);  	/* wake_tx_ws is initialized in i2400m_tx_setup() */ + +	INIT_WORK(&i2400m->reset_ws, __i2400m_dev_reset_handle); +	INIT_WORK(&i2400m->recovery_ws, __i2400m_error_recovery); +  	atomic_set(&i2400m->bus_reset_retries, 0);  	i2400m->alive = 0; @@ -962,7 +892,7 @@ int i2400m_setup(struct i2400m *i2400m, enum i2400m_bri bm_flags)  	result = i2400m_read_mac_addr(i2400m);  	if (result < 0)  		goto error_read_mac_addr; -	random_ether_addr(i2400m->src_mac_addr); +	eth_random_addr(i2400m->src_mac_addr);  	i2400m->pm_notifier.notifier_call = i2400m_pm_notifier;  	register_pm_notifier(&i2400m->pm_notifier); @@ -1040,6 +970,9 @@ void i2400m_release(struct i2400m *i2400m)  	i2400m_dev_stop(i2400m); +	cancel_work_sync(&i2400m->reset_ws); +	cancel_work_sync(&i2400m->recovery_ws); +  	i2400m_debugfs_rm(i2400m);  	sysfs_remove_group(&i2400m->wimax_dev.net_dev->dev.kobj,  			   &i2400m_dev_attr_group); @@ -1083,8 +1016,6 @@ module_init(i2400m_driver_init);  static  void __exit i2400m_driver_exit(void)  { -	/* for scheds i2400m_dev_reset_handle() */ -	flush_scheduled_work();  	i2400m_barker_db_exit();  }  module_exit(i2400m_driver_exit); diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c index 8b55a5b1415..c9c711dcd0e 100644 --- a/drivers/net/wimax/i2400m/fw.c +++ b/drivers/net/wimax/i2400m/fw.c @@ -51,10 +51,9 @@   * firmware. Normal hardware takes only signed firmware.   *   * On boot mode, in USB, we write to the device using the bulk out - * endpoint and read from it in the notification endpoint. In SDIO we - * talk to it via the write address and read from the read address. + * endpoint and read from it in the notification endpoint.   * - * Upon entrance to boot mode, the device sends (preceeded with a few + * Upon entrance to boot mode, the device sends (preceded with a few   * zero length packets (ZLPs) on the notification endpoint in USB) a   * reboot barker (4 le32 words with the same value). We ack it by   * sending the same barker to the device. The device acks with a @@ -158,6 +157,7 @@  #include <linux/sched.h>  #include <linux/slab.h>  #include <linux/usb.h> +#include <linux/export.h>  #include "i2400m.h" @@ -326,8 +326,10 @@ int i2400m_barker_db_init(const char *_options)  		unsigned barker;  		options_orig = kstrdup(_options, GFP_KERNEL); -		if (options_orig == NULL) +		if (options_orig == NULL) { +			result = -ENOMEM;  			goto error_parse; +		}  		options = options_orig;  		while ((token = strsep(&options, ",")) != NULL) { @@ -1053,7 +1055,6 @@ int i2400m_read_mac_addr(struct i2400m *i2400m)  		result = 0;  	}  	net_dev->addr_len = ETH_ALEN; -	memcpy(net_dev->perm_addr, ack_buf.ack_pl, ETH_ALEN);  	memcpy(net_dev->dev_addr, ack_buf.ack_pl, ETH_ALEN);  error_read_mac:  	d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, result); @@ -1267,7 +1268,7 @@ int i2400m_fw_check(struct i2400m *i2400m, const void *bcf, size_t bcf_size)  		size_t leftover, offset, header_len, size;  		leftover = top - itr; -		offset = itr - (const void *) bcf; +		offset = itr - bcf;  		if (leftover <= sizeof(*bcf_hdr)) {  			dev_err(dev, "firmware %s: %zu B left at @%zx, "  				"not enough for BCF header\n", @@ -1589,7 +1590,7 @@ int i2400m_dev_bootstrap(struct i2400m *i2400m, enum i2400m_bri flags)  		i2400m->fw_name = fw_name;  		ret = i2400m_fw_bootstrap(i2400m, fw, flags);  		release_firmware(fw); -		if (ret >= 0)	/* firmware loaded succesfully */ +		if (ret >= 0)	/* firmware loaded successfully */  			break;  		i2400m->fw_name = NULL;  	} diff --git a/drivers/net/wimax/i2400m/i2400m-sdio.h b/drivers/net/wimax/i2400m/i2400m-sdio.h deleted file mode 100644 index 1d63ffdedfd..00000000000 --- a/drivers/net/wimax/i2400m/i2400m-sdio.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Intel Wireless WiMAX Connection 2400m - * SDIO-specific i2400m driver definitions - * - * - * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - *   * Redistributions of source code must retain the above copyright - *     notice, this list of conditions and the following disclaimer. - *   * 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. - *   * Neither the name of Intel Corporation nor the names of its - *     contributors may be used to endorse or promote products derived - *     from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "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 THE COPYRIGHT - * OWNER OR CONTRIBUTORS 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. - * - * - * Intel Corporation <linux-wimax@intel.com> - * Brian Bian <brian.bian@intel.com> - * Dirk Brandewie <dirk.j.brandewie@intel.com> - * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> - * Yanir Lubetkin <yanirx.lubetkin@intel.com> - *  - Initial implementation - * - * - * This driver implements the bus-specific part of the i2400m for - * SDIO. Check i2400m.h for a generic driver description. - * - * ARCHITECTURE - * - * This driver sits under the bus-generic i2400m driver, providing the - * connection to the device. - * - * When probed, all the function pointers are setup and then the - * bus-generic code called. The generic driver will then use the - * provided pointers for uploading firmware (i2400ms_bus_bm*() in - * sdio-fw.c) and then setting up the device (i2400ms_dev_*() in - * sdio.c). - * - * Once firmware is uploaded, TX functions (sdio-tx.c) are called when - * data is ready for transmission in the TX fifo; then the SDIO IRQ is - * fired and data is available (sdio-rx.c), it is sent to the generic - * driver for processing with i2400m_rx. - */ - -#ifndef __I2400M_SDIO_H__ -#define __I2400M_SDIO_H__ - -#include "i2400m.h" - -/* Host-Device interface for SDIO */ -enum { -	I2400M_SDIO_BOOT_RETRIES = 3, -	I2400MS_BLK_SIZE = 256, -	I2400MS_PL_SIZE_MAX = 0x3E00, - -	I2400MS_DATA_ADDR = 0x0, -	I2400MS_INTR_STATUS_ADDR = 0x13, -	I2400MS_INTR_CLEAR_ADDR = 0x13, -	I2400MS_INTR_ENABLE_ADDR = 0x14, -	I2400MS_INTR_GET_SIZE_ADDR = 0x2C, -	/* The number of ticks to wait for the device to signal that -	 * it is ready */ -	I2400MS_INIT_SLEEP_INTERVAL = 100, -	/* How long to wait for the device to settle after reset */ -	I2400MS_SETTLE_TIME = 40, -	/* The number of msec to wait for IOR after sending IOE */ -	IWMC3200_IOR_TIMEOUT = 10, -}; - - -/** - * struct i2400ms - descriptor for a SDIO connected i2400m - * - * @i2400m: bus-generic i2400m implementation; has to be first (see - *     it's documentation in i2400m.h). - * - * @func: pointer to our SDIO function - * - * @tx_worker: workqueue struct used to TX data when the bus-generic - *     code signals packets are pending for transmission to the device. - * - * @tx_workqueue: workqeueue used for data TX; we don't use the - *     system's workqueue as that might cause deadlocks with code in - *     the bus-generic driver. The read/write operation to the queue - *     is protected with spinlock (tx_lock in struct i2400m) to avoid - *     the queue being destroyed in the middle of a the queue read/write - *     operation. - * - * @debugfs_dentry: dentry for the SDIO specific debugfs files - * - *     Note this value is set to NULL upon destruction; this is - *     because some routinges use it to determine if we are inside the - *     probe() path or some other path. When debugfs is disabled, - *     creation sets the dentry to '(void*) -ENODEV', which is valid - *     for the test. - */ -struct i2400ms { -	struct i2400m i2400m;		/* FIRST! See doc */ -	struct sdio_func *func; - -	struct work_struct tx_worker; -	struct workqueue_struct *tx_workqueue; -	char tx_wq_name[32]; - -	struct dentry *debugfs_dentry; - -	wait_queue_head_t bm_wfa_wq; -	int bm_wait_result; -	size_t bm_ack_size; - -	/* Device is any of the iwmc3200 SKUs */ -	unsigned iwmc3200:1; -}; - - -static inline -void i2400ms_init(struct i2400ms *i2400ms) -{ -	i2400m_init(&i2400ms->i2400m); -} - - -extern int i2400ms_rx_setup(struct i2400ms *); -extern void i2400ms_rx_release(struct i2400ms *); - -extern int i2400ms_tx_setup(struct i2400ms *); -extern void i2400ms_tx_release(struct i2400ms *); -extern void i2400ms_bus_tx_kick(struct i2400m *); - -extern ssize_t i2400ms_bus_bm_cmd_send(struct i2400m *, -				       const struct i2400m_bootrom_header *, -				       size_t, int); -extern ssize_t i2400ms_bus_bm_wait_for_ack(struct i2400m *, -					   struct i2400m_bootrom_header *, -					   size_t); -extern void i2400ms_bus_bm_release(struct i2400m *); -extern int i2400ms_bus_bm_setup(struct i2400m *); - -#endif /* #ifndef __I2400M_SDIO_H__ */ diff --git a/drivers/net/wimax/i2400m/i2400m-usb.h b/drivers/net/wimax/i2400m/i2400m-usb.h index eb80243e22d..649ecad6844 100644 --- a/drivers/net/wimax/i2400m/i2400m-usb.h +++ b/drivers/net/wimax/i2400m/i2400m-usb.h @@ -105,14 +105,14 @@ static inline void edc_init(struct edc *edc)   *   * @edc: pointer to error density counter.   * @max_err: maximum number of errors we can accept over the timeframe - * @timeframe: lenght of the timeframe (in jiffies). + * @timeframe: length of the timeframe (in jiffies).   *   * Returns: !0 1 if maximum acceptable errors per timeframe has been   *     exceeded. 0 otherwise.   *   * This is way to determine if the number of acceptable errors per time   * period has been exceeded. It is not accurate as there are cases in which - * this scheme will not work, for example if there are periodic occurences + * this scheme will not work, for example if there are periodic occurrences   * of errors that straddle updates to the start time. This scheme is   * sufficient for our usage.   * @@ -152,6 +152,9 @@ enum {  	/* Device IDs */  	USB_DEVICE_ID_I6050 = 0x0186,  	USB_DEVICE_ID_I6050_2 = 0x0188, +	USB_DEVICE_ID_I6150 = 0x07d6, +	USB_DEVICE_ID_I6150_2 = 0x07d7, +	USB_DEVICE_ID_I6150_3 = 0x07d9,  	USB_DEVICE_ID_I6250 = 0x0187,  }; @@ -204,7 +207,7 @@ enum {   *     usb_autopm_get/put_interface() barriers when executing   *     commands. See doc in i2400mu_suspend() for more information.   * - * @rx_size_auto_shrink: if true, the rx_size is shrinked + * @rx_size_auto_shrink: if true, the rx_size is shrunk   *     automatically based on the average size of the received   *     transactions. This allows the receive code to allocate smaller   *     chunks of memory and thus reduce pressure on the memory @@ -253,21 +256,20 @@ void i2400mu_init(struct i2400mu *i2400mu)  	i2400mu->rx_size_auto_shrink = 1;  } -extern int i2400mu_notification_setup(struct i2400mu *); -extern void i2400mu_notification_release(struct i2400mu *); +int i2400mu_notification_setup(struct i2400mu *); +void i2400mu_notification_release(struct i2400mu *); -extern int i2400mu_rx_setup(struct i2400mu *); -extern void i2400mu_rx_release(struct i2400mu *); -extern void i2400mu_rx_kick(struct i2400mu *); +int i2400mu_rx_setup(struct i2400mu *); +void i2400mu_rx_release(struct i2400mu *); +void i2400mu_rx_kick(struct i2400mu *); -extern int i2400mu_tx_setup(struct i2400mu *); -extern void i2400mu_tx_release(struct i2400mu *); -extern void i2400mu_bus_tx_kick(struct i2400m *); +int i2400mu_tx_setup(struct i2400mu *); +void i2400mu_tx_release(struct i2400mu *); +void i2400mu_bus_tx_kick(struct i2400m *); -extern ssize_t i2400mu_bus_bm_cmd_send(struct i2400m *, -				       const struct i2400m_bootrom_header *, -				       size_t, int); -extern ssize_t i2400mu_bus_bm_wait_for_ack(struct i2400m *, -					   struct i2400m_bootrom_header *, -					   size_t); +ssize_t i2400mu_bus_bm_cmd_send(struct i2400m *, +				const struct i2400m_bootrom_header *, size_t, +				int); +ssize_t i2400mu_bus_bm_wait_for_ack(struct i2400m *, +				    struct i2400m_bootrom_header *, size_t);  #endif /* #ifndef __I2400M_USB_H__ */ diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h index 59ac7705e76..5a34e72bab9 100644 --- a/drivers/net/wimax/i2400m/i2400m.h +++ b/drivers/net/wimax/i2400m/i2400m.h @@ -46,7 +46,7 @@   *  - bus generic driver (this part)   *   * The bus specific driver sets up stuff specific to the bus the - * device is connected to (USB, SDIO, PCI, tam-tam...non-authoritative + * device is connected to (USB, PCI, tam-tam...non-authoritative   * nor binding list) which is basically the device-model management   * (probe/disconnect, etc), moving data from device to kernel and   * back, doing the power saving details and reseting the device. @@ -75,7 +75,7 @@   *        device is up and running or shutdown (through ifconfig up /   *        down). Bus-generic only.   * - *  - control ops: control.c - implements various commmands for + *  - control ops: control.c - implements various commands for   *        controlling the device. bus-generic only.   *   *  - device model glue: driver.c - implements helpers for the @@ -155,7 +155,7 @@  #include <linux/netdevice.h>  #include <linux/completion.h>  #include <linux/rwsem.h> -#include <asm/atomic.h> +#include <linux/atomic.h>  #include <net/wimax.h>  #include <linux/wimax/i2400m.h>  #include <asm/byteorder.h> @@ -186,7 +186,7 @@ enum {   * struct i2400m_poke_table - Hardware poke table for the Intel 2400m   *   * This structure will be used to create a device specific poke table - * to put the device in a consistant state at boot time. + * to put the device in a consistent state at boot time.   *   * @address: The device address to poke   * @@ -238,14 +238,13 @@ struct i2400m_barker_db;   * amount needed for loading firmware, where us dev_start/stop setup   * the rest needed to do full data/control traffic.   * - * @bus_tx_block_size: [fill] SDIO imposes a 256 block size, USB 16, - *     so we have a tx_blk_size variable that the bus layer sets to - *     tell the engine how much of that we need. + * @bus_tx_block_size: [fill] USB imposes a 16 block size, but other + *     busses will differ.  So we have a tx_blk_size variable that the + *     bus layer sets to tell the engine how much of that we need.   *   * @bus_tx_room_min: [fill] Minimum room required while allocating - *     TX queue's buffer space for message header. SDIO requires - *     224 bytes and USB 16 bytes. Refer bus specific driver code - *     for details. + *     TX queue's buffer space for message header. USB requires + *     16 bytes. Refer to bus specific driver code for details.   *   * @bus_pl_size_max: [fill] Maximum payload size.   * @@ -526,7 +525,7 @@ struct i2400m_barker_db;   *   * @barker: barker type that the device uses; this is initialized by   *     i2400m_is_boot_barker() the first time it is called. Then it - *     won't change during the life cycle of the device and everytime + *     won't change during the life cycle of the device and every time   *     a boot barker is received, it is just verified for it being the   *     same.   * @@ -632,6 +631,11 @@ struct i2400m {  	struct work_struct wake_tx_ws;  	struct sk_buff *wake_tx_skb; +	struct work_struct reset_ws; +	const char *reset_reason; + +	struct work_struct recovery_ws; +  	struct dentry *debugfs_dentry;  	const char *fw_name;		/* name of the current firmware image */  	unsigned long fw_version;	/* version of the firmware interface */ @@ -698,7 +702,7 @@ enum i2400m_bm_cmd_flags {   * @I2400M_BRI_MAC_REINIT: We need to reinitialize the boot   *     rom after reading the MAC address. This is quite a dirty hack,   *     if you ask me -- the device requires the bootrom to be - *     intialized after reading the MAC address. + *     initialized after reading the MAC address.   */  enum i2400m_bri {  	I2400M_BRI_SOFT       = 1 << 1, @@ -706,18 +710,18 @@ enum i2400m_bri {  	I2400M_BRI_MAC_REINIT = 1 << 3,  }; -extern void i2400m_bm_cmd_prepare(struct i2400m_bootrom_header *); -extern int i2400m_dev_bootstrap(struct i2400m *, enum i2400m_bri); -extern int i2400m_read_mac_addr(struct i2400m *); -extern int i2400m_bootrom_init(struct i2400m *, enum i2400m_bri); -extern int i2400m_is_boot_barker(struct i2400m *, const void *, size_t); +void i2400m_bm_cmd_prepare(struct i2400m_bootrom_header *); +int i2400m_dev_bootstrap(struct i2400m *, enum i2400m_bri); +int i2400m_read_mac_addr(struct i2400m *); +int i2400m_bootrom_init(struct i2400m *, enum i2400m_bri); +int i2400m_is_boot_barker(struct i2400m *, const void *, size_t);  static inline  int i2400m_is_d2h_barker(const void *buf)  {  	const __le32 *barker = buf;  	return le32_to_cpu(*barker) == I2400M_D2H_MSG_BARKER;  } -extern void i2400m_unknown_barker(struct i2400m *, const void *, size_t); +void i2400m_unknown_barker(struct i2400m *, const void *, size_t);  /* Make/grok boot-rom header commands */ @@ -785,32 +789,31 @@ unsigned i2400m_brh_get_signature(const struct i2400m_bootrom_header *hdr)  /*   * Driver / device setup and internal functions   */ -extern void i2400m_init(struct i2400m *); -extern int i2400m_reset(struct i2400m *, enum i2400m_reset_type); -extern void i2400m_netdev_setup(struct net_device *net_dev); -extern int i2400m_sysfs_setup(struct device_driver *); -extern void i2400m_sysfs_release(struct device_driver *); -extern int i2400m_tx_setup(struct i2400m *); -extern void i2400m_wake_tx_work(struct work_struct *); -extern void i2400m_tx_release(struct i2400m *); - -extern int i2400m_rx_setup(struct i2400m *); -extern void i2400m_rx_release(struct i2400m *); - -extern void i2400m_fw_cache(struct i2400m *); -extern void i2400m_fw_uncache(struct i2400m *); - -extern void i2400m_net_rx(struct i2400m *, struct sk_buff *, unsigned, -			  const void *, int); -extern void i2400m_net_erx(struct i2400m *, struct sk_buff *, -			   enum i2400m_cs); -extern void i2400m_net_wake_stop(struct i2400m *); +void i2400m_init(struct i2400m *); +int i2400m_reset(struct i2400m *, enum i2400m_reset_type); +void i2400m_netdev_setup(struct net_device *net_dev); +int i2400m_sysfs_setup(struct device_driver *); +void i2400m_sysfs_release(struct device_driver *); +int i2400m_tx_setup(struct i2400m *); +void i2400m_wake_tx_work(struct work_struct *); +void i2400m_tx_release(struct i2400m *); + +int i2400m_rx_setup(struct i2400m *); +void i2400m_rx_release(struct i2400m *); + +void i2400m_fw_cache(struct i2400m *); +void i2400m_fw_uncache(struct i2400m *); + +void i2400m_net_rx(struct i2400m *, struct sk_buff *, unsigned, const void *, +		   int); +void i2400m_net_erx(struct i2400m *, struct sk_buff *, enum i2400m_cs); +void i2400m_net_wake_stop(struct i2400m *);  enum i2400m_pt; -extern int i2400m_tx(struct i2400m *, const void *, size_t, enum i2400m_pt); +int i2400m_tx(struct i2400m *, const void *, size_t, enum i2400m_pt);  #ifdef CONFIG_DEBUG_FS -extern int i2400m_debugfs_add(struct i2400m *); -extern void i2400m_debugfs_rm(struct i2400m *); +int i2400m_debugfs_add(struct i2400m *); +void i2400m_debugfs_rm(struct i2400m *);  #else  static inline int i2400m_debugfs_add(struct i2400m *i2400m)  { @@ -820,8 +823,8 @@ static inline void i2400m_debugfs_rm(struct i2400m *i2400m) {}  #endif  /* Initialize/shutdown the device */ -extern int i2400m_dev_initialize(struct i2400m *); -extern void i2400m_dev_shutdown(struct i2400m *); +int i2400m_dev_initialize(struct i2400m *); +void i2400m_dev_shutdown(struct i2400m *);  extern struct attribute_group i2400m_dev_attr_group; @@ -869,21 +872,21 @@ void i2400m_put(struct i2400m *i2400m)  	dev_put(i2400m->wimax_dev.net_dev);  } -extern int i2400m_dev_reset_handle(struct i2400m *, const char *); -extern int i2400m_pre_reset(struct i2400m *); -extern int i2400m_post_reset(struct i2400m *); -extern void i2400m_error_recovery(struct i2400m *); +int i2400m_dev_reset_handle(struct i2400m *, const char *); +int i2400m_pre_reset(struct i2400m *); +int i2400m_post_reset(struct i2400m *); +void i2400m_error_recovery(struct i2400m *);  /*   * _setup()/_release() are called by the probe/disconnect functions of   * the bus-specific drivers.   */ -extern int i2400m_setup(struct i2400m *, enum i2400m_bri bm_flags); -extern void i2400m_release(struct i2400m *); +int i2400m_setup(struct i2400m *, enum i2400m_bri bm_flags); +void i2400m_release(struct i2400m *); -extern int i2400m_rx(struct i2400m *, struct sk_buff *); -extern struct i2400m_msg_hdr *i2400m_tx_msg_get(struct i2400m *, size_t *); -extern void i2400m_tx_msg_sent(struct i2400m *); +int i2400m_rx(struct i2400m *, struct sk_buff *); +struct i2400m_msg_hdr *i2400m_tx_msg_get(struct i2400m *, size_t *); +void i2400m_tx_msg_sent(struct i2400m *);  /* @@ -896,34 +899,19 @@ struct device *i2400m_dev(struct i2400m *i2400m)  	return i2400m->wimax_dev.net_dev->dev.parent;  } -/* - * Helper for scheduling simple work functions - * - * This struct can get any kind of payload attached (normally in the - * form of a struct where you pack the stuff you want to pass to the - * _work function). - */ -struct i2400m_work { -	struct work_struct ws; -	struct i2400m *i2400m; -	size_t pl_size; -	u8 pl[0]; -}; - -extern int i2400m_msg_check_status(const struct i2400m_l3l4_hdr *, -				   char *, size_t); -extern int i2400m_msg_size_check(struct i2400m *, -				 const struct i2400m_l3l4_hdr *, size_t); -extern struct sk_buff *i2400m_msg_to_dev(struct i2400m *, const void *, size_t); -extern void i2400m_msg_to_dev_cancel_wait(struct i2400m *, int); -extern void i2400m_report_hook(struct i2400m *, -			       const struct i2400m_l3l4_hdr *, size_t); -extern void i2400m_report_hook_work(struct work_struct *); -extern int i2400m_cmd_enter_powersave(struct i2400m *); -extern int i2400m_cmd_exit_idle(struct i2400m *); -extern struct sk_buff *i2400m_get_device_info(struct i2400m *); -extern int i2400m_firmware_check(struct i2400m *); -extern int i2400m_set_idle_timeout(struct i2400m *, unsigned); +int i2400m_msg_check_status(const struct i2400m_l3l4_hdr *, char *, size_t); +int i2400m_msg_size_check(struct i2400m *, const struct i2400m_l3l4_hdr *, +			  size_t); +struct sk_buff *i2400m_msg_to_dev(struct i2400m *, const void *, size_t); +void i2400m_msg_to_dev_cancel_wait(struct i2400m *, int); +void i2400m_report_hook(struct i2400m *, const struct i2400m_l3l4_hdr *, +			size_t); +void i2400m_report_hook_work(struct work_struct *); +int i2400m_cmd_enter_powersave(struct i2400m *); +int i2400m_cmd_exit_idle(struct i2400m *); +struct sk_buff *i2400m_get_device_info(struct i2400m *); +int i2400m_firmware_check(struct i2400m *); +int i2400m_set_idle_timeout(struct i2400m *, unsigned);  static inline  struct usb_endpoint_descriptor *usb_get_epd(struct usb_interface *iface, int ep) @@ -931,13 +919,12 @@ struct usb_endpoint_descriptor *usb_get_epd(struct usb_interface *iface, int ep)  	return &iface->cur_altsetting->endpoint[ep].desc;  } -extern int i2400m_op_rfkill_sw_toggle(struct wimax_dev *, -				      enum wimax_rf_state); -extern void i2400m_report_tlv_rf_switches_status( -	struct i2400m *, const struct i2400m_tlv_rf_switches_status *); +int i2400m_op_rfkill_sw_toggle(struct wimax_dev *, enum wimax_rf_state); +void i2400m_report_tlv_rf_switches_status(struct i2400m *, +					  const struct i2400m_tlv_rf_switches_status *);  /* - * Helpers for firmware backwards compability + * Helpers for firmware backwards compatibility   *   * As we aim to support at least the firmware version that was   * released with the previous kernel/driver release, some code will be @@ -978,8 +965,8 @@ void __i2400m_msleep(unsigned ms)  /* module initialization helpers */ -extern int i2400m_barker_db_init(const char *); -extern void i2400m_barker_db_exit(void); +int i2400m_barker_db_init(const char *); +void i2400m_barker_db_exit(void); diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c index 94742e1eafe..a9970f1af97 100644 --- a/drivers/net/wimax/i2400m/netdev.c +++ b/drivers/net/wimax/i2400m/netdev.c @@ -76,6 +76,7 @@  #include <linux/slab.h>  #include <linux/netdevice.h>  #include <linux/ethtool.h> +#include <linux/export.h>  #include "i2400m.h" @@ -155,7 +156,7 @@ void i2400m_wake_tx_work(struct work_struct *ws)  	struct i2400m *i2400m = container_of(ws, struct i2400m, wake_tx_ws);  	struct net_device *net_dev = i2400m->wimax_dev.net_dev;  	struct device *dev = i2400m_dev(i2400m); -	struct sk_buff *skb = i2400m->wake_tx_skb; +	struct sk_buff *skb;  	unsigned long flags;  	spin_lock_irqsave(&i2400m->tx_lock, flags); @@ -166,7 +167,7 @@ void i2400m_wake_tx_work(struct work_struct *ws)  	d_fnstart(3, dev, "(ws %p i2400m %p skb %p)\n", ws, i2400m, skb);  	result = -EINVAL;  	if (skb == NULL) { -		dev_err(dev, "WAKE&TX: skb dissapeared!\n"); +		dev_err(dev, "WAKE&TX: skb disappeared!\n");  		goto out_put;  	}  	/* If we have, somehow, lost the connection after this was @@ -235,23 +236,26 @@ void i2400m_tx_prep_header(struct sk_buff *skb)  void i2400m_net_wake_stop(struct i2400m *i2400m)  {  	struct device *dev = i2400m_dev(i2400m); +	struct sk_buff *wake_tx_skb; +	unsigned long flags;  	d_fnstart(3, dev, "(i2400m %p)\n", i2400m); -	/* See i2400m_hard_start_xmit(), references are taken there -	 * and here we release them if the work was still -	 * pending. Note we can't differentiate work not pending vs -	 * never scheduled, so the NULL check does that. */ -	if (cancel_work_sync(&i2400m->wake_tx_ws) == 0 -	    && i2400m->wake_tx_skb != NULL) { -		unsigned long flags; -		struct sk_buff *wake_tx_skb; -		spin_lock_irqsave(&i2400m->tx_lock, flags); -		wake_tx_skb = i2400m->wake_tx_skb;	/* compat help */ -		i2400m->wake_tx_skb = NULL;	/* compat help */ -		spin_unlock_irqrestore(&i2400m->tx_lock, flags); +	/* +	 * See i2400m_hard_start_xmit(), references are taken there and +	 * here we release them if the packet was still pending. +	 */ +	cancel_work_sync(&i2400m->wake_tx_ws); + +	spin_lock_irqsave(&i2400m->tx_lock, flags); +	wake_tx_skb = i2400m->wake_tx_skb; +	i2400m->wake_tx_skb = NULL; +	spin_unlock_irqrestore(&i2400m->tx_lock, flags); + +	if (wake_tx_skb) {  		i2400m_put(i2400m);  		kfree_skb(wake_tx_skb);  	} +  	d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);  } @@ -287,7 +291,7 @@ int i2400m_net_wake_tx(struct i2400m *i2400m, struct net_device *net_dev,  	 * and if pending, release those resources. */  	result = 0;  	spin_lock_irqsave(&i2400m->tx_lock, flags); -	if (!work_pending(&i2400m->wake_tx_ws)) { +	if (!i2400m->wake_tx_skb) {  		netif_stop_queue(net_dev);  		i2400m_get(i2400m);  		i2400m->wake_tx_skb = skb_get(skb);	/* transfer ref count */ @@ -366,38 +370,27 @@ netdev_tx_t i2400m_hard_start_xmit(struct sk_buff *skb,  {  	struct i2400m *i2400m = net_dev_to_i2400m(net_dev);  	struct device *dev = i2400m_dev(i2400m); -	int result; +	int result = -1;  	d_fnstart(3, dev, "(skb %p net_dev %p)\n", skb, net_dev); -	if (skb_header_cloned(skb)) { -		/* -		 * Make tcpdump/wireshark happy -- if they are -		 * running, the skb is cloned and we will overwrite -		 * the mac fields in i2400m_tx_prep_header. Expand -		 * seems to fix this... -		 */ -		result = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); -		if (result) { -			result = NETDEV_TX_BUSY; -			goto error_expand; -		} -	} + +	if (skb_cow_head(skb, 0)) +		goto drop;  	if (i2400m->state == I2400M_SS_IDLE)  		result = i2400m_net_wake_tx(i2400m, net_dev, skb);  	else  		result = i2400m_net_tx(i2400m, net_dev, skb); -	if (result <  0) +	if (result <  0) { +drop:  		net_dev->stats.tx_dropped++; -	else { +	} else {  		net_dev->stats.tx_packets++;  		net_dev->stats.tx_bytes += skb->len;  	} -	result = NETDEV_TX_OK; -error_expand: -	kfree_skb(skb); +	dev_kfree_skb(skb);  	d_fnend(3, dev, "(skb %p net_dev %p) = %d\n", skb, net_dev, result); -	return result; +	return NETDEV_TX_OK;  } @@ -605,11 +598,12 @@ static void i2400m_get_drvinfo(struct net_device *net_dev,  {  	struct i2400m *i2400m = net_dev_to_i2400m(net_dev); -	strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver) - 1); -	strncpy(info->fw_version, i2400m->fw_name, sizeof(info->fw_version) - 1); +	strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); +	strlcpy(info->fw_version, i2400m->fw_name ? : "", +		sizeof(info->fw_version));  	if (net_dev->dev.parent) -		strncpy(info->bus_info, dev_name(net_dev->dev.parent), -			sizeof(info->bus_info) - 1); +		strlcpy(info->bus_info, dev_name(net_dev->dev.parent), +			sizeof(info->bus_info));  }  static const struct ethtool_ops i2400m_ethtool_ops = { diff --git a/drivers/net/wimax/i2400m/op-rfkill.c b/drivers/net/wimax/i2400m/op-rfkill.c index 9e02b90b008..b0dba35a8ad 100644 --- a/drivers/net/wimax/i2400m/op-rfkill.c +++ b/drivers/net/wimax/i2400m/op-rfkill.c @@ -27,7 +27,7 @@   * - report changes in the HW RF Kill switch [with   *   wimax_rfkill_{sw,hw}_report(), which happens when we detect those   *   indications coming through hardware reports]. We also do it on - *   initialization to let the stack know the intial HW state. + *   initialization to let the stack know the initial HW state.   *   * - implement indications from the stack to change the SW RF Kill   *   switch (coming from sysfs, the wimax stack or user space). @@ -73,7 +73,7 @@ int i2400m_radio_is(struct i2400m *i2400m, enum wimax_rf_state state)   * Generic Netlink will call this function when a message is sent from   * userspace to change the software RF-Kill switch status.   * - * This function will set the device's sofware RF-Kill switch state to + * This function will set the device's software RF-Kill switch state to   * match what is requested.   *   * NOTE: the i2400m has a strict state machine; we can only set the diff --git a/drivers/net/wimax/i2400m/rx.c b/drivers/net/wimax/i2400m/rx.c index 844133b44af..0b602951ff6 100644 --- a/drivers/net/wimax/i2400m/rx.c +++ b/drivers/net/wimax/i2400m/rx.c @@ -149,6 +149,8 @@  #include <linux/if_arp.h>  #include <linux/netdevice.h>  #include <linux/workqueue.h> +#include <linux/export.h> +#include <linux/moduleparam.h>  #include "i2400m.h" @@ -349,7 +351,7 @@ error_no_waiter:   *   * For reports: We can't clone the original skb where the data is   * because we need to send this up via netlink; netlink has to add - * headers and we can't overwrite what's preceeding the payload...as + * headers and we can't overwrite what's preceding the payload...as   * it is another message. So we just dup them.   */  static @@ -425,7 +427,7 @@ error_check:   *   * As in i2400m_rx_ctl(), we can't clone the original skb where the   * data is because we need to send this up via netlink; netlink has to - * add headers and we can't overwrite what's preceeding the + * add headers and we can't overwrite what's preceding the   * payload...as it is another message. So we just dup them.   */  static @@ -1344,29 +1346,22 @@ EXPORT_SYMBOL(i2400m_unknown_barker);  int i2400m_rx_setup(struct i2400m *i2400m)  {  	int result = 0; -	struct device *dev = i2400m_dev(i2400m);  	i2400m->rx_reorder = i2400m_rx_reorder_disabled? 0 : 1;  	if (i2400m->rx_reorder) {  		unsigned itr; -		size_t size;  		struct i2400m_roq_log *rd;  		result = -ENOMEM; -		size = sizeof(i2400m->rx_roq[0]) * (I2400M_RO_CIN + 1); -		i2400m->rx_roq = kzalloc(size, GFP_KERNEL); -		if (i2400m->rx_roq == NULL) { -			dev_err(dev, "RX: cannot allocate %zu bytes for " -				"reorder queues\n", size); +		i2400m->rx_roq = kcalloc(I2400M_RO_CIN + 1, +					 sizeof(i2400m->rx_roq[0]), GFP_KERNEL); +		if (i2400m->rx_roq == NULL)  			goto error_roq_alloc; -		} -		size = sizeof(*i2400m->rx_roq[0].log) * (I2400M_RO_CIN + 1); -		rd = kzalloc(size, GFP_KERNEL); +		rd = kcalloc(I2400M_RO_CIN + 1, sizeof(*i2400m->rx_roq[0].log), +			     GFP_KERNEL);  		if (rd == NULL) { -			dev_err(dev, "RX: cannot allocate %zu bytes for " -				"reorder queues log areas\n", size);  			result = -ENOMEM;  			goto error_roq_log_alloc;  		} diff --git a/drivers/net/wimax/i2400m/sdio-debug-levels.h b/drivers/net/wimax/i2400m/sdio-debug-levels.h deleted file mode 100644 index c5199874130..00000000000 --- a/drivers/net/wimax/i2400m/sdio-debug-levels.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * debug levels control file for the i2400m module's - */ -#ifndef __debug_levels__h__ -#define __debug_levels__h__ - -/* Maximum compile and run time debug level for all submodules */ -#define D_MODULENAME i2400m_sdio -#define D_MASTER CONFIG_WIMAX_I2400M_DEBUG_LEVEL - -#include <linux/wimax/debug.h> - -/* List of all the enabled modules */ -enum d_module { -	D_SUBMODULE_DECLARE(main), -	D_SUBMODULE_DECLARE(tx), -	D_SUBMODULE_DECLARE(rx), -	D_SUBMODULE_DECLARE(fw) -}; - - -#endif /* #ifndef __debug_levels__h__ */ diff --git a/drivers/net/wimax/i2400m/sdio-fw.c b/drivers/net/wimax/i2400m/sdio-fw.c deleted file mode 100644 index 8e025418f5b..00000000000 --- a/drivers/net/wimax/i2400m/sdio-fw.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Intel Wireless WiMAX Connection 2400m - * Firmware uploader's SDIO specifics - * - * - * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - *   * Redistributions of source code must retain the above copyright - *     notice, this list of conditions and the following disclaimer. - *   * 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. - *   * Neither the name of Intel Corporation nor the names of its - *     contributors may be used to endorse or promote products derived - *     from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "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 THE COPYRIGHT - * OWNER OR CONTRIBUTORS 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. - * - * - * Intel Corporation <linux-wimax@intel.com> - * Yanir Lubetkin <yanirx.lubetkin@intel.com> - * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> - *  - Initial implementation - * - * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> - *  - Bus generic/specific split for USB - * - * Dirk Brandewie <dirk.j.brandewie@intel.com> - *  - Initial implementation for SDIO - * - * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> - *  - SDIO rehash for changes in the bus-driver model - * - * Dirk Brandewie <dirk.j.brandewie@intel.com> - *  - Make it IRQ based, not polling - * - * THE PROCEDURE - * - * See fw.c for the generic description of this procedure. - * - * This file implements only the SDIO specifics. It boils down to how - * to send a command and waiting for an acknowledgement from the - * device. - * - * All this code is sequential -- all i2400ms_bus_bm_*() functions are - * executed in the same thread, except i2400ms_bm_irq() [on its own by - * the SDIO driver]. This makes it possible to avoid locking. - * - * COMMAND EXECUTION - * - * The generic firmware upload code will call i2400m_bus_bm_cmd_send() - * to send commands. - * - * The SDIO devices expects things in 256 byte blocks, so it will pad - * it, compute the checksum (if needed) and pass it to SDIO. - * - * ACK RECEPTION - * - * This works in IRQ mode -- the fw loader says when to wait for data - * and for that it calls i2400ms_bus_bm_wait_for_ack(). - * - * This checks if there is any data available (RX size > 0); if not, - * waits for the IRQ handler to notify about it. Once there is data, - * it is read and passed to the caller. Doing it this way we don't - * need much coordination/locking, and it makes it much more difficult - * for an interrupt to be lost and the wait_for_ack() function getting - * stuck even when data is pending. - */ -#include <linux/mmc/sdio_func.h> -#include "i2400m-sdio.h" - - -#define D_SUBMODULE fw -#include "sdio-debug-levels.h" - - -/* - * Send a boot-mode command to the SDIO function - * - * We use a bounce buffer (i2400m->bm_cmd_buf) because we need to - * touch the header if the RAW flag is not set. - * - * @flags: pass thru from i2400m_bm_cmd() - * @return: cmd_size if ok, < 0 errno code on error. - * - * Note the command is padded to the SDIO block size for the device. - */ -ssize_t i2400ms_bus_bm_cmd_send(struct i2400m *i2400m, -				const struct i2400m_bootrom_header *_cmd, -				size_t cmd_size, int flags) -{ -	ssize_t result; -	struct device *dev = i2400m_dev(i2400m); -	struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m); -	int opcode = _cmd == NULL ? -1 : i2400m_brh_get_opcode(_cmd); -	struct i2400m_bootrom_header *cmd; -	/* SDIO restriction */ -	size_t cmd_size_a = ALIGN(cmd_size, I2400MS_BLK_SIZE); - -	d_fnstart(5, dev, "(i2400m %p cmd %p size %zu)\n", -		  i2400m, _cmd, cmd_size); -	result = -E2BIG; -	if (cmd_size > I2400M_BM_CMD_BUF_SIZE) -		goto error_too_big; - -	if (_cmd != i2400m->bm_cmd_buf) -		memmove(i2400m->bm_cmd_buf, _cmd, cmd_size); -	cmd = i2400m->bm_cmd_buf; -	if (cmd_size_a > cmd_size)			/* Zero pad space */ -		memset(i2400m->bm_cmd_buf + cmd_size, 0, cmd_size_a - cmd_size); -	if ((flags & I2400M_BM_CMD_RAW) == 0) { -		if (WARN_ON(i2400m_brh_get_response_required(cmd) == 0)) -			dev_warn(dev, "SW BUG: response_required == 0\n"); -		i2400m_bm_cmd_prepare(cmd); -	} -	d_printf(4, dev, "BM cmd %d: %zu bytes (%zu padded)\n", -		 opcode, cmd_size, cmd_size_a); -	d_dump(5, dev, cmd, cmd_size); - -	sdio_claim_host(i2400ms->func);			/* Send & check */ -	result = sdio_memcpy_toio(i2400ms->func, I2400MS_DATA_ADDR, -				  i2400m->bm_cmd_buf, cmd_size_a); -	sdio_release_host(i2400ms->func); -	if (result < 0) { -		dev_err(dev, "BM cmd %d: cannot send: %ld\n", -			opcode, (long) result); -		goto error_cmd_send; -	} -	result = cmd_size; -error_cmd_send: -error_too_big: -	d_fnend(5, dev, "(i2400m %p cmd %p size %zu) = %d\n", -		i2400m, _cmd, cmd_size, (int) result); -	return result; -} - - -/* - * Read an ack from the device's boot-mode - * - * @i2400m: - * @_ack: pointer to where to store the read data - * @ack_size: how many bytes we should read - * - * Returns: < 0 errno code on error; otherwise, amount of received bytes. - * - * The ACK for a BM command is always at least sizeof(*ack) bytes, so - * check for that. We don't need to check for device reboots - * - */ -ssize_t i2400ms_bus_bm_wait_for_ack(struct i2400m *i2400m, -				    struct i2400m_bootrom_header *ack, -				    size_t ack_size) -{ -	ssize_t result; -	struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m); -	struct sdio_func *func = i2400ms->func; -	struct device *dev = &func->dev; -	int size; - -	BUG_ON(sizeof(*ack) > ack_size); - -	d_fnstart(5, dev, "(i2400m %p ack %p size %zu)\n", -		  i2400m, ack, ack_size); - -	result = wait_event_timeout(i2400ms->bm_wfa_wq, -				    i2400ms->bm_ack_size != -EINPROGRESS, -				    2 * HZ); -	if (result == 0) { -		result = -ETIMEDOUT; -		dev_err(dev, "BM: error waiting for an ack\n"); -		goto error_timeout; -	} - -	spin_lock(&i2400m->rx_lock); -	result = i2400ms->bm_ack_size; -	BUG_ON(result == -EINPROGRESS); -	if (result < 0)        /* so we exit when rx_release() is called */ -		dev_err(dev, "BM: %s failed: %zd\n", __func__, result); -	else { -		size = min(ack_size, i2400ms->bm_ack_size); -		memcpy(ack, i2400m->bm_ack_buf, size); -	} -	/* -	 * Remember always to clear the bm_ack_size to -EINPROGRESS -	 * after the RX data is processed -	 */ -	i2400ms->bm_ack_size = -EINPROGRESS; -	spin_unlock(&i2400m->rx_lock); - -error_timeout: -	d_fnend(5, dev, "(i2400m %p ack %p size %zu) = %zd\n", -		i2400m, ack, ack_size, result); -	return result; -} diff --git a/drivers/net/wimax/i2400m/sdio-rx.c b/drivers/net/wimax/i2400m/sdio-rx.c deleted file mode 100644 index fb6396dd115..00000000000 --- a/drivers/net/wimax/i2400m/sdio-rx.c +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Intel Wireless WiMAX Connection 2400m - * SDIO RX handling - * - * - * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - *   * Redistributions of source code must retain the above copyright - *     notice, this list of conditions and the following disclaimer. - *   * 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. - *   * Neither the name of Intel Corporation nor the names of its - *     contributors may be used to endorse or promote products derived - *     from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "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 THE COPYRIGHT - * OWNER OR CONTRIBUTORS 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. - * - * - * Intel Corporation <linux-wimax@intel.com> - * Dirk Brandewie <dirk.j.brandewie@intel.com> - *  - Initial implementation - * - * - * This handles the RX path on SDIO. - * - * The SDIO bus driver calls the "irq" routine when data is available. - * This is not a traditional interrupt routine since the SDIO bus - * driver calls us from its irq thread context.  Because of this - * sleeping in the SDIO RX IRQ routine is okay. - * - * From there on, we obtain the size of the data that is available, - * allocate an skb, copy it and then pass it to the generic driver's - * RX routine [i2400m_rx()]. - * - * ROADMAP - * - * i2400ms_irq() - *   i2400ms_rx() - *     __i2400ms_rx_get_size() - *     i2400m_is_boot_barker() - *     i2400m_rx() - * - * i2400ms_rx_setup() - * - * i2400ms_rx_release() - */ -#include <linux/workqueue.h> -#include <linux/wait.h> -#include <linux/skbuff.h> -#include <linux/mmc/sdio.h> -#include <linux/mmc/sdio_func.h> -#include <linux/slab.h> -#include "i2400m-sdio.h" - -#define D_SUBMODULE rx -#include "sdio-debug-levels.h" - -static const __le32 i2400m_ACK_BARKER[4] = { -	__constant_cpu_to_le32(I2400M_ACK_BARKER), -	__constant_cpu_to_le32(I2400M_ACK_BARKER), -	__constant_cpu_to_le32(I2400M_ACK_BARKER), -	__constant_cpu_to_le32(I2400M_ACK_BARKER) -}; - - -/* - * Read and return the amount of bytes available for RX - * - * The RX size has to be read like this: byte reads of three - * sequential locations; then glue'em together. - * - * sdio_readl() doesn't work. - */ -static ssize_t __i2400ms_rx_get_size(struct i2400ms *i2400ms) -{ -	int ret, cnt, val; -	ssize_t rx_size; -	unsigned xfer_size_addr; -	struct sdio_func *func = i2400ms->func; -	struct device *dev = &i2400ms->func->dev; - -	d_fnstart(7, dev, "(i2400ms %p)\n", i2400ms); -	xfer_size_addr = I2400MS_INTR_GET_SIZE_ADDR; -	rx_size = 0; -	for (cnt = 0; cnt < 3; cnt++) { -		val = sdio_readb(func, xfer_size_addr + cnt, &ret); -		if (ret < 0) { -			dev_err(dev, "RX: Can't read byte %d of RX size from " -				"0x%08x: %d\n", cnt, xfer_size_addr + cnt, ret); -			rx_size = ret; -			goto error_read; -		} -		rx_size = rx_size << 8 | (val & 0xff); -	} -	d_printf(6, dev, "RX: rx_size is %ld\n", (long) rx_size); -error_read: -	d_fnend(7, dev, "(i2400ms %p) = %ld\n", i2400ms, (long) rx_size); -	return rx_size; -} - - -/* - * Read data from the device (when in normal) - * - * Allocate an SKB of the right size, read the data in and then - * deliver it to the generic layer. - * - * We also check for a reboot barker. That means the device died and - * we have to reboot it. - */ -static -void i2400ms_rx(struct i2400ms *i2400ms) -{ -	int ret; -	struct sdio_func *func = i2400ms->func; -	struct device *dev = &func->dev; -	struct i2400m *i2400m = &i2400ms->i2400m; -	struct sk_buff *skb; -	ssize_t rx_size; - -	d_fnstart(7, dev, "(i2400ms %p)\n", i2400ms); -	rx_size = __i2400ms_rx_get_size(i2400ms); -	if (rx_size < 0) { -		ret = rx_size; -		goto error_get_size; -	} -	/* -	 * Hardware quirk: make sure to clear the INTR status register -	 * AFTER getting the data transfer size. -	 */ -	sdio_writeb(func, 1, I2400MS_INTR_CLEAR_ADDR, &ret); - -	ret = -ENOMEM; -	skb = alloc_skb(rx_size, GFP_ATOMIC); -	if (NULL == skb) { -		dev_err(dev, "RX: unable to alloc skb\n"); -		goto error_alloc_skb; -	} -	ret = sdio_memcpy_fromio(func, skb->data, -				 I2400MS_DATA_ADDR, rx_size); -	if (ret < 0) { -		dev_err(dev, "RX: SDIO data read failed: %d\n", ret); -		goto error_memcpy_fromio; -	} - -	rmb();	/* make sure we get boot_mode from dev_reset_handle */ -	if (unlikely(i2400m->boot_mode == 1)) { -		spin_lock(&i2400m->rx_lock); -		i2400ms->bm_ack_size = rx_size; -		spin_unlock(&i2400m->rx_lock); -		memcpy(i2400m->bm_ack_buf, skb->data, rx_size); -		wake_up(&i2400ms->bm_wfa_wq); -		d_printf(5, dev, "RX: SDIO boot mode message\n"); -		kfree_skb(skb); -		goto out; -	} -	ret = -EIO; -	if (unlikely(rx_size < sizeof(__le32))) { -		dev_err(dev, "HW BUG? only %zu bytes received\n", rx_size); -		goto error_bad_size; -	} -	if (likely(i2400m_is_d2h_barker(skb->data))) { -		skb_put(skb, rx_size); -		i2400m_rx(i2400m, skb); -	} else if (unlikely(i2400m_is_boot_barker(i2400m, -						  skb->data, rx_size))) { -		ret = i2400m_dev_reset_handle(i2400m, "device rebooted"); -		dev_err(dev, "RX: SDIO reboot barker\n"); -		kfree_skb(skb); -	} else { -		i2400m_unknown_barker(i2400m, skb->data, rx_size); -		kfree_skb(skb); -	} -out: -	d_fnend(7, dev, "(i2400ms %p) = void\n", i2400ms); -	return; - -error_memcpy_fromio: -	kfree_skb(skb); -error_alloc_skb: -error_get_size: -error_bad_size: -	d_fnend(7, dev, "(i2400ms %p) = %d\n", i2400ms, ret); -} - - -/* - * Process an interrupt from the SDIO card - * - * FIXME: need to process other events that are not just ready-to-read - * - * Checks there is data ready and then proceeds to read it. - */ -static -void i2400ms_irq(struct sdio_func *func) -{ -	int ret; -	struct i2400ms *i2400ms = sdio_get_drvdata(func); -	struct device *dev = &func->dev; -	int val; - -	d_fnstart(6, dev, "(i2400ms %p)\n", i2400ms); -	val = sdio_readb(func, I2400MS_INTR_STATUS_ADDR, &ret); -	if (ret < 0) { -		dev_err(dev, "RX: Can't read interrupt status: %d\n", ret); -		goto error_no_irq; -	} -	if (!val) { -		dev_err(dev, "RX: BUG? got IRQ but no interrupt ready?\n"); -		goto error_no_irq; -	} -	i2400ms_rx(i2400ms); -error_no_irq: -	d_fnend(6, dev, "(i2400ms %p) = void\n", i2400ms); -} - - -/* - * Setup SDIO RX - * - * Hooks up the IRQ handler and then enables IRQs. - */ -int i2400ms_rx_setup(struct i2400ms *i2400ms) -{ -	int result; -	struct sdio_func *func = i2400ms->func; -	struct device *dev = &func->dev; -	struct i2400m *i2400m = &i2400ms->i2400m; - -	d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms); - -	init_waitqueue_head(&i2400ms->bm_wfa_wq); -	spin_lock(&i2400m->rx_lock); -	i2400ms->bm_wait_result = -EINPROGRESS; -	/* -	 * Before we are about to enable the RX interrupt, make sure -	 * bm_ack_size is cleared to -EINPROGRESS which indicates -	 * no RX interrupt happened yet or the previous interrupt -	 * has been handled, we are ready to take the new interrupt -	 */ -	i2400ms->bm_ack_size = -EINPROGRESS; -	spin_unlock(&i2400m->rx_lock); - -	sdio_claim_host(func); -	result = sdio_claim_irq(func, i2400ms_irq); -	if (result < 0) { -		dev_err(dev, "Cannot claim IRQ: %d\n", result); -		goto error_irq_claim; -	} -	result = 0; -	sdio_writeb(func, 1, I2400MS_INTR_ENABLE_ADDR, &result); -	if (result < 0) { -		sdio_release_irq(func); -		dev_err(dev, "Failed to enable interrupts %d\n", result); -	} -error_irq_claim: -	sdio_release_host(func); -	d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result); -	return result; -} - - -/* - * Tear down SDIO RX - * - * Disables IRQs in the device and removes the IRQ handler. - */ -void i2400ms_rx_release(struct i2400ms *i2400ms) -{ -	int result; -	struct sdio_func *func = i2400ms->func; -	struct device *dev = &func->dev; -	struct i2400m *i2400m = &i2400ms->i2400m; - -	d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms); -	spin_lock(&i2400m->rx_lock); -	i2400ms->bm_ack_size = -EINTR; -	spin_unlock(&i2400m->rx_lock); -	wake_up_all(&i2400ms->bm_wfa_wq); -	sdio_claim_host(func); -	sdio_writeb(func, 0, I2400MS_INTR_ENABLE_ADDR, &result); -	sdio_release_irq(func); -	sdio_release_host(func); -	d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result); -} diff --git a/drivers/net/wimax/i2400m/sdio-tx.c b/drivers/net/wimax/i2400m/sdio-tx.c deleted file mode 100644 index b53cd1c80e3..00000000000 --- a/drivers/net/wimax/i2400m/sdio-tx.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Intel Wireless WiMAX Connection 2400m - * SDIO TX transaction backends - * - * - * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - *   * Redistributions of source code must retain the above copyright - *     notice, this list of conditions and the following disclaimer. - *   * 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. - *   * Neither the name of Intel Corporation nor the names of its - *     contributors may be used to endorse or promote products derived - *     from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "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 THE COPYRIGHT - * OWNER OR CONTRIBUTORS 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. - * - * - * Intel Corporation <linux-wimax@intel.com> - * Dirk Brandewie <dirk.j.brandewie@intel.com> - *  - Initial implementation - * - * - * Takes the TX messages in the i2400m's driver TX FIFO and sends them - * to the device until there are no more. - * - * If we fail sending the message, we just drop it. There isn't much - * we can do at this point. Most of the traffic is network, which has - * recovery methods for dropped packets. - * - * The SDIO functions are not atomic, so we can't run from the context - * where i2400m->bus_tx_kick() [i2400ms_bus_tx_kick()] is being called - * (some times atomic). Thus, the actual TX work is deferred to a - * workqueue. - * - * ROADMAP - * - * i2400ms_bus_tx_kick() - *   i2400ms_tx_submit()     [through workqueue] - * - * i2400m_tx_setup() - * - * i2400m_tx_release() - */ -#include <linux/mmc/sdio_func.h> -#include "i2400m-sdio.h" - -#define D_SUBMODULE tx -#include "sdio-debug-levels.h" - - -/* - * Pull TX transations from the TX FIFO and send them to the device - * until there are no more. - */ -static -void i2400ms_tx_submit(struct work_struct *ws) -{ -	int result; -	struct i2400ms *i2400ms = container_of(ws, struct i2400ms, tx_worker); -	struct i2400m *i2400m = &i2400ms->i2400m; -	struct sdio_func *func = i2400ms->func; -	struct device *dev = &func->dev; -	struct i2400m_msg_hdr *tx_msg; -	size_t tx_msg_size; - -	d_fnstart(4, dev, "(i2400ms %p, i2400m %p)\n", i2400ms, i2400ms); - -	while (NULL != (tx_msg = i2400m_tx_msg_get(i2400m, &tx_msg_size))) { -		d_printf(2, dev, "TX: submitting %zu bytes\n", tx_msg_size); -		d_dump(5, dev, tx_msg, tx_msg_size); - -		sdio_claim_host(func); -		result = sdio_memcpy_toio(func, 0, tx_msg, tx_msg_size); -		sdio_release_host(func); - -		i2400m_tx_msg_sent(i2400m); - -		if (result < 0) { -			dev_err(dev, "TX: cannot submit TX; tx_msg @%zu %zu B:" -				" %d\n", (void *) tx_msg - i2400m->tx_buf, -				tx_msg_size, result); -		} - -		if (result == -ETIMEDOUT) { -			i2400m_error_recovery(i2400m); -			break; -		} -		d_printf(2, dev, "TX: %zub submitted\n", tx_msg_size); -	} - -	d_fnend(4, dev, "(i2400ms %p) = void\n", i2400ms); -} - - -/* - * The generic driver notifies us that there is data ready for TX - * - * Schedule a run of i2400ms_tx_submit() to handle it. - */ -void i2400ms_bus_tx_kick(struct i2400m *i2400m) -{ -	struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m); -	struct device *dev = &i2400ms->func->dev; -	unsigned long flags; - -	d_fnstart(3, dev, "(i2400m %p) = void\n", i2400m); - -	/* schedule tx work, this is because tx may block, therefore -	 * it has to run in a thread context. -	 */ -	spin_lock_irqsave(&i2400m->tx_lock, flags); -	if (i2400ms->tx_workqueue != NULL) -		queue_work(i2400ms->tx_workqueue, &i2400ms->tx_worker); -	spin_unlock_irqrestore(&i2400m->tx_lock, flags); - -	d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); -} - -int i2400ms_tx_setup(struct i2400ms *i2400ms) -{ -	int result; -	struct device *dev = &i2400ms->func->dev; -	struct i2400m *i2400m = &i2400ms->i2400m; -	struct workqueue_struct *tx_workqueue; -	unsigned long flags; - -	d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms); - -	INIT_WORK(&i2400ms->tx_worker, i2400ms_tx_submit); -	snprintf(i2400ms->tx_wq_name, sizeof(i2400ms->tx_wq_name), -		 "%s-tx", i2400m->wimax_dev.name); -	tx_workqueue = -		create_singlethread_workqueue(i2400ms->tx_wq_name); -	if (tx_workqueue == NULL) { -		dev_err(dev, "TX: failed to create workqueue\n"); -		result = -ENOMEM; -	} else -		result = 0; -	spin_lock_irqsave(&i2400m->tx_lock, flags); -	i2400ms->tx_workqueue = tx_workqueue; -	spin_unlock_irqrestore(&i2400m->tx_lock, flags); -	d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result); -	return result; -} - -void i2400ms_tx_release(struct i2400ms *i2400ms) -{ -	struct i2400m *i2400m = &i2400ms->i2400m; -	struct workqueue_struct *tx_workqueue; -	unsigned long flags; - -	tx_workqueue = i2400ms->tx_workqueue; - -	spin_lock_irqsave(&i2400m->tx_lock, flags); -	i2400ms->tx_workqueue = NULL; -	spin_unlock_irqrestore(&i2400m->tx_lock, flags); - -	if (tx_workqueue) -		destroy_workqueue(tx_workqueue); -} diff --git a/drivers/net/wimax/i2400m/sdio.c b/drivers/net/wimax/i2400m/sdio.c deleted file mode 100644 index 9bfc26e1bc6..00000000000 --- a/drivers/net/wimax/i2400m/sdio.c +++ /dev/null @@ -1,602 +0,0 @@ -/* - * Intel Wireless WiMAX Connection 2400m - * Linux driver model glue for the SDIO device, reset & fw upload - * - * - * Copyright (C) 2007-2008 Intel Corporation <linux-wimax@intel.com> - * Dirk Brandewie <dirk.j.brandewie@intel.com> - * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> - * Yanir Lubetkin <yanirx.lubetkin@intel.com> - * - * 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. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * See i2400m-sdio.h for a general description of this driver. - * - * This file implements driver model glue, and hook ups for the - * generic driver to implement the bus-specific functions (device - * communication setup/tear down, firmware upload and resetting). - * - * ROADMAP - * - * i2400m_probe() - *   alloc_netdev() - *     i2400ms_netdev_setup() - *       i2400ms_init() - *       i2400m_netdev_setup() - *   i2400ms_enable_function() - *   i2400m_setup() - * - * i2400m_remove() - *     i2400m_release() - *     free_netdev(net_dev) - * - * i2400ms_bus_reset()            Called by i2400m_reset - *   __i2400ms_reset() - *     __i2400ms_send_barker() - */ - -#include <linux/slab.h> -#include <linux/debugfs.h> -#include <linux/mmc/sdio_ids.h> -#include <linux/mmc/sdio.h> -#include <linux/mmc/sdio_func.h> -#include "i2400m-sdio.h" -#include <linux/wimax/i2400m.h> - -#define D_SUBMODULE main -#include "sdio-debug-levels.h" - -/* IOE WiMAX function timeout in seconds */ -static int ioe_timeout = 2; -module_param(ioe_timeout, int, 0); - -static char i2400ms_debug_params[128]; -module_param_string(debug, i2400ms_debug_params, sizeof(i2400ms_debug_params), -		    0644); -MODULE_PARM_DESC(debug, -		 "String of space-separated NAME:VALUE pairs, where NAMEs " -		 "are the different debug submodules and VALUE are the " -		 "initial debug value to set."); - -/* Our firmware file name list */ -static const char *i2400ms_bus_fw_names[] = { -#define I2400MS_FW_FILE_NAME "i2400m-fw-sdio-1.3.sbcf" -	I2400MS_FW_FILE_NAME, -	NULL -}; - - -static const struct i2400m_poke_table i2400ms_pokes[] = { -	I2400M_FW_POKE(0x6BE260, 0x00000088), -	I2400M_FW_POKE(0x080550, 0x00000005), -	I2400M_FW_POKE(0xAE0000, 0x00000000), -	I2400M_FW_POKE(0x000000, 0x00000000), /* MUST be 0 terminated or bad -					       * things will happen */ -}; - -/* - * Enable the SDIO function - * - * Tries to enable the SDIO function; might fail if it is still not - * ready (in some hardware, the SDIO WiMAX function is only enabled - * when we ask it to explicitly doing). Tries until a timeout is - * reached. - * - * The @maxtries argument indicates how many times (at most) it should - * be tried to enable the function. 0 means forever. This acts along - * with the timeout (ie: it'll stop trying as soon as the maximum - * number of tries is reached _or_ as soon as the timeout is reached). - * - * The reverse of this is...sdio_disable_function() - * - * Returns: 0 if the SDIO function was enabled, < 0 errno code on - *     error (-ENODEV when it was unable to enable the function). - */ -static -int i2400ms_enable_function(struct i2400ms *i2400ms, unsigned maxtries) -{ -	struct sdio_func *func = i2400ms->func; -	u64 timeout; -	int err; -	struct device *dev = &func->dev; -	unsigned tries = 0; - -	d_fnstart(3, dev, "(func %p)\n", func); -	/* Setup timeout (FIXME: This needs to read the CIS table to -	 * get a real timeout) and then wait for the device to signal -	 * it is ready */ -	timeout = get_jiffies_64() + ioe_timeout * HZ; -	err = -ENODEV; -	while (err != 0 && time_before64(get_jiffies_64(), timeout)) { -		sdio_claim_host(func); -		/* -		 * There is a sillicon bug on the IWMC3200, where the -		 * IOE timeout will cause problems on Moorestown -		 * platforms (system hang). We explicitly overwrite -		 * func->enable_timeout here to work around the issue. -		 */ -		if (i2400ms->iwmc3200) -			func->enable_timeout = IWMC3200_IOR_TIMEOUT; -		err = sdio_enable_func(func); -		if (0 == err) { -			sdio_release_host(func); -			d_printf(2, dev, "SDIO function enabled\n"); -			goto function_enabled; -		} -		d_printf(2, dev, "SDIO function failed to enable: %d\n", err); -		sdio_release_host(func); -		if (maxtries > 0 && ++tries >= maxtries) { -			err = -ETIME; -			break; -		} -		msleep(I2400MS_INIT_SLEEP_INTERVAL); -	} -	/* If timed out, device is not there yet -- get -ENODEV so -	 * the device driver core will retry later on. */ -	if (err == -ETIME) { -		dev_err(dev, "Can't enable WiMAX function; " -			" has the function been enabled?\n"); -		err = -ENODEV; -	} -function_enabled: -	d_fnend(3, dev, "(func %p) = %d\n", func, err); -	return err; -} - - -/* - * Setup minimal device communication infrastructure needed to at - * least be able to update the firmware. - * - * Note the ugly trick: if we are in the probe path - * (i2400ms->debugfs_dentry == NULL), we only retry function - * enablement one, to avoid racing with the iwmc3200 top controller. - */ -static -int i2400ms_bus_setup(struct i2400m *i2400m) -{ -	int result; -	struct i2400ms *i2400ms = -		container_of(i2400m, struct i2400ms, i2400m); -	struct device *dev = i2400m_dev(i2400m); -	struct sdio_func *func = i2400ms->func; -	int retries; - -	sdio_claim_host(func); -	result = sdio_set_block_size(func, I2400MS_BLK_SIZE); -	sdio_release_host(func); -	if (result < 0) { -		dev_err(dev, "Failed to set block size: %d\n", result); -		goto error_set_blk_size; -	} - -	if (i2400ms->iwmc3200 && i2400ms->debugfs_dentry == NULL) -		retries = 1; -	else -		retries = 0; -	result = i2400ms_enable_function(i2400ms, retries); -	if (result < 0) { -		dev_err(dev, "Cannot enable SDIO function: %d\n", result); -		goto error_func_enable; -	} - -	result = i2400ms_tx_setup(i2400ms); -	if (result < 0) -		goto error_tx_setup; -	result = i2400ms_rx_setup(i2400ms); -	if (result < 0) -		goto error_rx_setup; -	return 0; - -error_rx_setup: -	i2400ms_tx_release(i2400ms); -error_tx_setup: -	sdio_claim_host(func); -	sdio_disable_func(func); -	sdio_release_host(func); -error_func_enable: -error_set_blk_size: -	return result; -} - - -/* - * Tear down minimal device communication infrastructure needed to at - * least be able to update the firmware. - */ -static -void i2400ms_bus_release(struct i2400m *i2400m) -{ -	struct i2400ms *i2400ms = -		container_of(i2400m, struct i2400ms, i2400m); -	struct sdio_func *func = i2400ms->func; - -	i2400ms_rx_release(i2400ms); -	i2400ms_tx_release(i2400ms); -	sdio_claim_host(func); -	sdio_disable_func(func); -	sdio_release_host(func); -} - - -/* - * Setup driver resources needed to communicate with the device - * - * The fw needs some time to settle, and it was just uploaded, - * so give it a break first. I'd prefer to just wait for the device to - * send something, but seems the poking we do to enable SDIO stuff - * interferes with it, so just give it a break before starting... - */ -static -int i2400ms_bus_dev_start(struct i2400m *i2400m) -{ -	struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m); -	struct sdio_func *func = i2400ms->func; -	struct device *dev = &func->dev; - -	d_fnstart(3, dev, "(i2400m %p)\n", i2400m); -	msleep(200); -	d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, 0); -	return 0; -} - - -/* - * Sends a barker buffer to the device - * - * This helper will allocate a kmalloced buffer and use it to transmit - * (then free it). Reason for this is that the SDIO host controller - * expects alignment (unknown exactly which) which the stack won't - * really provide and certain arches/host-controller combinations - * cannot use stack/vmalloc/text areas for DMA transfers. - */ -static -int __i2400ms_send_barker(struct i2400ms *i2400ms, -			  const __le32 *barker, size_t barker_size) -{ -	int  ret; -	struct sdio_func *func = i2400ms->func; -	struct device *dev = &func->dev; -	void *buffer; - -	ret = -ENOMEM; -	buffer = kmalloc(I2400MS_BLK_SIZE, GFP_KERNEL); -	if (buffer == NULL) -		goto error_kzalloc; - -	memcpy(buffer, barker, barker_size); -	sdio_claim_host(func); -	ret = sdio_memcpy_toio(func, 0, buffer, I2400MS_BLK_SIZE); -	sdio_release_host(func); - -	if (ret < 0) -		d_printf(0, dev, "E: barker error: %d\n", ret); - -	kfree(buffer); -error_kzalloc: -	return ret; -} - - -/* - * Reset a device at different levels (warm, cold or bus) - * - * @i2400ms: device descriptor - * @reset_type: soft, warm or bus reset (I2400M_RT_WARM/SOFT/BUS) - * - * FIXME: not tested -- need to confirm expected effects - * - * Warm and cold resets get an SDIO reset if they fail (unimplemented) - * - * Warm reset: - * - * The device will be fully reset internally, but won't be - * disconnected from the bus (so no reenumeration will - * happen). Firmware upload will be necessary. - * - * The device will send a reboot barker that will trigger the driver - * to reinitialize the state via __i2400m_dev_reset_handle. - * - * - * Cold and bus reset: - * - * The device will be fully reset internally, disconnected from the - * bus an a reenumeration will happen. Firmware upload will be - * necessary. Thus, we don't do any locking or struct - * reinitialization, as we are going to be fully disconnected and - * reenumerated. - * - * Note we need to return -ENODEV if a warm reset was requested and we - * had to resort to a bus reset. See i2400m_op_reset(), wimax_reset() - * and wimax_dev->op_reset. - * - * WARNING: no driver state saved/fixed - */ -static -int i2400ms_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt) -{ -	int result = 0; -	struct i2400ms *i2400ms = -		container_of(i2400m, struct i2400ms, i2400m); -	struct device *dev = i2400m_dev(i2400m); -	static const __le32 i2400m_WARM_BOOT_BARKER[4] = { -		cpu_to_le32(I2400M_WARM_RESET_BARKER), -		cpu_to_le32(I2400M_WARM_RESET_BARKER), -		cpu_to_le32(I2400M_WARM_RESET_BARKER), -		cpu_to_le32(I2400M_WARM_RESET_BARKER), -	}; -	static const __le32 i2400m_COLD_BOOT_BARKER[4] = { -		cpu_to_le32(I2400M_COLD_RESET_BARKER), -		cpu_to_le32(I2400M_COLD_RESET_BARKER), -		cpu_to_le32(I2400M_COLD_RESET_BARKER), -		cpu_to_le32(I2400M_COLD_RESET_BARKER), -	}; - -	if (rt == I2400M_RT_WARM) -		result = __i2400ms_send_barker(i2400ms, i2400m_WARM_BOOT_BARKER, -					       sizeof(i2400m_WARM_BOOT_BARKER)); -	else if (rt == I2400M_RT_COLD) -		result = __i2400ms_send_barker(i2400ms, i2400m_COLD_BOOT_BARKER, -					       sizeof(i2400m_COLD_BOOT_BARKER)); -	else if (rt == I2400M_RT_BUS) { -do_bus_reset: - -		i2400ms_bus_release(i2400m); - -		/* Wait for the device to settle */ -		msleep(40); - -		result =  i2400ms_bus_setup(i2400m); -	} else -		BUG(); -	if (result < 0 && rt != I2400M_RT_BUS) { -		dev_err(dev, "%s reset failed (%d); trying SDIO reset\n", -			rt == I2400M_RT_WARM ? "warm" : "cold", result); -		rt = I2400M_RT_BUS; -		goto do_bus_reset; -	} -	return result; -} - - -static -void i2400ms_netdev_setup(struct net_device *net_dev) -{ -	struct i2400m *i2400m = net_dev_to_i2400m(net_dev); -	struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m); -	i2400ms_init(i2400ms); -	i2400m_netdev_setup(net_dev); -} - - -/* - * Debug levels control; see debug.h - */ -struct d_level D_LEVEL[] = { -	D_SUBMODULE_DEFINE(main), -	D_SUBMODULE_DEFINE(tx), -	D_SUBMODULE_DEFINE(rx), -	D_SUBMODULE_DEFINE(fw), -}; -size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL); - - -#define __debugfs_register(prefix, name, parent)			\ -do {									\ -	result = d_level_register_debugfs(prefix, name, parent);	\ -	if (result < 0)							\ -		goto error;						\ -} while (0) - - -static -int i2400ms_debugfs_add(struct i2400ms *i2400ms) -{ -	int result; -	struct dentry *dentry = i2400ms->i2400m.wimax_dev.debugfs_dentry; - -	dentry = debugfs_create_dir("i2400m-sdio", dentry); -	result = PTR_ERR(dentry); -	if (IS_ERR(dentry)) { -		if (result == -ENODEV) -			result = 0;	/* No debugfs support */ -		goto error; -	} -	i2400ms->debugfs_dentry = dentry; -	__debugfs_register("dl_", main, dentry); -	__debugfs_register("dl_", tx, dentry); -	__debugfs_register("dl_", rx, dentry); -	__debugfs_register("dl_", fw, dentry); - -	return 0; - -error: -	debugfs_remove_recursive(i2400ms->debugfs_dentry); -	i2400ms->debugfs_dentry = NULL; -	return result; -} - - -static struct device_type i2400ms_type = { -	.name	= "wimax", -}; - -/* - * Probe a i2400m interface and register it - * - * @func:    SDIO function - * @id:      SDIO device ID - * @returns: 0 if ok, < 0 errno code on error. - * - * Alloc a net device, initialize the bus-specific details and then - * calls the bus-generic initialization routine. That will register - * the wimax and netdev devices, upload the firmware [using - * _bus_bm_*()], call _bus_dev_start() to finalize the setup of the - * communication with the device and then will start to talk to it to - * finnish setting it up. - * - * Initialization is tricky; some instances of the hw are packed with - * others in a way that requires a third driver that enables the WiMAX - * function. In those cases, we can't enable the SDIO function and - * we'll return with -ENODEV. When the driver that enables the WiMAX - * function does its thing, it has to do a bus_rescan_devices() on the - * SDIO bus so this driver is called again to enumerate the WiMAX - * function. - */ -static -int i2400ms_probe(struct sdio_func *func, -		  const struct sdio_device_id *id) -{ -	int result; -	struct net_device *net_dev; -	struct device *dev = &func->dev; -	struct i2400m *i2400m; -	struct i2400ms *i2400ms; - -	/* Allocate instance [calls i2400m_netdev_setup() on it]. */ -	result = -ENOMEM; -	net_dev = alloc_netdev(sizeof(*i2400ms), "wmx%d", -			       i2400ms_netdev_setup); -	if (net_dev == NULL) { -		dev_err(dev, "no memory for network device instance\n"); -		goto error_alloc_netdev; -	} -	SET_NETDEV_DEV(net_dev, dev); -	SET_NETDEV_DEVTYPE(net_dev, &i2400ms_type); -	i2400m = net_dev_to_i2400m(net_dev); -	i2400ms = container_of(i2400m, struct i2400ms, i2400m); -	i2400m->wimax_dev.net_dev = net_dev; -	i2400ms->func = func; -	sdio_set_drvdata(func, i2400ms); - -	i2400m->bus_tx_block_size = I2400MS_BLK_SIZE; -	/* -	 * Room required in the TX queue for SDIO message to accommodate -	 * a smallest payload while allocating header space is 224 bytes, -	 * which is the smallest message size(the block size 256 bytes) -	 * minus the smallest message header size(32 bytes). -	 */ -	i2400m->bus_tx_room_min = I2400MS_BLK_SIZE - I2400M_PL_ALIGN * 2; -	i2400m->bus_pl_size_max = I2400MS_PL_SIZE_MAX; -	i2400m->bus_setup = i2400ms_bus_setup; -	i2400m->bus_dev_start = i2400ms_bus_dev_start; -	i2400m->bus_dev_stop = NULL; -	i2400m->bus_release = i2400ms_bus_release; -	i2400m->bus_tx_kick = i2400ms_bus_tx_kick; -	i2400m->bus_reset = i2400ms_bus_reset; -	/* The iwmc3200-wimax sometimes requires the driver to try -	 * hard when we paint it into a corner. */ -	i2400m->bus_bm_retries = I2400M_SDIO_BOOT_RETRIES; -	i2400m->bus_bm_cmd_send = i2400ms_bus_bm_cmd_send; -	i2400m->bus_bm_wait_for_ack = i2400ms_bus_bm_wait_for_ack; -	i2400m->bus_fw_names = i2400ms_bus_fw_names; -	i2400m->bus_bm_mac_addr_impaired = 1; -	i2400m->bus_bm_pokes_table = &i2400ms_pokes[0]; - -	switch (func->device) { -	case SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX: -	case SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX_2G5: -		i2400ms->iwmc3200 = 1; -		break; -	default: -		i2400ms->iwmc3200 = 0; -	} - -	result = i2400m_setup(i2400m, I2400M_BRI_NO_REBOOT); -	if (result < 0) { -		dev_err(dev, "cannot setup device: %d\n", result); -		goto error_setup; -	} - -	result = i2400ms_debugfs_add(i2400ms); -	if (result < 0) { -		dev_err(dev, "cannot create SDIO debugfs: %d\n", -			result); -		goto error_debugfs_add; -	} -	return 0; - -error_debugfs_add: -	i2400m_release(i2400m); -error_setup: -	sdio_set_drvdata(func, NULL); -	free_netdev(net_dev); -error_alloc_netdev: -	return result; -} - - -static -void i2400ms_remove(struct sdio_func *func) -{ -	struct device *dev = &func->dev; -	struct i2400ms *i2400ms = sdio_get_drvdata(func); -	struct i2400m *i2400m = &i2400ms->i2400m; -	struct net_device *net_dev = i2400m->wimax_dev.net_dev; - -	d_fnstart(3, dev, "SDIO func %p\n", func); -	debugfs_remove_recursive(i2400ms->debugfs_dentry); -	i2400ms->debugfs_dentry = NULL; -	i2400m_release(i2400m); -	sdio_set_drvdata(func, NULL); -	free_netdev(net_dev); -	d_fnend(3, dev, "SDIO func %p\n", func); -} - -static -const struct sdio_device_id i2400ms_sdio_ids[] = { -	/* Intel: i2400m WiMAX (iwmc3200) over SDIO */ -	{ SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, -		      SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX) }, -	{ SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, -		      SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX_2G5) }, -	{ /* end: all zeroes */ }, -}; -MODULE_DEVICE_TABLE(sdio, i2400ms_sdio_ids); - - -static -struct sdio_driver i2400m_sdio_driver = { -	.name		= KBUILD_MODNAME, -	.probe		= i2400ms_probe, -	.remove		= i2400ms_remove, -	.id_table	= i2400ms_sdio_ids, -}; - - -static -int __init i2400ms_driver_init(void) -{ -	d_parse_params(D_LEVEL, D_LEVEL_SIZE, i2400ms_debug_params, -		       "i2400m_sdio.debug"); -	return sdio_register_driver(&i2400m_sdio_driver); -} -module_init(i2400ms_driver_init); - - -static -void __exit i2400ms_driver_exit(void) -{ -	flush_scheduled_work();	/* for the stuff we schedule */ -	sdio_unregister_driver(&i2400m_sdio_driver); -} -module_exit(i2400ms_driver_exit); - - -MODULE_AUTHOR("Intel Corporation <linux-wimax@intel.com>"); -MODULE_DESCRIPTION("Intel 2400M WiMAX networking for SDIO"); -MODULE_LICENSE("GPL"); -MODULE_FIRMWARE(I2400MS_FW_FILE_NAME); diff --git a/drivers/net/wimax/i2400m/tx.c b/drivers/net/wimax/i2400m/tx.c index 3f819efc06b..f20886ade1c 100644 --- a/drivers/net/wimax/i2400m/tx.c +++ b/drivers/net/wimax/i2400m/tx.c @@ -149,7 +149,7 @@   * (with a moved message header to make sure it is size-aligned to   * 16), TAIL room that was unusable (and thus is marked with a message   * header that says 'skip this') and at the head of the buffer, an - * imcomplete message with a couple of payloads. + * incomplete message with a couple of payloads.   *   * N   ___________________________________________________   *    |                                                   | @@ -245,6 +245,7 @@   */  #include <linux/netdevice.h>  #include <linux/slab.h> +#include <linux/export.h>  #include "i2400m.h" @@ -561,7 +562,7 @@ void i2400m_tx_new(struct i2400m *i2400m)  {  	struct device *dev = i2400m_dev(i2400m);  	struct i2400m_msg_hdr *tx_msg; -	bool try_head = 0; +	bool try_head = false;  	BUG_ON(i2400m->tx_msg != NULL);  	/*  	 * In certain situations, TX queue might have enough space to @@ -579,7 +580,7 @@ try_head:  	else if (tx_msg == TAIL_FULL) {  		i2400m_tx_skip_tail(i2400m);  		d_printf(2, dev, "new TX message: tail full, trying head\n"); -		try_head = 1; +		try_head = true;  		goto try_head;  	}  	memset(tx_msg, 0, I2400M_TX_PLD_SIZE); @@ -719,7 +720,7 @@ int i2400m_tx(struct i2400m *i2400m, const void *buf, size_t buf_len,  	unsigned long flags;  	size_t padded_len;  	void *ptr; -	bool try_head = 0; +	bool try_head = false;  	unsigned is_singleton = pl_type == I2400M_PT_RESET_WARM  		|| pl_type == I2400M_PT_RESET_COLD; @@ -770,7 +771,7 @@ try_new:  		d_printf(2, dev, "pl append: tail full\n");  		i2400m_tx_close(i2400m);  		i2400m_tx_skip_tail(i2400m); -		try_head = 1; +		try_head = true;  		goto try_new;  	} else if (ptr == NULL) {	/* All full */  		result = -ENOSPC; @@ -819,7 +820,7 @@ EXPORT_SYMBOL_GPL(i2400m_tx);   * the FIF that is ready for transmission.   *   * It sets the state in @i2400m to indicate the bus-specific driver is - * transfering that message (i2400m->tx_msg_size). + * transferring that message (i2400m->tx_msg_size).   *   * Once the transfer is completed, call i2400m_tx_msg_sent().   * diff --git a/drivers/net/wimax/i2400m/usb-fw.c b/drivers/net/wimax/i2400m/usb-fw.c index b58ec56b86f..e74664b8492 100644 --- a/drivers/net/wimax/i2400m/usb-fw.c +++ b/drivers/net/wimax/i2400m/usb-fw.c @@ -169,7 +169,7 @@ retry:   *   * Command can be a raw command, which requires no preparation (and   * which might not even be following the command format). Checks that - * the right amount of data was transfered. + * the right amount of data was transferred.   *   * To satisfy USB requirements (no onstack, vmalloc or in data segment   * buffers), we copy the command to i2400m->bm_cmd_buf and send it from @@ -212,7 +212,7 @@ ssize_t i2400mu_bus_bm_cmd_send(struct i2400m *i2400m,  	}  	if (result != cmd_size) {		/* all was transferred? */  		dev_err(dev, "boot-mode cmd %d: incomplete transfer " -			"(%zu vs %zu submitted)\n",  opcode, result, cmd_size); +			"(%zd vs %zu submitted)\n",  opcode, result, cmd_size);  		result = -EIO;  		goto error_cmd_size;  	} diff --git a/drivers/net/wimax/i2400m/usb-notif.c b/drivers/net/wimax/i2400m/usb-notif.c index d44b545f408..fc1355d98bc 100644 --- a/drivers/net/wimax/i2400m/usb-notif.c +++ b/drivers/net/wimax/i2400m/usb-notif.c @@ -199,7 +199,6 @@ int i2400mu_notification_setup(struct i2400mu *i2400mu)  	d_fnstart(4, dev, "(i2400m %p)\n", i2400mu);  	buf = kmalloc(I2400MU_MAX_NOTIFICATION_LEN, GFP_KERNEL | GFP_DMA);  	if (buf == NULL) { -		dev_err(dev, "notification: buffer allocation failed\n");  		ret = -ENOMEM;  		goto error_buf_alloc;  	} diff --git a/drivers/net/wimax/i2400m/usb-rx.c b/drivers/net/wimax/i2400m/usb-rx.c index a26483a812a..b78ee676e10 100644 --- a/drivers/net/wimax/i2400m/usb-rx.c +++ b/drivers/net/wimax/i2400m/usb-rx.c @@ -58,7 +58,7 @@   *    a zillion reads; by serializing, we are throttling.   *   *  - RX data processing can get heavy enough so that it is not - *    appropiate for doing it in the USB callback; thus we run it in a + *    appropriate for doing it in the USB callback; thus we run it in a   *    process context.   *   * We provide a read buffer of an arbitrary size (short of a page); if @@ -277,7 +277,7 @@ retry:  		d_printf(1, dev, "RX: size changed to %d, received %d, "  			 "copied %d, capacity %ld\n",  			 rx_size, read_size, rx_skb->len, -			 (long) (skb_end_pointer(new_skb) - new_skb->head)); +			 (long) skb_end_offset(new_skb));  		goto retry;  	}  		/* In most cases, it happens due to the hardware scheduling a diff --git a/drivers/net/wimax/i2400m/usb-tx.c b/drivers/net/wimax/i2400m/usb-tx.c index c65b9979f87..99ef81b3d5a 100644 --- a/drivers/net/wimax/i2400m/usb-tx.c +++ b/drivers/net/wimax/i2400m/usb-tx.c @@ -168,7 +168,7 @@ retry:  /*   * Get the next TX message in the TX FIFO and send it to the device   * - * Note we exit the loop if i2400mu_tx() fails; that funtion only + * Note we exit the loop if i2400mu_tx() fails; that function only   * fails on hard error (failing to tx a buffer not being one of them,   * see its doc).   * @@ -177,7 +177,6 @@ retry:  static  int i2400mu_txd(void *_i2400mu)  { -	int result = 0;  	struct i2400mu *i2400mu = _i2400mu;  	struct i2400m *i2400m = &i2400mu->i2400m;  	struct device *dev = &i2400mu->usb_iface->dev; @@ -208,16 +207,14 @@ int i2400mu_txd(void *_i2400mu)  		/* Yeah, we ignore errors ... not much we can do */  		i2400mu_tx(i2400mu, tx_msg, tx_msg_size);  		i2400m_tx_msg_sent(i2400m);	/* ack it, advance the FIFO */ -		if (result < 0) -			break;  	}  	spin_lock_irqsave(&i2400m->tx_lock, flags);  	i2400mu->tx_kthread = NULL;  	spin_unlock_irqrestore(&i2400m->tx_lock, flags); -	d_fnend(4, dev, "(i2400mu %p) = %d\n", i2400mu, result); -	return result; +	d_fnend(4, dev, "(i2400mu %p)\n", i2400mu); +	return 0;  } diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c index d3365ac85dd..cd15a93d908 100644 --- a/drivers/net/wimax/i2400m/usb.c +++ b/drivers/net/wimax/i2400m/usb.c @@ -67,6 +67,7 @@  #include <linux/wimax/i2400m.h>  #include <linux/debugfs.h>  #include <linux/slab.h> +#include <linux/module.h>  #define D_SUBMODULE usb @@ -338,6 +339,23 @@ int i2400mu_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt)  	return result;  } +static void i2400mu_get_drvinfo(struct net_device *net_dev, +                                struct ethtool_drvinfo *info) +{ +	struct i2400m *i2400m = net_dev_to_i2400m(net_dev); +	struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m); +	struct usb_device *udev = i2400mu->usb_dev; + +	strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); +	strlcpy(info->fw_version, i2400m->fw_name ? : "", +		sizeof(info->fw_version)); +	usb_make_path(udev, info->bus_info, sizeof(info->bus_info)); +} + +static const struct ethtool_ops i2400mu_ethtool_ops = { +	.get_drvinfo = i2400mu_get_drvinfo, +	.get_link = ethtool_op_get_link, +};  static  void i2400mu_netdev_setup(struct net_device *net_dev) @@ -346,6 +364,7 @@ void i2400mu_netdev_setup(struct net_device *net_dev)  	struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m);  	i2400mu_init(i2400mu);  	i2400m_netdev_setup(net_dev); +	net_dev->ethtool_ops = &i2400mu_ethtool_ops;  } @@ -491,6 +510,9 @@ int i2400mu_probe(struct usb_interface *iface,  	switch (id->idProduct) {  	case USB_DEVICE_ID_I6050:  	case USB_DEVICE_ID_I6050_2: +	case USB_DEVICE_ID_I6150: +	case USB_DEVICE_ID_I6150_2: +	case USB_DEVICE_ID_I6150_3:  	case USB_DEVICE_ID_I6250:  		i2400mu->i6050 = 1;  		break; @@ -514,7 +536,7 @@ int i2400mu_probe(struct usb_interface *iface,  #ifdef CONFIG_PM  	iface->needs_remote_wakeup = 1;		/* autosuspend (15s delay) */  	device_init_wakeup(dev, 1); -	usb_dev->autosuspend_delay = 15 * HZ; +	pm_runtime_set_autosuspend_delay(&usb_dev->dev, 15000);  	usb_enable_autosuspend(usb_dev);  #endif @@ -599,7 +621,7 @@ void i2400mu_disconnect(struct usb_interface *iface)   *   *    As well, the device might refuse going to sleep for whichever   *    reason. In this case we just fail. For system suspend/hibernate, - *    we *can't* fail. We check PM_EVENT_AUTO to see if the + *    we *can't* fail. We check PMSG_IS_AUTO to see if the   *    suspend call comes from the USB stack or from the system and act   *    in consequence.   * @@ -615,7 +637,7 @@ int i2400mu_suspend(struct usb_interface *iface, pm_message_t pm_msg)  	struct i2400m *i2400m = &i2400mu->i2400m;  #ifdef CONFIG_PM -	if (pm_msg.event & PM_EVENT_AUTO) +	if (PMSG_IS_AUTO(pm_msg))  		is_autosuspend = 1;  #endif @@ -676,7 +698,7 @@ int i2400mu_resume(struct usb_interface *iface)  	d_fnstart(3, dev, "(iface %p)\n", iface);  	rmb();		/* see i2400m->updown's documentation  */  	if (i2400m->updown == 0) { -		d_printf(1, dev, "fw was down, no resume neeed\n"); +		d_printf(1, dev, "fw was down, no resume needed\n");  		goto out;  	}  	d_printf(1, dev, "fw was up, resuming\n"); @@ -740,6 +762,9 @@ static  struct usb_device_id i2400mu_id_table[] = {  	{ USB_DEVICE(0x8086, USB_DEVICE_ID_I6050) },  	{ USB_DEVICE(0x8086, USB_DEVICE_ID_I6050_2) }, +	{ USB_DEVICE(0x8087, USB_DEVICE_ID_I6150) }, +	{ USB_DEVICE(0x8087, USB_DEVICE_ID_I6150_2) }, +	{ USB_DEVICE(0x8087, USB_DEVICE_ID_I6150_3) },  	{ USB_DEVICE(0x8086, USB_DEVICE_ID_I6250) },  	{ USB_DEVICE(0x8086, 0x0181) },  	{ USB_DEVICE(0x8086, 0x1403) }, @@ -780,7 +805,6 @@ module_init(i2400mu_driver_init);  static  void __exit i2400mu_driver_exit(void)  { -	flush_scheduled_work();	/* for the stuff we schedule from sysfs.c */  	usb_deregister(&i2400mu_driver);  }  module_exit(i2400mu_driver_exit);  | 
