1*d62bc4baSyz /*
2*d62bc4baSyz  * CDDL HEADER START
3*d62bc4baSyz  *
4*d62bc4baSyz  * The contents of this file are subject to the terms of the
5*d62bc4baSyz  * Common Development and Distribution License (the "License").
6*d62bc4baSyz  * You may not use this file except in compliance with the License.
7*d62bc4baSyz  *
8*d62bc4baSyz  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*d62bc4baSyz  * or http://www.opensolaris.org/os/licensing.
10*d62bc4baSyz  * See the License for the specific language governing permissions
11*d62bc4baSyz  * and limitations under the License.
12*d62bc4baSyz  *
13*d62bc4baSyz  * When distributing Covered Code, include this CDDL HEADER in each
14*d62bc4baSyz  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*d62bc4baSyz  * If applicable, add the following below this CDDL HEADER, with the
16*d62bc4baSyz  * fields enclosed by brackets "[]" replaced with your own identifying
17*d62bc4baSyz  * information: Portions Copyright [yyyy] [name of copyright owner]
18*d62bc4baSyz  *
19*d62bc4baSyz  * CDDL HEADER END
20*d62bc4baSyz  */
21*d62bc4baSyz /*
22*d62bc4baSyz  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*d62bc4baSyz  * Use is subject to license terms.
24*d62bc4baSyz  */
26*d62bc4baSyz #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*d62bc4baSyz #include <sys/types.h>
29*d62bc4baSyz #include <sys/mac.h>
30*d62bc4baSyz #include <sys/softmac_impl.h>
32*d62bc4baSyz typedef struct softmac_capab_ops {
33*d62bc4baSyz 	int	(*sc_hcksum_ack)(void *, t_uscalar_t);
34*d62bc4baSyz 	int	(*sc_zcopy_ack)(void *, t_uscalar_t);
35*d62bc4baSyz 	int	(*sc_mdt_ack)(void *, dl_capab_mdt_t *);
36*d62bc4baSyz } softmac_capab_ops_t;
38*d62bc4baSyz static int	dl_capab(ldi_handle_t, mblk_t **);
39*d62bc4baSyz static int	softmac_fill_hcksum_ack(void *, t_uscalar_t);
40*d62bc4baSyz static int	softmac_fill_zcopy_ack(void *, t_uscalar_t);
41*d62bc4baSyz static int	softmac_fill_mdt_ack(void *, dl_capab_mdt_t *);
42*d62bc4baSyz static int	softmac_adv_hcksum_ack(void *, t_uscalar_t);
43*d62bc4baSyz static int	softmac_adv_zcopy_ack(void *, t_uscalar_t);
44*d62bc4baSyz static int	softmac_adv_mdt_ack(void *, dl_capab_mdt_t *);
45*d62bc4baSyz static int	softmac_enable_hcksum_ack(void *, t_uscalar_t);
46*d62bc4baSyz static int	softmac_enable_mdt_ack(void *, dl_capab_mdt_t *);
47*d62bc4baSyz static int	softmac_capab_send(softmac_lower_t *, boolean_t);
48*d62bc4baSyz static int	i_capab_ack(mblk_t *, queue_t *, softmac_capab_ops_t *, void *);
49*d62bc4baSyz static int	i_capab_id_ack(mblk_t *, dl_capability_sub_t *, queue_t *,
50*d62bc4baSyz     softmac_capab_ops_t *, void *);
51*d62bc4baSyz static int	i_capab_sub_ack(mblk_t *, dl_capability_sub_t *, queue_t *,
52*d62bc4baSyz     softmac_capab_ops_t *, void *);
53*d62bc4baSyz static int	i_capab_hcksum_ack(dl_capab_hcksum_t *, queue_t *,
54*d62bc4baSyz     softmac_capab_ops_t *, void *);
55*d62bc4baSyz static int	i_capab_zcopy_ack(dl_capab_zerocopy_t *, queue_t *,
56*d62bc4baSyz     softmac_capab_ops_t *, void *);
57*d62bc4baSyz static int	i_capab_mdt_ack(dl_capab_mdt_t *, queue_t *,
58*d62bc4baSyz     softmac_capab_ops_t *, void *);
59*d62bc4baSyz static int	i_capab_hcksum_verify(dl_capab_hcksum_t *, queue_t *);
60*d62bc4baSyz static int	i_capab_zcopy_verify(dl_capab_zerocopy_t *, queue_t *);
61*d62bc4baSyz static int	i_capab_mdt_verify(dl_capab_mdt_t *, queue_t *);
63*d62bc4baSyz static softmac_capab_ops_t softmac_fill_capab_ops =
64*d62bc4baSyz {
65*d62bc4baSyz 	softmac_fill_hcksum_ack,
66*d62bc4baSyz 	softmac_fill_zcopy_ack,
67*d62bc4baSyz 	softmac_fill_mdt_ack,
68*d62bc4baSyz };
70*d62bc4baSyz static softmac_capab_ops_t softmac_adv_capab_ops =
71*d62bc4baSyz {
72*d62bc4baSyz 	softmac_adv_hcksum_ack,
73*d62bc4baSyz 	softmac_adv_zcopy_ack,
74*d62bc4baSyz 	softmac_adv_mdt_ack
75*d62bc4baSyz };
77*d62bc4baSyz static softmac_capab_ops_t softmac_enable_capab_ops =
78*d62bc4baSyz {
79*d62bc4baSyz 	softmac_enable_hcksum_ack,
80*d62bc4baSyz 	NULL,
81*d62bc4baSyz 	softmac_enable_mdt_ack
82*d62bc4baSyz };
84*d62bc4baSyz int
softmac_fill_capab(ldi_handle_t lh,softmac_t * softmac)85*d62bc4baSyz softmac_fill_capab(ldi_handle_t lh, softmac_t *softmac)
86*d62bc4baSyz {
87*d62bc4baSyz 	mblk_t			*mp = NULL;
88*d62bc4baSyz 	union DL_primitives	*prim;
89*d62bc4baSyz 	int			err = 0;
91*d62bc4baSyz 	if ((err = dl_capab(lh, &mp)) != 0)
92*d62bc4baSyz 		goto exit;
94*d62bc4baSyz 	prim = (union DL_primitives *)mp->b_rptr;
95*d62bc4baSyz 	if (prim->dl_primitive == DL_ERROR_ACK) {
96*d62bc4baSyz 		err = -1;
97*d62bc4baSyz 		goto exit;
98*d62bc4baSyz 	}
100*d62bc4baSyz 	err = i_capab_ack(mp, NULL, &softmac_fill_capab_ops, softmac);
102*d62bc4baSyz exit:
103*d62bc4baSyz 	freemsg(mp);
104*d62bc4baSyz 	return (err);
105*d62bc4baSyz }
107*d62bc4baSyz static int
dl_capab(ldi_handle_t lh,mblk_t ** mpp)108*d62bc4baSyz dl_capab(ldi_handle_t lh, mblk_t **mpp)
109*d62bc4baSyz {
110*d62bc4baSyz 	dl_capability_req_t	*capb;
111*d62bc4baSyz 	union DL_primitives	*dl_prim;
112*d62bc4baSyz 	mblk_t			*mp;
113*d62bc4baSyz 	int			err;
115*d62bc4baSyz 	if ((mp = allocb(sizeof (dl_capability_req_t), BPRI_MED)) == NULL)
116*d62bc4baSyz 		return (ENOMEM);
117*d62bc4baSyz 	mp->b_datap->db_type = M_PROTO;
119*d62bc4baSyz 	capb = (dl_capability_req_t *)mp->b_wptr;
120*d62bc4baSyz 	mp->b_wptr += sizeof (dl_capability_req_t);
121*d62bc4baSyz 	bzero(mp->b_rptr, sizeof (dl_capability_req_t));
122*d62bc4baSyz 	capb->dl_primitive = DL_CAPABILITY_REQ;
124*d62bc4baSyz 	(void) ldi_putmsg(lh, mp);
125*d62bc4baSyz 	if ((err = ldi_getmsg(lh, &mp, (timestruc_t *)NULL)) != 0)
126*d62bc4baSyz 		return (err);
128*d62bc4baSyz 	dl_prim = (union DL_primitives *)mp->b_rptr;
129*d62bc4baSyz 	switch (dl_prim->dl_primitive) {
130*d62bc4baSyz 	case DL_CAPABILITY_ACK:
131*d62bc4baSyz 		if (MBLKL(mp) < DL_CAPABILITY_ACK_SIZE) {
132*d62bc4baSyz 			printf("dl_capability: DL_CAPABILITY_ACK "
133*d62bc4baSyz 			    "protocol err\n");
134*d62bc4baSyz 			break;
135*d62bc4baSyz 		}
136*d62bc4baSyz 		*mpp = mp;
137*d62bc4baSyz 		return (0);
139*d62bc4baSyz 	case DL_ERROR_ACK:
140*d62bc4baSyz 		if (MBLKL(mp) < DL_ERROR_ACK_SIZE) {
141*d62bc4baSyz 			printf("dl_capability: DL_ERROR_ACK protocol err\n");
142*d62bc4baSyz 			break;
143*d62bc4baSyz 		}
144*d62bc4baSyz 		if (((dl_error_ack_t *)dl_prim)->dl_error_primitive !=
145*d62bc4baSyz 		    DL_CAPABILITY_REQ) {
146*d62bc4baSyz 			printf("dl_capability: DL_ERROR_ACK rtnd prim %u\n",
147*d62bc4baSyz 			    ((dl_error_ack_t *)dl_prim)->dl_error_primitive);
148*d62bc4baSyz 			break;
149*d62bc4baSyz 		}
151*d62bc4baSyz 		*mpp = mp;
152*d62bc4baSyz 		return (0);
154*d62bc4baSyz 	default:
155*d62bc4baSyz 		printf("dl_capability: bad ACK header %u\n",
156*d62bc4baSyz 		    dl_prim->dl_primitive);
157*d62bc4baSyz 		break;
158*d62bc4baSyz 	}
160*d62bc4baSyz 	freemsg(mp);
161*d62bc4baSyz 	return (-1);
162*d62bc4baSyz }
164*d62bc4baSyz static int
softmac_fill_hcksum_ack(void * arg,t_uscalar_t flags)165*d62bc4baSyz softmac_fill_hcksum_ack(void *arg, t_uscalar_t flags)
166*d62bc4baSyz {
167*d62bc4baSyz 	softmac_t	*softmac = (softmac_t *)arg;
169*d62bc4baSyz 	/*
170*d62bc4baSyz 	 * There are two types of acks we process here:
171*d62bc4baSyz 	 * 1. acks in reply to a (first form) generic capability req
172*d62bc4baSyz 	 *    (no ENABLE flag set)
173*d62bc4baSyz 	 * 2. acks in reply to a ENABLE capability req.
174*d62bc4baSyz 	 *    (ENABLE flag set)
175*d62bc4baSyz 	 * Only the first type should be expected here.
176*d62bc4baSyz 	 */
178*d62bc4baSyz 	if (flags & HCKSUM_ENABLE) {
179*d62bc4baSyz 		cmn_err(CE_WARN, "softmac_fill_hcksum_ack: unexpected "
180*d62bc4baSyz 		    "HCKSUM_ENABLE flag in hardware checksum capability");
181*d62bc4baSyz 	} else if (flags & (HCKSUM_INET_PARTIAL | HCKSUM_INET_FULL_V4 |
182*d62bc4baSyz 	    HCKSUM_INET_FULL_V6 | HCKSUM_IPHDRCKSUM)) {
183*d62bc4baSyz 		softmac->smac_capab_flags |= MAC_CAPAB_HCKSUM;
184*d62bc4baSyz 		softmac->smac_hcksum_txflags = flags;
185*d62bc4baSyz 	}
186*d62bc4baSyz 	return (0);
187*d62bc4baSyz }
189*d62bc4baSyz static int
softmac_fill_zcopy_ack(void * arg,t_uscalar_t flags)190*d62bc4baSyz softmac_fill_zcopy_ack(void *arg, t_uscalar_t flags)
191*d62bc4baSyz {
192*d62bc4baSyz 	softmac_t	*softmac = (softmac_t *)arg;
194*d62bc4baSyz 	ASSERT(flags == DL_CAPAB_VMSAFE_MEM);
195*d62bc4baSyz 	softmac->smac_capab_flags &= (~MAC_CAPAB_NO_ZCOPY);
196*d62bc4baSyz 	return (0);
197*d62bc4baSyz }