39d38
< /* $FreeBSD: head/sys/dev/oce/oce_if.c 246799 2013-02-14 17:34:17Z jpaetzel $ */
40a40,41
> /* $FreeBSD: head/sys/dev/oce/oce_if.c 247880 2013-03-06 09:53:38Z delphij $ */
>
96a98,99
> static int oce_tx_asic_stall_verify(POCE_SOFTC sc, struct mbuf *m);
> static struct mbuf *oce_insert_vlan_tag(POCE_SOFTC sc, struct mbuf *m, boolean_t *complete);
98d100
<
269,270d270
< #ifdef DEV_NETMAP
< #endif /* DEV_NETMAP */
488c488
<
---
>
570a571
>
635a637,638
> ii->eq->intr++;
>
782a786
> boolean_t complete = TRUE;
792a797,805
> if(oce_tx_asic_stall_verify(sc, m)) {
> m = oce_insert_vlan_tag(sc, m, &complete);
> if(!m) {
> device_printf(sc->dev, "Insertion unsuccessful\n");
> return 0;
> }
>
> }
>
840c853
< nichdr->u0.s.complete = 1;
---
> nichdr->u0.s.complete = complete;
846c859
< (m->m_pkthdr.csum_flags & CSUM_UDP) ? 1 : 0;
---
> (m->m_pkthdr.csum_flags & CSUM_UDP) ? 1 : 0;
848c861
< (m->m_pkthdr.csum_flags & CSUM_TCP) ? 1 : 0;
---
> (m->m_pkthdr.csum_flags & CSUM_TCP) ? 1 : 0;
898c911
<
---
>
1083a1097,1099
>
> if (!sc->link_status)
> return;
1306d1321
< !(m->m_flags & M_VLANTAG) &&
1346,1352d1360
< if (IS_XE201(sc) && cqe->u0.s.error) {
< /* Lancer A0 workaround
< * num_frags will be 1 more than actual in case of error
< */
< if (num_frags)
< num_frags -= 1;
< }
1461c1469
< #endif /* INET6 || INET */
---
> #endif
1474c1482
<
---
> bzero(&rxdb_reg, sizeof(pd_rxulp_db_t));
1515d1522
< DELAY(1);
1522d1528
< DELAY(1);
1557,1563c1563,1564
< if (IS_XE201(sc))
< /* Lancer A0 no buffer workaround */
< oce_discard_rx_comp(rq, cqe);
< else
< /* Post L3/L4 errors to stack.*/
< oce_rx(rq, cqe->u0.s.frag_index, cqe);
<
---
> /* Post L3/L4 errors to stack.*/
> oce_rx(rq, cqe->u0.s.frag_index, cqe);
1759a1761
> struct mbx_common_get_cntl_attr *fw_cmd;
1761d1762
<
1764c1765
<
---
>
1767c1768
<
---
>
1771c1772
<
---
>
1794a1796,1805
> /*
> firmware is filling all the attributes for this ioctl except
> the driver version..so fill it
> */
> if(req.u0.rsp.opcode == OPCODE_COMMON_GET_CNTL_ATTRIBUTES) {
> fw_cmd = (struct mbx_common_get_cntl_attr *) ioctl_ptr;
> strncpy(fw_cmd->params.rsp.cntl_attr_info.hba_attr.drv_ver_str,
> COMPONENT_REVISION, strlen(COMPONENT_REVISION));
> }
>
1800a1812,1821
> static void
> oce_eqd_set_periodic(POCE_SOFTC sc)
> {
> struct oce_set_eqd set_eqd[OCE_MAX_EQ];
> struct oce_aic_obj *aic;
> struct oce_eq *eqo;
> uint64_t now = 0, delta;
> int eqd, i, num = 0;
> uint32_t ips = 0;
> int tps;
1801a1823,1876
> for (i = 0 ; i < sc->neqs; i++) {
> eqo = sc->eq[i];
> aic = &sc->aic_obj[i];
> /* When setting the static eq delay from the user space */
> if (!aic->enable) {
> eqd = aic->et_eqd;
> goto modify_eqd;
> }
>
> now = ticks;
>
> /* Over flow check */
> if ((now < aic->ticks) || (eqo->intr < aic->intr_prev))
> goto done;
>
> delta = now - aic->ticks;
> tps = delta/hz;
>
> /* Interrupt rate based on elapsed ticks */
> if(tps)
> ips = (uint32_t)(eqo->intr - aic->intr_prev) / tps;
>
> if (ips > INTR_RATE_HWM)
> eqd = aic->cur_eqd + 20;
> else if (ips < INTR_RATE_LWM)
> eqd = aic->cur_eqd / 2;
> else
> goto done;
>
> if (eqd < 10)
> eqd = 0;
>
> /* Make sure that the eq delay is in the known range */
> eqd = min(eqd, aic->max_eqd);
> eqd = max(eqd, aic->min_eqd);
>
> modify_eqd:
> if (eqd != aic->cur_eqd) {
> set_eqd[num].delay_multiplier = (eqd * 65)/100;
> set_eqd[num].eq_id = eqo->eq_id;
> aic->cur_eqd = eqd;
> num++;
> }
> done:
> aic->intr_prev = eqo->intr;
> aic->ticks = now;
> }
>
> /* Is there atleast one eq that needs to be modified? */
> if(num)
> oce_mbox_eqd_modify_periodic(sc, set_eqd, num);
>
> }
>
1815a1891,1894
> /* calculate and set the eq delay for optimal interrupt rate */
> if (IS_BE(sc))
> oce_eqd_set_periodic(sc);
>
1852,1856c1931,1935
< /* Since taskqueue_drain takes a Giant Lock, We should not acquire
< any other lock. So unlock device lock and require after
< completing taskqueue_drain.
< */
< UNLOCK(&sc->dev_lock);
---
> /* Since taskqueue_drain takes a Gaint Lock, We should not acquire
> any other lock. So unlock device lock and require after
> completing taskqueue_drain.
> */
> UNLOCK(&sc->dev_lock);
1862c1941
< LOCK(&sc->dev_lock);
---
> LOCK(&sc->dev_lock);
1877c1956
< */
---
> */
1949a2029
> struct oce_async_event_qnq *dbgcqe;
1975a2056,2063
> else if(evt_type == ASYNC_EVENT_CODE_DEBUG &&
> optype == ASYNC_EVENT_DEBUG_QNQ) {
> dbgcqe =
> (struct oce_async_event_qnq *)cqe;
> if(dbgcqe->valid)
> sc->qnqid = dbgcqe->vlan_tag;
> sc->qnq_debug_event = TRUE;
> }
2034a2123,2198
> static int
> oce_check_ipv6_ext_hdr(struct mbuf *m)
> {
> struct ether_header *eh = mtod(m, struct ether_header *);
> caddr_t m_datatemp = m->m_data;
>
> if (eh->ether_type == htons(ETHERTYPE_IPV6)) {
> m->m_data += sizeof(struct ether_header);
> struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
>
> if((ip6->ip6_nxt != IPPROTO_TCP) && \
> (ip6->ip6_nxt != IPPROTO_UDP)){
> struct ip6_ext *ip6e = NULL;
> m->m_data += sizeof(struct ip6_hdr);
>
> ip6e = (struct ip6_ext *) mtod(m, struct ip6_ext *);
> if(ip6e->ip6e_len == 0xff) {
> m->m_data = m_datatemp;
> return TRUE;
> }
> }
> m->m_data = m_datatemp;
> }
> return FALSE;
> }
>
> static int
> is_be3_a1(POCE_SOFTC sc)
> {
> if((sc->flags & OCE_FLAGS_BE3) && ((sc->asic_revision & 0xFF) < 2)) {
> return TRUE;
> }
> return FALSE;
> }
>
> static struct mbuf *
> oce_insert_vlan_tag(POCE_SOFTC sc, struct mbuf *m, boolean_t *complete)
> {
> uint16_t vlan_tag = 0;
>
> if(!M_WRITABLE(m))
> return NULL;
>
> /* Embed vlan tag in the packet if it is not part of it */
> if(m->m_flags & M_VLANTAG) {
> vlan_tag = EVL_VLANOFTAG(m->m_pkthdr.ether_vtag);
> m->m_flags &= ~M_VLANTAG;
> }
>
> /* if UMC, ignore vlan tag insertion and instead insert pvid */
> if(sc->pvid) {
> if(!vlan_tag)
> vlan_tag = sc->pvid;
> *complete = FALSE;
> }
>
> if(vlan_tag) {
> m = ether_vlanencap(m, vlan_tag);
> }
>
> if(sc->qnqid) {
> m = ether_vlanencap(m, sc->qnqid);
> *complete = FALSE;
> }
> return m;
> }
>
> static int
> oce_tx_asic_stall_verify(POCE_SOFTC sc, struct mbuf *m)
> {
> if(is_be3_a1(sc) && IS_QNQ_OR_UMC(sc) && \
> oce_check_ipv6_ext_hdr(m)) {
> return TRUE;
> }
> return FALSE;
> }
< /* $FreeBSD: head/sys/dev/oce/oce_if.c 246799 2013-02-14 17:34:17Z jpaetzel $ */
40a40,41
> /* $FreeBSD: head/sys/dev/oce/oce_if.c 247880 2013-03-06 09:53:38Z delphij $ */
>
96a98,99
> static int oce_tx_asic_stall_verify(POCE_SOFTC sc, struct mbuf *m);
> static struct mbuf *oce_insert_vlan_tag(POCE_SOFTC sc, struct mbuf *m, boolean_t *complete);
98d100
<
269,270d270
< #ifdef DEV_NETMAP
< #endif /* DEV_NETMAP */
488c488
<
---
>
570a571
>
635a637,638
> ii->eq->intr++;
>
782a786
> boolean_t complete = TRUE;
792a797,805
> if(oce_tx_asic_stall_verify(sc, m)) {
> m = oce_insert_vlan_tag(sc, m, &complete);
> if(!m) {
> device_printf(sc->dev, "Insertion unsuccessful\n");
> return 0;
> }
>
> }
>
840c853
< nichdr->u0.s.complete = 1;
---
> nichdr->u0.s.complete = complete;
846c859
< (m->m_pkthdr.csum_flags & CSUM_UDP) ? 1 : 0;
---
> (m->m_pkthdr.csum_flags & CSUM_UDP) ? 1 : 0;
848c861
< (m->m_pkthdr.csum_flags & CSUM_TCP) ? 1 : 0;
---
> (m->m_pkthdr.csum_flags & CSUM_TCP) ? 1 : 0;
898c911
<
---
>
1083a1097,1099
>
> if (!sc->link_status)
> return;
1306d1321
< !(m->m_flags & M_VLANTAG) &&
1346,1352d1360
< if (IS_XE201(sc) && cqe->u0.s.error) {
< /* Lancer A0 workaround
< * num_frags will be 1 more than actual in case of error
< */
< if (num_frags)
< num_frags -= 1;
< }
1461c1469
< #endif /* INET6 || INET */
---
> #endif
1474c1482
<
---
> bzero(&rxdb_reg, sizeof(pd_rxulp_db_t));
1515d1522
< DELAY(1);
1522d1528
< DELAY(1);
1557,1563c1563,1564
< if (IS_XE201(sc))
< /* Lancer A0 no buffer workaround */
< oce_discard_rx_comp(rq, cqe);
< else
< /* Post L3/L4 errors to stack.*/
< oce_rx(rq, cqe->u0.s.frag_index, cqe);
<
---
> /* Post L3/L4 errors to stack.*/
> oce_rx(rq, cqe->u0.s.frag_index, cqe);
1759a1761
> struct mbx_common_get_cntl_attr *fw_cmd;
1761d1762
<
1764c1765
<
---
>
1767c1768
<
---
>
1771c1772
<
---
>
1794a1796,1805
> /*
> firmware is filling all the attributes for this ioctl except
> the driver version..so fill it
> */
> if(req.u0.rsp.opcode == OPCODE_COMMON_GET_CNTL_ATTRIBUTES) {
> fw_cmd = (struct mbx_common_get_cntl_attr *) ioctl_ptr;
> strncpy(fw_cmd->params.rsp.cntl_attr_info.hba_attr.drv_ver_str,
> COMPONENT_REVISION, strlen(COMPONENT_REVISION));
> }
>
1800a1812,1821
> static void
> oce_eqd_set_periodic(POCE_SOFTC sc)
> {
> struct oce_set_eqd set_eqd[OCE_MAX_EQ];
> struct oce_aic_obj *aic;
> struct oce_eq *eqo;
> uint64_t now = 0, delta;
> int eqd, i, num = 0;
> uint32_t ips = 0;
> int tps;
1801a1823,1876
> for (i = 0 ; i < sc->neqs; i++) {
> eqo = sc->eq[i];
> aic = &sc->aic_obj[i];
> /* When setting the static eq delay from the user space */
> if (!aic->enable) {
> eqd = aic->et_eqd;
> goto modify_eqd;
> }
>
> now = ticks;
>
> /* Over flow check */
> if ((now < aic->ticks) || (eqo->intr < aic->intr_prev))
> goto done;
>
> delta = now - aic->ticks;
> tps = delta/hz;
>
> /* Interrupt rate based on elapsed ticks */
> if(tps)
> ips = (uint32_t)(eqo->intr - aic->intr_prev) / tps;
>
> if (ips > INTR_RATE_HWM)
> eqd = aic->cur_eqd + 20;
> else if (ips < INTR_RATE_LWM)
> eqd = aic->cur_eqd / 2;
> else
> goto done;
>
> if (eqd < 10)
> eqd = 0;
>
> /* Make sure that the eq delay is in the known range */
> eqd = min(eqd, aic->max_eqd);
> eqd = max(eqd, aic->min_eqd);
>
> modify_eqd:
> if (eqd != aic->cur_eqd) {
> set_eqd[num].delay_multiplier = (eqd * 65)/100;
> set_eqd[num].eq_id = eqo->eq_id;
> aic->cur_eqd = eqd;
> num++;
> }
> done:
> aic->intr_prev = eqo->intr;
> aic->ticks = now;
> }
>
> /* Is there atleast one eq that needs to be modified? */
> if(num)
> oce_mbox_eqd_modify_periodic(sc, set_eqd, num);
>
> }
>
1815a1891,1894
> /* calculate and set the eq delay for optimal interrupt rate */
> if (IS_BE(sc))
> oce_eqd_set_periodic(sc);
>
1852,1856c1931,1935
< /* Since taskqueue_drain takes a Giant Lock, We should not acquire
< any other lock. So unlock device lock and require after
< completing taskqueue_drain.
< */
< UNLOCK(&sc->dev_lock);
---
> /* Since taskqueue_drain takes a Gaint Lock, We should not acquire
> any other lock. So unlock device lock and require after
> completing taskqueue_drain.
> */
> UNLOCK(&sc->dev_lock);
1862c1941
< LOCK(&sc->dev_lock);
---
> LOCK(&sc->dev_lock);
1877c1956
< */
---
> */
1949a2029
> struct oce_async_event_qnq *dbgcqe;
1975a2056,2063
> else if(evt_type == ASYNC_EVENT_CODE_DEBUG &&
> optype == ASYNC_EVENT_DEBUG_QNQ) {
> dbgcqe =
> (struct oce_async_event_qnq *)cqe;
> if(dbgcqe->valid)
> sc->qnqid = dbgcqe->vlan_tag;
> sc->qnq_debug_event = TRUE;
> }
2034a2123,2198
> static int
> oce_check_ipv6_ext_hdr(struct mbuf *m)
> {
> struct ether_header *eh = mtod(m, struct ether_header *);
> caddr_t m_datatemp = m->m_data;
>
> if (eh->ether_type == htons(ETHERTYPE_IPV6)) {
> m->m_data += sizeof(struct ether_header);
> struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
>
> if((ip6->ip6_nxt != IPPROTO_TCP) && \
> (ip6->ip6_nxt != IPPROTO_UDP)){
> struct ip6_ext *ip6e = NULL;
> m->m_data += sizeof(struct ip6_hdr);
>
> ip6e = (struct ip6_ext *) mtod(m, struct ip6_ext *);
> if(ip6e->ip6e_len == 0xff) {
> m->m_data = m_datatemp;
> return TRUE;
> }
> }
> m->m_data = m_datatemp;
> }
> return FALSE;
> }
>
> static int
> is_be3_a1(POCE_SOFTC sc)
> {
> if((sc->flags & OCE_FLAGS_BE3) && ((sc->asic_revision & 0xFF) < 2)) {
> return TRUE;
> }
> return FALSE;
> }
>
> static struct mbuf *
> oce_insert_vlan_tag(POCE_SOFTC sc, struct mbuf *m, boolean_t *complete)
> {
> uint16_t vlan_tag = 0;
>
> if(!M_WRITABLE(m))
> return NULL;
>
> /* Embed vlan tag in the packet if it is not part of it */
> if(m->m_flags & M_VLANTAG) {
> vlan_tag = EVL_VLANOFTAG(m->m_pkthdr.ether_vtag);
> m->m_flags &= ~M_VLANTAG;
> }
>
> /* if UMC, ignore vlan tag insertion and instead insert pvid */
> if(sc->pvid) {
> if(!vlan_tag)
> vlan_tag = sc->pvid;
> *complete = FALSE;
> }
>
> if(vlan_tag) {
> m = ether_vlanencap(m, vlan_tag);
> }
>
> if(sc->qnqid) {
> m = ether_vlanencap(m, sc->qnqid);
> *complete = FALSE;
> }
> return m;
> }
>
> static int
> oce_tx_asic_stall_verify(POCE_SOFTC sc, struct mbuf *m)
> {
> if(is_be3_a1(sc) && IS_QNQ_OR_UMC(sc) && \
> oce_check_ipv6_ext_hdr(m)) {
> return TRUE;
> }
> return FALSE;
> }