diff options
Diffstat (limited to 'drivers/net/qlcnic/qlcnic_init.c')
-rw-r--r-- | drivers/net/qlcnic/qlcnic_init.c | 136 |
1 files changed, 99 insertions, 37 deletions
diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c index 71a4e664ad7..75ba744b173 100644 --- a/drivers/net/qlcnic/qlcnic_init.c +++ b/drivers/net/qlcnic/qlcnic_init.c @@ -112,18 +112,45 @@ void qlcnic_release_rx_buffers(struct qlcnic_adapter *adapter) rds_ring = &recv_ctx->rds_rings[ring]; for (i = 0; i < rds_ring->num_desc; ++i) { rx_buf = &(rds_ring->rx_buf_arr[i]); - if (rx_buf->state == QLCNIC_BUFFER_FREE) + if (rx_buf->skb == NULL) continue; + pci_unmap_single(adapter->pdev, rx_buf->dma, rds_ring->dma_size, PCI_DMA_FROMDEVICE); - if (rx_buf->skb != NULL) - dev_kfree_skb_any(rx_buf->skb); + + dev_kfree_skb_any(rx_buf->skb); } } } +void qlcnic_reset_rx_buffers_list(struct qlcnic_adapter *adapter) +{ + struct qlcnic_recv_context *recv_ctx; + struct qlcnic_host_rds_ring *rds_ring; + struct qlcnic_rx_buffer *rx_buf; + int i, ring; + + recv_ctx = &adapter->recv_ctx; + for (ring = 0; ring < adapter->max_rds_rings; ring++) { + rds_ring = &recv_ctx->rds_rings[ring]; + + spin_lock(&rds_ring->lock); + + INIT_LIST_HEAD(&rds_ring->free_list); + + rx_buf = rds_ring->rx_buf_arr; + for (i = 0; i < rds_ring->num_desc; i++) { + list_add_tail(&rx_buf->list, + &rds_ring->free_list); + rx_buf++; + } + + spin_unlock(&rds_ring->lock); + } +} + void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter) { struct qlcnic_cmd_buffer *cmd_buf; @@ -181,7 +208,9 @@ skip_rds: tx_ring = adapter->tx_ring; vfree(tx_ring->cmd_buf_arr); + tx_ring->cmd_buf_arr = NULL; kfree(adapter->tx_ring); + adapter->tx_ring = NULL; } int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter) @@ -264,7 +293,6 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter) list_add_tail(&rx_buf->list, &rds_ring->free_list); rx_buf->ref_handle = i; - rx_buf->state = QLCNIC_BUFFER_FREE; rx_buf++; } spin_lock_init(&rds_ring->lock); @@ -413,7 +441,7 @@ int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter) /* resetall */ qlcnic_rom_lock(adapter); - QLCWR32(adapter, QLCNIC_ROMUSB_GLB_SW_RESET, 0xffffffff); + QLCWR32(adapter, QLCNIC_ROMUSB_GLB_SW_RESET, 0xfeffffff); qlcnic_rom_unlock(adapter); if (qlcnic_rom_fast_read(adapter, 0, &n) != 0 || (n != 0xcafecafe) || @@ -521,16 +549,13 @@ qlcnic_setup_idc_param(struct qlcnic_adapter *adapter) { u32 val; val = QLCRD32(adapter, QLCNIC_CRB_DEV_PARTITION_INFO); - val = (val >> (adapter->portnum * 4)) & 0xf; - - if ((val & 0x3) != 1) { - dev_err(&adapter->pdev->dev, "Not an Ethernet NIC func=%u\n", - val); + val = QLC_DEV_GET_DRV(val, adapter->portnum); + if ((val & 0x3) != QLCNIC_TYPE_NIC) { + dev_err(&adapter->pdev->dev, + "Not an Ethernet NIC func=%u\n", val); return -EIO; } - adapter->physical_port = (val >> 2); - if (qlcnic_rom_fast_read(adapter, QLCNIC_ROM_DEV_INIT_TIMEOUT, &timeo)) timeo = 30; @@ -544,16 +569,34 @@ qlcnic_setup_idc_param(struct qlcnic_adapter *adapter) { return 0; } +int +qlcnic_check_flash_fw_ver(struct qlcnic_adapter *adapter) +{ + u32 ver = -1, min_ver; + + qlcnic_rom_fast_read(adapter, QLCNIC_FW_VERSION_OFFSET, (int *)&ver); + + ver = QLCNIC_DECODE_VERSION(ver); + min_ver = QLCNIC_MIN_FW_VERSION; + + if (ver < min_ver) { + dev_err(&adapter->pdev->dev, + "firmware version %d.%d.%d unsupported." + "Min supported version %d.%d.%d\n", + _major(ver), _minor(ver), _build(ver), + _major(min_ver), _minor(min_ver), _build(min_ver)); + return -EINVAL; + } + + return 0; +} + static int qlcnic_has_mn(struct qlcnic_adapter *adapter) { - u32 capability, flashed_ver; + u32 capability; capability = 0; - qlcnic_rom_fast_read(adapter, - QLCNIC_FW_VERSION_OFFSET, (int *)&flashed_ver); - flashed_ver = QLCNIC_DECODE_VERSION(flashed_ver); - capability = QLCRD32(adapter, QLCNIC_PEG_TUNE_CAPABILITY); if (capability & QLCNIC_PEG_TUNE_MN_PRESENT) return 1; @@ -1007,7 +1050,7 @@ static int qlcnic_validate_firmware(struct qlcnic_adapter *adapter) { __le32 val; - u32 ver, min_ver, bios, min_size; + u32 ver, bios, min_size; struct pci_dev *pdev = adapter->pdev; const struct firmware *fw = adapter->fw; u8 fw_type = adapter->fw_type; @@ -1029,12 +1072,9 @@ qlcnic_validate_firmware(struct qlcnic_adapter *adapter) return -EINVAL; val = qlcnic_get_fw_version(adapter); - - min_ver = QLCNIC_VERSION_CODE(4, 0, 216); - ver = QLCNIC_DECODE_VERSION(val); - if ((_major(ver) > _QLCNIC_LINUX_MAJOR) || (ver < min_ver)) { + if (ver < QLCNIC_MIN_FW_VERSION) { dev_err(&pdev->dev, "%s: firmware version %d.%d.%d unsupported\n", fw_name[fw_type], _major(ver), _minor(ver), _build(ver)); @@ -1122,7 +1162,7 @@ qlcnic_release_firmware(struct qlcnic_adapter *adapter) adapter->fw = NULL; } -int qlcnic_phantom_init(struct qlcnic_adapter *adapter) +static int qlcnic_cmd_peg_ready(struct qlcnic_adapter *adapter) { u32 val; int retries = 60; @@ -1147,7 +1187,8 @@ int qlcnic_phantom_init(struct qlcnic_adapter *adapter) QLCWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED); out_err: - dev_err(&adapter->pdev->dev, "firmware init failed\n"); + dev_err(&adapter->pdev->dev, "Command Peg initialization not " + "complete, state: 0x%x.\n", val); return -EIO; } @@ -1180,6 +1221,10 @@ int qlcnic_init_firmware(struct qlcnic_adapter *adapter) { int err; + err = qlcnic_cmd_peg_ready(adapter); + if (err) + return err; + err = qlcnic_receive_peg_ready(adapter); if (err) return err; @@ -1265,14 +1310,12 @@ qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter, dma_addr_t dma; struct pci_dev *pdev = adapter->pdev; - buffer->skb = dev_alloc_skb(rds_ring->skb_size); - if (!buffer->skb) { + skb = dev_alloc_skb(rds_ring->skb_size); + if (!skb) { adapter->stats.skb_alloc_failure++; return -ENOMEM; } - skb = buffer->skb; - skb_reserve(skb, 2); dma = pci_map_single(pdev, skb->data, @@ -1281,13 +1324,11 @@ qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter, if (pci_dma_mapping_error(pdev, dma)) { adapter->stats.rx_dma_map_error++; dev_kfree_skb_any(skb); - buffer->skb = NULL; return -ENOMEM; } buffer->skb = skb; buffer->dma = dma; - buffer->state = QLCNIC_BUFFER_BUSY; return 0; } @@ -1300,14 +1341,15 @@ static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter, buffer = &rds_ring->rx_buf_arr[index]; + if (unlikely(buffer->skb == NULL)) { + WARN_ON(1); + return NULL; + } + pci_unmap_single(adapter->pdev, buffer->dma, rds_ring->dma_size, PCI_DMA_FROMDEVICE); skb = buffer->skb; - if (!skb) { - adapter->stats.null_skb++; - goto no_skb; - } if (likely(adapter->rx_csum && cksum == STATUS_CKSUM_OK)) { adapter->stats.csummed++; @@ -1319,8 +1361,7 @@ static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter, skb->dev = adapter->netdev; buffer->skb = NULL; -no_skb: - buffer->state = QLCNIC_BUFFER_FREE; + return skb; } @@ -1495,7 +1536,7 @@ qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max) WARN_ON(desc_cnt > 1); - if (rxbuf) + if (likely(rxbuf)) list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]); else adapter->stats.null_rxbuf++; @@ -1701,3 +1742,24 @@ qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring) sds_ring->consumer = consumer; writel(consumer, sds_ring->crb_sts_consumer); } + +void +qlcnic_fetch_mac(struct qlcnic_adapter *adapter, u32 off1, u32 off2, + u8 alt_mac, u8 *mac) +{ + u32 mac_low, mac_high; + int i; + + mac_low = QLCRD32(adapter, off1); + mac_high = QLCRD32(adapter, off2); + + if (alt_mac) { + mac_low |= (mac_low >> 16) | (mac_high << 16); + mac_high >>= 16; + } + + for (i = 0; i < 2; i++) + mac[i] = (u8)(mac_high >> ((1 - i) * 8)); + for (i = 2; i < 6; i++) + mac[i] = (u8)(mac_low >> ((5 - i) * 8)); +} |