int atm_find_ci(struct atm_vcc *vcc,short *vpi,int *vci) { unsigned long flags; static short p = 0; /* poor man's per-device cache */ static int c = 0; short old_p; int old_c; int err; spin_lock_irqsave(&vcc->dev->lock, flags); if (*vpi != ATM_VPI_ANY && *vci != ATM_VCI_ANY) { err = check_ci(vcc,*vpi,*vci); spin_unlock_irqrestore(&vcc->dev->lock, flags); return err; } /* last scan may have left values out of bounds for current device */ if (*vpi != ATM_VPI_ANY) p = *vpi; else if (p >= 1 << vcc->dev->ci_range.vpi_bits) p = 0; if (*vci != ATM_VCI_ANY) c = *vci; else if (c < ATM_NOT_RSV_VCI || c >= 1 << vcc->dev->ci_range.vci_bits) c = ATM_NOT_RSV_VCI; old_p = p; old_c = c; do { if (!check_ci(vcc,p,c)) { *vpi = p; *vci = c; spin_unlock_irqrestore(&vcc->dev->lock, flags); return 0; } if (*vci == ATM_VCI_ANY) { c++; if (c >= 1 << vcc->dev->ci_range.vci_bits) c = ATM_NOT_RSV_VCI; } if ((c == ATM_NOT_RSV_VCI || *vci != ATM_VCI_ANY) && *vpi == ATM_VPI_ANY) { p++; if (p >= 1 << vcc->dev->ci_range.vpi_bits) p = 0; } } while (old_p != p || old_c != c); spin_unlock_irqrestore(&vcc->dev->lock, flags); return -EADDRINUSE; }
void fab_op(CALL *call,int op,const struct atm_qos *qos, void (*callback)(CALL *call,int cause,void *more,void *user),void *user) { int error,error2; diag(COMPONENT,DIAG_INFO,"fab_op%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", !op ? " FREE" : "",op & RM_RSV(_RM_ANY) ? " RM_RSV:" : "", op & RM_IN_TX ? " IN_TX" : "",op & RM_IN_RX ? " IN_RX" : "", op & RM_OUT_TX ? " OUT_TX" : "",op & RM_OUT_RX ? " OUT_RX" : "", op & RM_PATH_TX ? " PATH_TX" : "",op & RM_PATH_RX ? " PATH_RX" : "", op & RM_CLAIM(_RM_ANY) ? " RM_CLAIM:" : "", op & _RM_SHIFT(RM_IN_TX) ? " IN_TX" : "", op & _RM_SHIFT(RM_IN_RX) ? " IN_RX" : "", op & _RM_SHIFT(RM_OUT_TX) ? " OUT_TX" : "", op & _RM_SHIFT(RM_OUT_RX) ? " OUT_RX" : "", op & _RM_SHIFT(RM_PATH_TX) ? " PATH_TX" : "", op & _RM_SHIFT(RM_PATH_RX) ? " PATH_RX" : ""); if (op & (RM_RSV(RM_IN) | RM_CLAIM(RM_IN))) { if (!check_ci(&call->in.pvc)) { callback(call,ATM_CV_CI_UNAVAIL,NULL,user); return; } call->in.qos = *qos; } if (op & (RM_RSV(RM_OUT) | RM_CLAIM(RM_OUT))) { if (!check_ci(&call->out.pvc)) { callback(call,ATM_CV_CI_UNAVAIL,NULL,user); return; } call->out.qos = *qos; } if (op & RM_CLAIM(RM_PATH)) { error = 0; if (call->in.qos.txtp.traffic_class != ATM_NONE) error = add_entry(&call->in.pvc,&call->out.pvc); if (!error) { if (call->in.qos.rxtp.traffic_class != ATM_NONE) error = add_entry(&call->out.pvc,&call->in.pvc); if (error && call->in.qos.txtp.traffic_class != ATM_NONE) { error2 = del_entry(&call->in.pvc,&call->out.pvc); if (error2) diag(COMPONENT,DIAG_ERROR,"del_entry: %s",strerror(error2)); } } if (error) { diag(COMPONENT,DIAG_ERROR,"add_entry: %s",strerror(error)); callback(call,ATM_CV_RES_UNAVAIL,NULL,user); return; } PRV(call)->active = 1; } if (!op && PRV(call)->active) { error = error2 = 0; if (call->in.qos.txtp.traffic_class != ATM_NONE) { error = del_entry(&call->in.pvc,&call->out.pvc); if (error) diag(COMPONENT,DIAG_ERROR,"del_entry: %s",strerror(error)); } if (call->in.qos.rxtp.traffic_class != ATM_NONE) { error2 = del_entry(&call->out.pvc,&call->in.pvc); if (error2) diag(COMPONENT,DIAG_ERROR,"del_entry: %s",strerror(error2)); } if (error || error2) { callback(call,ATM_CV_TEMP_FAIL,NULL,user); return; } } callback(call,0,NULL,user); }