static void if_usb_setup_firmware(struct lbs_private *priv) { struct if_usb_card *cardp = priv->card; struct cmd_ds_set_boot2_ver b2_cmd; struct cmd_ds_802_11_fw_wake_method wake_method; b2_cmd.hdr.size = cpu_to_le16(sizeof(b2_cmd)); b2_cmd.action = 0; b2_cmd.version = cardp->boot2_version; if (lbs_cmd_with_response(priv, CMD_SET_BOOT2_VER, &b2_cmd)) lbs_deb_usb("Setting boot2 version failed\n"); priv->wol_gpio = 2; /* Wake via GPIO2... */ priv->wol_gap = 20; /* ... after 20ms */ lbs_host_sleep_cfg(priv, EHS_WAKE_ON_UNICAST_DATA); wake_method.hdr.size = cpu_to_le16(sizeof(wake_method)); wake_method.action = cpu_to_le16(CMD_ACT_GET); if (lbs_cmd_with_response(priv, CMD_802_11_FW_WAKE_METHOD, &wake_method)) { lbs_pr_info("Firmware does not seem to support PS mode\n"); } else { if (le16_to_cpu(wake_method.method) == CMD_WAKE_METHOD_COMMAND_INT) { lbs_deb_usb("Firmware seems to support PS with wake-via-command\n"); priv->ps_supported = 1; } else { /* The versions which boot up this way don't seem to work even if we set it to the command interrupt */ lbs_pr_info("Firmware doesn't wake via command interrupt; disabling PS mode\n"); } } }
static int lbs_ethtool_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct lbs_private *priv = dev->ml_priv; uint32_t criteria = 0; if (priv->wol_criteria == 0xffffffff && wol->wolopts) return -EOPNOTSUPP; if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY)) return -EOPNOTSUPP; if (wol->wolopts & WAKE_UCAST) criteria |= EHS_WAKE_ON_UNICAST_DATA; if (wol->wolopts & WAKE_MCAST) criteria |= EHS_WAKE_ON_MULTICAST_DATA; if (wol->wolopts & WAKE_BCAST) criteria |= EHS_WAKE_ON_BROADCAST_DATA; if (wol->wolopts & WAKE_PHY) criteria |= EHS_WAKE_ON_MAC_EVENT; return lbs_host_sleep_cfg(priv, criteria, (struct wol_config *)NULL); }
/** * if_usb_probe - sets the configuration values * @intf: &usb_interface pointer * @id: pointer to usb_device_id * returns: 0 on success, error code on failure */ static int if_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *udev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; struct lbs_private *priv; struct if_usb_card *cardp; int i; udev = interface_to_usbdev(intf); cardp = kzalloc(sizeof(struct if_usb_card), GFP_KERNEL); if (!cardp) goto error; setup_timer(&cardp->fw_timeout, if_usb_fw_timeo, (unsigned long)cardp); init_waitqueue_head(&cardp->fw_wq); cardp->udev = udev; cardp->model = (uint32_t) id->driver_info; iface_desc = intf->cur_altsetting; lbs_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X" " bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n", le16_to_cpu(udev->descriptor.bcdUSB), udev->descriptor.bDeviceClass, udev->descriptor.bDeviceSubClass, udev->descriptor.bDeviceProtocol); for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; if (usb_endpoint_is_bulk_in(endpoint)) { cardp->ep_in_size = le16_to_cpu(endpoint->wMaxPacketSize); cardp->ep_in = usb_endpoint_num(endpoint); lbs_deb_usbd(&udev->dev, "in_endpoint = %d\n", cardp->ep_in); lbs_deb_usbd(&udev->dev, "Bulk in size is %d\n", cardp->ep_in_size); } else if (usb_endpoint_is_bulk_out(endpoint)) { cardp->ep_out_size = le16_to_cpu(endpoint->wMaxPacketSize); cardp->ep_out = usb_endpoint_num(endpoint); lbs_deb_usbd(&udev->dev, "out_endpoint = %d\n", cardp->ep_out); lbs_deb_usbd(&udev->dev, "Bulk out size is %d\n", cardp->ep_out_size); } } if (!cardp->ep_out_size || !cardp->ep_in_size) { lbs_deb_usbd(&udev->dev, "Endpoints not found\n"); goto dealloc; } if (!(cardp->rx_urb = usb_alloc_urb(0, GFP_KERNEL))) { lbs_deb_usbd(&udev->dev, "Rx URB allocation failed\n"); goto dealloc; } if (!(cardp->tx_urb = usb_alloc_urb(0, GFP_KERNEL))) { lbs_deb_usbd(&udev->dev, "Tx URB allocation failed\n"); goto dealloc; } cardp->ep_out_buf = kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE, GFP_KERNEL); if (!cardp->ep_out_buf) { lbs_deb_usbd(&udev->dev, "Could not allocate buffer\n"); goto dealloc; } /* Upload firmware */ kparam_block_sysfs_write(fw_name); if (__if_usb_prog_firmware(cardp, lbs_fw_name, BOOT_CMD_FW_BY_USB)) { kparam_unblock_sysfs_write(fw_name); lbs_deb_usbd(&udev->dev, "FW upload failed\n"); goto err_prog_firmware; } kparam_unblock_sysfs_write(fw_name); if (!(priv = lbs_add_card(cardp, &intf->dev))) goto err_prog_firmware; cardp->priv = priv; cardp->priv->fw_ready = 1; priv->hw_host_to_card = if_usb_host_to_card; priv->enter_deep_sleep = NULL; priv->exit_deep_sleep = NULL; priv->reset_deep_sleep_wakeup = NULL; #ifdef CONFIG_OLPC if (machine_is_olpc()) priv->reset_card = if_usb_reset_olpc_card; #endif cardp->boot2_version = udev->descriptor.bcdDevice; if_usb_submit_rx_urb(cardp); if (lbs_start_card(priv)) goto err_start_card; if_usb_setup_firmware(priv); usb_get_dev(udev); usb_set_intfdata(intf, cardp); if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_fw)) netdev_err(priv->dev, "cannot register lbs_flash_fw attribute\n"); if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_boot2)) netdev_err(priv->dev, "cannot register lbs_flash_boot2 attribute\n"); /* * EHS_REMOVE_WAKEUP is not supported on all versions of the firmware. */ priv->wol_criteria = EHS_REMOVE_WAKEUP; if (lbs_host_sleep_cfg(priv, priv->wol_criteria, NULL)) priv->ehs_remove_supported = false; return 0; err_start_card: lbs_remove_card(priv); err_prog_firmware: if_usb_reset_device(cardp); dealloc: if_usb_free(cardp); error: return -ENOMEM; }