1d62bc4baSyz147064 /* 2d62bc4baSyz147064 * CDDL HEADER START 3d62bc4baSyz147064 * 4d62bc4baSyz147064 * The contents of this file are subject to the terms of the 5d62bc4baSyz147064 * Common Development and Distribution License (the "License"). 6d62bc4baSyz147064 * You may not use this file except in compliance with the License. 7d62bc4baSyz147064 * 8d62bc4baSyz147064 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9d62bc4baSyz147064 * or http://www.opensolaris.org/os/licensing. 10d62bc4baSyz147064 * See the License for the specific language governing permissions 11d62bc4baSyz147064 * and limitations under the License. 12d62bc4baSyz147064 * 13d62bc4baSyz147064 * When distributing Covered Code, include this CDDL HEADER in each 14d62bc4baSyz147064 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15d62bc4baSyz147064 * If applicable, add the following below this CDDL HEADER, with the 16d62bc4baSyz147064 * fields enclosed by brackets "[]" replaced with your own identifying 17d62bc4baSyz147064 * information: Portions Copyright [yyyy] [name of copyright owner] 18d62bc4baSyz147064 * 19d62bc4baSyz147064 * CDDL HEADER END 20d62bc4baSyz147064 */ 21d62bc4baSyz147064 /* 22*0dc2366fSVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23d62bc4baSyz147064 * Use is subject to license terms. 24d62bc4baSyz147064 */ 25d62bc4baSyz147064 26d62bc4baSyz147064 #include <sys/strsubr.h> 27d62bc4baSyz147064 #include <inet/led.h> 28d62bc4baSyz147064 #include <sys/softmac_impl.h> 29d62bc4baSyz147064 30d62bc4baSyz147064 mblk_t * 31d62bc4baSyz147064 softmac_m_tx(void *arg, mblk_t *mp) 32d62bc4baSyz147064 { 33d62bc4baSyz147064 queue_t *wq = ((softmac_t *)arg)->smac_lower->sl_wq; 34d62bc4baSyz147064 35d62bc4baSyz147064 /* 36d62bc4baSyz147064 * Optimize for the most common case. 37d62bc4baSyz147064 */ 38d81b850fSyz147064 if (mp->b_next == NULL) { 395d460eafSCathy Zhou if (!SOFTMAC_CANPUTNEXT(wq)) 40d62bc4baSyz147064 return (mp); 41d62bc4baSyz147064 42d62bc4baSyz147064 mp->b_flag |= MSGNOLOOP; 43d62bc4baSyz147064 putnext(wq, mp); 44d62bc4baSyz147064 return (NULL); 45d62bc4baSyz147064 } 46d62bc4baSyz147064 47d62bc4baSyz147064 while (mp != NULL) { 48d62bc4baSyz147064 mblk_t *next = mp->b_next; 49d62bc4baSyz147064 505d460eafSCathy Zhou if (!SOFTMAC_CANPUTNEXT(wq)) 51d62bc4baSyz147064 break; 52d62bc4baSyz147064 mp->b_next = NULL; 53d62bc4baSyz147064 mp->b_flag |= MSGNOLOOP; 54d62bc4baSyz147064 putnext(wq, mp); 55d62bc4baSyz147064 mp = next; 56d62bc4baSyz147064 } 57d62bc4baSyz147064 return (mp); 58d62bc4baSyz147064 } 59d62bc4baSyz147064 60d62bc4baSyz147064 void 61d62bc4baSyz147064 softmac_rput_process_data(softmac_lower_t *slp, mblk_t *mp) 62d62bc4baSyz147064 { 63d62bc4baSyz147064 /* 64d62bc4baSyz147064 * When packets arrive, the softmac might not be fully started. 65d62bc4baSyz147064 */ 66d62bc4baSyz147064 ASSERT((slp->sl_softmac != NULL)); 67d62bc4baSyz147064 ASSERT((mp->b_next == NULL) && (mp->b_prev == NULL)); 68d62bc4baSyz147064 69d62bc4baSyz147064 if (DB_REF(mp) > 1) { 70d62bc4baSyz147064 mblk_t *tmp; 7110972ddeSCathy Zhou uint32_t start, stuff, end, value, flags; 72d62bc4baSyz147064 73d62bc4baSyz147064 if ((tmp = copymsg(mp)) == NULL) { 74d62bc4baSyz147064 cmn_err(CE_WARN, "softmac_rput_process_data: " 75d62bc4baSyz147064 "copymsg failed"); 76d62bc4baSyz147064 goto failed; 77d62bc4baSyz147064 } 78*0dc2366fSVenugopal Iyer mac_hcksum_get(mp, &start, &stuff, &end, &value, &flags); 79*0dc2366fSVenugopal Iyer mac_hcksum_set(tmp, start, stuff, end, value, flags); 80d62bc4baSyz147064 freemsg(mp); 81d62bc4baSyz147064 mp = tmp; 82d62bc4baSyz147064 } 83d62bc4baSyz147064 84da14cebeSEric Cheng mac_rx(slp->sl_softmac->smac_mh, NULL, mp); 85d62bc4baSyz147064 return; 86d62bc4baSyz147064 87d62bc4baSyz147064 failed: 88d62bc4baSyz147064 freemsg(mp); 89d62bc4baSyz147064 } 90d62bc4baSyz147064 91d62bc4baSyz147064 #define ACKTIMEOUT (10 * hz) 92d62bc4baSyz147064 93d62bc4baSyz147064 static int 94d62bc4baSyz147064 dlpi_get_errno(t_uscalar_t error, t_uscalar_t unix_errno) 95d62bc4baSyz147064 { 96d62bc4baSyz147064 return (error == DL_SYSERR ? unix_errno : EINVAL); 97d62bc4baSyz147064 } 98d62bc4baSyz147064 995d460eafSCathy Zhou int 100d62bc4baSyz147064 softmac_output(softmac_lower_t *slp, mblk_t *mp, t_uscalar_t dl_prim, 101d62bc4baSyz147064 t_uscalar_t ack, mblk_t **mpp) 102d62bc4baSyz147064 { 103d62bc4baSyz147064 union DL_primitives *dlp; 104f1956ffeSCathy Zhou mac_perim_handle_t mph; 105d62bc4baSyz147064 int err = 0; 106d62bc4baSyz147064 107f1956ffeSCathy Zhou mac_perim_enter_by_mh(slp->sl_softmac->smac_mh, &mph); 108f1956ffeSCathy Zhou 109f1956ffeSCathy Zhou ASSERT(!slp->sl_pending_ioctl); 110f1956ffeSCathy Zhou ASSERT(slp->sl_pending_prim == DL_PRIM_INVAL); 111d62bc4baSyz147064 112d62bc4baSyz147064 /* 113d62bc4baSyz147064 * Record the pending DLPI primitive. 114d62bc4baSyz147064 */ 115d62bc4baSyz147064 mutex_enter(&slp->sl_mutex); 116d62bc4baSyz147064 slp->sl_pending_prim = dl_prim; 117d62bc4baSyz147064 mutex_exit(&slp->sl_mutex); 118d62bc4baSyz147064 119d62bc4baSyz147064 putnext(slp->sl_wq, mp); 120d62bc4baSyz147064 121d62bc4baSyz147064 mutex_enter(&slp->sl_mutex); 122d62bc4baSyz147064 while (slp->sl_pending_prim != DL_PRIM_INVAL) { 123d3d50737SRafael Vanoni if (cv_reltimedwait(&slp->sl_cv, &slp->sl_mutex, ACKTIMEOUT, 124d3d50737SRafael Vanoni TR_CLOCK_TICK) == -1) 125d62bc4baSyz147064 break; 126d62bc4baSyz147064 } 127d62bc4baSyz147064 128d62bc4baSyz147064 mp = slp->sl_ack_mp; 129d62bc4baSyz147064 slp->sl_ack_mp = NULL; 130d62bc4baSyz147064 131d62bc4baSyz147064 /* 132d62bc4baSyz147064 * If we timed out, sl_ack_mp will still be NULL, but sl_pending_prim 133d62bc4baSyz147064 * won't be set to DL_PRIM_INVAL. 134d62bc4baSyz147064 */ 135d62bc4baSyz147064 ASSERT(mp != NULL || slp->sl_pending_prim != DL_PRIM_INVAL); 136d62bc4baSyz147064 137d62bc4baSyz147064 slp->sl_pending_prim = DL_PRIM_INVAL; 138d62bc4baSyz147064 mutex_exit(&slp->sl_mutex); 139d62bc4baSyz147064 140d62bc4baSyz147064 if (mp != NULL) { 141d62bc4baSyz147064 dlp = (union DL_primitives *)mp->b_rptr; 142d62bc4baSyz147064 143d62bc4baSyz147064 if (dlp->dl_primitive == DL_ERROR_ACK) { 144d62bc4baSyz147064 err = dlpi_get_errno(dlp->error_ack.dl_errno, 145d62bc4baSyz147064 dlp->error_ack.dl_unix_errno); 146d62bc4baSyz147064 } else { 147d62bc4baSyz147064 ASSERT(dlp->dl_primitive == ack); 148d62bc4baSyz147064 } 149d62bc4baSyz147064 } else { 150d62bc4baSyz147064 err = ENOMSG; 151d62bc4baSyz147064 } 152d62bc4baSyz147064 153d62bc4baSyz147064 if (mpp != NULL) 154d62bc4baSyz147064 *mpp = mp; 155d62bc4baSyz147064 else 156d62bc4baSyz147064 freemsg(mp); 157d62bc4baSyz147064 158f1956ffeSCathy Zhou mac_perim_exit(mph); 159d62bc4baSyz147064 return (err); 160d62bc4baSyz147064 } 161d62bc4baSyz147064 162d62bc4baSyz147064 void 163d62bc4baSyz147064 softmac_ioctl_tx(softmac_lower_t *slp, mblk_t *mp, mblk_t **mpp) 164d62bc4baSyz147064 { 165f1956ffeSCathy Zhou mac_perim_handle_t mph; 166f1956ffeSCathy Zhou 167f1956ffeSCathy Zhou mac_perim_enter_by_mh(slp->sl_softmac->smac_mh, &mph); 168d62bc4baSyz147064 169d62bc4baSyz147064 /* 170d62bc4baSyz147064 * Record that ioctl processing is currently in progress. 171d62bc4baSyz147064 */ 172d62bc4baSyz147064 mutex_enter(&slp->sl_mutex); 173d62bc4baSyz147064 slp->sl_pending_ioctl = B_TRUE; 174d62bc4baSyz147064 mutex_exit(&slp->sl_mutex); 175d62bc4baSyz147064 176d62bc4baSyz147064 putnext(slp->sl_wq, mp); 177d62bc4baSyz147064 178d62bc4baSyz147064 mutex_enter(&slp->sl_mutex); 179d62bc4baSyz147064 while (slp->sl_pending_ioctl) 180d62bc4baSyz147064 cv_wait(&slp->sl_cv, &slp->sl_mutex); 181d62bc4baSyz147064 mp = slp->sl_ack_mp; 182d62bc4baSyz147064 slp->sl_ack_mp = NULL; 183d62bc4baSyz147064 mutex_exit(&slp->sl_mutex); 184d62bc4baSyz147064 185d62bc4baSyz147064 ASSERT(mpp != NULL && mp != NULL); 186d62bc4baSyz147064 *mpp = mp; 187d62bc4baSyz147064 188f1956ffeSCathy Zhou mac_perim_exit(mph); 189d62bc4baSyz147064 } 190d62bc4baSyz147064 1915d460eafSCathy Zhou int 192d62bc4baSyz147064 softmac_mexchange_error_ack(mblk_t **mpp, t_uscalar_t error_primitive, 193d62bc4baSyz147064 t_uscalar_t error, t_uscalar_t unix_errno) 194d62bc4baSyz147064 { 195d62bc4baSyz147064 union DL_primitives *dlp; 196d62bc4baSyz147064 197d62bc4baSyz147064 if ((*mpp = mexchange(NULL, *mpp, sizeof (dl_error_ack_t), M_PCPROTO, 198d62bc4baSyz147064 DL_ERROR_ACK)) == NULL) 199d62bc4baSyz147064 return (ENOMEM); 200d62bc4baSyz147064 201d62bc4baSyz147064 dlp = (union DL_primitives *)(*mpp)->b_rptr; 202d62bc4baSyz147064 dlp->error_ack.dl_error_primitive = error_primitive; 203d62bc4baSyz147064 dlp->error_ack.dl_errno = error; 204d62bc4baSyz147064 dlp->error_ack.dl_unix_errno = unix_errno; 205d62bc4baSyz147064 206d62bc4baSyz147064 return (0); 207d62bc4baSyz147064 } 208d62bc4baSyz147064 209d62bc4baSyz147064 int 210d62bc4baSyz147064 softmac_proto_tx(softmac_lower_t *slp, mblk_t *mp, mblk_t **mpp) 211d62bc4baSyz147064 { 212d62bc4baSyz147064 int err = 0; 213d62bc4baSyz147064 t_uscalar_t dl_prim; 214d62bc4baSyz147064 215d62bc4baSyz147064 dl_prim = ((union DL_primitives *)mp->b_rptr)->dl_primitive; 216d62bc4baSyz147064 217d62bc4baSyz147064 ASSERT(slp->sl_softmac != NULL); 218d62bc4baSyz147064 219d62bc4baSyz147064 switch (dl_prim) { 220d62bc4baSyz147064 case DL_ENABMULTI_REQ: 221d62bc4baSyz147064 case DL_DISABMULTI_REQ: 222d62bc4baSyz147064 case DL_SET_PHYS_ADDR_REQ: 223d62bc4baSyz147064 case DL_UNBIND_REQ: 224d62bc4baSyz147064 case DL_UDQOS_REQ: 225d62bc4baSyz147064 case DL_PROMISCON_REQ: 226d62bc4baSyz147064 case DL_PROMISCOFF_REQ: 227d62bc4baSyz147064 err = softmac_output(slp, mp, dl_prim, DL_OK_ACK, mpp); 228d62bc4baSyz147064 break; 229d62bc4baSyz147064 case DL_BIND_REQ: 230d62bc4baSyz147064 err = softmac_output(slp, mp, dl_prim, DL_BIND_ACK, mpp); 231d62bc4baSyz147064 break; 232d62bc4baSyz147064 case DL_NOTIFY_REQ: 233d62bc4baSyz147064 err = softmac_output(slp, mp, dl_prim, DL_NOTIFY_ACK, mpp); 234d62bc4baSyz147064 break; 235d62bc4baSyz147064 case DL_CONTROL_REQ: 236d62bc4baSyz147064 err = softmac_output(slp, mp, dl_prim, DL_CONTROL_ACK, mpp); 237d62bc4baSyz147064 break; 238d62bc4baSyz147064 case DL_CAPABILITY_REQ: 239d62bc4baSyz147064 err = softmac_output(slp, mp, dl_prim, DL_CAPABILITY_ACK, mpp); 240d62bc4baSyz147064 break; 241d62bc4baSyz147064 default: 242d62bc4baSyz147064 if (mpp != NULL) { 243d62bc4baSyz147064 *mpp = mp; 244d62bc4baSyz147064 err = softmac_mexchange_error_ack(mpp, dl_prim, 245d62bc4baSyz147064 DL_UNSUPPORTED, 0); 246d62bc4baSyz147064 } 247d62bc4baSyz147064 break; 248d62bc4baSyz147064 } 249d62bc4baSyz147064 return (err); 250d62bc4baSyz147064 } 251