예제 #1
0
파일: dpc.c 프로젝트: Anjali05/linux
static struct dpc_dev *to_dpc_dev(struct pci_dev *dev)
{
	struct device *device;

	device = pcie_port_find_device(dev, PCIE_PORT_SERVICE_DPC);
	if (!device)
		return NULL;
	return get_service_data(to_pcie_device(device));
}
예제 #2
0
/**
 * aer_irq - Root Port's ISR
 * @irq: IRQ assigned to Root Port
 * @context: pointer to Root Port data structure
 *
 * Invoked when Root Port detects AER messages.
 **/
irqreturn_t aer_irq(int irq, void *context)
{
	unsigned int status, id;
	struct pcie_device *pdev = (struct pcie_device *)context;
	struct aer_rpc *rpc = get_service_data(pdev);
	int next_prod_idx;
	unsigned long flags;
	int pos;

	pos = pci_find_ext_capability(pdev->port, PCI_EXT_CAP_ID_ERR);
	/*
	 * Must lock access to Root Error Status Reg, Root Error ID Reg,
	 * and Root error producer/consumer index
	 */
	spin_lock_irqsave(&rpc->e_lock, flags);

	/* Read error status */
	pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, &status);
	if (!(status & ROOT_ERR_STATUS_MASKS)) {
		spin_unlock_irqrestore(&rpc->e_lock, flags);
		return IRQ_NONE;
	}

	/* Read error source and clear error status */
	pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_COR_SRC, &id);
	pci_write_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, status);

	/* Store error source for later DPC handler */
	next_prod_idx = rpc->prod_idx + 1;
	if (next_prod_idx == AER_ERROR_SOURCES_MAX)
		next_prod_idx = 0;
	if (next_prod_idx == rpc->cons_idx) {
		/*
		 * Error Storm Condition - possibly the same error occurred.
		 * Drop the error.
		 */
		spin_unlock_irqrestore(&rpc->e_lock, flags);
		return IRQ_HANDLED;
	}
	rpc->e_sources[rpc->prod_idx].status =  status;
	rpc->e_sources[rpc->prod_idx].id = id;
	rpc->prod_idx = next_prod_idx;
	spin_unlock_irqrestore(&rpc->e_lock, flags);

	/*  Invoke DPC handler */
	schedule_work(&rpc->dpc_handler);

	return IRQ_HANDLED;
}
예제 #3
0
irqreturn_t aer_irq(int irq, void *context)
{
	unsigned int status, id;
	struct pcie_device *pdev = (struct pcie_device *)context;
	struct aer_rpc *rpc = get_service_data(pdev);
	int next_prod_idx;
	unsigned long flags;
	int pos;

	pos = pci_find_ext_capability(pdev->port, PCI_EXT_CAP_ID_ERR);
	/*
                                                                 
                                          
  */
	spin_lock_irqsave(&rpc->e_lock, flags);

	/*                   */
	pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, &status);
	if (!(status & (PCI_ERR_ROOT_UNCOR_RCV|PCI_ERR_ROOT_COR_RCV))) {
		spin_unlock_irqrestore(&rpc->e_lock, flags);
		return IRQ_NONE;
	}

	/*                                          */
	pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_ERR_SRC, &id);
	pci_write_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, status);

	/*                                          */
	next_prod_idx = rpc->prod_idx + 1;
	if (next_prod_idx == AER_ERROR_SOURCES_MAX)
		next_prod_idx = 0;
	if (next_prod_idx == rpc->cons_idx) {
		/*
                                                              
                    
   */
		spin_unlock_irqrestore(&rpc->e_lock, flags);
		return IRQ_HANDLED;
	}
	rpc->e_sources[rpc->prod_idx].status =  status;
	rpc->e_sources[rpc->prod_idx].id = id;
	rpc->prod_idx = next_prod_idx;
	spin_unlock_irqrestore(&rpc->e_lock, flags);

	/*                     */
	schedule_work(&rpc->dpc_handler);

	return IRQ_HANDLED;
}
예제 #4
0
/**
 * aer_remove - clean up resources
 * @dev: pointer to the pcie_dev data structure
 *
 * Invoked when PCI Express bus unloads or AER probe fails.
 **/
static void aer_remove(struct pcie_device *dev)
{
	struct aer_rpc *rpc = get_service_data(dev);

	if (rpc) {
		/* If register interrupt service, it must be free. */
		if (rpc->isr)
			free_irq(dev->irq, dev);

		wait_event(rpc->wait_release, rpc->prod_idx == rpc->cons_idx);

		aer_delete_rootport(rpc);
		set_service_data(dev, NULL);
	}
}
예제 #5
0
static void aer_remove(struct pcie_device *dev)
{
	struct aer_rpc *rpc = get_service_data(dev);

	if (rpc) {
		
		if (rpc->isr)
			free_irq(dev->irq, dev);

		wait_event(rpc->wait_release, rpc->prod_idx == rpc->cons_idx);

		aer_disable_rootport(rpc);
		kfree(rpc);
		set_service_data(dev, NULL);
	}
}
예제 #6
0
int main(int argc, char *argv[])
{
  pid_t pid;
  int i;

  int users_number;
  int service_probability;
  int text_message_probability;

  int status;
  int deadproc = 0; /* A counter of the already terminated user processes */
  int qid;
  int sw; /* Qid of the switch */
  int dest; /* Destination of the message */
  int olddest; /* Destination of the previous message */

  int queues[MAXCHILDS + 1]; /* Queue identifiers - 0 is the qid of the switch */

  int msg_sender;
  int msg_recipient;
  char msg_text[160];
  int msg_service;
  int msg_service_data;

  int t;
  int timing[MAXCHILDS + 1][2];

  int unreachable_destinations[MAXCHILDS + 1];

  char *padding = "                                                                      ";
  char text[160];

  messagebuf_t msg, in;

  /* Command line argument parsing */
  if(argc != 4){
    usage(argv);
    exit(0);
  }

  users_number = strtol(argv[1], NULL, 10);  
  service_probability = strtol(argv[2], NULL, 10);
  text_message_probability = strtol(argv[3], NULL, 10);
  

  if((users_number < MINCHILDS) || (users_number > MAXCHILDS)){
    usage(argv);
    exit(1);
  }

  if((service_probability < 0) || (service_probability > 100)){
    usage(argv);
    exit(0);
  }

  if((text_message_probability < 0) || (text_message_probability > 100)){
    usage(argv);
    exit(0);
  }

  printf("Number of users: %d\n", users_number);
  printf("Probability of a service request: %d%%\n", service_probability);
  printf("Probability of a text message: %d%%\n", text_message_probability);
  printf("\n");

  /* Initialize the random number generator */
  srandom(time(NULL));

  /* Switch queue initialization */
  sw = init_queue(255);
  
  /* Read the last messages we have in the queue */
  while(receive_message(sw, TYPE_TEXT, &in)){
    printf("%d -- S -- Receiving old text messages\n", (int) time(NULL), i);
  }

  /* Read the last messages we have in the queue */
  while(receive_message(sw, TYPE_SERVICE, &in)){
    printf("%d -- S -- Receiving old service messge\n", (int) time(NULL), i);
  }

  /* All queues are "uninitialized" (set equal to switch queue) */
  for(i = 0; i <= users_number; i++){
    queues[i] = sw;
    unreachable_destinations[i] = 0;
  }

  /* Create users */
  for(i = 1; i <= users_number; i++){
    pid = fork();

    if (pid == 0){
      srandom(time(NULL) + 1000*i);

      /* Initialize queue  */
      qid = init_queue(i);
      
      /* Read the last messages we have in the queue */
      while(receive_message(qid, TYPE_TEXT, &in)){
	printf("%s%d -- U %02d -- Receiving old text messages\n", padding, (int) time(NULL), i);
      }

      /* Read the last messages we have in the queue */
      while(receive_message(qid, TYPE_SERVICE, &in)){
	printf("%s%d -- U %02d -- Receiving old service messge\n", padding, (int) time(NULL), i);
      }

      /* Let the switch know we are alive */
      user_send_connect(i, sw);
      
      /* Let the switch know how to reach us */
      user_send_qid(i, qid, sw);
      
      /* Enter the main loop */
      while(1){
	sleep(rand()%MAX_SLEEP);

    	/* Check if the switch requested a service */
    	if(receive_message(qid, TYPE_SERVICE, &in)){
    	  msg_service = get_service(&in);

    	  switch(msg_service){

    	  case SERVICE_TERMINATE:
    	    /* Send an acknowledgement to the switch */
    	    user_send_disconnect(i, getpid(), sw);
	    
    	    /* Read the last messages we have in the queue */
    	    while(receive_message(qid, TYPE_TEXT, &in)){
    	      msg_sender = get_sender(&in);
    	      get_text(&in, msg_text);
    	      printf("%s%d -- U %02d -- Message received\n", padding, (int) time(NULL), i);
	      printf("%s                      Sender: %d\n", padding, msg_sender);
	      printf("%s                      Text: %s\n", padding, msg_text);
    	    }
	    
    	    /* Remove the queue */
    	    close_queue(qid);
    	    printf("%s%d -- U %02d -- Termination\n", padding, (int) time(NULL), i);
    	    exit(0);
    	    break;

    	  case SERVICE_TIME:
    	    user_send_time(i, sw);
    	    printf("%s%d -- U %02d -- Timing\n", padding, (int) time(NULL), i);
    	    break;

	  }
    	}

    	/* Send a message */
    	if(random_number(100) < text_message_probability){
    	  dest = random_number(users_number + 1);

    	  /* Do not send a message to the switch, to yourself and to the previous recipient */
    	  while((dest == 0) || (dest == i) || (dest == olddest)){
    	    dest = random_number(users_number + 1);
    	  }
    	  olddest = dest;

    	  printf("%s%d -- U %02d -- Message to user %d\n", padding, (int) time(NULL), i, dest);
	  sprintf(text, "A message from me (%d) to you (%d)", i, dest);
    	  user_send_text_message(i, dest, text, sw);
    	}
	
    	/* Check the incoming box for simple messages */
    	if(receive_message(qid, TYPE_TEXT, &in)){
    	  msg_sender = get_sender(&in);
    	  get_text(&in, msg_text);
	  printf("%s%d -- U %02d -- Message received\n", padding, (int) time(NULL), i);
	  printf("%s                      Sender: %d\n", padding, msg_sender);
	  printf("%s                      Text: %s\n", padding, msg_text);
    	}
      }
    }
  }
  
  /* Switch (parent process) */ 
  while(1){
    /* Check if some user is answering to service messages */
    if(receive_message(sw, TYPE_SERVICE, &in)){
      msg_service = get_service(&in);
      msg_sender = get_sender(&in);

      switch(msg_service){
      case SERVICE_CONNECT:
	/* A new user has connected */
	printf("%d -- S -- Service: connection\n", (int) time(NULL));
	printf("                   User: %d\n", msg_sender);
	break;

      case SERVICE_DISCONNECT:
	/* The user is terminating */
	printf("%d -- S -- Service: disconnection\n", (int) time(NULL));
	printf("                   User: %d\n", msg_sender);

	deadproc++;
	break;

      case SERVICE_QID:
	/* The user is sending us its queue id */
	msg_service_data = get_service_data(&in);
	printf("%d -- S -- Service: queue\n", (int) time(NULL));
	printf("                   User: %d\n", msg_sender);
	printf("                   Qid: %d\n", msg_service_data);
	queues[msg_sender] = msg_service_data;
	break;

      case SERVICE_TIME:
	msg_service_data = get_service_data(&in);

	/* Timing informations */
	timing[msg_sender][1] = msg_service_data - timing[msg_sender][1];

	printf("%d -- S -- Service: timing\n", (int) time(NULL));
	printf("                   User: %d\n", msg_sender);
	printf("                   Timing: %d\n", timing[msg_sender][1]);

	/* The user is no more blocked by a timing operation */
	timing[msg_sender][0] = 0;
	break;
      }
    }

    /* Check if some user has connected */
    if(receive_message(sw, TYPE_TEXT, &in)){

      msg_recipient = get_recipient(&in);
      msg_sender = get_sender(&in);
      get_text(&in, msg_text);
      
      /* If the destination is connected */
      if(queues[msg_recipient] != sw){
	/* Send the message (forward it) */
	switch_send_text_message(msg_sender, msg_text, queues[msg_recipient]);
	
	printf("%d -- S -- Routing message\n", (int) time(NULL));
	printf("                   Sender: %d -- Destination: %d\n", msg_sender, msg_recipient);
	printf("                   Text: %s\n", msg_text);
      }
      else{
	unreachable_destinations[msg_sender] += 1;

	if (unreachable_destinations[msg_sender] > MAXFAILS) {
	  continue;
	}

	printf("%d -- S -- Unreachable destination\n", (int) time(NULL));
	printf("                   Sender: %d -- Destination: %d\n", msg_sender, msg_recipient);
	printf("                   Text: %s\n", msg_text);
	printf("                   Threshold: %d/%d\n", unreachable_destinations[msg_sender], MAXFAILS);

	if (unreachable_destinations[msg_sender] == MAXFAILS) {
	  printf("%d -- S -- User %d reached max unreachable destinations\n", (int) time(NULL), msg_sender);

	  switch_send_terminate(queues[msg_sender]);
	  
	  /* Remove its queue from the list */
	  queues[msg_sender] = sw;
	}
      }
      
      /* Randomly request a service to the sender of the last message */
      if((random_number(100)  < service_probability) && (queues[msg_sender] != sw)){
	if (random_number(100) < 40){
	  /* The user must terminate */
	  printf("%d -- S -- User %d chosen for termination\n", (int) time(NULL), msg_sender);

	  switch_send_terminate(queues[msg_sender]);

	  /* Remove its queue from the list */
	  queues[msg_sender] = sw;
	}
	else {
	  /* Check if we are already timing that user */
	  if(!timing[msg_sender][0]){
	    timing[msg_sender][0] = 1;
	    timing[msg_sender][1] = (int) time(NULL);
	    printf("%d -- S -- User %d chosen for timing...\n", timing[msg_sender][1], msg_sender);
	    switch_send_time(queues[msg_sender]);
	  }
	}
      }
    }
    else{
      if(deadproc == users_number){
	/* All childs have been terminated, just wait for the last to complete its jobs */
	waitpid(pid, &status, 0);

	/* Remove the switch queue */
	remove_queue(sw);

	printf("\n");
	printf("No more active users. Switch turns off.\n");
	
	/* Terminate the program */
	exit(0);
      }
    }
  }
}
예제 #7
0
static int publish_service(struct service *s) {
    int r = -1;
    TXTRecordRef txt;
    DNSServiceErrorType err;
    const char *name = NULL, *t;
    pa_proplist *proplist = NULL;
    pa_sample_spec ss;
    pa_channel_map map;
    char cm[PA_CHANNEL_MAP_SNPRINT_MAX], tmp[64];
    enum service_subtype subtype;

    const char * const subtype_text[] = {
        [SUBTYPE_HARDWARE] = "hardware",
        [SUBTYPE_VIRTUAL] = "virtual",
        [SUBTYPE_MONITOR] = "monitor"
    };

    pa_assert(s);

    if (s->service) {
        DNSServiceRefDeallocate(s->service);
        s->service = NULL;
    }

    TXTRecordCreate(&txt, 0, NULL);

    txt_record_server_data(s->userdata->core, &txt);

    get_service_data(s, &ss, &map, &name, &proplist, &subtype);
    TXTRecordSetValue(&txt, "device", strlen(name), name);

    snprintf(tmp, sizeof(tmp), "%u", ss.rate);
    TXTRecordSetValue(&txt, "rate", strlen(tmp), tmp);

    snprintf(tmp, sizeof(tmp), "%u", ss.channels);
    TXTRecordSetValue(&txt, "channels", strlen(tmp), tmp);

    t = pa_sample_format_to_string(ss.format);
    TXTRecordSetValue(&txt, "format", strlen(t), t);

    t = pa_channel_map_snprint(cm, sizeof(cm), &map);
    TXTRecordSetValue(&txt, "channel_map", strlen(t), t);

    t = subtype_text[subtype];
    TXTRecordSetValue(&txt, "subtype", strlen(t), t);

    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_DESCRIPTION)))
        TXTRecordSetValue(&txt, "description", strlen(t), t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_ICON_NAME)))
        TXTRecordSetValue(&txt, "icon-name", strlen(t), t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_VENDOR_NAME)))
        TXTRecordSetValue(&txt, "vendor-name", strlen(t), t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_PRODUCT_NAME)))
        TXTRecordSetValue(&txt, "product-name", strlen(t), t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_CLASS)))
        TXTRecordSetValue(&txt, "class", strlen(t), t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_FORM_FACTOR)))
        TXTRecordSetValue(&txt, "form-factor", strlen(t), t);

    err = DNSServiceRegister(&s->service,
                             0,         /* flags */
                             kDNSServiceInterfaceIndexAny,
                             s->service_name,
                             pa_sink_isinstance(s->device) ? SERVICE_TYPE_SINK : SERVICE_TYPE_SOURCE,
                             NULL,      /* domain */
                             NULL,      /* host */
                             compute_port(s->userdata),
                             TXTRecordGetLength(&txt),
                             TXTRecordGetBytesPtr(&txt),
                             dns_service_register_reply, s);

    if (err != kDNSServiceErr_NoError) {
        pa_log("DNSServiceRegister() returned err %d", err);
        goto finish;
    }

    pa_log_debug("Successfully registered Bonjour services for >%s<.", s->service_name);
    return 0;

finish:

    /* Remove this service */
    if (r < 0)
        service_free(s);

    TXTRecordDeallocate(&txt);

    return r;
}
static int publish_service(struct service *s) {
    int r = -1;
    AvahiStringList *txt = NULL;
    const char *name = NULL, *t;
    pa_proplist *proplist = NULL;
    pa_sample_spec ss;
    pa_channel_map map;
    char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
    enum service_subtype subtype;

    const char * const subtype_text[] = {
        [SUBTYPE_HARDWARE] = "hardware",
        [SUBTYPE_VIRTUAL] = "virtual",
        [SUBTYPE_MONITOR] = "monitor"
    };

    pa_assert(s);

    if (!s->userdata->client || avahi_client_get_state(s->userdata->client) != AVAHI_CLIENT_S_RUNNING)
        return 0;

    if (!s->entry_group) {
        if (!(s->entry_group = avahi_entry_group_new(s->userdata->client, service_entry_group_callback, s))) {
            pa_log("avahi_entry_group_new(): %s", avahi_strerror(avahi_client_errno(s->userdata->client)));
            goto finish;
        }
    } else
        avahi_entry_group_reset(s->entry_group);

    txt = txt_record_server_data(s->userdata->core, txt);

    get_service_data(s, &ss, &map, &name, &proplist, &subtype);
    txt = avahi_string_list_add_pair(txt, "device", name);
    txt = avahi_string_list_add_printf(txt, "rate=%u", ss.rate);
    txt = avahi_string_list_add_printf(txt, "channels=%u", ss.channels);
    txt = avahi_string_list_add_pair(txt, "format", pa_sample_format_to_string(ss.format));
    txt = avahi_string_list_add_pair(txt, "channel_map", pa_channel_map_snprint(cm, sizeof(cm), &map));
    txt = avahi_string_list_add_pair(txt, "subtype", subtype_text[subtype]);

    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_DESCRIPTION)))
        txt = avahi_string_list_add_pair(txt, "description", t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_ICON_NAME)))
        txt = avahi_string_list_add_pair(txt, "icon-name", t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_VENDOR_NAME)))
        txt = avahi_string_list_add_pair(txt, "vendor-name", t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_PRODUCT_NAME)))
        txt = avahi_string_list_add_pair(txt, "product-name", t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_CLASS)))
        txt = avahi_string_list_add_pair(txt, "class", t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_FORM_FACTOR)))
        txt = avahi_string_list_add_pair(txt, "form-factor", t);

    if (avahi_entry_group_add_service_strlst(
                s->entry_group,
                AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
                0,
                s->service_name,
                pa_sink_isinstance(s->device) ? SERVICE_TYPE_SINK : SERVICE_TYPE_SOURCE,
                NULL,
                NULL,
                compute_port(s->userdata),
                txt) < 0) {

        pa_log("avahi_entry_group_add_service_strlst(): %s", avahi_strerror(avahi_client_errno(s->userdata->client)));
        goto finish;
    }

    if (avahi_entry_group_add_service_subtype(
                s->entry_group,
                AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
                0,
                s->service_name,
                pa_sink_isinstance(s->device) ? SERVICE_TYPE_SINK : SERVICE_TYPE_SOURCE,
                NULL,
                pa_sink_isinstance(s->device) ? (subtype == SUBTYPE_HARDWARE ? SERVICE_SUBTYPE_SINK_HARDWARE : SERVICE_SUBTYPE_SINK_VIRTUAL) :
                (subtype == SUBTYPE_HARDWARE ? SERVICE_SUBTYPE_SOURCE_HARDWARE : (subtype == SUBTYPE_VIRTUAL ? SERVICE_SUBTYPE_SOURCE_VIRTUAL : SERVICE_SUBTYPE_SOURCE_MONITOR))) < 0) {

        pa_log("avahi_entry_group_add_service_subtype(): %s", avahi_strerror(avahi_client_errno(s->userdata->client)));
        goto finish;
    }

    if (pa_source_isinstance(s->device) && subtype != SUBTYPE_MONITOR) {
        if (avahi_entry_group_add_service_subtype(
                    s->entry_group,
                    AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
                    0,
                    s->service_name,
                    SERVICE_TYPE_SOURCE,
                    NULL,
                    SERVICE_SUBTYPE_SOURCE_NON_MONITOR) < 0) {

            pa_log("avahi_entry_group_add_service_subtype(): %s", avahi_strerror(avahi_client_errno(s->userdata->client)));
            goto finish;
        }
    }

    if (avahi_entry_group_commit(s->entry_group) < 0) {
        pa_log("avahi_entry_group_commit(): %s", avahi_strerror(avahi_client_errno(s->userdata->client)));
        goto finish;
    }

    r = 0;
    pa_log_debug("Successfully created entry group for %s.", s->service_name);

finish:

    /* Remove this service */
    if (r < 0)
        service_free(s);

    avahi_string_list_free(txt);

    return r;
}