예제 #1
0
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;
}
예제 #2
0
파일: tcpsw.c 프로젝트: ebichu/dd-wrt
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);
}