Command may fail while driver is reloading and can't accept FW commands till command interface is reinitialized. Such command failure is being logged to command stats. This results in NULL pointer access as command stats structure is being freed and reallocated during mlx5 devlink reload (see kernel log below). Fix it by making command stats statically allocated on driver probe. Kernel log: [ 2394.808802] BUG: unable to handle kernel paging request at 000000000002a9c0 [ 2394.810610] PGD 0 P4D 0 [ 2394.811811] Oops: 0002 [#1] SMP NOPTI ... [ 2394.815482] RIP: 0010:native_queued_spin_lock_slowpath+0x183/0x1d0 ... [ 2394.829505] Call Trace: [ 2394.830667] _raw_spin_lock_irq+0x23/0x26 [ 2394.831858] cmd_status_err+0x55/0x110 [mlx5_core] [ 2394.833020] mlx5_access_reg+0xe7/0x150 [mlx5_core] [ 2394.834175] mlx5_query_port_ptys+0x78/0xa0 [mlx5_core] [ 2394.835337] mlx5e_ethtool_get_link_ksettings+0x74/0x590 [mlx5_core] [ 2394.836454] ? kmem_cache_alloc_trace+0x140/0x1c0 [ 2394.837562] __rh_call_get_link_ksettings+0x33/0x100 [ 2394.838663] ? __rtnl_unlock+0x25/0x50 [ 2394.839755] __ethtool_get_link_ksettings+0x72/0x150 [ 2394.840862] duplex_show+0x6e/0xc0 [ 2394.841963] dev_attr_show+0x1c/0x40 [ 2394.843048] sysfs_kf_seq_show+0x9b/0x100 [ 2394.844123] seq_read+0x153/0x410 [ 2394.845187] vfs_read+0x91/0x140 [ 2394.846226] ksys_read+0x4f/0xb0 [ 2394.847234] do_syscall_64+0x5b/0x1a0 [ 2394.848228] entry_SYSCALL_64_after_hwframe+0x65/0xca
Unified · Split
| @@ -2176,15 +2176,9 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev) · 2175 unmodified lines | |||
| 2176 | return -EINVAL; | 2176 | return -EINVAL; |
| 2177 | } | 2177 | } |
| 2178 | 2178 | ||
| 2179 | cmd->stats = kvcalloc(MLX5_CMD_OP_MAX, sizeof(*cmd->stats), GFP_KERNEL); | ||
| 2180 | if (!cmd->stats) | ||
| 2181 | return -ENOMEM; | ||
| 2182 | |||
| 2183 | cmd->pool = dma_pool_create("mlx5_cmd", mlx5_core_dma_dev(dev), size, align, 0); | 2179 | cmd->pool = dma_pool_create("mlx5_cmd", mlx5_core_dma_dev(dev), size, align, 0); |
| 2184 | if (!cmd->pool) { | 2180 | if (!cmd->pool) |
| 2185 | err = -ENOMEM; | 2181 | return -ENOMEM; |
| 2186 | goto dma_pool_err; | ||
| 2187 | } | ||
| 2188 | 2182 | ||
| 2189 | err = alloc_cmd_page(dev, cmd); | 2183 | err = alloc_cmd_page(dev, cmd); |
| 2190 | if (err) | 2184 | if (err) |
| @@ -2268,8 +2262,6 @@ err_free_page: · 77 unmodified lines | |||
| 2268 | 2262 | ||
| 2269 | err_free_pool: | 2263 | err_free_pool: |
| 2270 | dma_pool_destroy(cmd->pool); | 2264 | dma_pool_destroy(cmd->pool); |
| 2271 | dma_pool_err: | ||
| 2272 | kvfree(cmd->stats); | ||
| 2273 | return err; | 2265 | return err; |
| 2274 | } | 2266 | } |
| 2275 | 2267 | ||
| @@ -2282,7 +2274,6 @@ void mlx5_cmd_cleanup(struct mlx5_core_dev *dev) · 6 unmodified lines | |||
| 2282 | destroy_msg_cache(dev); | 2274 | destroy_msg_cache(dev); |
| 2283 | free_cmd_page(dev, cmd); | 2275 | free_cmd_page(dev, cmd); |
| 2284 | dma_pool_destroy(cmd->pool); | 2276 | dma_pool_destroy(cmd->pool); |
| 2285 | kvfree(cmd->stats); | ||
| 2286 | } | 2277 | } |
| 2287 | 2278 | ||
| 2288 | void mlx5_cmd_set_state(struct mlx5_core_dev *dev, | 2279 | void mlx5_cmd_set_state(struct mlx5_core_dev *dev, |
| @@ -315,7 +315,7 @@ struct mlx5_cmd { · 314 unmodified lines | |||
| 315 | struct mlx5_cmd_debug dbg; | 315 | struct mlx5_cmd_debug dbg; |
| 316 | struct cmd_msg_cache cache[MLX5_NUM_COMMAND_CACHES]; | 316 | struct cmd_msg_cache cache[MLX5_NUM_COMMAND_CACHES]; |
| 317 | int checksum_disabled; | 317 | int checksum_disabled; |
| 318 | struct mlx5_cmd_stats *stats; | 318 | struct mlx5_cmd_stats stats[MLX5_CMD_OP_MAX]; |
| 319 | }; | 319 | }; |
| 320 | 320 | ||
| 321 | struct mlx5_cmd_mailbox { | 321 | struct mlx5_cmd_mailbox { |