summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/io/mac/mac_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/io/mac/mac_util.c')
-rw-r--r--usr/src/uts/common/io/mac/mac_util.c82
1 files changed, 56 insertions, 26 deletions
diff --git a/usr/src/uts/common/io/mac/mac_util.c b/usr/src/uts/common/io/mac/mac_util.c
index 371145e68c..3d9d2f9b39 100644
--- a/usr/src/uts/common/io/mac/mac_util.c
+++ b/usr/src/uts/common/io/mac/mac_util.c
@@ -244,14 +244,23 @@ mac_fix_cksum(mblk_t *mp_chain)
offset, cksum);
*(up) = (uint16_t)(cksum ? cksum : ~cksum);
+ /*
+ * Flag the packet so that it appears
+ * that the checksum has already been
+ * verified by the hardware.
+ */
+ flags &= ~HCK_FULLCKSUM;
flags |= HCK_FULLCKSUM_OK;
- value = 0xffff;
+ value = 0;
}
if (flags & HCK_IPV4_HDRCKSUM) {
ASSERT(ipha != NULL);
ipha->ipha_hdr_checksum =
(uint16_t)ip_csum_hdr(ipha);
+ flags &= ~HCK_IPV4_HDRCKSUM;
+ flags |= HCK_IPV4_HDRCKSUM_OK;
+
}
}
@@ -292,8 +301,8 @@ mac_fix_cksum(mblk_t *mp_chain)
* been verified by the hardware.
*/
flags &= ~HCK_PARTIALCKSUM;
- flags |= (HCK_FULLCKSUM | HCK_FULLCKSUM_OK);
- value = 0xffff;
+ flags |= HCK_FULLCKSUM_OK;
+ value = 0;
}
(void) hcksum_assoc(mp, NULL, NULL, start, stuff, end,
@@ -470,27 +479,25 @@ mac_pkt_drop(void *arg, mac_resource_handle_t resource, mblk_t *mp,
* returns B_TRUE.
*/
boolean_t
-mac_ip_hdr_length_v6(mblk_t *mp, ip6_t *ip6h, uint16_t *hdr_length,
- uint8_t *next_hdr, boolean_t *ip_fragmented, uint32_t *ip_frag_ident)
+mac_ip_hdr_length_v6(ip6_t *ip6h, uint8_t *endptr, uint16_t *hdr_length,
+ uint8_t *next_hdr, ip6_frag_t **fragp)
{
uint16_t length;
uint_t ehdrlen;
uint8_t *whereptr;
- uint8_t *endptr;
uint8_t *nexthdrp;
ip6_dest_t *desthdr;
ip6_rthdr_t *rthdr;
ip6_frag_t *fraghdr;
- endptr = mp->b_wptr;
if (((uchar_t *)ip6h + IPV6_HDR_LEN) > endptr)
return (B_FALSE);
ASSERT(IPH_HDR_VERSION(ip6h) == IPV6_VERSION);
length = IPV6_HDR_LEN;
whereptr = ((uint8_t *)&ip6h[1]); /* point to next hdr */
- if (ip_fragmented != NULL)
- *ip_fragmented = B_FALSE;
+ if (fragp != NULL)
+ *fragp = NULL;
nexthdrp = &ip6h->ip6_nxt;
while (whereptr < endptr) {
@@ -521,10 +528,8 @@ mac_ip_hdr_length_v6(mblk_t *mp, ip6_t *ip6h, uint16_t *hdr_length,
if ((uchar_t *)&fraghdr[1] > endptr)
return (B_FALSE);
nexthdrp = &fraghdr->ip6f_nxt;
- if (ip_fragmented != NULL)
- *ip_fragmented = B_TRUE;
- if (ip_frag_ident != NULL)
- *ip_frag_ident = fraghdr->ip6f_ident;
+ if (fragp != NULL)
+ *fragp = fraghdr;
break;
case IPPROTO_NONE:
/* No next header means we're finished */
@@ -561,6 +566,13 @@ mac_ip_hdr_length_v6(mblk_t *mp, ip6_t *ip6h, uint16_t *hdr_length,
}
}
+/*
+ * The following set of routines are there to take care of interrupt
+ * re-targeting for legacy (fixed) interrupts. Some older versions
+ * of the popular NICs like e1000g do not support MSI-X interrupts
+ * and they reserve fixed interrupts for RX/TX rings. To re-target
+ * these interrupts, PCITOOL ioctls need to be used.
+ */
typedef struct mac_dladm_intr {
int ino;
int cpu_id;
@@ -807,13 +819,20 @@ mac_client_set_intr_cpu(void *arg, mac_client_handle_t mch, int32_t cpuid)
mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
mac_resource_props_t *mrp;
mac_perim_handle_t mph;
+ flow_entry_t *flent = mcip->mci_flent;
+ mac_soft_ring_set_t *rx_srs;
+ mac_cpus_t *srs_cpu;
- if (cpuid == -1 || !mac_check_interrupt_binding(mdip, cpuid))
- return;
-
+ if (!mac_check_interrupt_binding(mdip, cpuid))
+ cpuid = -1;
mac_perim_enter_by_mh((mac_handle_t)mcip->mci_mip, &mph);
mrp = MCIP_RESOURCE_PROPS(mcip);
- mrp->mrp_intr_cpu = cpuid;
+ mrp->mrp_rx_intr_cpu = cpuid;
+ if (flent != NULL && flent->fe_rx_srs_cnt == 2) {
+ rx_srs = flent->fe_rx_srs[1];
+ srs_cpu = &rx_srs->srs_cpu;
+ srs_cpu->mc_rx_intr_cpu = cpuid;
+ }
mac_perim_exit(mph);
}
@@ -825,18 +844,29 @@ mac_client_intr_cpu(mac_client_handle_t mch)
mac_soft_ring_set_t *rx_srs;
flow_entry_t *flent = mcip->mci_flent;
mac_resource_props_t *mrp = MCIP_RESOURCE_PROPS(mcip);
+ mac_ring_t *ring;
+ mac_intr_t *mintr;
/*
* Check if we need to retarget the interrupt. We do this only
* for the primary MAC client. We do this if we have the only
- * exclusive ring in the group.
+ * exclusive ring in the group.
*/
if (mac_is_primary_client(mcip) && flent->fe_rx_srs_cnt == 2) {
rx_srs = flent->fe_rx_srs[1];
srs_cpu = &rx_srs->srs_cpu;
- if (mrp->mrp_intr_cpu == srs_cpu->mc_pollid)
+ ring = rx_srs->srs_ring;
+ mintr = &ring->mr_info.mri_intr;
+ /*
+ * If ddi_handle is present or the poll CPU is
+ * already bound to the interrupt CPU, return -1.
+ */
+ if (mintr->mi_ddi_handle != NULL ||
+ ((mrp->mrp_ncpus != 0) &&
+ (mrp->mrp_rx_intr_cpu == srs_cpu->mc_rx_pollid))) {
return (-1);
- return (srs_cpu->mc_pollid);
+ }
+ return (srs_cpu->mc_rx_pollid);
}
return (-1);
}
@@ -970,8 +1000,8 @@ mac_pkt_hash(uint_t media, mblk_t *mp, uint8_t policy, boolean_t is_outbound)
}
case ETHERTYPE_IPV6: {
ip6_t *ip6hp;
+ ip6_frag_t *frag = NULL;
uint16_t hdr_length;
- uint32_t ip_frag_ident;
/*
* If the header is not aligned or the header doesn't fit
@@ -984,8 +1014,8 @@ mac_pkt_hash(uint_t media, mblk_t *mp, uint8_t policy, boolean_t is_outbound)
!OK_32PTR((char *)ip6hp))
goto done;
- if (!mac_ip_hdr_length_v6(mp, ip6hp, &hdr_length, &proto,
- &ip_fragmented, &ip_frag_ident))
+ if (!mac_ip_hdr_length_v6(ip6hp, mp->b_wptr, &hdr_length,
+ &proto, &frag))
goto done;
skip_len += hdr_length;
@@ -994,7 +1024,7 @@ mac_pkt_hash(uint_t media, mblk_t *mp, uint8_t policy, boolean_t is_outbound)
* the frag_id to generate the hash inorder to get
* better distribution.
*/
- if (ip_fragmented || (policy & MAC_PKT_HASH_L3) != 0) {
+ if (frag != NULL || (policy & MAC_PKT_HASH_L3) != 0) {
uint8_t *ip_src = &(ip6hp->ip6_src.s6_addr8[12]);
uint8_t *ip_dst = &(ip6hp->ip6_dst.s6_addr8[12]);
@@ -1003,8 +1033,8 @@ mac_pkt_hash(uint_t media, mblk_t *mp, uint8_t policy, boolean_t is_outbound)
policy &= ~MAC_PKT_HASH_L3;
}
- if (ip_fragmented) {
- uint8_t *identp = (uint8_t *)&ip_frag_ident;
+ if (frag != NULL) {
+ uint8_t *identp = (uint8_t *)&frag->ip6f_ident;
hash ^= PKT_HASH_4BYTES(identp);
goto done;
}