nxge_send.c revision 321febde881fb7f55caa9bc4766f121ff16cd65e
"==> nxge_start: Starting tdc %d desc pending %d",
* For the following modes, check the link status * before sending the packet out: * nxge_lb_normal, nxge_lb_ext10g, nxge_lb_phy10g "==> nxge_start(0): LSO mp $%p mp_chain $%p",
"==> nxge_send(0): NULL mp_chain $%p != mp $%p",
"==> nxge_send(1): IS LSO mp_chain $%p != mp $%p",
"==> nxge_start: mp $%p len %d " "cksum_flags 0x%x (partial checksum) ",
"==> nxge_start: tdc %d: dumping ...: b_rptr $%p " "(Before header reserve: ORIGINAL LEN %d)",
"(IP ORIGINAL b_rptr $%p): %s",
mp->
b_rptr,
"TX Descriptor ring is channel %d mark mode %d",
"TX Descriptor ring is full: channel %d",
"TX Descriptor ring is full: channel %d",
/* free the current mp and mp_chain if not FULL */ "LSO packet: TX Descriptor ring is full: " "==> nxge_start(1): wr_index %d i %d msgdsize %d",
* The first 16 bytes of the premapped buffer are reserved * for header. No padding will be used. "len %d pkt_len %d pack_len %d",
* Hardware limits the transfer length to 4K for NIU and * 4076 (TX_MAX_TRANSFER_LENGTH) for Neptune. But we just * use TX_MAX_TRANSFER_LENGTH as the limit for both. * If len is longer than the limit, then we break nmp into * two chunks: Make the first chunk equal to the limit and * the second chunk for the remaining data. If the second * chunk is still larger than the limit, then it will be * broken into two in the next pass. "LSO packet: dupb failed: " "desc_vp $%p tx_desc_p $%p " "desc_pp $%p tx_desc_pp $%p " "len %d pkt_len %d pack_len %d",
"==> nxge_start(5): pack"));
"==> nxge_start: pack(6) " "(pkt_len %d pack_len %d)",
"==> nxge_start(7): > max NEW " "pkt_len %d pack_len %d(next)",
"pkt_len %d pack_len %d (new hdrp $%p)",
"USE BCOPY: before bcopy " "DESC IOADDR $%p entry %d " "bcopy ioaddr (SAD) $%p " "last USE BCOPY: copy from b_rptr $%p " "to KADDR $%p (len %d offset %d",
"==> nxge_start: dump packets " "DESC IOADDR $%p entry %d " "bcopy ioaddr (SAD) $%p " "USE DVMA: len %d",
len));
"USE DVMA: len %d clen %d " * this is the fix for multiple * cookies, which are basically * a descriptor entry, we don't set * SOP bit as well as related fields "desc $%p descp $%p (%d)",
"USE DVMA: len %d clen %d ",
"dma mapping failed for %d " "bytes addr $%p flags %x (%d)",
"Desc_entry %d ngathers %d " "desc_vp $%p tx_desc_p $%p " "len %d clen %d pkt_len %d pack_len %d nmblks %d " "dma_ioaddr (SAD) $%p mark %d",
"\t\tsad $%p\ttr_len %d len %d\tnptrs %d\t" "==> nxge_start(14): pull msg - " "len %d pkt_len %d ngathers %d",
/* Pull all message blocks from b_cont */ /* Assume we use bcopy to premapped buffers */ "==> nxge_start(14-1): < (msg_min + 16)" "len %d pkt_len %d min_len %d bzero %d ngathers %d",
"==> nxge_start(14-2): < msg_min - " "len %d pkt_len %d min_len %d ngathers %d",
"==> nxge_start: cksum_flags 0x%x (partial checksum) ",
"==> nxge_start: from IP cksum_flags 0x%x " "start_offset %d stuff_offset %d",
"==> nxge_start: from IP cksum_flags 0x%x " "after SHIFT start_offset %d stuff_offset %d",
/* pkt_len already includes 16 + paddings!! */ /* Update the control header length */ "==> nxge_start(15_x1): setting SOP " "tot_xfer_len 0x%llx (%d) pkt_len %d tmp_len " "0x%llx hdrp->value 0x%llx",
TX_CTL,
"==> nxge_start(15_x2): setting SOP " "after SWAP: tot_xfer_len 0x%llx pkt_len %d " "tmp_len 0x%llx hdrp->value 0x%llx",
"tot_xfer_len (%d) pkt_len %d npads %d",
"\t\tsad $%p\ttr_len %d len %d\tnptrs %d\tmark %d sop %d\n",
"==> nxge_start: dump packets(17) (after sop set, len " "==> nxge_start(18): TX desc sync: sop_index %d",
"cs_off = 0x%02X cs_s_off = 0x%02X " "pkt_len %d ngathers %d sop_index %d\n",
}
else {
/* more than one descriptor and wrap around */ "cs_off = 0x%02X cs_s_off = 0x%02X " "pkt_len %d ngathers %d sop_index %d\n",
"cs_off = 0x%02X cs_s_off = 0x%02X " "pkt_len %d ngathers %d sop_index %d\n",
"channel %d wr_index %d wrap %d ngathers %d desc_pend %d",
/* Kick the Transmit kick register */ "==> nxge_start: more LSO: " "==> nxge_start: lso again: " "lso_gathers %d ngathers %d cur_index_lso %d " "wr_index %d sop_index %d",
"==> nxge_start: next : count %d",
/* Kick start the Transmit kick register */ "==> nxge_start: lso exit (nothing changed)"));
"==> nxge_start (channel %d): before lso " "lso_gathers %d ngathers %d cur_index_lso %d " "wr_index %d sop_index %d lso_again %d",
"==> nxge_start (channel %d): after lso " "lso_gathers %d ngathers %d cur_index_lso %d " "wr_index %d sop_index %d lso_again %d",
"tx_desc_p = %X index = %d",
"ddi_dma_unbind_handle failed");
/* Add FMA to check the access handle nxge_hregh */ * nxge_m_tx() - send a chain of packets "==> nxge_m_tx: hardware not initialized"));
* Until Nemo tx resource works, the mac driver * does the load balancing based on TCP port, * or CPU. For debugging, we use a system * configurable parameter. "==> nxge_m_tx: (go back to loop) mp $%p next $%p",
* allocate space big enough to cover * the max ip header length and the first * 4 bytes of the TCP/IP header. /* SPI starts at the 4th byte */ }
else {
/* fragmented packet *//* Software LSO starts here */ "==> nxge_lso_info_get(flag !=NULL): mss %d *flags 0x%x",
"<== nxge_lso_info_get: mss %d", *
mss));
* Do Soft LSO on the oversized packet. * 1. Create a chain of message for headers. * 2. Fill up header messages with proper information. * 3. Copy Eithernet, IP, and TCP headers from the original message to * each new message with necessary adjustments. * * Unchange the ethernet header for DIX frames. (by default) * * IP Total Length field is updated to MSS or less(only for the last one). * * IP Identification value is incremented by one for each packet. * * TCP sequence Number is recalculated according to the payload length. * * Set FIN and/or PSH flags for the *last* packet if applied. * 4. Update LSO information in the first message header. * 5. Release the original message header. * check the length of LSO packet payload and calculate the number of * segments to be generated. "==> nxge_do_softlso: mss %d oiph $%p " "original ip_sum oiph->ip_sum 0x%x " "original tcp_sum otcph->th_sum 0x%x " "oiph->ip_len %d pktlen %d ehlen %d " "l4_len %d (0x%x) ip_len - iphlen %d ",
"<== nxge_do_softlso: not IPV4 " "oiph->ip_len %d pktlen %d ehlen %d tcphlen %d",
"<== nxge_do_softlso: not TCP " "oiph->ip_len %d pktlen %d ehlen %d tcphlen %d",
"<== nxge_do_softlso: len not matched " "oiph->ip_len %d pktlen %d ehlen %d tcphlen %d",
/* TCP flags can not include URG, RST, or SYN */ "nxge_do_softlso: otcph $%p pktlen: %d, " "hdrlen %d ehlen %d iphlen %d tcphlen %d " "mblkl(mp): %d, mblkl(datamp): %d",
"==> nxge_do_softlso: dst 0x%x src 0x%x sum 0x%x ~new 0x%x " "hckflags 0x%x start_offset %d stuff_offset %d " "value (original) 0x%x th_sum 0x%x " "pktlen %d l4_len %d (0x%x) " "MBLKL(mp): %d, MBLKL(datamp): %d dump header %s",
(
sum &
0xffff), (~
sum &
0xffff),
"==> nxge_do_softlso: pktlen %d " "MBLKL(mp): %d, MBLKL(datamp): %d " "available %d mss %d segnum %d",
* Try to pre-allocate all header messages for (i = 0; i <
segnum; i++) {
/* Clean up the mp_chain */ "Could not allocate enough messages for headers!"));
"mp $%p nmp $%p mp_chain $%p mp_chain->b_next $%p",
"==> nxge_do_softlso: mp $%p nmp $%p mp_chain $%p",
* Associate payload with new packets "Can not dupb(datamp), have to do clean up"));
"==> nxge_do_softlso: (loop) before mp $%p cmp $%p " "dupb nmp $%p len %d left %d msd %d ",
"==> nxge_do_softlso: (loop) after mp $%p cmp $%p " "dupb nmp $%p len %d left %d mss %d ",
"nxge_do_softlso: before available: %d, " "left: %d, len: %d, segnum: %d MBLK(nmp): %d",
"nxge_do_softlso: after available: %d, " "left: %d, len: %d, segnum: %d MBLK(nmp): %d",
"nxge_do_softlso: (4) len > 0 available: %d, " "left: %d, len: %d, segnum: %d MBLK(nmp): %d",
"Can not dupb(datamp) (1), : NXGE_DEBUG_MSG((NULL, TX_CTL, goto cleanup_allocated_msgs; NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, NXGE_DEBUG_MSG((NULL, TX_CTL, available, left, len, (int)MBLKL(nmp))); if (datamp->b_cont != NULL) { NXGE_DEBUG_MSG((NULL, TX_CTL, available, left, len, (int)MBLKL(nmp))); NXGE_DEBUG_MSG((NULL, TX_CTL, available, left, len, (int)MBLKL(nmp))); VERIFY(cmp->b_next == NULL); NXGE_DEBUG_MSG((NULL, TX_CTL, available, left, len, (int)MBLKL(nmp))); * From now, start to fill up all headers for the first message * Hardware checksum flags need to be updated separately for FULLCKSUM * and PARTIALCKSUM cases. For full checksum, copy the original flags * into every new packet is enough. But for HCK_PARTIALCKSUM, all * required fields need to be updated properly. bcopy(mp->b_rptr, nmp->b_rptr, hdrlen); nmp->b_wptr = nmp->b_rptr + hdrlen; niph = (struct ip *)(nmp->b_rptr + ehlen); niph->ip_len = htons(mss + iphlen + tcphlen); ip_id = ntohs(niph->ip_id); ntcph = (struct tcphdr *)(nmp->b_rptr + ehlen + iphlen); bcopy((char *)&ntcph->th_seq, &tcp_seq_tmp, 4); tcp_seq = ntohl(tcp_seq_tmp); tcp_seq = ntohl(ntcph->th_seq); ntcph->th_flags &= ~(TH_FIN | TH_PUSH | TH_RST); DB_CKSUMFLAGS(nmp) = (uint16_t)hckflags; DB_CKSUMSTART(nmp) = start_offset; DB_CKSUMSTUFF(nmp) = stuff_offset; /* calculate IP checksum and TCP pseudo header checksum */ niph->ip_sum = (uint16_t)nxge_csgen((uint16_t *)niph, iphlen); sum = htons(l4_len) + l4cksum; sum = (sum & 0xFFFF) + (sum >> 16); ntcph->th_sum = (sum & 0xffff); NXGE_DEBUG_MSG((NULL, TX_CTL, (int)MBLKL(mp), (int)MBLKL(datamp), nxge_dump_packet((char *)niph, 52))); while ((nmp = nmp->b_next)->b_next != NULL) { NXGE_DEBUG_MSG((NULL, TX_CTL, bcopy(cmp->b_rptr, nmp->b_rptr, hdrlen); nmp->b_wptr = nmp->b_rptr + hdrlen; niph = (struct ip *)(nmp->b_rptr + ehlen); niph->ip_id = htons(++ip_id); niph->ip_len = htons(mss + iphlen + tcphlen); ntcph = (struct tcphdr *)(nmp->b_rptr + ehlen + iphlen); ntcph->th_flags &= ~(TH_FIN | TH_PUSH | TH_RST | TH_URG); tcp_seq_tmp = htonl(tcp_seq); bcopy(&tcp_seq_tmp, (char *)&ntcph->th_seq, 4); ntcph->th_seq = htonl(tcp_seq); DB_CKSUMFLAGS(nmp) = (uint16_t)hckflags; DB_CKSUMSTART(nmp) = start_offset; DB_CKSUMSTUFF(nmp) = stuff_offset; /* calculate IP checksum and TCP pseudo header checksum */ niph->ip_sum = (uint16_t)nxge_csgen((uint16_t *)niph, iphlen); ntcph->th_sum = (sum & 0xffff); NXGE_DEBUG_MSG((NULL, TX_CTL, pktlen, (int)MBLKL(mp), (int)MBLKL(datamp))); * Set FIN and/or PSH flags if present only in the last packet. * The ip_len could be different from prior packets. bcopy(cmp->b_rptr, nmp->b_rptr, hdrlen); nmp->b_wptr = nmp->b_rptr + hdrlen; niph = (struct ip *)(nmp->b_rptr + ehlen); niph->ip_id = htons(++ip_id); niph->ip_len = htons(msgsize(nmp->b_cont) + iphlen + tcphlen); ntcph = (struct tcphdr *)(nmp->b_rptr + ehlen + iphlen); tcp_seq_tmp = htonl(tcp_seq); bcopy(&tcp_seq_tmp, (char *)&ntcph->th_seq, 4); ntcph->th_seq = htonl(tcp_seq); ntcph->th_flags = (otcph->th_flags & ~TH_URG); DB_CKSUMFLAGS(nmp) = (uint16_t)hckflags; DB_CKSUMSTART(nmp) = start_offset; DB_CKSUMSTUFF(nmp) = stuff_offset; /* calculate IP checksum and TCP pseudo header checksum */ niph->ip_sum = (uint16_t)nxge_csgen((uint16_t *)niph, iphlen); l4_len = ntohs(niph->ip_len) - iphlen; sum = htons(l4_len) + l4cksum; sum = (sum & 0xFFFF) + (sum >> 16); ntcph->th_sum = (sum & 0xffff); NXGE_DEBUG_MSG((NULL, TX_CTL, nxge_dump_packet((char *)niph, 52), (int)MBLKL(mp), (int)MBLKL(datamp))); NXGE_DEBUG_MSG((NULL, TX_CTL, while (mp_chain != NULL) { mp_chain = mp_chain->b_next; * We're done here, so just free the original message and return the * new message chain, that could be NULL if failed, back to the caller. NXGE_DEBUG_MSG((NULL, TX_CTL, * Will be called before NIC driver do further operation on the message. * The input message may include LSO information, if so, go to softlso logic * to eliminate the oversized LSO packet for the incapable underlying h/w. * The return could be the same non-LSO message or a message chain for LSO case. * The driver needs to call this function per packet and process the whole chain nxge_lso_eliminate(mblk_t *mp) NXGE_DEBUG_MSG((NULL, TX_CTL, nxge_lso_info_get(mp, &mss, &lsoflags); NXGE_DEBUG_MSG((NULL, TX_CTL, if ((nmp = nxge_do_softlso(mp, mss)) != NULL) { NXGE_DEBUG_MSG((NULL, TX_CTL, NXGE_DEBUG_MSG((NULL, TX_CTL, NXGE_DEBUG_MSG((NULL, TX_CTL, nxge_csgen(uint16_t *adr, int len) for (i = 0; i < (len / 2); i++) { sum += (adr[i] & 0xffff); sum += adr[len / 2] & 0xff00; while ((c = ((sum & 0xffff0000) >> 16)) != 0) {