static int add_port_entries(struct mlx4_ib_dev *device, int port_num) { int i; char buff[10]; struct mlx4_ib_iov_port *port = NULL; int ret = 0 ; struct ib_port_attr attr; /* get the physical gid and pkey table sizes.*/ ret = __mlx4_ib_query_port(&device->ib_dev, port_num, &attr, 1); if (ret) goto err; port = &device->iov_ports[port_num - 1]; port->dev = device; port->num = port_num; /* Directory structure: * iov - * port num - * admin_guids * gids (operational) * mcg_table */ port->dentr_ar = kzalloc(sizeof (struct mlx4_ib_iov_sysfs_attr_ar), GFP_KERNEL); if (!port->dentr_ar) { ret = -ENOMEM; goto err; } sprintf(buff, "%d", port_num); port->cur_port = kobject_create_and_add(buff, kobject_get(device->ports_parent)); if (!port->cur_port) { ret = -ENOMEM; goto kobj_create_err; } /* admin GUIDs */ port->admin_alias_parent = kobject_create_and_add("admin_guids", kobject_get(port->cur_port)); if (!port->admin_alias_parent) { ret = -ENOMEM; goto err_admin_guids; } for (i = 0 ; i < attr.gid_tbl_len; i++) { sprintf(buff, "%d", i); port->dentr_ar->dentries[i].entry_num = i; ret = create_sysfs_entry(port, &port->dentr_ar->dentries[i], buff, port->admin_alias_parent, show_admin_alias_guid, store_admin_alias_guid); if (ret) goto err_admin_alias_parent; } /* gids subdirectory (operational gids) */ port->gids_parent = kobject_create_and_add("gids", kobject_get(port->cur_port)); if (!port->gids_parent) { ret = -ENOMEM; goto err_gids; } for (i = 0 ; i < attr.gid_tbl_len; i++) { sprintf(buff, "%d", i); port->dentr_ar->dentries[attr.gid_tbl_len + i].entry_num = i; ret = create_sysfs_entry(port, &port->dentr_ar->dentries[attr.gid_tbl_len + i], buff, port->gids_parent, show_port_gid, NULL); if (ret) goto err_gids_parent; } /* physical port pkey table */ port->pkeys_parent = kobject_create_and_add("pkeys", kobject_get(port->cur_port)); if (!port->pkeys_parent) { ret = -ENOMEM; goto err_pkeys; } for (i = 0 ; i < attr.pkey_tbl_len; i++) { sprintf(buff, "%d", i); port->dentr_ar->dentries[2 * attr.gid_tbl_len + i].entry_num = i; ret = create_sysfs_entry(port, &port->dentr_ar->dentries[2 * attr.gid_tbl_len + i], buff, port->pkeys_parent, show_phys_port_pkey, NULL); if (ret) goto err_pkeys_parent; } /* MCGs table */ port->mcgs_parent = kobject_create_and_add("mcgs", kobject_get(port->cur_port)); if (!port->mcgs_parent) { ret = -ENOMEM; goto err_mcgs; } return 0; err_mcgs: kobject_put(port->cur_port); err_pkeys_parent: kobject_put(port->pkeys_parent); err_pkeys: kobject_put(port->cur_port); err_gids_parent: kobject_put(port->gids_parent); err_gids: kobject_put(port->cur_port); err_admin_alias_parent: kobject_put(port->admin_alias_parent); err_admin_guids: kobject_put(port->cur_port); kobject_put(port->cur_port); /* once more for create_and_add buff */ kobj_create_err: kobject_put(device->ports_parent); kfree(port->dentr_ar); err: pr_err("add_port_entries FAILED: for port:%d, error: %d\n", port_num, ret); return ret; }
static int set_guid_rec(struct ib_device *ibdev, u8 port, int index, struct mlx4_sriov_alias_guid_info_rec_det *rec_det) { int err; struct mlx4_ib_dev *dev = to_mdev(ibdev); struct ib_sa_guidinfo_rec guid_info_rec; ib_sa_comp_mask comp_mask; struct ib_port_attr attr; struct mlx4_alias_guid_work_context *callback_context; unsigned long resched_delay, flags, flags1; struct list_head *head = &dev->sriov.alias_guid.ports_guid[port - 1].cb_list; err = __mlx4_ib_query_port(ibdev, port, &attr, 1); if (err) { pr_debug("mlx4_ib_query_port failed (err: %d), port: %d\n", err, port); return err; } /*check the port was configured by the sm, otherwise no need to send */ if (attr.state != IB_PORT_ACTIVE) { pr_debug("port %d not active...rescheduling\n", port); resched_delay = 5 * HZ; err = -EAGAIN; goto new_schedule; } callback_context = kmalloc(sizeof *callback_context, GFP_KERNEL); if (!callback_context) { err = -ENOMEM; resched_delay = HZ * 5; goto new_schedule; } callback_context->port = port; callback_context->dev = dev; callback_context->block_num = index; memset(&guid_info_rec, 0, sizeof (struct ib_sa_guidinfo_rec)); guid_info_rec.lid = cpu_to_be16(attr.lid); guid_info_rec.block_num = index; memcpy(guid_info_rec.guid_info_list, rec_det->all_recs, GUID_REC_SIZE * NUM_ALIAS_GUID_IN_REC); comp_mask = IB_SA_GUIDINFO_REC_LID | IB_SA_GUIDINFO_REC_BLOCK_NUM | rec_det->guid_indexes; init_completion(&callback_context->done); spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1); list_add_tail(&callback_context->list, head); spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1); callback_context->query_id = ib_sa_guid_info_rec_query(dev->sriov.alias_guid.sa_client, ibdev, port, &guid_info_rec, comp_mask, rec_det->method, 1000, GFP_KERNEL, aliasguid_query_handler, callback_context, &callback_context->sa_query); if (callback_context->query_id < 0) { pr_debug("ib_sa_guid_info_rec_query failed, query_id: " "%d. will reschedule to the next 1 sec.\n", callback_context->query_id); spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1); list_del(&callback_context->list); kfree(callback_context); spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1); resched_delay = 1 * HZ; err = -EAGAIN; goto new_schedule; } err = 0; goto out; new_schedule: spin_lock_irqsave(&dev->sriov.going_down_lock, flags); spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1); invalidate_guid_record(dev, port, index); if (!dev->sriov.is_going_down) { queue_delayed_work(dev->sriov.alias_guid.ports_guid[port - 1].wq, &dev->sriov.alias_guid.ports_guid[port - 1].alias_guid_work, resched_delay); } spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1); spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags); out: return err; }