/** * if_usb_send_fw_pkt - This function downloads the FW * * @priv pointer to struct lbtf_private * * Returns: 0 */ static int if_usb_send_fw_pkt(struct if_usb_card *cardp) { struct fwdata *fwdata = cardp->ep_out_buf; u8 *firmware = (u8 *) cardp->fw->data; lbtf_deb_enter(LBTF_DEB_FW); /* If we got a CRC failure on the last block, back up and retry it */ if (!cardp->CRC_OK) { cardp->totalbytes = cardp->fwlastblksent; cardp->fwseqnum--; } lbtf_deb_usb2(&cardp->udev->dev, "totalbytes = %d\n", cardp->totalbytes); /* struct fwdata (which we sent to the card) has an extra __le32 field in between the header and the data, which is not in the struct fwheader in the actual firmware binary. Insert the seqnum in the middle... */ memcpy(&fwdata->hdr, &firmware[cardp->totalbytes], sizeof(struct fwheader)); cardp->fwlastblksent = cardp->totalbytes; cardp->totalbytes += sizeof(struct fwheader); memcpy(fwdata->data, &firmware[cardp->totalbytes], le32_to_cpu(fwdata->hdr.datalength)); lbtf_deb_usb2(&cardp->udev->dev, "Data length = %d\n", le32_to_cpu(fwdata->hdr.datalength)); fwdata->seqnum = cpu_to_le32(++cardp->fwseqnum); cardp->totalbytes += le32_to_cpu(fwdata->hdr.datalength); usb_tx_block(cardp, cardp->ep_out_buf, sizeof(struct fwdata) + le32_to_cpu(fwdata->hdr.datalength), 0); if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_DATA_TO_RECV)) { lbtf_deb_usb2(&cardp->udev->dev, "There are data to follow\n"); lbtf_deb_usb2(&cardp->udev->dev, "seqnum = %d totalbytes = %d\n", cardp->fwseqnum, cardp->totalbytes); } else if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) { lbtf_deb_usb2(&cardp->udev->dev, "Host has finished FW downloading\n"); lbtf_deb_usb2(&cardp->udev->dev, "Donwloading FW JUMP BLOCK\n"); /* Host has finished FW downloading * Donwloading FW JUMP BLOCK */ cardp->fwfinalblk = 1; } lbtf_deb_usb2(&cardp->udev->dev, "Firmware download done; size %d\n", cardp->totalbytes); lbtf_deb_leave(LBTF_DEB_FW); return 0; }
/** * if_usb_receive - read data received from the device. * * @urb pointer to struct urb */ static void if_usb_receive(struct urb *urb) { struct if_usb_card *cardp = urb->context; struct sk_buff *skb = cardp->rx_skb; struct lbtf_private *priv = cardp->priv; int recvlength = urb->actual_length; uint8_t *recvbuff = NULL; uint32_t recvtype = 0; __le32 *pkt = (__le32 *) skb->data; lbtf_deb_enter(LBTF_DEB_USB); if (recvlength) { if (urb->status) { lbtf_deb_usbd(&cardp->udev->dev, "RX URB failed: %d\n", urb->status); kfree_skb(skb); goto setup_for_next; } recvbuff = skb->data; recvtype = le32_to_cpu(pkt[0]); lbtf_deb_usbd(&cardp->udev->dev, "Recv length = 0x%x, Recv type = 0x%X\n", recvlength, recvtype); } else if (urb->status) { kfree_skb(skb); lbtf_deb_leave(LBTF_DEB_USB); return; } 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 */ u32 event_cause = le32_to_cpu(pkt[1]); lbtf_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n", event_cause); /* Icky undocumented magic special case */ if (event_cause & 0xffff0000) { u16 tmp; u8 retrycnt; u8 failure; tmp = event_cause >> 16; retrycnt = tmp & 0x00ff; failure = (tmp & 0xff00) >> 8; lbtf_send_tx_feedback(priv, retrycnt, failure); } else if (event_cause == LBTF_EVENT_BCN_SENT) lbtf_bcn_sent(priv); else lbtf_deb_usbd(&cardp->udev->dev, "Unsupported notification %d received\n", event_cause); kfree_skb(skb); break; }
/** * if_usb_probe - sets the configuration values * * @ifnum interface number * @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 lbtf_private *priv; struct if_usb_card *cardp; int i; lbtf_deb_enter(LBTF_DEB_USB); 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; iface_desc = intf->cur_altsetting; lbtf_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); lbtf_deb_usbd(&udev->dev, "in_endpoint = %d\n", cardp->ep_in); lbtf_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); lbtf_deb_usbd(&udev->dev, "out_endpoint = %d\n", cardp->ep_out); lbtf_deb_usbd(&udev->dev, "Bulk out size is %d\n", cardp->ep_out_size); } } if (!cardp->ep_out_size || !cardp->ep_in_size) { lbtf_deb_usbd(&udev->dev, "Endpoints not found\n"); /* Endpoints not found */ goto dealloc; } cardp->rx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!cardp->rx_urb) goto dealloc; cardp->tx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!cardp->tx_urb) goto dealloc; cardp->cmd_urb = usb_alloc_urb(0, GFP_KERNEL); if (!cardp->cmd_urb) goto dealloc; cardp->ep_out_buf = kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE, GFP_KERNEL); if (!cardp->ep_out_buf) { lbtf_deb_usbd(&udev->dev, "Could not allocate buffer\n"); goto dealloc; } priv = lbtf_add_card(cardp, &udev->dev); if (!priv) goto dealloc; cardp->priv = priv; priv->hw_host_to_card = if_usb_host_to_card; priv->hw_prog_firmware = if_usb_prog_firmware; priv->hw_reset_device = if_usb_reset_device; cardp->boot2_version = udev->descriptor.bcdDevice; usb_get_dev(udev); usb_set_intfdata(intf, cardp); return 0; dealloc: if_usb_free(cardp); error: lbtf_deb_leave(LBTF_DEB_MAIN); return -ENOMEM; }
static void if_usb_receive_fwload(struct urb *urb) { struct if_usb_card *cardp = urb->context; struct sk_buff *skb = cardp->rx_skb; struct fwsyncheader *syncfwheader; struct bootcmdresp bcmdresp; lbtf_deb_enter(LBTF_DEB_USB); if (urb->status) { lbtf_deb_usbd(&cardp->udev->dev, "URB status is failed during fw load\n"); kfree_skb(skb); lbtf_deb_leave(LBTF_DEB_USB); return; } if (cardp->fwdnldover) { __le32 *tmp = (__le32 *)(skb->data); if (tmp[0] == cpu_to_le32(CMD_TYPE_INDICATION) && tmp[1] == cpu_to_le32(MACREG_INT_CODE_FIRMWARE_READY)) { /* Firmware ready event received */ pr_info("Firmware ready event received\n"); wake_up(&cardp->fw_wq); } else { lbtf_deb_usb("Waiting for confirmation; got %x %x\n", le32_to_cpu(tmp[0]), le32_to_cpu(tmp[1])); if_usb_submit_rx_urb_fwload(cardp); } kfree_skb(skb); lbtf_deb_leave(LBTF_DEB_USB); return; } if (cardp->bootcmdresp <= 0) { memcpy(&bcmdresp, skb->data, sizeof(bcmdresp)); if (le16_to_cpu(cardp->udev->descriptor.bcdDevice) < 0x3106) { kfree_skb(skb); if_usb_submit_rx_urb_fwload(cardp); cardp->bootcmdresp = 1; /* Received valid boot command response */ lbtf_deb_usbd(&cardp->udev->dev, "Received valid boot command response\n"); lbtf_deb_leave(LBTF_DEB_USB); return; } if (bcmdresp.magic != cpu_to_le32(BOOT_CMD_MAGIC_NUMBER)) { if (bcmdresp.magic == cpu_to_le32(CMD_TYPE_REQUEST) || bcmdresp.magic == cpu_to_le32(CMD_TYPE_DATA) || bcmdresp.magic == cpu_to_le32(CMD_TYPE_INDICATION)) { if (!cardp->bootcmdresp) pr_info("Firmware already seems alive; resetting\n"); cardp->bootcmdresp = -1; } else { pr_info("boot cmd response wrong magic number (0x%x)\n", le32_to_cpu(bcmdresp.magic)); } } else if (bcmdresp.cmd != BOOT_CMD_FW_BY_USB) { pr_info("boot cmd response cmd_tag error (%d)\n", bcmdresp.cmd); } else if (bcmdresp.result != BOOT_CMD_RESP_OK) { pr_info("boot cmd response result error (%d)\n", bcmdresp.result); } else { cardp->bootcmdresp = 1; lbtf_deb_usbd(&cardp->udev->dev, "Received valid boot command response\n"); } kfree_skb(skb); if_usb_submit_rx_urb_fwload(cardp); lbtf_deb_leave(LBTF_DEB_USB); return; } syncfwheader = kmemdup(skb->data, sizeof(struct fwsyncheader), GFP_ATOMIC); if (!syncfwheader) { lbtf_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n"); kfree_skb(skb); lbtf_deb_leave(LBTF_DEB_USB); return; } if (!syncfwheader->cmd) { lbtf_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n"); lbtf_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n", le32_to_cpu(syncfwheader->seqnum)); cardp->CRC_OK = 1; } else { lbtf_deb_usbd(&cardp->udev->dev, "FW received Blk with CRC error\n"); cardp->CRC_OK = 0; } kfree_skb(skb); /* reschedule timer for 200ms hence */ mod_timer(&cardp->fw_timeout, jiffies + (HZ/5)); if (cardp->fwfinalblk) { cardp->fwdnldover = 1; goto exit; } if_usb_send_fw_pkt(cardp); exit: if_usb_submit_rx_urb_fwload(cardp); kfree(syncfwheader); lbtf_deb_leave(LBTF_DEB_USB); }