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)); }
/** * 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; }
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; }
/** * 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); } }
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); } }
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); } } } }
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; }