1/*- 2 * Copyright (c) 2001-2003 3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * Author: Hartmut Brandt <harti@freebsd.org> 28 * 29 * ForeHE driver. 30 * 31 * Receive. 32 */ 33 34#include <sys/cdefs.h>
|
35__FBSDID("$FreeBSD: head/sys/dev/hatm/if_hatm_rx.c 257176 2013-10-26 17:58:36Z glebius $");
|
35__FBSDID("$FreeBSD: head/sys/dev/hatm/if_hatm_rx.c 271849 2014-09-19 03:51:26Z glebius $"); |
36 37#include "opt_inet.h" 38#include "opt_natm.h" 39 40#include <sys/types.h> 41#include <sys/param.h> 42#include <sys/systm.h> 43#include <sys/kernel.h> 44#include <sys/bus.h> 45#include <sys/errno.h> 46#include <sys/conf.h> 47#include <sys/module.h> 48#include <sys/queue.h> 49#include <sys/syslog.h> 50#include <sys/condvar.h> 51#include <sys/sysctl.h> 52#include <vm/uma.h> 53 54#include <sys/sockio.h> 55#include <sys/mbuf.h> 56#include <sys/socket.h> 57 58#include <net/if.h> 59#include <net/if_var.h> 60#include <net/if_media.h> 61#include <net/if_atm.h> 62#include <net/route.h> 63#ifdef ENABLE_BPF 64#include <net/bpf.h> 65#endif 66#include <netinet/in.h> 67#include <netinet/if_atm.h> 68 69#include <machine/bus.h> 70#include <machine/resource.h> 71#include <sys/bus.h> 72#include <sys/rman.h> 73#include <dev/pci/pcireg.h> 74#include <dev/pci/pcivar.h> 75 76#include <dev/utopia/utopia.h> 77#include <dev/hatm/if_hatmconf.h> 78#include <dev/hatm/if_hatmreg.h> 79#include <dev/hatm/if_hatmvar.h> 80 81void 82hatm_rx(struct hatm_softc *sc, u_int cid, u_int flags, struct mbuf *m0, 83 u_int len) 84{ 85 struct hevcc *vcc; 86 struct atm_pseudohdr aph; 87 struct mbuf *m, *m1; 88 u_int vpi, vci; 89 u_char *ptr; 90 91 DBG(sc, RX, ("cid=%#x flags=%#x len=%u mbuf=%p", cid, flags, len, m0)); 92 93 vcc = sc->vccs[cid]; 94 if (vcc == NULL) 95 goto drop; 96 97 if (flags & HE_REGM_RBRQ_CON_CLOSED) { 98 if (vcc->vflags & HE_VCC_RX_CLOSING) { 99 vcc->vflags &= ~HE_VCC_RX_CLOSING; 100 if (vcc->param.flags & ATMIO_FLAG_ASYNC) { 101 if (!(vcc->vflags & HE_VCC_OPEN)) 102 hatm_vcc_closed(sc, cid); 103 } else 104 cv_signal(&sc->vcc_cv); 105 } 106 goto drop; 107 } 108 109 if (!(vcc->vflags & HE_VCC_RX_OPEN)) 110 goto drop; 111 112 if (flags & HE_REGM_RBRQ_HBUF_ERROR) { 113 sc->istats.hbuf_error++; 114 if (vcc->chain != NULL) { 115 m_freem(vcc->chain); 116 vcc->chain = vcc->last = NULL; 117 } 118 goto drop; 119 } 120 if (m0 == NULL) { 121 sc->istats.no_rcv_mbuf++; 122 return; 123 } 124 125 if ((m0->m_len = len) == 0) { 126 sc->istats.empty_hbuf++; 127 m_free(m0); 128 129 } else if (vcc->chain == NULL) { 130 sc->istats.rx_seg++; 131 vcc->chain = vcc->last = m0; 132 vcc->last->m_next = NULL; 133 vcc->chain->m_pkthdr.len = m0->m_len; 134 vcc->chain->m_pkthdr.rcvif = sc->ifp; 135 136 } else { 137 sc->istats.rx_seg++; 138 vcc->last->m_next = m0; 139 vcc->last = m0; 140 vcc->last->m_next = NULL; 141 vcc->chain->m_pkthdr.len += m0->m_len; 142 } 143 144 if (!(flags & HE_REGM_RBRQ_END_PDU)) 145 return; 146 147 if (flags & HE_REGM_RBRQ_CRC_ERROR) { 148 if (vcc->chain) 149 m_freem(vcc->chain); 150 vcc->chain = vcc->last = NULL; 151 sc->istats.crc_error++;
|
152 sc->ifp->if_ierrors++;
|
152 if_inc_counter(sc->ifp, IFCOUNTER_IERRORS, 1); |
153 return; 154 } 155 if (flags & HE_REGM_RBRQ_LEN_ERROR) { 156 if (vcc->chain) 157 m_freem(vcc->chain); 158 vcc->chain = vcc->last = NULL; 159 sc->istats.len_error++;
|
160 sc->ifp->if_ierrors++;
|
160 if_inc_counter(sc->ifp, IFCOUNTER_IERRORS, 1); |
161 return; 162 } 163 164#ifdef HATM_DEBUG 165 if (sc->debug & DBG_DUMP) { 166 struct mbuf *tmp; 167 168 for (tmp = vcc->chain; tmp != NULL; tmp = tmp->m_next) { 169 printf("mbuf %p: len=%u\n", tmp, tmp->m_len); 170 for (ptr = mtod(tmp, u_char *); 171 ptr < mtod(tmp, u_char *) + tmp->m_len; ptr++) 172 printf("%02x ", *ptr); 173 printf("\n"); 174 } 175 } 176#endif 177 178 if (vcc->param.aal == ATMIO_AAL_5) { 179 /* 180 * Need to remove padding and the trailer. The trailer 181 * may be split accross buffers according to 2.10.1.2 182 * Assume that mbufs sizes are even (buffer sizes and cell 183 * payload sizes are) and that there are no empty mbufs. 184 */ 185 m = vcc->last; 186 if (m->m_len == 2) { 187 /* Ah, oh, only part of CRC */ 188 if (m == vcc->chain) { 189 /* ups */ 190 sc->istats.short_aal5++; 191 m_freem(vcc->chain); 192 vcc->chain = vcc->last = NULL; 193 return; 194 } 195 for (m1 = vcc->chain; m1->m_next != m; m1 = m1->m_next) 196 ; 197 ptr = (u_char *)m1->m_data + m1->m_len - 4; 198 199 } else if (m->m_len == 4) { 200 /* Ah, oh, only CRC */ 201 if (m == vcc->chain) { 202 /* ups */ 203 sc->istats.short_aal5++; 204 m_freem(vcc->chain); 205 vcc->chain = vcc->last = NULL; 206 return; 207 } 208 for (m1 = vcc->chain; m1->m_next != m; m1 = m1->m_next) 209 ; 210 ptr = (u_char *)m1->m_data + m1->m_len - 2; 211 212 } else if (m->m_len >= 6) { 213 ptr = (u_char *)m->m_data + m->m_len - 6; 214 } else 215 panic("hatm_rx: bad mbuf len %d", m->m_len); 216 217 len = (ptr[0] << 8) + ptr[1]; 218 if (len > (u_int)vcc->chain->m_pkthdr.len - 4) { 219 sc->istats.badlen_aal5++; 220 m_freem(vcc->chain); 221 vcc->chain = vcc->last = NULL; 222 return; 223 } 224 m_adj(vcc->chain, -(vcc->chain->m_pkthdr.len - len)); 225 } 226 m = vcc->chain; 227 vcc->chain = vcc->last = NULL; 228 229#ifdef ENABLE_BPF 230 if (!(vcc->param.flags & ATMIO_FLAG_NG) && 231 (vcc->param.aal == ATMIO_AAL_5) && 232 (vcc->param.flags & ATM_PH_LLCSNAP)) 233 BPF_MTAP(sc->ifp, m); 234#endif 235 236 vpi = HE_VPI(cid); 237 vci = HE_VCI(cid); 238 239 ATM_PH_FLAGS(&aph) = vcc->param.flags & 0xff; 240 ATM_PH_VPI(&aph) = vpi; 241 ATM_PH_SETVCI(&aph, vci); 242
|
243 sc->ifp->if_ipackets++;
|
243 if_inc_counter(sc->ifp, IFCOUNTER_IPACKETS, 1); |
244 /* this is in if_atmsubr.c */
|
245 /* sc->ifp->if_ibytes += len; */
|
245 /* if_inc_counter(sc->ifp, IFCOUNTER_IBYTES, len); */ |
246 247 vcc->ibytes += len; 248 vcc->ipackets++; 249 250#if 0 251 { 252 struct mbuf *tmp; 253 254 for (tmp = m; tmp != NULL; tmp = tmp->m_next) { 255 printf("mbuf %p: len=%u\n", tmp, tmp->m_len); 256 for (ptr = mtod(tmp, u_char *); 257 ptr < mtod(tmp, u_char *) + tmp->m_len; ptr++) 258 printf("%02x ", *ptr); 259 printf("\n"); 260 } 261 } 262#endif 263 264 atm_input(sc->ifp, &aph, m, vcc->rxhand); 265 266 return; 267 268 drop: 269 if (m0 != NULL) 270 m_free(m0); 271} 272 273void 274hatm_rx_vcc_open(struct hatm_softc *sc, u_int cid) 275{ 276 struct hevcc *vcc = sc->vccs[cid]; 277 uint32_t rsr0, rsr1, rsr4; 278 279 rsr0 = rsr1 = rsr4 = 0; 280 281 if (vcc->param.traffic == ATMIO_TRAFFIC_ABR) { 282 rsr1 |= HE_REGM_RSR1_AQI; 283 rsr4 |= HE_REGM_RSR4_AQI; 284 } 285 286 if (vcc->param.aal == ATMIO_AAL_5) { 287 rsr0 |= HE_REGM_RSR0_STARTPDU | HE_REGM_RSR0_AAL_5; 288 } else if (vcc->param.aal == ATMIO_AAL_0) { 289 rsr0 |= HE_REGM_RSR0_AAL_0; 290 } else { 291 if (sc->rbp_s1.size != 0) { 292 rsr1 |= (1 << HE_REGS_RSR1_GROUP); 293 rsr4 |= (1 << HE_REGS_RSR4_GROUP); 294 } 295 rsr0 |= HE_REGM_RSR0_AAL_RAW | HE_REGM_RSR0_PTI7 | 296 HE_REGM_RSR0_RM | HE_REGM_RSR0_F5OAM; 297 } 298 rsr0 |= HE_REGM_RSR0_OPEN; 299 300 WRITE_RSR(sc, cid, 0, 0xf, rsr0); 301 WRITE_RSR(sc, cid, 1, 0xf, rsr1); 302 WRITE_RSR(sc, cid, 4, 0xf, rsr4); 303 304 vcc->vflags |= HE_VCC_RX_OPEN; 305} 306 307/* 308 * Close the RX side of a VCC. 309 */ 310void 311hatm_rx_vcc_close(struct hatm_softc *sc, u_int cid) 312{ 313 struct hevcc *vcc = sc->vccs[cid]; 314 uint32_t v; 315 316 vcc->vflags |= HE_VCC_RX_CLOSING; 317 WRITE_RSR(sc, cid, 0, 0xf, 0); 318 319 v = READ4(sc, HE_REGO_RCCSTAT); 320 while ((sc->ifp->if_drv_flags & IFF_DRV_RUNNING) && 321 (READ4(sc, HE_REGO_RCCSTAT) & HE_REGM_RCCSTAT_PROG)) 322 cv_timedwait(&sc->cv_rcclose, &sc->mtx, 1); 323 324 if (!(sc->ifp->if_drv_flags & IFF_DRV_RUNNING)) 325 return; 326 327 WRITE_MBOX4(sc, HE_REGO_RCON_CLOSE, cid); 328 329 vcc->vflags |= HE_VCC_RX_CLOSING; 330 vcc->vflags &= ~HE_VCC_RX_OPEN; 331}
|