static void if_usb_setup_firmware(struct lbtf_private *priv) { struct if_usb_card *cardp = priv->card; struct cmd_ds_set_boot2_ver b2_cmd; if_usb_submit_rx_urb(cardp); b2_cmd.hdr.size = cpu_to_le16(sizeof(b2_cmd)); b2_cmd.action = 0; b2_cmd.version = cardp->boot2_version; if (lbtf_cmd_with_response(priv, CMD_SET_BOOT2_VER, &b2_cmd)) printk(KERN_INFO "libertastf: setting boot2 version failed\n"); }
static void if_usb_setup_firmware(struct lbtf_private *priv) { struct if_usb_card *cardp = priv->card; struct cmd_ds_set_boot2_ver b2_cmd; lbtf_deb_enter(LBTF_DEB_USB); if_usb_submit_rx_urb(cardp); b2_cmd.hdr.size = cpu_to_le16(sizeof(b2_cmd)); b2_cmd.action = 0; b2_cmd.version = cardp->boot2_version; if (lbtf_cmd_with_response(priv, CMD_SET_BOOT2_VER, &b2_cmd)) lbtf_deb_usb("Setting boot2 version failed\n"); lbtf_deb_leave(LBTF_DEB_USB); }
static int if_usb_resume(struct usb_interface *intf) { struct usb_card_rec *cardp = usb_get_intfdata(intf); wlan_private *priv = cardp->priv; lbs_deb_enter(LBS_DEB_USB); cardp->rx_urb_recall = 0; if_usb_submit_rx_urb(cardp->priv); netif_device_attach(cardp->eth_dev); netif_device_attach(priv->mesh_dev); lbs_deb_leave(LBS_DEB_USB); return 0; }
/** * @brief sets the configuration values * @param ifnum interface number * @param id pointer to usb_device_id * @return 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) { lbs_pr_err("Out of memory allocating private data.\n"); goto error; } setup_timer(&cardp->fw_timeout, if_usb_fw_timeo, (unsigned long)cardp); init_waitqueue_head(&cardp->fw_wq); cardp->udev = udev; 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 */ if (if_usb_prog_firmware(cardp)) { lbs_deb_usbd(&udev->dev, "FW upload failed\n"); goto err_prog_firmware; } if (!(priv = lbs_add_card(cardp, &udev->dev))) goto err_prog_firmware; cardp->priv = priv; cardp->priv->fw_ready = 1; priv->hw_host_to_card = if_usb_host_to_card; #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); 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; }
/** * 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; }
static int if_usb_prog_firmware(wlan_private * priv) { struct usb_card_rec *cardp = priv->card; int i = 0; static int reset_count = 10; int ret = 0; lbs_deb_enter(LBS_DEB_USB); cardp->rinfo.priv = priv; restart: if (if_usb_submit_rx_urb_fwload(priv) < 0) { lbs_deb_usbd(&cardp->udev->dev, "URB submission is failed\n"); ret = -1; goto done; } cardp->bootcmdresp = 0; do { int j = 0; i++; /* Issue Boot command = 1, Boot from Download-FW */ if_usb_issue_boot_command(priv, BOOT_CMD_FW_BY_USB); /* wait for command response */ do { j++; msleep_interruptible(100); } while (cardp->bootcmdresp == 0 && j < 10); } while (cardp->bootcmdresp == 0 && i < 5); if (cardp->bootcmdresp == 0) { if (--reset_count >= 0) { libertas_do_reset(priv); goto restart; } return -1; } i = 0; priv->adapter->fw_ready = 0; cardp->totalbytes = 0; cardp->fwlastblksent = 0; cardp->CRC_OK = 1; cardp->fwdnldover = 0; cardp->fwseqnum = -1; cardp->totalbytes = 0; cardp->fwfinalblk = 0; if_prog_firmware(priv); do { lbs_deb_usbd(&cardp->udev->dev,"Wlan sched timeout\n"); i++; msleep_interruptible(100); if (priv->adapter->surpriseremoved || i >= 20) break; } while (!cardp->fwdnldover); if (!cardp->fwdnldover) { lbs_pr_info("failed to load fw, resetting device!\n"); if (--reset_count >= 0) { libertas_do_reset(priv); goto restart; } lbs_pr_info("FW download failure, time = %d ms\n", i * 100); ret = -1; goto done; } if_usb_submit_rx_urb(priv); /* Delay 200 ms to waiting for the FW ready */ msleep_interruptible(200); priv->adapter->fw_ready = 1; done: lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret); return ret; }
/** * @brief This function reads of the packet into the upload buff, * wake up the main thread and initialise the Rx callack. * * @param urb pointer to struct urb * @return N/A */ static void if_usb_receive(struct urb *urb) { struct read_cb_info *rinfo = (struct read_cb_info *)urb->context; wlan_private *priv = rinfo->priv; struct sk_buff *skb = rinfo->skb; struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card; int recvlength = urb->actual_length; u8 *recvbuff = NULL; u32 recvtype; lbs_deb_enter(LBS_DEB_USB); if (recvlength) { if (urb->status) { lbs_deb_usbd(&cardp->udev->dev, "URB status is failed\n"); kfree_skb(skb); goto setup_for_next; } recvbuff = skb->data + IPFIELD_ALIGN_OFFSET; memcpy(&recvtype, recvbuff, sizeof(u32)); lbs_deb_usbd(&cardp->udev->dev, "Recv length = 0x%x\n", recvlength); lbs_deb_usbd(&cardp->udev->dev, "Receive type = 0x%X\n", recvtype); recvtype = le32_to_cpu(recvtype); lbs_deb_usbd(&cardp->udev->dev, "Receive type after = 0x%X\n", recvtype); } else if (urb->status) goto rx_exit; switch (recvtype) { case CMD_TYPE_DATA: process_cmdtypedata(recvlength, skb, cardp, priv); break; case CMD_TYPE_REQUEST: process_cmdrequest(recvlength, recvbuff, skb, cardp, priv); break; case CMD_TYPE_INDICATION: /* Event cause handling */ spin_lock(&priv->adapter->driver_lock); cardp->usb_event_cause = le32_to_cpu(*(__le32 *) (recvbuff + MESSAGE_HEADER_LEN)); lbs_deb_usbd(&cardp->udev->dev,"**EVENT** 0x%X\n", cardp->usb_event_cause); if (cardp->usb_event_cause & 0xffff0000) { libertas_send_tx_feedback(priv); spin_unlock(&priv->adapter->driver_lock); break; } cardp->usb_event_cause <<= 3; cardp->usb_int_cause |= his_cardevent; kfree_skb(skb); libertas_interrupt(priv->dev); spin_unlock(&priv->adapter->driver_lock); goto rx_exit; default: kfree_skb(skb); break; } setup_for_next: if_usb_submit_rx_urb(priv); rx_exit: lbs_deb_leave(LBS_DEB_USB); }