Example #1
0
File: usb.c Project: Anjali05/linux
static
void i2400mu_netdev_setup(struct net_device *net_dev)
{
	struct i2400m *i2400m = net_dev_to_i2400m(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;
}
Example #2
0
static
int i2400m_stop(struct net_device *net_dev)
{
	struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
	struct device *dev = i2400m_dev(i2400m);

	d_fnstart(3, dev, "(net_dev %p [i2400m %p])\n", net_dev, i2400m);
	i2400m_net_wake_stop(i2400m);
	d_fnend(3, dev, "(net_dev %p [i2400m %p]) = 0\n", net_dev, i2400m);
	return 0;
}
Example #3
0
static void i2400m_get_drvinfo(struct net_device *net_dev,
			       struct ethtool_drvinfo *info)
{
	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);
	if (net_dev->dev.parent)
		strncpy(info->bus_info, dev_name(net_dev->dev.parent),
			sizeof(info->bus_info) - 1);
}
Example #4
0
/*
 * Create a fake ethernet header
 *
 * For emulating an ethernet device, every received IP header has to
 * be prefixed with an ethernet header. Fake it with the given
 * protocol.
 */
static
void i2400m_rx_fake_eth_header(struct net_device *net_dev,
			       void *_eth_hdr, __be16 protocol)
{
	struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
	struct ethhdr *eth_hdr = _eth_hdr;

	memcpy(eth_hdr->h_dest, net_dev->dev_addr, sizeof(eth_hdr->h_dest));
	memcpy(eth_hdr->h_source, i2400m->src_mac_addr,
	       sizeof(eth_hdr->h_source));
	eth_hdr->h_proto = protocol;
}
Example #5
0
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;

	strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver) - 1);
	strncpy(info->fw_version,
	        i2400m->fw_name ? : "", sizeof(info->fw_version) - 1);
	usb_make_path(udev, info->bus_info, sizeof(info->bus_info));
}
Example #6
0
static
int i2400m_change_mtu(struct net_device *net_dev, int new_mtu)
{
	int result;
	struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
	struct device *dev = i2400m_dev(i2400m);

	if (new_mtu >= I2400M_MAX_MTU) {
		dev_err(dev, "Cannot change MTU to %d (max is %d)\n",
			new_mtu, I2400M_MAX_MTU);
		result = -EINVAL;
	} else {
		net_dev->mtu = new_mtu;
		result = 0;
	}
	return result;
}
Example #7
0
static
int i2400m_open(struct net_device *net_dev)
{
	int result;
	struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
	struct device *dev = i2400m_dev(i2400m);

	d_fnstart(3, dev, "(net_dev %p [i2400m %p])\n", net_dev, i2400m);
	if (i2400m->ready == 0) {
		dev_err(dev, "Device is still initializing\n");
		result = -EBUSY;
	} else
		result = 0;
	d_fnend(3, dev, "(net_dev %p [i2400m %p]) = %d\n",
		net_dev, i2400m, result);
	return result;
}
Example #8
0
static
int i2400m_open(struct net_device *net_dev)
{
	int result;
	struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
	struct device *dev = i2400m_dev(i2400m);

	d_fnstart(3, dev, "(net_dev %p [i2400m %p])\n", net_dev, i2400m);
	/* Make sure we wait until init is complete... */
	mutex_lock(&i2400m->init_mutex);
	if (i2400m->updown)
		result = 0;
	else
		result = -EBUSY;
	mutex_unlock(&i2400m->init_mutex);
	d_fnend(3, dev, "(net_dev %p [i2400m %p]) = %d\n",
		net_dev, i2400m, result);
	return result;
}
Example #9
0
/*
 * Transmit a packet to the base station on behalf of the network stack
 *
 *
 * Returns: NETDEV_TX_OK (always, even in case of error)
 *
 * In case of error, we just drop it. Reasons:
 *
 *  - we add a hw header to each skb, and if the network stack
 *    retries, we have no way to know if that skb has it or not.
 *
 *  - network protocols have their own drop-recovery mechanisms
 *
 *  - there is not much else we can do
 *
 * If the device is idle, we need to wake it up; that is an operation
 * that will sleep. See i2400m_net_wake_tx() for details.
 */
static
netdev_tx_t i2400m_hard_start_xmit(struct sk_buff *skb,
					 struct net_device *net_dev)
{
	struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
	struct device *dev = i2400m_dev(i2400m);
	int result;

	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 (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)
		net_dev->stats.tx_dropped++;
	else {
		net_dev->stats.tx_packets++;
		net_dev->stats.tx_bytes += skb->len;
	}
	result = NETDEV_TX_OK;
error_expand:
	kfree_skb(skb);
	d_fnend(3, dev, "(skb %p net_dev %p) = %d\n", skb, net_dev, result);
	return result;
}
Example #10
0
/*
 * Transmit a packet to the base station on behalf of the network stack
 *
 *
 * Returns: NETDEV_TX_OK (always, even in case of error)
 *
 * In case of error, we just drop it. Reasons:
 *
 *  - we add a hw header to each skb, and if the network stack
 *    retries, we have no way to know if that skb has it or not.
 *
 *  - network protocols have their own drop-recovery mechanisms
 *
 *  - there is not much else we can do
 *
 * If the device is idle, we need to wake it up; that is an operation
 * that will sleep. See i2400m_net_wake_tx() for details.
 */
static
int i2400m_hard_start_xmit(struct sk_buff *skb,
			   struct net_device *net_dev)
{
	int result;
	struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
	struct device *dev = i2400m_dev(i2400m);

	d_fnstart(3, dev, "(skb %p net_dev %p)\n", skb, net_dev);
	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)
		net_dev->stats.tx_dropped++;
	else {
		net_dev->stats.tx_packets++;
		net_dev->stats.tx_bytes += skb->len;
	}
	kfree_skb(skb);
	result = NETDEV_TX_OK;
	d_fnend(3, dev, "(skb %p net_dev %p) = %d\n", skb, net_dev, result);
	return result;
}
/*
 * Probe a i2400m interface and register it
 *
 * @iface:   USB interface to link to
 * @id:      USB class/subclass/protocol 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.
 */
static
int i2400mu_probe(struct usb_interface *iface,
		  const struct usb_device_id *id)
{
	int result;
	struct net_device *net_dev;
	struct device *dev = &iface->dev;
	struct i2400m *i2400m;
	struct i2400mu *i2400mu;
	struct usb_device *usb_dev = interface_to_usbdev(iface);

	if (usb_dev->speed != USB_SPEED_HIGH)
		dev_err(dev, "device not connected as high speed\n");

	/* Allocate instance [calls i2400m_netdev_setup() on it]. */
	result = -ENOMEM;
	net_dev = alloc_netdev(sizeof(*i2400mu), "wmx%d",
			       i2400mu_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, &i2400mu_type);
	i2400m = net_dev_to_i2400m(net_dev);
	i2400mu = container_of(i2400m, struct i2400mu, i2400m);
	i2400m->wimax_dev.net_dev = net_dev;
	i2400mu->usb_dev = usb_get_dev(usb_dev);
	i2400mu->usb_iface = iface;
	usb_set_intfdata(iface, i2400mu);

	i2400m->bus_tx_block_size = I2400MU_BLK_SIZE;
	/*
	 * Room required in the Tx queue for USB message to accommodate
	 * a smallest payload while allocating header space is 16 bytes.
	 * Adding this room  for the new tx message increases the
	 * possibilities of including any payload with size <= 16 bytes.
	 */
	i2400m->bus_tx_room_min = I2400MU_BLK_SIZE;
	i2400m->bus_pl_size_max = I2400MU_PL_SIZE_MAX;
	i2400m->bus_setup = NULL;
	i2400m->bus_dev_start = i2400mu_bus_dev_start;
	i2400m->bus_dev_stop = i2400mu_bus_dev_stop;
	i2400m->bus_release = NULL;
	i2400m->bus_tx_kick = i2400mu_bus_tx_kick;
	i2400m->bus_reset = i2400mu_bus_reset;
	i2400m->bus_bm_retries = I2400M_USB_BOOT_RETRIES;
	i2400m->bus_bm_cmd_send = i2400mu_bus_bm_cmd_send;
	i2400m->bus_bm_wait_for_ack = i2400mu_bus_bm_wait_for_ack;
	i2400m->bus_bm_mac_addr_impaired = 0;

	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;
	default:
		break;
	}

	if (i2400mu->i6050) {
		i2400m->bus_fw_names = i2400mu_bus_fw_names_6050;
		i2400mu->endpoint_cfg.bulk_out = 0;
		i2400mu->endpoint_cfg.notification = 3;
		i2400mu->endpoint_cfg.reset_cold = 2;
		i2400mu->endpoint_cfg.bulk_in = 1;
	} else {
		i2400m->bus_fw_names = i2400mu_bus_fw_names_5x50;
		i2400mu->endpoint_cfg.bulk_out = 0;
		i2400mu->endpoint_cfg.notification = 1;
		i2400mu->endpoint_cfg.reset_cold = 2;
		i2400mu->endpoint_cfg.bulk_in = 3;
	}
#ifdef CONFIG_PM
	iface->needs_remote_wakeup = 1;		/* autosuspend (15s delay) */
	device_init_wakeup(dev, 1);
	pm_runtime_set_autosuspend_delay(&usb_dev->dev, 15000);
	usb_enable_autosuspend(usb_dev);
#endif

	result = i2400m_setup(i2400m, I2400M_BRI_MAC_REINIT);
	if (result < 0) {
		dev_err(dev, "cannot setup device: %d\n", result);
		goto error_setup;
	}
	result = i2400mu_debugfs_add(i2400mu);
	if (result < 0) {
		dev_err(dev, "Can't register i2400mu's debugfs: %d\n", result);
		goto error_debugfs_add;
	}
	return 0;

error_debugfs_add:
	i2400m_release(i2400m);
error_setup:
	usb_set_intfdata(iface, NULL);
	usb_put_dev(i2400mu->usb_dev);
	free_netdev(net_dev);
error_alloc_netdev:
	return result;
}
Example #12
0
/*
 * 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;
}
Example #13
0
/*
 * Probe a i2400m interface and register it
 *
 * @iface:   USB interface to link to
 * @id:      USB class/subclass/protocol 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.
 */
static
int i2400mu_probe(struct usb_interface *iface,
		  const struct usb_device_id *id)
{
	int result;
	struct net_device *net_dev;
	struct device *dev = &iface->dev;
	struct i2400m *i2400m;
	struct i2400mu *i2400mu;
	struct usb_device *usb_dev = interface_to_usbdev(iface);

	if (usb_dev->speed != USB_SPEED_HIGH)
		dev_err(dev, "device not connected as high speed\n");

	/* Allocate instance [calls i2400m_netdev_setup() on it]. */
	result = -ENOMEM;
	net_dev = alloc_netdev(sizeof(*i2400mu), "wmx%d",
			       i2400mu_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, &i2400mu_type);
	i2400m = net_dev_to_i2400m(net_dev);
	i2400mu = container_of(i2400m, struct i2400mu, i2400m);
	i2400m->wimax_dev.net_dev = net_dev;
	i2400mu->usb_dev = usb_get_dev(usb_dev);
	i2400mu->usb_iface = iface;
	usb_set_intfdata(iface, i2400mu);

	i2400m->bus_tx_block_size = I2400MU_BLK_SIZE;
	i2400m->bus_pl_size_max = I2400MU_PL_SIZE_MAX;
	i2400m->bus_dev_start = i2400mu_bus_dev_start;
	i2400m->bus_dev_stop = i2400mu_bus_dev_stop;
	i2400m->bus_tx_kick = i2400mu_bus_tx_kick;
	i2400m->bus_reset = i2400mu_bus_reset;
	i2400m->bus_bm_retries = I2400M_BOOT_RETRIES;
	i2400m->bus_bm_cmd_send = i2400mu_bus_bm_cmd_send;
	i2400m->bus_bm_wait_for_ack = i2400mu_bus_bm_wait_for_ack;
	i2400m->bus_fw_names = i2400mu_bus_fw_names;
	i2400m->bus_bm_mac_addr_impaired = 0;

#ifdef CONFIG_PM
	iface->needs_remote_wakeup = 1;		/* autosuspend (15s delay) */
	device_init_wakeup(dev, 1);
	usb_autopm_enable(i2400mu->usb_iface);
	usb_dev->autosuspend_delay = 15 * HZ;
	usb_dev->autosuspend_disabled = 0;
#endif

	result = i2400m_setup(i2400m, I2400M_BRI_MAC_REINIT);
	if (result < 0) {
		dev_err(dev, "cannot setup device: %d\n", result);
		goto error_setup;
	}
	result = i2400mu_debugfs_add(i2400mu);
	if (result < 0) {
		dev_err(dev, "Can't register i2400mu's debugfs: %d\n", result);
		goto error_debugfs_add;
	}
	return 0;

error_debugfs_add:
	i2400m_release(i2400m);
error_setup:
	usb_set_intfdata(iface, NULL);
	usb_put_dev(i2400mu->usb_dev);
	free_netdev(net_dev);
error_alloc_netdev:
	return result;
}