| .. | .. |
|---|
| 45 | 45 | unsigned long state; |
|---|
| 46 | 46 | }; |
|---|
| 47 | 47 | |
|---|
| 48 | | -struct mlx5_delayed_event { |
|---|
| 49 | | - struct list_head list; |
|---|
| 50 | | - struct mlx5_core_dev *dev; |
|---|
| 51 | | - enum mlx5_dev_event event; |
|---|
| 52 | | - unsigned long param; |
|---|
| 53 | | -}; |
|---|
| 54 | | - |
|---|
| 55 | 48 | enum { |
|---|
| 56 | 49 | MLX5_INTERFACE_ADDED, |
|---|
| 57 | 50 | MLX5_INTERFACE_ATTACHED, |
|---|
| 58 | 51 | }; |
|---|
| 59 | 52 | |
|---|
| 60 | | -static void add_delayed_event(struct mlx5_priv *priv, |
|---|
| 61 | | - struct mlx5_core_dev *dev, |
|---|
| 62 | | - enum mlx5_dev_event event, |
|---|
| 63 | | - unsigned long param) |
|---|
| 64 | | -{ |
|---|
| 65 | | - struct mlx5_delayed_event *delayed_event; |
|---|
| 66 | | - |
|---|
| 67 | | - delayed_event = kzalloc(sizeof(*delayed_event), GFP_ATOMIC); |
|---|
| 68 | | - if (!delayed_event) { |
|---|
| 69 | | - mlx5_core_err(dev, "event %d is missed\n", event); |
|---|
| 70 | | - return; |
|---|
| 71 | | - } |
|---|
| 72 | | - |
|---|
| 73 | | - mlx5_core_dbg(dev, "Accumulating event %d\n", event); |
|---|
| 74 | | - delayed_event->dev = dev; |
|---|
| 75 | | - delayed_event->event = event; |
|---|
| 76 | | - delayed_event->param = param; |
|---|
| 77 | | - list_add_tail(&delayed_event->list, &priv->waiting_events_list); |
|---|
| 78 | | -} |
|---|
| 79 | | - |
|---|
| 80 | | -static void delayed_event_release(struct mlx5_device_context *dev_ctx, |
|---|
| 81 | | - struct mlx5_priv *priv) |
|---|
| 82 | | -{ |
|---|
| 83 | | - struct mlx5_core_dev *dev = container_of(priv, struct mlx5_core_dev, priv); |
|---|
| 84 | | - struct mlx5_delayed_event *de; |
|---|
| 85 | | - struct mlx5_delayed_event *n; |
|---|
| 86 | | - struct list_head temp; |
|---|
| 87 | | - |
|---|
| 88 | | - INIT_LIST_HEAD(&temp); |
|---|
| 89 | | - |
|---|
| 90 | | - spin_lock_irq(&priv->ctx_lock); |
|---|
| 91 | | - |
|---|
| 92 | | - priv->is_accum_events = false; |
|---|
| 93 | | - list_splice_init(&priv->waiting_events_list, &temp); |
|---|
| 94 | | - if (!dev_ctx->context) |
|---|
| 95 | | - goto out; |
|---|
| 96 | | - list_for_each_entry_safe(de, n, &temp, list) |
|---|
| 97 | | - dev_ctx->intf->event(dev, dev_ctx->context, de->event, de->param); |
|---|
| 98 | | - |
|---|
| 99 | | -out: |
|---|
| 100 | | - spin_unlock_irq(&priv->ctx_lock); |
|---|
| 101 | | - |
|---|
| 102 | | - list_for_each_entry_safe(de, n, &temp, list) { |
|---|
| 103 | | - list_del(&de->list); |
|---|
| 104 | | - kfree(de); |
|---|
| 105 | | - } |
|---|
| 106 | | -} |
|---|
| 107 | | - |
|---|
| 108 | | -/* accumulating events that can come after mlx5_ib calls to |
|---|
| 109 | | - * ib_register_device, till adding that interface to the events list. |
|---|
| 110 | | - */ |
|---|
| 111 | | -static void delayed_event_start(struct mlx5_priv *priv) |
|---|
| 112 | | -{ |
|---|
| 113 | | - spin_lock_irq(&priv->ctx_lock); |
|---|
| 114 | | - priv->is_accum_events = true; |
|---|
| 115 | | - spin_unlock_irq(&priv->ctx_lock); |
|---|
| 116 | | -} |
|---|
| 117 | 53 | |
|---|
| 118 | 54 | void mlx5_add_device(struct mlx5_interface *intf, struct mlx5_priv *priv) |
|---|
| 119 | 55 | { |
|---|
| .. | .. |
|---|
| 129 | 65 | |
|---|
| 130 | 66 | dev_ctx->intf = intf; |
|---|
| 131 | 67 | |
|---|
| 132 | | - delayed_event_start(priv); |
|---|
| 133 | | - |
|---|
| 134 | 68 | dev_ctx->context = intf->add(dev); |
|---|
| 135 | 69 | if (dev_ctx->context) { |
|---|
| 136 | 70 | set_bit(MLX5_INTERFACE_ADDED, &dev_ctx->state); |
|---|
| .. | .. |
|---|
| 139 | 73 | |
|---|
| 140 | 74 | spin_lock_irq(&priv->ctx_lock); |
|---|
| 141 | 75 | list_add_tail(&dev_ctx->list, &priv->ctx_list); |
|---|
| 142 | | - |
|---|
| 143 | | -#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING |
|---|
| 144 | | - if (dev_ctx->intf->pfault) { |
|---|
| 145 | | - if (priv->pfault) { |
|---|
| 146 | | - mlx5_core_err(dev, "multiple page fault handlers not supported"); |
|---|
| 147 | | - } else { |
|---|
| 148 | | - priv->pfault_ctx = dev_ctx->context; |
|---|
| 149 | | - priv->pfault = dev_ctx->intf->pfault; |
|---|
| 150 | | - } |
|---|
| 151 | | - } |
|---|
| 152 | | -#endif |
|---|
| 153 | 76 | spin_unlock_irq(&priv->ctx_lock); |
|---|
| 154 | 77 | } |
|---|
| 155 | | - |
|---|
| 156 | | - delayed_event_release(dev_ctx, priv); |
|---|
| 157 | 78 | |
|---|
| 158 | 79 | if (!dev_ctx->context) |
|---|
| 159 | 80 | kfree(dev_ctx); |
|---|
| .. | .. |
|---|
| 179 | 100 | if (!dev_ctx) |
|---|
| 180 | 101 | return; |
|---|
| 181 | 102 | |
|---|
| 182 | | -#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING |
|---|
| 183 | | - spin_lock_irq(&priv->ctx_lock); |
|---|
| 184 | | - if (priv->pfault == dev_ctx->intf->pfault) |
|---|
| 185 | | - priv->pfault = NULL; |
|---|
| 186 | | - spin_unlock_irq(&priv->ctx_lock); |
|---|
| 187 | | - |
|---|
| 188 | | - synchronize_srcu(&priv->pfault_srcu); |
|---|
| 189 | | -#endif |
|---|
| 190 | | - |
|---|
| 191 | 103 | spin_lock_irq(&priv->ctx_lock); |
|---|
| 192 | 104 | list_del(&dev_ctx->list); |
|---|
| 193 | 105 | spin_unlock_irq(&priv->ctx_lock); |
|---|
| .. | .. |
|---|
| 207 | 119 | if (!dev_ctx) |
|---|
| 208 | 120 | return; |
|---|
| 209 | 121 | |
|---|
| 210 | | - delayed_event_start(priv); |
|---|
| 211 | 122 | if (intf->attach) { |
|---|
| 212 | 123 | if (test_bit(MLX5_INTERFACE_ATTACHED, &dev_ctx->state)) |
|---|
| 213 | | - goto out; |
|---|
| 124 | + return; |
|---|
| 214 | 125 | if (intf->attach(dev, dev_ctx->context)) |
|---|
| 215 | | - goto out; |
|---|
| 216 | | - |
|---|
| 126 | + return; |
|---|
| 217 | 127 | set_bit(MLX5_INTERFACE_ATTACHED, &dev_ctx->state); |
|---|
| 218 | 128 | } else { |
|---|
| 219 | 129 | if (test_bit(MLX5_INTERFACE_ADDED, &dev_ctx->state)) |
|---|
| 220 | | - goto out; |
|---|
| 130 | + return; |
|---|
| 221 | 131 | dev_ctx->context = intf->add(dev); |
|---|
| 222 | 132 | if (!dev_ctx->context) |
|---|
| 223 | | - goto out; |
|---|
| 224 | | - |
|---|
| 133 | + return; |
|---|
| 225 | 134 | set_bit(MLX5_INTERFACE_ADDED, &dev_ctx->state); |
|---|
| 226 | 135 | } |
|---|
| 227 | | - |
|---|
| 228 | | -out: |
|---|
| 229 | | - delayed_event_release(dev_ctx, priv); |
|---|
| 230 | 136 | } |
|---|
| 231 | 137 | |
|---|
| 232 | 138 | void mlx5_attach_device(struct mlx5_core_dev *dev) |
|---|
| .. | .. |
|---|
| 287 | 193 | return found; |
|---|
| 288 | 194 | } |
|---|
| 289 | 195 | |
|---|
| 290 | | -int mlx5_register_device(struct mlx5_core_dev *dev) |
|---|
| 196 | +void mlx5_register_device(struct mlx5_core_dev *dev) |
|---|
| 291 | 197 | { |
|---|
| 292 | 198 | struct mlx5_priv *priv = &dev->priv; |
|---|
| 293 | 199 | struct mlx5_interface *intf; |
|---|
| .. | .. |
|---|
| 297 | 203 | list_for_each_entry(intf, &intf_list, list) |
|---|
| 298 | 204 | mlx5_add_device(intf, priv); |
|---|
| 299 | 205 | mutex_unlock(&mlx5_intf_mutex); |
|---|
| 300 | | - |
|---|
| 301 | | - return 0; |
|---|
| 302 | 206 | } |
|---|
| 303 | 207 | |
|---|
| 304 | 208 | void mlx5_unregister_device(struct mlx5_core_dev *dev) |
|---|
| .. | .. |
|---|
| 371 | 275 | mutex_unlock(&mlx5_intf_mutex); |
|---|
| 372 | 276 | } |
|---|
| 373 | 277 | |
|---|
| 374 | | -void *mlx5_get_protocol_dev(struct mlx5_core_dev *mdev, int protocol) |
|---|
| 375 | | -{ |
|---|
| 376 | | - struct mlx5_priv *priv = &mdev->priv; |
|---|
| 377 | | - struct mlx5_device_context *dev_ctx; |
|---|
| 378 | | - unsigned long flags; |
|---|
| 379 | | - void *result = NULL; |
|---|
| 380 | | - |
|---|
| 381 | | - spin_lock_irqsave(&priv->ctx_lock, flags); |
|---|
| 382 | | - |
|---|
| 383 | | - list_for_each_entry(dev_ctx, &mdev->priv.ctx_list, list) |
|---|
| 384 | | - if ((dev_ctx->intf->protocol == protocol) && |
|---|
| 385 | | - dev_ctx->intf->get_dev) { |
|---|
| 386 | | - result = dev_ctx->intf->get_dev(dev_ctx->context); |
|---|
| 387 | | - break; |
|---|
| 388 | | - } |
|---|
| 389 | | - |
|---|
| 390 | | - spin_unlock_irqrestore(&priv->ctx_lock, flags); |
|---|
| 391 | | - |
|---|
| 392 | | - return result; |
|---|
| 393 | | -} |
|---|
| 394 | | -EXPORT_SYMBOL(mlx5_get_protocol_dev); |
|---|
| 395 | | - |
|---|
| 396 | 278 | /* Must be called with intf_mutex held */ |
|---|
| 397 | 279 | void mlx5_add_dev_by_protocol(struct mlx5_core_dev *dev, int protocol) |
|---|
| 398 | 280 | { |
|---|
| .. | .. |
|---|
| 427 | 309 | /* Must be called with intf_mutex held */ |
|---|
| 428 | 310 | struct mlx5_core_dev *mlx5_get_next_phys_dev(struct mlx5_core_dev *dev) |
|---|
| 429 | 311 | { |
|---|
| 430 | | - u32 pci_id = mlx5_gen_pci_id(dev); |
|---|
| 431 | 312 | struct mlx5_core_dev *res = NULL; |
|---|
| 432 | 313 | struct mlx5_core_dev *tmp_dev; |
|---|
| 433 | 314 | struct mlx5_priv *priv; |
|---|
| 315 | + u32 pci_id; |
|---|
| 434 | 316 | |
|---|
| 317 | + if (!mlx5_core_is_pf(dev)) |
|---|
| 318 | + return NULL; |
|---|
| 319 | + |
|---|
| 320 | + pci_id = mlx5_gen_pci_id(dev); |
|---|
| 435 | 321 | list_for_each_entry(priv, &mlx5_dev_list, dev_list) { |
|---|
| 436 | 322 | tmp_dev = container_of(priv, struct mlx5_core_dev, priv); |
|---|
| 323 | + if (!mlx5_core_is_pf(tmp_dev)) |
|---|
| 324 | + continue; |
|---|
| 325 | + |
|---|
| 437 | 326 | if ((dev != tmp_dev) && (mlx5_gen_pci_id(tmp_dev) == pci_id)) { |
|---|
| 438 | 327 | res = tmp_dev; |
|---|
| 439 | 328 | break; |
|---|
| .. | .. |
|---|
| 443 | 332 | return res; |
|---|
| 444 | 333 | } |
|---|
| 445 | 334 | |
|---|
| 446 | | -void mlx5_core_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event, |
|---|
| 447 | | - unsigned long param) |
|---|
| 448 | | -{ |
|---|
| 449 | | - struct mlx5_priv *priv = &dev->priv; |
|---|
| 450 | | - struct mlx5_device_context *dev_ctx; |
|---|
| 451 | | - unsigned long flags; |
|---|
| 452 | | - |
|---|
| 453 | | - spin_lock_irqsave(&priv->ctx_lock, flags); |
|---|
| 454 | | - |
|---|
| 455 | | - if (priv->is_accum_events) |
|---|
| 456 | | - add_delayed_event(priv, dev, event, param); |
|---|
| 457 | | - |
|---|
| 458 | | - /* After mlx5_detach_device, the dev_ctx->intf is still set and dev_ctx is |
|---|
| 459 | | - * still in priv->ctx_list. In this case, only notify the dev_ctx if its |
|---|
| 460 | | - * ADDED or ATTACHED bit are set. |
|---|
| 461 | | - */ |
|---|
| 462 | | - list_for_each_entry(dev_ctx, &priv->ctx_list, list) |
|---|
| 463 | | - if (dev_ctx->intf->event && |
|---|
| 464 | | - (test_bit(MLX5_INTERFACE_ADDED, &dev_ctx->state) || |
|---|
| 465 | | - test_bit(MLX5_INTERFACE_ATTACHED, &dev_ctx->state))) |
|---|
| 466 | | - dev_ctx->intf->event(dev, dev_ctx->context, event, param); |
|---|
| 467 | | - |
|---|
| 468 | | - spin_unlock_irqrestore(&priv->ctx_lock, flags); |
|---|
| 469 | | -} |
|---|
| 470 | | - |
|---|
| 471 | | -#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING |
|---|
| 472 | | -void mlx5_core_page_fault(struct mlx5_core_dev *dev, |
|---|
| 473 | | - struct mlx5_pagefault *pfault) |
|---|
| 474 | | -{ |
|---|
| 475 | | - struct mlx5_priv *priv = &dev->priv; |
|---|
| 476 | | - int srcu_idx; |
|---|
| 477 | | - |
|---|
| 478 | | - srcu_idx = srcu_read_lock(&priv->pfault_srcu); |
|---|
| 479 | | - if (priv->pfault) |
|---|
| 480 | | - priv->pfault(dev, priv->pfault_ctx, pfault); |
|---|
| 481 | | - srcu_read_unlock(&priv->pfault_srcu, srcu_idx); |
|---|
| 482 | | -} |
|---|
| 483 | | -#endif |
|---|
| 484 | 335 | |
|---|
| 485 | 336 | void mlx5_dev_list_lock(void) |
|---|
| 486 | 337 | { |
|---|