void isl38xx_handle_sleep_request(isl38xx_control_block *control_block, int *powerstate, void __iomem *device_base) { /* device requests to go into sleep mode * check whether the transmit queues for data and management are empty */ if (isl38xx_in_queue(control_block, ISL38XX_CB_TX_DATA_LQ)) /* data tx queue not empty */ return; if (isl38xx_in_queue(control_block, ISL38XX_CB_TX_MGMTQ)) /* management tx queue not empty */ return; /* check also whether received frames are pending */ if (isl38xx_in_queue(control_block, ISL38XX_CB_RX_DATA_LQ)) /* data rx queue not empty */ return; if (isl38xx_in_queue(control_block, ISL38XX_CB_RX_MGMTQ)) /* management rx queue not empty */ return; #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "Device going to sleep mode\n"); #endif /* all queues are empty, allow the device to go into sleep mode */ *powerstate = ISL38XX_PSM_POWERSAVE_STATE; /* assert the Sleep interrupt in the Device Interrupt Register */ isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_SLEEP, ISL38XX_DEV_INT_REG); udelay(ISL38XX_WRITEIO_DELAY); }
void isl38xx_handle_sleep_request(isl38xx_control_block *control_block, int *powerstate, void __iomem *device_base) { if (isl38xx_in_queue(control_block, ISL38XX_CB_TX_DATA_LQ)) return; if (isl38xx_in_queue(control_block, ISL38XX_CB_TX_MGMTQ)) return; if (isl38xx_in_queue(control_block, ISL38XX_CB_RX_DATA_LQ)) return; if (isl38xx_in_queue(control_block, ISL38XX_CB_RX_MGMTQ)) return; #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "Device going to sleep mode\n"); #endif *powerstate = ISL38XX_PSM_POWERSAVE_STATE; isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_SLEEP, ISL38XX_DEV_INT_REG); udelay(ISL38XX_WRITEIO_DELAY); }
void isl38xx_handle_wakeup(isl38xx_control_block *control_block, int *powerstate, void __iomem *device_base) { *powerstate = ISL38XX_PSM_ACTIVE_STATE; if (!isl38xx_in_queue(control_block, ISL38XX_CB_TX_DATA_LQ) && !isl38xx_in_queue(control_block, ISL38XX_CB_TX_MGMTQ)) return; #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_ANYTHING, "Wake up handler trigger the device\n"); #endif isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_UPDATE, ISL38XX_DEV_INT_REG); udelay(ISL38XX_WRITEIO_DELAY); }
void isl38xx_handle_wakeup(isl38xx_control_block *control_block, int *powerstate, void __iomem *device_base) { /* device is in active state, update the powerstate flag */ *powerstate = ISL38XX_PSM_ACTIVE_STATE; /* now check whether there are frames pending for the card */ if (!isl38xx_in_queue(control_block, ISL38XX_CB_TX_DATA_LQ) && !isl38xx_in_queue(control_block, ISL38XX_CB_TX_MGMTQ)) return; #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_ANYTHING, "Wake up handler trigger the device\n"); #endif /* either data or management transmit queue has a frame pending * trigger the device by setting the Update bit in the Device Int reg */ isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_UPDATE, ISL38XX_DEV_INT_REG); udelay(ISL38XX_WRITEIO_DELAY); }
irqreturn_t islpci_interrupt(int irq, void *config) { u32 reg; islpci_private *priv = config; struct net_device *ndev = priv->ndev; void __iomem *device = priv->device_base; int powerstate = ISL38XX_PSM_POWERSAVE_STATE; /* lock the interrupt handler */ spin_lock(&priv->slock); /* received an interrupt request on a shared IRQ line * first check whether the device is in sleep mode */ reg = readl(device + ISL38XX_CTRL_STAT_REG); if (reg & ISL38XX_CTRL_STAT_SLEEPMODE) /* device is in sleep mode, IRQ was generated by someone else */ { #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "Assuming someone else called the IRQ\n"); #endif spin_unlock(&priv->slock); return IRQ_NONE; } /* check whether there is any source of interrupt on the device */ reg = readl(device + ISL38XX_INT_IDENT_REG); /* also check the contents of the Interrupt Enable Register, because this * will filter out interrupt sources from other devices on the same irq ! */ reg &= readl(device + ISL38XX_INT_EN_REG); reg &= ISL38XX_INT_SOURCES; if (reg != 0) { if (islpci_get_state(priv) != PRV_STATE_SLEEP) powerstate = ISL38XX_PSM_ACTIVE_STATE; /* reset the request bits in the Identification register */ isl38xx_w32_flush(device, reg, ISL38XX_INT_ACK_REG); #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_FUNCTION_CALLS, "IRQ: Identification register 0x%p 0x%x \n", device, reg); #endif /* check for each bit in the register separately */ if (reg & ISL38XX_INT_IDENT_UPDATE) { #if VERBOSE > SHOW_ERROR_MESSAGES /* Queue has been updated */ DEBUG(SHOW_TRACING, "IRQ: Update flag \n"); DEBUG(SHOW_QUEUE_INDEXES, "CB drv Qs: [%i][%i][%i][%i][%i][%i]\n", le32_to_cpu(priv->control_block-> driver_curr_frag[0]), le32_to_cpu(priv->control_block-> driver_curr_frag[1]), le32_to_cpu(priv->control_block-> driver_curr_frag[2]), le32_to_cpu(priv->control_block-> driver_curr_frag[3]), le32_to_cpu(priv->control_block-> driver_curr_frag[4]), le32_to_cpu(priv->control_block-> driver_curr_frag[5]) ); DEBUG(SHOW_QUEUE_INDEXES, "CB dev Qs: [%i][%i][%i][%i][%i][%i]\n", le32_to_cpu(priv->control_block-> device_curr_frag[0]), le32_to_cpu(priv->control_block-> device_curr_frag[1]), le32_to_cpu(priv->control_block-> device_curr_frag[2]), le32_to_cpu(priv->control_block-> device_curr_frag[3]), le32_to_cpu(priv->control_block-> device_curr_frag[4]), le32_to_cpu(priv->control_block-> device_curr_frag[5]) ); #endif /* cleanup the data low transmit queue */ islpci_eth_cleanup_transmit(priv, priv->control_block); /* device is in active state, update the * powerstate flag if necessary */ powerstate = ISL38XX_PSM_ACTIVE_STATE; /* check all three queues in priority order * call the PIMFOR receive function until the * queue is empty */ if (isl38xx_in_queue(priv->control_block, ISL38XX_CB_RX_MGMTQ) != 0) { #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "Received frame in Management Queue\n"); #endif islpci_mgt_receive(ndev); islpci_mgt_cleanup_transmit(ndev); /* Refill slots in receive queue */ islpci_mgmt_rx_fill(ndev); /* no need to trigger the device, next islpci_mgt_transaction does it */ } while (isl38xx_in_queue(priv->control_block, ISL38XX_CB_RX_DATA_LQ) != 0) { #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "Received frame in Data Low Queue \n"); #endif islpci_eth_receive(priv); } /* check whether the data transmit queues were full */ if (priv->data_low_tx_full) { /* check whether the transmit is not full anymore */ if (ISL38XX_CB_TX_QSIZE - isl38xx_in_queue(priv->control_block, ISL38XX_CB_TX_DATA_LQ) >= ISL38XX_MIN_QTHRESHOLD) { /* nope, the driver is ready for more network frames */ netif_wake_queue(priv->ndev); /* reset the full flag */ priv->data_low_tx_full = 0; } } } if (reg & ISL38XX_INT_IDENT_INIT) { /* Device has been initialized */ #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "IRQ: Init flag, device initialized \n"); #endif wake_up(&priv->reset_done); } if (reg & ISL38XX_INT_IDENT_SLEEP) { /* Device intends to move to powersave state */ #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "IRQ: Sleep flag \n"); #endif isl38xx_handle_sleep_request(priv->control_block, &powerstate, priv->device_base); } if (reg & ISL38XX_INT_IDENT_WAKEUP) { /* Device has been woken up to active state */ #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "IRQ: Wakeup flag \n"); #endif isl38xx_handle_wakeup(priv->control_block, &powerstate, priv->device_base); } } else { #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "Assuming someone else called the IRQ\n"); #endif spin_unlock(&priv->slock); return IRQ_NONE; } /* sleep -> ready */ if (islpci_get_state(priv) == PRV_STATE_SLEEP && powerstate == ISL38XX_PSM_ACTIVE_STATE) islpci_set_state(priv, PRV_STATE_READY); /* !sleep -> sleep */ if (islpci_get_state(priv) != PRV_STATE_SLEEP && powerstate == ISL38XX_PSM_POWERSAVE_STATE) islpci_set_state(priv, PRV_STATE_SLEEP); /* unlock the interrupt handler */ spin_unlock(&priv->slock); return IRQ_HANDLED; }
int islpci_eth_transmit(struct sk_buff *skb, struct net_device *nwdev) { islpci_private *private_config = nwdev->priv; isl38xx_control_block *control_block = private_config->control_block; isl38xx_fragment *fragment; u32 index, counter, pci_map_address; int fragments; int frame_size; int offset; struct sk_buff *newskb; int newskb_offset; unsigned long flags; unsigned char wds_mac[6]; #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_transmit \n"); #endif // lock the driver code driver_lock( &private_config->slock, &flags ); // check whether the deviec is running // if( !netif_running( nwdev ) ) // { // DEBUG( SHOW_ERROR_MESSAGES, "%s: Tx on stopped device!\n", // nwdev->name); // return 1; // } // tx_timeout_check( nwdev, islpci_eth_tx_timeout ); // skb_tx_check( nwdev, skb ); // determine the amount of fragments needed to store the frame memset (wds_mac, 0, 6); #ifdef WDS_LINKS check_skb_for_wds(skb, wds_mac); #ifdef ISLPCI_ETH_DEBUG if ( wds_mac[0] || wds_mac[1] || wds_mac[2] || wds_mac[3] || wds_mac[4] || wds_mac[5] ) { printk("islpci_eth_transmit:check_skb_for_wds ! %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", wds_mac[0], wds_mac[1], wds_mac[2], wds_mac[3], wds_mac[4], wds_mac[5] ); } else { printk("islpci_eth_transmit:check_skb_for_wds %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", wds_mac[0], wds_mac[1], wds_mac[2], wds_mac[3], wds_mac[4], wds_mac[5] ); } #endif #endif frame_size = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len; if( init_wds ) frame_size += 6; fragments = frame_size / MAX_FRAGMENT_SIZE; fragments += frame_size % MAX_FRAGMENT_SIZE == 0 ? 0 : 1; #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "Fragments needed for frame %i\n", fragments); #endif // check whether the destination queue has enough fragments for the frame if (ISL38XX_CB_TX_QSIZE - isl38xx_in_queue( control_block, ISL38XX_CB_TX_DATA_LQ ) < fragments ) { // Error, cannot add the frame because the queue is full DEBUG(SHOW_ERROR_MESSAGES, "Error: Queue [%i] not enough room\n", ISL38XX_CB_TX_DATA_LQ); // trigger the device by setting the Update bit in the Device Int reg writel(ISL38XX_DEV_INT_UPDATE, private_config->remapped_device_base + ISL38XX_DEV_INT_REG); udelay(ISL38XX_WRITEIO_DELAY); // unlock the driver code driver_unlock( &private_config->slock, &flags ); return -EBUSY; } // Check alignment and WDS frame formatting. The start of the packet should // be aligned on a 4-byte boundary. If WDS is enabled add another 6 bytes // and add WDS address information if( ((int) skb->data & 0x03) | init_wds ) { // get the number of bytes to add and re-allign offset = (int) skb->data & 0x03; offset += init_wds ? 6 : 0; // check whether the current skb can be used if (!skb_cloned(skb) && (skb_tailroom(skb) >= offset)) { unsigned char *src = skb->data; #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "skb offset %i wds %i\n", offset, init_wds ); #endif // allign the buffer on 4-byte boundary skb_reserve(skb, (int) skb->data & 0x03 ); if( init_wds ) { // wds requires an additional address field of 6 bytes skb_put( skb, 6 ); #ifdef ISLPCI_ETH_DEBUG printk("islpci_eth_transmit:wds_mac\n" ); #endif memmove( skb->data+6, src, skb->len ); memcpy( skb->data, wds_mac, 6 ); } else { memmove( skb->data, src, skb->len ); } #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "memmove %p %p %i \n", skb->data, src, skb->len ); #endif } else { newskb = dev_alloc_skb( init_wds ? skb->len+6 : skb->len ); newskb_offset = (int) newskb->data & 0x03; // Check if newskb->data is aligned if( newskb_offset ) skb_reserve(newskb, newskb_offset); skb_put(newskb, init_wds ? skb->len+6 : skb->len ); if( init_wds ) { memcpy( newskb->data+6, skb->data, skb->len ); memcpy( newskb->data, wds_mac, 6 ); #ifdef ISLPCI_ETH_DEBUG printk("islpci_eth_transmit:wds_mac\n" ); #endif } else memcpy( newskb->data, skb->data, skb->len ); #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "memcpy %p %p %i wds %i\n", newskb->data, skb->data, skb->len, init_wds ); #endif newskb->dev = skb->dev; dev_kfree_skb(skb); skb = newskb; } } // display the buffer contents for debugging #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG( SHOW_BUFFER_CONTENTS, "\ntx %p ", skb->data ); display_buffer((char *) skb->data, skb->len ); #endif // map the skb buffer to pci memory for DMA operation pci_map_address = pci_map_single( private_config->pci_device, (void *) skb->data, skb->len, PCI_DMA_TODEVICE ); if( pci_map_address == (dma_addr_t) NULL ) { // error mapping the buffer to device accessable memory address DEBUG(SHOW_ERROR_MESSAGES, "Error map DMA addr, data lost\n" ); // free the skbuf structure before aborting dev_kfree_skb(skb); // unlock the driver code driver_unlock( &private_config->slock, &flags ); return -EIO; } // place each fragment in the control block structure and store in the last // needed fragment entry of the pci_map_tx_address and data_low_tx arrays // the skb frame information for (counter = 0; counter < fragments; counter++ ) { // get a pointer to the target control block fragment index = (counter + le32_to_cpu( control_block->driver_curr_frag[ISL38XX_CB_TX_DATA_LQ])) % ISL38XX_CB_TX_QSIZE; fragment = &control_block->tx_data_low[index]; // check whether this frame fragment is the last one if( counter == fragments-1 ) { // the fragment is the last one, add the streaming DMA mapping for // proper PCI bus operation private_config->pci_map_tx_address[index] = (dma_addr_t) pci_map_address; // store the skb address for future freeing private_config->data_low_tx[index] = skb; } else { // the fragment will be followed by more fragments // clear the pci_map_tx_address and data_low_tx entries private_config->pci_map_tx_address[index] = (dma_addr_t) NULL; private_config->data_low_tx[index] = NULL; } // set the proper fragment start address and size information fragment->address = cpu_to_le32( pci_map_address + counter*MAX_FRAGMENT_SIZE ); fragment->size = cpu_to_le16( frame_size > MAX_FRAGMENT_SIZE ? MAX_FRAGMENT_SIZE : frame_size ); fragment->flags = cpu_to_le16( frame_size > MAX_FRAGMENT_SIZE ? 1 : 0 ); frame_size -= MAX_FRAGMENT_SIZE; } // ready loading all fragements to the control block and setup pci mapping // update the control block interface information add_le32p(&control_block->driver_curr_frag[ISL38XX_CB_TX_DATA_LQ], fragments); // check whether the data tx queue is full now if( ISL38XX_CB_TX_QSIZE - isl38xx_in_queue( control_block, ISL38XX_CB_TX_DATA_LQ ) < ISL38XX_MIN_QTHRESHOLD ) { // stop the transmission of network frames to the driver netif_stop_queue(nwdev); // set the full flag for the data low transmission queue private_config->data_low_tx_full = 1; } // trigger the device isl38xx_trigger_device( &private_config->powerstate, private_config->remapped_device_base ); // set the transmission time nwdev->trans_start = jiffies; private_config->statistics.tx_packets++; private_config->statistics.tx_bytes += skb->len; // cleanup the data low transmit queue islpci_eth_cleanup_transmit( private_config, private_config->control_block ); // unlock the driver code driver_unlock( &private_config->slock, &flags ); return 0; }
/****************************************************************************** Device Interrupt Handler ******************************************************************************/ void islpci_interrupt(int irq, void *config, struct pt_regs *regs) { u32 reg; islpci_private *private_config = config; void *device = private_config->device_id; u16 status; // received an interrupt request on a shared IRQ line // first check whether the device is in sleep mode if( reg = readl( device + ISL38XX_CTRL_STAT_REG), reg & ISL38XX_CTRL_STAT_SLEEPMODE ) // device is in sleep mode, IRQ was generated by someone else return; // lock the interrupt handler spin_lock( &private_config->slock ); #ifdef CONFIG_ARCH_ISL3893 // check the interrupt source on the host registers reg = (u32) uPCI->ARMIntReg; reg &= (u32) uPCI->ARMIntEnReg; // pci_unmap_single( private_config->pci_device, private_config->control_block, // sizeof(struct isl38xx_cb), PCI_DMA_FROMDEVICE ); flush_cache_all(); #else // check whether there is any source of interrupt on the device reg = readl(device + ISL38XX_INT_IDENT_REG); // also check the contents of the Interrupt Enable Register, because this // will filter out interrupt sources from other devices on the same irq ! reg &= readl(device + ISL38XX_INT_EN_REG); #endif if (reg &= ISL38XX_INT_SOURCES, reg != 0) { #ifdef CONFIG_ARCH_ISL3893 // write the acknowledge register on the host uPCI->ARMIntAckReg = reg; #else // reset the request bits in the Identification register writel(reg, device + ISL38XX_INT_ACK_REG); #endif #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_FUNCTION_CALLS, "IRQ: Identification register value 0x%x \n", reg ); #endif // check for each bit in the register separately if (reg & ISL38XX_INT_IDENT_UPDATE) { #if VERBOSE > SHOW_ERROR_MESSAGES // Queue has been updated DEBUG(SHOW_TRACING, "IRQ: Update flag \n"); DEBUG(SHOW_QUEUE_INDEXES, "CB drv Qs: [%i][%i][%i][%i][%i][%i]\n", le32_to_cpu(private_config->control_block->driver_curr_frag[0]), le32_to_cpu(private_config->control_block->driver_curr_frag[1]), le32_to_cpu(private_config->control_block->driver_curr_frag[2]), le32_to_cpu(private_config->control_block->driver_curr_frag[3]), le32_to_cpu(private_config->control_block->driver_curr_frag[4]), le32_to_cpu(private_config->control_block->driver_curr_frag[5]) ); DEBUG(SHOW_QUEUE_INDEXES, "CB dev Qs: [%i][%i][%i][%i][%i][%i]\n", le32_to_cpu(private_config->control_block->device_curr_frag[0]), le32_to_cpu(private_config->control_block->device_curr_frag[1]), le32_to_cpu(private_config->control_block->device_curr_frag[2]), le32_to_cpu(private_config->control_block->device_curr_frag[3]), le32_to_cpu(private_config->control_block->device_curr_frag[4]), le32_to_cpu(private_config->control_block->device_curr_frag[5]) ); #endif // device is in active state, update the powerstate flag private_config->powerstate = ISL38XX_PSM_ACTIVE_STATE; // check all three queues in priority order // call the PIMFOR receive function until the queue is empty while (isl38xx_in_queue(private_config->control_block, ISL38XX_CB_RX_MGMTQ) != 0) { #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "Received frame in Management Queue\n"); #endif islpci_mgt_receive(private_config); // call the pimfor transmit function for processing the next // management frame in the shadow queue islpci_mgt_transmit( private_config ); } while (isl38xx_in_queue(private_config->control_block, ISL38XX_CB_RX_DATA_LQ) != 0) { #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "Received frame in Data Low Queue \n"); #endif islpci_eth_receive(private_config); } // check whether the data transmit queues were full if (private_config->data_low_tx_full) { // check whether the transmit is not full anymore if( ISL38XX_CB_TX_QSIZE - isl38xx_in_queue( private_config->control_block, ISL38XX_CB_TX_DATA_LQ ) >= ISL38XX_MIN_QTHRESHOLD ) { // nope, the driver is ready for more network frames netif_wake_queue(private_config->my_module); // reset the full flag private_config->data_low_tx_full = 0; } } } if (reg & ISL38XX_INT_IDENT_INIT) { // Device has been initialized #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "IRQ: Init flag, device initialized \n"); #endif // perform card initlialization by sending objects islpci_mgt_initialize( private_config ); } if (reg & ISL38XX_INT_IDENT_SLEEP) { // Device intends to move to powersave state #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_ANYTHING, "IRQ: Sleep flag \n"); #endif isl38xx_handle_sleep_request( private_config->control_block, &private_config->powerstate, private_config->remapped_device_base ); } if (reg & ISL38XX_INT_IDENT_WAKEUP) { // Device has been woken up to active state #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_ANYTHING, "IRQ: Wakeup flag \n"); #endif isl38xx_handle_wakeup( private_config->control_block, &private_config->powerstate, private_config->remapped_device_base ); } } // unlock the interrupt handler spin_unlock( &private_config->slock ); return; }
int islpci_reset(islpci_private * private_config, char *firmware ) { isl38xx_control_block *control_block = private_config->control_block; queue_entry *entry; // unsigned long flags; #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_FUNCTION_CALLS, "isl38xx_reset \n"); #endif // lock the driver code //driver_lock( &private_config->slock, &flags ); // stop the transmission of network frames to the driver netif_stop_queue(private_config->my_module); // disable all device interrupts writel(0, private_config->remapped_device_base + ISL38XX_INT_EN_REG); // flush all management queues while( isl38xx_in_queue(control_block, ISL38XX_CB_TX_MGMTQ) != 0 ) { islpci_get_queue(private_config->remapped_device_base, &private_config->mgmt_tx_shadowq, &entry); islpci_put_queue(private_config->remapped_device_base, &private_config->mgmt_tx_freeq, entry); // decrement the real management index private_config->index_mgmt_tx--; } // while( isl38xx_in_queue(control_block, ISL38XX_CB_RX_MGMTQ) != 0 ) // { // islpci_get_queue(private_config->remapped_device_base, // &private_config->mgmt_rx_shadowq, &entry); // islpci_put_queue(private_config->remapped_device_base, // &private_config->mgmt_rx_freeq, entry); // decrement the real management index // private_config->index_mgmt_rx--; // } #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "Firmware file: %s \n", firmware ); #endif if (isl38xx_upload_firmware( firmware, private_config->remapped_device_base, private_config->device_host_address ) == -1) { // error uploading the firmware DEBUG(SHOW_ERROR_MESSAGES, "ERROR: could not upload the firmware \n" ); // unlock the driver code //driver_unlock( &private_config->slock, &flags ); return -1; } // unlock the driver code //driver_unlock( &private_config->slock, &flags ); return 0; }