in lanai.c [1616:1695]
static int handle_service(struct lanai_dev *lanai, u32 s)
{
vci_t vci = SERVICE_GET_VCI(s);
struct lanai_vcc *lvcc;
read_lock(&vcc_sklist_lock);
lvcc = lanai->vccs[vci];
if (unlikely(lvcc == NULL)) {
read_unlock(&vcc_sklist_lock);
DPRINTK("(itf %d) got service entry 0x%X for nonexistent "
"vcc %d\n", lanai->number, (unsigned int) s, vci);
if (s & SERVICE_TX)
lanai->stats.service_notx++;
else
lanai->stats.service_norx++;
return 0;
}
if (s & SERVICE_TX) { /* segmentation interrupt */
if (unlikely(lvcc->tx.atmvcc == NULL)) {
read_unlock(&vcc_sklist_lock);
DPRINTK("(itf %d) got service entry 0x%X for non-TX "
"vcc %d\n", lanai->number, (unsigned int) s, vci);
lanai->stats.service_notx++;
return 0;
}
__set_bit(vci, lanai->transmit_ready);
lvcc->tx.endptr = SERVICE_GET_END(s);
read_unlock(&vcc_sklist_lock);
return 1;
}
if (unlikely(lvcc->rx.atmvcc == NULL)) {
read_unlock(&vcc_sklist_lock);
DPRINTK("(itf %d) got service entry 0x%X for non-RX "
"vcc %d\n", lanai->number, (unsigned int) s, vci);
lanai->stats.service_norx++;
return 0;
}
if (unlikely(lvcc->rx.atmvcc->qos.aal != ATM_AAL5)) {
read_unlock(&vcc_sklist_lock);
DPRINTK("(itf %d) got RX service entry 0x%X for non-AAL5 "
"vcc %d\n", lanai->number, (unsigned int) s, vci);
lanai->stats.service_rxnotaal5++;
atomic_inc(&lvcc->rx.atmvcc->stats->rx_err);
return 0;
}
if (likely(!(s & (SERVICE_TRASH | SERVICE_STREAM | SERVICE_CRCERR)))) {
vcc_rx_aal5(lvcc, SERVICE_GET_END(s));
read_unlock(&vcc_sklist_lock);
return 0;
}
if (s & SERVICE_TRASH) {
int bytes;
read_unlock(&vcc_sklist_lock);
DPRINTK("got trashed rx pdu on vci %d\n", vci);
atomic_inc(&lvcc->rx.atmvcc->stats->rx_err);
lvcc->stats.x.aal5.service_trash++;
bytes = (SERVICE_GET_END(s) * 16) -
(((unsigned long) lvcc->rx.buf.ptr) -
((unsigned long) lvcc->rx.buf.start)) + 47;
if (bytes < 0)
bytes += lanai_buf_size(&lvcc->rx.buf);
lanai->stats.ovfl_trash += (bytes / 48);
return 0;
}
if (s & SERVICE_STREAM) {
read_unlock(&vcc_sklist_lock);
atomic_inc(&lvcc->rx.atmvcc->stats->rx_err);
lvcc->stats.x.aal5.service_stream++;
printk(KERN_ERR DEV_LABEL "(itf %d): Got AAL5 stream "
"PDU on VCI %d!\n", lanai->number, vci);
lanai_reset(lanai);
return 0;
}
DPRINTK("got rx crc error on vci %d\n", vci);
atomic_inc(&lvcc->rx.atmvcc->stats->rx_err);
lvcc->stats.x.aal5.service_rxcrc++;
lvcc->rx.buf.ptr = &lvcc->rx.buf.start[SERVICE_GET_END(s) * 4];
cardvcc_write(lvcc, SERVICE_GET_END(s), vcc_rxreadptr);
read_unlock(&vcc_sklist_lock);
return 0;
}