Deleted Added
full compact
37c37
< __FBSDID("$FreeBSD: head/sys/dev/sge/if_sge.c 207625 2010-05-04 17:34:00Z yongari $");
---
> __FBSDID("$FreeBSD: head/sys/dev/sge/if_sge.c 207628 2010-05-04 19:04:51Z yongari $");
758a759,760
> struct sge_rxdesc *rxd;
> struct sge_txdesc *txd;
871a874,877
> txd = &cd->sge_txdesc[i];
> txd->tx_m = NULL;
> txd->tx_dmamap = NULL;
> txd->tx_ndesc = 0;
873c879
< &cd->sge_tx_map[i]);
---
> &txd->tx_dmamap);
888a895,897
> rxd = &cd->sge_rxdesc[i];
> rxd->rx_m = NULL;
> rxd->rx_dmamap = NULL;
890c899
< &cd->sge_rx_map[i]);
---
> &rxd->rx_dmamap);
905a915,916
> struct sge_rxdesc *rxd;
> struct sge_txdesc *txd;
937c948,949
< if (cd->sge_rx_map[i] != NULL) {
---
> rxd = &cd->sge_rxdesc[i];
> if (rxd->rx_dmamap != NULL) {
939,940c951,952
< cd->sge_rx_map[i]);
< cd->sge_rx_map[i] = NULL;
---
> rxd->rx_dmamap);
> rxd->rx_dmamap = NULL;
954c966,967
< if (cd->sge_tx_map[i] != NULL) {
---
> txd = &cd->sge_txdesc[i];
> if (txd->tx_dmamap != NULL) {
956,957c969,970
< cd->sge_tx_map[i]);
< cd->sge_tx_map[i] = NULL;
---
> txd->tx_dmamap);
> txd->tx_dmamap = NULL;
993a1007
> struct sge_txdesc *txd;
999,1005c1013,1020
< if (cd->sge_tx_mbuf[i] != NULL) {
< bus_dmamap_sync(cd->sge_txmbuf_tag,
< cd->sge_tx_map[i], BUS_DMASYNC_POSTWRITE);
< bus_dmamap_unload(cd->sge_txmbuf_tag,
< cd->sge_tx_map[i]);
< m_free(cd->sge_tx_mbuf[i]);
< cd->sge_tx_mbuf[i] = NULL;
---
> txd = &cd->sge_txdesc[i];
> if (txd->tx_m != NULL) {
> bus_dmamap_sync(cd->sge_txmbuf_tag, txd->tx_dmamap,
> BUS_DMASYNC_POSTWRITE);
> bus_dmamap_unload(cd->sge_txmbuf_tag, txd->tx_dmamap);
> m_free(txd->tx_m);
> txd->tx_m = NULL;
> txd->tx_ndesc = 0;
1039a1055
> struct sge_rxdesc *rxd;
1045,1046c1061,1063
< if (cd->sge_rx_mbuf[i] != NULL) {
< bus_dmamap_sync(cd->sge_rxmbuf_tag, cd->sge_rx_map[i],
---
> rxd = &cd->sge_rxdesc[i];
> if (rxd->rx_m != NULL) {
> bus_dmamap_sync(cd->sge_rxmbuf_tag, rxd->rx_dmamap,
1049,1051c1066,1068
< cd->sge_rx_map[i]);
< m_free(cd->sge_rx_mbuf[i]);
< cd->sge_rx_mbuf[i] = NULL;
---
> rxd->rx_dmamap);
> m_free(rxd->rx_m);
> rxd->rx_m = NULL;
1065a1083
> struct sge_rxdesc *rxd;
1085,1086c1103,1105
< if (cd->sge_rx_mbuf[prod] != NULL) {
< bus_dmamap_sync(cd->sge_rxmbuf_tag, cd->sge_rx_map[prod],
---
> rxd = &cd->sge_rxdesc[prod];
> if (rxd->rx_m != NULL) {
> bus_dmamap_sync(cd->sge_rxmbuf_tag, rxd->rx_dmamap,
1088c1107
< bus_dmamap_unload(cd->sge_rxmbuf_tag, cd->sge_rx_map[prod]);
---
> bus_dmamap_unload(cd->sge_rxmbuf_tag, rxd->rx_dmamap);
1090,1091c1109,1110
< map = cd->sge_rx_map[prod];
< cd->sge_rx_map[prod] = cd->sge_rx_spare_map;
---
> map = rxd->rx_dmamap;
> rxd->rx_dmamap = cd->sge_rx_spare_map;
1093c1112
< bus_dmamap_sync(cd->sge_rxmbuf_tag, cd->sge_rx_map[prod],
---
> bus_dmamap_sync(cd->sge_rxmbuf_tag, rxd->rx_dmamap,
1095c1114
< cd->sge_rx_mbuf[prod] = m;
---
> rxd->rx_m = m;
1181c1200
< m = cd->sge_rx_mbuf[cons];
---
> m = cd->sge_rxdesc[cons].rx_m;
1247a1267
> struct sge_txdesc *txd;
1249c1269
< int cons, prod;
---
> int cons, nsegs, prod;
1263c1283
< for (; cons != prod; SGE_INC(cons, SGE_TX_RING_CNT)) {
---
> for (; cons != prod;) {
1267,1276c1287,1294
< cd->sge_tx_cnt--;
< ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
< if (cd->sge_tx_mbuf[cons] != NULL) {
< bus_dmamap_sync(cd->sge_txmbuf_tag,
< cd->sge_tx_map[cons], BUS_DMASYNC_POSTWRITE);
< bus_dmamap_unload(cd->sge_txmbuf_tag,
< cd->sge_tx_map[cons]);
< m_freem(cd->sge_tx_mbuf[cons]);
< cd->sge_tx_mbuf[cons] = NULL;
< if (SGE_TX_ERROR(txstat) != 0) {
---
> /*
> * Only the first descriptor of multi-descriptor transmission
> * is updated by controller. Driver should skip entire
> * chained buffers for the transmitted frame. In other words
> * TDC_OWN bit is valid only at the first descriptor of a
> * multi-descriptor transmission.
> */
> if (SGE_TX_ERROR(txstat) != 0) {
1278,1279c1296,1297
< device_printf(sc->sge_dev, "Tx error : 0x%b\n",
< txstat, TX_ERR_BITS);
---
> device_printf(sc->sge_dev, "Tx error : 0x%b\n",
> txstat, TX_ERR_BITS);
1281,1282c1299,1300
< ifp->if_oerrors++;
< } else {
---
> ifp->if_oerrors++;
> } else {
1284c1302
< ifp->if_collisions += (txstat & 0xFFFF) - 1;
---
> ifp->if_collisions += (txstat & 0xFFFF) - 1;
1286,1287c1304
< ifp->if_opackets++;
< }
---
> ifp->if_opackets++;
1289c1306,1323
<
---
> txd = &cd->sge_txdesc[cons];
> for (nsegs = 0; nsegs < txd->tx_ndesc; nsegs++) {
> ld->sge_tx_ring[cons].sge_cmdsts = 0;
> SGE_INC(cons, SGE_TX_RING_CNT);
> }
> /* Reclaim transmitted mbuf. */
> KASSERT(txd->tx_m != NULL,
> ("%s: freeing NULL mbuf\n", __func__));
> bus_dmamap_sync(cd->sge_txmbuf_tag, txd->tx_dmamap,
> BUS_DMASYNC_POSTWRITE);
> bus_dmamap_unload(cd->sge_txmbuf_tag, txd->tx_dmamap);
> m_freem(txd->tx_m);
> txd->tx_m = NULL;
> cd->sge_tx_cnt -= txd->tx_ndesc;
> KASSERT(cd->sge_tx_cnt >= 0,
> ("%s: Active Tx desc counter was garbled\n", __func__));
> txd->tx_ndesc = 0;
> ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1390a1425
> struct sge_txdesc *txd;
1392d1426
< bus_dmamap_t map;
1394c1428
< int error, nsegs, prod;
---
> int error, i, nsegs, prod, si;
1398,1416c1432,1437
< prod = sc->sge_cdata.sge_tx_prod;
< map = sc->sge_cdata.sge_tx_map[prod];
< /*
< * Reading Windows inf file indicates SiS controller supports
< * TSO, VLAN hardware tag insertion/stripping, interrupt
< * moderation and Tx/Rx checksum offloading. Unfortunately
< * vendor didn't release these information so we're guessing
< * descriptor usage with trial and errors.
< *
< * Controller seems to support multi-fragmented buffers but
< * don't know how to enable that feature so limit number of
< * fragmented Tx buffers to single buffer until we understand
< * the controller internals.
< * I assume the controller can pad zero bytes if frame length
< * is less than 60 bytes and I also think the controller has
< * no Tx buffer alignment limitation. - Need testing!
< */
< if ((*m_head)->m_next != NULL) {
< m = m_defrag(*m_head, M_DONTWAIT);
---
> si = prod = sc->sge_cdata.sge_tx_prod;
> txd = &sc->sge_cdata.sge_txdesc[prod];
> error = bus_dmamap_load_mbuf_sg(sc->sge_cdata.sge_txmbuf_tag,
> txd->tx_dmamap, *m_head, txsegs, &nsegs, 0);
> if (error == EFBIG) {
> m = m_collapse(*m_head, M_DONTWAIT, SGE_MAXTXSEGS);
1423,1428c1444,1451
< }
< error = bus_dmamap_load_mbuf_sg(sc->sge_cdata.sge_txmbuf_tag, map,
< *m_head, txsegs, &nsegs, 0);
< if (error != 0) {
< m_freem(*m_head);
< *m_head = NULL;
---
> error = bus_dmamap_load_mbuf_sg(sc->sge_cdata.sge_txmbuf_tag,
> txd->tx_dmamap, *m_head, txsegs, &nsegs, 0);
> if (error != 0) {
> m_freem(*m_head);
> *m_head = NULL;
> return (error);
> }
> } else if (error != 0)
1430c1453,1454
< }
---
>
> KASSERT(nsegs != 0, ("zero segment returned"));
1433c1457
< bus_dmamap_unload(sc->sge_cdata.sge_txmbuf_tag, map);
---
> bus_dmamap_unload(sc->sge_cdata.sge_txmbuf_tag, txd->tx_dmamap);
1436c1460
< bus_dmamap_sync(sc->sge_cdata.sge_txmbuf_tag, map,
---
> bus_dmamap_sync(sc->sge_cdata.sge_txmbuf_tag, txd->tx_dmamap,
1438a1463
> m = *m_head;
1440c1465
< if ((*m_head)->m_pkthdr.csum_flags & CSUM_IP)
---
> if (m->m_pkthdr.csum_flags & CSUM_IP)
1442c1467
< if ((*m_head)->m_pkthdr.csum_flags & CSUM_TCP)
---
> if (m->m_pkthdr.csum_flags & CSUM_TCP)
1444c1469
< if ((*m_head)->m_pkthdr.csum_flags & CSUM_UDP)
---
> if (m->m_pkthdr.csum_flags & CSUM_UDP)
1446,1451c1471,1490
< desc = &sc->sge_ldata.sge_tx_ring[prod];
< desc->sge_sts_size = htole32((*m_head)->m_pkthdr.len);
< desc->sge_ptr = htole32(SGE_ADDR_LO(txsegs[0].ds_addr));
< desc->sge_flags = htole32(txsegs[0].ds_len);
< if (prod == SGE_TX_RING_CNT - 1)
< desc->sge_flags |= htole32(RING_END);
---
> for (i = 0; i < nsegs; i++) {
> desc = &sc->sge_ldata.sge_tx_ring[prod];
> if (i == 0) {
> desc->sge_sts_size = htole32(m->m_pkthdr.len);
> desc->sge_cmdsts = 0;
> } else {
> desc->sge_sts_size = 0;
> desc->sge_cmdsts = htole32(TDC_OWN);
> }
> desc->sge_ptr = htole32(SGE_ADDR_LO(txsegs[i].ds_addr));
> desc->sge_flags = htole32(txsegs[i].ds_len);
> if (prod == SGE_TX_RING_CNT - 1)
> desc->sge_flags |= htole32(RING_END);
> sc->sge_cdata.sge_tx_cnt++;
> SGE_INC(prod, SGE_TX_RING_CNT);
> }
> /* Update producer index. */
> sc->sge_cdata.sge_tx_prod = prod;
>
> desc = &sc->sge_ldata.sge_tx_ring[si];
1453,1454c1492,1493
< if(((*m_head)->m_flags & M_VLANTAG) != 0) {
< cflags |= (*m_head)->m_pkthdr.ether_vtag;
---
> if((m->m_flags & M_VLANTAG) != 0) {
> cflags |= m->m_pkthdr.ether_vtag;
1457c1496
< desc->sge_cmdsts = htole32(TDC_DEF | TDC_CRC | TDC_PAD | cflags);
---
> desc->sge_cmdsts |= htole32(TDC_DEF | TDC_CRC | TDC_PAD | cflags);
1469,1475c1508,1510
< if ((prod % SGE_TX_INTR_FRAMES) == 0)
< desc->sge_cmdsts |= htole32(TDC_OWN | TDC_INTR);
< else
< desc->sge_cmdsts |= htole32(TDC_OWN);
< sc->sge_cdata.sge_tx_mbuf[prod] = *m_head;
< sc->sge_cdata.sge_tx_cnt++;
< SGE_INC(sc->sge_cdata.sge_tx_prod, SGE_TX_RING_CNT);
---
> desc->sge_cmdsts |= htole32(TDC_OWN | TDC_INTR);
> txd->tx_m = m;
> txd->tx_ndesc = nsegs;
1506c1541,1542
< if (sc->sge_cdata.sge_tx_cnt == SGE_TX_RING_CNT - 1) {
---
> if (sc->sge_cdata.sge_tx_cnt > (SGE_TX_RING_CNT -
> SGE_MAXTXSEGS)) {