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; }
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; }
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); }
/* * 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; }
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)); }
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; }
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; }
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; }
/* * 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; }
/* * 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; }
/* * 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; }
/* * 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; }