/* * Scan the IBFT table structure for the NIC and Target fields. When * found add them on the passed-in list. We do not support the other * fields at this point, so they are skipped. */ static int __init ibft_register_kobjects(struct ibft_table_header *header, struct list_head *list) { struct ibft_control *control = NULL; void *ptr, *end; int rc = 0; u16 offset; u16 eot_offset; control = (void *)header + sizeof(*header); end = (void *)control + control->hdr.length; eot_offset = (void *)header + header->length - (void *)control; rc = ibft_verify_hdr("control", (struct ibft_hdr *)control, id_control, sizeof(*control)); /* iBFT table safety checking */ rc |= ((control->hdr.index) ? -ENODEV : 0); if (rc) { printk(KERN_ERR "iBFT error: Control header is invalid!\n"); return rc; } for (ptr = &control->initiator_off; ptr < end; ptr += sizeof(u16)) { offset = *(u16 *)ptr; if (offset && offset < header->length && offset < eot_offset) { rc = ibft_create_kobject(header, (void *)header + offset, list); if (rc) break; } } return rc; }
/* * Helper function for ibft_register_kobjects. */ static int __init ibft_create_kobject(struct acpi_table_ibft *header, struct ibft_hdr *hdr) { struct iscsi_boot_kobj *boot_kobj = NULL; struct ibft_kobject *ibft_kobj = NULL; struct ibft_nic *nic = (struct ibft_nic *)hdr; struct pci_dev *pci_dev; int rc = 0; ibft_kobj = kzalloc(sizeof(*ibft_kobj), GFP_KERNEL); if (!ibft_kobj) return -ENOMEM; ibft_kobj->header = header; ibft_kobj->hdr = hdr; switch (hdr->id) { case id_initiator: rc = ibft_verify_hdr("initiator", hdr, id_initiator, sizeof(*ibft_kobj->initiator)); if (rc) break; boot_kobj = iscsi_boot_create_initiator(boot_kset, hdr->index, ibft_kobj, ibft_attr_show_initiator, ibft_check_initiator_for); if (!boot_kobj) { rc = -ENOMEM; goto free_ibft_obj; } break; case id_nic: rc = ibft_verify_hdr("ethernet", hdr, id_nic, sizeof(*ibft_kobj->nic)); if (rc) break; boot_kobj = iscsi_boot_create_ethernet(boot_kset, hdr->index, ibft_kobj, ibft_attr_show_nic, ibft_check_nic_for); if (!boot_kobj) { rc = -ENOMEM; goto free_ibft_obj; } break; case id_target: rc = ibft_verify_hdr("target", hdr, id_target, sizeof(*ibft_kobj->tgt)); if (rc) break; boot_kobj = iscsi_boot_create_target(boot_kset, hdr->index, ibft_kobj, ibft_attr_show_target, ibft_check_tgt_for); if (!boot_kobj) { rc = -ENOMEM; goto free_ibft_obj; } break; case id_reserved: case id_control: case id_extensions: /* Fields which we don't support. Ignore them */ rc = 1; break; default: printk(KERN_ERR "iBFT has unknown structure type (%d). " \ "Report this bug to %.6s!\n", hdr->id, header->header.oem_id); rc = 1; break; } if (rc) { /* Skip adding this kobject, but exit with non-fatal error. */ rc = 0; goto free_ibft_obj; } if (hdr->id == id_nic) { /* * We don't search for the device in other domains than * zero. This is because on x86 platforms the BIOS * executes only devices which are in domain 0. Furthermore, the * iBFT spec doesn't have a domain id field :-( */ pci_dev = pci_get_bus_and_slot((nic->pci_bdf & 0xff00) >> 8, (nic->pci_bdf & 0xff)); if (pci_dev) { rc = sysfs_create_link(&boot_kobj->kobj, &pci_dev->dev.kobj, "device"); pci_dev_put(pci_dev); } }
static int __init ibft_create_kobject(struct acpi_table_ibft *header, struct ibft_hdr *hdr) { struct iscsi_boot_kobj *boot_kobj = NULL; struct ibft_kobject *ibft_kobj = NULL; struct ibft_nic *nic = (struct ibft_nic *)hdr; struct pci_dev *pci_dev; int rc = 0; ibft_kobj = kzalloc(sizeof(*ibft_kobj), GFP_KERNEL); if (!ibft_kobj) return -ENOMEM; ibft_kobj->header = header; ibft_kobj->hdr = hdr; switch (hdr->id) { case id_initiator: rc = ibft_verify_hdr("initiator", hdr, id_initiator, sizeof(*ibft_kobj->initiator)); if (rc) break; boot_kobj = iscsi_boot_create_initiator(boot_kset, hdr->index, ibft_kobj, ibft_attr_show_initiator, ibft_check_initiator_for, ibft_kobj_release); if (!boot_kobj) { rc = -ENOMEM; goto free_ibft_obj; } break; case id_nic: rc = ibft_verify_hdr("ethernet", hdr, id_nic, sizeof(*ibft_kobj->nic)); if (rc) break; boot_kobj = iscsi_boot_create_ethernet(boot_kset, hdr->index, ibft_kobj, ibft_attr_show_nic, ibft_check_nic_for, ibft_kobj_release); if (!boot_kobj) { rc = -ENOMEM; goto free_ibft_obj; } break; case id_target: rc = ibft_verify_hdr("target", hdr, id_target, sizeof(*ibft_kobj->tgt)); if (rc) break; boot_kobj = iscsi_boot_create_target(boot_kset, hdr->index, ibft_kobj, ibft_attr_show_target, ibft_check_tgt_for, ibft_kobj_release); if (!boot_kobj) { rc = -ENOMEM; goto free_ibft_obj; } break; case id_reserved: case id_control: case id_extensions: /* */ rc = 1; break; default: printk(KERN_ERR "iBFT has unknown structure type (%d). " \ "Report this bug to %.6s!\n", hdr->id, header->header.oem_id); rc = 1; break; } if (rc) { /* */ rc = 0; goto free_ibft_obj; } if (hdr->id == id_nic) { /* */ pci_dev = pci_get_bus_and_slot((nic->pci_bdf & 0xff00) >> 8, (nic->pci_bdf & 0xff)); if (pci_dev) { rc = sysfs_create_link(&boot_kobj->kobj, &pci_dev->dev.kobj, "device"); pci_dev_put(pci_dev); } }
/* * Helper function for ibft_register_kobjects. */ static int __init ibft_create_kobject(struct ibft_table_header *header, struct ibft_hdr *hdr, struct list_head *list) { struct ibft_kobject *ibft_kobj = NULL; struct ibft_nic *nic = (struct ibft_nic *)hdr; struct pci_dev *pci_dev; int rc = 0; ibft_kobj = kzalloc(sizeof(*ibft_kobj), GFP_KERNEL); if (!ibft_kobj) return -ENOMEM; ibft_kobj->header = header; ibft_kobj->hdr = hdr; switch (hdr->id) { case id_initiator: rc = ibft_verify_hdr("initiator", hdr, id_initiator, sizeof(*ibft_kobj->initiator)); break; case id_nic: rc = ibft_verify_hdr("ethernet", hdr, id_nic, sizeof(*ibft_kobj->nic)); break; case id_target: rc = ibft_verify_hdr("target", hdr, id_target, sizeof(*ibft_kobj->tgt)); break; case id_reserved: case id_control: case id_extensions: /* Fields which we don't support. Ignore them */ rc = 1; break; default: printk(KERN_ERR "iBFT has unknown structure type (%d). " \ "Report this bug to %.6s!\n", hdr->id, header->oem_id); rc = 1; break; } if (rc) { /* Skip adding this kobject, but exit with non-fatal error. */ kfree(ibft_kobj); goto out_invalid_struct; } ibft_kobj->kobj.kset = ibft_kset; rc = kobject_init_and_add(&ibft_kobj->kobj, &ibft_ktype, NULL, ibft_id_names[hdr->id], hdr->index); if (rc) { kfree(ibft_kobj); goto out; } kobject_uevent(&ibft_kobj->kobj, KOBJ_ADD); if (hdr->id == id_nic) { /* * We don't search for the device in other domains than * zero. This is because on x86 platforms the BIOS * executes only devices which are in domain 0. Furthermore, the * iBFT spec doesn't have a domain id field :-( */ pci_dev = pci_get_bus_and_slot((nic->pci_bdf & 0xff00) >> 8, (nic->pci_bdf & 0xff)); if (pci_dev) { rc = sysfs_create_link(&ibft_kobj->kobj, &pci_dev->dev.kobj, "device"); pci_dev_put(pci_dev); } }
/* * Helper function for ibft_register_kobjects. */ static int __init ibft_create_kobject(struct ibft_table_header *header, struct ibft_hdr *hdr, struct list_head *list) { struct ibft_kobject *ibft_kobj = NULL; struct ibft_nic *nic = (struct ibft_nic *)hdr; struct pci_dev *pci_dev; int rc = 0; ibft_kobj = kzalloc(sizeof(*ibft_kobj), GFP_KERNEL); if (!ibft_kobj) return -ENOMEM; ibft_kobj->header = header; ibft_kobj->hdr = hdr; switch (hdr->id) { case id_initiator: rc = ibft_verify_hdr("initiator", hdr, id_initiator, sizeof(*ibft_kobj->initiator)); break; case id_nic: rc = ibft_verify_hdr("ethernet", hdr, id_nic, sizeof(*ibft_kobj->nic)); break; case id_target: rc = ibft_verify_hdr("target", hdr, id_target, sizeof(*ibft_kobj->tgt)); break; case id_reserved: case id_control: case id_extensions: /* Fields which we don't support. Ignore them */ rc = 1; break; default: printk(KERN_ERR "iBFT has unknown structure type (%d). " \ "Report this bug to your vendor!\n", hdr->id); rc = 1; break; } if (rc) { kfree(ibft_kobj); goto out_invalid_struct; } /* kobject fief. We will let the reference counter do the job of deleting its name if we fail here. */ kobj_set_kset_s(ibft_kobj, ibft_subsys); ibft_kobj->kobj.ktype = &ibft_ktype; rc = kobject_set_name(&ibft_kobj->kobj, ibft_id_names[hdr->id], hdr->index); if (rc) goto kobject_do_put; rc = kobject_register(&ibft_kobj->kobj); if (rc) goto kobject_do_put; if (hdr->id == id_nic) { pci_dev = pci_get_bus_and_slot((nic->pci_bdf & 0xff00) >> 8, (nic->pci_bdf & 0xff)); if (pci_dev) { rc = sysfs_create_link(&ibft_kobj->kobj, &pci_dev->dev.kobj, "device"); pci_dev_put(pci_dev); } }