1*d62bc4baSyz147064 /* 2*d62bc4baSyz147064 * CDDL HEADER START 3*d62bc4baSyz147064 * 4*d62bc4baSyz147064 * The contents of this file are subject to the terms of the 5*d62bc4baSyz147064 * Common Development and Distribution License (the "License"). 6*d62bc4baSyz147064 * You may not use this file except in compliance with the License. 7*d62bc4baSyz147064 * 8*d62bc4baSyz147064 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*d62bc4baSyz147064 * or http://www.opensolaris.org/os/licensing. 10*d62bc4baSyz147064 * See the License for the specific language governing permissions 11*d62bc4baSyz147064 * and limitations under the License. 12*d62bc4baSyz147064 * 13*d62bc4baSyz147064 * When distributing Covered Code, include this CDDL HEADER in each 14*d62bc4baSyz147064 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*d62bc4baSyz147064 * If applicable, add the following below this CDDL HEADER, with the 16*d62bc4baSyz147064 * fields enclosed by brackets "[]" replaced with your own identifying 17*d62bc4baSyz147064 * information: Portions Copyright [yyyy] [name of copyright owner] 18*d62bc4baSyz147064 * 19*d62bc4baSyz147064 * CDDL HEADER END 20*d62bc4baSyz147064 */ 21*d62bc4baSyz147064 /* 22*d62bc4baSyz147064 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*d62bc4baSyz147064 * Use is subject to license terms. 24*d62bc4baSyz147064 */ 25*d62bc4baSyz147064 26*d62bc4baSyz147064 #pragma ident "%Z%%M% %I% %E% SMI" 27*d62bc4baSyz147064 28*d62bc4baSyz147064 #include <sys/types.h> 29*d62bc4baSyz147064 #include <sys/mac.h> 30*d62bc4baSyz147064 #include <sys/softmac_impl.h> 31*d62bc4baSyz147064 32*d62bc4baSyz147064 typedef struct softmac_capab_ops { 33*d62bc4baSyz147064 int (*sc_hcksum_ack)(void *, t_uscalar_t); 34*d62bc4baSyz147064 int (*sc_zcopy_ack)(void *, t_uscalar_t); 35*d62bc4baSyz147064 int (*sc_mdt_ack)(void *, dl_capab_mdt_t *); 36*d62bc4baSyz147064 } softmac_capab_ops_t; 37*d62bc4baSyz147064 38*d62bc4baSyz147064 static int dl_capab(ldi_handle_t, mblk_t **); 39*d62bc4baSyz147064 static int softmac_fill_hcksum_ack(void *, t_uscalar_t); 40*d62bc4baSyz147064 static int softmac_fill_zcopy_ack(void *, t_uscalar_t); 41*d62bc4baSyz147064 static int softmac_fill_mdt_ack(void *, dl_capab_mdt_t *); 42*d62bc4baSyz147064 static int softmac_adv_hcksum_ack(void *, t_uscalar_t); 43*d62bc4baSyz147064 static int softmac_adv_zcopy_ack(void *, t_uscalar_t); 44*d62bc4baSyz147064 static int softmac_adv_mdt_ack(void *, dl_capab_mdt_t *); 45*d62bc4baSyz147064 static int softmac_enable_hcksum_ack(void *, t_uscalar_t); 46*d62bc4baSyz147064 static int softmac_enable_mdt_ack(void *, dl_capab_mdt_t *); 47*d62bc4baSyz147064 static int softmac_capab_send(softmac_lower_t *, boolean_t); 48*d62bc4baSyz147064 static int i_capab_ack(mblk_t *, queue_t *, softmac_capab_ops_t *, void *); 49*d62bc4baSyz147064 static int i_capab_id_ack(mblk_t *, dl_capability_sub_t *, queue_t *, 50*d62bc4baSyz147064 softmac_capab_ops_t *, void *); 51*d62bc4baSyz147064 static int i_capab_sub_ack(mblk_t *, dl_capability_sub_t *, queue_t *, 52*d62bc4baSyz147064 softmac_capab_ops_t *, void *); 53*d62bc4baSyz147064 static int i_capab_hcksum_ack(dl_capab_hcksum_t *, queue_t *, 54*d62bc4baSyz147064 softmac_capab_ops_t *, void *); 55*d62bc4baSyz147064 static int i_capab_zcopy_ack(dl_capab_zerocopy_t *, queue_t *, 56*d62bc4baSyz147064 softmac_capab_ops_t *, void *); 57*d62bc4baSyz147064 static int i_capab_mdt_ack(dl_capab_mdt_t *, queue_t *, 58*d62bc4baSyz147064 softmac_capab_ops_t *, void *); 59*d62bc4baSyz147064 static int i_capab_hcksum_verify(dl_capab_hcksum_t *, queue_t *); 60*d62bc4baSyz147064 static int i_capab_zcopy_verify(dl_capab_zerocopy_t *, queue_t *); 61*d62bc4baSyz147064 static int i_capab_mdt_verify(dl_capab_mdt_t *, queue_t *); 62*d62bc4baSyz147064 63*d62bc4baSyz147064 static softmac_capab_ops_t softmac_fill_capab_ops = 64*d62bc4baSyz147064 { 65*d62bc4baSyz147064 softmac_fill_hcksum_ack, 66*d62bc4baSyz147064 softmac_fill_zcopy_ack, 67*d62bc4baSyz147064 softmac_fill_mdt_ack, 68*d62bc4baSyz147064 }; 69*d62bc4baSyz147064 70*d62bc4baSyz147064 static softmac_capab_ops_t softmac_adv_capab_ops = 71*d62bc4baSyz147064 { 72*d62bc4baSyz147064 softmac_adv_hcksum_ack, 73*d62bc4baSyz147064 softmac_adv_zcopy_ack, 74*d62bc4baSyz147064 softmac_adv_mdt_ack 75*d62bc4baSyz147064 }; 76*d62bc4baSyz147064 77*d62bc4baSyz147064 static softmac_capab_ops_t softmac_enable_capab_ops = 78*d62bc4baSyz147064 { 79*d62bc4baSyz147064 softmac_enable_hcksum_ack, 80*d62bc4baSyz147064 NULL, 81*d62bc4baSyz147064 softmac_enable_mdt_ack 82*d62bc4baSyz147064 }; 83*d62bc4baSyz147064 84*d62bc4baSyz147064 int 85*d62bc4baSyz147064 softmac_fill_capab(ldi_handle_t lh, softmac_t *softmac) 86*d62bc4baSyz147064 { 87*d62bc4baSyz147064 mblk_t *mp = NULL; 88*d62bc4baSyz147064 union DL_primitives *prim; 89*d62bc4baSyz147064 int err = 0; 90*d62bc4baSyz147064 91*d62bc4baSyz147064 if ((err = dl_capab(lh, &mp)) != 0) 92*d62bc4baSyz147064 goto exit; 93*d62bc4baSyz147064 94*d62bc4baSyz147064 prim = (union DL_primitives *)mp->b_rptr; 95*d62bc4baSyz147064 if (prim->dl_primitive == DL_ERROR_ACK) { 96*d62bc4baSyz147064 err = -1; 97*d62bc4baSyz147064 goto exit; 98*d62bc4baSyz147064 } 99*d62bc4baSyz147064 100*d62bc4baSyz147064 err = i_capab_ack(mp, NULL, &softmac_fill_capab_ops, softmac); 101*d62bc4baSyz147064 102*d62bc4baSyz147064 exit: 103*d62bc4baSyz147064 freemsg(mp); 104*d62bc4baSyz147064 return (err); 105*d62bc4baSyz147064 } 106*d62bc4baSyz147064 107*d62bc4baSyz147064 static int 108*d62bc4baSyz147064 dl_capab(ldi_handle_t lh, mblk_t **mpp) 109*d62bc4baSyz147064 { 110*d62bc4baSyz147064 dl_capability_req_t *capb; 111*d62bc4baSyz147064 union DL_primitives *dl_prim; 112*d62bc4baSyz147064 mblk_t *mp; 113*d62bc4baSyz147064 int err; 114*d62bc4baSyz147064 115*d62bc4baSyz147064 if ((mp = allocb(sizeof (dl_capability_req_t), BPRI_MED)) == NULL) 116*d62bc4baSyz147064 return (ENOMEM); 117*d62bc4baSyz147064 mp->b_datap->db_type = M_PROTO; 118*d62bc4baSyz147064 119*d62bc4baSyz147064 capb = (dl_capability_req_t *)mp->b_wptr; 120*d62bc4baSyz147064 mp->b_wptr += sizeof (dl_capability_req_t); 121*d62bc4baSyz147064 bzero(mp->b_rptr, sizeof (dl_capability_req_t)); 122*d62bc4baSyz147064 capb->dl_primitive = DL_CAPABILITY_REQ; 123*d62bc4baSyz147064 124*d62bc4baSyz147064 (void) ldi_putmsg(lh, mp); 125*d62bc4baSyz147064 if ((err = ldi_getmsg(lh, &mp, (timestruc_t *)NULL)) != 0) 126*d62bc4baSyz147064 return (err); 127*d62bc4baSyz147064 128*d62bc4baSyz147064 dl_prim = (union DL_primitives *)mp->b_rptr; 129*d62bc4baSyz147064 switch (dl_prim->dl_primitive) { 130*d62bc4baSyz147064 case DL_CAPABILITY_ACK: 131*d62bc4baSyz147064 if (MBLKL(mp) < DL_CAPABILITY_ACK_SIZE) { 132*d62bc4baSyz147064 printf("dl_capability: DL_CAPABILITY_ACK " 133*d62bc4baSyz147064 "protocol err\n"); 134*d62bc4baSyz147064 break; 135*d62bc4baSyz147064 } 136*d62bc4baSyz147064 *mpp = mp; 137*d62bc4baSyz147064 return (0); 138*d62bc4baSyz147064 139*d62bc4baSyz147064 case DL_ERROR_ACK: 140*d62bc4baSyz147064 if (MBLKL(mp) < DL_ERROR_ACK_SIZE) { 141*d62bc4baSyz147064 printf("dl_capability: DL_ERROR_ACK protocol err\n"); 142*d62bc4baSyz147064 break; 143*d62bc4baSyz147064 } 144*d62bc4baSyz147064 if (((dl_error_ack_t *)dl_prim)->dl_error_primitive != 145*d62bc4baSyz147064 DL_CAPABILITY_REQ) { 146*d62bc4baSyz147064 printf("dl_capability: DL_ERROR_ACK rtnd prim %u\n", 147*d62bc4baSyz147064 ((dl_error_ack_t *)dl_prim)->dl_error_primitive); 148*d62bc4baSyz147064 break; 149*d62bc4baSyz147064 } 150*d62bc4baSyz147064 151*d62bc4baSyz147064 *mpp = mp; 152*d62bc4baSyz147064 return (0); 153*d62bc4baSyz147064 154*d62bc4baSyz147064 default: 155*d62bc4baSyz147064 printf("dl_capability: bad ACK header %u\n", 156*d62bc4baSyz147064 dl_prim->dl_primitive); 157*d62bc4baSyz147064 break; 158*d62bc4baSyz147064 } 159*d62bc4baSyz147064 160*d62bc4baSyz147064 freemsg(mp); 161*d62bc4baSyz147064 return (-1); 162*d62bc4baSyz147064 } 163*d62bc4baSyz147064 164*d62bc4baSyz147064 static int 165*d62bc4baSyz147064 softmac_fill_hcksum_ack(void *arg, t_uscalar_t flags) 166*d62bc4baSyz147064 { 167*d62bc4baSyz147064 softmac_t *softmac = (softmac_t *)arg; 168*d62bc4baSyz147064 169*d62bc4baSyz147064 /* 170*d62bc4baSyz147064 * There are two types of acks we process here: 171*d62bc4baSyz147064 * 1. acks in reply to a (first form) generic capability req 172*d62bc4baSyz147064 * (no ENABLE flag set) 173*d62bc4baSyz147064 * 2. acks in reply to a ENABLE capability req. 174*d62bc4baSyz147064 * (ENABLE flag set) 175*d62bc4baSyz147064 * Only the first type should be expected here. 176*d62bc4baSyz147064 */ 177*d62bc4baSyz147064 178*d62bc4baSyz147064 if (flags & HCKSUM_ENABLE) { 179*d62bc4baSyz147064 cmn_err(CE_WARN, "softmac_fill_hcksum_ack: unexpected " 180*d62bc4baSyz147064 "HCKSUM_ENABLE flag in hardware checksum capability"); 181*d62bc4baSyz147064 } else if (flags & (HCKSUM_INET_PARTIAL | HCKSUM_INET_FULL_V4 | 182*d62bc4baSyz147064 HCKSUM_INET_FULL_V6 | HCKSUM_IPHDRCKSUM)) { 183*d62bc4baSyz147064 softmac->smac_capab_flags |= MAC_CAPAB_HCKSUM; 184*d62bc4baSyz147064 softmac->smac_hcksum_txflags = flags; 185*d62bc4baSyz147064 } 186*d62bc4baSyz147064 return (0); 187*d62bc4baSyz147064 } 188*d62bc4baSyz147064 189*d62bc4baSyz147064 static int 190*d62bc4baSyz147064 softmac_fill_zcopy_ack(void *arg, t_uscalar_t flags) 191*d62bc4baSyz147064 { 192*d62bc4baSyz147064 softmac_t *softmac = (softmac_t *)arg; 193*d62bc4baSyz147064 194*d62bc4baSyz147064 ASSERT(flags == DL_CAPAB_VMSAFE_MEM); 195*d62bc4baSyz147064 softmac->smac_capab_flags &= (~MAC_CAPAB_NO_ZCOPY); 196*d62bc4baSyz147064 return (0); 197*d62bc4baSyz147064 } 198*d62bc4baSyz147064 199*d62bc4baSyz147064 static int 200*d62bc4baSyz147064 softmac_fill_mdt_ack(void *arg, dl_capab_mdt_t *mdt) 201*d62bc4baSyz147064 { 202*d62bc4baSyz147064 softmac_t *softmac = (softmac_t *)arg; 203*d62bc4baSyz147064 204*d62bc4baSyz147064 /* 205*d62bc4baSyz147064 * There are two types of acks we process here: 206*d62bc4baSyz147064 * 1. acks in reply to a (first form) generic capability req 207*d62bc4baSyz147064 * (ENABLE flag might be set by some drivers) 208*d62bc4baSyz147064 * 2. acks in reply to a ENABLE capability req. 209*d62bc4baSyz147064 * (ENABLE flag set) 210*d62bc4baSyz147064 */ 211*d62bc4baSyz147064 212*d62bc4baSyz147064 ASSERT(mdt->mdt_version == MDT_VERSION_2); 213*d62bc4baSyz147064 softmac->smac_mdt = B_TRUE; 214*d62bc4baSyz147064 softmac->smac_mdt_capab.mdt_hdr_head = mdt->mdt_hdr_head; 215*d62bc4baSyz147064 softmac->smac_mdt_capab.mdt_hdr_tail = mdt->mdt_hdr_tail; 216*d62bc4baSyz147064 softmac->smac_mdt_capab.mdt_max_pld = mdt->mdt_max_pld; 217*d62bc4baSyz147064 softmac->smac_mdt_capab.mdt_span_limit = mdt->mdt_span_limit; 218*d62bc4baSyz147064 return (0); 219*d62bc4baSyz147064 } 220*d62bc4baSyz147064 221*d62bc4baSyz147064 int 222*d62bc4baSyz147064 softmac_capab_enable(softmac_lower_t *slp) 223*d62bc4baSyz147064 { 224*d62bc4baSyz147064 softmac_t *softmac = slp->sl_softmac; 225*d62bc4baSyz147064 int err; 226*d62bc4baSyz147064 227*d62bc4baSyz147064 if (softmac->smac_no_capability_req) 228*d62bc4baSyz147064 return (0); 229*d62bc4baSyz147064 230*d62bc4baSyz147064 /* 231*d62bc4baSyz147064 * Send DL_CAPABILITY_REQ to get capability advertisement. 232*d62bc4baSyz147064 */ 233*d62bc4baSyz147064 if ((err = softmac_capab_send(slp, B_FALSE)) != 0) 234*d62bc4baSyz147064 return (err); 235*d62bc4baSyz147064 236*d62bc4baSyz147064 /* 237*d62bc4baSyz147064 * Send DL_CAPABILITY_REQ to enable specific capabilities. 238*d62bc4baSyz147064 */ 239*d62bc4baSyz147064 if ((err = softmac_capab_send(slp, B_TRUE)) != 0) 240*d62bc4baSyz147064 return (err); 241*d62bc4baSyz147064 242*d62bc4baSyz147064 return (0); 243*d62bc4baSyz147064 } 244*d62bc4baSyz147064 245*d62bc4baSyz147064 static int 246*d62bc4baSyz147064 softmac_capab_send(softmac_lower_t *slp, boolean_t enable) 247*d62bc4baSyz147064 { 248*d62bc4baSyz147064 softmac_t *softmac; 249*d62bc4baSyz147064 dl_capability_req_t *capb; 250*d62bc4baSyz147064 dl_capability_sub_t *subcapb; 251*d62bc4baSyz147064 mblk_t *reqmp, *ackmp; 252*d62bc4baSyz147064 int err; 253*d62bc4baSyz147064 size_t size = 0; 254*d62bc4baSyz147064 255*d62bc4baSyz147064 softmac = slp->sl_softmac; 256*d62bc4baSyz147064 257*d62bc4baSyz147064 if (enable) { 258*d62bc4baSyz147064 /* No need to enable DL_CAPAB_ZEROCOPY */ 259*d62bc4baSyz147064 if (softmac->smac_capab_flags & MAC_CAPAB_HCKSUM) 260*d62bc4baSyz147064 size += sizeof (dl_capability_sub_t) + 261*d62bc4baSyz147064 sizeof (dl_capab_hcksum_t); 262*d62bc4baSyz147064 263*d62bc4baSyz147064 if (softmac->smac_mdt) { 264*d62bc4baSyz147064 if (!(softmac->smac_mdt_capab.mdt_flags & 265*d62bc4baSyz147064 DL_CAPAB_MDT_ENABLE)) { 266*d62bc4baSyz147064 /* 267*d62bc4baSyz147064 * The MDT capability was not enabled for the 268*d62bc4baSyz147064 * first time, enable it now. 269*d62bc4baSyz147064 */ 270*d62bc4baSyz147064 size += sizeof (dl_capability_sub_t) + 271*d62bc4baSyz147064 sizeof (dl_capab_mdt_t); 272*d62bc4baSyz147064 } 273*d62bc4baSyz147064 } 274*d62bc4baSyz147064 275*d62bc4baSyz147064 if (size == 0) 276*d62bc4baSyz147064 return (0); 277*d62bc4baSyz147064 } 278*d62bc4baSyz147064 279*d62bc4baSyz147064 /* 280*d62bc4baSyz147064 * Create DL_CAPABILITY_REQ message and send it down 281*d62bc4baSyz147064 */ 282*d62bc4baSyz147064 reqmp = allocb(sizeof (dl_capability_req_t) + size, BPRI_MED); 283*d62bc4baSyz147064 if (reqmp == NULL) 284*d62bc4baSyz147064 return (ENOMEM); 285*d62bc4baSyz147064 286*d62bc4baSyz147064 bzero(reqmp->b_rptr, sizeof (dl_capability_req_t) + size); 287*d62bc4baSyz147064 288*d62bc4baSyz147064 DB_TYPE(reqmp) = M_PROTO; 289*d62bc4baSyz147064 reqmp->b_wptr = reqmp->b_rptr + sizeof (dl_capability_req_t) + size; 290*d62bc4baSyz147064 291*d62bc4baSyz147064 capb = (dl_capability_req_t *)reqmp->b_rptr; 292*d62bc4baSyz147064 capb->dl_primitive = DL_CAPABILITY_REQ; 293*d62bc4baSyz147064 294*d62bc4baSyz147064 if (!enable) 295*d62bc4baSyz147064 goto output; 296*d62bc4baSyz147064 297*d62bc4baSyz147064 capb->dl_sub_offset = sizeof (dl_capability_req_t); 298*d62bc4baSyz147064 299*d62bc4baSyz147064 if (softmac->smac_capab_flags & MAC_CAPAB_HCKSUM) { 300*d62bc4baSyz147064 dl_capab_hcksum_t *hck_subcapp; 301*d62bc4baSyz147064 302*d62bc4baSyz147064 size = sizeof (dl_capability_sub_t) + 303*d62bc4baSyz147064 sizeof (dl_capab_hcksum_t); 304*d62bc4baSyz147064 capb->dl_sub_length += size; 305*d62bc4baSyz147064 306*d62bc4baSyz147064 subcapb = (dl_capability_sub_t *)(capb + 1); 307*d62bc4baSyz147064 subcapb->dl_cap = DL_CAPAB_HCKSUM; 308*d62bc4baSyz147064 subcapb->dl_length = sizeof (dl_capab_hcksum_t); 309*d62bc4baSyz147064 hck_subcapp = (dl_capab_hcksum_t *)(subcapb + 1); 310*d62bc4baSyz147064 hck_subcapp->hcksum_version = HCKSUM_VERSION_1; 311*d62bc4baSyz147064 hck_subcapp->hcksum_txflags = 312*d62bc4baSyz147064 softmac->smac_hcksum_txflags | HCKSUM_ENABLE; 313*d62bc4baSyz147064 } 314*d62bc4baSyz147064 315*d62bc4baSyz147064 if (softmac->smac_mdt) { 316*d62bc4baSyz147064 if (!(softmac->smac_mdt_capab.mdt_flags & 317*d62bc4baSyz147064 DL_CAPAB_MDT_ENABLE)) { 318*d62bc4baSyz147064 dl_capab_mdt_t *mdt_subcapp; 319*d62bc4baSyz147064 320*d62bc4baSyz147064 size = sizeof (dl_capability_sub_t) + 321*d62bc4baSyz147064 sizeof (dl_capab_mdt_t); 322*d62bc4baSyz147064 capb->dl_sub_length += size; 323*d62bc4baSyz147064 324*d62bc4baSyz147064 subcapb = (dl_capability_sub_t *) 325*d62bc4baSyz147064 ((uint8_t *)(subcapb + 1) + subcapb->dl_length); 326*d62bc4baSyz147064 327*d62bc4baSyz147064 subcapb->dl_cap = DL_CAPAB_MDT; 328*d62bc4baSyz147064 subcapb->dl_length = sizeof (dl_capab_mdt_t); 329*d62bc4baSyz147064 mdt_subcapp = (dl_capab_mdt_t *)(subcapb + 1); 330*d62bc4baSyz147064 mdt_subcapp->mdt_version = MDT_VERSION_2; 331*d62bc4baSyz147064 mdt_subcapp->mdt_flags = 332*d62bc4baSyz147064 (softmac->smac_mdt_capab.mdt_flags | 333*d62bc4baSyz147064 DL_CAPAB_MDT_ENABLE); 334*d62bc4baSyz147064 mdt_subcapp->mdt_hdr_head = 335*d62bc4baSyz147064 softmac->smac_mdt_capab.mdt_hdr_head; 336*d62bc4baSyz147064 mdt_subcapp->mdt_hdr_tail = 337*d62bc4baSyz147064 softmac->smac_mdt_capab.mdt_hdr_tail; 338*d62bc4baSyz147064 mdt_subcapp->mdt_max_pld = 339*d62bc4baSyz147064 softmac->smac_mdt_capab.mdt_max_pld; 340*d62bc4baSyz147064 mdt_subcapp->mdt_span_limit = 341*d62bc4baSyz147064 softmac->smac_mdt_capab.mdt_span_limit; 342*d62bc4baSyz147064 } 343*d62bc4baSyz147064 } 344*d62bc4baSyz147064 345*d62bc4baSyz147064 output: 346*d62bc4baSyz147064 err = softmac_proto_tx(slp, reqmp, &ackmp); 347*d62bc4baSyz147064 if (err == 0) { 348*d62bc4baSyz147064 if (enable) { 349*d62bc4baSyz147064 err = i_capab_ack(ackmp, NULL, 350*d62bc4baSyz147064 &softmac_enable_capab_ops, softmac); 351*d62bc4baSyz147064 } else { 352*d62bc4baSyz147064 err = i_capab_ack(ackmp, NULL, 353*d62bc4baSyz147064 &softmac_adv_capab_ops, softmac); 354*d62bc4baSyz147064 } 355*d62bc4baSyz147064 } 356*d62bc4baSyz147064 freemsg(ackmp); 357*d62bc4baSyz147064 358*d62bc4baSyz147064 return (err); 359*d62bc4baSyz147064 } 360*d62bc4baSyz147064 361*d62bc4baSyz147064 static int 362*d62bc4baSyz147064 softmac_adv_hcksum_ack(void *arg, t_uscalar_t flags) 363*d62bc4baSyz147064 { 364*d62bc4baSyz147064 softmac_t *softmac = (softmac_t *)arg; 365*d62bc4baSyz147064 366*d62bc4baSyz147064 /* 367*d62bc4baSyz147064 * There are two types of acks we process here: 368*d62bc4baSyz147064 * 1. acks in reply to a (first form) generic capability req 369*d62bc4baSyz147064 * (no ENABLE flag set) 370*d62bc4baSyz147064 * 2. acks in reply to a ENABLE capability req. 371*d62bc4baSyz147064 * (ENABLE flag set) 372*d62bc4baSyz147064 * Only the first type should be expected here. 373*d62bc4baSyz147064 */ 374*d62bc4baSyz147064 375*d62bc4baSyz147064 if (flags & HCKSUM_ENABLE) { 376*d62bc4baSyz147064 cmn_err(CE_WARN, "softmac_adv_hcksum_ack: unexpected " 377*d62bc4baSyz147064 "HCKSUM_ENABLE flag in hardware checksum capability"); 378*d62bc4baSyz147064 return (-1); 379*d62bc4baSyz147064 } else if (flags & (HCKSUM_INET_PARTIAL | HCKSUM_INET_FULL_V4 | 380*d62bc4baSyz147064 HCKSUM_INET_FULL_V6 | HCKSUM_IPHDRCKSUM)) { 381*d62bc4baSyz147064 /* 382*d62bc4baSyz147064 * The acknowledgement should be the same as we got when 383*d62bc4baSyz147064 * the softmac is created. 384*d62bc4baSyz147064 */ 385*d62bc4baSyz147064 if (!(softmac->smac_capab_flags & MAC_CAPAB_HCKSUM)) { 386*d62bc4baSyz147064 ASSERT(B_FALSE); 387*d62bc4baSyz147064 return (-1); 388*d62bc4baSyz147064 } 389*d62bc4baSyz147064 if (softmac->smac_hcksum_txflags != flags) { 390*d62bc4baSyz147064 ASSERT(B_FALSE); 391*d62bc4baSyz147064 return (-1); 392*d62bc4baSyz147064 } 393*d62bc4baSyz147064 } 394*d62bc4baSyz147064 395*d62bc4baSyz147064 return (0); 396*d62bc4baSyz147064 } 397*d62bc4baSyz147064 398*d62bc4baSyz147064 static int 399*d62bc4baSyz147064 softmac_adv_zcopy_ack(void *arg, t_uscalar_t flags) 400*d62bc4baSyz147064 { 401*d62bc4baSyz147064 softmac_t *softmac = (softmac_t *)arg; 402*d62bc4baSyz147064 403*d62bc4baSyz147064 /* 404*d62bc4baSyz147064 * The acknowledgement should be the same as we got when 405*d62bc4baSyz147064 * the softmac is created. 406*d62bc4baSyz147064 */ 407*d62bc4baSyz147064 ASSERT(flags == DL_CAPAB_VMSAFE_MEM); 408*d62bc4baSyz147064 if (softmac->smac_capab_flags & MAC_CAPAB_NO_ZCOPY) { 409*d62bc4baSyz147064 ASSERT(B_FALSE); 410*d62bc4baSyz147064 return (-1); 411*d62bc4baSyz147064 } 412*d62bc4baSyz147064 413*d62bc4baSyz147064 return (0); 414*d62bc4baSyz147064 } 415*d62bc4baSyz147064 416*d62bc4baSyz147064 static int 417*d62bc4baSyz147064 softmac_adv_mdt_ack(void *arg, dl_capab_mdt_t *mdt) 418*d62bc4baSyz147064 { 419*d62bc4baSyz147064 softmac_t *softmac = (softmac_t *)arg; 420*d62bc4baSyz147064 421*d62bc4baSyz147064 /* 422*d62bc4baSyz147064 * The acknowledgement should be the same as we got when 423*d62bc4baSyz147064 * the softmac is created. 424*d62bc4baSyz147064 */ 425*d62bc4baSyz147064 if (!softmac->smac_mdt) { 426*d62bc4baSyz147064 ASSERT(B_FALSE); 427*d62bc4baSyz147064 return (-1); 428*d62bc4baSyz147064 } 429*d62bc4baSyz147064 430*d62bc4baSyz147064 if ((softmac->smac_mdt_capab.mdt_hdr_head != mdt->mdt_hdr_head) || 431*d62bc4baSyz147064 (softmac->smac_mdt_capab.mdt_hdr_tail != mdt->mdt_hdr_tail) || 432*d62bc4baSyz147064 (softmac->smac_mdt_capab.mdt_max_pld != mdt->mdt_max_pld) || 433*d62bc4baSyz147064 (softmac->smac_mdt_capab.mdt_span_limit != mdt->mdt_span_limit)) { 434*d62bc4baSyz147064 ASSERT(B_FALSE); 435*d62bc4baSyz147064 return (-1); 436*d62bc4baSyz147064 } 437*d62bc4baSyz147064 /* 438*d62bc4baSyz147064 * We need the mdt_flags field to know whether an additional 439*d62bc4baSyz147064 * DL_CAPAB_MDT_ENABLE is necessary. 440*d62bc4baSyz147064 */ 441*d62bc4baSyz147064 softmac->smac_mdt_capab.mdt_flags = mdt->mdt_flags; 442*d62bc4baSyz147064 return (0); 443*d62bc4baSyz147064 } 444*d62bc4baSyz147064 445*d62bc4baSyz147064 static int 446*d62bc4baSyz147064 softmac_enable_hcksum_ack(void *arg, t_uscalar_t flags) 447*d62bc4baSyz147064 { 448*d62bc4baSyz147064 softmac_t *softmac = (softmac_t *)arg; 449*d62bc4baSyz147064 450*d62bc4baSyz147064 /* 451*d62bc4baSyz147064 * There are two types of acks we process here: 452*d62bc4baSyz147064 * 1. acks in reply to a (first form) generic capability req 453*d62bc4baSyz147064 * (no ENABLE flag set) 454*d62bc4baSyz147064 * 2. acks in reply to a ENABLE capability req. 455*d62bc4baSyz147064 * (ENABLE flag set) 456*d62bc4baSyz147064 * Only the second type should be expected here. 457*d62bc4baSyz147064 */ 458*d62bc4baSyz147064 459*d62bc4baSyz147064 if (flags & HCKSUM_ENABLE) { 460*d62bc4baSyz147064 if ((flags & ~HCKSUM_ENABLE) != softmac->smac_hcksum_txflags) { 461*d62bc4baSyz147064 cmn_err(CE_WARN, "softmac_enable_hcksum_ack: unexpected" 462*d62bc4baSyz147064 " hardware capability flag value 0x%x", flags); 463*d62bc4baSyz147064 return (-1); 464*d62bc4baSyz147064 } 465*d62bc4baSyz147064 } else { 466*d62bc4baSyz147064 cmn_err(CE_WARN, "softmac_enable_hcksum_ack: " 467*d62bc4baSyz147064 "hardware checksum flag HCKSUM_ENABLE is not set"); 468*d62bc4baSyz147064 return (-1); 469*d62bc4baSyz147064 } 470*d62bc4baSyz147064 471*d62bc4baSyz147064 return (0); 472*d62bc4baSyz147064 } 473*d62bc4baSyz147064 474*d62bc4baSyz147064 static int 475*d62bc4baSyz147064 softmac_enable_mdt_ack(void *arg, dl_capab_mdt_t *mdt) 476*d62bc4baSyz147064 { 477*d62bc4baSyz147064 softmac_t *softmac = (softmac_t *)arg; 478*d62bc4baSyz147064 479*d62bc4baSyz147064 /* 480*d62bc4baSyz147064 * There are two types of acks we process here: 481*d62bc4baSyz147064 * 1. acks in reply to a (first form) generic capability req 482*d62bc4baSyz147064 * (no ENABLE flag set) 483*d62bc4baSyz147064 * 2. acks in reply to a ENABLE capability req. 484*d62bc4baSyz147064 * (ENABLE flag set) 485*d62bc4baSyz147064 * Only the second type should be expected here. 486*d62bc4baSyz147064 */ 487*d62bc4baSyz147064 488*d62bc4baSyz147064 if (mdt->mdt_flags & DL_CAPAB_MDT_ENABLE) { 489*d62bc4baSyz147064 if ((softmac->smac_mdt_capab.mdt_hdr_head != 490*d62bc4baSyz147064 mdt->mdt_hdr_head) || 491*d62bc4baSyz147064 (softmac->smac_mdt_capab.mdt_hdr_tail != 492*d62bc4baSyz147064 mdt->mdt_hdr_tail) || 493*d62bc4baSyz147064 (softmac->smac_mdt_capab.mdt_max_pld != 494*d62bc4baSyz147064 mdt->mdt_max_pld) || 495*d62bc4baSyz147064 (softmac->smac_mdt_capab.mdt_span_limit != 496*d62bc4baSyz147064 mdt->mdt_span_limit)) { 497*d62bc4baSyz147064 cmn_err(CE_WARN, "softmac_enable_mdt_ack: " 498*d62bc4baSyz147064 "unexpected MDT capability value"); 499*d62bc4baSyz147064 return (-1); 500*d62bc4baSyz147064 } 501*d62bc4baSyz147064 softmac->smac_mdt_capab.mdt_flags = mdt->mdt_flags; 502*d62bc4baSyz147064 } else { 503*d62bc4baSyz147064 cmn_err(CE_WARN, "softmac_enable_mdt_ack: " 504*d62bc4baSyz147064 "MDT flag DL_CAPAB_MDT_ENABLE is not set"); 505*d62bc4baSyz147064 return (-1); 506*d62bc4baSyz147064 } 507*d62bc4baSyz147064 508*d62bc4baSyz147064 return (0); 509*d62bc4baSyz147064 } 510*d62bc4baSyz147064 511*d62bc4baSyz147064 static int 512*d62bc4baSyz147064 i_capab_ack(mblk_t *mp, queue_t *q, softmac_capab_ops_t *op, void *arg) 513*d62bc4baSyz147064 { 514*d62bc4baSyz147064 union DL_primitives *prim; 515*d62bc4baSyz147064 dl_capability_ack_t *cap; 516*d62bc4baSyz147064 dl_capability_sub_t *sub, *end; 517*d62bc4baSyz147064 int err = 0; 518*d62bc4baSyz147064 519*d62bc4baSyz147064 prim = (union DL_primitives *)mp->b_rptr; 520*d62bc4baSyz147064 ASSERT(prim->dl_primitive == DL_CAPABILITY_ACK); 521*d62bc4baSyz147064 522*d62bc4baSyz147064 cap = (dl_capability_ack_t *)prim; 523*d62bc4baSyz147064 if (cap->dl_sub_length == 0) 524*d62bc4baSyz147064 goto exit; 525*d62bc4baSyz147064 526*d62bc4baSyz147064 /* Is dl_sub_length correct? */ 527*d62bc4baSyz147064 if ((sizeof (*cap) + cap->dl_sub_length) > MBLKL(mp)) { 528*d62bc4baSyz147064 err = EINVAL; 529*d62bc4baSyz147064 goto exit; 530*d62bc4baSyz147064 } 531*d62bc4baSyz147064 532*d62bc4baSyz147064 sub = (dl_capability_sub_t *)((caddr_t)cap + cap->dl_sub_offset); 533*d62bc4baSyz147064 end = (dl_capability_sub_t *)((caddr_t)cap + cap->dl_sub_length 534*d62bc4baSyz147064 - sizeof (*sub)); 535*d62bc4baSyz147064 for (; (sub <= end) && (err == 0); ) { 536*d62bc4baSyz147064 switch (sub->dl_cap) { 537*d62bc4baSyz147064 case DL_CAPAB_ID_WRAPPER: 538*d62bc4baSyz147064 err = i_capab_id_ack(mp, sub, q, op, arg); 539*d62bc4baSyz147064 break; 540*d62bc4baSyz147064 default: 541*d62bc4baSyz147064 err = i_capab_sub_ack(mp, sub, q, op, arg); 542*d62bc4baSyz147064 break; 543*d62bc4baSyz147064 } 544*d62bc4baSyz147064 sub = (dl_capability_sub_t *)((caddr_t)sub + sizeof (*sub) 545*d62bc4baSyz147064 + sub->dl_length); 546*d62bc4baSyz147064 } 547*d62bc4baSyz147064 548*d62bc4baSyz147064 exit: 549*d62bc4baSyz147064 return (err); 550*d62bc4baSyz147064 } 551*d62bc4baSyz147064 552*d62bc4baSyz147064 static int 553*d62bc4baSyz147064 i_capab_id_ack(mblk_t *mp, dl_capability_sub_t *outers, 554*d62bc4baSyz147064 queue_t *q, softmac_capab_ops_t *op, void *arg) 555*d62bc4baSyz147064 { 556*d62bc4baSyz147064 dl_capab_id_t *capab_id; 557*d62bc4baSyz147064 dl_capability_sub_t *inners; 558*d62bc4baSyz147064 caddr_t capend; 559*d62bc4baSyz147064 int err = EINVAL; 560*d62bc4baSyz147064 561*d62bc4baSyz147064 ASSERT(outers->dl_cap == DL_CAPAB_ID_WRAPPER); 562*d62bc4baSyz147064 563*d62bc4baSyz147064 capend = (caddr_t)(outers + 1) + outers->dl_length; 564*d62bc4baSyz147064 if (capend > (caddr_t)mp->b_wptr) { 565*d62bc4baSyz147064 cmn_err(CE_WARN, "i_capab_id_ack: malformed " 566*d62bc4baSyz147064 "sub-capability too long"); 567*d62bc4baSyz147064 return (err); 568*d62bc4baSyz147064 } 569*d62bc4baSyz147064 570*d62bc4baSyz147064 capab_id = (dl_capab_id_t *)(outers + 1); 571*d62bc4baSyz147064 572*d62bc4baSyz147064 if (outers->dl_length < sizeof (*capab_id) || 573*d62bc4baSyz147064 (inners = &capab_id->id_subcap, 574*d62bc4baSyz147064 inners->dl_length > (outers->dl_length - sizeof (*inners)))) { 575*d62bc4baSyz147064 cmn_err(CE_WARN, "i_capab_id_ack: malformed " 576*d62bc4baSyz147064 "encapsulated capab type %d too long", 577*d62bc4baSyz147064 inners->dl_cap); 578*d62bc4baSyz147064 return (err); 579*d62bc4baSyz147064 } 580*d62bc4baSyz147064 581*d62bc4baSyz147064 if ((q != NULL) && (!dlcapabcheckqid(&capab_id->id_mid, q))) { 582*d62bc4baSyz147064 cmn_err(CE_WARN, "i_capab_id_ack: pass-thru module(s) " 583*d62bc4baSyz147064 "detected, discarding capab type %d", inners->dl_cap); 584*d62bc4baSyz147064 return (err); 585*d62bc4baSyz147064 } 586*d62bc4baSyz147064 587*d62bc4baSyz147064 /* Process the encapsulated sub-capability */ 588*d62bc4baSyz147064 return (i_capab_sub_ack(mp, inners, q, op, arg)); 589*d62bc4baSyz147064 } 590*d62bc4baSyz147064 591*d62bc4baSyz147064 static int 592*d62bc4baSyz147064 i_capab_sub_ack(mblk_t *mp, dl_capability_sub_t *sub, queue_t *q, 593*d62bc4baSyz147064 softmac_capab_ops_t *op, void *arg) 594*d62bc4baSyz147064 { 595*d62bc4baSyz147064 caddr_t capend; 596*d62bc4baSyz147064 dl_capab_hcksum_t *hcksum; 597*d62bc4baSyz147064 dl_capab_zerocopy_t *zcopy; 598*d62bc4baSyz147064 dl_capab_mdt_t *mdt; 599*d62bc4baSyz147064 int err = 0; 600*d62bc4baSyz147064 601*d62bc4baSyz147064 capend = (caddr_t)(sub + 1) + sub->dl_length; 602*d62bc4baSyz147064 if (capend > (caddr_t)mp->b_wptr) { 603*d62bc4baSyz147064 cmn_err(CE_WARN, "i_capab_sub_ack: " 604*d62bc4baSyz147064 "malformed sub-capability too long"); 605*d62bc4baSyz147064 return (EINVAL); 606*d62bc4baSyz147064 } 607*d62bc4baSyz147064 608*d62bc4baSyz147064 switch (sub->dl_cap) { 609*d62bc4baSyz147064 case DL_CAPAB_HCKSUM: 610*d62bc4baSyz147064 hcksum = (dl_capab_hcksum_t *)(sub + 1); 611*d62bc4baSyz147064 err = i_capab_hcksum_ack(hcksum, q, op, arg); 612*d62bc4baSyz147064 break; 613*d62bc4baSyz147064 614*d62bc4baSyz147064 case DL_CAPAB_ZEROCOPY: 615*d62bc4baSyz147064 zcopy = (dl_capab_zerocopy_t *)(sub + 1); 616*d62bc4baSyz147064 err = i_capab_zcopy_ack(zcopy, q, op, arg); 617*d62bc4baSyz147064 break; 618*d62bc4baSyz147064 619*d62bc4baSyz147064 case DL_CAPAB_MDT: 620*d62bc4baSyz147064 mdt = (dl_capab_mdt_t *)(sub + 1); 621*d62bc4baSyz147064 err = i_capab_mdt_ack(mdt, q, op, arg); 622*d62bc4baSyz147064 break; 623*d62bc4baSyz147064 624*d62bc4baSyz147064 default: 625*d62bc4baSyz147064 cmn_err(CE_WARN, "i_capab_sub_ack: unknown capab type %d", 626*d62bc4baSyz147064 sub->dl_cap); 627*d62bc4baSyz147064 err = EINVAL; 628*d62bc4baSyz147064 } 629*d62bc4baSyz147064 630*d62bc4baSyz147064 return (err); 631*d62bc4baSyz147064 } 632*d62bc4baSyz147064 633*d62bc4baSyz147064 static int 634*d62bc4baSyz147064 i_capab_hcksum_ack(dl_capab_hcksum_t *hcksum, queue_t *q, 635*d62bc4baSyz147064 softmac_capab_ops_t *op, void *arg) 636*d62bc4baSyz147064 { 637*d62bc4baSyz147064 t_uscalar_t flags; 638*d62bc4baSyz147064 int err = 0; 639*d62bc4baSyz147064 640*d62bc4baSyz147064 if ((err = i_capab_hcksum_verify(hcksum, q)) != 0) 641*d62bc4baSyz147064 return (err); 642*d62bc4baSyz147064 643*d62bc4baSyz147064 flags = hcksum->hcksum_txflags; 644*d62bc4baSyz147064 645*d62bc4baSyz147064 if (!(flags & (HCKSUM_INET_PARTIAL | HCKSUM_INET_FULL_V4 | 646*d62bc4baSyz147064 HCKSUM_INET_FULL_V6 | HCKSUM_IPHDRCKSUM | HCKSUM_ENABLE))) { 647*d62bc4baSyz147064 cmn_err(CE_WARN, "i_capab_hcksum_ack: invalid " 648*d62bc4baSyz147064 "hardware checksum capability flags 0x%x", flags); 649*d62bc4baSyz147064 return (EINVAL); 650*d62bc4baSyz147064 } 651*d62bc4baSyz147064 652*d62bc4baSyz147064 if (op->sc_hcksum_ack) 653*d62bc4baSyz147064 return (op->sc_hcksum_ack(arg, flags)); 654*d62bc4baSyz147064 else { 655*d62bc4baSyz147064 cmn_err(CE_WARN, "i_capab_hcksum_ack: unexpected hardware " 656*d62bc4baSyz147064 "checksum acknowledgement"); 657*d62bc4baSyz147064 return (EINVAL); 658*d62bc4baSyz147064 } 659*d62bc4baSyz147064 } 660*d62bc4baSyz147064 661*d62bc4baSyz147064 static int 662*d62bc4baSyz147064 i_capab_zcopy_ack(dl_capab_zerocopy_t *zcopy, queue_t *q, 663*d62bc4baSyz147064 softmac_capab_ops_t *op, void *arg) 664*d62bc4baSyz147064 { 665*d62bc4baSyz147064 t_uscalar_t flags; 666*d62bc4baSyz147064 int err = 0; 667*d62bc4baSyz147064 668*d62bc4baSyz147064 if ((err = i_capab_zcopy_verify(zcopy, q)) != 0) 669*d62bc4baSyz147064 return (err); 670*d62bc4baSyz147064 671*d62bc4baSyz147064 flags = zcopy->zerocopy_flags; 672*d62bc4baSyz147064 if (!(flags & DL_CAPAB_VMSAFE_MEM)) { 673*d62bc4baSyz147064 cmn_err(CE_WARN, "i_capab_zcopy_ack: invalid zcopy capability " 674*d62bc4baSyz147064 "flags 0x%x", flags); 675*d62bc4baSyz147064 return (EINVAL); 676*d62bc4baSyz147064 } 677*d62bc4baSyz147064 if (op->sc_zcopy_ack) 678*d62bc4baSyz147064 return (op->sc_zcopy_ack(arg, flags)); 679*d62bc4baSyz147064 else { 680*d62bc4baSyz147064 cmn_err(CE_WARN, "i_capab_zcopy_ack: unexpected zcopy " 681*d62bc4baSyz147064 "acknowledgement"); 682*d62bc4baSyz147064 return (EINVAL); 683*d62bc4baSyz147064 } 684*d62bc4baSyz147064 } 685*d62bc4baSyz147064 686*d62bc4baSyz147064 static int 687*d62bc4baSyz147064 i_capab_mdt_ack(dl_capab_mdt_t *mdt, queue_t *q, 688*d62bc4baSyz147064 softmac_capab_ops_t *op, void *arg) 689*d62bc4baSyz147064 { 690*d62bc4baSyz147064 int err; 691*d62bc4baSyz147064 692*d62bc4baSyz147064 if ((err = i_capab_mdt_verify(mdt, q)) != 0) 693*d62bc4baSyz147064 return (err); 694*d62bc4baSyz147064 695*d62bc4baSyz147064 if (op->sc_mdt_ack) 696*d62bc4baSyz147064 return (op->sc_mdt_ack(arg, mdt)); 697*d62bc4baSyz147064 else { 698*d62bc4baSyz147064 cmn_err(CE_WARN, "i_capab_mdt_ack: unexpected MDT " 699*d62bc4baSyz147064 "acknowledgement"); 700*d62bc4baSyz147064 return (EINVAL); 701*d62bc4baSyz147064 } 702*d62bc4baSyz147064 } 703*d62bc4baSyz147064 704*d62bc4baSyz147064 static int 705*d62bc4baSyz147064 i_capab_hcksum_verify(dl_capab_hcksum_t *hcksum, queue_t *q) 706*d62bc4baSyz147064 { 707*d62bc4baSyz147064 if (hcksum->hcksum_version != HCKSUM_VERSION_1) { 708*d62bc4baSyz147064 cmn_err(CE_WARN, "i_capab_hcksum_verify: " 709*d62bc4baSyz147064 "unsupported hardware checksum capability (version %d, " 710*d62bc4baSyz147064 "expected %d)", hcksum->hcksum_version, HCKSUM_VERSION_1); 711*d62bc4baSyz147064 return (-1); 712*d62bc4baSyz147064 } 713*d62bc4baSyz147064 714*d62bc4baSyz147064 if ((q != NULL) && !dlcapabcheckqid(&hcksum->hcksum_mid, q)) { 715*d62bc4baSyz147064 cmn_err(CE_WARN, "i_capab_hcksum_verify: unexpected pass-thru " 716*d62bc4baSyz147064 "module detected; hardware checksum capability discarded"); 717*d62bc4baSyz147064 return (-1); 718*d62bc4baSyz147064 } 719*d62bc4baSyz147064 return (0); 720*d62bc4baSyz147064 } 721*d62bc4baSyz147064 722*d62bc4baSyz147064 static int 723*d62bc4baSyz147064 i_capab_zcopy_verify(dl_capab_zerocopy_t *zcopy, queue_t *q) 724*d62bc4baSyz147064 { 725*d62bc4baSyz147064 if (zcopy->zerocopy_version != ZEROCOPY_VERSION_1) { 726*d62bc4baSyz147064 cmn_err(CE_WARN, "i_capab_zcopy_verify: unsupported zcopy " 727*d62bc4baSyz147064 "capability (version %d, expected %d)", 728*d62bc4baSyz147064 zcopy->zerocopy_version, ZEROCOPY_VERSION_1); 729*d62bc4baSyz147064 return (-1); 730*d62bc4baSyz147064 } 731*d62bc4baSyz147064 732*d62bc4baSyz147064 if ((q != NULL) && !dlcapabcheckqid(&zcopy->zerocopy_mid, q)) { 733*d62bc4baSyz147064 cmn_err(CE_WARN, "i_capab_zcopy_verify: unexpected pass-thru " 734*d62bc4baSyz147064 "module detected; zcopy checksum capability discarded"); 735*d62bc4baSyz147064 return (-1); 736*d62bc4baSyz147064 } 737*d62bc4baSyz147064 return (0); 738*d62bc4baSyz147064 } 739*d62bc4baSyz147064 740*d62bc4baSyz147064 static int 741*d62bc4baSyz147064 i_capab_mdt_verify(dl_capab_mdt_t *mdt, queue_t *q) 742*d62bc4baSyz147064 { 743*d62bc4baSyz147064 if (mdt->mdt_version != MDT_VERSION_2) { 744*d62bc4baSyz147064 cmn_err(CE_WARN, "i_capab_mdt_verify: unsupported MDT " 745*d62bc4baSyz147064 "capability (version %d, expected %d)", 746*d62bc4baSyz147064 mdt->mdt_version, MDT_VERSION_2); 747*d62bc4baSyz147064 return (-1); 748*d62bc4baSyz147064 } 749*d62bc4baSyz147064 750*d62bc4baSyz147064 if ((q != NULL) && !dlcapabcheckqid(&mdt->mdt_mid, q)) { 751*d62bc4baSyz147064 cmn_err(CE_WARN, "i_capab_mdt_verify: unexpected pass-thru " 752*d62bc4baSyz147064 "module detected; MDT capability discarded"); 753*d62bc4baSyz147064 return (-1); 754*d62bc4baSyz147064 } 755*d62bc4baSyz147064 return (0); 756*d62bc4baSyz147064 } 757