diff options
Diffstat (limited to 'sys/dev/qlxgbe/ql_os.c')
-rw-r--r-- | sys/dev/qlxgbe/ql_os.c | 130 |
1 files changed, 108 insertions, 22 deletions
diff --git a/sys/dev/qlxgbe/ql_os.c b/sys/dev/qlxgbe/ql_os.c index ec92e8f..ecc6cce 100644 --- a/sys/dev/qlxgbe/ql_os.c +++ b/sys/dev/qlxgbe/ql_os.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014 Qlogic Corporation + * Copyright (c) 2013-2016 Qlogic Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -80,6 +80,7 @@ static int qla_send(qla_host_t *ha, struct mbuf **m_headp); static void qla_tx_done(void *context, int pending); static void qla_get_peer(qla_host_t *ha); static void qla_error_recovery(void *context, int pending); +static void qla_async_event(void *context, int pending); /* * Hooks to the Operating Systems @@ -120,6 +121,7 @@ MALLOC_DEFINE(M_QLA83XXBUF, "qla83xxbuf", "Buffers for qla83xx driver"); static char dev_str[64]; +static char ver_str[64]; /* * Name: qla_pci_probe @@ -134,6 +136,9 @@ qla_pci_probe(device_t dev) "Qlogic ISP 83xx PCI CNA Adapter-Ethernet Function", QLA_VERSION_MAJOR, QLA_VERSION_MINOR, QLA_VERSION_BUILD); + snprintf(ver_str, sizeof(ver_str), "v%d.%d.%d", + QLA_VERSION_MAJOR, QLA_VERSION_MINOR, + QLA_VERSION_BUILD); device_set_desc(dev, dev_str); break; default: @@ -151,6 +156,11 @@ qla_add_sysctls(qla_host_t *ha) { device_t dev = ha->pci_dev; + SYSCTL_ADD_STRING(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), + OID_AUTO, "version", CTLFLAG_RD, + ver_str, 0, "Driver Version"); + SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "stats", CTLTYPE_INT | CTLFLAG_RW, @@ -235,6 +245,13 @@ qla_watchdog(void *arg) ha->err_inject = 0; taskqueue_enqueue(ha->err_tq, &ha->err_task); } else { + + if (ha->async_event) { + ha->async_event = 0; + taskqueue_enqueue(ha->async_event_tq, + &ha->async_event_task); + } + for (i = 0; i < ha->hw.num_tx_rings; i++) { hw_tx_cntxt = &hw->tx_cntxt[i]; if (qla_le32_to_host(*(hw_tx_cntxt->tx_cons)) != @@ -270,6 +287,7 @@ qla_pci_attach(device_t dev) qla_host_t *ha = NULL; uint32_t rsrc_len; int i; + uint32_t num_rcvq = 0; QL_DPRINT2(ha, (dev, "%s: enter\n", __func__)); @@ -328,6 +346,37 @@ qla_pci_attach(device_t dev) " msix_count 0x%x pci_reg %p\n", __func__, ha, ha->pci_func, rsrc_len, ha->msix_count, ha->pci_reg)); + /* initialize hardware */ + if (ql_init_hw(ha)) { + device_printf(dev, "%s: ql_init_hw failed\n", __func__); + goto qla_pci_attach_err; + } + + device_printf(dev, "%s: firmware[%d.%d.%d.%d]\n", __func__, + ha->fw_ver_major, ha->fw_ver_minor, ha->fw_ver_sub, + ha->fw_ver_build); + snprintf(ha->fw_ver_str, sizeof(ha->fw_ver_str), "%d.%d.%d.%d", + ha->fw_ver_major, ha->fw_ver_minor, ha->fw_ver_sub, + ha->fw_ver_build); + + if (qla_get_nic_partition(ha, NULL, &num_rcvq)) { + device_printf(dev, "%s: qla_get_nic_partition failed\n", + __func__); + goto qla_pci_attach_err; + } + device_printf(dev, "%s: ha %p pci_func 0x%x rsrc_count 0x%08x" + " msix_count 0x%x pci_reg %p num_rcvq = %d\n", __func__, ha, + ha->pci_func, rsrc_len, ha->msix_count, ha->pci_reg, num_rcvq); + + +#ifdef QL_ENABLE_ISCSI_TLV + if ((ha->msix_count < 64) || (num_rcvq != 32)) { + ha->hw.num_sds_rings = 15; + ha->hw.num_tx_rings = 32; + } +#endif /* #ifdef QL_ENABLE_ISCSI_TLV */ + ha->hw.num_rds_rings = ha->hw.num_sds_rings; + ha->msix_count = ha->hw.num_sds_rings + 1; if (pci_alloc_msix(dev, &ha->msix_count)) { @@ -377,19 +426,6 @@ qla_pci_attach(device_t dev) printf("%s: mp__ncpus %d sds %d rds %d msi-x %d\n", __func__, mp_ncpus, ha->hw.num_sds_rings, ha->hw.num_rds_rings, ha->msix_count); - /* initialize hardware */ - if (ql_init_hw(ha)) { - device_printf(dev, "%s: ql_init_hw failed\n", __func__); - goto qla_pci_attach_err; - } - - device_printf(dev, "%s: firmware[%d.%d.%d.%d]\n", __func__, - ha->fw_ver_major, ha->fw_ver_minor, ha->fw_ver_sub, - ha->fw_ver_build); - snprintf(ha->fw_ver_str, sizeof(ha->fw_ver_str), "%d.%d.%d.%d", - ha->fw_ver_major, ha->fw_ver_minor, ha->fw_ver_sub, - ha->fw_ver_build); - ql_read_mac_addr(ha); /* allocate parent dma tag */ @@ -437,6 +473,12 @@ qla_pci_attach(device_t dev) taskqueue_start_threads(&ha->err_tq, 1, PI_NET, "%s errq", device_get_nameunit(ha->pci_dev)); + TASK_INIT(&ha->async_event_task, 0, qla_async_event, ha); + ha->async_event_tq = taskqueue_create_fast("qla_asyncq", M_NOWAIT, + taskqueue_thread_enqueue, &ha->async_event_tq); + taskqueue_start_threads(&ha->async_event_tq, 1, PI_NET, "%s asyncq", + device_get_nameunit(ha->pci_dev)); + QL_DPRINT2(ha, (dev, "%s: exit 0\n", __func__)); return (0); @@ -528,6 +570,11 @@ qla_release(qla_host_t *ha) dev = ha->pci_dev; + if (ha->async_event_tq) { + taskqueue_drain(ha->async_event_tq, &ha->async_event_task); + taskqueue_free(ha->async_event_tq); + } + if (ha->err_tq) { taskqueue_drain(ha->err_tq, &ha->err_task); taskqueue_free(ha->err_tq); @@ -805,6 +852,8 @@ qla_init_locked(qla_host_t *ha) if (qla_alloc_xmt_bufs(ha) != 0) return; + qla_confirm_9kb_enable(ha); + if (qla_alloc_rcv_bufs(ha) != 0) return; @@ -1098,7 +1147,7 @@ qla_start(struct ifnet *ifp) return; } - if (!ha->watchdog_ticks) + if (!ha->hw.link_up || !ha->watchdog_ticks) ql_update_link_state(ha); if (!ha->hw.link_up) { @@ -1142,12 +1191,27 @@ qla_send(qla_host_t *ha, struct mbuf **m_headp) uint32_t tx_idx; struct mbuf *m_head = *m_headp; uint32_t txr_idx = ha->txr_idx; + uint32_t iscsi_pdu = 0; QL_DPRINT8(ha, (ha->pci_dev, "%s: enter\n", __func__)); /* check if flowid is set */ - if (M_HASHTYPE_GET(m_head) != M_HASHTYPE_NONE) + + if (M_HASHTYPE_GET(m_head) != M_HASHTYPE_NONE) { +#ifdef QL_ENABLE_ISCSI_TLV + if (qla_iscsi_pdu(ha, m_head) == 0) { + iscsi_pdu = 1; + txr_idx = m_head->m_pkthdr.flowid & + ((ha->hw.num_tx_rings >> 1) - 1); + } else { + txr_idx = m_head->m_pkthdr.flowid & + (ha->hw.num_tx_rings - 1); + } +#else txr_idx = m_head->m_pkthdr.flowid & (ha->hw.num_tx_rings - 1); +#endif /* #ifdef QL_ENABLE_ISCSI_TLV */ + } + tx_idx = ha->hw.tx_cntxt[txr_idx].txr_next; map = ha->tx_ring[txr_idx].tx_buf[tx_idx].map; @@ -1210,8 +1274,8 @@ qla_send(qla_host_t *ha, struct mbuf **m_headp) bus_dmamap_sync(ha->tx_tag, map, BUS_DMASYNC_PREWRITE); - if (!(ret = ql_hw_send(ha, segs, nsegs, tx_idx, m_head, txr_idx))) { - + if (!(ret = ql_hw_send(ha, segs, nsegs, tx_idx, m_head, txr_idx, + iscsi_pdu))) { ha->tx_ring[txr_idx].count++; ha->tx_ring[txr_idx].tx_buf[tx_idx].m_head = m_head; } else { @@ -1515,15 +1579,23 @@ ql_get_mbuf(qla_host_t *ha, qla_rx_buf_t *rxb, struct mbuf *nmp) int ret = 0; uint32_t offset; bus_dma_segment_t segs[1]; - int nsegs; + int nsegs, mbuf_size; QL_DPRINT2(ha, (ha->pci_dev, "%s: enter\n", __func__)); ifp = ha->ifp; + if (ha->hw.enable_9kb) + mbuf_size = MJUM9BYTES; + else + mbuf_size = MCLBYTES; + if (mp == NULL) { - mp = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); + if (ha->hw.enable_9kb) + mp = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, mbuf_size); + else + mp = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (mp == NULL) { ha->err_m_getcl++; @@ -1532,9 +1604,9 @@ ql_get_mbuf(qla_host_t *ha, qla_rx_buf_t *rxb, struct mbuf *nmp) "%s: m_getcl failed\n", __func__); goto exit_ql_get_mbuf; } - mp->m_len = mp->m_pkthdr.len = MCLBYTES; + mp->m_len = mp->m_pkthdr.len = mbuf_size; } else { - mp->m_len = mp->m_pkthdr.len = MCLBYTES; + mp->m_len = mp->m_pkthdr.len = mbuf_size; mp->m_data = mp->m_ext.ext_buf; mp->m_next = NULL; } @@ -1635,6 +1707,9 @@ qla_error_recovery(void *context, int pending) (void)QLA_LOCK(ha, __func__, 0); + ha->hw.imd_compl = 1; + qla_mdelay(__func__, 300); + ha->flags.stop_rcv = 1; ql_hw_stop_rcv(ha); @@ -1687,6 +1762,7 @@ qla_error_recovery(void *context, int pending) QLA_UNLOCK(ha, __func__); return; } + qla_confirm_9kb_enable(ha); if (qla_alloc_rcv_bufs(ha) != 0) { QLA_UNLOCK(ha, __func__); @@ -1704,3 +1780,13 @@ qla_error_recovery(void *context, int pending) QLA_UNLOCK(ha, __func__); } +static void +qla_async_event(void *context, int pending) +{ + qla_host_t *ha = context; + + (void)QLA_LOCK(ha, __func__, 0); + qla_hw_async_event(ha); + QLA_UNLOCK(ha, __func__); +} + |